Hey everyone,

I looked into using just the rasterizer package from the 
"golang.org/x/image/vector" package and tested it vs the rasterizer derived 
from the freetype package. I will call these the GV and FT rasterizers. One 
thing with the GV is that it only does non-zero-winding-rule, while the FT 
does that and even-odd-winding-rule. For stroking and most things you need 
the non-zero-winding, but just an FYI, the SVG spec asks for both.

What I did like about the GV is the flattener for Bezier curves vs the FT 
version, which is not recursive and hence cleaner, and more stateless to 
implement. I also like GV interface to the last step which is rasterizing a 
representation of flat lines with some version of  anti-aliasing. GV uses 
the Draw method with a source and a target image, and the path works as an 
alpha mask. FT on the other hand uses a Painter, which seems a little more 
mysterious to me.

So, what I did was abstract the last anti-aliasing step into an interface 
called Scanner. The ScannerGV struct satisfies Scanner by wrapping the Draw 
func from the vector package, and is included in  rasterx. ScannerFT, which 
is derived from the anti-aliasing code in the freetype package, is in a 
different repository, "github.com/srwiley/scanFT". In order to use 
ScannerFT, you need to include that into your project separately.

The Bezier curve flattener now in the rasterx/fill.go file is a modified 
version of the vector package flattener (more on that below). So, at this 
point the only part of rasterx that depends on any freetype code is 
isolated in the scanFT repository. Which brings me to a bit of a pet peeve 
of mine. Flattening Bezier curves had nothing to do with rasterizing and 
anti-aliasing, but they always seem to be thrown together in the same file. 
It is instructive to have a logical separation, which is one reason why I 
like abstracting the Scanner from everything else.

As far as performance, it was not clear cut which was better. GV seems to 
have the edge with more complex and small resolution images, and FT has the 
edge with higher resolution/lower complexity images.

Below are the results of some benchmarks performed on a sample shape (the 
letter Q ). The first test is the time it takes to scan the image after all 
the curves have been flattened. The second test is the time it takes to 
flatten, and scan a simple filled image. The last test is the time it takes 
to flatten a stroked and dashed outline of the shape and scan it. Results 
for three different image sizes are shown.

128x128 Image
Test                        Rep       Time
BenchmarkScanGV-16          5000      287180 ns/op
BenchmarkFillGV-16          5000      339831 ns/op
BenchmarkDashGV-16          2000      968265 ns/op

BenchmarkScanFT-16         20000       88118 ns/op
BenchmarkFillFT-16          5000      214370 ns/op
BenchmarkDashFT-16          1000     2063797 ns/op

256x256 Image
Test                        Rep       Time
BenchmarkScanGV-16          2000     1188452 ns/op
BenchmarkFillGV-16          1000     1277268 ns/op
BenchmarkDashGV-16          500      2238169 ns/op

BenchmarkScanFT-16          5000      290685 ns/op
BenchmarkFillFT-16          3000      446329 ns/op
BenchmarkDashFT-16           500     2923512 ns/op

512x512 Image
Test                        Rep       Time
BenchmarkScanGV-16           500     3341038 ns/op
BenchmarkFillGV-16           500     4032213 ns/op
BenchmarkDashGV-16           200     6003355 ns/op

BenchmarkScanFT-16          5000      292884 ns/op
BenchmarkFillFT-16          3000      449582 ns/op
BenchmarkDashFT-16           500     2800493 ns/op

Here are some additional benchmarks using oksvg with either 8 large icons 
(landscape) and a set of 44 simpler small icons (sports):

oksvg with FT scanner

BenchmarkLandscapeIcons-16               1    2,100,513,290 ns/op
BenchmarkSportsIcons-16                200       6,017,063 ns/op

BenchmarkLandscapeIcons-16               1    2,167,196,383 ns/op
BenchmarkSportsIcons-16                200       6,020,537 ns/op

oksvg with GV scanner

BenchmarkLandscapeIcons-16               1    2,097,975,097 ns/op
BenchmarkSportsIcons-16                100      18,507,261 ns/op

BenchmarkLandscapeIcons-16               1    2,002,543,751 ns/op
BenchmarkSportsIcons-16                100      13,407,936 ns/op

So, you can either use the GV scanner or the FT scanner, depending on how 
big vs how complex your icons are, if you need even-odd winding rule, and 
whether or not you care about freetype vs go-friendly licenses. Right now 
the rasterx and oksvg package have no license, but I will put in place a 
go-friendly version soon.

Finally, a little bit more on the Bezier curve flattener from the vector 
package. I had to modify that for my purposes, but I also did a little 
optimization. Instead of doing a series of linear interpolations (Lerps), I 
used the expanded form (see https://pomax.github.io/bezierinfo/#matrix). 
This usually gives a 10-20 percent speed up for cubic Bezier curves and 
maybe single digit improvement for quadratics. I also want to implement a 
version that uses fixed rather than floating point numbers.

One more set of benchmark results:

BenchmarkBezierQuadLerp-16        10000000           135 ns/op
BenchmarkBezierQuad-16            10000000           130 ns/op
BenchmarkBezierCubeLerp-16        10000000           162 ns/op
BenchmarkBezierCube-16            10000000           138 ns/op


Cheers!



-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to