simpler
This commit is contained in:
parent
fe488708cd
commit
0affa5284b
1 changed files with 115 additions and 131 deletions
|
@ -1937,150 +1937,134 @@ proc fillShapes(
|
||||||
if maybeLeftMaxX > maybeRightMaxX:
|
if maybeLeftMaxX > maybeRightMaxX:
|
||||||
swap left, right
|
swap left, right
|
||||||
|
|
||||||
let requiresAntiAliasing =
|
# We have 2 non-intersecting lines that require anti-aliasing
|
||||||
left.segment.requiresAntiAliasing or
|
# Use trapezoid coverage at the edges and fill in the middle
|
||||||
right.segment.requiresAntiAliasing
|
|
||||||
|
|
||||||
if requiresAntiAliasing:
|
when allowSimd and defined(amd64):
|
||||||
# We have 2 non-intersecting lines that require anti-aliasing
|
let vecRgbx = mm_set_ps(
|
||||||
# Use trapezoid coverage at the edges and fill in the middle
|
rgbx.a.float32,
|
||||||
|
rgbx.b.float32,
|
||||||
|
rgbx.g.float32,
|
||||||
|
rgbx.r.float32
|
||||||
|
)
|
||||||
|
|
||||||
when allowSimd and defined(amd64):
|
proc solveX(entry: PartitionEntry, y: float32): float32 =
|
||||||
let vecRgbx = mm_set_ps(
|
if entry.m == 0:
|
||||||
rgbx.a.float32,
|
entry.b
|
||||||
rgbx.b.float32,
|
else:
|
||||||
rgbx.g.float32,
|
(y - entry.b) / entry.m
|
||||||
rgbx.r.float32
|
|
||||||
)
|
|
||||||
|
|
||||||
proc solveX(entry: PartitionEntry, y: float32): float32 =
|
proc solveY(entry: PartitionEntry, x: float32): float32 =
|
||||||
if entry.m == 0:
|
entry.m * x + entry.b
|
||||||
entry.b
|
|
||||||
else:
|
|
||||||
(y - entry.b) / entry.m
|
|
||||||
|
|
||||||
proc solveY(entry: PartitionEntry, x: float32): float32 =
|
var
|
||||||
entry.m * x + entry.b
|
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
|
var
|
||||||
leftTop = vec2(0, y.float32)
|
rightTop = vec2(0, y.float32)
|
||||||
leftBottom = vec2(0, (y + 1).float32)
|
rightBottom = vec2(0, (y + 1).float32)
|
||||||
leftTop.x = left.solveX(leftTop.y.float32)
|
rightTop.x = right.solveX(rightTop.y)
|
||||||
leftBottom.x = left.solveX(leftBottom.y)
|
rightBottom.x = right.solveX(rightBottom.y)
|
||||||
|
|
||||||
var
|
let
|
||||||
rightTop = vec2(0, y.float32)
|
leftMaxX = max(leftTop.x, leftBottom.x)
|
||||||
rightBottom = vec2(0, (y + 1).float32)
|
rightMinX = min(rightTop.x, rightBottom.x)
|
||||||
rightTop.x = right.solveX(rightTop.y)
|
leftCoverEnd = leftMaxX.ceil.int
|
||||||
rightBottom.x = right.solveX(rightBottom.y)
|
rightCoverBegin = rightMinX.trunc.int
|
||||||
|
|
||||||
let
|
if leftCoverEnd < rightCoverBegin:
|
||||||
leftMaxX = max(leftTop.x, leftBottom.x)
|
# Only take this shortcut if the partial coverage areas on the
|
||||||
rightMinX = min(rightTop.x, rightBottom.x)
|
# left and the right do not overlap
|
||||||
leftCoverEnd = leftMaxX.ceil.int
|
|
||||||
rightCoverBegin = rightMinX.trunc.int
|
|
||||||
|
|
||||||
if leftCoverEnd < rightCoverBegin:
|
let blender = blendMode.blender()
|
||||||
# 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
|
|
||||||
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)
|
|
||||||
|
|
||||||
|
block: # Left-side partial coverage
|
||||||
let
|
let
|
||||||
fillBegin = leftCoverEnd.clamp(0, image.width)
|
inverted = leftTop.x < leftBottom.x
|
||||||
fillEnd = rightCoverBegin.clamp(0, image.width)
|
sliverStart = min(leftTop.x, leftBottom.x)
|
||||||
if fillEnd - fillBegin > 0:
|
rectStart = max(leftTop.x, leftBottom.x)
|
||||||
hits[0] = (fixed32(fillBegin.float32), 1.int16)
|
var
|
||||||
hits[1] = (fixed32(fillEnd.float32), -1.int16)
|
pen = sliverStart
|
||||||
image.fillHits(rgbx, 0, y, hits, 2, NonZero, blendMode)
|
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)
|
||||||
|
|
||||||
inc y
|
block: # Right-side partial coverage
|
||||||
continue
|
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)
|
||||||
|
|
||||||
else:
|
|
||||||
let
|
let
|
||||||
minX = left.segment.at.x.int.clamp(0, image.width)
|
fillBegin = leftCoverEnd.clamp(0, image.width)
|
||||||
maxX = right.segment.at.x.int.clamp(0, image.width)
|
fillEnd = rightCoverBegin.clamp(0, image.width)
|
||||||
hits[0] = (cast[Fixed32](minX * 256), 1.int16)
|
if fillEnd - fillBegin > 0:
|
||||||
hits[1] = (cast[Fixed32](maxX * 256), -1.int16)
|
hits[0] = (fixed32(fillBegin.float32), 1.int16)
|
||||||
image.fillHits(rgbx, 0, y, hits, 2, NonZero, blendMode)
|
hits[1] = (fixed32(fillEnd.float32), -1.int16)
|
||||||
|
image.fillHits(rgbx, 0, y, hits, 2, NonZero, blendMode)
|
||||||
|
|
||||||
inc y
|
inc y
|
||||||
continue
|
continue
|
||||||
|
|
Loading…
Reference in a new issue