Merge pull request #110 from guzba/master

paths.nim scanline method perf improved
This commit is contained in:
treeform 2021-02-17 19:37:46 -08:00 committed by GitHub
commit de63a0fa68
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 42 additions and 36 deletions

View file

@ -894,7 +894,7 @@ proc partitionSegments(
partitions
proc computeCoverages(
template computeCoverages(
coverages: var seq[uint8],
hits: var seq[(float32, int16)],
numHits: var int,
@ -903,16 +903,17 @@ proc computeCoverages(
partitions: seq[seq[(Segment, int16)]],
partitionHeight: uint32,
windingRule: WindingRule
) {.inline.} =
) =
const
ep = 0.0001 * PI
quality = 5 # Must divide 255 cleanly (1, 3, 5, 15, 17, 51, 85)
sampleCoverage = (255 div quality).uint8
offset = 1 / quality.float32
initialOffset = offset / 2
initialOffset = offset / 2 + ep
let
partition =
if partitionHeight == 0:
if partitionHeight == 0 or partitions.len == 1:
0.uint32
else:
min(y.uint32 div partitionHeight, partitions.high.uint32)
@ -920,11 +921,10 @@ proc computeCoverages(
zeroMem(coverages[0].addr, coverages.len)
# Do scanlines for this row
var yLine = y.float32 + initialOffset - offset
for m in 0 ..< quality:
const ep = 0.0001 * PI
let
yLine = y.float32 + initialOffset + offset * m.float32 + ep
scanline = Line(a: vec2(0, yLine), b: vec2(size.x, yLine))
yLine += offset
let scanline = line(vec2(0, yLine), vec2(size.x, yLine))
numHits = 0
for (segment, winding) in partitions[partition]:
if segment.at.y <= scanline.a.y and segment.to.y >= scanline.a.y:
@ -932,47 +932,53 @@ proc computeCoverages(
if scanline.intersects(segment, at): # and segment.to != at:
if numHits == hits.len:
hits.setLen(hits.len * 2)
hits[numHits] = (at.x.clamp(0, scanline.b.x), winding)
hits[numHits] = (min(at.x, size.x), winding)
inc numHits
quickSort(hits, 0, numHits - 1)
var
x: float32
prevAt: float32
count: int
for i in 0 ..< numHits:
let (at, winding) = hits[i]
var fillStart = x.int
let leftCover = if at.int - x.int > 0: trunc(x) + 1 - x else: at - x
if leftCover != 0:
inc fillStart
if at > 0:
if shouldFill(windingRule, count):
coverages[x.int] += (leftCover * sampleCoverage.float32).uint8
var fillStart = prevAt.int
if at.int - x.int > 0:
let rightCover = at - trunc(at)
if rightCover > 0 and shouldFill(windingRule, count):
coverages[at.int] += (rightCover * sampleCoverage.float32).uint8
let
pixelCrossed = at.int - prevAt.int > 0
leftCover =
if pixelCrossed:
trunc(prevAt) + 1 - prevAt
else:
at - prevAt
if leftCover != 0:
inc fillStart
coverages[prevAt.int] +=
(leftCover * sampleCoverage.float32).uint8
let fillLen = at.int - fillStart
if fillLen > 0 and shouldFill(windingRule, count):
var i = fillStart
when defined(amd64) and not defined(pixieNoSimd):
let vSampleCoverage = mm_set1_epi8(cast[int8](sampleCoverage))
for j in countup(i, fillStart + fillLen - 16, 16):
let current = mm_loadu_si128(coverages[j].addr)
mm_storeu_si128(
coverages[j].addr,
mm_add_epi8(current, vSampleCoverage)
)
i += 16
for j in i ..< fillStart + fillLen:
coverages[j] += sampleCoverage
if pixelCrossed:
let rightCover = at - trunc(at)
if rightCover > 0:
coverages[at.int] += (rightCover * sampleCoverage.float32).uint8
let fillLen = at.int - fillStart
if fillLen > 0:
var i = fillStart
when defined(amd64) and not defined(pixieNoSimd):
let vSampleCoverage = mm_set1_epi8(cast[int8](sampleCoverage))
for j in countup(i, fillStart + fillLen - 16, 16):
var coverage = mm_loadu_si128(coverages[j].addr)
coverage = mm_add_epi8(coverage, vSampleCoverage)
mm_storeu_si128(coverages[j].addr, coverage)
i += 16
for j in i ..< fillStart + fillLen:
coverages[j] += sampleCoverage
prevAt = at
count += winding
x = at
proc fillShapes(
image: Image,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 356 KiB

After

Width:  |  Height:  |  Size: 356 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB