| // Copyright 2023 Google LLC |
| // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. |
| |
| #ifndef Contour_DEFINED |
| #define Contour_DEFINED |
| |
| #include "include/core/SkRect.h" |
| #include "include/private/base/SkAssert.h" |
| #include "include/private/base/SkSpan_impl.h" |
| |
| #include <limits.h> |
| #include <cstddef> |
| #include <cstdint> |
| #include <iterator> |
| #include <vector> |
| |
| class SkPath; |
| namespace myers { class Segment; } |
| struct SkPoint; |
| |
| namespace contour { |
| struct Point { |
| int32_t x; |
| int32_t y; |
| }; |
| |
| class Contour { |
| public: |
| SkSpan<const Point> points; |
| SkIRect bounds; |
| }; |
| |
| class Contours { |
| class Iterator { |
| public: |
| using value_type = Contour; |
| using difference_type = ptrdiff_t; |
| using pointer = value_type*; |
| using reference = value_type; |
| using iterator_category = std::input_iterator_tag; |
| Iterator(const Contours& contours, size_t index) |
| : fContours{contours} |
| , fIndex{index} { } |
| Iterator(const Iterator& that) : Iterator{ that.fContours, that.fIndex } { } |
| Iterator& operator++() { ++fIndex; return *this; } |
| Iterator operator++(int) { Iterator tmp(*this); operator++(); return tmp; } |
| bool operator==(const Iterator& rhs) const { return fIndex == rhs.fIndex; } |
| bool operator!=(const Iterator& rhs) const { return fIndex != rhs.fIndex; } |
| value_type operator*() { return fContours[fIndex]; } |
| friend difference_type operator-(Iterator lhs, Iterator rhs) { |
| return lhs.fIndex - rhs.fIndex; |
| } |
| |
| private: |
| const Contours& fContours; |
| size_t fIndex = 0; |
| }; |
| public: |
| static constexpr double kScaleFactor = 1024; |
| static Contours Make(SkPath path); |
| |
| Contour operator[](size_t i) const { |
| SkASSERT(i < fContours.size()); |
| auto& [bounds, end] = fContours[i]; |
| int32_t start = i == 0 ? 0 : fContours[i-1].end; |
| SkSpan<const Point> points{&fPoints[start], end - start}; |
| return {points, bounds}; |
| } |
| |
| Iterator begin() const { |
| return Iterator{*this, 0}; |
| } |
| |
| Iterator end() const { |
| return Iterator{*this, fContours.size()}; |
| } |
| |
| size_t size() const { |
| return fContours.size(); |
| } |
| |
| bool empty() const { |
| return fContours.empty(); |
| } |
| |
| std::vector<myers::Segment> segments() const; |
| |
| private: |
| static constexpr SkIRect kEmptyRect = SkIRect::MakeLTRB(INT_MAX, INT_MAX, INT_MIN, INT_MIN); |
| struct CompactContour { |
| SkIRect bounds; |
| int32_t end; |
| }; |
| |
| static Point RoundSkPoint(SkPoint p); |
| bool currentContourIsEmpty() const; |
| void addPointToCurrentContour(SkPoint p); |
| void moveToStartOfContour(SkPoint p); |
| void closeContourIfNeeded(); |
| |
| Point fContourStart; |
| SkIRect fContourBounds = kEmptyRect; |
| |
| std::vector<Point> fPoints; |
| std::vector<CompactContour> fContours; |
| }; |
| } // namespace contour |
| |
| #endif // Contour_DEFINED |