From cddfe43315662a18e9282df928d39835c3fc90bf Mon Sep 17 00:00:00 2001
From: Ryan Oldenburg <guzba8@gmail.com>
Date: Fri, 4 Dec 2020 14:09:08 -0600
Subject: [PATCH] scanLineHits a bunch faster

---
 src/pixie/paths.nim | 42 ++++++++++++++++++++++++------------------
 tests/test_svg.nim  |  5 ++++-
 2 files changed, 28 insertions(+), 19 deletions(-)

diff --git a/src/pixie/paths.nim b/src/pixie/paths.nim
index f9d3b0a..cccc626 100644
--- a/src/pixie/paths.nim
+++ b/src/pixie/paths.nim
@@ -599,32 +599,38 @@ proc fillPolygons*(
   proc scanLineHits(
     polys: seq[seq[Vec2]],
     hits: var seq[(float32, bool)],
+    size: Vec2,
     y: int,
     shiftY: float32
-  ) =
+  ) {.inline.} =
     hits.setLen(0)
-    var yLine = (float32(y) + ep) + shiftY
-    var scan = Segment(at: vec2(-10000, yLine), to: vec2(100000, yLine))
+
+    let
+      yLine = (float32(y) + ep) + shiftY
+      scan = Segment(at: vec2(-10000, yLine), to: vec2(100000, yLine))
 
     for poly in polys:
-      for (at, to) in poly.zipwise:
-        let line = Segment(at: at, to: to)
+      for e in poly.zipwise:
+        let line = cast[Segment](e)
         var at: Vec2
         if line.intersects(scan, at):
-          let winding = line.at.y > line.to.y
-          let x = at.x.clamp(0, size.x)
+          let
+            winding = line.at.y > line.to.y
+            x = at.x.clamp(0, size.x)
           hits.add((x, winding))
 
     hits.sort(proc(a, b: (float32, bool)): int = cmp(a[0], b[0]))
 
-  var hits: seq[(float32, bool)]
-
-  var alphas = newSeq[float32](result.width)
+  var
+    hits = newSeq[(float32, bool)]()
+    alphas = newSeq[float32](result.width)
   for y in 0 ..< result.height:
-    for x in 0 ..< result.width:
-      alphas[x] = 0
+    # Reset alphas for this row.
+    zeroMem(alphas[0].addr, alphas.len * 4)
+
+    # Do scanlines for this row.
     for m in 0 ..< quality:
-      polys.scanLineHits(hits, y, float32(m)/float32(quality))
+      polys.scanLineHits(hits, size, y, float32(m) / float32(quality))
       if hits.len == 0:
         continue
       var
@@ -633,12 +639,11 @@ proc fillPolygons*(
       for x in 0 ..< result.width:
         var penEdge = penFill
         while true:
-          if curHit >= hits.len:
+          if curHit >= hits.len or x != hits[curHit][0].int:
             break
-          if x != hits[curHit][0].int:
-            break
-          let cover = hits[curHit][0] - x.float32
-          let winding = hits[curHit][1]
+          let
+            cover = hits[curHit][0] - x.float32
+            winding = hits[curHit][1]
           if winding == false:
             penFill += 1.0
             penEdge += 1.0 - cover
@@ -647,6 +652,7 @@ proc fillPolygons*(
             penEdge -= 1.0 - cover
           inc curHit
         alphas[x] += penEdge
+
     for x in 0 ..< result.width:
       let a = clamp(abs(alphas[x]) / float32(quality), 0.0, 1.0)
       var colorWithAlpha = color
diff --git a/tests/test_svg.nim b/tests/test_svg.nim
index e9a63ed..d9b2361 100644
--- a/tests/test_svg.nim
+++ b/tests/test_svg.nim
@@ -3,4 +3,7 @@ import pixie/fileformats/svg, pixie
 let
   original = readFile("tests/images/svg/Ghostscript_Tiger.svg")
   image = decodeSvg(original)
-image.writeFile("tests/images/svg/Ghostscript_Tiger.png")
+  gold = readImage("tests/images/svg/Ghostscript_Tiger.png")
+
+doAssert image.data == gold.data
+# image.writeFile("tests/images/svg/Ghostscript_Tiger.png")