1*c8dee2aaSAndroid Build Coastguard Worker // Copyright 2023 Google LLC 2*c8dee2aaSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. 3*c8dee2aaSAndroid Build Coastguard Worker 4*c8dee2aaSAndroid Build Coastguard Worker #ifndef Contour_DEFINED 5*c8dee2aaSAndroid Build Coastguard Worker #define Contour_DEFINED 6*c8dee2aaSAndroid Build Coastguard Worker 7*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h" 8*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h" 9*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkSpan_impl.h" 10*c8dee2aaSAndroid Build Coastguard Worker 11*c8dee2aaSAndroid Build Coastguard Worker #include <limits.h> 12*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef> 13*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint> 14*c8dee2aaSAndroid Build Coastguard Worker #include <iterator> 15*c8dee2aaSAndroid Build Coastguard Worker #include <vector> 16*c8dee2aaSAndroid Build Coastguard Worker 17*c8dee2aaSAndroid Build Coastguard Worker class SkPath; 18*c8dee2aaSAndroid Build Coastguard Worker namespace myers { class Segment; } 19*c8dee2aaSAndroid Build Coastguard Worker struct SkPoint; 20*c8dee2aaSAndroid Build Coastguard Worker 21*c8dee2aaSAndroid Build Coastguard Worker namespace contour { 22*c8dee2aaSAndroid Build Coastguard Worker struct Point { 23*c8dee2aaSAndroid Build Coastguard Worker int32_t x; 24*c8dee2aaSAndroid Build Coastguard Worker int32_t y; 25*c8dee2aaSAndroid Build Coastguard Worker }; 26*c8dee2aaSAndroid Build Coastguard Worker 27*c8dee2aaSAndroid Build Coastguard Worker class Contour { 28*c8dee2aaSAndroid Build Coastguard Worker public: 29*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const Point> points; 30*c8dee2aaSAndroid Build Coastguard Worker SkIRect bounds; 31*c8dee2aaSAndroid Build Coastguard Worker }; 32*c8dee2aaSAndroid Build Coastguard Worker 33*c8dee2aaSAndroid Build Coastguard Worker class Contours { 34*c8dee2aaSAndroid Build Coastguard Worker class Iterator { 35*c8dee2aaSAndroid Build Coastguard Worker public: 36*c8dee2aaSAndroid Build Coastguard Worker using value_type = Contour; 37*c8dee2aaSAndroid Build Coastguard Worker using difference_type = ptrdiff_t; 38*c8dee2aaSAndroid Build Coastguard Worker using pointer = value_type*; 39*c8dee2aaSAndroid Build Coastguard Worker using reference = value_type; 40*c8dee2aaSAndroid Build Coastguard Worker using iterator_category = std::input_iterator_tag; Iterator(const Contours & contours,size_t index)41*c8dee2aaSAndroid Build Coastguard Worker Iterator(const Contours& contours, size_t index) 42*c8dee2aaSAndroid Build Coastguard Worker : fContours{contours} 43*c8dee2aaSAndroid Build Coastguard Worker , fIndex{index} { } Iterator(const Iterator & that)44*c8dee2aaSAndroid Build Coastguard Worker Iterator(const Iterator& that) : Iterator{ that.fContours, that.fIndex } { } 45*c8dee2aaSAndroid Build Coastguard Worker Iterator& operator++() { ++fIndex; return *this; } 46*c8dee2aaSAndroid Build Coastguard Worker Iterator operator++(int) { Iterator tmp(*this); operator++(); return tmp; } 47*c8dee2aaSAndroid Build Coastguard Worker bool operator==(const Iterator& rhs) const { return fIndex == rhs.fIndex; } 48*c8dee2aaSAndroid Build Coastguard Worker bool operator!=(const Iterator& rhs) const { return fIndex != rhs.fIndex; } 49*c8dee2aaSAndroid Build Coastguard Worker value_type operator*() { return fContours[fIndex]; } 50*c8dee2aaSAndroid Build Coastguard Worker friend difference_type operator-(Iterator lhs, Iterator rhs) { 51*c8dee2aaSAndroid Build Coastguard Worker return lhs.fIndex - rhs.fIndex; 52*c8dee2aaSAndroid Build Coastguard Worker } 53*c8dee2aaSAndroid Build Coastguard Worker 54*c8dee2aaSAndroid Build Coastguard Worker private: 55*c8dee2aaSAndroid Build Coastguard Worker const Contours& fContours; 56*c8dee2aaSAndroid Build Coastguard Worker size_t fIndex = 0; 57*c8dee2aaSAndroid Build Coastguard Worker }; 58*c8dee2aaSAndroid Build Coastguard Worker public: 59*c8dee2aaSAndroid Build Coastguard Worker static constexpr double kScaleFactor = 1024; 60*c8dee2aaSAndroid Build Coastguard Worker static Contours Make(SkPath path); 61*c8dee2aaSAndroid Build Coastguard Worker 62*c8dee2aaSAndroid Build Coastguard Worker Contour operator[](size_t i) const { 63*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(i < fContours.size()); 64*c8dee2aaSAndroid Build Coastguard Worker auto& [bounds, end] = fContours[i]; 65*c8dee2aaSAndroid Build Coastguard Worker int32_t start = i == 0 ? 0 : fContours[i-1].end; 66*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const Point> points{&fPoints[start], end - start}; 67*c8dee2aaSAndroid Build Coastguard Worker return {points, bounds}; 68*c8dee2aaSAndroid Build Coastguard Worker } 69*c8dee2aaSAndroid Build Coastguard Worker begin()70*c8dee2aaSAndroid Build Coastguard Worker Iterator begin() const { 71*c8dee2aaSAndroid Build Coastguard Worker return Iterator{*this, 0}; 72*c8dee2aaSAndroid Build Coastguard Worker } 73*c8dee2aaSAndroid Build Coastguard Worker end()74*c8dee2aaSAndroid Build Coastguard Worker Iterator end() const { 75*c8dee2aaSAndroid Build Coastguard Worker return Iterator{*this, fContours.size()}; 76*c8dee2aaSAndroid Build Coastguard Worker } 77*c8dee2aaSAndroid Build Coastguard Worker size()78*c8dee2aaSAndroid Build Coastguard Worker size_t size() const { 79*c8dee2aaSAndroid Build Coastguard Worker return fContours.size(); 80*c8dee2aaSAndroid Build Coastguard Worker } 81*c8dee2aaSAndroid Build Coastguard Worker empty()82*c8dee2aaSAndroid Build Coastguard Worker bool empty() const { 83*c8dee2aaSAndroid Build Coastguard Worker return fContours.empty(); 84*c8dee2aaSAndroid Build Coastguard Worker } 85*c8dee2aaSAndroid Build Coastguard Worker 86*c8dee2aaSAndroid Build Coastguard Worker std::vector<myers::Segment> segments() const; 87*c8dee2aaSAndroid Build Coastguard Worker 88*c8dee2aaSAndroid Build Coastguard Worker private: 89*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkIRect kEmptyRect = SkIRect::MakeLTRB(INT_MAX, INT_MAX, INT_MIN, INT_MIN); 90*c8dee2aaSAndroid Build Coastguard Worker struct CompactContour { 91*c8dee2aaSAndroid Build Coastguard Worker SkIRect bounds; 92*c8dee2aaSAndroid Build Coastguard Worker int32_t end; 93*c8dee2aaSAndroid Build Coastguard Worker }; 94*c8dee2aaSAndroid Build Coastguard Worker 95*c8dee2aaSAndroid Build Coastguard Worker static Point RoundSkPoint(SkPoint p); 96*c8dee2aaSAndroid Build Coastguard Worker bool currentContourIsEmpty() const; 97*c8dee2aaSAndroid Build Coastguard Worker void addPointToCurrentContour(SkPoint p); 98*c8dee2aaSAndroid Build Coastguard Worker void moveToStartOfContour(SkPoint p); 99*c8dee2aaSAndroid Build Coastguard Worker void closeContourIfNeeded(); 100*c8dee2aaSAndroid Build Coastguard Worker 101*c8dee2aaSAndroid Build Coastguard Worker Point fContourStart; 102*c8dee2aaSAndroid Build Coastguard Worker SkIRect fContourBounds = kEmptyRect; 103*c8dee2aaSAndroid Build Coastguard Worker 104*c8dee2aaSAndroid Build Coastguard Worker std::vector<Point> fPoints; 105*c8dee2aaSAndroid Build Coastguard Worker std::vector<CompactContour> fContours; 106*c8dee2aaSAndroid Build Coastguard Worker }; 107*c8dee2aaSAndroid Build Coastguard Worker } // namespace contour 108*c8dee2aaSAndroid Build Coastguard Worker 109*c8dee2aaSAndroid Build Coastguard Worker #endif // Contour_DEFINED 110