// 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 #include #include #include #include class SkPath; namespace myers { class Segment; } struct SkPoint; namespace contour { struct Point { int32_t x; int32_t y; }; class Contour { public: SkSpan 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 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 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 fPoints; std::vector fContours; }; } // namespace contour #endif // Contour_DEFINED