23 return {p0.
x - p1.
x, p0.
y - p1.
y};
40 auto [left, right] = std::minmax(fUpper.
x, fLower.
x);
41 return std::make_tuple(left, fUpper.
y, right, fLower.
y);
45 return fUpper.
y == fLower.
y;
49 return fUpper.
x == fLower.
x;
58 return d0x * d1y - d1x * d0y;
83 const auto [u0, l0] = s0;
84 const auto [u1, l1] = s1;
86 const Point d0 = l0 - u0;
87 const Point d1 = l1 - u1;
105 return cross(d0, d1);
118 const auto [u, l] =
s;
125 const auto [left, right] = std::minmax(u.x, l.x);
136 if (
s.isHorizontal()) {
148 const Point dUToP =
p - u;
149 const Point dS = l - u;
152 return cross(dUToP, dS);
170 const auto [u0, l0] = s0;
171 const auto [u1, l1] = s1;
173 const auto [left0, right0] = std::minmax(u0.x, l0.x);
174 const auto [left1, right1] = std::minmax(u1.x, l1.x);
176 if (right0 < left1) {
178 }
else if (right1 < left0) {
182 const Point d0 = l0 - u0;
183 const Point d1 = l1 - u1;
190 using Int96 = bo::Int96;
235 using value_type =
Event;
236 using difference_type = ptrdiff_t;
237 using pointer = value_type*;
238 using reference = value_type;
239 using iterator_category = std::input_iterator_tag;
240 Iterator(
const EventQueue& eventQueue,
size_t index)
241 : fEventQueue{eventQueue}
243 Iterator(
const Iterator& that) : Iterator{ that.fEventQueue, that.fIndex } { }
244 Iterator& operator++() { ++fIndex;
return *
this; }
245 Iterator operator++(
int) { Iterator tmp(*
this); operator++();
return tmp; }
246 bool operator==(
const Iterator& rhs)
const {
return fIndex == rhs.fIndex; }
247 bool operator!=(
const Iterator& rhs)
const {
return fIndex != rhs.fIndex; }
248 value_type
operator*() {
return fEventQueue[fIndex]; }
249 friend difference_type
operator-(Iterator lhs, Iterator rhs) {
250 return lhs.fIndex - rhs.fIndex;
266 const int32_t endOfBegin;
267 const int32_t endOfHorizontal;
268 const int32_t endOfEnd;
300 std::tie(this->yOrdering, this->type, this->xTieBreaker, this->originalSegment)
301 == std::tie(r.yOrdering, r.type, r.xTieBreaker, r.originalSegment);
305 std::vector<SetupTuple> eventOrdering;
306 for (
const auto&
s : segments) {
309 if (
s.upper() ==
s.lower()) {
313 if (
s.isHorizontal()) {
315 eventOrdering.push_back(SetupTuple{
s.upper().
y, kHorizontal, -
s.upper().
x,
s});
318 eventOrdering.push_back(SetupTuple{
s.upper().
y, kBegin, -
s.upper().
x,
s});
319 eventOrdering.push_back(SetupTuple{
s.lower().
y, kEnd, -
s.lower().
x,
s});
324 auto eventLess = [](
const SetupTuple& l,
const SetupTuple& r) {
325 return std::tie(l.yOrdering, l.type, l.xTieBreaker) <
326 std::tie(r.yOrdering, r.type, r.xTieBreaker);
330 std::sort(eventOrdering.begin(), eventOrdering.end(), eventLess);
333 auto eraseFrom = std::unique(eventOrdering.begin(), eventOrdering.end());
334 eventOrdering.erase(eraseFrom, eventOrdering.end());
336 std::vector<CompactEvent> events;
337 std::vector<Segment> segmentStorage;
338 segmentStorage.reserve(eventOrdering.size());
340 int32_t currentY = eventOrdering.front().yOrdering;
345 for (
const auto& [
y,
type, _,
s] : eventOrdering) {
348 events.push_back(CompactEvent{currentY,
353 start = endOfBegin = endOfHorizontal = endOfEnd = segmentStorage.size();
357 segmentStorage.push_back(
s);
360 const size_t segmentCount = segmentStorage.size();
362 case kBegin: endOfBegin = segmentCount;
364 case kHorizontal: endOfHorizontal = segmentCount;
366 case kEnd: endOfEnd = segmentCount;
371 events.push_back(CompactEvent{currentY,
377 return EventQueue{std::move(events), std::move(segmentStorage)};
382 auto& [
y,
start, endOfBegin, endOfHorizontal, endOfEnd] = fEvents[
i];
385 horizontal{&fSegmentStorage[endOfBegin], endOfHorizontal - endOfBegin};
391 return Iterator{*
this, 0};
395 return Iterator{*
this, fEvents.size()};
399 return fEvents.size();
403 return fEvents.empty();
407 EventQueue(std::vector<CompactEvent>&& events, std::vector<Segment>&& segmentStorage)
408 : fEvents{
std::move(events)}
409 , fSegmentStorage{
std::move(segmentStorage)} {}
411 const std::vector<CompactEvent> fEvents;
412 const std::vector<Segment> fSegmentStorage;
431 fCrossings.emplace_back(s0, s1);
435 return std::move(fCrossings);
439 std::vector<Crossing> fCrossings;
443 static constexpr Segment kLeftStatusSentinel{{INT32_MIN, INT32_MIN}, {INT32_MIN, INT32_MAX}};
444 static constexpr Segment kRightStatusSentinel{{INT32_MAX, INT32_MIN}, {INT32_MAX, INT32_MAX}};
448 fStatus.push_back(kLeftStatusSentinel);
449 fStatus.push_back(kRightStatusSentinel);
453 auto& [
y, beginnings, horizontals, endings] =
e;
456 this->sortAndRecord(
y);
458 this->handleBeginnings(
y, beginnings);
459 this->handleHorizontals(
y, horizontals);
460 this->handleEndings(endings);
470 using StatusLine = std::vector<Segment>;
472 bool statusEmpty()
const {
473 return fStatus.size() == 2;
477 void sortAndRecord(int32_t
y) {
479 if (fStatus.size() <= 3) {
484 for (
size_t i = 2;
i < fStatus.size() - 1; ++
i) {
485 const Segment t = fStatus[
i];
490 fStatus[j] = fStatus[j-1];
498 template <
typename CrossingCheck>
499 void checkCrossingsLeftAndRight(
500 const Segment& segment, StatusLine::iterator insertionPoint, CrossingCheck
check) {
503 for (
auto cursor = std::make_reverse_iterator(insertionPoint);
check(*cursor); ++cursor) {
508 for (
auto cursor = insertionPoint;
check(*cursor); ++cursor) {
515 for (
const Segment&
s : inserting) {
516 auto insertionPoint =
517 std::lower_bound(fStatus.begin(), fStatus.end(),
s,
522 auto checkIntersect = [&](
const Segment& toCheck) {
525 this->checkCrossingsLeftAndRight(
s, insertionPoint, checkIntersect);
527 fStatus.insert(insertionPoint,
s);
534 for (
const Segment&
s : horizontals) {
535 auto insertionPoint =
536 std::lower_bound(fStatus.begin(), fStatus.end(),
s,
540 auto checkIntersection = [&](
const Segment& toCheck) {
544 this->checkCrossingsLeftAndRight(
s, insertionPoint, checkIntersection);
546 fStatus.insert(insertionPoint,
s);
549 this->handleEndings(horizontals);
554 for (
const Segment&
s : removing) {
555 auto removedPoint =
std::remove(fStatus.begin(), fStatus.end(),
s);
556 SkASSERT(removedPoint != fStatus.end());
557 fStatus.erase(removedPoint, fStatus.end());
562 CrossingAccumulator fCrossings;
589 auto [left0, top0, right0, bottom0] = s0.
bounds();
590 auto [left1, top1, right1, bottom1] = s1.
bounds();
591 if (right1 < left0 || right0 < left1 || bottom1 < top0 || bottom0 < top1) {
604 const Point U0toU1 = (u1 - u0);
605 const int64_t D0xU0toU1 =
cross(
D0, U0toU1);
606 if (D0xU0toU1 == 0) {
613 const Point U0toL1 = (l1 - u0);
614 const int64_t D0xU0toL1 =
cross(
D0, U0toL1);
615 if (D0xU0toL1 == 0) {
621 return (D0xU0toU1 ^ D0xU0toL1) < 0;
625 const Point U1toL0 = (l0 - u1);
626 const int64_t D1xU1toL0 =
cross(
D1, U1toL0);
627 if (D1xU1toL0 == 0) {
634 return (D0xU0toU1 ^ D1xU1toL0) >= 0;
640 auto isNonZeroSegment = [](
const Segment& segment) {
641 return segment.upper() != segment.lower();
643 const auto zeroSegments = std::partition(segments.
begin(), segments.
end(), isNonZeroSegment);
647 const auto duplicateSegments = std::unique(segments.
begin(), zeroSegments);
653 if (cleanSegments.
size() >= 2) {
GrAATriangulator::Event Event
static float next(float f)
static float prev(float f)
#define check(reporter, ref, unref, make, kill)
static std::vector< SkPDFIndirectReference > sort(const THashSet< SkPDFIndirectReference > &src)
constexpr int64_t SkToS64(S x)
constexpr T * data() const
constexpr T * begin() const
constexpr T * end() const
constexpr bool empty() const
constexpr size_t size() const
void recordCrossing(const Segment &s0, const Segment &s1)
std::vector< Crossing > finishAndReleaseCrossings()
static EventQueue Make(const SkSpan< const Segment > segments)
Event operator[](size_t i) const
const Point & upper() const
std::tuple< int32_t, int32_t, int32_t, int32_t > bounds() const
bool isHorizontal() const
const Point & lower() const
std::vector< Crossing > finishAndReleaseCrossings()
void handleEvent(Event e)
Int96 multiply(int64_t a, int32_t b)
std::variant< Lower, Cross, Upper > EventType
constexpr Color operator*(T value, const Color &c)
std::tuple< int64_t, int64_t > point_to_s64(Point p)
bool s0_less_than_s1_at_y(const Segment &s0, const Segment &s1, int32_t y)
bool s0_intersects_s1(const Segment &s0, const Segment &s1)
Point operator-(const Point &p0, const Point &p1)
std::vector< Crossing > brute_force_crossings(SkSpan< Segment >)
int64_t cross(Point d0, Point d1)
int64_t compare_slopes(const Segment &s0, const Segment &s1)
constexpr bool operator!=(const Point &p0, const Point &p1)
bool slope_s0_less_than_slope_s1(const Segment &s0, const Segment &s1)
std::vector< Crossing > myers_find_crossings(const SkSpan< const Segment > segments)
int64_t compare_point_to_segment(Point p, const Segment &s)
bool segment_less_than_upper_to_insert(const Segment &segment, const Segment &to_insert)
constexpr bool operator==(const Point &p0, const Point &p1)
int compare(const void *untyped_lhs, const void *untyped_rhs)
SkSpan< const Segment > horizontal
SkSpan< const Segment > end
SkSpan< const Segment > begin