From 7225883aa9a11a18ea492a96a49cd2abd83ce770 Mon Sep 17 00:00:00 2001 From: Ryan Oldenburg Date: Sat, 25 Jun 2022 13:47:51 -0500 Subject: [PATCH] better shortcut detection, improves polygon test --- src/pixie/internal.nim | 16 +++++++++++++++- src/pixie/paths.nim | 14 +++++++++----- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/pixie/internal.nim b/src/pixie/internal.nim index 448d955..79eda21 100644 --- a/src/pixie/internal.nim +++ b/src/pixie/internal.nim @@ -1,4 +1,4 @@ -import chroma, common, system/memory, vmath +import bumpy, chroma, common, system/memory, vmath const allowSimd* = not defined(pixieNoSimd) and not defined(tcc) @@ -51,6 +51,20 @@ proc `*`*(color: ColorRGBX, opacity: float32): ColorRGBX {.raises: [].} = a = ((color.a * x) div 255).uint8 rgbx(r, g, b, a) +proc intersectsInside*(a, b: Segment, at: var Vec2): bool {.inline.} = + ## Checks if the a segment intersects b segment (excluding endpoints). + ## If it returns true, at will have point of intersection + let + s1 = a.to - a.at + s2 = b.to - b.at + denominator = (-s2.x * s1.y + s1.x * s2.y) + s = (-s1.y * (a.at.x - b.at.x) + s1.x * (a.at.y - b.at.y)) / denominator + t = (s2.x * (a.at.y - b.at.y) - s2.y * (a.at.x - b.at.x)) / denominator + + if s > 0 and s < 1 and t > 0 and t < 1: + at = a.at + (t * s1) + return true + proc fillUnsafe*( data: var seq[uint8], value: uint8, start, len: int ) {.inline, raises: [].} = diff --git a/src/pixie/paths.nim b/src/pixie/paths.nim index 69dc18e..96eb56b 100644 --- a/src/pixie/paths.nim +++ b/src/pixie/paths.nim @@ -1205,7 +1205,7 @@ proc partitionSegments( entry0 = partition.entries[0].segment entry1 = partition.entries[1].segment var at: Vec2 - if not intersects(entry0, entry1, at): + if not intersectsInside(entry0, entry1, at): # These two segments do not intersect, enable shortcut partition.twoNonintersectingSpanningSegments = true # Ensure entry[0] is on the left @@ -1916,7 +1916,7 @@ proc fillShapes( if allEntriesInScanlineSpanIt and tmp == 2: var at: Vec2 - if not intersects( + if not intersectsInside( partitions[partitionIndex].entries[entryIndices[0]].segment, partitions[partitionIndex].entries[entryIndices[1]].segment, at @@ -1925,9 +1925,13 @@ proc fillShapes( var left = partitions[partitionIndex].entries[entryIndices[0]] right = partitions[partitionIndex].entries[entryIndices[1]] - # Ensure left is on the left - if left.segment.at.x > right.segment.at.x: - swap left, right + block: + # Ensure left is actually on the left + let + maybeLeftMaxX = max(left.segment.at.x, left.segment.to.x) + maybeRightMaxX = max(right.segment.at.x, right.segment.to.x) + if maybeLeftMaxX > maybeRightMaxX: + swap left, right let requiresAntiAliasing = left.segment.requiresAntiAliasing or