Skip to content

Commit

Permalink
Add scanx benchmarks, see #334
Browse files Browse the repository at this point in the history
  • Loading branch information
tdewolff committed Feb 2, 2025
1 parent 095c872 commit 24ed619
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 20 deletions.
6 changes: 6 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ require (
github.com/paulmach/orb v0.11.1
github.com/paulmach/osm v0.8.0
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
github.com/srwiley/scanx v0.0.0-20190309010443-e94503791388
github.com/tdewolff/argp v0.0.0-20240625173203-87b04d5d3e52
github.com/tdewolff/font v0.0.0-20250120192450-68a3ecdf9008
github.com/tdewolff/minify/v2 v2.21.1
Expand All @@ -33,7 +34,11 @@ require (
filippo.io/edwards25519 v1.1.0 // indirect
fyne.io/systray v1.11.0 // indirect
git.sr.ht/~sbinet/gg v0.6.0 // indirect
github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298 // indirect
github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966 // indirect
github.com/BurntSushi/toml v1.4.0 // indirect
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 // indirect
github.com/BurntSushi/xgbutil v0.0.0-20190907113008-ad855c713046 // indirect
github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b // indirect
github.com/andybalholm/brotli v1.1.1 // indirect
github.com/benoitkugler/textlayout v0.3.0 // indirect
Expand All @@ -57,6 +62,7 @@ require (
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rymdport/portal v0.2.6 // indirect
github.com/srwiley/scanFT v0.0.0-20220128184157-0d1ee492111f // indirect
go.mongodb.org/mongo-driver v1.17.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Expand Down
31 changes: 11 additions & 20 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,17 @@ git.sr.ht/~sbinet/cmpimg v0.1.0 h1:E0zPRk2muWuCqSKSVZIWsgtU9pjsw3eKHi8VmQeScxo=
git.sr.ht/~sbinet/cmpimg v0.1.0/go.mod h1:FU12psLbF4TfNXkKH2ZZQ29crIqoiqTZmeQ7dkp/pxE=
git.sr.ht/~sbinet/gg v0.6.0 h1:RIzgkizAk+9r7uPzf/VfbJHBMKUr0F5hRFxTUGMnt38=
git.sr.ht/~sbinet/gg v0.6.0/go.mod h1:uucygbfC9wVPQIfrmwM2et0imr8L7KQWywX0xpFMm94=
github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298 h1:1qlsVAQJXZHsaM8b6OLVo6muQUQd4CwkH/D3fnnbHXA=
github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298/go.mod h1:D+QujdIlUNfa0igpNMk6UIvlb6C252URs4yupRUV4lQ=
github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966 h1:lTG4HQym5oPKjL7nGs+csTgiDna685ZXjxijkne828g=
github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966/go.mod h1:Mid70uvE93zn9wgF92A/r5ixgnvX8Lh68fxp9KQBaI0=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/BurntSushi/xgbutil v0.0.0-20190907113008-ad855c713046 h1:O/r2Sj+8QcMF7V5IcmiE2sMFV2q3J47BEirxbXJAdzA=
github.com/BurntSushi/xgbutil v0.0.0-20190907113008-ad855c713046/go.mod h1:uw9h2sd4WWHOPdJ13MQpwK5qYWKYDumDqxWWIknEQ+k=
github.com/ByteArena/poly2tri-go v0.0.0-20170716161910-d102ad91854f h1:l7moT9o/v/9acCWA64Yz/HDLqjcRTvc0noQACi4MsJw=
github.com/ByteArena/poly2tri-go v0.0.0-20170716161910-d102ad91854f/go.mod h1:vIOkSdX3NDCPwgu8FIuTat2zDF0FPXXQ0RYFRy+oQic=
github.com/Kagami/go-avif v0.1.0 h1:8GHAGLxCdFfhpd4Zg8j1EqO7rtcQNenxIDerC/uu68w=
Expand Down Expand Up @@ -335,6 +342,10 @@ github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c h1:km8GpoQut05eY3GiY
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS5Hmnjxy6AgTPd0Inb3pW05ftPSX7NZO7Q=
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ=
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE=
github.com/srwiley/scanFT v0.0.0-20220128184157-0d1ee492111f h1:uLR2GaV0kWYZ3Ns3l3sjtiN+mOWAQadvrL8HXcyKjl0=
github.com/srwiley/scanFT v0.0.0-20220128184157-0d1ee492111f/go.mod h1:LZwgIPG9X6nH6j5Ef+xMFspl6Hru4b5EJxzMfeqHYJY=
github.com/srwiley/scanx v0.0.0-20190309010443-e94503791388 h1:ZdkidVdpLW13BQ9a+/3uerT2ezy9J7KQWH18JCfhDmI=
github.com/srwiley/scanx v0.0.0-20190309010443-e94503791388/go.mod h1:C/WY5lmWfMtPFYYBTd3Lzdn4FTLr+RxlIeiBNye+/os=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
Expand All @@ -347,14 +358,6 @@ github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tdewolff/argp v0.0.0-20240625173203-87b04d5d3e52 h1:bHOA+qzNf3CwchHAIA1k68QgERWiOgZMIh3qoOB3DzA=
github.com/tdewolff/argp v0.0.0-20240625173203-87b04d5d3e52/go.mod h1:e1dkYfBKpwfFhwXWrQpEU2ClFgxYOT4SrHd6fKD7nIE=
github.com/tdewolff/font v0.0.0-20240728193914-9dc6e3441d03 h1:8gZpGeUF+0bYYNDJCWXG64YH4WdSFZDFoWp1RKil1Qg=
github.com/tdewolff/font v0.0.0-20240728193914-9dc6e3441d03/go.mod h1:wiFLtNiPVz+WWkn1CekBWgSEEV5PTR7qae3wKbU0xd0=
github.com/tdewolff/font v0.0.0-20241124202446-69fd7001fa87 h1:5Z5ipvCu4GECO8woya1D6wonR0JXA8DPaj/KOthhr4w=
github.com/tdewolff/font v0.0.0-20241124202446-69fd7001fa87/go.mod h1:qCEdvMrY8e5eoJdaYEDaCV9NYKzlFCYFPUQwlGHJ9tk=
github.com/tdewolff/font v0.0.0-20241125130148-1635d719282c h1:0sLc4SkdpMt0OS7a541GHg1EzPJ/Z44u5N+KTtSNP5k=
github.com/tdewolff/font v0.0.0-20241125130148-1635d719282c/go.mod h1:qCEdvMrY8e5eoJdaYEDaCV9NYKzlFCYFPUQwlGHJ9tk=
github.com/tdewolff/font v0.0.0-20241125190050-d899fdc808fc h1:8YYYxRss857qPp/DHQw5Ej5jMdWkTFYz6kHO9tnqY3M=
github.com/tdewolff/font v0.0.0-20241125190050-d899fdc808fc/go.mod h1:qCEdvMrY8e5eoJdaYEDaCV9NYKzlFCYFPUQwlGHJ9tk=
github.com/tdewolff/font v0.0.0-20250120192450-68a3ecdf9008 h1:qjVwh/3ItmR7J2cZt8vfpwGOwG8Azw7TAk1O9oD6O+4=
github.com/tdewolff/font v0.0.0-20250120192450-68a3ecdf9008/go.mod h1:qCEdvMrY8e5eoJdaYEDaCV9NYKzlFCYFPUQwlGHJ9tk=
github.com/tdewolff/minify/v2 v2.21.1 h1:AAf5iltw6+KlUvjRNPAPrANIXl3XEJNBBzuZom5iCAM=
Expand Down Expand Up @@ -430,10 +433,6 @@ golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+o
golang.org/x/image v0.0.0-20210504121937-7319ad40d33e/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
golang.org/x/image v0.21.0 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s=
golang.org/x/image v0.21.0/go.mod h1:vUbsLavqK/W303ZroQQVKQ+Af3Yl6Uz1Ppu5J/cLz78=
golang.org/x/image v0.22.0 h1:UtK5yLUzilVrkjMAZAZ34DXGpASN8i8pj8g+O+yd10g=
golang.org/x/image v0.22.0/go.mod h1:9hPFhljd4zZ1GNSIZJ49sqbp45GKK9t6w+iXvGqZUz4=
golang.org/x/image v0.23.0 h1:HseQ7c2OpPKTPVzNjG5fwJsOTCiiwS4QdsYi5XU6H68=
golang.org/x/image v0.23.0/go.mod h1:wJJBTdLfCCf3tiHa1fNxpZmUI4mmoZvwMCPP0ddoNKY=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
Expand Down Expand Up @@ -512,8 +511,6 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
Expand Down Expand Up @@ -597,8 +594,6 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
Expand All @@ -624,10 +619,6 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
Expand Down
54 changes: 54 additions & 0 deletions path.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import (
"sort"
"strings"

"github.com/srwiley/scanx"
"github.com/tdewolff/parse/v2/strconv"
"golang.org/x/image/math/fixed"
"golang.org/x/image/vector"
)

Expand Down Expand Up @@ -2390,3 +2392,55 @@ func (p *Path) ToRasterizer(ras *vector.Rasterizer, resolution Resolution) {
ras.ClosePath()
}
}

func fixedPoint26_6(x, y float64) fixed.Point26_6 {
const Scale = float64(int(1) << 6)
return fixed.Point26_6{
fixed.Int26_6(x*Scale + 0.5),
fixed.Int26_6(y*Scale + 0.5),
}
}

func (p *Path) ToScanx(ras *scanx.Scanner, dy float64, resolution Resolution) {
dpmm := resolution.DPMM()
tolerance := PixelTolerance / dpmm // tolerance of 1/10 of a pixel
for i := 0; i < len(p.d); {
cmd := p.d[i]
switch cmd {
case MoveToCmd:
ras.Start(fixedPoint26_6(p.d[i+1]*dpmm, dy-p.d[i+2]*dpmm))
case LineToCmd:
ras.Line(fixedPoint26_6(p.d[i+1]*dpmm, dy-p.d[i+2]*dpmm))
case QuadToCmd, CubeToCmd, ArcToCmd:
// flatten
var q *Path
var start Point
if 0 < i {
start = Point{p.d[i-3], p.d[i-2]}
}
if cmd == QuadToCmd {
cp := Point{p.d[i+1], p.d[i+2]}
end := Point{p.d[i+3], p.d[i+4]}
q = flattenQuadraticBezier(start, cp, end, tolerance)
} else if cmd == CubeToCmd {
cp1 := Point{p.d[i+1], p.d[i+2]}
cp2 := Point{p.d[i+3], p.d[i+4]}
end := Point{p.d[i+5], p.d[i+6]}
q = flattenCubicBezier(start, cp1, cp2, end, tolerance)
} else {
rx, ry, phi := p.d[i+1], p.d[i+2], p.d[i+3]
large, sweep := toArcFlags(p.d[i+4])
end := Point{p.d[i+5], p.d[i+6]}
q = flattenEllipticArc(start, rx, ry, phi, large, sweep, end, tolerance)
}
for j := 4; j < len(q.d); j += 4 {
ras.Line(fixedPoint26_6(q.d[j+1]*dpmm, dy-q.d[j+2]*dpmm))
}
case CloseCmd:
ras.Line(fixedPoint26_6(p.d[i+1]*dpmm, dy-p.d[i+2]*dpmm))
default:
panic("quadratic and cubic Béziers and arcs should have been replaced")
}
i += cmdLen(cmd)
}
}
73 changes: 73 additions & 0 deletions path_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@ package canvas

import (
"fmt"
"image"
"image/png"
"math"
"os"
"strings"
"testing"

"github.com/srwiley/scanx"
"github.com/tdewolff/test"
"golang.org/x/image/vector"
"gonum.org/v1/plot"
"gonum.org/v1/plot/plotter"
"gonum.org/v1/plot/vg"
Expand Down Expand Up @@ -944,3 +948,72 @@ func TestPathLengthParametrization(t *testing.T) {
}
plotPathLengthParametrization("test/len_param_ellipse.png", 20, speed, length, theta1, theta2)
}

func BenchmarkToRasterizer(b *testing.B) {
res := DPMM(1.0)
data, err := os.ReadFile("resources/netherlands.path")
if err != nil {
panic(err)
}
p, err := ParseSVGPath(string(data))
if err != nil {
panic(err)
}
bounds := p.FastBounds()
p = p.Transform(Identity.Scale(1.0, -1.0).Translate(-bounds.X0, -bounds.Y1))

w, h := math.Ceil(float64(res)*bounds.W()), math.Ceil(float64(res)*bounds.H())
rect := image.Rect(0, 0, int(w), int(h))
img := image.NewRGBA(rect)
ras := &vector.Rasterizer{}
ras.Reset(int(w), int(h))

src := image.NewUniform(image.Black)
p.ToRasterizer(ras, res)
ras.Draw(img, rect, src, image.Point{0, 0})

f, _ := os.Create("ToRasterizer.png")
defer f.Close()
(&png.Encoder{}).Encode(f, img)

b.ResetTimer()
for i := 0; i < b.N; i++ {
ras.Reset(int(w), int(h))
p.ToRasterizer(ras, res)
ras.Draw(img, rect, src, image.Point{0, 0})
}
}

func BenchmarkToScanx(b *testing.B) {
res := DPMM(1.0)
data, err := os.ReadFile("resources/netherlands.path")
if err != nil {
panic(err)
}
p, err := ParseSVGPath(string(data))
if err != nil {
panic(err)
}
bounds := p.FastBounds()
p = p.Transform(Identity.Scale(1.0, -1.0).Translate(-bounds.X0, -bounds.Y1))

w, h := math.Ceil(float64(res)*bounds.W()), math.Ceil(float64(res)*bounds.H())
img := image.NewRGBA(image.Rect(0, 0, int(w), int(h)))
spanner := scanx.NewImgSpanner(img)
scanner := scanx.NewScanner(spanner, int(w), int(h))

scanner.SetColor(image.Black)
p.ToScanx(scanner, h*float64(res), res)
scanner.Draw()

f, _ := os.Create("ToScanx.png")
defer f.Close()
(&png.Encoder{}).Encode(f, img)

b.ResetTimer()
for i := 0; i < b.N; i++ {
scanner.Clear()
p.ToScanx(scanner, h*float64(res), res)
scanner.Draw()
}
}
Loading

0 comments on commit 24ed619

Please # to comment.