diff options
-rw-r--r-- | gm/ninepatchstretch.cpp | 69 | ||||
-rw-r--r-- | gyp/core.gypi | 1 | ||||
-rw-r--r-- | include/core/SkCanvas.h | 22 | ||||
-rw-r--r-- | include/core/SkDevice.h | 4 | ||||
-rw-r--r-- | include/utils/SkDeferredCanvas.h | 2 | ||||
-rw-r--r-- | src/core/SkCanvas.cpp | 123 | ||||
-rw-r--r-- | src/core/SkDevice.cpp | 21 | ||||
-rw-r--r-- | src/core/SkNinePatchIter.cpp | 72 | ||||
-rw-r--r-- | src/core/SkNinePatchIter.h | 42 | ||||
-rw-r--r-- | src/core/SkPictureFlat.h | 3 | ||||
-rw-r--r-- | src/core/SkPicturePlayback.cpp | 7 | ||||
-rw-r--r-- | src/core/SkPictureRecord.cpp | 17 | ||||
-rw-r--r-- | src/core/SkPictureRecord.h | 2 | ||||
-rw-r--r-- | src/core/SkRecordDraw.cpp | 4 | ||||
-rw-r--r-- | src/core/SkRecorder.cpp | 5 | ||||
-rw-r--r-- | src/core/SkRecorder.h | 2 | ||||
-rw-r--r-- | src/core/SkRecords.h | 5 | ||||
-rw-r--r-- | src/pipe/SkGPipePriv.h | 1 | ||||
-rw-r--r-- | src/pipe/SkGPipeRead.cpp | 14 | ||||
-rw-r--r-- | src/pipe/SkGPipeWrite.cpp | 12 | ||||
-rw-r--r-- | src/utils/SkDeferredCanvas.cpp | 16 |
21 files changed, 349 insertions, 95 deletions
diff --git a/gm/ninepatchstretch.cpp b/gm/ninepatchstretch.cpp index 5031480aa5..267c41587b 100644 --- a/gm/ninepatchstretch.cpp +++ b/gm/ninepatchstretch.cpp @@ -6,15 +6,24 @@ */ #include "gm.h" +#include "SkSurface.h" -static void make_bitmap(SkBitmap* bitmap, SkIRect* center) { +static SkSurface* make_surface(SkCanvas* root, int N) { + SkImageInfo info = SkImageInfo::MakeN32Premul(N, N); + SkSurface* surface = root->newSurface(info); + if (!surface) { + surface = SkSurface::NewRaster(info); + } + return surface; +} + +static SkImage* make_image(SkCanvas* root, SkIRect* center) { const int kFixed = 28; const int kStretchy = 8; const int kSize = 2*kFixed + kStretchy; - bitmap->allocN32Pixels(kSize, kSize); - SkCanvas canvas(*bitmap); - canvas.clear(SK_ColorTRANSPARENT); + SkAutoTUnref<SkSurface> surface(make_surface(root, kSize)); + SkCanvas* canvas = surface->getCanvas(); SkRect r = SkRect::MakeWH(SkIntToScalar(kSize), SkIntToScalar(kSize)); const SkScalar strokeWidth = SkIntToScalar(6); @@ -26,39 +35,48 @@ static void make_bitmap(SkBitmap* bitmap, SkIRect* center) { paint.setAntiAlias(true); paint.setColor(0xFFFF0000); - canvas.drawRoundRect(r, radius, radius, paint); + canvas->drawRoundRect(r, radius, radius, paint); r.setXYWH(SkIntToScalar(kFixed), 0, SkIntToScalar(kStretchy), SkIntToScalar(kSize)); paint.setColor(0x8800FF00); - canvas.drawRect(r, paint); + canvas->drawRect(r, paint); r.setXYWH(0, SkIntToScalar(kFixed), SkIntToScalar(kSize), SkIntToScalar(kStretchy)); paint.setColor(0x880000FF); - canvas.drawRect(r, paint); + canvas->drawRect(r, paint); + + return surface->newImageSnapshot(); } -namespace skiagm { +static void image_to_bitmap(const SkImage* image, SkBitmap* bm) { + SkImageInfo info = SkImageInfo::MakeN32Premul(image->width(), image->height()); + bm->allocPixels(info); + image->readPixels(info, bm->getPixels(), bm->rowBytes(), 0, 0); +} -class NinePatchStretchGM : public GM { +class NinePatchStretchGM : public skiagm::GM { public: - SkBitmap fBM; + SkAutoTUnref<SkImage> fImage; + SkBitmap fBitmap; + SkIRect fCenter; NinePatchStretchGM() {} protected: - virtual SkString onShortName() { + SkString onShortName() override { return SkString("ninepatch-stretch"); } - virtual SkISize onISize() { - return SkISize::Make(400, 400); + SkISize onISize() override { + return SkISize::Make(760, 400); } - virtual void onDraw(SkCanvas* canvas) { - SkBitmap bm; - SkIRect center; - make_bitmap(&bm, ¢er); + void onDraw(SkCanvas* canvas) override { + if (NULL == fBitmap.pixelRef()) { + fImage.reset(make_image(canvas, &fCenter)); + image_to_bitmap(fImage, &fBitmap); + } // amount of bm that should not be stretched (unless we have to) - const SkScalar fixed = SkIntToScalar(bm.width() - center.width()); + const SkScalar fixed = SkIntToScalar(fBitmap.width() - fCenter.width()); const SkTSize<SkScalar> size[] = { { fixed * 4 / 5, fixed * 4 / 5 }, // shrink in both axes @@ -67,7 +85,7 @@ protected: { fixed * 4, fixed * 4 } }; - canvas->drawBitmap(bm, SkIntToScalar(10), SkIntToScalar(10), NULL); + canvas->drawBitmap(fBitmap, 10, 10, NULL); SkScalar x = SkIntToScalar(100); SkScalar y = SkIntToScalar(100); @@ -80,18 +98,15 @@ protected: int i = ix * 2 + iy; SkRect r = SkRect::MakeXYWH(x + ix * fixed, y + iy * fixed, size[i].width(), size[i].height()); - canvas->drawBitmapNine(bm, center, r, &paint); + canvas->drawBitmapNine(fBitmap, fCenter, r, &paint); + canvas->drawImageNine(fImage, fCenter, r.makeOffset(360, 0), &paint); + } } } private: - typedef GM INHERITED; + typedef skiagm::GM INHERITED; }; +DEF_GM( return new NinePatchStretchGM; ) -////////////////////////////////////////////////////////////////////////////// - -static GM* MyFactory(void*) { return new NinePatchStretchGM; } -static GMRegistry reg(MyFactory); - -} diff --git a/gyp/core.gypi b/gyp/core.gypi index c41ba187eb..4da1685c10 100644 --- a/gyp/core.gypi +++ b/gyp/core.gypi @@ -134,6 +134,7 @@ '<(skia_src_path)/core/SkMipMap.cpp', '<(skia_src_path)/core/SkMiniRecorder.cpp', '<(skia_src_path)/core/SkMultiPictureDraw.cpp', + '<(skia_src_path)/core/SkNinePatchIter.cpp', '<(skia_src_path)/core/SkPackBits.cpp', '<(skia_src_path)/core/SkPaint.cpp', '<(skia_src_path)/core/SkPaintPriv.cpp', diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h index 7bdb6d219c..7bff02a6a9 100644 --- a/include/core/SkCanvas.h +++ b/include/core/SkCanvas.h @@ -792,6 +792,23 @@ public: void drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst, const SkPaint* paint = NULL); + /** + * Draw the image stretched differentially to fit into dst. + * center is a rect within the image, and logically divides the image + * into 9 sections (3x3). For example, if the middle pixel of a [5x5] + * image is the "center", then the center-rect should be [2, 2, 3, 3]. + * + * If the dst is >= the image size, then... + * - The 4 corners are not stretched at all. + * - The sides are stretched in only one axis. + * - The center is stretched in both axes. + * Else, for each axis where dst < image, + * - The corners shrink proportionally + * - The sides (along the shrink axis) and center are not drawn + */ + void drawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst, + const SkPaint* paint = NULL); + /** Draw the specified bitmap, with its top/left corner at (x,y), using the specified paint, transformed by the current matrix. Note: if the paint contains a maskfilter that generates a mask which extends beyond the @@ -1230,6 +1247,9 @@ protected: virtual void onDrawPath(const SkPath&, const SkPaint&); virtual void onDrawImage(const SkImage*, SkScalar dx, SkScalar dy, const SkPaint*); virtual void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*); + virtual void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst, + const SkPaint*); + virtual void onDrawBitmap(const SkBitmap&, SkScalar dx, SkScalar dy, const SkPaint*); virtual void onDrawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint*, DrawBitmapRectFlags); @@ -1347,8 +1367,6 @@ private: void internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, const SkPaint* paint, DrawBitmapRectFlags flags); - void internalDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, - const SkRect& dst, const SkPaint* paint); void internalDrawPaint(const SkPaint& paint); void internalSaveLayer(const SkRect* bounds, const SkPaint*, SaveFlags, SaveLayerStrategy); void internalDrawDevice(SkBaseDevice*, int x, int y, const SkPaint*, bool isBitmapDevice); diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h index 2db685a96e..6b00c104fc 100644 --- a/include/core/SkDevice.h +++ b/include/core/SkDevice.h @@ -220,10 +220,14 @@ protected: const SkRect* srcOrNull, const SkRect& dst, const SkPaint& paint, SkCanvas::DrawBitmapRectFlags flags) = 0; + virtual void drawBitmapNine(const SkDraw&, const SkBitmap&, const SkIRect& center, + const SkRect& dst, const SkPaint&); virtual void drawImage(const SkDraw&, const SkImage*, SkScalar x, SkScalar y, const SkPaint&); virtual void drawImageRect(const SkDraw&, const SkImage*, const SkRect* src, const SkRect& dst, const SkPaint&); + virtual void drawImageNine(const SkDraw&, const SkImage*, const SkIRect& center, + const SkRect& dst, const SkPaint&); /** * Does not handle text decoration. diff --git a/include/utils/SkDeferredCanvas.h b/include/utils/SkDeferredCanvas.h index 4ace35f22f..1f5b12a417 100644 --- a/include/utils/SkDeferredCanvas.h +++ b/include/utils/SkDeferredCanvas.h @@ -178,6 +178,8 @@ protected: void onDrawImage(const SkImage*, SkScalar left, SkScalar top, const SkPaint*) override; void onDrawImageRect(const SkImage*, const SkRect* src, const SkRect& dst, const SkPaint*) override; + void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst, + const SkPaint*) override; void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst, const SkPaint*) override; void onDrawSprite(const SkBitmap&, int left, int top, const SkPaint*) override; diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index d7c62e8e11..88339ff4f3 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -16,6 +16,7 @@ #include "SkErrorInternals.h" #include "SkImage.h" #include "SkMetaData.h" +#include "SkNinePatchIter.h" #include "SkPathOps.h" #include "SkPatchUtils.h" #include "SkPicture.h" @@ -1771,8 +1772,19 @@ void SkCanvas::drawImageRect(const SkImage* image, const SkRect* src, const SkRe this->onDrawImageRect(image, src, dst, paint); } +void SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst, + const SkPaint* paint) { + if (dst.isEmpty()) { + return; + } + if (!SkNinePatchIter::Valid(image->width(), image->height(), center)) { + this->drawImageRect(image, NULL, dst, paint); + } + this->onDrawImageNine(image, center, dst, paint); +} + void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) { - if (bitmap.empty()) { + if (bitmap.drawsNothing()) { return; } this->onDrawBitmap(bitmap, dx, dy, paint); @@ -1780,7 +1792,7 @@ void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, cons void SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, const SkPaint* paint, DrawBitmapRectFlags flags) { - if (bitmap.empty()) { + if (bitmap.drawsNothing() || dst.isEmpty()) { return; } this->onDrawBitmapRect(bitmap, src, dst, paint, flags); @@ -1788,14 +1800,17 @@ void SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, c void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, const SkPaint* paint) { - if (bitmap.empty()) { + if (bitmap.drawsNothing() || dst.isEmpty()) { return; } + if (!SkNinePatchIter::Valid(bitmap.width(), bitmap.height(), center)) { + this->drawBitmapRectToRect(bitmap, NULL, dst, paint); + } this->onDrawBitmapNine(bitmap, center, dst, paint); } void SkCanvas::drawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint* paint) { - if (bitmap.empty()) { + if (bitmap.drawsNothing()) { return; } this->onDrawSprite(bitmap, left, top, paint); @@ -2116,15 +2131,13 @@ void SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const this->internalDrawBitmapRect(bitmap, src, dst, paint, flags); } -void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap, - const SkIRect& center, const SkRect& dst, - const SkPaint* paint) { - if (bitmap.drawsNothing()) { - return; - } +void SkCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst, + const SkPaint* paint) { + TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageNine()"); + + SkRect storage; + const SkRect* bounds = &dst; if (NULL == paint || paint->canComputeFastBounds()) { - SkRect storage; - const SkRect* bounds = &dst; if (paint) { bounds = &paint->computeFastBounds(dst, &storage); } @@ -2132,58 +2145,19 @@ void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap, return; } } - - const int32_t w = bitmap.width(); - const int32_t h = bitmap.height(); - - SkIRect c = center; - // pin center to the bounds of the bitmap - c.fLeft = SkMax32(0, center.fLeft); - c.fTop = SkMax32(0, center.fTop); - c.fRight = SkPin32(center.fRight, c.fLeft, w); - c.fBottom = SkPin32(center.fBottom, c.fTop, h); - - const SkScalar srcX[4] = { - 0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w) - }; - const SkScalar srcY[4] = { - 0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h) - }; - SkScalar dstX[4] = { - dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft), - dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight - }; - SkScalar dstY[4] = { - dst.fTop, dst.fTop + SkIntToScalar(c.fTop), - dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom - }; - - if (dstX[1] > dstX[2]) { - dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width()); - dstX[2] = dstX[1]; - } - - if (dstY[1] > dstY[2]) { - dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height()); - dstY[2] = dstY[1]; + + SkLazyPaint lazy; + if (NULL == paint) { + paint = lazy.init(); } - - for (int y = 0; y < 3; y++) { - SkRect s, d; - - s.fTop = srcY[y]; - s.fBottom = srcY[y+1]; - d.fTop = dstY[y]; - d.fBottom = dstY[y+1]; - for (int x = 0; x < 3; x++) { - s.fLeft = srcX[x]; - s.fRight = srcX[x+1]; - d.fLeft = dstX[x]; - d.fRight = dstX[x+1]; - this->internalDrawBitmapRect(bitmap, &s, d, paint, - kNone_DrawBitmapRectFlag); - } + + LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds) + + while (iter.next()) { + iter.fDevice->drawImageNine(iter, image, center, dst, looper.paint()); } + + LOOPER_END } void SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, @@ -2191,8 +2165,29 @@ void SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, c TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()"); SkDEBUGCODE(bitmap.validate();) - // Need a device entry-point, so gpu can use a mesh - this->internalDrawBitmapNine(bitmap, center, dst, paint); + SkRect storage; + const SkRect* bounds = &dst; + if (NULL == paint || paint->canComputeFastBounds()) { + if (paint) { + bounds = &paint->computeFastBounds(dst, &storage); + } + if (this->quickReject(*bounds)) { + return; + } + } + + SkLazyPaint lazy; + if (NULL == paint) { + paint = lazy.init(); + } + + LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds) + + while (iter.next()) { + iter.fDevice->drawBitmapNine(iter, bitmap, center, dst, looper.paint()); + } + + LOOPER_END } class SkDeviceFilteredPaint { diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp index 8f7f50c863..90161b4eb3 100644 --- a/src/core/SkDevice.cpp +++ b/src/core/SkDevice.cpp @@ -11,6 +11,7 @@ #include "SkDrawFilter.h" #include "SkImage_Base.h" #include "SkMetaData.h" +#include "SkNinePatchIter.h" #include "SkPatchUtils.h" #include "SkPathMeasure.h" #include "SkRasterClip.h" @@ -161,6 +162,26 @@ void SkBaseDevice::drawImageRect(const SkDraw& draw, const SkImage* image, const } } +void SkBaseDevice::drawImageNine(const SkDraw& draw, const SkImage* image, const SkIRect& center, + const SkRect& dst, const SkPaint& paint) { + SkNinePatchIter iter(image->width(), image->height(), center, dst); + + SkRect srcR, dstR; + while (iter.next(&srcR, &dstR)) { + this->drawImageRect(draw, image, &srcR, dstR, paint); + } +} + +void SkBaseDevice::drawBitmapNine(const SkDraw& draw, const SkBitmap& bitmap, const SkIRect& center, + const SkRect& dst, const SkPaint& paint) { + SkNinePatchIter iter(bitmap.width(), bitmap.height(), center, dst); + + SkRect srcR, dstR; + while (iter.next(&srcR, &dstR)) { + this->drawBitmapRect(draw, bitmap, &srcR, dstR, paint, SkCanvas::kNone_DrawBitmapRectFlag); + } +} + void SkBaseDevice::drawAtlas(const SkDraw& draw, const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], const SkColor colors[], int count, SkXfermode::Mode mode, const SkPaint& paint) { diff --git a/src/core/SkNinePatchIter.cpp b/src/core/SkNinePatchIter.cpp new file mode 100644 index 0000000000..c6bd16dcdb --- /dev/null +++ b/src/core/SkNinePatchIter.cpp @@ -0,0 +1,72 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkNinePatchIter.h" +#include "SkRect.h" + +bool SkNinePatchIter::Valid(int width, int height, const SkIRect& center) { + return !center.isEmpty() && SkIRect::MakeWH(width, height).contains(center); +} + +SkNinePatchIter::SkNinePatchIter(int w, int h, const SkIRect& c, const SkRect& dst) { + SkASSERT(SkIRect::MakeWH(w, h).contains(c)); + + fSrcX[0] = 0; + fSrcX[1] = SkIntToScalar(c.fLeft); + fSrcX[2] = SkIntToScalar(c.fRight); + fSrcX[3] = SkIntToScalar(w); + + fSrcY[0] = 0; + fSrcY[1] = SkIntToScalar(c.fTop); + fSrcY[2] = SkIntToScalar(c.fBottom); + fSrcY[3] = SkIntToScalar(h); + + fDstX[0] = dst.fLeft; + fDstX[1] = dst.fLeft + SkIntToScalar(c.fLeft); + fDstX[2] = dst.fRight - SkIntToScalar(w - c.fRight); + fDstX[3] = dst.fRight; + + fDstY[0] = dst.fTop; + fDstY[1] = dst.fTop + SkIntToScalar(c.fTop); + fDstY[2] = dst.fBottom - SkIntToScalar(h - c.fBottom); + fDstY[3] = dst.fBottom; + + if (fDstX[1] > fDstX[2]) { + fDstX[1] = fDstX[0] + (fDstX[3] - fDstX[0]) * c.fLeft / (w - c.width()); + fDstX[2] = fDstX[1]; + } + + if (fDstY[1] > fDstY[2]) { + fDstY[1] = fDstY[0] + (fDstY[3] - fDstY[0]) * c.fTop / (h - c.height()); + fDstY[2] = fDstY[1]; + } + + fCurrX = fCurrY = 0; + fDone = false; +} + +bool SkNinePatchIter::next(SkRect* src, SkRect* dst) { + if (fDone) { + return false; + } + + const int x = fCurrX; + const int y = fCurrY; + SkASSERT(x >= 0 && x < 4); + SkASSERT(y >= 0 && y < 4); + + 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 (4 == ++fCurrX) { + fCurrX = 0; + fCurrY += 1; + if (fCurrY >= 4) { + fDone = true; + } + } + return true; +} diff --git a/src/core/SkNinePatchIter.h b/src/core/SkNinePatchIter.h new file mode 100644 index 0000000000..2d7e9a8b19 --- /dev/null +++ b/src/core/SkNinePatchIter.h @@ -0,0 +1,42 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkNinePatchIter_DEFINED +#define SkNinePatchIter_DEFINED + +#include "SkScalar.h" + +struct SkIRect; +struct SkRect; + +/** + * Disect a ninepatch request into an sequence of src-rect / dst-rect pairs + */ +class SkNinePatchIter { +public: + static bool Valid(int imageWidth, int imageHeight, const SkIRect& center); + + SkNinePatchIter(int imageWidth, int imageHeight, const SkIRect& center, const SkRect& dst); + + /** + * While it returns true, use src/dst to draw the image/bitmap + */ + bool next(SkRect* src, SkRect* dst); + +private: + SkScalar fSrcX[4]; + SkScalar fSrcY[4]; + SkScalar fDstX[4]; + SkScalar fDstY[4]; + + int fCurrX; + int fCurrY; + bool fDone; +}; + +#endif + diff --git a/src/core/SkPictureFlat.h b/src/core/SkPictureFlat.h index 07411002ae..d421c47603 100644 --- a/src/core/SkPictureFlat.h +++ b/src/core/SkPictureFlat.h @@ -72,8 +72,9 @@ enum DrawType { DRAW_IMAGE, DRAW_IMAGE_RECT, DRAW_ATLAS, + DRAW_IMAGE_NINE, - LAST_DRAWTYPE_ENUM = DRAW_ATLAS + LAST_DRAWTYPE_ENUM = DRAW_IMAGE_NINE }; // In the 'match' method, this constant will match any flavor of DRAW_BITMAP* diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp index a1bb1ba293..1cf1a1bfb4 100644 --- a/src/core/SkPicturePlayback.cpp +++ b/src/core/SkPicturePlayback.cpp @@ -242,6 +242,13 @@ void SkPicturePlayback::handleOp(SkReader32* reader, const SkPoint& loc = reader->skipT<SkPoint>(); canvas->drawImage(image, loc.fX, loc.fY, paint); } break; + case DRAW_IMAGE_NINE: { + const SkPaint* paint = fPictureData->getPaint(reader); + const SkImage* image = fPictureData->getImage(reader); + const SkIRect& center = reader->skipT<SkIRect>(); + const SkRect& dst = reader->skipT<SkRect>(); + canvas->drawImageNine(image, center, dst, paint); + } break; case DRAW_IMAGE_RECT: { const SkPaint* paint = fPictureData->getPaint(reader); const SkImage* image = fPictureData->getImage(reader); diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp index 0fbf98089a..5f85b47aac 100644 --- a/src/core/SkPictureRecord.cpp +++ b/src/core/SkPictureRecord.cpp @@ -101,6 +101,7 @@ static inline size_t get_paint_offset(DrawType op, size_t opSize) { 1, // DRAW_IMAGE - right after op code 1, // DRAW_IMAGE_RECT - right after op code 1, // DRAW_ATLAS - right after op code + 1, // DRAW_IMAGE_NINE - right after op code }; SK_COMPILE_ASSERT(sizeof(gPaintOffsets) == LAST_DRAWTYPE_ENUM + 1, @@ -584,7 +585,7 @@ void SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, void SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst, const SkPaint* paint) { - // id + paint_index + bitmap_index + bool_for_src + // id + paint_index + image_index + bool_for_src size_t size = 4 * kUInt32Size; if (src) { size += sizeof(*src); // + rect @@ -601,6 +602,20 @@ void SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, c this->validate(initialOffset, size); } +void SkPictureRecord::onDrawImageNine(const SkImage* img, const SkIRect& center, const SkRect& dst, + const SkPaint* paint) { + // id + paint_index + image_index + center + dst + size_t size = 3 * kUInt32Size + sizeof(SkIRect) + sizeof(SkRect); + + size_t initialOffset = this->addDraw(DRAW_IMAGE_NINE, &size); + SkASSERT(initialOffset+get_paint_offset(DRAW_IMAGE_NINE, size) == fWriter.bytesWritten()); + this->addPaintPtr(paint); + this->addImage(img); + this->addIRect(center); + this->addRect(dst); + this->validate(initialOffset, size); +} + void SkPictureRecord::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, const SkPaint* paint) { // op + paint index + bitmap id + center + dst rect diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h index cee5ea35f5..e2d5f7d1df 100644 --- a/src/core/SkPictureRecord.h +++ b/src/core/SkPictureRecord.h @@ -188,6 +188,8 @@ protected: void onDrawImage(const SkImage*, SkScalar left, SkScalar top, const SkPaint*) override; void onDrawImageRect(const SkImage*, const SkRect* src, const SkRect& dst, const SkPaint*) override; + void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst, + const SkPaint*) override; void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst, const SkPaint*) override; void onDrawSprite(const SkBitmap&, int left, int top, const SkPaint*) override; diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp index 944443c8ee..af71624474 100644 --- a/src/core/SkRecordDraw.cpp +++ b/src/core/SkRecordDraw.cpp @@ -97,6 +97,7 @@ DRAW(DrawBitmapRectToRectBleed, DRAW(DrawDRRect, drawDRRect(r.outer, r.inner, r.paint)); DRAW(DrawImage, drawImage(r.image, r.left, r.top, r.paint)); DRAW(DrawImageRect, drawImageRect(r.image, r.src, r.dst, r.paint)); +DRAW(DrawImageNine, drawImageNine(r.image, r.center, r.dst, r.paint)); DRAW(DrawOval, drawOval(r.oval, r.paint)); DRAW(DrawPaint, drawPaint(r.paint)); DRAW(DrawPath, drawPath(r.path, r.paint)); @@ -413,6 +414,9 @@ private: Bounds bounds(const DrawImageRect& op) const { return this->adjustAndMap(op.dst, op.paint); } + Bounds bounds(const DrawImageNine& op) const { + return this->adjustAndMap(op.dst, op.paint); + } Bounds bounds(const DrawBitmapRectToRect& op) const { return this->adjustAndMap(op.dst, op.paint); } diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp index 812fd9d49c..c27405575c 100644 --- a/src/core/SkRecorder.cpp +++ b/src/core/SkRecorder.cpp @@ -222,6 +222,11 @@ void SkRecorder::onDrawImageRect(const SkImage* image, const SkRect* src, APPEND(DrawImageRect, this->copy(paint), image, this->copy(src), dst); } +void SkRecorder::onDrawImageNine(const SkImage* image, const SkIRect& center, + const SkRect& dst, const SkPaint* paint) { + APPEND(DrawImageNine, this->copy(paint), image, center, dst); +} + void SkRecorder::onDrawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint* paint) { APPEND(DrawSprite, this->copy(paint), delay_copy(bitmap), left, top); } diff --git a/src/core/SkRecorder.h b/src/core/SkRecorder.h index 53c658fa6f..3809ae239d 100644 --- a/src/core/SkRecorder.h +++ b/src/core/SkRecorder.h @@ -100,6 +100,8 @@ public: void onDrawImage(const SkImage*, SkScalar left, SkScalar top, const SkPaint*) override; void onDrawImageRect(const SkImage*, const SkRect* src, const SkRect& dst, const SkPaint*) override; + void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst, + const SkPaint*) override; void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst, const SkPaint*) override; void onDrawSprite(const SkBitmap&, int left, int top, const SkPaint*) override; diff --git a/src/core/SkRecords.h b/src/core/SkRecords.h index 381f91438b..8e778bf7a2 100644 --- a/src/core/SkRecords.h +++ b/src/core/SkRecords.h @@ -44,6 +44,7 @@ namespace SkRecords { M(DrawDrawable) \ M(DrawImage) \ M(DrawImageRect) \ + M(DrawImageNine) \ M(DrawDRRect) \ M(DrawOval) \ M(DrawPaint) \ @@ -288,6 +289,10 @@ RECORD4(DrawImageRect, Optional<SkPaint>, paint, RefBox<const SkImage>, image, Optional<SkRect>, src, SkRect, dst); +RECORD4(DrawImageNine, Optional<SkPaint>, paint, + RefBox<const SkImage>, image, + SkIRect, center, + SkRect, dst); RECORD2(DrawOval, SkPaint, paint, SkRect, oval); RECORD1(DrawPaint, SkPaint, paint); RECORD2(DrawPath, SkPaint, paint, PreCachedPath, path); diff --git a/src/pipe/SkGPipePriv.h b/src/pipe/SkGPipePriv.h index 2f246e452c..614853dd92 100644 --- a/src/pipe/SkGPipePriv.h +++ b/src/pipe/SkGPipePriv.h @@ -46,6 +46,7 @@ enum DrawOps { kDrawDRRect_DrawOp, kDrawImage_DrawOp, kDrawImageRect_DrawOp, + kDrawImageNine_DrawOp, kDrawOval_DrawOp, kDrawPaint_DrawOp, kDrawPatch_DrawOp, diff --git a/src/pipe/SkGPipeRead.cpp b/src/pipe/SkGPipeRead.cpp index 8d3048d76f..48e0c0641b 100644 --- a/src/pipe/SkGPipeRead.cpp +++ b/src/pipe/SkGPipeRead.cpp @@ -695,6 +695,19 @@ static void drawImageRect_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32 } } +static void drawImageNine_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32, + SkGPipeState* state) { + unsigned slot = DrawOp_unpackData(op32); + unsigned flags = DrawOp_unpackFlags(op32); + bool hasPaint = SkToBool(flags & kDrawBitmap_HasPaint_DrawOpFlag); + const SkIRect* center = skip<SkIRect>(reader); + const SkRect* dst = skip<SkRect>(reader); + const SkImage* image = state->getImage(slot); + if (state->shouldDraw()) { + canvas->drawImageNine(image, *center, *dst, hasPaint ? &state->paint() : NULL); + } +} + /////////////////////////////////////////////////////////////////////////////// static void drawPicture_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32, @@ -866,6 +879,7 @@ static const ReadProc gReadTable[] = { drawDRRect_rp, drawImage_rp, drawImageRect_rp, + drawImageNine_rp, drawOval_rp, drawPaint_rp, drawPatch_rp, diff --git a/src/pipe/SkGPipeWrite.cpp b/src/pipe/SkGPipeWrite.cpp index f2aaaae216..4dbb5b536c 100644 --- a/src/pipe/SkGPipeWrite.cpp +++ b/src/pipe/SkGPipeWrite.cpp @@ -280,6 +280,8 @@ protected: void onDrawImage(const SkImage*, SkScalar left, SkScalar top, const SkPaint*) override; void onDrawImageRect(const SkImage*, const SkRect* src, const SkRect& dst, const SkPaint*) override; + void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst, + const SkPaint*) override; void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst, const SkPaint*) override; void onDrawSprite(const SkBitmap&, int left, int top, const SkPaint*) override; @@ -883,6 +885,16 @@ void SkGPipeCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, con } } +void SkGPipeCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst, + const SkPaint* paint) { + NOTIFY_SETUP(this); + size_t opBytesNeeded = sizeof(SkIRect) + sizeof(SkRect); // center + dst + if (this->commonDrawImage(image, kDrawImageNine_DrawOp, 0, opBytesNeeded, paint)) { + fWriter.writeIRect(center); + fWriter.writeRect(dst); + } +} + void SkGPipeCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, const SkPaint& paint) { if (byteLength) { diff --git a/src/utils/SkDeferredCanvas.cpp b/src/utils/SkDeferredCanvas.cpp index ccf0b012b1..8e34235848 100644 --- a/src/utils/SkDeferredCanvas.cpp +++ b/src/utils/SkDeferredCanvas.cpp @@ -229,6 +229,9 @@ protected: void drawImageRect(const SkDraw&, const SkImage*, const SkRect*, const SkRect&, const SkPaint&) override {SkASSERT(0);} + void drawImageNine(const SkDraw&, const SkImage*, const SkIRect&, const SkRect&, + const SkPaint&) override + {SkASSERT(0);} void drawText(const SkDraw&, const void* text, size_t len, SkScalar x, SkScalar y, const SkPaint& paint) override {SkASSERT(0);} @@ -903,6 +906,19 @@ void SkDeferredCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, this->recordedDrawCommand(); } +void SkDeferredCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, + const SkRect& dst, const SkPaint* paint) { + if (fDeferredDrawing && + this->isFullFrame(&dst, paint) && + isPaintOpaque(paint, image)) { + this->getDeferredDevice()->skipPendingCommands(); + } + + AutoImmediateDrawIfNeeded autoDraw(*this, image, paint); + this->drawingCanvas()->drawImageNine(image, center, dst, paint); + this->recordedDrawCommand(); +} + void SkDeferredCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, const SkPaint* paint) { |