diff --git a/src/pixie/masks.nim b/src/pixie/masks.nim index 763718c..9887e6e 100644 --- a/src/pixie/masks.nim +++ b/src/pixie/masks.nim @@ -178,25 +178,35 @@ proc getValueSmooth*(mask: Mask, x, y: float32): uint8 = proc spread*(mask: Mask, spread: float32) = ## Grows the mask by spread. + let spread = round(spread).int if spread == 0: return if spread < 0: raise newException(PixieError, "Cannot apply negative spread") - let - copy = mask.copy() - spread = round(spread).int + # Spread in the X direction. Store with dimensions swapped for reading later. + let spreadX = newMask(mask.height, mask.width) for y in 0 ..< mask.height: for x in 0 ..< mask.width: var maxValue: uint8 - block blurBox: - for by in max(y - spread, 0) .. min(y + spread, mask.height - 1): - for bx in max(x - spread, 0) .. min(x + spread, mask.width - 1): - let value = copy.getValueUnsafe(bx, by) - if value > maxValue: - maxValue = value - if maxValue == 255: - break blurBox + for xx in max(x - spread, 0) .. min(x + spread, mask.width - 1): + let value = mask.getValueUnsafe(xx, y) + if value > maxValue: + maxValue = value + if maxValue == 255: + break + spreadX.setValueUnsafe(y, x, maxValue) + + # Spread in the Y direction and modify mask. + for y in 0 ..< mask.height: + for x in 0 ..< mask.width: + var maxValue: uint8 + for yy in max(y - spread, 0) .. min(y + spread, mask.height - 1): + let value = spreadX.getValueUnsafe(yy, x) + if value > maxValue: + maxValue = value + if maxValue == 255: + break mask.setValueUnsafe(x, y, maxValue) proc ceil*(mask: Mask) = diff --git a/src/pixie/paths.nim b/src/pixie/paths.nim index 124dd5b..e3f8bd3 100644 --- a/src/pixie/paths.nim +++ b/src/pixie/paths.nim @@ -1137,12 +1137,10 @@ iterator walk( # between zero and nonzero (or the last hit) count += winding continue - if at <= 0: - count += winding - continue - if shouldFill(windingRule, count): - yield (prevAt, at, count) - prevAt = at + if at > 0: + if shouldFill(windingRule, count): + yield (prevAt, at, count) + prevAt = at count += winding when defined(pixieLeakCheck): diff --git a/tests/benchmark_masks.nim b/tests/benchmark_masks.nim index f92e8d9..5c0a550 100644 --- a/tests/benchmark_masks.nim +++ b/tests/benchmark_masks.nim @@ -33,5 +33,31 @@ timeIt "ceil": reset() -timeIt "spread": - mask.spread(10) +block spread_1: + var p: Path + p.rect(500, 500, 500, 500) + + timeIt "spread_1": + mask.fill(0) + mask.fillPath(p) + mask.spread(10) + +block spread_2: + var p: Path + p.rect(500, 500, 1000, 1000) + + timeIt "spread_2": + mask.fill(0) + mask.fillPath(p) + mask.spread(10) + +block spread_3: + timeIt "spread_3": + mask.fill(255) + mask.spread(10) + +block spread_4: + timeIt "spread_4": + mask.fill(0) + mask.setValueUnsafe(1000, 1000, 255) + mask.spread(10)