add drawImageNine
this also exposes nine-patch drawing directly to devices, and creates a shared iterator for unrolling a nine-patch into single rect->rect draws. BUG=skia: Review URL: https://codereview.chromium.org/1211583003
This commit is contained in:
parent
b4022965a2
commit
4c21dc5ddf
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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',
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
void SkCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
|
||||
const SkPaint* paint) {
|
||||
if (bitmap.drawsNothing()) {
|
||||
return;
|
||||
}
|
||||
if (NULL == paint || paint->canComputeFastBounds()) {
|
||||
TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageNine()");
|
||||
|
||||
SkRect storage;
|
||||
const SkRect* bounds = &dst;
|
||||
if (NULL == paint || paint->canComputeFastBounds()) {
|
||||
if (paint) {
|
||||
bounds = &paint->computeFastBounds(dst, &storage);
|
||||
}
|
||||
@ -2133,57 +2146,18 @@ void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap,
|
||||
}
|
||||
}
|
||||
|
||||
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];
|
||||
SkLazyPaint lazy;
|
||||
if (NULL == paint) {
|
||||
paint = lazy.init();
|
||||
}
|
||||
|
||||
if (dstY[1] > dstY[2]) {
|
||||
dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height());
|
||||
dstY[2] = dstY[1];
|
||||
LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
|
||||
|
||||
while (iter.next()) {
|
||||
iter.fDevice->drawImageNine(iter, image, center, dst, looper.paint());
|
||||
}
|
||||
|
||||
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_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 {
|
||||
|
@ -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) {
|
||||
|
72
src/core/SkNinePatchIter.cpp
Normal file
72
src/core/SkNinePatchIter.cpp
Normal file
@ -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;
|
||||
}
|
42
src/core/SkNinePatchIter.h
Normal file
42
src/core/SkNinePatchIter.h
Normal file
@ -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
|
||||
|
@ -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*
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -46,6 +46,7 @@ enum DrawOps {
|
||||
kDrawDRRect_DrawOp,
|
||||
kDrawImage_DrawOp,
|
||||
kDrawImageRect_DrawOp,
|
||||
kDrawImageNine_DrawOp,
|
||||
kDrawOval_DrawOp,
|
||||
kDrawPaint_DrawOp,
|
||||
kDrawPatch_DrawOp,
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user