// Copyright 2010 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 raster

import (
	
	

	
)

// maxAbs returns the maximum of abs(a) and abs(b).
func maxAbs(,  fixed.Int26_6) fixed.Int26_6 {
	if  < 0 {
		 = -
	}
	if  < 0 {
		 = -
	}
	if  <  {
		return 
	}
	return 
}

// pNeg returns the vector -p, or equivalently p rotated by 180 degrees.
func pNeg( fixed.Point26_6) fixed.Point26_6 {
	return fixed.Point26_6{-.X, -.Y}
}

// pDot returns the dot product p·q.
func pDot( fixed.Point26_6,  fixed.Point26_6) fixed.Int52_12 {
	,  := int64(.X), int64(.Y)
	,  := int64(.X), int64(.Y)
	return fixed.Int52_12(* + *)
}

// pLen returns the length of the vector p.
func pLen( fixed.Point26_6) fixed.Int26_6 {
	// TODO(nigeltao): use fixed point math.
	 := float64(.X)
	 := float64(.Y)
	return fixed.Int26_6(math.Sqrt(* + *))
}

// pNorm returns the vector p normalized to the given length, or zero if p is
// degenerate.
func pNorm( fixed.Point26_6,  fixed.Int26_6) fixed.Point26_6 {
	 := pLen()
	if  == 0 {
		return fixed.Point26_6{}
	}
	,  := int64(), int64()
	 := int64(.X) *  / 
	 := int64(.Y) *  / 
	return fixed.Point26_6{fixed.Int26_6(), fixed.Int26_6()}
}

// pRot45CW returns the vector p rotated clockwise by 45 degrees.
//
// Note that the Y-axis grows downwards, so {1, 0}.Rot45CW is {1/√2, 1/√2}.
func pRot45CW( fixed.Point26_6) fixed.Point26_6 {
	// 181/256 is approximately 1/√2, or sin(π/4).
	,  := int64(.X), int64(.Y)
	 := (+ - ) * 181 / 256
	 := (+ + ) * 181 / 256
	return fixed.Point26_6{fixed.Int26_6(), fixed.Int26_6()}
}

// pRot90CW returns the vector p rotated clockwise by 90 degrees.
//
// Note that the Y-axis grows downwards, so {1, 0}.Rot90CW is {0, 1}.
func pRot90CW( fixed.Point26_6) fixed.Point26_6 {
	return fixed.Point26_6{-.Y, .X}
}

// pRot135CW returns the vector p rotated clockwise by 135 degrees.
//
// Note that the Y-axis grows downwards, so {1, 0}.Rot135CW is {-1/√2, 1/√2}.
func pRot135CW( fixed.Point26_6) fixed.Point26_6 {
	// 181/256 is approximately 1/√2, or sin(π/4).
	,  := int64(.X), int64(.Y)
	 := (- - ) * 181 / 256
	 := (+ - ) * 181 / 256
	return fixed.Point26_6{fixed.Int26_6(), fixed.Int26_6()}
}

// pRot45CCW returns the vector p rotated counter-clockwise by 45 degrees.
//
// Note that the Y-axis grows downwards, so {1, 0}.Rot45CCW is {1/√2, -1/√2}.
func pRot45CCW( fixed.Point26_6) fixed.Point26_6 {
	// 181/256 is approximately 1/√2, or sin(π/4).
	,  := int64(.X), int64(.Y)
	 := (+ + ) * 181 / 256
	 := (- + ) * 181 / 256
	return fixed.Point26_6{fixed.Int26_6(), fixed.Int26_6()}
}

// pRot90CCW returns the vector p rotated counter-clockwise by 90 degrees.
//
// Note that the Y-axis grows downwards, so {1, 0}.Rot90CCW is {0, -1}.
func pRot90CCW( fixed.Point26_6) fixed.Point26_6 {
	return fixed.Point26_6{.Y, -.X}
}

// pRot135CCW returns the vector p rotated counter-clockwise by 135 degrees.
//
// Note that the Y-axis grows downwards, so {1, 0}.Rot135CCW is {-1/√2, -1/√2}.
func pRot135CCW( fixed.Point26_6) fixed.Point26_6 {
	// 181/256 is approximately 1/√2, or sin(π/4).
	,  := int64(.X), int64(.Y)
	 := (- + ) * 181 / 256
	 := (- - ) * 181 / 256
	return fixed.Point26_6{fixed.Int26_6(), fixed.Int26_6()}
}

// An Adder accumulates points on a curve.
type Adder interface {
	// Start starts a new curve at the given point.
	Start(a fixed.Point26_6)
	// Add1 adds a linear segment to the current curve.
	Add1(b fixed.Point26_6)
	// Add2 adds a quadratic segment to the current curve.
	Add2(b, c fixed.Point26_6)
	// Add3 adds a cubic segment to the current curve.
	Add3(b, c, d fixed.Point26_6)
}

// A Path is a sequence of curves, and a curve is a start point followed by a
// sequence of linear, quadratic or cubic segments.
type Path []fixed.Int26_6

// String returns a human-readable representation of a Path.
func ( Path) () string {
	 := ""
	for  := 0;  < len(); {
		if  != 0 {
			 += " "
		}
		switch [] {
		case 0:
			 += "S0" + fmt.Sprint([]fixed.Int26_6([+1:+3]))
			 += 4
		case 1:
			 += "A1" + fmt.Sprint([]fixed.Int26_6([+1:+3]))
			 += 4
		case 2:
			 += "A2" + fmt.Sprint([]fixed.Int26_6([+1:+5]))
			 += 6
		case 3:
			 += "A3" + fmt.Sprint([]fixed.Int26_6([+1:+7]))
			 += 8
		default:
			panic("freetype/raster: bad path")
		}
	}
	return 
}

// Clear cancels any previous calls to p.Start or p.AddXxx.
func ( *Path) () {
	* = (*)[:0]
}

// Start starts a new curve at the given point.
func ( *Path) ( fixed.Point26_6) {
	* = append(*, 0, .X, .Y, 0)
}

// Add1 adds a linear segment to the current curve.
func ( *Path) ( fixed.Point26_6) {
	* = append(*, 1, .X, .Y, 1)
}

// Add2 adds a quadratic segment to the current curve.
func ( *Path) (,  fixed.Point26_6) {
	* = append(*, 2, .X, .Y, .X, .Y, 2)
}

// Add3 adds a cubic segment to the current curve.
func ( *Path) (, ,  fixed.Point26_6) {
	* = append(*, 3, .X, .Y, .X, .Y, .X, .Y, 3)
}

// AddPath adds the Path q to p.
func ( *Path) ( Path) {
	* = append(*, ...)
}

// AddStroke adds a stroked Path.
func ( *Path) ( Path,  fixed.Int26_6,  Capper,  Joiner) {
	Stroke(, , , , )
}

// firstPoint returns the first point in a non-empty Path.
func ( Path) () fixed.Point26_6 {
	return fixed.Point26_6{[1], [2]}
}

// lastPoint returns the last point in a non-empty Path.
func ( Path) () fixed.Point26_6 {
	return fixed.Point26_6{[len()-3], [len()-2]}
}

// addPathReversed adds q reversed to p.
// For example, if q consists of a linear segment from A to B followed by a
// quadratic segment from B to C to D, then the values of q looks like:
// index: 01234567890123
// value: 0AA01BB12CCDD2
// So, when adding q backwards to p, we want to Add2(C, B) followed by Add1(A).
func addPathReversed( Adder,  Path) {
	if len() == 0 {
		return
	}
	 := len() - 1
	for {
		switch [] {
		case 0:
			return
		case 1:
			 -= 4
			.Add1(
				fixed.Point26_6{[-2], [-1]},
			)
		case 2:
			 -= 6
			.Add2(
				fixed.Point26_6{[+2], [+3]},
				fixed.Point26_6{[-2], [-1]},
			)
		case 3:
			 -= 8
			.Add3(
				fixed.Point26_6{[+4], [+5]},
				fixed.Point26_6{[+2], [+3]},
				fixed.Point26_6{[-2], [-1]},
			)
		default:
			panic("freetype/raster: bad path")
		}
	}
}