// Copyright 2015 The Freetype-Go Authors. All rights reserved.
// Use of this source code is governed by your choice of either the
// FreeType License or the GNU General Public License version 2 (or
// any later version), both of which can be found in the LICENSE file.

package truetype

import (
	
	

	
	
	
)

func powerOf2( int) bool {
	return  != 0 && (&(-1)) == 0
}

// Options are optional arguments to NewFace.
type Options struct {
	// Size is the font size in points, as in "a 10 point font size".
	//
	// A zero value means to use a 12 point font size.
	Size float64

	// DPI is the dots-per-inch resolution.
	//
	// A zero value means to use 72 DPI.
	DPI float64

	// Hinting is how to quantize the glyph nodes.
	//
	// A zero value means to use no hinting.
	Hinting font.Hinting

	// GlyphCacheEntries is the number of entries in the glyph mask image
	// cache.
	//
	// If non-zero, it must be a power of 2.
	//
	// A zero value means to use 512 entries.
	GlyphCacheEntries int

	// SubPixelsX is the number of sub-pixel locations a glyph's dot is
	// quantized to, in the horizontal direction. For example, a value of 8
	// means that the dot is quantized to 1/8th of a pixel. This quantization
	// only affects the glyph mask image, not its bounding box or advance
	// width. A higher value gives a more faithful glyph image, but reduces the
	// effectiveness of the glyph cache.
	//
	// If non-zero, it must be a power of 2, and be between 1 and 64 inclusive.
	//
	// A zero value means to use 4 sub-pixel locations.
	SubPixelsX int

	// SubPixelsY is the number of sub-pixel locations a glyph's dot is
	// quantized to, in the vertical direction. For example, a value of 8
	// means that the dot is quantized to 1/8th of a pixel. This quantization
	// only affects the glyph mask image, not its bounding box or advance
	// width. A higher value gives a more faithful glyph image, but reduces the
	// effectiveness of the glyph cache.
	//
	// If non-zero, it must be a power of 2, and be between 1 and 64 inclusive.
	//
	// A zero value means to use 1 sub-pixel location.
	SubPixelsY int
}

func ( *Options) () float64 {
	if  != nil && .Size > 0 {
		return .Size
	}
	return 12
}

func ( *Options) () float64 {
	if  != nil && .DPI > 0 {
		return .DPI
	}
	return 72
}

func ( *Options) () font.Hinting {
	if  != nil {
		switch .Hinting {
		case font.HintingVertical, font.HintingFull:
			// TODO: support vertical hinting.
			return font.HintingFull
		}
	}
	return font.HintingNone
}

func ( *Options) () int {
	if  != nil && powerOf2(.GlyphCacheEntries) {
		return .GlyphCacheEntries
	}
	// 512 is 128 * 4 * 1, which lets us cache 128 glyphs at 4 * 1 subpixel
	// locations in the X and Y direction.
	return 512
}

func ( *Options) () ( uint32, ,  fixed.Int26_6) {
	if  != nil {
		switch .SubPixelsX {
		case 1, 2, 4, 8, 16, 32, 64:
			return subPixels(.SubPixelsX)
		}
	}
	// This default value of 4 isn't based on anything scientific, merely as
	// small a number as possible that looks almost as good as no quantization,
	// or returning subPixels(64).
	return subPixels(4)
}

func ( *Options) () ( uint32, ,  fixed.Int26_6) {
	if  != nil {
		switch .SubPixelsX {
		case 1, 2, 4, 8, 16, 32, 64:
			return subPixels(.SubPixelsX)
		}
	}
	// This default value of 1 isn't based on anything scientific, merely that
	// vertical sub-pixel glyph rendering is pretty rare. Baseline locations
	// can usually afford to snap to the pixel grid, so the vertical direction
	// doesn't have the deal with the horizontal's fractional advance widths.
	return subPixels(1)
}

// subPixels returns q and the bias and mask that leads to q quantized
// sub-pixel locations per full pixel.
//
// For example, q == 4 leads to a bias of 8 and a mask of 0xfffffff0, or -16,
// because we want to round fractions of fixed.Int26_6 as:
//	-  0 to  7 rounds to 0.
//	-  8 to 23 rounds to 16.
//	- 24 to 39 rounds to 32.
//	- 40 to 55 rounds to 48.
//	- 56 to 63 rounds to 64.
// which means to add 8 and then bitwise-and with -16, in two's complement
// representation.
//
// When q ==  1, we want bias == 32 and mask == -64.
// When q ==  2, we want bias == 16 and mask == -32.
// When q ==  4, we want bias ==  8 and mask == -16.
// ...
// When q == 64, we want bias ==  0 and mask ==  -1. (The no-op case).
// The pattern is clear.
func subPixels( int) ( uint32, ,  fixed.Int26_6) {
	return uint32(), 32 / fixed.Int26_6(), -64 / fixed.Int26_6()
}

// glyphCacheEntry caches the arguments and return values of rasterize.
type glyphCacheEntry struct {
	key glyphCacheKey
	val glyphCacheVal
}

type glyphCacheKey struct {
	index  Index
	fx, fy uint8
}

type glyphCacheVal struct {
	advanceWidth fixed.Int26_6
	offset       image.Point
	gw           int
	gh           int
}

type indexCacheEntry struct {
	rune  rune
	index Index
}

// NewFace returns a new font.Face for the given Font.
func ( *Font,  *Options) font.Face {
	 := &face{
		f:          ,
		hinting:    .hinting(),
		scale:      fixed.Int26_6(0.5 + (.size() * .dpi() * 64 / 72)),
		glyphCache: make([]glyphCacheEntry, .glyphCacheEntries()),
	}
	.subPixelX, .subPixelBiasX, .subPixelMaskX = .subPixelsX()
	.subPixelY, .subPixelBiasY, .subPixelMaskY = .subPixelsY()

	// Fill the cache with invalid entries. Valid glyph cache entries have fx
	// and fy in the range [0, 64). Valid index cache entries have rune >= 0.
	for  := range .glyphCache {
		.glyphCache[].key.fy = 0xff
	}
	for  := range .indexCache {
		.indexCache[].rune = -1
	}

	// Set the rasterizer's bounds to be big enough to handle the largest glyph.
	 := .Bounds(.scale)
	 := +int(.Min.X) >> 6
	 := -int(.Max.Y) >> 6
	 := +int(.Max.X+63) >> 6
	 := -int(.Min.Y-63) >> 6
	.maxw =  - 
	.maxh =  - 
	.masks = image.NewAlpha(image.Rect(0, 0, .maxw, .maxh*len(.glyphCache)))
	.r.SetBounds(.maxw, .maxh)
	.p = facePainter{}

	return 
}

type face struct {
	f             *Font
	hinting       font.Hinting
	scale         fixed.Int26_6
	subPixelX     uint32
	subPixelBiasX fixed.Int26_6
	subPixelMaskX fixed.Int26_6
	subPixelY     uint32
	subPixelBiasY fixed.Int26_6
	subPixelMaskY fixed.Int26_6
	masks         *image.Alpha
	glyphCache    []glyphCacheEntry
	r             raster.Rasterizer
	p             raster.Painter
	paintOffset   int
	maxw          int
	maxh          int
	glyphBuf      GlyphBuf
	indexCache    [indexCacheLen]indexCacheEntry

	// TODO: clip rectangle?
}

const indexCacheLen = 256

func ( *face) ( rune) Index {
	const  = indexCacheLen - 1
	 := &.indexCache[&]
	if .rune ==  {
		return .index
	}
	 := .f.Index()
	.rune = 
	.index = 
	return 
}

// Close satisfies the font.Face interface.
func ( *face) () error { return nil }

// Metrics satisfies the font.Face interface.
func ( *face) () font.Metrics {
	 := float64(.scale)
	 := float64(.f.FUnitsPerEm())
	return font.Metrics{
		Height:  .scale,
		Ascent:  fixed.Int26_6(math.Ceil( * float64(+.f.ascent) / )),
		Descent: fixed.Int26_6(math.Ceil( * float64(-.f.descent) / )),
	}
}

// Kern satisfies the font.Face interface.
func ( *face) (,  rune) fixed.Int26_6 {
	 := .index()
	 := .index()
	 := .f.Kern(.scale, , )
	if .hinting != font.HintingNone {
		 = ( + 32) &^ 63
	}
	return 
}

// Glyph satisfies the font.Face interface.
func ( *face) ( fixed.Point26_6,  rune) (
	 image.Rectangle,  image.Image,  image.Point,  fixed.Int26_6,  bool) {

	// Quantize to the sub-pixel granularity.
	 := (.X + .subPixelBiasX) & .subPixelMaskX
	 := (.Y + .subPixelBiasY) & .subPixelMaskY

	// Split the coordinates into their integer and fractional parts.
	,  := int(>>6), &0x3f
	,  := int(>>6), &0x3f

	 := .index()
	 := uint32()
	 = *.subPixelX - uint32(/.subPixelMaskX)
	 = *.subPixelY - uint32(/.subPixelMaskY)
	 &= uint32(len(.glyphCache) - 1)
	.paintOffset = .maxh * int()
	 := glyphCacheKey{
		index: ,
		fx:    uint8(),
		fy:    uint8(),
	}
	var  glyphCacheVal
	if .glyphCache[].key !=  {
		var  bool
		,  = .rasterize(, , )
		if ! {
			return image.Rectangle{}, nil, image.Point{}, 0, false
		}
		.glyphCache[] = glyphCacheEntry{, }
	} else {
		 = .glyphCache[].val
	}

	.Min = image.Point{
		X:  + .offset.X,
		Y:  + .offset.Y,
	}
	.Max = image.Point{
		X: .Min.X + .gw,
		Y: .Min.Y + .gh,
	}
	return , .masks, image.Point{Y: .paintOffset}, .advanceWidth, true
}

func ( *face) ( rune) ( fixed.Rectangle26_6,  fixed.Int26_6,  bool) {
	if  := .glyphBuf.Load(.f, .scale, .index(), .hinting);  != nil {
		return fixed.Rectangle26_6{}, 0, false
	}
	 := +.glyphBuf.Bounds.Min.X
	 := -.glyphBuf.Bounds.Max.Y
	 := +.glyphBuf.Bounds.Max.X
	 := -.glyphBuf.Bounds.Min.Y
	if  >  ||  >  {
		return fixed.Rectangle26_6{}, 0, false
	}
	return fixed.Rectangle26_6{
		Min: fixed.Point26_6{
			X: ,
			Y: ,
		},
		Max: fixed.Point26_6{
			X: ,
			Y: ,
		},
	}, .glyphBuf.AdvanceWidth, true
}

func ( *face) ( rune) ( fixed.Int26_6,  bool) {
	if  := .glyphBuf.Load(.f, .scale, .index(), .hinting);  != nil {
		return 0, false
	}
	return .glyphBuf.AdvanceWidth, true
}

// rasterize returns the advance width, integer-pixel offset to render at, and
// the width and height of the given glyph at the given sub-pixel offsets.
//
// The 26.6 fixed point arguments fx and fy must be in the range [0, 1).
func ( *face) ( Index, ,  fixed.Int26_6) ( glyphCacheVal,  bool) {
	if  := .glyphBuf.Load(.f, .scale, , .hinting);  != nil {
		return glyphCacheVal{}, false
	}
	// Calculate the integer-pixel bounds for the glyph.
	 := int(+.glyphBuf.Bounds.Min.X) >> 6
	 := int(-.glyphBuf.Bounds.Max.Y) >> 6
	 := int(+.glyphBuf.Bounds.Max.X+0x3f) >> 6
	 := int(-.glyphBuf.Bounds.Min.Y+0x3f) >> 6
	if  >  ||  >  {
		return glyphCacheVal{}, false
	}
	// A TrueType's glyph's nodes can have negative co-ordinates, but the
	// rasterizer clips anything left of x=0 or above y=0. xmin and ymin are
	// the pixel offsets, based on the font's FUnit metrics, that let a
	// negative co-ordinate in TrueType space be non-negative in rasterizer
	// space. xmin and ymin are typically <= 0.
	 -= fixed.Int26_6( << 6)
	 -= fixed.Int26_6( << 6)
	// Rasterize the glyph's vectors.
	.r.Clear()
	 := .paintOffset * .maxw
	clear(.masks.Pix[ : +.maxw*.maxh])
	 := 0
	for ,  := range .glyphBuf.Ends {
		.drawContour(.glyphBuf.Points[:], , )
		 = 
	}
	.r.Rasterize(.p)
	return glyphCacheVal{
		.glyphBuf.AdvanceWidth,
		image.Point{, },
		 - ,
		 - ,
	}, true
}

func clear( []byte) {
	for  := range  {
		[] = 0
	}
}

// drawContour draws the given closed contour with the given offset.
func ( *face) ( []Point, ,  fixed.Int26_6) {
	if len() == 0 {
		return
	}

	// The low bit of each point's Flags value is whether the point is on the
	// curve. Truetype fonts only have quadratic Bézier curves, not cubics.
	// Thus, two consecutive off-curve points imply an on-curve point in the
	// middle of those two.
	//
	// See http://chanae.walon.org/pub/ttf/ttf_glyphs.htm for more details.

	// ps[0] is a truetype.Point measured in FUnits and positive Y going
	// upwards. start is the same thing measured in fixed point units and
	// positive Y going downwards, and offset by (dx, dy).
	 := fixed.Point26_6{
		X:  + [0].X,
		Y:  - [0].Y,
	}
	var  []Point
	if [0].Flags&0x01 != 0 {
		 = [1:]
	} else {
		 := fixed.Point26_6{
			X:  + [len()-1].X,
			Y:  - [len()-1].Y,
		}
		if [len()-1].Flags&0x01 != 0 {
			 = 
			 = [:len()-1]
		} else {
			 = fixed.Point26_6{
				X: (.X + .X) / 2,
				Y: (.Y + .Y) / 2,
			}
			 = 
		}
	}
	.r.Start()
	,  := , true
	for ,  := range  {
		 := fixed.Point26_6{
			X:  + .X,
			Y:  - .Y,
		}
		 := .Flags&0x01 != 0
		if  {
			if  {
				.r.Add1()
			} else {
				.r.Add2(, )
			}
		} else {
			if  {
				// No-op.
			} else {
				 := fixed.Point26_6{
					X: (.X + .X) / 2,
					Y: (.Y + .Y) / 2,
				}
				.r.Add2(, )
			}
		}
		,  = , 
	}
	// Close the curve.
	if  {
		.r.Add1()
	} else {
		.r.Add2(, )
	}
}

// facePainter is like a raster.AlphaSrcPainter, with an additional Y offset
// (face.paintOffset) to the painted spans.
type facePainter struct {
	a *face
}

func ( facePainter) ( []raster.Span,  bool) {
	 := .a.masks
	 := .Bounds()
	.Min.Y = .a.paintOffset
	.Max.Y = .a.paintOffset + .a.maxh
	for ,  := range  {
		.Y += .a.paintOffset
		if .Y < .Min.Y {
			continue
		}
		if .Y >= .Max.Y {
			return
		}
		if .X0 < .Min.X {
			.X0 = .Min.X
		}
		if .X1 > .Max.X {
			.X1 = .Max.X
		}
		if .X0 >= .X1 {
			continue
		}
		 := (.Y-.Rect.Min.Y)*.Stride - .Rect.Min.X
		 := .Pix[+.X0 : +.X1]
		 := uint8(.Alpha >> 8)
		for  := range  {
			[] = 
		}
	}
}