/* * Copyright 2006 The Android Open Source Project * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file.
*/
class SkRegionPriv { public: inlinestatic constexpr int kRunTypeSentinel = 0x7FFFFFFF; typedef SkRegion::RunType RunType; typedef SkRegion::RunHead RunHead;
// Call the function with each span, in Y -> X ascending order. // We pass a rect, but we will still ensure the span Y->X ordering, so often the height // of the rect may be 1. It should never be empty. staticvoid VisitSpans(const SkRegion& rgn, const std::function<void(const SkIRect&)>&);
/** * Number of spans with different Y values. This does not count the initial * Top value, nor does it count the final Y-Sentinel value. In the logical * case of a rectangle, this would return 1, and an empty region would * return 0.
*/ int getYSpanCount() const { return fYSpanCount;
}
/** * Number of intervals in the entire region. This equals the number of * rects that would be returned by the Iterator. In the logical case of * a rect, this would return 1, and an empty region would return 0.
*/ int getIntervalCount() const { return fIntervalCount;
}
RunHead* head = (RunHead*)sk_malloc_throw(size);
head->fRefCnt = 1;
head->fRunCount = count; // these must be filled in later, otherwise we will be invalid
head->fYSpanCount = 0;
head->fIntervalCount = 0; return head;
}
static RunHead* Alloc(int count, int yspancount, int intervalCount) { if (yspancount <= 0 || intervalCount <= 1) { return nullptr;
}
RunHead* head = Alloc(count); if (!head) { return nullptr;
}
head->fYSpanCount = yspancount;
head->fIntervalCount = intervalCount; return head;
}
RunHead* ensureWritable() {
RunHead* writable = this; if (fRefCnt > 1) { // We need to alloc & copy the current region before decrease // the refcount because it could be freed in the meantime.
writable = Alloc(fRunCount, fYSpanCount, fIntervalCount);
memcpy(writable->writable_runs(), this->readonly_runs(),
fRunCount * sizeof(RunType));
// fRefCount might have changed since we last checked. // If we own the last reference at this point, we need to // free the memory. if (--fRefCnt == 0) {
sk_free(this);
}
} return writable;
}
/** * Given a scanline (including its Bottom value at runs[0]), return the next * scanline. Asserts that there is one (i.e. runs[0] < Sentinel)
*/ static SkRegion::RunType* SkipEntireScanline(const SkRegion::RunType runs[]) { // we are not the Y Sentinel
SkASSERT(runs[0] < SkRegion_kRunTypeSentinel);
// skip the entire line [B N [L R] S]
runs += 1 + 1 + intervals * 2 + 1; returnconst_cast<SkRegion::RunType*>(runs);
}
/** * Return the scanline that contains the Y value. This requires that the Y * value is already known to be contained within the bounds of the region, * and so this routine never returns nullptr. * * It returns the beginning of the scanline, starting with its Bottom value.
*/
SkRegion::RunType* findScanline(int y) const { const RunType* runs = this->readonly_runs();
// if the top-check fails, we didn't do a quick check on the bounds
SkASSERT(y >= runs[0]);
runs += 1; // skip top-Y for (;;) { int bottom = runs[0]; // If we hit this, we've walked off the region, and our bounds check // failed.
SkASSERT(bottom < SkRegion_kRunTypeSentinel); if (y < bottom) { break;
}
runs = SkipEntireScanline(runs);
} returnconst_cast<SkRegion::RunType*>(runs);
}
// Copy src runs into us, computing interval counts and bounds along the way void computeRunBounds(SkIRect* bounds) {
RunType* runs = this->writable_runs();
bounds->fTop = *runs++;
int bot; int ySpanCount = 0; int intervalCount = 0; int left = SK_MaxS32; int rite = SK_MinS32;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.