// 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 (
	"golang.org/x/image/math/fixed"
)

// 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(p, q fixed.Point26_6) fixed.Point26_6 {
	return fixed.Point26_6{
		X: (p.X + q.X) / 2,
		Y: (p.Y + q.Y) / 2,
	}
}

func parseLoca(src *source, loca table, glyfOffset uint32, indexToLocFormat bool, numGlyphs int) (locations []uint32, err error) {
	if indexToLocFormat {
		if loca.length != 4*uint32(numGlyphs+1) {
			return nil, errInvalidLocaTable
		}
	} else {
		if loca.length != 2*uint32(numGlyphs+1) {
			return nil, errInvalidLocaTable
		}
	}

	locations = make([]uint32, numGlyphs+1)
	buf, err := src.view(nil, int(loca.offset), int(loca.length))
	if err != nil {
		return nil, err
	}

	if indexToLocFormat {
		for i := range locations {
			locations[i] = 1*uint32(u32(buf[4*i:])) + glyfOffset
		}
	} else {
		for i := range locations {
			locations[i] = 2*uint32(u16(buf[2*i:])) + glyfOffset
		}
	}
	return locations, err
}

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

func loadGlyf(f *Font, b *Buffer, x GlyphIndex, stackBottom, recursionDepth uint32) error {
	data, err := f.viewGlyphData(b, x)
	if err != nil {
		return err
	}
	if len(data) == 0 {
		return nil
	}
	if len(data) < glyfHeaderLen {
		return errInvalidGlyphData
	}
	index := glyfHeaderLen

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

	if numContours < 0 {
		return loadCompoundGlyf(f, b, data[glyfHeaderLen:], stackBottom, recursionDepth)
	}

	// Skip the hinting instructions.
	index += 2
	if index > len(data) {
		return errInvalidGlyphData
	}
	hintsLength := int(u16(data[index-2:]))
	index += hintsLength
	if index > len(data) {
		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.
	flagIndex := int32(index)
	xIndex, yIndex, ok := findXYIndexes(data, index, numPoints)
	if !ok {
		return errInvalidGlyphData
	}

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

func findXYIndexes(data []byte, index, numPoints int) (xIndex, yIndex int32, ok bool) {
	xDataLen := 0
	yDataLen := 0
	for i := 0; ; {
		if i > numPoints {
			return 0, 0, false
		}
		if i == numPoints {
			break
		}

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

		xSize := 0
		if flag&flagXShortVector != 0 {
			xSize = 1
		} else if flag&flagThisXIsSame == 0 {
			xSize = 2
		}
		xDataLen += xSize * repeatCount

		ySize := 0
		if flag&flagYShortVector != 0 {
			ySize = 1
		} else if flag&flagThisYIsSame == 0 {
			ySize = 2
		}
		yDataLen += ySize * repeatCount

		i += repeatCount
	}
	if index+xDataLen+yDataLen > len(data) {
		return 0, 0, false
	}
	return int32(index), int32(index + xDataLen), true
}

func loadCompoundGlyf(f *Font, b *Buffer, data []byte, stackBottom, recursionDepth uint32) error {
	if recursionDepth++; recursionDepth == 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.

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

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

		if flags&flagArgsAreXYValues == 0 {
			return errUnsupportedCompoundGlyph
		}
		elem.hasTransform = flags&(flagWeHaveAScale|flagWeHaveAnXAndYScale|flagWeHaveATwoByTwo) != 0
		if elem.hasTransform {
			switch {
			case flags&flagWeHaveAScale != 0:
				if len(data) < 2 {
					return errInvalidGlyphData
				}
				elem.transformXX = int16(u16(data))
				elem.transformXY = 0
				elem.transformYX = 0
				elem.transformYY = elem.transformXX
				data = data[2:]
			case flags&flagWeHaveAnXAndYScale != 0:
				if len(data) < 4 {
					return errInvalidGlyphData
				}
				elem.transformXX = int16(u16(data[0:]))
				elem.transformXY = 0
				elem.transformYX = 0
				elem.transformYY = int16(u16(data[2:]))
				data = data[4:]
			case flags&flagWeHaveATwoByTwo != 0:
				if len(data) < 8 {
					return errInvalidGlyphData
				}
				elem.transformXX = int16(u16(data[0:]))
				elem.transformXY = int16(u16(data[2:]))
				elem.transformYX = int16(u16(data[4:]))
				elem.transformYY = int16(u16(data[6:]))
				data = data[8:]
				// TODO: find a font that does this, so we can verify that
				// we've got the xy vs yx ordering right.
				return errUnsupportedCompoundGlyph
			}
		}

		if flags&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 i := stackBottom; i < stackTop; i++ {
		elem := &b.compoundStack[i]
		base := len(b.segments)
		if err := loadGlyf(f, b, elem.glyphIndex, stackTop, recursionDepth); err != nil {
			return err
		}
		dx, dy := fixed.Int26_6(elem.dx), fixed.Int26_6(elem.dy)
		segs := b.segments[base:]
		if elem.hasTransform {
			txx := elem.transformXX
			txy := elem.transformXY
			tyx := elem.transformYX
			tyy := elem.transformYY
			for j := range segs {
				transformArgs(&segs[j].Args, txx, txy, tyx, tyy, dx, dy)
			}
		} else {
			for j := range segs {
				translateArgs(&segs[j].Args, dx, dy)
			}
		}
	}

	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.
	endIndex int32
	prevEnd  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 (g *glyfIter) nextContour() (ok bool) {
	if g.c == g.numContours {
		return false
	}
	g.c++

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

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

	return true
}

func (g *glyfIter) close() {
	switch {
	case !g.firstOffCurveValid && !g.lastOffCurveValid:
		g.closed = true
		g.seg = Segment{
			Op: SegmentOpLineTo,
			Args: [6]fixed.Int26_6{
				g.firstOnCurve.X,
				g.firstOnCurve.Y,
			},
		}
	case !g.firstOffCurveValid && g.lastOffCurveValid:
		g.closed = true
		g.seg = Segment{
			Op: SegmentOpQuadTo,
			Args: [6]fixed.Int26_6{
				g.lastOffCurve.X,
				g.lastOffCurve.Y,
				g.firstOnCurve.X,
				g.firstOnCurve.Y,
			},
		}
	case g.firstOffCurveValid && !g.lastOffCurveValid:
		g.closed = true
		g.seg = Segment{
			Op: SegmentOpQuadTo,
			Args: [6]fixed.Int26_6{
				g.firstOffCurve.X,
				g.firstOffCurve.Y,
				g.firstOnCurve.X,
				g.firstOnCurve.Y,
			},
		}
	case g.firstOffCurveValid && g.lastOffCurveValid:
		mid := midPoint(g.lastOffCurve, g.firstOffCurve)
		g.lastOffCurveValid = false
		g.seg = Segment{
			Op: SegmentOpQuadTo,
			Args: [6]fixed.Int26_6{
				g.lastOffCurve.X,
				g.lastOffCurve.Y,
				mid.X,
				mid.Y,
			},
		}
	}
}

func (g *glyfIter) nextSegment() (ok bool) {
	for !g.closed {
		if g.closing || !g.nextPoint() {
			g.closing = true
			g.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).
		p := fixed.Point26_6{
			X: fixed.Int26_6(g.x),
			Y: fixed.Int26_6(g.y),
		}

		if !g.firstOnCurveValid {
			if g.on {
				g.firstOnCurve = p
				g.firstOnCurveValid = true
				g.seg = Segment{
					Op: SegmentOpMoveTo,
					Args: [6]fixed.Int26_6{
						p.X,
						p.Y,
					},
				}
				return true
			} else if !g.firstOffCurveValid {
				g.firstOffCurve = p
				g.firstOffCurveValid = true
				continue
			} else {
				midp := midPoint(g.firstOffCurve, p)
				g.firstOnCurve = midp
				g.firstOnCurveValid = true
				g.lastOffCurve = p
				g.lastOffCurveValid = true
				g.seg = Segment{
					Op: SegmentOpMoveTo,
					Args: [6]fixed.Int26_6{
						midp.X,
						midp.Y,
					},
				}
				return true
			}

		} else if !g.lastOffCurveValid {
			if !g.on {
				g.lastOffCurve = p
				g.lastOffCurveValid = true
				continue
			} else {
				g.seg = Segment{
					Op: SegmentOpLineTo,
					Args: [6]fixed.Int26_6{
						p.X,
						p.Y,
					},
				}
				return true
			}

		} else {
			if !g.on {
				midp := midPoint(g.lastOffCurve, p)
				g.seg = Segment{
					Op: SegmentOpQuadTo,
					Args: [6]fixed.Int26_6{
						g.lastOffCurve.X,
						g.lastOffCurve.Y,
						midp.X,
						midp.Y,
					},
				}
				g.lastOffCurve = p
				g.lastOffCurveValid = true
				return true
			} else {
				g.seg = Segment{
					Op: SegmentOpQuadTo,
					Args: [6]fixed.Int26_6{
						g.lastOffCurve.X,
						g.lastOffCurve.Y,
						p.X,
						p.Y,
					},
				}
				g.lastOffCurveValid = false
				return true
			}
		}
	}
	return false
}

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

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

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

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

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