walkInteger iterator

This commit is contained in:
Ryan Oldenburg 2022-06-16 23:32:19 -05:00
parent 2f2fe303ee
commit 52bd7bef57

View file

@ -1158,7 +1158,7 @@ proc maxEntryCount(partitioning: var Partitioning): int =
proc fixed32(f: float32): Fixed32 {.inline.} = proc fixed32(f: float32): Fixed32 {.inline.} =
Fixed32(f * 256) Fixed32(f * 256)
proc integer(p: Fixed32): int {.inline.} = proc integer(p: Fixed32): int32 {.inline.} =
p div 256 p div 256
proc trunc(p: Fixed32): Fixed32 {.inline.} = proc trunc(p: Fixed32): Fixed32 {.inline.} =
@ -1223,6 +1223,20 @@ iterator walk(
if prevAt != width.float32.fixed32 and count != 0: if prevAt != width.float32.fixed32 and count != 0:
echo "Leak detected: ", count, " @ (", prevAt, ", ", y, ")" echo "Leak detected: ", count, " @ (", prevAt, ", ", y, ")"
iterator walkInteger(
hits: seq[(int32, int16)],
numHits: int,
windingRule: WindingRule,
y, width: int
): (int32, int32) =
for (prevAt, at, count) in hits.walk(numHits, windingRule, y, width):
let
fillStart = prevAt.integer
fillLen = at.integer - fillStart
if fillLen <= 0:
continue
yield (fillStart, fillLen)
proc computeCoverage( proc computeCoverage(
coverages: ptr UncheckedArray[uint8], coverages: ptr UncheckedArray[uint8],
hits: var seq[(Fixed32, int16)], hits: var seq[(Fixed32, int16)],
@ -1481,22 +1495,6 @@ proc fillCoverage(
mask.clearUnsafe(0, y, startX, y) mask.clearUnsafe(0, y, startX, y)
mask.clearUnsafe(startX + coverages.len, y, mask.width, y) mask.clearUnsafe(startX + coverages.len, y, mask.width, y)
template walkHits(
hits: seq[(int32, int16)],
numHits: int,
windingRule: WindingRule,
y, width: int,
inner: untyped
) =
for (prevAt, at, count) in hits.walk(numHits, windingRule, y, width):
let
fillStart {.inject.} = prevAt.integer
fillLen {.inject.} = at.integer - fillStart
if fillLen <= 0:
continue
inner
proc fillHits( proc fillHits(
image: Image, image: Image,
rgbx: ColorRGBX, rgbx: ColorRGBX,
@ -1506,36 +1504,36 @@ proc fillHits(
windingRule: WindingRule, windingRule: WindingRule,
blendMode: BlendMode blendMode: BlendMode
) = ) =
template simdBlob(image: Image, x: var int, blendProc: untyped) = template simdBlob(image: Image, x: var int, len: int32, blendProc: untyped) =
when allowSimd: when allowSimd:
when defined(amd64): when defined(amd64):
let colorVec = mm_set1_epi32(cast[int32](rgbx)) let colorVec = mm_set1_epi32(cast[int32](rgbx))
for _ in 0 ..< fillLen div 4: for _ in 0 ..< len div 4:
let backdrop = mm_loadu_si128(image.unsafe[x, y].addr) let backdrop = mm_loadu_si128(image.unsafe[x, y].addr)
mm_storeu_si128(image.unsafe[x, y].addr, blendProc(backdrop, colorVec)) mm_storeu_si128(image.unsafe[x, y].addr, blendProc(backdrop, colorVec))
x += 4 x += 4
case blendMode: case blendMode:
of OverwriteBlend: of OverwriteBlend:
walkHits hits, numHits, windingRule, y, image.width: for (start, len) in hits.walkInteger(numHits, windingRule, y, image.width):
fillUnsafe(image.data, rgbx, image.dataIndex(fillStart, y), fillLen) fillUnsafe(image.data, rgbx, image.dataIndex(start, y), len)
of NormalBlend: of NormalBlend:
walkHits hits, numHits, windingRule, y, image.width: for (start, len) in hits.walkInteger(numHits, windingRule, y, image.width):
if rgbx.a == 255: if rgbx.a == 255:
fillUnsafe(image.data, rgbx, image.dataIndex(fillStart, y), fillLen) fillUnsafe(image.data, rgbx, image.dataIndex(start, y), len)
else: else:
var x = fillStart var x = start
simdBlob(image, x, blendNormalSimd) simdBlob(image, x, len, blendNormalSimd)
for x in x ..< fillStart + fillLen: for x in x ..< start + len:
let backdrop = image.unsafe[x, y] let backdrop = image.unsafe[x, y]
image.unsafe[x, y] = blendNormal(backdrop, rgbx) image.unsafe[x, y] = blendNormal(backdrop, rgbx)
of MaskBlend: of MaskBlend:
var filledTo = startX var filledTo = startX
walkHits hits, numHits, windingRule, y, image.width: for (start, len) in hits.walkInteger(numHits, windingRule, y, image.width):
block: # Clear any gap between this fill and the previous fill block: # Clear any gap between this fill and the previous fill
let gapBetween = fillStart - filledTo let gapBetween = start - filledTo
if gapBetween > 0: if gapBetween > 0:
fillUnsafe( fillUnsafe(
image.data, image.data,
@ -1543,12 +1541,12 @@ proc fillHits(
image.dataIndex(filledTo, y), image.dataIndex(filledTo, y),
gapBetween gapBetween
) )
filledTo = fillStart + fillLen filledTo = start + len
block: # Handle this fill block: # Handle this fill
if rgbx.a != 255: if rgbx.a != 255:
var x = fillStart var x = start
simdBlob(image, x, blendMaskSimd) simdBlob(image, x, len, blendMaskSimd)
for x in x ..< fillStart + fillLen: for x in x ..< start + len:
let backdrop = image.unsafe[x, y] let backdrop = image.unsafe[x, y]
image.unsafe[x, y] = blendMask(backdrop, rgbx) image.unsafe[x, y] = blendMask(backdrop, rgbx)
@ -1557,8 +1555,8 @@ proc fillHits(
else: else:
let blender = blendMode.blender() let blender = blendMode.blender()
walkHits hits, numHits, windingRule, y, image.width: for (start, len) in hits.walkInteger(numHits, windingRule, y, image.width):
for x in fillStart ..< fillStart + fillLen: for x in start ..< start + len:
let backdrop = image.unsafe[x, y] let backdrop = image.unsafe[x, y]
image.unsafe[x, y] = blender(backdrop, rgbx) image.unsafe[x, y] = blender(backdrop, rgbx)
@ -1570,44 +1568,44 @@ proc fillHits(
windingRule: WindingRule, windingRule: WindingRule,
blendMode: BlendMode blendMode: BlendMode
) = ) =
template simdBlob(mask: Mask, x: var int, blendProc: untyped) = template simdBlob(mask: Mask, x: var int, len: int32, blendProc: untyped) =
when allowSimd: when allowSimd:
when defined(amd64): when defined(amd64):
let vec255 = mm_set1_epi8(255) let vec255 = mm_set1_epi8(255)
for _ in 0 ..< fillLen div 16: for _ in 0 ..< len div 16:
let backdrop = mm_loadu_si128(mask.unsafe[x, y].addr) let backdrop = mm_loadu_si128(mask.unsafe[x, y].addr)
mm_storeu_si128(mask.unsafe[x, y].addr, blendProc(backdrop, vec255)) mm_storeu_si128(mask.unsafe[x, y].addr, blendProc(backdrop, vec255))
x += 16 x += 16
case blendMode: case blendMode:
of NormalBlend, OverwriteBlend: of NormalBlend, OverwriteBlend:
walkHits hits, numHits, windingRule, y, mask.width: for (start, len) in hits.walkInteger(numHits, windingRule, y, mask.width):
fillUnsafe(mask.data, 255, mask.dataIndex(fillStart, y), fillLen) fillUnsafe(mask.data, 255, mask.dataIndex(start, y), len)
of MaskBlend: of MaskBlend:
var filledTo = startX var filledTo = startX
walkHits hits, numHits, windingRule,y, mask.width: for (start, len) in hits.walkInteger(numHits, windingRule, y, mask.width):
let gapBetween = fillStart - filledTo let gapBetween = start - filledTo
if gapBetween > 0: if gapBetween > 0:
fillUnsafe(mask.data, 0, mask.dataIndex(filledTo, y), gapBetween) fillUnsafe(mask.data, 0, mask.dataIndex(filledTo, y), gapBetween)
filledTo = fillStart + fillLen filledTo = start + len
mask.clearUnsafe(0, y, startX, y) mask.clearUnsafe(0, y, startX, y)
mask.clearUnsafe(filledTo, y, mask.width, y) mask.clearUnsafe(filledTo, y, mask.width, y)
of SubtractMaskBlend: of SubtractMaskBlend:
walkHits hits, numHits, windingRule, y, mask.width: for (start, len) in hits.walkInteger(numHits, windingRule, y, mask.width):
var x = fillStart var x = start
simdBlob(mask, x, maskBlendSubtractSimd) simdBlob(mask, x, len, maskBlendSubtractSimd)
for x in x ..< fillStart + fillLen: for x in x ..< start + len:
let backdrop = mask.unsafe[x, y] let backdrop = mask.unsafe[x, y]
mask.unsafe[x, y] = maskBlendSubtract(backdrop, 255) mask.unsafe[x, y] = maskBlendSubtract(backdrop, 255)
of ExcludeMaskBlend: of ExcludeMaskBlend:
walkHits hits, numHits, windingRule, y, mask.width: for (start, len) in hits.walkInteger(numHits, windingRule, y, mask.width):
var x = fillStart var x = start
simdBlob(mask, x, maskBlendExcludeSimd) simdBlob(mask, x, len, maskBlendExcludeSimd)
for x in x ..< fillStart + fillLen: for x in x ..< start + len:
let backdrop = mask.unsafe[x, y] let backdrop = mask.unsafe[x, y]
mask.unsafe[x, y] = maskBlendExclude(backdrop, 255) mask.unsafe[x, y] = maskBlendExclude(backdrop, 255)