simpler
This commit is contained in:
parent
0affa5284b
commit
f41f895e24
1 changed files with 136 additions and 144 deletions
|
@ -1919,155 +1919,147 @@ proc fillShapes(
|
||||||
break
|
break
|
||||||
|
|
||||||
if allEntriesInScanlineSpanIt and tmp == 2:
|
if allEntriesInScanlineSpanIt and tmp == 2:
|
||||||
var at: Vec2
|
var
|
||||||
if not intersectsInside(
|
left = partitions[partitionIndex].entries[entryIndices[0]]
|
||||||
partitions[partitionIndex].entries[entryIndices[0]].segment,
|
right = partitions[partitionIndex].entries[entryIndices[1]]
|
||||||
partitions[partitionIndex].entries[entryIndices[1]].segment,
|
block:
|
||||||
at
|
# Ensure left is actually on the left
|
||||||
):
|
let
|
||||||
# We have 2 non-intersecting lines
|
maybeLeftMaxX = max(left.segment.at.x, left.segment.to.x)
|
||||||
var
|
maybeRightMaxX = max(right.segment.at.x, right.segment.to.x)
|
||||||
left = partitions[partitionIndex].entries[entryIndices[0]]
|
if maybeLeftMaxX > maybeRightMaxX:
|
||||||
right = partitions[partitionIndex].entries[entryIndices[1]]
|
swap left, right
|
||||||
block:
|
|
||||||
# Ensure left is actually on the left
|
# Use trapezoid coverage at the edges and fill in the middle
|
||||||
|
|
||||||
|
when allowSimd and defined(amd64):
|
||||||
|
let vecRgbx = mm_set_ps(
|
||||||
|
rgbx.a.float32,
|
||||||
|
rgbx.b.float32,
|
||||||
|
rgbx.g.float32,
|
||||||
|
rgbx.r.float32
|
||||||
|
)
|
||||||
|
|
||||||
|
proc solveX(entry: PartitionEntry, y: float32): float32 =
|
||||||
|
if entry.m == 0:
|
||||||
|
entry.b
|
||||||
|
else:
|
||||||
|
(y - entry.b) / entry.m
|
||||||
|
|
||||||
|
proc solveY(entry: PartitionEntry, x: float32): float32 =
|
||||||
|
entry.m * x + entry.b
|
||||||
|
|
||||||
|
var
|
||||||
|
leftTop = vec2(0, y.float32)
|
||||||
|
leftBottom = vec2(0, (y + 1).float32)
|
||||||
|
leftTop.x = left.solveX(leftTop.y.float32)
|
||||||
|
leftBottom.x = left.solveX(leftBottom.y)
|
||||||
|
|
||||||
|
var
|
||||||
|
rightTop = vec2(0, y.float32)
|
||||||
|
rightBottom = vec2(0, (y + 1).float32)
|
||||||
|
rightTop.x = right.solveX(rightTop.y)
|
||||||
|
rightBottom.x = right.solveX(rightBottom.y)
|
||||||
|
|
||||||
|
let
|
||||||
|
leftMaxX = max(leftTop.x, leftBottom.x)
|
||||||
|
rightMinX = min(rightTop.x, rightBottom.x)
|
||||||
|
leftCoverEnd = leftMaxX.ceil.int
|
||||||
|
rightCoverBegin = rightMinX.trunc.int
|
||||||
|
|
||||||
|
if leftCoverEnd < rightCoverBegin:
|
||||||
|
# Only take this shortcut if the partial coverage areas on the
|
||||||
|
# left and the right do not overlap
|
||||||
|
|
||||||
|
let blender = blendMode.blender()
|
||||||
|
|
||||||
|
block: # Left-side partial coverage
|
||||||
let
|
let
|
||||||
maybeLeftMaxX = max(left.segment.at.x, left.segment.to.x)
|
inverted = leftTop.x < leftBottom.x
|
||||||
maybeRightMaxX = max(right.segment.at.x, right.segment.to.x)
|
sliverStart = min(leftTop.x, leftBottom.x)
|
||||||
if maybeLeftMaxX > maybeRightMaxX:
|
rectStart = max(leftTop.x, leftBottom.x)
|
||||||
swap left, right
|
var
|
||||||
|
pen = sliverStart
|
||||||
|
prevPen = pen
|
||||||
|
penY = if inverted: y.float32 else: (y + 1).float32
|
||||||
|
prevPenY = penY
|
||||||
|
for x in sliverStart.int ..< rectStart.ceil.int:
|
||||||
|
prevPen = pen
|
||||||
|
pen = (x + 1).float32
|
||||||
|
var rightRectArea = 0.float32
|
||||||
|
if pen > rectStart:
|
||||||
|
rightRectArea = pen - rectStart
|
||||||
|
pen = rectStart
|
||||||
|
prevPenY = penY
|
||||||
|
penY = left.solveY(pen)
|
||||||
|
if x < 0 or x >= image.width:
|
||||||
|
continue
|
||||||
|
let
|
||||||
|
run = pen - prevPen
|
||||||
|
triangleArea = 0.5.float32 * run * abs(penY - prevPenY)
|
||||||
|
rectArea =
|
||||||
|
if inverted:
|
||||||
|
(prevPenY - y.float32) * run
|
||||||
|
else:
|
||||||
|
((y + 1).float32 - prevPenY) * run
|
||||||
|
area = triangleArea + rectArea + rightRectArea
|
||||||
|
dataIndex = image.dataIndex(x, y)
|
||||||
|
backdrop = image.data[dataIndex]
|
||||||
|
source =
|
||||||
|
when allowSimd and defined(amd64):
|
||||||
|
applyOpacity(vecRgbx, area)
|
||||||
|
else:
|
||||||
|
rgbx * area
|
||||||
|
image.data[dataIndex] = blender(backdrop, source)
|
||||||
|
|
||||||
# We have 2 non-intersecting lines that require anti-aliasing
|
block: # Right-side partial coverage
|
||||||
# Use trapezoid coverage at the edges and fill in the middle
|
let
|
||||||
|
inverted = rightTop.x > rightBottom.x
|
||||||
when allowSimd and defined(amd64):
|
rectEnd = min(rightTop.x, rightBottom.x)
|
||||||
let vecRgbx = mm_set_ps(
|
sliverEnd = max(rightTop.x, rightBottom.x)
|
||||||
rgbx.a.float32,
|
var
|
||||||
rgbx.b.float32,
|
pen = rectEnd
|
||||||
rgbx.g.float32,
|
prevPen = pen
|
||||||
rgbx.r.float32
|
penY = if inverted: (y + 1).float32 else: y.float32
|
||||||
)
|
prevPenY = penY
|
||||||
|
for x in rectEnd.int ..< sliverEnd.ceil.int:
|
||||||
proc solveX(entry: PartitionEntry, y: float32): float32 =
|
prevPen = pen
|
||||||
if entry.m == 0:
|
pen = (x + 1).float32
|
||||||
entry.b
|
let leftRectArea = prevPen.fractional
|
||||||
else:
|
if pen > sliverEnd:
|
||||||
(y - entry.b) / entry.m
|
pen = sliverEnd
|
||||||
|
prevPenY = penY
|
||||||
proc solveY(entry: PartitionEntry, x: float32): float32 =
|
penY = right.solveY(pen)
|
||||||
entry.m * x + entry.b
|
if x < 0 or x >= image.width:
|
||||||
|
continue
|
||||||
var
|
let
|
||||||
leftTop = vec2(0, y.float32)
|
run = pen - prevPen
|
||||||
leftBottom = vec2(0, (y + 1).float32)
|
triangleArea = 0.5.float32 * run * abs(penY - prevPenY)
|
||||||
leftTop.x = left.solveX(leftTop.y.float32)
|
rectArea =
|
||||||
leftBottom.x = left.solveX(leftBottom.y)
|
if inverted:
|
||||||
|
(penY - y.float32) * run
|
||||||
var
|
else:
|
||||||
rightTop = vec2(0, y.float32)
|
((y + 1).float32 - penY) * run
|
||||||
rightBottom = vec2(0, (y + 1).float32)
|
area = leftRectArea + triangleArea + rectArea
|
||||||
rightTop.x = right.solveX(rightTop.y)
|
dataIndex = image.dataIndex(x, y)
|
||||||
rightBottom.x = right.solveX(rightBottom.y)
|
backdrop = image.data[dataIndex]
|
||||||
|
source =
|
||||||
|
when allowSimd and defined(amd64):
|
||||||
|
applyOpacity(vecRgbx, area)
|
||||||
|
else:
|
||||||
|
rgbx * area
|
||||||
|
image.data[dataIndex] = blender(backdrop, source)
|
||||||
|
|
||||||
let
|
let
|
||||||
leftMaxX = max(leftTop.x, leftBottom.x)
|
fillBegin = leftCoverEnd.clamp(0, image.width)
|
||||||
rightMinX = min(rightTop.x, rightBottom.x)
|
fillEnd = rightCoverBegin.clamp(0, image.width)
|
||||||
leftCoverEnd = leftMaxX.ceil.int
|
if fillEnd - fillBegin > 0:
|
||||||
rightCoverBegin = rightMinX.trunc.int
|
hits[0] = (fixed32(fillBegin.float32), 1.int16)
|
||||||
|
hits[1] = (fixed32(fillEnd.float32), -1.int16)
|
||||||
|
image.fillHits(rgbx, 0, y, hits, 2, NonZero, blendMode)
|
||||||
|
|
||||||
if leftCoverEnd < rightCoverBegin:
|
inc y
|
||||||
# Only take this shortcut if the partial coverage areas on the
|
continue
|
||||||
# left and the right do not overlap
|
|
||||||
|
|
||||||
let blender = blendMode.blender()
|
|
||||||
|
|
||||||
block: # Left-side partial coverage
|
|
||||||
let
|
|
||||||
inverted = leftTop.x < leftBottom.x
|
|
||||||
sliverStart = min(leftTop.x, leftBottom.x)
|
|
||||||
rectStart = max(leftTop.x, leftBottom.x)
|
|
||||||
var
|
|
||||||
pen = sliverStart
|
|
||||||
prevPen = pen
|
|
||||||
penY = if inverted: y.float32 else: (y + 1).float32
|
|
||||||
prevPenY = penY
|
|
||||||
for x in sliverStart.int ..< rectStart.ceil.int:
|
|
||||||
prevPen = pen
|
|
||||||
pen = (x + 1).float32
|
|
||||||
var rightRectArea = 0.float32
|
|
||||||
if pen > rectStart:
|
|
||||||
rightRectArea = pen - rectStart
|
|
||||||
pen = rectStart
|
|
||||||
prevPenY = penY
|
|
||||||
penY = left.solveY(pen)
|
|
||||||
if x < 0 or x >= image.width:
|
|
||||||
continue
|
|
||||||
let
|
|
||||||
run = pen - prevPen
|
|
||||||
triangleArea = 0.5.float32 * run * abs(penY - prevPenY)
|
|
||||||
rectArea =
|
|
||||||
if inverted:
|
|
||||||
(prevPenY - y.float32) * run
|
|
||||||
else:
|
|
||||||
((y + 1).float32 - prevPenY) * run
|
|
||||||
area = triangleArea + rectArea + rightRectArea
|
|
||||||
dataIndex = image.dataIndex(x, y)
|
|
||||||
backdrop = image.data[dataIndex]
|
|
||||||
source =
|
|
||||||
when allowSimd and defined(amd64):
|
|
||||||
applyOpacity(vecRgbx, area)
|
|
||||||
else:
|
|
||||||
rgbx * area
|
|
||||||
image.data[dataIndex] = blender(backdrop, source)
|
|
||||||
|
|
||||||
block: # Right-side partial coverage
|
|
||||||
let
|
|
||||||
inverted = rightTop.x > rightBottom.x
|
|
||||||
rectEnd = min(rightTop.x, rightBottom.x)
|
|
||||||
sliverEnd = max(rightTop.x, rightBottom.x)
|
|
||||||
var
|
|
||||||
pen = rectEnd
|
|
||||||
prevPen = pen
|
|
||||||
penY = if inverted: (y + 1).float32 else: y.float32
|
|
||||||
prevPenY = penY
|
|
||||||
for x in rectEnd.int ..< sliverEnd.ceil.int:
|
|
||||||
prevPen = pen
|
|
||||||
pen = (x + 1).float32
|
|
||||||
let leftRectArea = prevPen.fractional
|
|
||||||
if pen > sliverEnd:
|
|
||||||
pen = sliverEnd
|
|
||||||
prevPenY = penY
|
|
||||||
penY = right.solveY(pen)
|
|
||||||
if x < 0 or x >= image.width:
|
|
||||||
continue
|
|
||||||
let
|
|
||||||
run = pen - prevPen
|
|
||||||
triangleArea = 0.5.float32 * run * abs(penY - prevPenY)
|
|
||||||
rectArea =
|
|
||||||
if inverted:
|
|
||||||
(penY - y.float32) * run
|
|
||||||
else:
|
|
||||||
((y + 1).float32 - penY) * run
|
|
||||||
area = leftRectArea + triangleArea + rectArea
|
|
||||||
dataIndex = image.dataIndex(x, y)
|
|
||||||
backdrop = image.data[dataIndex]
|
|
||||||
source =
|
|
||||||
when allowSimd and defined(amd64):
|
|
||||||
applyOpacity(vecRgbx, area)
|
|
||||||
else:
|
|
||||||
rgbx * area
|
|
||||||
image.data[dataIndex] = blender(backdrop, source)
|
|
||||||
|
|
||||||
let
|
|
||||||
fillBegin = leftCoverEnd.clamp(0, image.width)
|
|
||||||
fillEnd = rightCoverBegin.clamp(0, image.width)
|
|
||||||
if fillEnd - fillBegin > 0:
|
|
||||||
hits[0] = (fixed32(fillBegin.float32), 1.int16)
|
|
||||||
hits[1] = (fixed32(fillEnd.float32), -1.int16)
|
|
||||||
image.fillHits(rgbx, 0, y, hits, 2, NonZero, blendMode)
|
|
||||||
|
|
||||||
inc y
|
|
||||||
continue
|
|
||||||
|
|
||||||
computeCoverage(
|
computeCoverage(
|
||||||
cast[ptr UncheckedArray[uint8]](coverages[0].addr),
|
cast[ptr UncheckedArray[uint8]](coverages[0].addr),
|
||||||
|
|
Loading…
Reference in a new issue