32class AutoAAClipValidate {
37 ~AutoAAClipValidate() {
45 #define AUTO_AACLIP_VALIDATE(clip) AutoAAClipValidate acv(clip)
47 #define AUTO_AACLIP_VALIDATE(clip)
52static constexpr int32_t
kMaxInt32 = 0x7FFFFFFF;
56static size_t compute_row_length(
const uint8_t row[],
int width) {
57 const uint8_t* origRow = row;
83 fBoundsRight =
bounds.fRight;
85 fRight =
bounds.fLeft + row[0];
96 bool done()
const {
return fDone; }
97 int left()
const {
return fLeft; }
98 int right()
const {
return fRight; }
99 U8CPU alpha()
const {
return fAlpha; }
103 if (fRight == fBoundsRight) {
129 Iter(
int y,
const uint8_t*
data,
const YOffset*
start,
const YOffset*
end)
134 , fBottom(
y +
start->fY + 1)
137 bool done()
const {
return fDone; }
138 int top()
const {
return fTop; }
139 int bottom()
const {
return fBottom; }
140 const uint8_t*
data()
const {
return fData; }
144 const YOffset*
prev = fCurrYOff;
145 const YOffset* curr =
prev + 1;
149 if (curr >= fStopYOff) {
154 fBottom += curr->fY -
prev->fY;
155 fData += curr->fOffset -
prev->fOffset;
162 const YOffset* fCurrYOff =
nullptr;
163 const YOffset* fStopYOff =
nullptr;
164 const uint8_t* fData =
nullptr;
181 return (YOffset*)((
char*)
this +
sizeof(
RunHead));
184 return (
const YOffset*)((
const char*)
this +
sizeof(
RunHead));
194 size_t size =
sizeof(
RunHead) + rowCount *
sizeof(YOffset) + dataSize;
196 head->fRefCnt.store(1);
197 head->fRowCount = rowCount;
198 head->fDataSize = dataSize;
218 YOffset* yoff =
head->yoffsets();
219 yoff->fY =
bounds.height() - 1;
221 uint8_t* row =
head->data();
234 if (!
clip.fRunHead) {
240 head->yoffsets() +
head->fRowCount);
270 Row* row = fRows.
begin();
271 Row* stop = fRows.
end();
283 void operateX(
int lastY, RowIter& iterA, RowIter& iterB,
AlphaProc proc);
298 row = this->flushRow(
true);
311 int gap =
x - row->fWidth;
313 AppendRun(
data, 0, gap);
319 row->fWidth +=
count;
326 this->addRun(
x,
y, alpha, 1);
327 this->flushRowH(fCurrRow);
335 this->addRun(
x,
y, 0xFF,
width);
339 this->flushRowH(fCurrRow);
357 if (leftAlpha == 0xFF) {
359 }
else if (leftAlpha > 0) {
360 this->addRun(
x++,
y, leftAlpha, 1);
365 if (rightAlpha == 0xFF) {
369 this->addRun(
x,
y, 0xFF,
width);
371 if (rightAlpha > 0 && rightAlpha < 255) {
372 this->addRun(
x +
width,
y, rightAlpha, 1);
379 this->flushRowH(fCurrRow);
388 this->flushRow(
false);
390 const Row* row = fRows.
begin();
391 const Row* stop = fRows.
end();
395 dataSize += row->fData->size();
400 return target->setEmpty();
409 YOffset* yoffset =
head->yoffsets();
411 uint8_t* baseData =
data;
419 yoffset->fY = row->fY - adjustY;
423 size_t n = row->fData->size();
424 memcpy(
data, row->fData->begin(), n);
434 return target->trimBounds();
440 for (
y = 0;
y < fRows.
size(); ++
y) {
441 const Row& row = fRows[
y];
442 SkDebugf(
"Y:%3d W:%3d", row.fY, row.fWidth);
446 const uint8_t* ptr =
data.begin();
447 for (
int x = 0;
x <
count;
x += 2) {
448 SkDebugf(
" [%3d:%02X]", ptr[0], ptr[1]);
458 for (
int i = 0;
i < fRows.
size(); ++
i) {
459 const Row& row = fRows[
i];
462 int count = row.fData->size();
463 const uint8_t* ptr = row.fData->begin();
466 for (
int x = 0;
x <
count;
x += 2) {
479 void flushRowH(Row* row) {
481 if (row->fWidth < fWidth) {
482 AppendRun(*row->fData, 0, fWidth - row->fWidth);
483 row->fWidth = fWidth;
487 Row* flushRow(
bool readyForAnother) {
491 this->flushRowH(&fRows[
count - 1]);
496 Row* curr = &fRows[
count - 1];
499 if (*
prev->fData == *curr->fData) {
501 if (readyForAnother) {
502 curr->fData->clear();
509 if (readyForAnother) {
515 if (readyForAnother) {
529 uint8_t* ptr =
data.append(2);
537void SkAAClip::Builder::operateX(
int lastY, RowIter& iterA, RowIter& iterB,
AlphaProc proc) {
538 auto advanceRowIter = [](RowIter& iter,
int& iterLeft,
int& iterRite,
int rite) {
539 if (rite == iterRite) {
541 iterLeft = iter.left();
542 iterRite = iter.right();
546 int leftA = iterA.left();
547 int riteA = iterA.right();
548 int leftB = iterB.left();
549 int riteB = iterB.right();
560 alphaA = iterA.alpha();
561 if (riteA <= leftB) {
564 rite = leftA = leftB;
566 }
else if (leftB < leftA) {
568 alphaB = iterB.alpha();
569 if (riteB <= leftA) {
572 rite = leftB = leftA;
576 rite = leftA = leftB =
std::min(riteA, riteB);
577 alphaA = iterA.alpha();
578 alphaB = iterB.alpha();
590 this->addRun(
left, lastY, proc(alphaA, alphaB), rite -
left);
594 advanceRowIter(iterA, leftA, riteA, rite);
595 advanceRowIter(iterB, leftB, riteB, rite);
596 }
while (!iterA.done() || !iterB.done());
612 int topA = iterA.top();
613 int botA = iterA.bottom();
615 int topB = iterB.top();
616 int botB = iterB.bottom();
618 auto advanceIter = [](Iter& iter,
int& iterTop,
int& iterBot,
int bot) {
619 if (bot == iterBot) {
623 iterBot = iter.bottom();
627#if defined(SK_BUILD_FOR_FUZZER)
628 if ((botA - topA) > 100000 || (botB - topB) > 100000) {
634 const uint8_t* rowA =
nullptr;
635 const uint8_t* rowB =
nullptr;
647 }
else if (topB < topA) {
657 bot = topA = topB =
std::min(botA, botB);
671 if (!rowA && !rowB) {
675 RowIter rowIterA(rowA, rowA ?
A.getBounds() : fBounds);
676 RowIter rowIterB(rowB, rowB ?
B.getBounds() : fBounds);
677 this->operateX(bot - 1, rowIterA, rowIterB, proc);
680 advanceIter(iterA, topA, botA, bot);
681 advanceIter(iterB, topB, botB, bot);
682 }
while (!iterA.done() || !iterB.done());
694 void checkForYGap(
int y) {
697 int gap =
y - fLastY;
699 fBuilder->addRun(fLeft,
y - 1, 0, fRight - fLeft);
708 fLeft =
builder->fBounds.fLeft;
709 fRight =
builder->fBounds.fRight;
716 fBuilder->fMinY = fMinY;
731 const SkAlpha alphas[2] = {alpha, 0};
732 const int16_t runs[2] = {1, 0};
736 fBuilder->addColumn(
x,
y, alpha,
height);
743 this->checkForYGap(
y);
751 this->checkForYGap(
y);
752 fBuilder->addAntiRectRun(
x,
y,
width,
height, leftAlpha, rightAlpha);
761 this->checkForYGap(
y);
762 fBuilder->addRun(
x,
y, 0xFF,
width);
767 this->checkForYGap(
y);
782 int localCount =
count;
791 if (
right > fRight) {
793 localCount -=
right - fRight;
798 fBuilder->addRun(localX,
y, *alpha, localCount);
819 void recordMinY(
int y) {
826 SK_ABORT(
"---- did not expect to get called here");
832 return this->finish(
target);
846 return this->finish(
target);
852 auto expandRowToMask = [](uint8_t*
dst,
const uint8_t* row,
int width) {
856 memset(
dst, row[1], n);
867 mask->
image() =
nullptr;
882 while (!iter.done()) {
884 expandRowToMask(
dst, iter.data(),
width);
886 }
while (++
y < iter.bottom());
894 if (
nullptr == fRunHead) {
900 const RunHead*
head = fRunHead;
904 const YOffset* yoff =
head->yoffsets();
905 const YOffset* ystop = yoff +
head->fRowCount;
910 int32_t prevOffset = -1;
911 while (yoff < ystop) {
915 SkASSERT(prevOffset < (int32_t)yoff->fOffset);
916 prevOffset = yoff->fOffset;
917 const uint8_t* row =
head->data() + yoff->fOffset;
918 size_t rowLength = compute_row_length(row,
fBounds.
width());
919 SkASSERT(yoff->fOffset + rowLength <= head->fDataSize);
927static void dump_one_row(
const uint8_t*
SK_RESTRICT row,
928 int width,
int leading_num) {
938 }
else if (val > 0) {
941 for (
int i = 0 ;
i < n ;
i++) {
955 while (!iter.done()) {
957 dump_one_row(iter.data(),
width, iter.bottom() - iter.top() + 1);
960 dump_one_row(iter.data(),
width, 0);
961 }
while (++
y < iter.bottom());
973 int* leftZ,
int* riteZ) {
1021 row[-2] = n - leftZ;
1049 }
while (riteZ > 0);
1055bool SkAAClip::trimLeftRight() {
1063 RunHead*
head = fRunHead;
1064 YOffset* yoff =
head->yoffsets();
1065 YOffset* stop = yoff +
head->fRowCount;
1071 int leftZeros =
width;
1072 int riteZeros =
width;
1073 while (yoff < stop) {
1077 if (
L < leftZeros) {
1080 if (
R < riteZeros) {
1083 if (0 == (leftZeros | riteZeros)) {
1091 if (
width == leftZeros) {
1098 fBounds.
fLeft += leftZeros;
1105 yoff =
head->yoffsets();
1106 while (yoff < stop) {
1107 uint8_t* row =
base + yoff->fOffset;
1126 }
while (
width > 0);
1131bool SkAAClip::trimTopBottom() {
1139 RunHead*
head = fRunHead;
1140 YOffset* yoff =
head->yoffsets();
1141 YOffset* stop = yoff +
head->fRowCount;
1142 const uint8_t*
base =
head->data();
1147 while (yoff < stop) {
1148 const uint8_t*
data =
base + yoff->fOffset;
1162 yoff =
head->yoffsets();
1163 int dy = yoff[
skip - 1].fY + 1;
1168 YOffset*
dst =
head->yoffsets();
1169 size_t size =
head->fRowCount *
sizeof(YOffset) +
head->fDataSize;
1179 base =
head->data();
1186 stop = yoff =
head->yoffsets() +
head->fRowCount;
1195 memmove(stop -
skip, stop,
head->fDataSize);
1214bool SkAAClip::trimBounds() {
1219 const RunHead*
head = fRunHead;
1220 const YOffset* yoff =
head->yoffsets();
1223 const YOffset& lastY = yoff[
head->fRowCount - 1];
1229 return this->trimTopBottom() && this->trimLeftRight();
1256 fRunHead =
src.fRunHead;
1291 if (
head->fRowCount != 1) {
1294 const YOffset* yoff =
head->yoffsets();
1299 const uint8_t* row =
head->data() + yoff->fOffset;
1302 if (row[1] != 0xFF) {
1309 }
while (
width > 0);
1332 auto appendXRun = [&xArray](uint8_t
value,
int count) {
1349 YOffset* currY =
nullptr;
1351 for (; !iter.
done(); iter.
next()) {
1357 if (bot > prevBot) {
1360 appendXRun(0,
bounds.width() - prevRight);
1364 if (top > prevBot) {
1366 currY->fY = top - 1;
1367 currY->fOffset = xArray.
size();
1368 appendXRun(0,
bounds.width());
1372 currY->fY = bot - 1;
1373 currY->fOffset = xArray.
size();
1379 appendXRun(0,
x - prevRight);
1382 appendXRun(0xFF,
w);
1387 appendXRun(0,
bounds.width() - prevRight);
1411 if (
path.isInverseFillType()) {
1414 path.getBounds().roundOut(&ibounds);
1456 return builder.applyClipOp(
this, other,
op);
1471 }
else if (pixelBounds ==
fBounds) {
1480 return this->
setRect(pixelBounds);
1484 return this->
op(clip,
op);
1517 return this->
op(rectClip,
op);
1525 if (
nullptr ==
dst) {
1536 dst->fRunHead = fRunHead;
1539 dst->fBounds.offset(
dx, dy);
1543void SkAAClip::freeRuns() {
1546 if (1 == fRunHead->
fRefCnt--) {
1552const uint8_t* SkAAClip::findRow(
int y,
int* lastYForRow)
const {
1560 const YOffset* yoff = fRunHead->
yoffsets();
1561 while (yoff->fY <
y) {
1567 *lastYForRow =
fBounds.
y() + yoff->fY;
1569 return fRunHead->
data() + yoff->fOffset;
1572const uint8_t* SkAAClip::findX(
const uint8_t
data[],
int x,
int* initialCount)
const {
1581 *initialCount = n -
x;
1600 const uint8_t* row = this->findRow(top, &lastY);
1601 if (lastY < bottom) {
1609 while (0xFF == row[1]) {
1610 if (
count >= rectWidth) {
1626 int n = initialCount;
1653void SkAAClipBlitter::ensureRunsAndAA() {
1654 if (
nullptr == fScanlineScratch) {
1656 int count = fAAClipBounds.width() + 1;
1660 fRuns = (int16_t*)fScanlineScratch;
1670 const uint8_t* row = fAAClip->findRow(
y);
1672 row = fAAClip->findX(row,
x, &initialCount);
1674 if (initialCount >=
width) {
1679 if (0xFF == alpha) {
1685 this->ensureRunsAndAA();
1688 fBlitter->blitAntiH(
x,
y, fAA, fRuns);
1698 int srcN = srcRuns[0];
1712 dstAA[0] = newAlpha;
1715 if (0 == (srcN -= minN)) {
1724 if (0 == (rowN -= minN)) {
1736 const int16_t runs[]) {
1738 const uint8_t* row = fAAClip->findRow(
y);
1740 row = fAAClip->findX(row,
x, &initialCount);
1742 this->ensureRunsAndAA();
1744 merge(row, initialCount, aa, runs, fAA, fRuns, fAAClipBounds.width());
1745 fBlitter->blitAntiH(
x,
y, fAA, fRuns);
1749 if (fAAClip->quickContains(
x,
y,
x + 1,
y +
height)) {
1750 fBlitter->blitV(
x,
y,
height, alpha);
1756 const uint8_t* row = fAAClip->findRow(
y, &lastY);
1757 int dy = lastY -
y + 1;
1763 row = fAAClip->findX(row,
x);
1766 fBlitter->blitV(
x,
y, dy, newAlpha);
1789 int initialRowCount,
void*
dst);
1812template <
typename T>
1821 unsigned rowA = row[1];
1824 }
else if (0 == rowA) {
1827 for (
int i = 0;
i < n; ++
i) {
1832 if (0 == (srcN -= n)) {
1852 return mergeT<uint8_t> ;
1854 return mergeT<uint16_t>;
1865 return -bitInAByte >> 8;
1878 const size_t dstRB = dstMask->
fRowBytes;
1880 const int wholeBytes =
width >> 3;
1881 const int leftOverBits =
width & 7;
1885 for (
int i = 0;
i < wholeBytes; ++
i) {
1886 int srcByte =
src[
i];
1898 int srcByte =
src[wholeBytes];
1899 for (
int x = 0;
x < leftOverBits; ++
x) {
1912 if (fAAClip->quickContains(
clip)) {
1913 fBlitter->blitMask(origMask,
clip);
1917 const SkMask* mask = &origMask;
1926 grayMask.
image() =
reinterpret_cast<uint8_t*
>(
1933 this->ensureRunsAndAA();
1948 rowMask.
image() = (uint8_t*)fScanlineScratch;
1951 const int stopY =
y +
clip.height();
1955 const uint8_t* row = fAAClip->findRow(
y, &localStopY);
1957 localStopY =
std::min(localStopY + 1, stopY);
1960 row = fAAClip->findX(row,
clip.fLeft, &initialCount);
1965 fBlitter->blitMask(rowMask, rowMask.
fBounds);
1966 src = (
const void*)((
const char*)
src + srcRB);
1967 }
while (++
y < localStopY);
1968 }
while (
y < stopY);
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
sk_bzero(glyphs, sizeof(glyphs))
static float next(float f)
static float prev(float f)
static void count_left_right_zeros(const uint8_t *row, int width, int *leftZ, int *riteZ)
static bool row_is_all_zeros(const uint8_t *row, int width)
static void small_memcpy(void *dst, const void *src, size_t n)
static U8CPU bit2byte(int bitInAByte)
static MergeAAProc find_merge_aa_proc(SkMask::Format format)
void mergeT(const void *inSrc, int srcN, const uint8_t *SK_RESTRICT row, int rowN, void *inDst)
static void merge(const uint8_t *SK_RESTRICT row, int rowN, const SkAlpha *SK_RESTRICT srcAA, const int16_t *SK_RESTRICT srcRuns, SkAlpha *SK_RESTRICT dstAA, int16_t *SK_RESTRICT dstRuns, int width)
static uint8_t mergeOne(uint8_t value, unsigned alpha)
#define AUTO_AACLIP_VALIDATE(clip)
static void upscaleBW2A8(SkMask *dstMask, const SkMask &srcMask)
void(* MergeAAProc)(const void *src, int width, const uint8_t *row, int initialRowCount, void *dst)
static void expandToRuns(const uint8_t *SK_RESTRICT data, int initialCount, int width, int16_t *SK_RESTRICT runs, SkAlpha *SK_RESTRICT aa)
static int trim_row_left_right(uint8_t *row, int width, int leftZ, int riteZ)
static void small_bzero(void *dst, size_t n)
#define SkDEBUGFAIL(message)
#define SK_ABORT(message,...)
uint8_t(*)(uint8_t src, uint8_t dst) AlphaProc
#define SkGetPackedB16(color)
#define SkGetPackedG16(color)
static uint16_t SkPackRGB16(unsigned r, unsigned g, unsigned b)
#define SkGetPackedR16(color)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static SkCanvas * trim(SkCanvas *canvas, SkScalar width, SkScalar height, const SkRect *content)
static bool skip(SkStream *stream, size_t amount)
#define SK_INIT_TO_AVOID_WARNING
SK_API void sk_free(void *)
static void * sk_malloc_throw(size_t size)
static U8CPU SkMulDiv255Round(U16CPU a, U16CPU b)
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)
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
constexpr int SkToInt(S x)
constexpr uint32_t SkToU32(S x)
void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override
void blitRect(int x, int y, int width, int height) override
Blit a solid rectangle one or more pixels wide.
void blitH(int x, int y, int width) override
Blit a horizontal run of one or more pixels.
~SkAAClipBlitter() override
void blitMask(const SkMask &, const SkIRect &clip) override
void blitV(int x, int y, int height, SkAlpha alpha) override
Blit a vertical run of pixels with a constant alpha value.
void blitAntiRect(int x, int y, int width, int height, SkAlpha leftAlpha, SkAlpha rightAlpha) override
void blitAntiH(int x, int y, const SkAlpha alpha[], const int16_t runs[]) override
Blitter(Builder *builder)
void blitH(int x, int y, int width) override
Blit a horizontal run of one or more pixels.
void blitV(int x, int y, int height, SkAlpha alpha) override
void blitRect(int x, int y, int width, int height) override
Blit a solid rectangle one or more pixels wide.
void blitMask(const SkMask &, const SkIRect &clip) override
Builder(const SkIRect &bounds)
bool blitPath(SkAAClip *target, const SkPath &path, bool doAA)
bool applyClipOp(SkAAClip *target, const SkAAClip &other, SkClipOp op)
void debug(bool compress_y=false) const
SkAAClip & operator=(const SkAAClip &)
bool setRect(const SkIRect &)
bool translate(int dx, int dy, SkAAClip *dst) const
bool setPath(const SkPath &, const SkIRect &bounds, bool doAA=true)
bool op(const SkIRect &, SkClipOp)
void copyToMask(SkMaskBuilder *) const
bool quickContains(const SkIRect &r) const
bool setRegion(const SkRegion &)
static SkPath Rect(const SkRect &, SkPathDirection=SkPathDirection::kCW, unsigned startIndex=0)
const SkRect & getBounds() const
const SkIRect & rect() const
const SkIRect & getBounds() const
static void AntiFillPath(const SkPath &, const SkRasterClip &, SkBlitter *)
static void FillPath(const SkPath &, const SkIRect &, SkBlitter *)
size_t size_bytes() const
void removeShuffle(int index)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
uint32_t uint32_t * format
static float min(float r, float g, float b)
Optional< SkRect > bounds
sk_sp< SkBlender > blender SkRect rect
skia_private::AutoTArray< sk_sp< SkImageFilter > > filters TypedMatrix matrix TypedMatrix matrix SkScalar dx
constexpr int32_t kMaxInt32
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
const YOffset * yoffsets() const
std::atomic< int32_t > fRefCnt
static RunHead * AllocRect(const SkIRect &bounds)
static Iter Iterate(const SkAAClip &clip)
static int ComputeRowSizeForWidth(int width)
static RunHead * Alloc(int rowCount, size_t dataSize)
const uint8_t * data() const
bool intersect(const SkIRect &r)
static bool Intersects(const SkIRect &a, const SkIRect &b)
int32_t fBottom
larger y-axis bounds
constexpr int32_t height() const
int32_t fTop
smaller y-axis bounds
constexpr int32_t width() const
int32_t fLeft
smaller x-axis bounds
bool contains(int32_t x, int32_t y) const
int32_t fRight
larger x-axis bounds
static uint8_t * AllocImage(size_t bytes, AllocType=kUninit_Alloc)
@ k3D_Format
3 8bit per pixl planes: alpha, mul, add
@ kA8_Format
8bits per pixel mask (e.g. antialiasing)
@ kLCD16_Format
565 alpha for r/g/b
@ kBW_Format
1bit per pixel mask (e.g. monochrome)
const void * getAddr(int x, int y) const
uint8_t const *const fImage
size_t computeImageSize() const
static SkRect Make(const SkISize &size)
SkScalar fBottom
larger y-axis bounds
constexpr float left() const
constexpr float top() const
SkScalar fLeft
smaller x-axis bounds
constexpr float x() const
constexpr float y() const
SkScalar fRight
larger x-axis bounds
bool contains(SkScalar x, SkScalar y) const
void round(SkIRect *dst) const
constexpr float height() const
constexpr float width() const
SkScalar fTop
smaller y-axis bounds
std::shared_ptr< const fml::Mapping > data