diff --git a/util.go b/util.go index 3cd3258..0f46ac6 100644 --- a/util.go +++ b/util.go @@ -10,6 +10,7 @@ import ( "os" "strings" + "github.com/golang/freetype/raster" "github.com/golang/freetype/truetype" "golang.org/x/image/font" @@ -77,6 +78,18 @@ func fi(x float64) fixed.Int26_6 { return fixed.Int26_6(x * 64) } +func unfix(x fixed.Int26_6) float64 { + const shift, mask = 6, 1<<6 - 1 + if x >= 0 { + return float64(x>>shift) + float64(x&mask)/64 + } + x = -x + if x >= 0 { + return -(float64(x>>shift) + float64(x&mask)/64) + } + return 0 +} + func loadFontFace(path string, points float64) font.Face { fontBytes, err := ioutil.ReadFile(path) if err != nil { @@ -91,3 +104,55 @@ func loadFontFace(path string, points float64) font.Face { // Hinting: font.HintingFull, }) } + +func flattenPath(p raster.Path) [][]Point { + var result [][]Point + path := make([]Point, 0, 16) + var cx, cy float64 + for i := 0; i < len(p); { + switch p[i] { + case 0: + if len(path) > 0 { + result = append(result, path) + path = make([]Point, 0, 16) + } + x := unfix(p[i+1]) + y := unfix(p[i+2]) + path = append(path, Point{x, y}) + cx, cy = x, y + i += 4 + case 1: + x := unfix(p[i+1]) + y := unfix(p[i+2]) + path = append(path, Point{x, y}) + cx, cy = x, y + i += 4 + case 2: + x1 := unfix(p[i+1]) + y1 := unfix(p[i+2]) + x2 := unfix(p[i+3]) + y2 := unfix(p[i+4]) + points := QuadraticBezier(cx, cy, x1, y1, x2, y2) + path = append(path, points...) + cx, cy = x2, y2 + i += 6 + case 3: + x1 := unfix(p[i+1]) + y1 := unfix(p[i+2]) + x2 := unfix(p[i+3]) + y2 := unfix(p[i+4]) + x3 := unfix(p[i+5]) + y3 := unfix(p[i+6]) + points := CubicBezier(cx, cy, x1, y1, x2, y2, x3, y3) + path = append(path, points...) + cx, cy = x3, y3 + i += 8 + default: + panic("bad path") + } + } + if len(path) > 0 { + result = append(result, path) + } + return result +}