package textmeasure

import (
	
	

	
	

	
)

// glyph describes one glyph in an atlas.
type glyph struct {
	dot     *geo.Point
	frame   *rect
	advance float64
}

// atlas is a set of pre-drawn glyphs of a fixed set of runes. This allows for efficient text drawing.
type atlas struct {
	face       font.Face
	mapping    map[rune]glyph
	ascent     float64
	descent    float64
	lineHeight float64
}

// NewAtlas creates a new atlas containing glyphs of the union of the given sets of runes (plus
// unicode.ReplacementChar) from the given font face.
//
// Creating an atlas is rather expensive, do not create a new atlas each frame.
//
// Do not destroy or close the font.Face after creating the atlas. atlas still uses it.
func ( font.Face,  ...[]rune) *atlas {
	 := make(map[rune]bool)
	 := []rune{unicode.ReplacementChar}
	for ,  := range  {
		for ,  := range  {
			if ![] {
				 = append(, )
				[] = true
			}
		}
	}

	,  := makeSquareMapping(, , fixed.I(2))

	 := &rect{
		tl: geo.NewPoint(
			i2f(.Min.X),
			i2f(.Min.Y),
		),
		br: geo.NewPoint(
			i2f(.Max.X),
			i2f(.Max.Y),
		),
	}

	 := make(map[rune]glyph)
	for ,  := range  {
		[] = glyph{
			dot: geo.NewPoint(
				i2f(.dot.X),
				.br.Y-(i2f(.dot.Y)-.tl.Y),
			),
			frame: rect{
				tl: geo.NewPoint(
					i2f(.frame.Min.X),
					.br.Y-(i2f(.frame.Min.Y)-.tl.Y),
				),
				br: geo.NewPoint(
					i2f(.frame.Max.X),
					.br.Y-(i2f(.frame.Max.Y)-.tl.Y),
				),
			}.norm(),
			advance: i2f(.advance),
		}
	}

	return &atlas{
		face:       ,
		mapping:    ,
		ascent:     i2f(.Metrics().Ascent),
		descent:    i2f(.Metrics().Descent),
		lineHeight: i2f(.Metrics().Height),
	}
}

func ( *atlas) ( rune) bool {
	,  := .mapping[]
	return 
}

// glyph returns the description of r within the atlas.
func ( *atlas) ( rune) glyph {
	return .mapping[]
}

// Kern returns the kerning distance between runes r0 and r1. Positive distance means that the
// glyphs should be further apart.
func ( *atlas) (,  rune) float64 {
	return i2f(.face.Kern(, ))
}

// Ascent returns the distance from the top of the line to the baseline.
func ( *atlas) () float64 {
	return .ascent
}

// Descent returns the distance from the baseline to the bottom of the line.
func ( *atlas) () float64 {
	return .descent
}

// DrawRune returns parameters necessary for drawing a rune glyph.
//
// Rect is a rectangle where the glyph should be positioned. frame is the glyph frame inside the
// atlas's Picture. NewDot is the new position of the dot.
func ( *atlas) (,  rune,  *geo.Point) (, ,  *rect,  *geo.Point) {
	, ,  := .measureRune(, , )
	if  == nil {
		return newRect(), newRect(), newRect(), 
	}
	 = .rect()
	 = 
	if .w()*.h() != 0 {
		 = .rect()
	}
	return , , , 
}

// runeRect keeps temporary glyph bounds on the stack. Ruler needs the same
// arithmetic as DrawRune, but does not need a heap rectangle for each glyph.
type runeRect struct{ tl, br geo.Point }

func ( runeRect) () float64  { return .br.X - .tl.X }
func ( runeRect) () float64  { return .br.Y - .tl.Y }
func ( runeRect) () *rect { return &rect{tl: .tl.Copy(), br: .br.Copy()} }

func ( *atlas) (,  rune,  *geo.Point) (,  runeRect,  *rect) {
	if !.contains() {
		 = unicode.ReplacementChar
	}
	if !.contains(unicode.ReplacementChar) {
		return runeRect{}, runeRect{}, nil
	}
	if !.contains() {
		 = unicode.ReplacementChar
	}
	if  >= 0 {
		.X += .Kern(, )
	}
	 := .glyph()
	// Preserve the packed operation order even for fractional or large dots.
	,  := .X-.dot.X, .Y-.dot.Y
	 = runeRect{
		tl: geo.Point{X: .frame.tl.X + , Y: .frame.tl.Y + },
		br: geo.Point{X: .frame.br.X + , Y: .frame.br.Y + },
	}
	 = 
	if .w()*.h() != 0 {
		.tl.Y = .Y - .Descent()
		.br.Y = .Y + .Ascent()
	}
	.X += .advance
	return , , .frame
}

type fixedGlyph struct {
	dot     fixed.Point26_6
	frame   fixed.Rectangle26_6
	advance fixed.Int26_6
}

// makeSquareMapping finds an optimal glyph arrangement of the given runes, so that their common
// bounding box is as square as possible.
func makeSquareMapping( font.Face,  []rune,  fixed.Int26_6) (map[rune]fixedGlyph, fixed.Rectangle26_6) {
	if ,  := .(*metricPreservingFace);  {
		return makeMetricsSquareMapping(, , )
	}
	 := sort.Search(int(fixed.I(1024*1024)), func( int) bool {
		 := fixed.Int26_6()
		,  := makeMapping(, , , )
		return .Max.X-.Min.X >= .Max.Y-.Min.Y
	})
	return makeMapping(, , , fixed.Int26_6())
}

// makeMapping arranges glyphs of the given runes into rows in such a way, that no glyph is located
// fully to the right of the specified width. Specifically, it places glyphs in a row one by one and
// once it reaches the specified width, it starts a new row.
func makeMapping( font.Face,  []rune, ,  fixed.Int26_6) (map[rune]fixedGlyph, fixed.Rectangle26_6) {
	 := make(map[rune]fixedGlyph)
	 := fixed.Rectangle26_6{}

	 := fixed.P(0, 0)

	for ,  := range  {
		, ,  := .GlyphBounds()
		if ! {
			continue
		}

		// this is important for drawing, artifacts arise otherwise
		 := fixed.Rectangle26_6{
			Min: fixed.P(.Min.X.Floor(), .Min.Y.Floor()),
			Max: fixed.P(.Max.X.Ceil(), .Max.Y.Ceil()),
		}

		.X -= .Min.X
		 = .Add()

		[] = fixedGlyph{
			dot:     ,
			frame:   ,
			advance: ,
		}
		 = .Union()

		.X = .Max.X

		// padding + align to integer
		.X += 
		.X = fixed.I(.X.Ceil())

		// width exceeded, new row
		if .Max.X >=  {
			.X = 0
			.Y += .Metrics().Ascent + .Metrics().Descent

			// padding + align to integer
			.Y += 
			.Y = fixed.I(.Y.Ceil())
		}
	}

	return , 
}

func i2f( fixed.Int26_6) float64 {
	return float64() / (1 << 6)
}