36 for (
int i = 0; i <
count; ++i) {
50 bool init(
int maxHeight,
int maxTransitions,
bool pathIsInverse);
53 if (fCurrScanline !=
nullptr) {
54 fCurrScanline->fXCount = (SkRegion::RunType)((
int)(fCurrXPtr - fCurrScanline->firstX()));
55 if (!this->collapsWithPrev()) {
56 fCurrScanline = fCurrScanline->nextScanline();
63 void copyToRgn(SkRegion::RunType runs[])
const;
72 SkDebugf(
"SkRgnBuilder: Top = %d\n", fTop);
73 Scanline* line = (Scanline*)fStorage;
74 while (line < fCurrScanline) {
75 SkDebugf(
"SkRgnBuilder::Scanline: LastY=%d, fXCount=%d", line->fLastY, line->fXCount);
76 for (
int i = 0; i < line->fXCount; i++) {
99 SkRegion::RunType fLastY;
100 SkRegion::RunType fXCount;
102 SkRegion::RunType* firstX() {
return (SkRegion::RunType*)(
this + 1); }
103 Scanline* nextScanline() {
105 return (Scanline*)((SkRegion::RunType*)(
this + 1) + fXCount + 1);
108 SkRegion::RunType* fStorage;
109 Scanline* fCurrScanline;
110 Scanline* fPrevScanline;
112 SkRegion::RunType* fCurrXPtr;
113 SkRegion::RunType fTop;
117 bool collapsWithPrev() {
118 if (fPrevScanline !=
nullptr &&
119 fPrevScanline->fLastY + 1 == fCurrScanline->fLastY &&
120 fPrevScanline->fXCount == fCurrScanline->fXCount &&
121 sk_memeq32(fPrevScanline->firstX(), fCurrScanline->firstX(), fCurrScanline->fXCount))
124 fPrevScanline->fLastY = fCurrScanline->fLastY;
132 : fStorage(nullptr) {
140 if ((maxHeight | maxTransitions) < 0) {
150 maxTransitions = safe.
addInt(maxTransitions, 2);
162 if (!safe || !SkTFitsIn<int32_t>(
count)) {
167 fStorage = (SkRegion::RunType*)
sk_malloc_canfail(fStorageCount,
sizeof(SkRegion::RunType));
168 if (
nullptr == fStorage) {
172 fCurrScanline =
nullptr;
173 fPrevScanline =
nullptr;
178 if (fCurrScanline ==
nullptr) {
179 fTop = (SkRegion::RunType)(
y);
180 fCurrScanline = (Scanline*)fStorage;
181 fCurrScanline->fLastY = (SkRegion::RunType)(
y);
182 fCurrXPtr = fCurrScanline->firstX();
186 if (
y > fCurrScanline->fLastY) {
188 fCurrScanline->fXCount = (SkRegion::RunType)((
int)(fCurrXPtr - fCurrScanline->firstX()));
190 int prevLastY = fCurrScanline->fLastY;
191 if (!this->collapsWithPrev()) {
192 fPrevScanline = fCurrScanline;
193 fCurrScanline = fCurrScanline->nextScanline();
196 if (
y - 1 > prevLastY) {
197 fCurrScanline->fLastY = (SkRegion::RunType)(
y - 1);
198 fCurrScanline->fXCount = 0;
199 fCurrScanline = fCurrScanline->nextScanline();
202 fCurrScanline->fLastY = (SkRegion::RunType)(
y);
203 fCurrXPtr = fCurrScanline->firstX();
207 if (fCurrXPtr > fCurrScanline->firstX() && fCurrXPtr[-1] ==
x) {
208 fCurrXPtr[-1] = (SkRegion::RunType)(
x +
width);
210 fCurrXPtr[0] = (SkRegion::RunType)(
x);
211 fCurrXPtr[1] = (SkRegion::RunType)(
x +
width);
214 SkASSERT(fCurrXPtr - fStorage < fStorageCount);
218 if (fCurrScanline ==
nullptr) {
222 const SkRegion::RunType* line = fStorage;
223 const SkRegion::RunType* stop = (
const SkRegion::RunType*)fCurrScanline;
225 return 2 + (
int)(stop - line);
231 SkASSERT((
const SkRegion::RunType*)fCurrScanline - fStorage == 5);
233 Scanline* line = (Scanline*)fStorage;
236 r->
setLTRB(line->firstX()[0], fTop, line->firstX()[1], line->fLastY + 1);
241 SkASSERT((
const SkRegion::RunType*)fCurrScanline - fStorage > 4);
243 Scanline* line = (Scanline*)fStorage;
244 const Scanline* stop = fCurrScanline;
248 *runs++ = (SkRegion::RunType)(line->fLastY + 1);
249 int count = line->fXCount;
250 *runs++ =
count >> 1;
252 memcpy(runs, line->firstX(),
count *
sizeof(SkRegion::RunType));
256 line = line->nextScanline();
257 }
while (line < stop);
263 static const uint8_t gPathVerbToInitialLastIndex[] = {
272 SkASSERT((
unsigned)verb < std::size(gPathVerbToInitialLastIndex));
273 return gPathVerbToInitialLastIndex[verb];
277 static const uint8_t gPathVerbToMaxEdges[] = {
286 SkASSERT((
unsigned)verb < std::size(gPathVerbToMaxEdges));
287 return gPathVerbToMaxEdges[verb];
305 for (
int i = 1; i <= lastIndex; i++) {
306 if (top > pts[i].fY) {
308 }
else if (bot < pts[i].fY) {
313 if (top > pts[0].fY) {
315 }
else if (bot < pts[0].fY) {
331 if (path.isInverseFillType()) {
332 return dst->set(
clip);
334 return dst->setEmpty();
341 if (
clip.
isEmpty() || !path.isFinite() || path.isEmpty()) {
352 if (
clip.isComplex()) {
362 static constexpr int kTileSize = 32767 >> 1;
363 const SkIRect pathBounds = path.getBounds().roundOut();
370 for (int64_t top = clipBounds.
fTop; top < clipBounds.
fBottom; top += kTileSize) {
371 int64_t bot = std::min(top + kTileSize, (int64_t)clipBounds.
fBottom);
373 int64_t
right = std::min(
left + kTileSize, (int64_t)clipBounds.
fRight);
397 int pathTop, pathBot;
399 if (0 == pathTransitions) {
403 int clipTop, clipBot;
404 int clipTransitions =
clip.count_runtype_values(&clipTop, &clipBot);
406 int top = std::max(pathTop, clipTop);
407 int bot = std::min(pathBot, clipBot);
414 if (!builder.init(bot - top,
415 std::max(pathTransitions, clipTransitions),
416 path.isInverseFillType())) {
424 int count = builder.computeRunCount();
427 }
else if (count == kRectRegionRuns) {
458 void set(
int x,
int y0,
int y1) {
469 return std::min(
fY0,
fY1);
476 if (
base->fFlags == Edge::kCompleteLink) {
487 if ((
base->fFlags & Edge::kY0Link) == 0) {
490 if ((e->fFlags & Edge::kY1Link) == 0 && y0 == e->fY1) {
493 e->fFlags =
SkToU8(e->fFlags | Edge::kY1Link);
500 if ((
base->fFlags & Edge::kY1Link) == 0) {
503 if ((e->fFlags & Edge::kY0Link) == 0 && y1 == e->fY0) {
506 e->fFlags =
SkToU8(e->fFlags | Edge::kY0Link);
512 base->fFlags = Edge::kCompleteLink;
516 while (0 == edge->
fFlags) {
539 }
while (edge !=
base);
547 return (
a.fX ==
b.fX) ?
a.top() <
b.top() :
a.fX <
b.fX;
574 edge[0].
set(r.fLeft, r.fBottom, r.fTop);
575 edge[1].
set(r.fRight, r.fTop, r.fBottom);
584 for (e =
start; e != stop; e++) {
589 for (e =
start; e != stop; e++) {
591 SkASSERT(e->fFlags == Edge::kCompleteLink);
595 path->incReserve(
count << 1);
static float prev(float f)
#define SkDEBUGFAIL(message)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
SK_API void sk_free(void *)
static void * sk_malloc_canfail(size_t size)
static constexpr int16_t SK_MaxS16
static constexpr int16_t SK_MinS16
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
static bool left(const SkPoint &p0, const SkPoint &p1)
static bool right(const SkPoint &p0, const SkPoint &p1)
static constexpr int SkRegion_kRunTypeSentinel
static unsigned verb_to_initial_last_index(unsigned verb)
static unsigned verb_to_max_edges(unsigned verb)
static void find_link(Edge *base, Edge *stop)
static bool sk_memeq32(const int32_t *SK_RESTRICT a, const int32_t *SK_RESTRICT b, int count)
static int count_path_runtype_values(const SkPath &path, int *itop, int *ibot)
static bool check_inverse_on_empty_return(SkRegion *dst, const SkPath &path, const SkRegion &clip)
static int extract_path(Edge *edge, Edge *stop, SkPath *path)
#define SkScalarRoundToInt(x)
constexpr int32_t SkToS32(S x)
constexpr uint8_t SkToU8(S x)
static void dump(const float m[20], SkYUVColorSpace cs, bool rgb2yuv)
Type::kYUV Type::kRGBA() int(0.7 *637)
static SkMatrix Translate(SkScalar dx, SkScalar dy)
Verb next(SkPoint pts[4])
const SkRect & getBounds() const
SkRegion::RunType RunType
const SkIRect & rect() const
void translate(int dx, int dy)
bool getBoundaryPath(SkPath *path) const
@ kUnion_Op
target unioned with operand
@ kIntersect_Op
target intersected with operand
const SkIRect & getBounds() const
bool op(const SkIRect &rect, Op op)
bool setRect(const SkIRect &rect)
bool setPath(const SkPath &path, const SkRegion &clip)
void swap(SkRegion &other)
int computeRunCount() const
void copyToRgn(SkRegion::RunType runs[]) const
bool init(int maxHeight, int maxTransitions, bool pathIsInverse)
void blitH(int x, int y, int width) override
Blit a horizontal run of one or more pixels.
void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override
void copyToRect(SkIRect *) const
size_t add(size_t x, size_t y)
size_t mul(size_t x, size_t y)
static bool PathRequiresTiling(const SkIRect &bounds)
static void FillPath(const SkPath &, const SkIRect &, SkBlitter *)
bool operator()(const Edge &a, const Edge &b) const
void set(int x, int y0, int y1)
SkRegionPriv::RunType fY0
SkRegionPriv::RunType fY1
static bool Intersects(const SkIRect &a, const SkIRect &b)
int32_t fBottom
larger y-axis bounds
int32_t fTop
smaller y-axis bounds
void offset(int32_t dx, int32_t dy)
int32_t fLeft
smaller x-axis bounds
void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom)
int32_t fRight
larger x-axis bounds
void set(const SkIRect &src)
SkRegion::RunType * writable_runs()
static RunHead * Alloc(int count)
void computeRunBounds(SkIRect *bounds)