// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package sfnt

import (
	
)

// Flags for simple (non-compound) glyphs.
//
// See https://www.microsoft.com/typography/OTSPEC/glyf.htm
const (
	flagOnCurve      = 1 << 0 // 0x0001
	flagXShortVector = 1 << 1 // 0x0002
	flagYShortVector = 1 << 2 // 0x0004
	flagRepeat       = 1 << 3 // 0x0008

	// The same flag bits are overloaded to have two meanings, dependent on the
	// value of the flag{X,Y}ShortVector bits.
	flagPositiveXShortVector = 1 << 4 // 0x0010
	flagThisXIsSame          = 1 << 4 // 0x0010
	flagPositiveYShortVector = 1 << 5 // 0x0020
	flagThisYIsSame          = 1 << 5 // 0x0020
)

// Flags for compound glyphs.
//
// See https://www.microsoft.com/typography/OTSPEC/glyf.htm
const (
	flagArg1And2AreWords        = 1 << 0  // 0x0001
	flagArgsAreXYValues         = 1 << 1  // 0x0002
	flagRoundXYToGrid           = 1 << 2  // 0x0004
	flagWeHaveAScale            = 1 << 3  // 0x0008
	flagReserved4               = 1 << 4  // 0x0010
	flagMoreComponents          = 1 << 5  // 0x0020
	flagWeHaveAnXAndYScale      = 1 << 6  // 0x0040
	flagWeHaveATwoByTwo         = 1 << 7  // 0x0080
	flagWeHaveInstructions      = 1 << 8  // 0x0100
	flagUseMyMetrics            = 1 << 9  // 0x0200
	flagOverlapCompound         = 1 << 10 // 0x0400
	flagScaledComponentOffset   = 1 << 11 // 0x0800
	flagUnscaledComponentOffset = 1 << 12 // 0x1000
)

func midPoint(,  fixed.Point26_6) fixed.Point26_6 {
	return fixed.Point26_6{
		X: (.X + .X) / 2,
		Y: (.Y + .Y) / 2,
	}
}

func parseLoca( *source,  table,  uint32,  bool,  int32) ( []uint32,  error) {
	if  {
		if .length != 4*uint32(+1) {
			return nil, errInvalidLocaTable
		}
	} else {
		if .length != 2*uint32(+1) {
			return nil, errInvalidLocaTable
		}
	}

	 = make([]uint32, +1)
	,  := .view(nil, int(.offset), int(.length))
	if  != nil {
		return nil, 
	}

	if  {
		for  := range  {
			[] = 1*uint32(u32([4*:])) + 
		}
	} else {
		for  := range  {
			[] = 2*uint32(u16([2*:])) + 
		}
	}
	return , 
}

// https://www.microsoft.com/typography/OTSPEC/glyf.htm says that "Each
// glyph begins with the following [10 byte] header".
const glyfHeaderLen = 10

func loadGlyf( *Font,  *Buffer,  GlyphIndex, ,  uint32) error {
	, , ,  := .viewGlyphData(, )
	if  != nil {
		return 
	}
	if len() == 0 {
		return nil
	}
	if len() < glyfHeaderLen {
		return errInvalidGlyphData
	}
	 := glyfHeaderLen

	,  := int16(u16()), 0
	switch {
	case  == -1:
		// We have a compound glyph. No-op.
	case  == 0:
		return nil
	case  > 0:
		// We have a simple (non-compound) glyph.
		 += 2 * int()
		if  > len() {
			return errInvalidGlyphData
		}
		// The +1 for numPoints is because the value in the file format is
		// inclusive, but Go's slice[:index] semantics are exclusive.
		 = 1 + int(u16([-2:]))
	default:
		return errInvalidGlyphData
	}

	if  < 0 {
		return loadCompoundGlyf(, , [glyfHeaderLen:], , )
	}

	// Skip the hinting instructions.
	 += 2
	if  > len() {
		return errInvalidGlyphData
	}
	 := int(u16([-2:]))
	 += 
	if  > len() {
		return errInvalidGlyphData
	}

	// For simple (non-compound) glyphs, the remainder of the glyf data
	// consists of (flags, x, y) points: the Bézier curve segments. These are
	// stored in columns (all the flags first, then all the x coordinates, then
	// all the y coordinates), not rows, as it compresses better.
	//
	// Decoding those points in row order involves two passes. The first pass
	// determines the indexes (relative to the data slice) of where the flags,
	// the x coordinates and the y coordinates each start.
	 := int32()
	, ,  := findXYIndexes(, , )
	if ! {
		return errInvalidGlyphData
	}

	// The second pass decodes each (flags, x, y) tuple in row order.
	 := glyfIter{
		data:      ,
		flagIndex: ,
		xIndex:    ,
		yIndex:    ,
		endIndex:  glyfHeaderLen,
		// The -1 on prevEnd and finalEnd are because the contour-end index in
		// the file format is inclusive, but Go's slice[:index] is exclusive.
		prevEnd:     -1,
		finalEnd:    int32( - 1),
		numContours: int32(),
	}
	for .nextContour() {
		for .nextSegment() {
			.segments = append(.segments, .seg)
		}
	}
	return .err
}

func findXYIndexes( []byte, ,  int) (,  int32,  bool) {
	 := 0
	 := 0
	for  := 0; ; {
		if  >  {
			return 0, 0, false
		}
		if  ==  {
			break
		}

		 := 1
		if  >= len() {
			return 0, 0, false
		}
		 := []
		++
		if &flagRepeat != 0 {
			if  >= len() {
				return 0, 0, false
			}
			 += int([])
			++
		}

		 := 0
		if &flagXShortVector != 0 {
			 = 1
		} else if &flagThisXIsSame == 0 {
			 = 2
		}
		 +=  * 

		 := 0
		if &flagYShortVector != 0 {
			 = 1
		} else if &flagThisYIsSame == 0 {
			 = 2
		}
		 +=  * 

		 += 
	}
	if ++ > len() {
		return 0, 0, false
	}
	return int32(), int32( + ), true
}

func loadCompoundGlyf( *Font,  *Buffer,  []byte, ,  uint32) error {
	if ++;  == maxCompoundRecursionDepth {
		return errUnsupportedCompoundGlyph
	}

	// Read and process the compound glyph's components. They are two separate
	// for loops, since reading parses the elements of the data slice, and
	// processing can overwrite the backing array.

	 := 
	for {
		if  >= maxCompoundStackSize {
			return errUnsupportedCompoundGlyph
		}
		 := &.compoundStack[]
		++

		if len() < 4 {
			return errInvalidGlyphData
		}
		 := u16()
		.glyphIndex = GlyphIndex(u16([2:]))
		if &flagArg1And2AreWords == 0 {
			if len() < 6 {
				return errInvalidGlyphData
			}
			.dx = int16(int8([4]))
			.dy = int16(int8([5]))
			 = [6:]
		} else {
			if len() < 8 {
				return errInvalidGlyphData
			}
			.dx = int16(u16([4:]))
			.dy = int16(u16([6:]))
			 = [8:]
		}

		if &flagArgsAreXYValues == 0 {
			return errUnsupportedCompoundGlyph
		}
		.hasTransform = &(flagWeHaveAScale|flagWeHaveAnXAndYScale|flagWeHaveATwoByTwo) != 0
		if .hasTransform {
			switch {
			case &flagWeHaveAScale != 0:
				if len() < 2 {
					return errInvalidGlyphData
				}
				.transformXX = int16(u16())
				.transformXY = 0
				.transformYX = 0
				.transformYY = .transformXX
				 = [2:]
			case &flagWeHaveAnXAndYScale != 0:
				if len() < 4 {
					return errInvalidGlyphData
				}
				.transformXX = int16(u16([0:]))
				.transformXY = 0
				.transformYX = 0
				.transformYY = int16(u16([2:]))
				 = [4:]
			case &flagWeHaveATwoByTwo != 0:
				if len() < 8 {
					return errInvalidGlyphData
				}
				.transformXX = int16(u16([0:]))
				.transformXY = int16(u16([2:]))
				.transformYX = int16(u16([4:]))
				.transformYY = int16(u16([6:]))
				 = [8:]
			}
		}

		if &flagMoreComponents == 0 {
			break
		}
	}

	// To support hinting, we'd have to save the remaining bytes in data here
	// and interpret them after the for loop below, since that for loop's
	// loadGlyf calls can overwrite the backing array.

	for  := ;  < ; ++ {
		 := &.compoundStack[]
		 := len(.segments)
		if  := loadGlyf(, , .glyphIndex, , );  != nil {
			return 
		}
		,  := fixed.Int26_6(.dx), fixed.Int26_6(.dy)
		 := .segments[:]
		if .hasTransform {
			 := .transformXX
			 := .transformXY
			 := .transformYX
			 := .transformYY
			for  := range  {
				transformArgs(&[].Args, , , , , , )
			}
		} else {
			for  := range  {
				translateArgs(&[].Args, , )
			}
		}
	}

	return nil
}

type glyfIter struct {
	data []byte
	err  error

	// Various indices into the data slice. See the "Decoding those points in
	// row order" comment above.
	flagIndex int32
	xIndex    int32
	yIndex    int32

	// endIndex points to the uint16 that is the inclusive point index of the
	// current contour's end. prevEnd is the previous contour's end. finalEnd
	// should match the final contour's end.
	endIndex int32
	prevEnd  int32
	finalEnd int32

	// c and p count the current contour and point, up to numContours and
	// numPoints.
	c, numContours int32
	p, nPoints     int32

	// The next two groups of fields track points and segments. Points are what
	// the underlying file format provides. Bézier curve segments are what the
	// rasterizer consumes.
	//
	// Points are either on-curve or off-curve. Two consecutive on-curve points
	// define a linear curve segment between them. N off-curve points between
	// on-curve points define N quadratic curve segments. The TrueType glyf
	// format does not use cubic curves. If N is greater than 1, some of these
	// segment end points are implicit, the midpoint of two off-curve points.
	// Given the points A, B1, B2, ..., BN, C, where A and C are on-curve and
	// all the Bs are off-curve, the segments are:
	//
	//	- A,                  B1, midpoint(B1, B2)
	//	- midpoint(B1, B2),   B2, midpoint(B2, B3)
	//	- midpoint(B2, B3),   B3, midpoint(B3, B4)
	//	- ...
	//	- midpoint(BN-1, BN), BN, C
	//
	// Note that the sequence of Bs may wrap around from the last point in the
	// glyf data to the first. A and C may also be the same point (the only
	// explicit on-curve point), or there may be no explicit on-curve points at
	// all (but still implicit ones between explicit off-curve points).

	// Points.
	x, y    int16
	on      bool
	flag    uint8
	repeats uint8

	// Segments.
	closing            bool
	closed             bool
	firstOnCurveValid  bool
	firstOffCurveValid bool
	lastOffCurveValid  bool
	firstOnCurve       fixed.Point26_6
	firstOffCurve      fixed.Point26_6
	lastOffCurve       fixed.Point26_6
	seg                Segment
}

func ( *glyfIter) () ( bool) {
	if .c == .numContours {
		if .prevEnd != .finalEnd {
			.err = errInvalidGlyphData
		}
		return false
	}
	.c++

	 := int32(u16(.data[.endIndex:]))
	.endIndex += 2
	if ( <= .prevEnd) || (.finalEnd < ) {
		.err = errInvalidGlyphData
		return false
	}
	.nPoints =  - .prevEnd
	.p = 0
	.prevEnd = 

	.closing = false
	.closed = false
	.firstOnCurveValid = false
	.firstOffCurveValid = false
	.lastOffCurveValid = false

	return true
}

func ( *glyfIter) () {
	switch {
	case !.firstOffCurveValid && !.lastOffCurveValid:
		.closed = true
		.seg = Segment{
			Op:   SegmentOpLineTo,
			Args: [3]fixed.Point26_6{.firstOnCurve},
		}
	case !.firstOffCurveValid && .lastOffCurveValid:
		.closed = true
		.seg = Segment{
			Op:   SegmentOpQuadTo,
			Args: [3]fixed.Point26_6{.lastOffCurve, .firstOnCurve},
		}
	case .firstOffCurveValid && !.lastOffCurveValid:
		.closed = true
		.seg = Segment{
			Op:   SegmentOpQuadTo,
			Args: [3]fixed.Point26_6{.firstOffCurve, .firstOnCurve},
		}
	case .firstOffCurveValid && .lastOffCurveValid:
		.lastOffCurveValid = false
		.seg = Segment{
			Op: SegmentOpQuadTo,
			Args: [3]fixed.Point26_6{
				.lastOffCurve,
				midPoint(.lastOffCurve, .firstOffCurve),
			},
		}
	}
}

func ( *glyfIter) () ( bool) {
	for !.closed {
		if .closing || !.nextPoint() {
			.closing = true
			.close()
			return true
		}

		// Convert the tuple (g.x, g.y) to a fixed.Point26_6, since the latter
		// is what's held in a Segment. The input (g.x, g.y) is a pair of int16
		// values, measured in font units, since that is what the underlying
		// format provides. The output is a pair of fixed.Int26_6 values. A
		// fixed.Int26_6 usually represents a 26.6 fixed number of pixels, but
		// this here is just a straight numerical conversion, with no scaling
		// factor. A later step scales the Segment.Args values by such a factor
		// to convert e.g. 1792 font units to 10.5 pixels at 2048 font units
		// per em and 12 ppem (pixels per em).
		 := fixed.Point26_6{
			X: fixed.Int26_6(.x),
			Y: fixed.Int26_6(.y),
		}

		if !.firstOnCurveValid {
			if .on {
				.firstOnCurve = 
				.firstOnCurveValid = true
				.seg = Segment{
					Op:   SegmentOpMoveTo,
					Args: [3]fixed.Point26_6{},
				}
				return true
			} else if !.firstOffCurveValid {
				.firstOffCurve = 
				.firstOffCurveValid = true
				continue
			} else {
				.firstOnCurve = midPoint(.firstOffCurve, )
				.firstOnCurveValid = true
				.lastOffCurve = 
				.lastOffCurveValid = true
				.seg = Segment{
					Op:   SegmentOpMoveTo,
					Args: [3]fixed.Point26_6{.firstOnCurve},
				}
				return true
			}

		} else if !.lastOffCurveValid {
			if !.on {
				.lastOffCurve = 
				.lastOffCurveValid = true
				continue
			} else {
				.seg = Segment{
					Op:   SegmentOpLineTo,
					Args: [3]fixed.Point26_6{},
				}
				return true
			}

		} else {
			if !.on {
				.seg = Segment{
					Op: SegmentOpQuadTo,
					Args: [3]fixed.Point26_6{
						.lastOffCurve,
						midPoint(.lastOffCurve, ),
					},
				}
				.lastOffCurve = 
				.lastOffCurveValid = true
				return true
			} else {
				.seg = Segment{
					Op:   SegmentOpQuadTo,
					Args: [3]fixed.Point26_6{.lastOffCurve, },
				}
				.lastOffCurveValid = false
				return true
			}
		}
	}
	return false
}

func ( *glyfIter) () ( bool) {
	if .p == .nPoints {
		return false
	}
	.p++

	if .repeats > 0 {
		.repeats--
	} else {
		.flag = .data[.flagIndex]
		.flagIndex++
		if .flag&flagRepeat != 0 {
			.repeats = .data[.flagIndex]
			.flagIndex++
		}
	}

	if .flag&flagXShortVector != 0 {
		if .flag&flagPositiveXShortVector != 0 {
			.x += int16(.data[.xIndex])
		} else {
			.x -= int16(.data[.xIndex])
		}
		.xIndex += 1
	} else if .flag&flagThisXIsSame == 0 {
		.x += int16(u16(.data[.xIndex:]))
		.xIndex += 2
	}

	if .flag&flagYShortVector != 0 {
		if .flag&flagPositiveYShortVector != 0 {
			.y += int16(.data[.yIndex])
		} else {
			.y -= int16(.data[.yIndex])
		}
		.yIndex += 1
	} else if .flag&flagThisYIsSame == 0 {
		.y += int16(u16(.data[.yIndex:]))
		.yIndex += 2
	}

	.on = .flag&flagOnCurve != 0
	return true
}