blob: 06b1db5fa718482847460b48f779e2a37aa730e5 [file] [log] [blame]
// 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