diff --git a/src/pixie/paths.nim b/src/pixie/paths.nim
index c79ab33..e132588 100644
--- a/src/pixie/paths.nim
+++ b/src/pixie/paths.nim
@@ -1110,6 +1110,35 @@ proc shouldFill(windingRule: WindingRule, count: int): bool {.inline.} =
   of wrEvenOdd:
     count mod 2 != 0
 
+iterator walk(
+  hits: seq[(float32, int16)],
+  numHits: int,
+  windingRule: WindingRule,
+  y: int,
+  size: Vec2
+): (float32, float32, int32) =
+  var
+    prevAt: float32
+    count: int32
+  for i in 0 ..< numHits:
+    let (at, winding) = hits[i]
+    if windingRule == wrNonZero and
+      (count != 0) == (count + winding != 0) and
+      i < numHits - 1:
+      # Shortcut: if nonzero rule, we only care about when the count changes
+      # between zero and nonzero (or the last hit)
+      count += winding
+      continue
+    if at > 0:
+      if shouldFill(windingRule, count):
+        yield (prevAt, at, count)
+      prevAt = at
+    count += winding
+
+  when defined(pixieLeakCheck):
+    if prevAt != size.x and count != 0:
+      echo "Leak detected: ", count, " @ (", prevAt, ", ", y, ")"
+
 proc computeCoverages(
   coverages: var seq[uint8],
   hits: var seq[(float32, int16)],
@@ -1155,61 +1184,40 @@ proc computeCoverages(
     else:
       insertionSort(hits, numHits - 1)
 
-    var
-      prevAt: float32
-      count: int
-    for i in 0 ..< numHits:
-      let (at, winding) = hits[i]
-      if windingRule == wrNonZero and
-        (count != 0) == (count + winding != 0) and
-        i < numHits - 1:
-        # Shortcut: if nonzero rule, we only care about when the count changes
-        # between zero and nonzero (or the last hit)
-        count += winding
-        continue
-      if at > 0:
-        if shouldFill(windingRule, count):
-          var fillStart = prevAt.int
-
-          let
-            pixelCrossed = at.int - prevAt.int > 0
-            leftCover =
-              if pixelCrossed:
-                trunc(prevAt) + 1 - prevAt
-              else:
-                at - prevAt
-          if leftCover != 0:
-            inc fillStart
-            coverages[prevAt.int] += (leftCover * sampleCoverage.float32).uint8
+    for (prevAt, at, count) in hits.walk(numHits, windingRule, y, size):
+      var fillStart = prevAt.int
 
+      let
+        pixelCrossed = at.int - prevAt.int > 0
+        leftCover =
           if pixelCrossed:
-            let rightCover = at - trunc(at)
-            if rightCover > 0:
-              coverages[at.int] += (rightCover * sampleCoverage.float32).uint8
+            trunc(prevAt) + 1 - prevAt
+          else:
+            at - prevAt
+      if leftCover != 0:
+        inc fillStart
+        coverages[prevAt.int] += (leftCover * sampleCoverage.float32).uint8
 
-          let fillLen = at.int - fillStart
-          if fillLen > 0:
-            var i = fillStart
-            if aa:
-              when defined(amd64) and not defined(pixieNoSimd):
-                let vSampleCoverage = mm_set1_epi8(cast[int8](sampleCoverage))
-                for j in countup(i, fillStart + fillLen - 16, 16):
-                  var coverage = mm_loadu_si128(coverages[j].addr)
-                  coverage = mm_add_epi8(coverage, vSampleCoverage)
-                  mm_storeu_si128(coverages[j].addr, coverage)
-                  i += 16
-              for j in i ..< fillStart + fillLen:
-                coverages[j] += sampleCoverage
-            else:
-              nimSetMem(coverages[fillStart].addr, sampleCoverage.cint, fillLen)
+      if pixelCrossed:
+        let rightCover = at - trunc(at)
+        if rightCover > 0:
+          coverages[at.int] += (rightCover * sampleCoverage.float32).uint8
 
-        prevAt = at
-
-      count += winding
-
-    when defined(pixieLeakCheck):
-      if prevAt != size.x and count != 0:
-        echo "Leak detected: ", count, " @ (", prevAt, ", ", y, ")"
+      let fillLen = at.int - fillStart
+      if fillLen > 0:
+        var i = fillStart
+        if aa:
+          when defined(amd64) and not defined(pixieNoSimd):
+            let vSampleCoverage = mm_set1_epi8(cast[int8](sampleCoverage))
+            for j in countup(i, fillStart + fillLen - 16, 16):
+              var coverage = mm_loadu_si128(coverages[j].addr)
+              coverage = mm_add_epi8(coverage, vSampleCoverage)
+              mm_storeu_si128(coverages[j].addr, coverage)
+              i += 16
+          for j in i ..< fillStart + fillLen:
+            coverages[j] += sampleCoverage
+        else:
+          nimSetMem(coverages[fillStart].addr, sampleCoverage.cint, fillLen)
 
 proc fillShapes(
   image: Image,
@@ -1397,9 +1405,9 @@ proc strokeShapes(
   if strokeWidth <= 0:
     return
 
-  let miterAngleLimit = miterLimitToAngle(miterLimit)
-
-  let halfStroke = strokeWidth / 2
+  let
+    halfStroke = strokeWidth / 2
+    miterAngleLimit = miterLimitToAngle(miterLimit)
 
   proc makeCircle(at: Vec2): seq[Vec2] =
     var path: Path