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:
parent
51493ee848
commit
ca8c0953e8
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
180
gm/lattice.cpp
180
gm/lattice.cpp
@ -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; )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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));
|
||||||
|
|
||||||
|
@ -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));
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user