faster path filling, precompute m and b
This commit is contained in:
parent
87c7e9fee6
commit
85c4833e70
1 changed files with 62 additions and 53 deletions
|
@ -35,8 +35,13 @@ type
|
||||||
|
|
||||||
SomePath* = Path | string
|
SomePath* = Path | string
|
||||||
|
|
||||||
|
PartitionEntry = object
|
||||||
|
atY, toY: float32
|
||||||
|
m, b: float32
|
||||||
|
winding: int16
|
||||||
|
|
||||||
Partitioning = object
|
Partitioning = object
|
||||||
partitions: seq[seq[(Segment, int16)]]
|
partitions: seq[seq[PartitionEntry]]
|
||||||
startY, partitionHeight: uint32
|
startY, partitionHeight: uint32
|
||||||
|
|
||||||
const
|
const
|
||||||
|
@ -1076,8 +1081,19 @@ proc partitionSegments(
|
||||||
result.partitionHeight = height.uint32 div numPartitions
|
result.partitionHeight = height.uint32 div numPartitions
|
||||||
|
|
||||||
for (segment, winding) in segments:
|
for (segment, winding) in segments:
|
||||||
|
var entry: PartitionEntry
|
||||||
|
entry.atY = segment.at.y
|
||||||
|
entry.toY = segment.to.y
|
||||||
|
entry.winding = winding
|
||||||
|
let d = segment.at.x - segment.to.x
|
||||||
|
if d == 0:
|
||||||
|
entry.b = segment.at.x # Leave m = 0, store the x we want in b
|
||||||
|
else:
|
||||||
|
entry.m = (segment.at.y - segment.to.y) / d
|
||||||
|
entry.b = segment.at.y - entry.m * segment.at.x
|
||||||
|
|
||||||
if result.partitionHeight == 0:
|
if result.partitionHeight == 0:
|
||||||
result.partitions[0].add((segment, winding))
|
result.partitions[0].add(entry)
|
||||||
else:
|
else:
|
||||||
var
|
var
|
||||||
atPartition = max(0, segment.at.y - result.startY.float32).uint32
|
atPartition = max(0, segment.at.y - result.startY.float32).uint32
|
||||||
|
@ -1087,7 +1103,7 @@ proc partitionSegments(
|
||||||
atPartition = clamp(atPartition, 0, result.partitions.high.uint32)
|
atPartition = clamp(atPartition, 0, result.partitions.high.uint32)
|
||||||
toPartition = clamp(toPartition, 0, result.partitions.high.uint32)
|
toPartition = clamp(toPartition, 0, result.partitions.high.uint32)
|
||||||
for i in atPartition .. toPartition:
|
for i in atPartition .. toPartition:
|
||||||
result.partitions[i].add((segment, winding))
|
result.partitions[i].add(entry)
|
||||||
|
|
||||||
proc getIndexForY(partitioning: Partitioning, y: int): uint32 {.inline.} =
|
proc getIndexForY(partitioning: Partitioning, y: int): uint32 {.inline.} =
|
||||||
if partitioning.partitionHeight == 0 or partitioning.partitions.len == 1:
|
if partitioning.partitionHeight == 0 or partitioning.partitions.len == 1:
|
||||||
|
@ -1191,38 +1207,31 @@ proc computeCoverages(
|
||||||
zeroMem(coverages[0].addr, coverages.len)
|
zeroMem(coverages[0].addr, coverages.len)
|
||||||
|
|
||||||
# Do scanlines for this row
|
# Do scanlines for this row
|
||||||
let partitionIndex = partitioning.getIndexForY(y)
|
let
|
||||||
|
partitionIndex = partitioning.getIndexForY(y)
|
||||||
|
partitionEntryCount = partitioning.partitions[partitionIndex].len
|
||||||
var yLine = y.float32 + initialOffset - offset
|
var yLine = y.float32 + initialOffset - offset
|
||||||
for m in 0 ..< quality:
|
for m in 0 ..< quality:
|
||||||
yLine += offset
|
yLine += offset
|
||||||
numHits = 0
|
numHits = 0
|
||||||
for i in 0 ..< partitioning.partitions[partitionIndex].len: # Perf
|
for i in 0 ..< partitionEntryCount: # Perf
|
||||||
let
|
let entry = partitioning.partitions[partitionIndex][i]
|
||||||
segment = partitioning.partitions[partitionIndex][i][0]
|
if entry.atY <= yLine and entry.toY >= yLine:
|
||||||
winding = partitioning.partitions[partitionIndex][i][1]
|
let x =
|
||||||
if segment.at.y <= yLine and segment.to.y >= yLine:
|
if entry.m == 0:
|
||||||
let
|
entry.b
|
||||||
d = segment.at.x - segment.to.x
|
|
||||||
x =
|
|
||||||
if d == 0:
|
|
||||||
segment.at.x
|
|
||||||
else:
|
else:
|
||||||
let
|
(yLine - entry.b) / entry.m
|
||||||
m = (segment.at.y - segment.to.y) / d
|
|
||||||
b = segment.at.y - m * segment.at.x
|
|
||||||
(yLine - b) / m
|
|
||||||
|
|
||||||
if numHits == hits.len:
|
if numHits == hits.len:
|
||||||
hits.setLen(hits.len * 2)
|
hits.setLen(hits.len * 2)
|
||||||
hits[numHits] = (min(x, width), winding)
|
hits[numHits] = (min(x, width), entry.winding)
|
||||||
inc numHits
|
inc numHits
|
||||||
|
|
||||||
if numHits > 0:
|
if numHits > 0:
|
||||||
sort(hits, 0, numHits - 1)
|
sort(hits, 0, numHits - 1)
|
||||||
|
|
||||||
if not aa:
|
if aa:
|
||||||
continue
|
|
||||||
|
|
||||||
for (prevAt, at, count) in hits.walk(numHits, windingRule, y, width):
|
for (prevAt, at, count) in hits.walk(numHits, windingRule, y, width):
|
||||||
var fillStart = prevAt.int
|
var fillStart = prevAt.int
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue