Implement a fast path for solid color lattice rectangle

Add a flag that hints, which lattice rectangles are solid colors.
Draw solid rectangles and 1x1 rectangles with drawRect.

Test: Measured performance of a ninepatch drawn by HWUI
Bug: b/69796044
Change-Id: Ib3b00ca608da42fa9f2d2038cc126a978421ec7c
Reviewed-on: https://skia-review.googlesource.com/79821
Commit-Queue: Stan Iliev <stani@google.com>
Reviewed-by: Derek Sollenberger <djsollen@google.com>
This commit is contained in:
Stan Iliev 2017-12-11 13:01:58 -05:00 committed by Skia Commit-Bot
parent 51493ee848
commit ca8c0953e8
17 changed files with 296 additions and 58 deletions

View File

@ -22,8 +22,9 @@ public:
fLattice.fXCount = xCount; fLattice.fXCount = xCount;
fLattice.fYDivs = yDivs; fLattice.fYDivs = yDivs;
fLattice.fYCount = yCount; fLattice.fYCount = yCount;
fLattice.fFlags = nullptr; fLattice.fRectTypes = nullptr;
fLattice.fBounds = nullptr; fLattice.fBounds = nullptr;
fLattice.fColors = nullptr;
fName = SkStringPrintf("DrawLattice_%s", desc); fName = SkStringPrintf("DrawLattice_%s", desc);
} }

View File

@ -1548,7 +1548,7 @@ static void fuzz_canvas(Fuzz* fuzz, SkCanvas* canvas, int depth = 9) {
} }
constexpr int kMax = 6; constexpr int kMax = 6;
int xDivs[kMax], yDivs[kMax]; int xDivs[kMax], yDivs[kMax];
SkCanvas::Lattice lattice{xDivs, yDivs, nullptr, 0, 0, nullptr}; SkCanvas::Lattice lattice{xDivs, yDivs, nullptr, 0, 0, nullptr, nullptr};
fuzz->nextRange(&lattice.fXCount, 2, kMax); fuzz->nextRange(&lattice.fXCount, 2, kMax);
fuzz->nextRange(&lattice.fYCount, 2, kMax); fuzz->nextRange(&lattice.fYCount, 2, kMax);
fuzz->nextN(xDivs, lattice.fXCount); fuzz->nextN(xDivs, lattice.fXCount);
@ -1566,7 +1566,7 @@ static void fuzz_canvas(Fuzz* fuzz, SkCanvas* canvas, int depth = 9) {
} }
constexpr int kMax = 6; constexpr int kMax = 6;
int xDivs[kMax], yDivs[kMax]; int xDivs[kMax], yDivs[kMax];
SkCanvas::Lattice lattice{xDivs, yDivs, nullptr, 0, 0, nullptr}; SkCanvas::Lattice lattice{xDivs, yDivs, nullptr, 0, 0, nullptr, nullptr};
fuzz->nextRange(&lattice.fXCount, 2, kMax); fuzz->nextRange(&lattice.fXCount, 2, kMax);
fuzz->nextRange(&lattice.fYCount, 2, kMax); fuzz->nextRange(&lattice.fYCount, 2, kMax);
fuzz->nextN(xDivs, lattice.fXCount); fuzz->nextN(xDivs, lattice.fXCount);

View File

@ -124,7 +124,8 @@ protected:
lattice.fXDivs = xDivs + 1; lattice.fXDivs = xDivs + 1;
lattice.fYCount = 4; lattice.fYCount = 4;
lattice.fYDivs = yDivs + 1; lattice.fYDivs = yDivs + 1;
lattice.fFlags = nullptr; lattice.fRectTypes = nullptr;
lattice.fColors = nullptr;
SkIRect bounds = SkIRect::MakeLTRB(padLeft, padTop, SkIRect bounds = SkIRect::MakeLTRB(padLeft, padTop,
image->width() - padRight, image->height() - padBottom); image->width() - padRight, image->height() - padBottom);
@ -140,6 +141,19 @@ protected:
} }
} }
// Provide hints about 3 solid color rects. These colors match
// what was already in the bitmap.
int fixedColorX[3] = {2, 4, 1};
int fixedColorY[3] = {1, 1, 2};
SkColor fixedColor[3] = {SK_ColorBLACK, SK_ColorBLACK, SK_ColorBLACK};
const SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType,
kUnpremul_SkAlphaType);
for (int rectNum = 0; rectNum < 3; rectNum++) {
int srcX = xDivs[fixedColorX[rectNum]-1];
int srcY = yDivs[fixedColorY[rectNum]-1];
image->readPixels(info, &fixedColor[rectNum], 4, srcX, srcY);
}
// Include the degenerate first div. While normally the first patch is "scalable", // Include the degenerate first div. While normally the first patch is "scalable",
// this will mean that the first non-degenerate patch is "fixed". // this will mean that the first non-degenerate patch is "fixed".
lattice.fXCount = 5; lattice.fXCount = 5;
@ -148,13 +162,26 @@ protected:
lattice.fYDivs = yDivs; lattice.fYDivs = yDivs;
// Let's skip a few rects. // Let's skip a few rects.
SkCanvas::Lattice::Flags flags[36]; SkCanvas::Lattice::RectType flags[36];
sk_bzero(flags, 36 * sizeof(SkCanvas::Lattice::Flags)); sk_bzero(flags, 36 * sizeof(SkCanvas::Lattice::RectType));
flags[4] = SkCanvas::Lattice::kTransparent_Flags; flags[4] = SkCanvas::Lattice::kTransparent;
flags[9] = SkCanvas::Lattice::kTransparent_Flags; flags[9] = SkCanvas::Lattice::kTransparent;
flags[12] = SkCanvas::Lattice::kTransparent_Flags; flags[12] = SkCanvas::Lattice::kTransparent;
flags[19] = SkCanvas::Lattice::kTransparent_Flags; flags[19] = SkCanvas::Lattice::kTransparent;
lattice.fFlags = flags; for (int rectNum = 0; rectNum < 3; rectNum++) {
flags[fixedColorY[rectNum]*6 + fixedColorX[rectNum]]
= SkCanvas::Lattice::kFixedColor;
}
lattice.fRectTypes = flags;
SkColor colors[36];
sk_bzero(colors, 36 * sizeof(SkColor));
for (int rectNum = 0; rectNum < 3; rectNum++) {
colors[fixedColorY[rectNum]*6 + fixedColorX[rectNum]]
= fixedColor[rectNum];
}
lattice.fColors = colors;
canvas->translate(400, 0); canvas->translate(400, 0);
for (int iy = 0; iy < 2; ++iy) { for (int iy = 0; iy < 2; ++iy) {
@ -179,3 +206,140 @@ private:
typedef skiagm::GM INHERITED; typedef skiagm::GM INHERITED;
}; };
DEF_GM( return new LatticeGM; ) DEF_GM( return new LatticeGM; )
// LatticeGM2 exercises code paths that draw fixed color and 1x1 rectangles.
class LatticeGM2 : public skiagm::GM {
public:
LatticeGM2() {}
SkString onShortName() override {
return SkString("lattice2");
}
SkISize onISize() override {
return SkISize::Make(800, 800);
}
sk_sp<SkImage> makeImage(SkCanvas* root, int padLeft, int padTop, int padRight, int padBottom) {
const int kSize = 80;
auto surface(make_surface(root, kSize, padLeft, padTop, padRight, padBottom));
SkCanvas* canvas = surface->getCanvas();;
SkPaint paint;
paint.setAntiAlias(false);
SkRect r;
//first line
r.setXYWH(0, 0, 4, 1); //4x1 green rect
paint.setColor(0xFF00FF00);
canvas->drawRect(r, paint);
r.setXYWH(4, 0, 1, 1); //1x1 blue pixel -> draws as rectangle
paint.setColor(0xFF0000FF);
canvas->drawRect(r, paint);
r.setXYWH(5, 0, kSize-5, 1); //the rest of the line is red
paint.setColor(0xFFFF0000);
canvas->drawRect(r, paint);
//second line -> draws as fixed color rectangles
r.setXYWH(0, 1, 4, 1); //4x1 red rect
paint.setColor(0xFFFF0000);
canvas->drawRect(r, paint);
r.setXYWH(4, 1, 1, 1); //1x1 blue pixel with alpha
paint.setColor(0x880000FF);
canvas->drawRect(r, paint);
r.setXYWH(5, 1, kSize-5, 1); //the rest of the line is green
paint.setColor(0xFF00FF00);
canvas->drawRect(r, paint);
//third line - does not draw, because it is transparent
r.setXYWH(0, 2, 4, kSize-2); //4x78 green rect
paint.setColor(0xFF00FF00);
canvas->drawRect(r, paint);
r.setXYWH(4, 2, 1, kSize-2); //1x78 red pixel with alpha
paint.setColor(0x88FF0000);
canvas->drawRect(r, paint);
r.setXYWH(5, 2, kSize-5, kSize-2); //the rest of the image is blue
paint.setColor(0xFF0000FF);
canvas->drawRect(r, paint);
return surface->makeImageSnapshot();
}
void onDrawHelper(SkCanvas* canvas, int padLeft, int padTop, int padRight, int padBottom,
SkPaint& paint) {
int xDivs[2] = {4, 5};
int yDivs[2] = {1, 2};
canvas->save();
sk_sp<SkImage> image = makeImage(canvas, padLeft, padTop, padRight, padBottom);
canvas->drawImage(image, 10, 10, nullptr);
SkCanvas::Lattice lattice;
lattice.fXCount = 2;
lattice.fXDivs = xDivs;
lattice.fYCount = 2;
lattice.fYDivs = yDivs;
lattice.fBounds = nullptr;
SkCanvas::Lattice::RectType flags[9];
sk_bzero(flags, 9 * sizeof(SkCanvas::Lattice::RectType));
flags[3] = SkCanvas::Lattice::kFixedColor;
flags[4] = SkCanvas::Lattice::kFixedColor;
flags[5] = SkCanvas::Lattice::kFixedColor;
flags[6] = SkCanvas::Lattice::kTransparent;
flags[7] = SkCanvas::Lattice::kTransparent;
flags[8] = SkCanvas::Lattice::kTransparent;
lattice.fRectTypes = flags;
SkColor colors[9] = {SK_ColorBLACK, SK_ColorBLACK, SK_ColorBLACK,
0xFFFF0000, 0x880000FF, 0xFF00FF00,
SK_ColorBLACK, SK_ColorBLACK, SK_ColorBLACK};
lattice.fColors = colors;
paint.setColor(0xFFFFFFFF);
canvas->drawImageLattice(image.get(), lattice,
SkRect::MakeXYWH(100, 100, 200, 200), &paint);
//draw the same content with alpha
canvas->translate(400, 0);
paint.setColor(0x80000FFF);
canvas->drawImageLattice(image.get(), lattice,
SkRect::MakeXYWH(100, 100, 200, 200), &paint);
canvas->restore();
}
void onDraw(SkCanvas* canvas) override {
//draw a rectangle in the background with transparent pixels
SkPaint paint;
paint.setColor(0x7F123456);
paint.setBlendMode(SkBlendMode::kSrc);
canvas->drawRect( SkRect::MakeXYWH(300, 0, 300, 800), paint);
//draw image lattice with kSrcOver blending
paint.setBlendMode(SkBlendMode::kSrcOver);
this->onDrawHelper(canvas, 0, 0, 0, 0, paint);
//draw image lattice with kSrcATop blending
canvas->translate(0.0f, 400.0f);
paint.setBlendMode(SkBlendMode::kSrcATop);
this->onDrawHelper(canvas, 0, 0, 0, 0, paint);
}
private:
typedef skiagm::GM INHERITED;
};
DEF_GM( return new LatticeGM2; )

View File

@ -1760,12 +1760,19 @@ public:
*/ */
struct Lattice { struct Lattice {
/** \enum SkCanvas::Lattice::Flags /** \enum SkCanvas::Lattice::RectType
Optional setting per rectangular grid entry to make it transparent. Optional setting per rectangular grid entry.
*/ */
enum Flags : uint8_t { enum RectType : uint8_t {
kDefault = 0,
/** Set to skip lattice rectangle by making it transparent. */ /** Set to skip lattice rectangle by making it transparent. */
kTransparent_Flags = 1 << 0, kTransparent,
/** The lattice rectangle is a fixed color. The color value is stored
in fColors.
*/
kFixedColor,
}; };
/** Array of x-coordinates that divide the bitmap vertically. /** Array of x-coordinates that divide the bitmap vertically.
@ -1784,13 +1791,13 @@ public:
*/ */
const int* fYDivs; const int* fYDivs;
/** Optional array of flags, one per rectangular grid entry: /** Optional array of rectangle types, one per rectangular grid entry:
array length must be (fXCount + 1) * (fYCount + 1). array length must be (fXCount + 1) * (fYCount + 1).
Array entries correspond to the rectangular grid entries, ascending Array entries correspond to the rectangular grid entries, ascending
left to right and then top to bottom. left to right and then top to bottom.
*/ */
const Flags* fFlags; const RectType* fRectTypes;
/** Number of entries in fXDivs array; one less than the number of /** Number of entries in fXDivs array; one less than the number of
horizontal divisions. horizontal divisions.
@ -1807,6 +1814,15 @@ public:
*/ */
const SkIRect* fBounds; const SkIRect* fBounds;
/** Optional array of colors, one per rectangular grid entry:
array length must be (fXCount + 1) * (fYCount + 1).
Array entries correspond to the rectangular grid entries, ascending
left to right and then top to bottom.
*/
const SkColor* fColors;
}; };
/** Draw SkBitmap bitmap stretched proportionally to fit into SkRect dst. /** Draw SkBitmap bitmap stretched proportionally to fit into SkRect dst.

View File

@ -223,8 +223,24 @@ void SkBaseDevice::drawImageLattice(const SkImage* image,
SkLatticeIter iter(lattice, dst); SkLatticeIter iter(lattice, dst);
SkRect srcR, dstR; SkRect srcR, dstR;
while (iter.next(&srcR, &dstR)) { SkColor c;
this->drawImageRect(image, &srcR, dstR, paint, SkCanvas::kStrict_SrcRectConstraint); bool isFixedColor = false;
const SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType);
while (iter.next(&srcR, &dstR, &isFixedColor, &c)) {
if (isFixedColor || (srcR.width() <= 1.0f && srcR.height() <= 1.0f &&
image->readPixels(info, &c, 4, srcR.fLeft, srcR.fTop))) {
// Fast draw with drawRect, if this is a patch containing a single color
// or if this is a patch containing a single pixel.
if (0 != c || !paint.isSrcOver()) {
SkPaint paintCopy(paint);
int alpha = SkAlphaMul(SkColorGetA(c), SkAlpha255To256(paint.getAlpha()));
paintCopy.setColor(SkColorSetA(c, alpha));
this->drawRect(dstR, paintCopy);
}
} else {
this->drawImageRect(image, &srcR, dstR, paint, SkCanvas::kStrict_SrcRectConstraint);
}
} }
} }

View File

@ -166,16 +166,19 @@ SkLatticeIter::SkLatticeIter(const SkCanvas::Lattice& lattice, const SkRect& dst
fNumRectsInLattice = (xCount + 1) * (yCount + 1); fNumRectsInLattice = (xCount + 1) * (yCount + 1);
fNumRectsToDraw = fNumRectsInLattice; fNumRectsToDraw = fNumRectsInLattice;
if (lattice.fFlags) { if (lattice.fRectTypes) {
fFlags.push_back_n(fNumRectsInLattice); fRectTypes.push_back_n(fNumRectsInLattice);
fColors.push_back_n(fNumRectsInLattice);
const SkCanvas::Lattice::Flags* flags = lattice.fFlags; const SkCanvas::Lattice::RectType* flags = lattice.fRectTypes;
const SkColor* colors = lattice.fColors;
bool hasPadRow = (yCount != origYCount); bool hasPadRow = (yCount != origYCount);
bool hasPadCol = (xCount != origXCount); bool hasPadCol = (xCount != origXCount);
if (hasPadRow) { if (hasPadRow) {
// The first row of rects are all empty, skip the first row of flags. // The first row of rects are all empty, skip the first row of flags.
flags += origXCount + 1; flags += origXCount + 1;
colors += origXCount + 1;
} }
int i = 0; int i = 0;
@ -184,17 +187,20 @@ SkLatticeIter::SkLatticeIter(const SkCanvas::Lattice& lattice, const SkRect& dst
if (0 == x && hasPadCol) { if (0 == x && hasPadCol) {
// The first column of rects are all empty. Skip a rect. // The first column of rects are all empty. Skip a rect.
flags++; flags++;
colors++;
continue; continue;
} }
fFlags[i] = *flags; fRectTypes[i] = *flags;
fColors[i] = *colors;
flags++; flags++;
colors++;
i++; i++;
} }
} }
for (int j = 0; j < fFlags.count(); j++) { for (int j = 0; j < fRectTypes.count(); j++) {
if (SkCanvas::Lattice::kTransparent_Flags == fFlags[j]) { if (SkCanvas::Lattice::kTransparent == fRectTypes[j]) {
fNumRectsToDraw--; fNumRectsToDraw--;
} }
} }
@ -248,7 +254,7 @@ SkLatticeIter::SkLatticeIter(int w, int h, const SkIRect& c, const SkRect& dst)
fNumRectsToDraw = 9; fNumRectsToDraw = 9;
} }
bool SkLatticeIter::next(SkRect* src, SkRect* dst) { bool SkLatticeIter::next(SkRect* src, SkRect* dst, bool* isFixedColor, SkColor* fixedColor) {
int currRect = fCurrX + fCurrY * (fSrcX.count() - 1); int currRect = fCurrX + fCurrY * (fSrcX.count() - 1);
if (currRect == fNumRectsInLattice) { if (currRect == fNumRectsInLattice) {
return false; return false;
@ -264,12 +270,20 @@ bool SkLatticeIter::next(SkRect* src, SkRect* dst) {
fCurrY += 1; fCurrY += 1;
} }
if (fFlags.count() > 0 && SkToBool(SkCanvas::Lattice::kTransparent_Flags & fFlags[currRect])) { if (fRectTypes.count() > 0
return this->next(src, dst); && SkToBool(SkCanvas::Lattice::kTransparent == fRectTypes[currRect])) {
return this->next(src, dst, isFixedColor, fixedColor);
} }
src->set(fSrcX[x], fSrcY[y], fSrcX[x + 1], fSrcY[y + 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]); dst->set(fDstX[x], fDstY[y], fDstX[x + 1], fDstY[y + 1]);
if (isFixedColor && fixedColor) {
*isFixedColor = fRectTypes.count() > 0
&& SkToBool(SkCanvas::Lattice::kFixedColor == fRectTypes[currRect]);
if (*isFixedColor) {
*fixedColor = fColors[currRect];
}
}
return true; return true;
} }

View File

@ -30,9 +30,12 @@ public:
SkLatticeIter(int imageWidth, int imageHeight, const SkIRect& center, const SkRect& dst); SkLatticeIter(int imageWidth, int imageHeight, const SkIRect& center, const SkRect& dst);
/** /**
* While it returns true, use src/dst to draw the image/bitmap * While it returns true, use src/dst to draw the image/bitmap. Optional parameters
* isFixedColor and fixedColor specify if the rectangle is filled with a fixed color.
* If (*isFixedColor) is true, then (*fixedColor) contains the rectangle color.
*/ */
bool next(SkRect* src, SkRect* dst); bool next(SkRect* src, SkRect* dst, bool* isFixedColor = nullptr,
SkColor* fixedColor = nullptr);
/** /**
* Apply a matrix to the dst points. * Apply a matrix to the dst points.
@ -51,7 +54,8 @@ private:
SkTArray<SkScalar> fSrcY; SkTArray<SkScalar> fSrcY;
SkTArray<SkScalar> fDstX; SkTArray<SkScalar> fDstX;
SkTArray<SkScalar> fDstY; SkTArray<SkScalar> fDstY;
SkTArray<SkCanvas::Lattice::Flags> fFlags; SkTArray<SkCanvas::Lattice::RectType> fRectTypes;
SkTArray<SkColor> fColors;
int fCurrX; int fCurrX;
int fCurrY; int fCurrY;

View File

@ -330,9 +330,13 @@ namespace {
void draw(SkCanvas* c, const SkMatrix&) const { void draw(SkCanvas* c, const SkMatrix&) const {
auto xdivs = pod<int>(this, 0), auto xdivs = pod<int>(this, 0),
ydivs = pod<int>(this, xs*sizeof(int)); ydivs = pod<int>(this, xs*sizeof(int));
auto colors = (0 == fs) ? nullptr :
pod<SkColor>(this, (xs+ys)*sizeof(int));
auto flags = (0 == fs) ? nullptr : auto flags = (0 == fs) ? nullptr :
pod<SkCanvas::Lattice::Flags>(this, (xs+ys)*sizeof(int)); pod<SkCanvas::Lattice::RectType>(this, (xs+ys)*sizeof(int)+
c->drawImageLattice(image.get(), {xdivs, ydivs, flags, xs, ys, &src}, dst, &paint); fs*sizeof(SkColor));
c->drawImageLattice(image.get(), {xdivs, ydivs, flags, xs, ys, &src, colors}, dst,
&paint);
} }
}; };
@ -619,14 +623,16 @@ void SkLiteDL::drawImageRect(sk_sp<const SkImage> image, const SkRect* src, cons
void SkLiteDL::drawImageLattice(sk_sp<const SkImage> image, const SkCanvas::Lattice& lattice, void SkLiteDL::drawImageLattice(sk_sp<const SkImage> image, const SkCanvas::Lattice& lattice,
const SkRect& dst, const SkPaint* paint) { const SkRect& dst, const SkPaint* paint) {
int xs = lattice.fXCount, ys = lattice.fYCount; int xs = lattice.fXCount, ys = lattice.fYCount;
int fs = lattice.fFlags ? (xs + 1) * (ys + 1) : 0; int fs = lattice.fRectTypes ? (xs + 1) * (ys + 1) : 0;
size_t bytes = (xs + ys) * sizeof(int) + fs * sizeof(SkCanvas::Lattice::Flags); size_t bytes = (xs + ys) * sizeof(int) + fs * sizeof(SkCanvas::Lattice::RectType)
+ fs * sizeof(SkColor);
SkASSERT(lattice.fBounds); SkASSERT(lattice.fBounds);
void* pod = this->push<DrawImageLattice>(bytes, std::move(image), xs, ys, fs, *lattice.fBounds, void* pod = this->push<DrawImageLattice>(bytes, std::move(image), xs, ys, fs, *lattice.fBounds,
dst, paint); dst, paint);
copy_v(pod, lattice.fXDivs, xs, copy_v(pod, lattice.fXDivs, xs,
lattice.fYDivs, ys, lattice.fYDivs, ys,
lattice.fFlags, fs); lattice.fColors, fs,
lattice.fRectTypes, fs);
} }
void SkLiteDL::drawText(const void* text, size_t bytes, void SkLiteDL::drawText(const void* text, size_t bytes,

View File

@ -351,8 +351,11 @@ void SkPicturePlayback::handleOp(SkReadBuffer* reader,
lattice.fYCount = reader->readInt(); lattice.fYCount = reader->readInt();
lattice.fYDivs = (const int*) reader->skip(lattice.fYCount * sizeof(int32_t)); lattice.fYDivs = (const int*) reader->skip(lattice.fYCount * sizeof(int32_t));
int flagCount = reader->readInt(); int flagCount = reader->readInt();
lattice.fFlags = (0 == flagCount) ? nullptr : (const SkCanvas::Lattice::Flags*) lattice.fRectTypes = (0 == flagCount) ? nullptr :
reader->skip(SkAlign4(flagCount * sizeof(SkCanvas::Lattice::Flags))); (const SkCanvas::Lattice::RectType*)
reader->skip(SkAlign4(flagCount * sizeof(SkCanvas::Lattice::RectType)));
lattice.fColors = (0 == flagCount) ? nullptr : (const SkColor*)
reader->skip(SkAlign4(flagCount * sizeof(SkColor)));
SkIRect src; SkIRect src;
reader->readIRect(&src); reader->readIRect(&src);
lattice.fBounds = &src; lattice.fBounds = &src;

View File

@ -550,9 +550,12 @@ void SkPictureRecord::onDrawImageNine(const SkImage* img, const SkIRect& center,
void SkPictureRecord::onDrawImageLattice(const SkImage* image, const Lattice& lattice, void SkPictureRecord::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
const SkRect& dst, const SkPaint* paint) { const SkRect& dst, const SkPaint* paint) {
// xCount + xDivs + yCount+ yDivs // xCount + xDivs + yCount+ yDivs
int flagCount = (nullptr == lattice.fFlags) ? 0 : (lattice.fXCount + 1) * (lattice.fYCount + 1); int flagCount = (nullptr == lattice.fRectTypes) ? 0 :
(lattice.fXCount + 1) * (lattice.fYCount + 1);
size_t latticeSize = (1 + lattice.fXCount + 1 + lattice.fYCount + 1) * kUInt32Size + size_t latticeSize = (1 + lattice.fXCount + 1 + lattice.fYCount + 1) * kUInt32Size +
SkAlign4(flagCount * sizeof(SkCanvas::Lattice::Flags)) + sizeof(SkIRect); SkAlign4(flagCount * sizeof(SkCanvas::Lattice::RectType)) +
SkAlign4(flagCount * sizeof(SkColor)) +
sizeof(SkIRect);
// op + paint index + image index + lattice + dst rect // op + paint index + image index + lattice + dst rect
size_t size = 3 * kUInt32Size + latticeSize + sizeof(dst); size_t size = 3 * kUInt32Size + latticeSize + sizeof(dst);
@ -564,7 +567,8 @@ void SkPictureRecord::onDrawImageLattice(const SkImage* image, const Lattice& la
this->addInt(lattice.fYCount); this->addInt(lattice.fYCount);
fWriter.writePad(lattice.fYDivs, lattice.fYCount * kUInt32Size); fWriter.writePad(lattice.fYDivs, lattice.fYCount * kUInt32Size);
this->addInt(flagCount); this->addInt(flagCount);
fWriter.writePad(lattice.fFlags, flagCount * sizeof(SkCanvas::Lattice::Flags)); fWriter.writePad(lattice.fRectTypes, flagCount * sizeof(SkCanvas::Lattice::RectType));
fWriter.writePad(lattice.fColors, flagCount * sizeof(SkColor));
SkASSERT(lattice.fBounds); SkASSERT(lattice.fBounds);
this->addIRect(*lattice.fBounds); this->addIRect(*lattice.fBounds);
this->addRect(dst); this->addRect(dst);

View File

@ -101,7 +101,8 @@ template <> void Draw::draw(const DrawImageLattice& r) {
lattice.fXDivs = r.xDivs; lattice.fXDivs = r.xDivs;
lattice.fYCount = r.yCount; lattice.fYCount = r.yCount;
lattice.fYDivs = r.yDivs; lattice.fYDivs = r.yDivs;
lattice.fFlags = (0 == r.flagCount) ? nullptr : r.flags; lattice.fRectTypes = (0 == r.flagCount) ? nullptr : r.flags;
lattice.fColors = (0 == r.flagCount) ? nullptr : r.colors;
lattice.fBounds = &r.src; lattice.fBounds = &r.src;
fCanvas->drawImageLattice(r.image.get(), lattice, r.dst, r.paint); fCanvas->drawImageLattice(r.image.get(), lattice, r.dst, r.paint);
} }

View File

@ -238,12 +238,13 @@ void SkRecorder::onDrawImageNine(const SkImage* image, const SkIRect& center,
void SkRecorder::onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst, void SkRecorder::onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
const SkPaint* paint) { const SkPaint* paint) {
int flagCount = lattice.fFlags ? (lattice.fXCount + 1) * (lattice.fYCount + 1) : 0; int flagCount = lattice.fRectTypes ? (lattice.fXCount + 1) * (lattice.fYCount + 1) : 0;
SkASSERT(lattice.fBounds); SkASSERT(lattice.fBounds);
APPEND(DrawImageLattice, this->copy(paint), sk_ref_sp(image), APPEND(DrawImageLattice, this->copy(paint), sk_ref_sp(image),
lattice.fXCount, this->copy(lattice.fXDivs, lattice.fXCount), lattice.fXCount, this->copy(lattice.fXDivs, lattice.fXCount),
lattice.fYCount, this->copy(lattice.fYDivs, lattice.fYCount), lattice.fYCount, this->copy(lattice.fYDivs, lattice.fYCount),
flagCount, this->copy(lattice.fFlags, flagCount), *lattice.fBounds, dst); flagCount, this->copy(lattice.fRectTypes, flagCount),
this->copy(lattice.fColors, flagCount), *lattice.fBounds, dst);
} }
void SkRecorder::onDrawText(const void* text, size_t byteLength, void SkRecorder::onDrawText(const void* text, size_t byteLength,

View File

@ -256,7 +256,8 @@ RECORD(DrawImageLattice, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag,
int yCount; int yCount;
PODArray<int> yDivs; PODArray<int> yDivs;
int flagCount; int flagCount;
PODArray<SkCanvas::Lattice::Flags> flags; PODArray<SkCanvas::Lattice::RectType> flags;
PODArray<SkColor> colors;
SkIRect src; SkIRect src;
SkRect dst); SkRect dst);
RECORD(DrawImageRect, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag, RECORD(DrawImageRect, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag,

View File

@ -244,7 +244,8 @@ GR_DRAW_OP_TEST_DEFINE(NonAALatticeOp) {
// edge of the image subset, respectively. // edge of the image subset, respectively.
std::unique_ptr<int[]> xdivs; std::unique_ptr<int[]> xdivs;
std::unique_ptr<int[]> ydivs; std::unique_ptr<int[]> ydivs;
std::unique_ptr<SkCanvas::Lattice::Flags[]> flags; std::unique_ptr<SkCanvas::Lattice::RectType[]> flags;
std::unique_ptr<SkColor[]> colors;
SkIRect subset; SkIRect subset;
do { do {
imgW = random->nextRangeU(1, 1000); imgW = random->nextRangeU(1, 1000);
@ -271,14 +272,17 @@ GR_DRAW_OP_TEST_DEFINE(NonAALatticeOp) {
bool hasFlags = random->nextBool(); bool hasFlags = random->nextBool();
if (hasFlags) { if (hasFlags) {
int n = (lattice.fXCount + 1) * (lattice.fYCount + 1); int n = (lattice.fXCount + 1) * (lattice.fYCount + 1);
flags.reset(new SkCanvas::Lattice::Flags[n]); flags.reset(new SkCanvas::Lattice::RectType[n]);
colors.reset(new SkColor[n]);
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
flags[i] = random->nextBool() ? SkCanvas::Lattice::kTransparent_Flags flags[i] = random->nextBool() ? SkCanvas::Lattice::kTransparent
: (SkCanvas::Lattice::Flags)0; : SkCanvas::Lattice::kDefault;
} }
lattice.fFlags = flags.get(); lattice.fRectTypes = flags.get();
lattice.fColors = colors.get();
} else { } else {
lattice.fFlags = nullptr; lattice.fRectTypes = nullptr;
lattice.fColors = nullptr;
} }
} while (!SkLatticeIter::Valid(imgW, imgH, lattice)); } while (!SkLatticeIter::Valid(imgW, imgH, lattice));

View File

@ -556,7 +556,7 @@ void SkPipeCanvas::onDrawImageLattice(const SkImage* image, const Lattice& latti
if (paint) { if (paint) {
extra |= kHasPaint_DrawImageLatticeMask; extra |= kHasPaint_DrawImageLatticeMask;
} }
if (lattice.fFlags) { if (lattice.fRectTypes) {
extra |= kHasFlags_DrawImageLatticeMask; extra |= kHasFlags_DrawImageLatticeMask;
} }
if (lattice.fXCount >= kCount_DrawImageLatticeMask) { if (lattice.fXCount >= kCount_DrawImageLatticeMask) {
@ -583,10 +583,11 @@ void SkPipeCanvas::onDrawImageLattice(const SkImage* image, const Lattice& latti
// so we can store them smaller. // so we can store them smaller.
writer.write(lattice.fXDivs, lattice.fXCount * sizeof(int32_t)); writer.write(lattice.fXDivs, lattice.fXCount * sizeof(int32_t));
writer.write(lattice.fYDivs, lattice.fYCount * sizeof(int32_t)); writer.write(lattice.fYDivs, lattice.fYCount * sizeof(int32_t));
if (lattice.fFlags) { if (lattice.fRectTypes) {
int32_t count = (lattice.fXCount + 1) * (lattice.fYCount + 1); int32_t count = (lattice.fXCount + 1) * (lattice.fYCount + 1);
SkASSERT(count > 0); SkASSERT(count > 0);
write_pad(&writer, lattice.fFlags, count); write_pad(&writer, lattice.fRectTypes, count);
write_pad(&writer, lattice.fColors, count*sizeof(SkColor));
} }
SkASSERT(lattice.fBounds); SkASSERT(lattice.fBounds);
writer.write(&lattice.fBounds, sizeof(*lattice.fBounds)); writer.write(&lattice.fBounds, sizeof(*lattice.fBounds));

View File

@ -560,9 +560,11 @@ static void drawImageLattice_handler(SkPipeReader& reader, uint32_t packedVerb,
if (packedVerb & kHasFlags_DrawImageLatticeMask) { if (packedVerb & kHasFlags_DrawImageLatticeMask) {
int32_t count = (lattice.fXCount + 1) * (lattice.fYCount + 1); int32_t count = (lattice.fXCount + 1) * (lattice.fYCount + 1);
SkASSERT(count > 0); SkASSERT(count > 0);
lattice.fFlags = skip<SkCanvas::Lattice::Flags>(reader, SkAlign4(count)); lattice.fRectTypes = skip<SkCanvas::Lattice::RectType>(reader, SkAlign4(count));
lattice.fColors = skip<SkColor>(reader, SkAlign4(count));
} else { } else {
lattice.fFlags = nullptr; lattice.fRectTypes = nullptr;
lattice.fColors = nullptr;
} }
lattice.fBounds = skip<SkIRect>(reader); lattice.fBounds = skip<SkIRect>(reader);
const SkRect* dst = skip<SkRect>(reader); const SkRect* dst = skip<SkRect>(reader);

View File

@ -1272,13 +1272,13 @@ Json::Value SkDrawCommand::MakeJsonLattice(const SkCanvas::Lattice& lattice) {
YDivs.append(Json::Value(lattice.fYDivs[i])); YDivs.append(Json::Value(lattice.fYDivs[i]));
} }
result[SKDEBUGCANVAS_ATTRIBUTE_LATTICEYDIVS] = YDivs; result[SKDEBUGCANVAS_ATTRIBUTE_LATTICEYDIVS] = YDivs;
if (nullptr != lattice.fFlags) { if (nullptr != lattice.fRectTypes) {
Json::Value flags(Json::arrayValue); Json::Value flags(Json::arrayValue);
int flagCount = 0; int flagCount = 0;
for (int row = 0; row < lattice.fYCount+1; row++) { for (int row = 0; row < lattice.fYCount+1; row++) {
Json::Value flagsRow(Json::arrayValue); Json::Value flagsRow(Json::arrayValue);
for (int column = 0; column < lattice.fXCount+1; column++) { for (int column = 0; column < lattice.fXCount+1; column++) {
flagsRow.append(Json::Value(lattice.fFlags[flagCount++])); flagsRow.append(Json::Value(lattice.fRectTypes[flagCount++]));
} }
flags.append(flagsRow); flags.append(flagsRow);
} }