38#define SkRegion_gEmptyRunHeadPtr ((SkRegionPriv::RunHead*)-1)
39#define SkRegion_gRectRunHeadPtr nullptr
54 int count()
const {
return fCount; }
57 SkASSERT((
unsigned)i < (
unsigned)fCount);
85 int intervals = runs[-1];
95 runs += intervals * 2 + 1;
99bool SkRegion::RunsAreARect(
const SkRegion::RunType runs[],
int count,
104 if (
count == kRectRegionRuns) {
115 bounds->setLTRB(runs[3], runs[0], runs[4], runs[1]);
142void SkRegion::freeRuns() {
145 if (--fRunHead->
fRefCnt == 0) {
151void SkRegion::allocateRuns(
int count,
int ySpanCount,
int intervalCount) {
155void SkRegion::allocateRuns(
int count) {
159void SkRegion::allocateRuns(
const RunHead& head) {
161 head.getYSpanCount(),
162 head.getIntervalCount());
173 swap(fRunHead, other.fRunHead);
179 }
else if (this->
isRect()) {
209 fRunHead = src.fRunHead;
220 return this->
op(tmp, rgn,
op);
226 return this->
op(rgn, tmp,
op);
231#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
233char* SkRegion::toString() {
234 Iterator iter(*
this);
236 while (!iter.done()) {
241 const int max = (
count*((11*4)+5))+11+1;
248 while (!iter.done()) {
249 const SkIRect& r = iter.rect();
261int SkRegion::count_runtype_values(
int* itop,
int* ibot)
const {
279bool SkRegion::setRuns(RunType runs[],
int count) {
291 if (count > kRectRegionRuns) {
292 RunType* stop = runs +
count;
333 this->allocateRuns(
count);
353void SkRegion::BuildRectRuns(
const SkIRect& bounds,
354 RunType runs[kRectRegionRuns]) {
404 return runs + 2 + runs[1] * 2 + 1;
467const SkRegion::RunType* SkRegion::getRuns(RunType tmpStorage[],
468 int* intervals)
const {
470 const RunType* runs = tmpStorage;
475 }
else if (this->
isRect()) {
476 BuildRectRuns(
fBounds, tmpStorage);
540 bool weAreARect = this->
isRect();
541 bool theyAreARect = rgn.
isRect();
543 if (weAreARect && theyAreARect) {
583 ah->
fRunCount *
sizeof(SkRegion::RunType));
599 if (
nullptr == dst) {
614 dst->fRunHead = dst->fRunHead->ensureWritable();
617 tmp.allocateRuns(*fRunHead);
623 dst->fBounds.offset(dx, dy);
626 RunType* druns = dst->fRunHead->writable_runs();
628 *druns++ = (SkRegion::RunType)(*sruns++ + dy);
630 int bottom = *sruns++;
634 *druns++ = (SkRegion::RunType)(bottom + dy);
641 *druns++ = (SkRegion::RunType)(
x + dx);
642 *druns++ = (SkRegion::RunType)(*sruns++ + dx);
649 SkASSERT(druns - dst->fRunHead->readonly_runs() == dst->fRunHead->fRunCount);
662 for (
int i = 1; i <
count; i++) {
672#pragma warning ( push )
673#pragma warning ( disable : 4701 )
682 #define assert_valid_pair(left, rite)
714 bool a_flush =
false;
715 bool b_flush =
false;
722 if (a_left < b_left) {
725 if (a_rite <= b_left) {
729 rite = a_left = b_left;
731 }
else if (b_left < a_left) {
734 if (b_rite <= a_left) {
738 rite = b_left = a_left;
743 if (a_rite <= b_rite) {
744 rite = b_left = a_rite;
747 if (b_rite <= a_rite) {
748 rite = a_left = b_rite;
792 bool firstInterval =
true;
794 rec.
init(a_runs, b_runs);
796 while (!rec.
done()) {
800 int rite = rec.
fRite;
805 if (firstInterval || *(dst - 1) <
left) {
808 firstInterval =
false;
815 SkASSERT(dst < &(*array)[array->count() - 1]);
817 return dst - &(*array)[0];
821#pragma warning ( pop )
851 int start = fPrevDst + fPrevLen + 2;
855 SkASSERT(len >= 1 && (len & 1) == 1);
860 if (fPrevLen == len &&
861 (1 == len || !memcmp(&(*fArray)[fPrevDst],
867 if (len == 1 && fPrevLen == 0) {
879 (*fArray)[fStartDst] = fTop;
883 return (
int)(fPrevDst - fStartDst + fPrevLen + 1);
886 bool isEmpty()
const {
return 0 == fPrevLen; }
899#define QUICK_EXIT_TRUE_COUNT (-1)
919 int a_top = *a_runs++;
920 int a_bot = *a_runs++;
921 int b_top = *b_runs++;
922 int b_bot = *b_runs++;
934 RgnOper oper(std::min(a_top, b_top), dst, op);
943 bool a_flush =
false;
944 bool b_flush =
false;
949 if (a_bot <= b_top) {
955 }
else if (b_top < a_top) {
958 if (b_bot <= a_top) {
968 if (a_bot <= b_bot) {
972 if (b_bot <= a_bot) {
979 oper.
addSpan(top, gSentinel, gSentinel);
983 if (quickExit && !oper.
isEmpty()) {
1008 return oper.
flush();
1022static int count_to_intervals(
int count) {
1024 return (
count - 4) >> 1;
1033 return result ?
result->setRect(rect) : !rect.isEmpty();
1040bool SkRegion::Oper(
const SkRegion& rgnaOrig,
const SkRegion& rgnbOrig, Op op,
1061 bool a_empty = rgna->
isEmpty();
1062 bool b_empty = rgnb->
isEmpty();
1063 bool a_rect = rgna->
isRect();
1064 bool b_rect = rgnb->
isRect();
1074 if (b_rect && rgnb->fBounds.containsNoEmptyCheck(rgna->fBounds)) {
1080 if ((a_empty | b_empty)
1081 || !
bounds.intersect(rgna->fBounds, rgnb->fBounds)) {
1084 if (a_rect & b_rect) {
1087 if (a_rect && rgna->fBounds.
contains(rgnb->fBounds)) {
1090 if (b_rect && rgnb->fBounds.
contains(rgna->fBounds)) {
1102 if (a_rect && rgna->fBounds.
contains(rgnb->fBounds)) {
1105 if (b_rect && rgnb->fBounds.
contains(rgna->fBounds)) {
1123 RunType tmpA[kRectRegionRuns];
1124 RunType tmpB[kRectRegionRuns];
1126 int a_intervals, b_intervals;
1127 const RunType* a_runs = rgna->getRuns(tmpA, &a_intervals);
1128 const RunType* b_runs = rgnb->getRuns(tmpB, &b_intervals);
1144 return SkRegion::Oper(rgna, rgnb,
op,
this);
1150 if (
nullptr == storage) {
1151 size_t size =
sizeof(int32_t);
1155 size += 2 *
sizeof(int32_t);
1156 size += fRunHead->
fRunCount *
sizeof(RunType);
1184 if (ySpanCount < 1 || intervalCount < 2) {
1189 sum = safeMath.
addInt(sum, ySpanCount);
1190 sum = safeMath.
addInt(sum, ySpanCount);
1191 sum = safeMath.
addInt(sum, ySpanCount);
1192 sum = safeMath.
addInt(sum, intervalCount);
1193 sum = safeMath.
addInt(sum, intervalCount);
1194 return safeMath && sum == runCount;
1204 int32_t intervalCount) {
1216 const int32_t*
const end = runs + runCount;
1217 SkIRect bounds = {0, 0, 0 ,0};
1219 rect.fTop = *runs++;
1223 if (rect.fTop != givenBounds.
fTop) {
1228 if (ySpanCount < 0) {
1231 rect.fBottom = *runs++;
1235 if (rect.fBottom > givenBounds.
fBottom) {
1238 if (rect.fBottom <= rect.fTop) {
1242 int32_t xIntervals = *runs++;
1244 if (xIntervals < 0 || xIntervals > intervalCount || runs + 1 + 2 * xIntervals >
end) {
1247 intervalCount -= xIntervals;
1248 bool firstInterval =
true;
1249 int32_t lastRight = 0;
1250 while (xIntervals-- > 0) {
1251 rect.fLeft = *runs++;
1252 rect.fRight = *runs++;
1255 rect.fLeft >= rect.fRight ||
1256 (!firstInterval && rect.fLeft <= lastRight)) {
1259 lastRight = rect.fRight;
1260 firstInterval =
false;
1266 rect.fTop = rect.fBottom;
1270 if (ySpanCount != 0 || intervalCount != 0 || givenBounds != bounds) {
1292 if (!
buffer.read(&tmp.fBounds,
sizeof(tmp.fBounds)) || tmp.fBounds.
isEmpty()) {
1298 int32_t ySpanCount, intervalCount;
1299 if (!
buffer.readS32(&ySpanCount) ||
1300 !
buffer.readS32(&intervalCount) ||
1305 tmp.fBounds, ySpanCount, intervalCount)) {
1308 tmp.allocateRuns(
count, ySpanCount, intervalCount);
1321bool SkRegion::isValid()
const {
1331 return fRunHead && fRunHead->
fRefCnt > 0 &&
1337void SkRegionPriv::Validate(
const SkRegion& rgn) {
SkASSERT(rgn.isValid()); }
1339void SkRegion::dump()
const {
1346 for (
int i = 0; i < fRunHead->
fRunCount; i++)
1376 fRect = rgn.fBounds;
1392 if (fRuns ==
nullptr) {
1397 const RunType* runs = fRuns;
1406 int intervals = runs[1];
1407 if (0 == intervals) {
1431 while (!fIter.
done()) {
1452 while (!
fIter.done()) {
1453 if (r.
fTop >= fClip.fBottom) {
1487 const SkRegion::RunType* runs = rgn.fRunHead->
findScanline(
y);
1491 if (runs[0] >=
right) {
1495 if (runs[1] <=
left) {
1515 if (fRuns ==
nullptr) {
1526 const SkRegion::RunType* runs = fRuns;
1528 if (runs[0] >= fRight) {
1536 *
left = std::max(fLeft, runs[0]);
1539 *
right = std::min(fRight, runs[1]);
1548 const std::function<
void(
const SkIRect&)>& visitor) {
1549 for (
int i = 0; i < pairCount; ++i) {
1550 visitor({ pairs[0],
y, pairs[1],
y + 1 });
1556 const std::function<
void(
const SkIRect&)>& visitor) {
1567 int pairCount = *p++;
1568 if (pairCount == 1) {
1569 visitor({ p[0], top, p[1], bot });
1571 }
else if (pairCount > 1) {
1573 for (
int y = top;
y < bot; ++
y) {
std::unique_ptr< SkLatticeIter > fIter
#define SkAssertResult(cond)
#define SkDEBUGFAIL(message)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
#define SK_INIT_TO_AVOID_WARNING
SK_API void sk_free(void *)
static void * sk_malloc_throw(size_t size)
static constexpr int32_t SK_MaxS32
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)
#define assert_sentinel(value, isSentinel)
static constexpr int SkRegion_kRunTypeSentinel
bool SkRegionValueIsSentinel(int32_t value)
static bool validate_run(const int32_t *runs, int runCount, const SkIRect &givenBounds, int32_t ySpanCount, int32_t intervalCount)
static int operate_on_span(const SkRegionPriv::RunType a_runs[], const SkRegionPriv::RunType b_runs[], RunArray *array, int dstOffset, int min, int max)
static bool scanline_intersects(const SkRegionPriv::RunType runs[], SkRegionPriv::RunType L, SkRegionPriv::RunType R)
static bool validate_run_count(int ySpanCount, int intervalCount, int runCount)
static bool setEmptyCheck(SkRegion *result)
static const SkRegionPriv::RunType * scanline_next(const SkRegionPriv::RunType runs[])
static void visit_pairs(int pairCount, int y, const int32_t pairs[], const std::function< void(const SkIRect &)> &visitor)
static int32_t pin_offset_s32(int32_t min, int32_t max, int32_t offset)
static int distance_to_sentinel(const SkRegionPriv::RunType *runs)
static int operate(const SkRegionPriv::RunType a_runs[], const SkRegionPriv::RunType b_runs[], RunArray *dst, SkRegion::Op op, bool quickExit)
static SkRegionPriv::RunType scanline_bottom(const SkRegionPriv::RunType runs[])
static bool scanline_contains(const SkRegionPriv::RunType runs[], SkRegionPriv::RunType L, SkRegionPriv::RunType R)
#define SkRegion_gEmptyRunHeadPtr
#define QUICK_EXIT_TRUE_COUNT
static SkRegionPriv::RunType * skip_intervals(const SkRegionPriv::RunType runs[])
constexpr int kRunArrayStackCount
static const struct @341 gOpMinMax[]
static bool setRegionCheck(SkRegion *result, const SkRegion &rgn)
#define assert_valid_pair(left, rite)
static bool isRunCountEmpty(int count)
#define SkRegion_gRectRunHeadPtr
static bool setRectCheck(SkRegion *result, const SkIRect &rect)
constexpr size_t SkToSizeT(S x)
constexpr int32_t SkToS32(S x)
constexpr int SkToInt(S x)
Type::kYUV Type::kRGBA() int(0.7 *637)
void addSpan(int bottom, const SkRegionPriv::RunType a_runs[], const SkRegionPriv::RunType b_runs[])
RgnOper(int top, RunArray *array, SkRegion::Op op)
void resizeToAtLeast(int count)
SkRegionPriv::RunType & operator[](int i)
static void VisitSpans(const SkRegion &rgn, const std::function< void(const SkIRect &)> &)
SkRegion::RunType RunType
Cliperator(const SkRegion ®ion, const SkIRect &clip)
const SkIRect & rect() const
void reset(const SkRegion ®ion)
bool next(int *left, int *right)
Spanerator(const SkRegion ®ion, int y, int left, int right)
void translate(int dx, int dy)
size_t readFromMemory(const void *buffer, size_t length)
bool contains(int32_t x, int32_t y) const
bool operator==(const SkRegion &other) const
@ kReverseDifference_Op
operand minus target
@ kUnion_Op
target unioned with operand
@ kReplace_Op
replace target with operand
@ kIntersect_Op
target intersected with operand
@ kDifference_Op
target minus operand
@ kXOR_Op
target exclusive or with operand
bool setRects(const SkIRect rects[], int count)
int computeRegionComplexity() const
SkRegion & operator=(const SkRegion ®ion)
const SkIRect & getBounds() const
bool op(const SkIRect &rect, Op op)
bool setRect(const SkIRect &rect)
void swap(SkRegion &other)
bool setRegion(const SkRegion ®ion)
size_t writeToMemory(void *buffer) const
bool intersects(const SkIRect &rect) const
void realloc(size_t count)
static const uint8_t buffer[]
static float max(float r, float g, float b)
static float min(float r, float g, float b)
Optional< SkRect > bounds
bool intersect(const SkIRect &r)
static bool Intersects(const SkIRect &a, const SkIRect &b)
int32_t fBottom
larger y-axis bounds
constexpr int32_t bottom() const
constexpr int32_t right() const
int32_t fTop
smaller y-axis bounds
int32_t fLeft
smaller x-axis bounds
int32_t fRight
larger x-axis bounds
SkScalar fBottom
larger y-axis bounds
constexpr SkRect makeOffset(float dx, float dy) const
bool intersect(const SkRect &r)
SkScalar fLeft
smaller x-axis bounds
SkScalar fRight
larger x-axis bounds
bool contains(SkScalar x, SkScalar y) const
void setLTRB(float left, float top, float right, float bottom)
SkScalar fTop
smaller y-axis bounds
SkRegion::RunType * writable_runs()
static RunHead * Alloc(int count)
const SkRegion::RunType * readonly_runs() const
void computeRunBounds(SkIRect *bounds)
RunHead * ensureWritable()
int getYSpanCount() const
int getIntervalCount() const
SkRegion::RunType * findScanline(int y) const
std::atomic< int32_t > fRefCnt
const SkRegionPriv::RunType * fB_runs
void init(const SkRegionPriv::RunType a_runs[], const SkRegionPriv::RunType b_runs[])
const SkRegionPriv::RunType * fA_runs