move path functions to path.go
This commit is contained in:
parent
2a0857f791
commit
a6a18ab3e8
140
path.go
Normal file
140
path.go
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
package gg
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/golang/freetype/raster"
|
||||||
|
"golang.org/x/image/math/fixed"
|
||||||
|
)
|
||||||
|
|
||||||
|
func flattenPath(p raster.Path) [][]Point {
|
||||||
|
var result [][]Point
|
||||||
|
var path []Point
|
||||||
|
var cx, cy float64
|
||||||
|
for i := 0; i < len(p); {
|
||||||
|
switch p[i] {
|
||||||
|
case 0:
|
||||||
|
if len(path) > 0 {
|
||||||
|
result = append(result, path)
|
||||||
|
path = nil
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
func dashPath(paths [][]Point, dashes []float64) [][]Point {
|
||||||
|
var result [][]Point
|
||||||
|
if len(dashes) == 0 {
|
||||||
|
return paths
|
||||||
|
}
|
||||||
|
if len(dashes) == 1 {
|
||||||
|
dashes = append(dashes, dashes[0])
|
||||||
|
}
|
||||||
|
for _, path := range paths {
|
||||||
|
if len(path) < 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
previous := path[0]
|
||||||
|
pathIndex := 1
|
||||||
|
dashIndex := 0
|
||||||
|
segmentLength := 0.0
|
||||||
|
var segment []Point
|
||||||
|
segment = append(segment, previous)
|
||||||
|
for pathIndex < len(path) {
|
||||||
|
dashLength := dashes[dashIndex]
|
||||||
|
point := path[pathIndex]
|
||||||
|
d := previous.Distance(point)
|
||||||
|
maxd := dashLength - segmentLength
|
||||||
|
if d > maxd {
|
||||||
|
t := maxd / d
|
||||||
|
p := previous.Interpolate(point, t)
|
||||||
|
segment = append(segment, p)
|
||||||
|
if dashIndex%2 == 0 && len(segment) > 1 {
|
||||||
|
result = append(result, segment)
|
||||||
|
}
|
||||||
|
segment = nil
|
||||||
|
segment = append(segment, p)
|
||||||
|
segmentLength = 0
|
||||||
|
previous = p
|
||||||
|
dashIndex = (dashIndex + 1) % len(dashes)
|
||||||
|
} else {
|
||||||
|
segment = append(segment, point)
|
||||||
|
previous = point
|
||||||
|
segmentLength += d
|
||||||
|
pathIndex++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if dashIndex%2 == 0 && len(segment) > 1 {
|
||||||
|
result = append(result, segment)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func rasterPath(paths [][]Point) raster.Path {
|
||||||
|
var result raster.Path
|
||||||
|
for _, path := range paths {
|
||||||
|
var previous fixed.Point26_6
|
||||||
|
for i, point := range path {
|
||||||
|
f := point.Fixed()
|
||||||
|
if i == 0 {
|
||||||
|
result.Start(f)
|
||||||
|
} else {
|
||||||
|
dx := f.X - previous.X
|
||||||
|
dy := f.Y - previous.Y
|
||||||
|
if dx < 0 {
|
||||||
|
dx = -dx
|
||||||
|
}
|
||||||
|
if dy < 0 {
|
||||||
|
dy = -dy
|
||||||
|
}
|
||||||
|
if dx+dy > 4 {
|
||||||
|
// TODO: this is a hack for cases where two points are
|
||||||
|
// too close - causes rendering issues with joins / caps
|
||||||
|
result.Add1(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
previous = f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func dashed(path raster.Path, dashes []float64) raster.Path {
|
||||||
|
return rasterPath(dashPath(flattenPath(path), dashes))
|
||||||
|
}
|
135
util.go
135
util.go
@ -10,7 +10,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/golang/freetype/raster"
|
|
||||||
"github.com/golang/freetype/truetype"
|
"github.com/golang/freetype/truetype"
|
||||||
|
|
||||||
"golang.org/x/image/font"
|
"golang.org/x/image/font"
|
||||||
@ -105,137 +104,3 @@ func loadFontFace(path string, points float64) (font.Face, error) {
|
|||||||
})
|
})
|
||||||
return face, nil
|
return face, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func flattenPath(p raster.Path) [][]Point {
|
|
||||||
var result [][]Point
|
|
||||||
var path []Point
|
|
||||||
var cx, cy float64
|
|
||||||
for i := 0; i < len(p); {
|
|
||||||
switch p[i] {
|
|
||||||
case 0:
|
|
||||||
if len(path) > 0 {
|
|
||||||
result = append(result, path)
|
|
||||||
path = nil
|
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
func dashPath(paths [][]Point, dashes []float64) [][]Point {
|
|
||||||
var result [][]Point
|
|
||||||
if len(dashes) == 0 {
|
|
||||||
return paths
|
|
||||||
}
|
|
||||||
if len(dashes) == 1 {
|
|
||||||
dashes = append(dashes, dashes[0])
|
|
||||||
}
|
|
||||||
for _, path := range paths {
|
|
||||||
if len(path) < 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
previous := path[0]
|
|
||||||
pathIndex := 1
|
|
||||||
dashIndex := 0
|
|
||||||
segmentLength := 0.0
|
|
||||||
var segment []Point
|
|
||||||
segment = append(segment, previous)
|
|
||||||
for pathIndex < len(path) {
|
|
||||||
dashLength := dashes[dashIndex]
|
|
||||||
point := path[pathIndex]
|
|
||||||
d := previous.Distance(point)
|
|
||||||
maxd := dashLength - segmentLength
|
|
||||||
if d > maxd {
|
|
||||||
t := maxd / d
|
|
||||||
p := previous.Interpolate(point, t)
|
|
||||||
segment = append(segment, p)
|
|
||||||
if dashIndex%2 == 0 && len(segment) > 1 {
|
|
||||||
result = append(result, segment)
|
|
||||||
}
|
|
||||||
segment = nil
|
|
||||||
segment = append(segment, p)
|
|
||||||
segmentLength = 0
|
|
||||||
previous = p
|
|
||||||
dashIndex = (dashIndex + 1) % len(dashes)
|
|
||||||
} else {
|
|
||||||
segment = append(segment, point)
|
|
||||||
previous = point
|
|
||||||
segmentLength += d
|
|
||||||
pathIndex++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if dashIndex%2 == 0 && len(segment) > 1 {
|
|
||||||
result = append(result, segment)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func rasterPath(paths [][]Point) raster.Path {
|
|
||||||
var result raster.Path
|
|
||||||
for _, path := range paths {
|
|
||||||
var previous fixed.Point26_6
|
|
||||||
for i, point := range path {
|
|
||||||
f := point.Fixed()
|
|
||||||
if i == 0 {
|
|
||||||
result.Start(f)
|
|
||||||
} else {
|
|
||||||
dx := f.X - previous.X
|
|
||||||
dy := f.Y - previous.Y
|
|
||||||
if dx < 0 {
|
|
||||||
dx = -dx
|
|
||||||
}
|
|
||||||
if dy < 0 {
|
|
||||||
dy = -dy
|
|
||||||
}
|
|
||||||
if dx+dy > 4 {
|
|
||||||
// TODO: this is a hack for cases where two points are
|
|
||||||
// too close - causes rendering issues with joins / caps
|
|
||||||
result.Add1(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
previous = f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func dashed(path raster.Path, dashes []float64) raster.Path {
|
|
||||||
return rasterPath(dashPath(flattenPath(path), dashes))
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user