aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--bench/DrawLatticeBench.cpp1
-rw-r--r--gm/lattice.cpp10
-rw-r--r--include/core/SkCanvas.h30
-rw-r--r--include/private/SkRecords.h2
-rw-r--r--src/core/SkLatticeIter.cpp88
-rw-r--r--src/core/SkLatticeIter.h11
-rw-r--r--src/core/SkLiteDL.cpp26
-rw-r--r--src/core/SkPicturePlayback.cpp3
-rw-r--r--src/core/SkPictureRecord.cpp6
-rw-r--r--src/core/SkRecordDraw.cpp1
-rw-r--r--src/core/SkRecorder.cpp4
-rw-r--r--src/gpu/batches/GrNinePatch.cpp4
12 files changed, 131 insertions, 55 deletions
diff --git a/bench/DrawLatticeBench.cpp b/bench/DrawLatticeBench.cpp
index 9c4d31a099..19d549f297 100644
--- a/bench/DrawLatticeBench.cpp
+++ b/bench/DrawLatticeBench.cpp
@@ -21,6 +21,7 @@ public:
fLattice.fXCount = xCount;
fLattice.fYDivs = yDivs;
fLattice.fYCount = yCount;
+ fLattice.fFlags = nullptr;
fName = SkStringPrintf("DrawLattice_%s", desc);
}
diff --git a/gm/lattice.cpp b/gm/lattice.cpp
index 63de2a66b4..919fb3588e 100644
--- a/gm/lattice.cpp
+++ b/gm/lattice.cpp
@@ -113,6 +113,7 @@ protected:
lattice.fXDivs = xDivs + 1;
lattice.fYCount = 4;
lattice.fYDivs = yDivs + 1;
+ lattice.fFlags = nullptr;
for (int iy = 0; iy < 2; ++iy) {
for (int ix = 0; ix < 2; ++ix) {
@@ -130,6 +131,15 @@ protected:
lattice.fYCount = 5;
lattice.fYDivs = yDivs;
+ // Let's skip a few rects.
+ SkCanvas::Lattice::Flags flags[36];
+ sk_bzero(flags, 36 * sizeof(SkCanvas::Lattice::Flags));
+ flags[4] = SkCanvas::Lattice::kTransparent_Flags;
+ flags[9] = SkCanvas::Lattice::kTransparent_Flags;
+ flags[12] = SkCanvas::Lattice::kTransparent_Flags;
+ flags[19] = SkCanvas::Lattice::kTransparent_Flags;
+ lattice.fFlags = flags;
+
canvas->translate(400, 0);
for (int iy = 0; iy < 2; ++iy) {
for (int ix = 0; ix < 2; ++ix) {
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index acf0ad2a54..d28d0f1898 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -934,21 +934,35 @@ public:
* Specifies coordinates to divide a bitmap into (xCount*yCount) rects.
*/
struct Lattice {
+ enum Flags : uint8_t {
+ // If set, indicates that we should not draw corresponding rect.
+ kTransparent_Flags = 1 << 0,
+ };
+
// An array of x-coordinates that divide the bitmap vertically.
- // These must be unique, increasing, and in the set [0, width].
+ // These must be unique, increasing, and in the set [0, width).
// Does not have ownership.
- const int* fXDivs;
-
- // The number of fXDivs.
- int fXCount;
+ const int* fXDivs;
// An array of y-coordinates that divide the bitmap horizontally.
- // These must be unique, increasing, and in the set [0, height].
+ // These must be unique, increasing, and in the set [0, height).
// Does not have ownership.
- const int* fYDivs;
+ const int* fYDivs;
+
+ // If non-null, the length of this array must be equal to
+ // (fXCount + 1) * (fYCount + 1). Note that we allow the first rect
+ // in each direction to empty (divs[0] = 0). In this case, the
+ // caller still must specify a flag (as a placeholder) for these
+ // empty rects.
+ // The flags correspond to the rects in the lattice, first moving
+ // left to right and then top to bottom.
+ const Flags* fFlags;
+
+ // The number of fXDivs.
+ int fXCount;
// The number of fYDivs.
- int fYCount;
+ int fYCount;
};
/**
diff --git a/include/private/SkRecords.h b/include/private/SkRecords.h
index 09961ce04a..2800a96b56 100644
--- a/include/private/SkRecords.h
+++ b/include/private/SkRecords.h
@@ -242,6 +242,8 @@ RECORD(DrawImageLattice, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag,
PODArray<int> xDivs;
int yCount;
PODArray<int> yDivs;
+ int flagCount;
+ PODArray<SkCanvas::Lattice::Flags> flags;
SkRect dst);
RECORD(DrawImageRect, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag,
Optional<SkPaint> paint;
diff --git a/src/core/SkLatticeIter.cpp b/src/core/SkLatticeIter.cpp
index ba6ac97a5b..38ef2828bd 100644
--- a/src/core/SkLatticeIter.cpp
+++ b/src/core/SkLatticeIter.cpp
@@ -12,13 +12,9 @@
* Divs must be in increasing order with no duplicates.
*/
static bool valid_divs(const int* divs, int count, int len) {
- if (count <= 0) {
- return false;
- }
-
int prev = -1;
for (int i = 0; i < count; i++) {
- if (prev >= divs[i] || divs[i] > len) {
+ if (prev >= divs[i] || divs[i] >= len) {
return false;
}
}
@@ -27,6 +23,12 @@ static bool valid_divs(const int* divs, int count, int len) {
}
bool SkLatticeIter::Valid(int width, int height, const SkCanvas::Lattice& lattice) {
+ bool zeroXDivs = lattice.fXCount <= 0 || (1 == lattice.fXCount && 0 == lattice.fXDivs[0]);
+ bool zeroYDivs = lattice.fYCount <= 0 || (1 == lattice.fYCount && 0 == lattice.fYDivs[0]);
+ if (zeroXDivs && zeroYDivs) {
+ return false;
+ }
+
return valid_divs(lattice.fXDivs, lattice.fXCount, width) &&
valid_divs(lattice.fYDivs, lattice.fYCount, height);
}
@@ -104,9 +106,9 @@ SkLatticeIter::SkLatticeIter(int srcWidth, int srcHeight, const SkCanvas::Lattic
const SkRect& dst)
{
const int* xDivs = lattice.fXDivs;
- int xCount = lattice.fXCount;
+ const int origXCount = lattice.fXCount;
const int* yDivs = lattice.fYDivs;
- int yCount = lattice.fYCount;
+ const int origYCount = lattice.fYCount;
// In the x-dimension, the first rectangle always starts at x = 0 and is "scalable".
// If xDiv[0] is 0, it indicates that the first rectangle is degenerate, so the
@@ -117,15 +119,16 @@ SkLatticeIter::SkLatticeIter(int srcWidth, int srcHeight, const SkCanvas::Lattic
// As we move left to right across the image, alternating patches will be "fixed" or
// "scalable" in the x-direction. Similarly, as move top to bottom, alternating
// patches will be "fixed" or "scalable" in the y-direction.
- SkASSERT(xCount > 0 && yCount > 0);
- bool xIsScalable = (0 == xDivs[0]);
+ int xCount = origXCount;
+ int yCount = origYCount;
+ bool xIsScalable = (xCount > 0 && 0 == xDivs[0]);
if (xIsScalable) {
// Once we've decided that the first patch is "scalable", we don't need the
// xDiv. It is always implied that we start at zero.
xDivs++;
xCount--;
}
- bool yIsScalable = (0 == yDivs[0]);
+ bool yIsScalable = (yCount > 0 && 0 == yDivs[0]);
if (yIsScalable) {
// Once we've decided that the first patch is "scalable", we don't need the
// yDiv. It is always implied that we start at zero.
@@ -133,14 +136,6 @@ SkLatticeIter::SkLatticeIter(int srcWidth, int srcHeight, const SkCanvas::Lattic
yCount--;
}
- // We never need the final xDiv/yDiv if it is equal to the width/height. This is implied.
- if (xCount > 0 && srcWidth == xDivs[xCount - 1]) {
- xCount--;
- }
- if (yCount > 0 && srcHeight == yDivs[yCount - 1]) {
- yCount--;
- }
-
// Count "scalable" and "fixed" pixels in each dimension.
int xCountScalable = count_scalable_pixels(xDivs, xCount, xIsScalable, srcWidth);
int xCountFixed = srcWidth - xCountScalable;
@@ -158,8 +153,42 @@ SkLatticeIter::SkLatticeIter(int srcWidth, int srcHeight, const SkCanvas::Lattic
dst.fTop, dst.fBottom, yIsScalable);
fCurrX = fCurrY = 0;
- fDone = false;
- fNumRects = (xCount + 1) * (yCount + 1);
+ fNumRectsInLattice = (xCount + 1) * (yCount + 1);
+ fNumRectsToDraw = fNumRectsInLattice;
+
+ if (lattice.fFlags) {
+ fFlags.push_back_n(fNumRectsInLattice);
+
+ const SkCanvas::Lattice::Flags* flags = lattice.fFlags;
+
+ bool hasPadRow = (yCount != origYCount);
+ bool hasPadCol = (xCount != origXCount);
+ if (hasPadRow) {
+ // The first row of rects are all empty, skip the first row of flags.
+ flags += origXCount + 1;
+ }
+
+ int i = 0;
+ for (int y = 0; y < yCount + 1; y++) {
+ for (int x = 0; x < origXCount + 1; x++) {
+ if (0 == x && hasPadCol) {
+ // The first column of rects are all empty. Skip a rect.
+ flags++;
+ continue;
+ }
+
+ fFlags[i] = *flags;
+ flags++;
+ i++;
+ }
+ }
+
+ for (int j = 0; j < fFlags.count(); j++) {
+ if (SkCanvas::Lattice::kTransparent_Flags == fFlags[j]) {
+ fNumRectsToDraw--;
+ }
+ }
+ }
}
bool SkLatticeIter::Valid(int width, int height, const SkIRect& center) {
@@ -205,12 +234,13 @@ SkLatticeIter::SkLatticeIter(int w, int h, const SkIRect& c, const SkRect& dst)
}
fCurrX = fCurrY = 0;
- fDone = false;
- fNumRects = 9;
+ fNumRectsInLattice = 9;
+ fNumRectsToDraw = 9;
}
bool SkLatticeIter::next(SkRect* src, SkRect* dst) {
- if (fDone) {
+ int currRect = fCurrX + fCurrY * (fSrcX.count() - 1);
+ if (currRect == fNumRectsInLattice) {
return false;
}
@@ -219,15 +249,17 @@ bool SkLatticeIter::next(SkRect* src, SkRect* dst) {
SkASSERT(x >= 0 && x < fSrcX.count() - 1);
SkASSERT(y >= 0 && y < fSrcY.count() - 1);
- src->set(fSrcX[x], fSrcY[y], fSrcX[x + 1], fSrcY[y + 1]);
- dst->set(fDstX[x], fDstY[y], fDstX[x + 1], fDstY[y + 1]);
if (fSrcX.count() - 1 == ++fCurrX) {
fCurrX = 0;
fCurrY += 1;
- if (fCurrY >= fSrcY.count() - 1) {
- fDone = true;
- }
}
+
+ if (fFlags.count() > 0 && SkToBool(SkCanvas::Lattice::kTransparent_Flags & fFlags[currRect])) {
+ return this->next(src, dst);
+ }
+
+ src->set(fSrcX[x], fSrcY[y], fSrcX[x + 1], fSrcY[y + 1]);
+ dst->set(fDstX[x], fDstY[y], fDstX[x + 1], fDstY[y + 1]);
return true;
}
diff --git a/src/core/SkLatticeIter.h b/src/core/SkLatticeIter.h
index 192b6c5b54..deb2fe95eb 100644
--- a/src/core/SkLatticeIter.h
+++ b/src/core/SkLatticeIter.h
@@ -41,10 +41,10 @@ public:
void mapDstScaleTranslate(const SkMatrix& matrix);
/**
- * Returns the total number of rects that will be drawn.
+ * Returns the number of rects that will actually be drawn.
*/
- int numRects() const {
- return fNumRects;
+ int numRectsToDraw() const {
+ return fNumRectsToDraw;
}
private:
@@ -52,11 +52,12 @@ private:
SkTArray<SkScalar> fSrcY;
SkTArray<SkScalar> fDstX;
SkTArray<SkScalar> fDstY;
+ SkTArray<SkCanvas::Lattice::Flags> fFlags;
int fCurrX;
int fCurrY;
- bool fDone;
- int fNumRects;
+ int fNumRectsInLattice;
+ int fNumRectsToDraw;
};
#endif
diff --git a/src/core/SkLiteDL.cpp b/src/core/SkLiteDL.cpp
index eaa5a79626..8c8abb1cc3 100644
--- a/src/core/SkLiteDL.cpp
+++ b/src/core/SkLiteDL.cpp
@@ -352,19 +352,21 @@ namespace {
};
struct DrawImageLattice final : Op {
static const auto kType = Type::DrawImageLattice;
- DrawImageLattice(sk_sp<const SkImage>&& image, int xs, int ys,
+ DrawImageLattice(sk_sp<const SkImage>&& image, int xs, int ys, int fs,
const SkRect& dst, const SkPaint* paint)
- : image(std::move(image)), xs(xs), ys(ys), dst(dst) {
+ : image(std::move(image)), xs(xs), ys(ys), fs(fs), dst(dst) {
if (paint) { this->paint = *paint; }
}
sk_sp<const SkImage> image;
- int xs, ys;
+ int xs, ys, fs;
SkRect dst;
SkPaint paint;
void draw(SkCanvas* c, const SkMatrix&) {
auto xdivs = pod<int>(this, 0),
ydivs = pod<int>(this, xs*sizeof(int));
- c->drawImageLattice(image.get(), {xdivs, xs, ydivs, ys}, dst, &paint);
+ auto flags = (0 == fs) ? nullptr :
+ pod<SkCanvas::Lattice::Flags>(this, (xs+ys)*sizeof(int));
+ c->drawImageLattice(image.get(), {xdivs, ydivs, flags, xs, ys}, dst, &paint);
}
};
@@ -665,11 +667,13 @@ void SkLiteDL::drawBitmapRect(const SkBitmap& bm, const SkRect* src, const SkRec
void SkLiteDL::drawBitmapLattice(const SkBitmap& bm, const SkCanvas::Lattice& lattice,
const SkRect& dst, const SkPaint* paint) {
int xs = lattice.fXCount, ys = lattice.fYCount;
- size_t bytes = (xs + ys) * sizeof(int);
- void* pod = this->push<DrawImageLattice>(bytes, SkImage::MakeFromBitmap(bm), xs, ys, dst,
+ int fs = lattice.fFlags ? (xs + 1) * (ys + 1) : 0;
+ size_t bytes = (xs + ys) * sizeof(int) + fs * sizeof(SkCanvas::Lattice::Flags);
+ void* pod = this->push<DrawImageLattice>(bytes, SkImage::MakeFromBitmap(bm), xs, ys, fs, dst,
paint);
copy_v(pod, lattice.fXDivs, xs,
- lattice.fYDivs, ys);
+ lattice.fYDivs, ys,
+ lattice.fFlags, fs);
}
void SkLiteDL::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
@@ -686,10 +690,12 @@ void SkLiteDL::drawImageRect(const SkImage* image, const SkRect* src, const SkRe
void SkLiteDL::drawImageLattice(const SkImage* image, const SkCanvas::Lattice& lattice,
const SkRect& dst, const SkPaint* paint) {
int xs = lattice.fXCount, ys = lattice.fYCount;
- size_t bytes = (xs + ys) * sizeof(int);
- void* pod = this->push<DrawImageLattice>(bytes, sk_ref_sp(image), xs, ys, dst, paint);
+ int fs = lattice.fFlags ? (xs + 1) * (ys + 1) : 0;
+ size_t bytes = (xs + ys) * sizeof(int) + fs * sizeof(SkCanvas::Lattice::Flags);
+ void* pod = this->push<DrawImageLattice>(bytes, sk_ref_sp(image), xs, ys, fs, dst, paint);
copy_v(pod, lattice.fXDivs, xs,
- lattice.fYDivs, ys);
+ lattice.fYDivs, ys,
+ lattice.fFlags, fs);
}
void SkLiteDL::drawText(const void* text, size_t bytes,
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index 3df64227a6..4520b6d325 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -316,6 +316,9 @@ void SkPicturePlayback::handleOp(SkReadBuffer* reader,
lattice.fXDivs = (const int*) reader->skip(lattice.fXCount * sizeof(int32_t));
lattice.fYCount = reader->readInt();
lattice.fYDivs = (const int*) reader->skip(lattice.fYCount * sizeof(int32_t));
+ int flagCount = reader->readInt();
+ lattice.fFlags = (0 == flagCount) ? nullptr : (const SkCanvas::Lattice::Flags*)
+ reader->skip(SkAlign4(flagCount * sizeof(SkCanvas::Lattice::Flags)));
SkRect dst;
reader->readRect(&dst);
canvas->drawImageLattice(image, lattice, dst, paint);
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index 8eab63016b..5ee2e9fb35 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -538,7 +538,9 @@ void SkPictureRecord::onDrawImageNine(const SkImage* img, const SkIRect& center,
void SkPictureRecord::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
const SkRect& dst, const SkPaint* paint) {
// xCount + xDivs + yCount+ yDivs
- size_t latticeSize = (1 + lattice.fXCount + 1 + lattice.fYCount) * kUInt32Size;
+ int flagCount = (nullptr == lattice.fFlags) ? 0 : (lattice.fXCount + 1) * (lattice.fYCount + 1);
+ size_t latticeSize = (1 + lattice.fXCount + 1 + lattice.fYCount + 1) * kUInt32Size +
+ SkAlign4(flagCount * sizeof(SkCanvas::Lattice::Flags));
// op + paint index + image index + lattice + dst rect
size_t size = 3 * kUInt32Size + latticeSize + sizeof(dst);
@@ -549,6 +551,8 @@ void SkPictureRecord::onDrawImageLattice(const SkImage* image, const Lattice& la
fWriter.writePad(lattice.fXDivs, lattice.fXCount * kUInt32Size);
this->addInt(lattice.fYCount);
fWriter.writePad(lattice.fYDivs, lattice.fYCount * kUInt32Size);
+ this->addInt(flagCount);
+ fWriter.writePad(lattice.fFlags, flagCount * sizeof(SkCanvas::Lattice::Flags));
this->addRect(dst);
this->validate(initialOffset, size);
}
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
index 6545586499..2952591319 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -106,6 +106,7 @@ template <> void Draw::draw(const DrawImageLattice& r) {
lattice.fXDivs = r.xDivs;
lattice.fYCount = r.yCount;
lattice.fYDivs = r.yDivs;
+ lattice.fFlags = (0 == r.flagCount) ? nullptr : r.flags;
fCanvas->drawImageLattice(r.image.get(), lattice, r.dst, r.paint);
}
diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp
index 840e19b90d..4c09e514be 100644
--- a/src/core/SkRecorder.cpp
+++ b/src/core/SkRecorder.cpp
@@ -238,9 +238,11 @@ void SkRecorder::onDrawImageNine(const SkImage* image, const SkIRect& center,
void SkRecorder::onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
const SkPaint* paint) {
+ int flagCount = lattice.fFlags ? (lattice.fXCount + 1) * (lattice.fYCount + 1) : 0;
APPEND(DrawImageLattice, this->copy(paint), sk_ref_sp(image),
lattice.fXCount, this->copy(lattice.fXDivs, lattice.fXCount),
- lattice.fYCount, this->copy(lattice.fYDivs, lattice.fYCount), dst);
+ lattice.fYCount, this->copy(lattice.fYDivs, lattice.fYCount),
+ flagCount, this->copy(lattice.fFlags, flagCount), dst);
}
void SkRecorder::onDrawText(const void* text, size_t byteLength,
diff --git a/src/gpu/batches/GrNinePatch.cpp b/src/gpu/batches/GrNinePatch.cpp
index 3417c5c095..522e775c33 100644
--- a/src/gpu/batches/GrNinePatch.cpp
+++ b/src/gpu/batches/GrNinePatch.cpp
@@ -82,7 +82,7 @@ private:
int patchCnt = fPatches.count();
int numRects = 0;
for (int i = 0; i < patchCnt; i++) {
- numRects += fPatches[i].fIter->numRects();
+ numRects += fPatches[i].fIter->numRectsToDraw();
}
SkAutoTUnref<const GrBuffer> indexBuffer(
@@ -132,7 +132,7 @@ private:
if (!isScaleTranslate) {
SkPoint* positions = reinterpret_cast<SkPoint*>(patchVerts);
patch.fViewMatrix.mapPointsWithStride(positions, vertexStride,
- kVertsPerRect * patch.fIter->numRects());
+ kVertsPerRect * patch.fIter->numRectsToDraw());
}
}
helper.recordDraw(target, gp.get());