diff options
-rw-r--r-- | bench/DrawLatticeBench.cpp | 1 | ||||
-rw-r--r-- | gm/lattice.cpp | 10 | ||||
-rw-r--r-- | include/core/SkCanvas.h | 30 | ||||
-rw-r--r-- | include/private/SkRecords.h | 2 | ||||
-rw-r--r-- | src/core/SkLatticeIter.cpp | 88 | ||||
-rw-r--r-- | src/core/SkLatticeIter.h | 11 | ||||
-rw-r--r-- | src/core/SkLiteDL.cpp | 26 | ||||
-rw-r--r-- | src/core/SkPicturePlayback.cpp | 3 | ||||
-rw-r--r-- | src/core/SkPictureRecord.cpp | 6 | ||||
-rw-r--r-- | src/core/SkRecordDraw.cpp | 1 | ||||
-rw-r--r-- | src/core/SkRecorder.cpp | 4 | ||||
-rw-r--r-- | src/gpu/batches/GrNinePatch.cpp | 4 |
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()); |