use mask coverage
This commit is contained in:
parent
aa6775240f
commit
4bcfae7eb5
2 changed files with 53 additions and 18 deletions
|
@ -39,7 +39,7 @@ block:
|
||||||
for shape in shapes:
|
for shape in shapes:
|
||||||
for v in shape:
|
for v in shape:
|
||||||
p.lineTo(v)
|
p.lineTo(v)
|
||||||
a.fillPath(p, rgba(0, 0, 255, 255))
|
a.fillPath(p, rgbx(0, 0, 255, 255))
|
||||||
|
|
||||||
# a.writeFile("pixie1.png")
|
# a.writeFile("pixie1.png")
|
||||||
|
|
||||||
|
@ -79,14 +79,14 @@ block:
|
||||||
let a = newImage(1920, 1080)
|
let a = newImage(1920, 1080)
|
||||||
|
|
||||||
timeIt "pixie2":
|
timeIt "pixie2":
|
||||||
a.fill(rgba(255, 255, 255, 255))
|
a.fill(rgbx(255, 255, 255, 255))
|
||||||
|
|
||||||
let p = newPath()
|
let p = newPath()
|
||||||
p.moveTo(shapes[0][0])
|
p.moveTo(shapes[0][0])
|
||||||
for shape in shapes:
|
for shape in shapes:
|
||||||
for v in shape:
|
for v in shape:
|
||||||
p.lineTo(v)
|
p.lineTo(v)
|
||||||
a.fillPath(p, rgba(0, 0, 255, 255))
|
a.fillPath(p, rgbx(0, 0, 255, 255))
|
||||||
|
|
||||||
# a.writeFile("pixie2.png")
|
# a.writeFile("pixie2.png")
|
||||||
|
|
||||||
|
@ -127,14 +127,14 @@ block:
|
||||||
let a = newImage(1000, 1000)
|
let a = newImage(1000, 1000)
|
||||||
|
|
||||||
timeIt "pixie3":
|
timeIt "pixie3":
|
||||||
a.fill(rgba(255, 255, 255, 255))
|
a.fill(rgbx(255, 255, 255, 255))
|
||||||
|
|
||||||
let p = newPath()
|
let p = newPath()
|
||||||
p.moveTo(shapes[0][0])
|
p.moveTo(shapes[0][0])
|
||||||
for shape in shapes:
|
for shape in shapes:
|
||||||
for v in shape:
|
for v in shape:
|
||||||
p.lineTo(v)
|
p.lineTo(v)
|
||||||
a.fillPath(p, rgba(255, 0, 0, 255))
|
a.fillPath(p, rgbx(255, 0, 0, 255))
|
||||||
|
|
||||||
# a.writeFile("pixie3.png")
|
# a.writeFile("pixie3.png")
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ block:
|
||||||
for shape in shapes:
|
for shape in shapes:
|
||||||
for v in shape:
|
for v in shape:
|
||||||
p.lineTo(v)
|
p.lineTo(v)
|
||||||
a.fillPath(p, rgba(255, 0, 0, 127))
|
a.fillPath(p, rgbx(127, 0, 0, 127))
|
||||||
|
|
||||||
# a.writeFile("pixie4.png")
|
# a.writeFile("pixie4.png")
|
||||||
|
|
||||||
|
@ -202,6 +202,6 @@ block:
|
||||||
|
|
||||||
var tmp: Image
|
var tmp: Image
|
||||||
timeIt "pixie fillImage":
|
timeIt "pixie fillImage":
|
||||||
tmp = path.fillImage(1000, 1000, rgba(255, 0, 0, 127))
|
tmp = path.fillImage(1000, 1000, rgbx(127, 0, 0, 127))
|
||||||
|
|
||||||
# tmp.writeFile("tmp.png")
|
# tmp.writeFile("tmp.png")
|
||||||
|
|
|
@ -1221,7 +1221,7 @@ iterator walk(
|
||||||
echo "Leak detected: ", count, " @ (", prevAt, ", ", y, ")"
|
echo "Leak detected: ", count, " @ (", prevAt, ", ", y, ")"
|
||||||
|
|
||||||
proc computeCoverage(
|
proc computeCoverage(
|
||||||
coverages: var seq[uint8],
|
coverages: ptr UncheckedArray[uint8],
|
||||||
hits: var seq[(float32, int16)],
|
hits: var seq[(float32, int16)],
|
||||||
numHits: var int,
|
numHits: var int,
|
||||||
aa: var bool,
|
aa: var bool,
|
||||||
|
@ -1236,9 +1236,6 @@ proc computeCoverage(
|
||||||
|
|
||||||
aa = partitioning.partitions[partitionIndex].requiresAntiAliasing
|
aa = partitioning.partitions[partitionIndex].requiresAntiAliasing
|
||||||
|
|
||||||
if aa: # Coverage is only used for anti-aliasing
|
|
||||||
zeroMem(coverages[0].addr, coverages.len)
|
|
||||||
|
|
||||||
let
|
let
|
||||||
quality = if aa: 5 else: 1 # Must divide 255 cleanly (1, 3, 5, 15, 17, 51, 85)
|
quality = if aa: 5 else: 1 # Must divide 255 cleanly (1, 3, 5, 15, 17, 51, 85)
|
||||||
sampleCoverage = (255 div quality).uint8
|
sampleCoverage = (255 div quality).uint8
|
||||||
|
@ -1606,7 +1603,7 @@ proc fillShapes(
|
||||||
|
|
||||||
for y in startY ..< pathHeight:
|
for y in startY ..< pathHeight:
|
||||||
computeCoverage(
|
computeCoverage(
|
||||||
coverages,
|
cast[ptr UncheckedArray[uint8]](coverages[0].addr),
|
||||||
hits,
|
hits,
|
||||||
numHits,
|
numHits,
|
||||||
aa,
|
aa,
|
||||||
|
@ -1618,6 +1615,7 @@ proc fillShapes(
|
||||||
)
|
)
|
||||||
if aa:
|
if aa:
|
||||||
mask.fillCoverage(startX, y, coverages, blendMode)
|
mask.fillCoverage(startX, y, coverages, blendMode)
|
||||||
|
zeroMem(coverages[0].addr, coverages.len)
|
||||||
else:
|
else:
|
||||||
mask.fillHits(startX, y, hits, numHits, windingRule, blendMode)
|
mask.fillHits(startX, y, hits, numHits, windingRule, blendMode)
|
||||||
|
|
||||||
|
@ -2421,7 +2419,7 @@ else:
|
||||||
|
|
||||||
for y in startY ..< pathHeight:
|
for y in startY ..< pathHeight:
|
||||||
computeCoverage(
|
computeCoverage(
|
||||||
coverages,
|
cast[ptr UncheckedArray[uint8]](coverages[0].addr),
|
||||||
hits,
|
hits,
|
||||||
numHits,
|
numHits,
|
||||||
aa,
|
aa,
|
||||||
|
@ -2439,6 +2437,7 @@ else:
|
||||||
coverages,
|
coverages,
|
||||||
blendMode
|
blendMode
|
||||||
)
|
)
|
||||||
|
zeroMem(coverages[0].addr, coverages.len)
|
||||||
else:
|
else:
|
||||||
image.fillHits(
|
image.fillHits(
|
||||||
rgbx,
|
rgbx,
|
||||||
|
@ -2454,15 +2453,51 @@ else:
|
||||||
image.clearUnsafe(0, 0, 0, startY)
|
image.clearUnsafe(0, 0, 0, startY)
|
||||||
image.clearUnsafe(0, pathHeight, 0, image.height)
|
image.clearUnsafe(0, pathHeight, 0, image.height)
|
||||||
|
|
||||||
proc fillMask*(path: SomePath, width, height: int): Mask =
|
proc fillMask*(
|
||||||
result = newMask(width, height)
|
path: SomePath, width, height: int, windingRule = wrNonZero
|
||||||
result.fillPath(path, blendMode = bmOverwrite)
|
): Mask =
|
||||||
|
let shapes = parseSomePath(path, true, 1)
|
||||||
|
|
||||||
proc fillImage*(path: SomePath, width, height: int, color: SomeColor): Image =
|
result = newMask(width, height)
|
||||||
|
|
||||||
|
let
|
||||||
|
segments = shapes.shapesToSegments()
|
||||||
|
bounds = computeBounds(segments).snapToPixels()
|
||||||
|
startY = max(0, bounds.y.int)
|
||||||
|
pathHeight = min(height, (bounds.y + bounds.h).int)
|
||||||
|
partitioning = partitionSegments(segments, startY, pathHeight)
|
||||||
|
width = width.float32
|
||||||
|
|
||||||
|
var
|
||||||
|
hits = newSeq[(float32, int16)](partitioning.maxEntryCount)
|
||||||
|
numHits: int
|
||||||
|
aa: bool
|
||||||
|
for y in startY ..< pathHeight:
|
||||||
|
computeCoverage(
|
||||||
|
cast[ptr UncheckedArray[uint8]](result.data[result.dataIndex(0, y)].addr),
|
||||||
|
hits,
|
||||||
|
numHits,
|
||||||
|
aa,
|
||||||
|
width,
|
||||||
|
y,
|
||||||
|
0,
|
||||||
|
partitioning,
|
||||||
|
windingRule
|
||||||
|
)
|
||||||
|
if not aa:
|
||||||
|
for (prevAt, at, count) in hits.walk(numHits, windingRule, y, width):
|
||||||
|
let
|
||||||
|
startIndex = result.dataIndex(prevAt.int, y)
|
||||||
|
len = at.int - prevAt.int
|
||||||
|
fillUnsafe(result.data, 255, startIndex, len)
|
||||||
|
|
||||||
|
proc fillImage*(
|
||||||
|
path: SomePath, width, height: int, color: SomeColor, windingRule = wrNonZero
|
||||||
|
): Image =
|
||||||
result = newImage(width, height)
|
result = newImage(width, height)
|
||||||
|
|
||||||
let
|
let
|
||||||
mask = path.fillMask(width, height)
|
mask = path.fillMask(width, height, windingRule)
|
||||||
rgbx = color.rgbx()
|
rgbx = color.rgbx()
|
||||||
|
|
||||||
var i: int
|
var i: int
|
||||||
|
|
Loading…
Reference in a new issue