Add drawImageLattice() and drawBitmapLattice() APIs
The specified image/bitmap is divided into rects, which can be draw stretched, shrunk, or at a fixed size. Will be used by Android to draw 9patch (which are acutally N-patch) images. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1992283002 Review-Url: https://codereview.chromium.org/1992283002
This commit is contained in:
parent
7d0e3bc785
commit
c573a40ed5
59
bench/DrawLatticeBench.cpp
Normal file
59
bench/DrawLatticeBench.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2016 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "Benchmark.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkRect.h"
|
||||
#include "SkString.h"
|
||||
|
||||
class DrawLatticeBench : public Benchmark {
|
||||
public:
|
||||
DrawLatticeBench(int* xDivs, int xCount, int* yDivs, int yCount, const SkISize& srcSize,
|
||||
const SkRect& dst, const char* desc)
|
||||
: fSrcSize(srcSize)
|
||||
, fDst(dst)
|
||||
{
|
||||
fLattice.fXDivs = xDivs;
|
||||
fLattice.fXCount = xCount;
|
||||
fLattice.fYDivs = yDivs;
|
||||
fLattice.fYCount = yCount;
|
||||
|
||||
fName = SkStringPrintf("DrawLattice_%s", desc);
|
||||
}
|
||||
|
||||
const char* onGetName() override {
|
||||
return fName.c_str();
|
||||
}
|
||||
|
||||
bool isSuitableFor(Backend backend) override {
|
||||
return kRaster_Backend == backend || kGPU_Backend == backend;
|
||||
}
|
||||
|
||||
void onDelayedSetup() override {
|
||||
fBitmap.allocN32Pixels(fSrcSize.width(), fSrcSize.height());
|
||||
fBitmap.eraseColor(0x880000FF);
|
||||
}
|
||||
|
||||
void onDraw(int loops, SkCanvas* canvas) override {
|
||||
for (int i = 0; i < loops; i++) {
|
||||
canvas->drawBitmapLattice(fBitmap, fLattice, fDst);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
SkISize fSrcSize;
|
||||
SkCanvas::Lattice fLattice;
|
||||
SkRect fDst;
|
||||
SkString fName;
|
||||
SkBitmap fBitmap;
|
||||
|
||||
typedef Benchmark INHERITED;
|
||||
};
|
||||
|
||||
static int gDivs[2] = { 250, 750, };
|
||||
DEF_BENCH(return new DrawLatticeBench(gDivs, 2, gDivs, 2, SkISize::Make(1000, 1000),
|
||||
SkRect::MakeWH(4000.0f, 4000.0f), "StandardNine");)
|
147
gm/lattice.cpp
Normal file
147
gm/lattice.cpp
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright 2016 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "gm.h"
|
||||
#include "SkSurface.h"
|
||||
|
||||
static sk_sp<SkSurface> make_surface(SkCanvas* root, int N) {
|
||||
SkImageInfo info = SkImageInfo::MakeN32Premul(N, N);
|
||||
auto surface = root->makeSurface(info);
|
||||
if (!surface) {
|
||||
surface = SkSurface::MakeRaster(info);
|
||||
}
|
||||
return surface;
|
||||
}
|
||||
|
||||
static sk_sp<SkImage> make_image(SkCanvas* root, int* xDivs, int* yDivs) {
|
||||
const int kCap = 28;
|
||||
const int kMid = 8;
|
||||
const int kSize = 2*kCap + 3*kMid;
|
||||
|
||||
auto surface(make_surface(root, kSize));
|
||||
SkCanvas* canvas = surface->getCanvas();
|
||||
|
||||
SkRect r = SkRect::MakeWH(SkIntToScalar(kSize), SkIntToScalar(kSize));
|
||||
const SkScalar strokeWidth = SkIntToScalar(6);
|
||||
const SkScalar radius = SkIntToScalar(kCap) - strokeWidth/2;
|
||||
|
||||
xDivs[0] = yDivs[0] = kCap;
|
||||
xDivs[1] = yDivs[1] = kCap + kMid;
|
||||
xDivs[2] = yDivs[2] = kCap + 2 * kMid;
|
||||
xDivs[3] = yDivs[3] = kCap + 3 * kMid;
|
||||
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(true);
|
||||
|
||||
paint.setColor(0xFFFFFF00);
|
||||
canvas->drawRoundRect(r, radius, radius, paint);
|
||||
|
||||
r.setXYWH(SkIntToScalar(kCap), 0, SkIntToScalar(kMid), SkIntToScalar(kSize));
|
||||
paint.setColor(0x8800FF00);
|
||||
canvas->drawRect(r, paint);
|
||||
r.setXYWH(SkIntToScalar(kCap + kMid), 0, SkIntToScalar(kMid), SkIntToScalar(kSize));
|
||||
paint.setColor(0x880000FF);
|
||||
canvas->drawRect(r, paint);
|
||||
r.setXYWH(SkIntToScalar(kCap + 2*kMid), 0, SkIntToScalar(kMid), SkIntToScalar(kSize));
|
||||
paint.setColor(0x88FF00FF);
|
||||
canvas->drawRect(r, paint);
|
||||
|
||||
r.setXYWH(0, SkIntToScalar(kCap), SkIntToScalar(kSize), SkIntToScalar(kMid));
|
||||
paint.setColor(0x8800FF00);
|
||||
canvas->drawRect(r, paint);
|
||||
r.setXYWH(0, SkIntToScalar(kCap + kMid), SkIntToScalar(kSize), SkIntToScalar(kMid));
|
||||
paint.setColor(0x880000FF);
|
||||
canvas->drawRect(r, paint);
|
||||
r.setXYWH(0, SkIntToScalar(kCap + 2*kMid), SkIntToScalar(kSize), SkIntToScalar(kMid));
|
||||
paint.setColor(0x88FF00FF);
|
||||
canvas->drawRect(r, paint);
|
||||
|
||||
return surface->makeImageSnapshot();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is similar to NinePatchStretchGM, but it also tests "ninepatch" images with more
|
||||
* than nine patches.
|
||||
*/
|
||||
class LatticeGM : public skiagm::GM {
|
||||
public:
|
||||
LatticeGM() {}
|
||||
|
||||
protected:
|
||||
SkString onShortName() override {
|
||||
return SkString("lattice");
|
||||
}
|
||||
|
||||
SkISize onISize() override {
|
||||
return SkISize::Make(800, 400);
|
||||
}
|
||||
|
||||
void onDraw(SkCanvas* canvas) override {
|
||||
int xDivs[5];
|
||||
int yDivs[5];
|
||||
xDivs[0] = 0;
|
||||
yDivs[0] = 0;
|
||||
|
||||
SkBitmap bitmap;
|
||||
sk_sp<SkImage> image = make_image(canvas, xDivs + 1, yDivs + 1);
|
||||
image_to_bitmap(image.get(), &bitmap);
|
||||
|
||||
const SkTSize<SkScalar> size[] = {
|
||||
{ 50, 50, }, // shrink in both axes
|
||||
{ 50, 200, }, // shrink in X
|
||||
{ 200, 50, }, // shrink in Y
|
||||
{ 200, 200, },
|
||||
};
|
||||
|
||||
canvas->drawImage(image, 10, 10, nullptr);
|
||||
|
||||
SkScalar x = SkIntToScalar(100);
|
||||
SkScalar y = SkIntToScalar(100);
|
||||
|
||||
SkCanvas::Lattice lattice;
|
||||
lattice.fXCount = 4;
|
||||
lattice.fXDivs = xDivs + 1;
|
||||
lattice.fYCount = 4;
|
||||
lattice.fYDivs = yDivs + 1;
|
||||
|
||||
for (int iy = 0; iy < 2; ++iy) {
|
||||
for (int ix = 0; ix < 2; ++ix) {
|
||||
int i = ix * 2 + iy;
|
||||
SkRect r = SkRect::MakeXYWH(x + ix * 60, y + iy * 60,
|
||||
size[i].width(), size[i].height());
|
||||
canvas->drawBitmapLattice(bitmap, lattice, r);
|
||||
}
|
||||
}
|
||||
|
||||
// Include the degenerate first div. While normally the first patch is "scalable",
|
||||
// this will mean that the first non-degenerate patch is "fixed".
|
||||
lattice.fXCount = 5;
|
||||
lattice.fXDivs = xDivs;
|
||||
lattice.fYCount = 5;
|
||||
lattice.fYDivs = yDivs;
|
||||
|
||||
canvas->translate(400, 0);
|
||||
for (int iy = 0; iy < 2; ++iy) {
|
||||
for (int ix = 0; ix < 2; ++ix) {
|
||||
int i = ix * 2 + iy;
|
||||
SkRect r = SkRect::MakeXYWH(x + ix * 60, y + iy * 60,
|
||||
size[i].width(), size[i].height());
|
||||
canvas->drawImageLattice(image.get(), lattice, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
typedef skiagm::GM INHERITED;
|
||||
};
|
||||
DEF_GM( return new LatticeGM; )
|
@ -187,8 +187,8 @@
|
||||
'<(skia_src_path)/core/SkModeColorFilter.cpp',
|
||||
'<(skia_src_path)/core/SkMultiPictureDraw.cpp',
|
||||
'<(skia_src_path)/core/SkNextID.h',
|
||||
'<(skia_src_path)/core/SkNinePatchIter.cpp',
|
||||
'<(skia_src_path)/core/SkNinePatchIter.h',
|
||||
'<(skia_src_path)/core/SkLatticeIter.cpp',
|
||||
'<(skia_src_path)/core/SkLatticeIter.h',
|
||||
'<(skia_src_path)/core/SkNormalBevelSource.cpp',
|
||||
'<(skia_src_path)/core/SkNormalBevelSource.h',
|
||||
'<(skia_src_path)/core/SkNormalMapSource.cpp',
|
||||
|
@ -938,7 +938,7 @@ public:
|
||||
SrcRectConstraint = kStrict_SrcRectConstraint);
|
||||
|
||||
/**
|
||||
* Draw the bitmap stretched differentially to fit into dst.
|
||||
* Draw the bitmap stretched or shrunk differentially to fit into dst.
|
||||
* center is a rect within the bitmap, and logically divides the bitmap
|
||||
* into 9 sections (3x3). For example, if the middle pixel of a [5x5]
|
||||
* bitmap is the "center", then the center-rect should be [2, 2, 3, 3].
|
||||
@ -954,6 +954,47 @@ public:
|
||||
void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
|
||||
const SkPaint* paint = NULL);
|
||||
|
||||
/**
|
||||
* Specifies coordinates to divide a bitmap into (xCount*yCount) rects.
|
||||
*/
|
||||
struct Lattice {
|
||||
// An array of x-coordinates that divide the bitmap vertically.
|
||||
// These must be unique, increasing, and in the set [0, width].
|
||||
// Does not have ownership.
|
||||
const int* fXDivs;
|
||||
|
||||
// The number of fXDivs.
|
||||
int fXCount;
|
||||
|
||||
// An array of y-coordinates that divide the bitmap horizontally.
|
||||
// These must be unique, increasing, and in the set [0, height].
|
||||
// Does not have ownership.
|
||||
const int* fYDivs;
|
||||
|
||||
// The number of fYDivs.
|
||||
int fYCount;
|
||||
};
|
||||
|
||||
/**
|
||||
* Draw the bitmap stretched or shrunk differentially to fit into dst.
|
||||
*
|
||||
* Moving horizontally across the bitmap, alternating rects will be "scalable"
|
||||
* (in the x-dimension) to fit into dst or must be left "fixed". The first rect
|
||||
* is treated as "fixed", but it's possible to specify an empty first rect by
|
||||
* making lattice.fXDivs[0] = 0.
|
||||
*
|
||||
* The scale factor for all "scalable" rects will be the same, and may be greater
|
||||
* than or less than 1 (meaning we can stretch or shrink). If the number of
|
||||
* "fixed" pixels is greater than the width of the dst, we will collapse all of
|
||||
* the "scalable" regions and appropriately downscale the "fixed" regions.
|
||||
*
|
||||
* The same interpretation also applies to the y-dimension.
|
||||
*/
|
||||
void drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
|
||||
const SkPaint* paint = nullptr);
|
||||
void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
|
||||
const SkPaint* paint = nullptr);
|
||||
|
||||
/** Draw the text, with origin at (x,y), using the specified paint.
|
||||
The origin is interpreted based on the Align setting in the paint.
|
||||
@param text The text to be drawn
|
||||
@ -1435,6 +1476,8 @@ protected:
|
||||
SrcRectConstraint);
|
||||
virtual void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
|
||||
const SkPaint*);
|
||||
virtual void onDrawImageLattice(const SkImage*, const Lattice& lattice, const SkRect& dst,
|
||||
const SkPaint*);
|
||||
|
||||
enum ClipEdgeStyle {
|
||||
kHard_ClipEdgeStyle,
|
||||
|
@ -197,13 +197,15 @@ protected:
|
||||
const SkPaint& paint,
|
||||
SkCanvas::SrcRectConstraint) = 0;
|
||||
virtual void drawBitmapNine(const SkDraw&, const SkBitmap&, const SkIRect& center,
|
||||
const SkRect& dst, const SkPaint&);
|
||||
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&, SkCanvas::SrcRectConstraint);
|
||||
virtual void drawImageNine(const SkDraw&, const SkImage*, const SkIRect& center,
|
||||
const SkRect& dst, const SkPaint&);
|
||||
virtual void drawImageLattice(const SkDraw&, const SkImage*, const SkCanvas::Lattice&,
|
||||
const SkRect& dst, const SkPaint&);
|
||||
|
||||
/**
|
||||
* Does not handle text decoration.
|
||||
|
@ -55,6 +55,7 @@ namespace SkRecords {
|
||||
M(ClipRegion) \
|
||||
M(DrawDrawable) \
|
||||
M(DrawImage) \
|
||||
M(DrawImageLattice) \
|
||||
M(DrawImageRect) \
|
||||
M(DrawImageNine) \
|
||||
M(DrawDRRect) \
|
||||
@ -222,6 +223,14 @@ RECORD(DrawImage, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag,
|
||||
sk_sp<const SkImage> image;
|
||||
SkScalar left;
|
||||
SkScalar top);
|
||||
RECORD(DrawImageLattice, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag,
|
||||
Optional<SkPaint> paint;
|
||||
sk_sp<const SkImage> image;
|
||||
int xCount;
|
||||
PODArray<int> xDivs;
|
||||
int yCount;
|
||||
PODArray<int> yDivs;
|
||||
SkRect dst);
|
||||
RECORD(DrawImageRect, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag,
|
||||
Optional<SkPaint> paint;
|
||||
sk_sp<const SkImage> image;
|
||||
|
@ -19,9 +19,9 @@
|
||||
#include "SkImage_Base.h"
|
||||
#include "SkImageFilter.h"
|
||||
#include "SkImageFilterCache.h"
|
||||
#include "SkLatticeIter.h"
|
||||
#include "SkMatrixUtils.h"
|
||||
#include "SkMetaData.h"
|
||||
#include "SkNinePatchIter.h"
|
||||
#include "SkPaintPriv.h"
|
||||
#include "SkPatchUtils.h"
|
||||
#include "SkPicture.h"
|
||||
@ -1985,7 +1985,7 @@ void SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const
|
||||
if (dst.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (!SkNinePatchIter::Valid(image->width(), image->height(), center)) {
|
||||
if (!SkLatticeIter::Valid(image->width(), image->height(), center)) {
|
||||
this->drawImageRect(image, dst, paint);
|
||||
}
|
||||
this->onDrawImageNine(image, center, dst, paint);
|
||||
@ -2022,12 +2022,30 @@ void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, con
|
||||
if (bitmap.drawsNothing() || dst.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (!SkNinePatchIter::Valid(bitmap.width(), bitmap.height(), center)) {
|
||||
if (!SkLatticeIter::Valid(bitmap.width(), bitmap.height(), center)) {
|
||||
this->drawBitmapRect(bitmap, dst, paint);
|
||||
}
|
||||
this->onDrawBitmapNine(bitmap, center, dst, paint);
|
||||
}
|
||||
|
||||
void SkCanvas::drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
|
||||
const SkPaint* paint) {
|
||||
sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
|
||||
this->drawImageLattice(image.get(), lattice, dst, paint);
|
||||
}
|
||||
|
||||
void SkCanvas::drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
|
||||
const SkPaint* paint) {
|
||||
RETURN_ON_NULL(image);
|
||||
if (dst.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (!SkLatticeIter::Valid(image->width(), image->height(), lattice)) {
|
||||
this->drawImageRect(image, dst, paint);
|
||||
}
|
||||
this->onDrawImageLattice(image, lattice, dst, paint);
|
||||
}
|
||||
|
||||
void SkCanvas::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
|
||||
const SkColor colors[], int count, SkXfermode::Mode mode,
|
||||
const SkRect* cull, const SkPaint* paint) {
|
||||
@ -2332,6 +2350,29 @@ void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const S
|
||||
LOOPER_END
|
||||
}
|
||||
|
||||
void SkCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
|
||||
const SkPaint* paint) {
|
||||
if (nullptr == paint || paint->canComputeFastBounds()) {
|
||||
SkRect storage;
|
||||
if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SkLazyPaint lazy;
|
||||
if (nullptr == paint) {
|
||||
paint = lazy.init();
|
||||
}
|
||||
|
||||
LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
|
||||
|
||||
while (iter.next()) {
|
||||
iter.fDevice->drawImageLattice(iter, image, lattice, dst, looper.paint());
|
||||
}
|
||||
|
||||
LOOPER_END
|
||||
}
|
||||
|
||||
void SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
|
||||
const SkPaint* paint, SrcRectConstraint constraint) {
|
||||
TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()");
|
||||
|
@ -12,8 +12,8 @@
|
||||
#include "SkImage_Base.h"
|
||||
#include "SkImageFilter.h"
|
||||
#include "SkImageFilterCache.h"
|
||||
#include "SkLatticeIter.h"
|
||||
#include "SkMetaData.h"
|
||||
#include "SkNinePatchIter.h"
|
||||
#include "SkPatchUtils.h"
|
||||
#include "SkPathMeasure.h"
|
||||
#include "SkRasterClip.h"
|
||||
@ -152,6 +152,17 @@ void SkBaseDevice::drawImage(const SkDraw& draw, const SkImage* image, SkScalar
|
||||
}
|
||||
}
|
||||
|
||||
void SkBaseDevice::drawImageLattice(const SkDraw& draw, const SkImage* image,
|
||||
const SkCanvas::Lattice& lattice, const SkRect& dst,
|
||||
const SkPaint& paint) {
|
||||
SkLatticeIter iter(image->width(), image->height(), lattice, dst);
|
||||
|
||||
SkRect srcR, dstR;
|
||||
while (iter.next(&srcR, &dstR)) {
|
||||
this->drawImageRect(draw, image, &srcR, dstR, paint, SkCanvas::kStrict_SrcRectConstraint);
|
||||
}
|
||||
}
|
||||
|
||||
void SkBaseDevice::drawImageRect(const SkDraw& draw, const SkImage* image, const SkRect* src,
|
||||
const SkRect& dst, const SkPaint& paint,
|
||||
SkCanvas::SrcRectConstraint constraint) {
|
||||
@ -164,7 +175,7 @@ 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);
|
||||
SkLatticeIter iter(image->width(), image->height(), center, dst);
|
||||
|
||||
SkRect srcR, dstR;
|
||||
while (iter.next(&srcR, &dstR)) {
|
||||
@ -174,7 +185,7 @@ void SkBaseDevice::drawImageNine(const SkDraw& draw, const SkImage* image, const
|
||||
|
||||
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);
|
||||
SkLatticeIter iter(bitmap.width(), bitmap.height(), center, dst);
|
||||
|
||||
SkRect srcR, dstR;
|
||||
while (iter.next(&srcR, &dstR)) {
|
||||
|
230
src/core/SkLatticeIter.cpp
Normal file
230
src/core/SkLatticeIter.cpp
Normal file
@ -0,0 +1,230 @@
|
||||
/*
|
||||
* 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 "SkLatticeIter.h"
|
||||
#include "SkRect.h"
|
||||
|
||||
/**
|
||||
* Divs must be in increasing order with no duplicates.
|
||||
*/
|
||||
static bool valid_divs(const int* divs, int count, int len) {
|
||||
if (count <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int prev = -1;
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (prev >= divs[i] || divs[i] > len) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SkLatticeIter::Valid(int width, int height, const SkCanvas::Lattice& lattice) {
|
||||
return valid_divs(lattice.fXDivs, lattice.fXCount, width) &&
|
||||
valid_divs(lattice.fYDivs, lattice.fYCount, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the number of pixels that are in "scalable" patches.
|
||||
*/
|
||||
static int count_scalable_pixels(const int32_t* divs, int numDivs, bool firstIsScalable,
|
||||
int length) {
|
||||
if (0 == numDivs) {
|
||||
return firstIsScalable ? length : 0;
|
||||
}
|
||||
|
||||
int i;
|
||||
int count;
|
||||
if (firstIsScalable) {
|
||||
count = divs[0];
|
||||
i = 1;
|
||||
} else {
|
||||
count = 0;
|
||||
i = 0;
|
||||
}
|
||||
|
||||
for (; i < numDivs; i += 2) {
|
||||
// Alternatively, we could use |top| and |bottom| as variable names, instead of
|
||||
// |left| and |right|.
|
||||
int left = divs[i];
|
||||
int right = (i + 1 < numDivs) ? divs[i + 1] : length;
|
||||
count += right - left;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set points for the src and dst rects on subsequent draw calls.
|
||||
*/
|
||||
static void set_points(float* dst, float* src, const int* divs, int divCount, int srcFixed,
|
||||
int srcScalable, float dstStart, float dstStop, bool isScalable) {
|
||||
|
||||
float dstLen = dstStop - dstStart;
|
||||
int srcLen = srcFixed + srcScalable;
|
||||
float scale;
|
||||
if (srcFixed <= dstLen) {
|
||||
// This is the "normal" case, where we scale the "scalable" patches and leave
|
||||
// the other patches fixed.
|
||||
scale = (dstLen - ((float) srcFixed)) / ((float) srcScalable);
|
||||
} else {
|
||||
// In this case, we eliminate the "scalable" patches and scale the "fixed" patches.
|
||||
scale = dstLen / ((float) srcFixed);
|
||||
}
|
||||
|
||||
src[0] = 0.0f;
|
||||
dst[0] = dstStart;
|
||||
for (int i = 0; i < divCount; i++) {
|
||||
src[i + 1] = (float) (divs[i]);
|
||||
float srcDelta = src[i + 1] - src[i];
|
||||
float dstDelta;
|
||||
if (srcFixed <= dstLen) {
|
||||
dstDelta = isScalable ? scale * srcDelta : srcDelta;
|
||||
} else {
|
||||
dstDelta = isScalable ? 0.0f : scale * srcDelta;
|
||||
}
|
||||
dst[i + 1] = dst[i] + dstDelta;
|
||||
|
||||
// Alternate between "scalable" and "fixed" patches.
|
||||
isScalable = !isScalable;
|
||||
}
|
||||
|
||||
src[divCount + 1] = (float) srcLen;
|
||||
dst[divCount + 1] = dstStop;
|
||||
}
|
||||
|
||||
SkLatticeIter::SkLatticeIter(int srcWidth, int srcHeight, const SkCanvas::Lattice& lattice,
|
||||
const SkRect& dst)
|
||||
{
|
||||
const int* xDivs = lattice.fXDivs;
|
||||
int xCount = lattice.fXCount;
|
||||
const int* yDivs = lattice.fYDivs;
|
||||
int yCount = lattice.fYCount;
|
||||
|
||||
// In the x-dimension, the first rectangle always starts at x = 0 and is "scalable".
|
||||
// If xDiv[0] is 0, it indicates that the first rectangle is degenerate, so the
|
||||
// first real rectangle "scalable" in the x-direction.
|
||||
//
|
||||
// The same interpretation applies to the y-dimension.
|
||||
//
|
||||
// As we move left to right across the image, alternating patches will be "fixed" or
|
||||
// "scalable" in the x-direction. Similarly, as move top to bottom, alternating
|
||||
// patches will be "fixed" or "scalable" in the y-direction.
|
||||
SkASSERT(xCount > 0 && yCount > 0);
|
||||
bool xIsScalable = (0 == xDivs[0]);
|
||||
if (xIsScalable) {
|
||||
// Once we've decided that the first patch is "scalable", we don't need the
|
||||
// xDiv. It is always implied that we start at zero.
|
||||
xDivs++;
|
||||
xCount--;
|
||||
}
|
||||
bool yIsScalable = (0 == yDivs[0]);
|
||||
if (yIsScalable) {
|
||||
// Once we've decided that the first patch is "scalable", we don't need the
|
||||
// yDiv. It is always implied that we start at zero.
|
||||
yDivs++;
|
||||
yCount--;
|
||||
}
|
||||
|
||||
// We never need the final xDiv/yDiv if it is equal to the width/height. This is implied.
|
||||
if (xCount > 0 && srcWidth == xDivs[xCount - 1]) {
|
||||
xCount--;
|
||||
}
|
||||
if (yCount > 0 && srcHeight == yDivs[yCount - 1]) {
|
||||
yCount--;
|
||||
}
|
||||
|
||||
// Count "scalable" and "fixed" pixels in each dimension.
|
||||
int xCountScalable = count_scalable_pixels(xDivs, xCount, xIsScalable, srcWidth);
|
||||
int xCountFixed = srcWidth - xCountScalable;
|
||||
int yCountScalable = count_scalable_pixels(yDivs, yCount, yIsScalable, srcHeight);
|
||||
int yCountFixed = srcHeight - yCountScalable;
|
||||
|
||||
fSrcX.reset(xCount + 2);
|
||||
fDstX.reset(xCount + 2);
|
||||
set_points(fDstX.begin(), fSrcX.begin(), xDivs, xCount, xCountFixed, xCountScalable,
|
||||
dst.fLeft, dst.fRight, xIsScalable);
|
||||
|
||||
fSrcY.reset(yCount + 2);
|
||||
fDstY.reset(yCount + 2);
|
||||
set_points(fDstY.begin(), fSrcY.begin(), yDivs, yCount, yCountFixed, yCountScalable,
|
||||
dst.fTop, dst.fBottom, yIsScalable);
|
||||
|
||||
fCurrX = fCurrY = 0;
|
||||
fDone = false;
|
||||
}
|
||||
|
||||
bool SkLatticeIter::Valid(int width, int height, const SkIRect& center) {
|
||||
return !center.isEmpty() && SkIRect::MakeWH(width, height).contains(center);
|
||||
}
|
||||
|
||||
SkLatticeIter::SkLatticeIter(int w, int h, const SkIRect& c, const SkRect& dst) {
|
||||
SkASSERT(SkIRect::MakeWH(w, h).contains(c));
|
||||
|
||||
fSrcX.reset(4);
|
||||
fSrcY.reset(4);
|
||||
fDstX.reset(4);
|
||||
fDstY.reset(4);
|
||||
|
||||
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 SkLatticeIter::next(SkRect* src, SkRect* dst) {
|
||||
if (fDone) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int x = fCurrX;
|
||||
const int y = fCurrY;
|
||||
SkASSERT(x >= 0 && x < fSrcX.count() - 1);
|
||||
SkASSERT(y >= 0 && y < fSrcY.count() - 1);
|
||||
|
||||
src->set(fSrcX[x], fSrcY[y], fSrcX[x + 1], fSrcY[y + 1]);
|
||||
dst->set(fDstX[x], fDstY[y], fDstX[x + 1], fDstY[y + 1]);
|
||||
if (fSrcX.count() - 1 == ++fCurrX) {
|
||||
fCurrX = 0;
|
||||
fCurrY += 1;
|
||||
if (fCurrY >= fSrcY.count() - 1) {
|
||||
fDone = true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
49
src/core/SkLatticeIter.h
Normal file
49
src/core/SkLatticeIter.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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 SkLatticeIter_DEFINED
|
||||
#define SkLatticeIter_DEFINED
|
||||
|
||||
#include "SkCanvas.h"
|
||||
#include "SkScalar.h"
|
||||
#include "SkTArray.h"
|
||||
|
||||
struct SkIRect;
|
||||
struct SkRect;
|
||||
|
||||
/**
|
||||
* Disect a lattice request into an sequence of src-rect / dst-rect pairs
|
||||
*/
|
||||
class SkLatticeIter {
|
||||
public:
|
||||
|
||||
static bool Valid(int imageWidth, int imageHeight, const SkCanvas::Lattice& lattice);
|
||||
|
||||
SkLatticeIter(int imageWidth, int imageHeight, const SkCanvas::Lattice& lattice,
|
||||
const SkRect& dst);
|
||||
|
||||
static bool Valid(int imageWidth, int imageHeight, const SkIRect& center);
|
||||
|
||||
SkLatticeIter(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:
|
||||
SkTArray<SkScalar> fSrcX;
|
||||
SkTArray<SkScalar> fSrcY;
|
||||
SkTArray<SkScalar> fDstX;
|
||||
SkTArray<SkScalar> fDstY;
|
||||
|
||||
int fCurrX;
|
||||
int fCurrY;
|
||||
bool fDone;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,72 +0,0 @@
|
||||
/*
|
||||
* 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 < 3);
|
||||
SkASSERT(y >= 0 && y < 3);
|
||||
|
||||
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 (3 == ++fCurrX) {
|
||||
fCurrX = 0;
|
||||
fCurrY += 1;
|
||||
if (fCurrY >= 3) {
|
||||
fDone = true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -91,8 +91,9 @@ enum DrawType {
|
||||
TRANSLATE_Z,
|
||||
|
||||
DRAW_SHADOWED_PICTURE_LIGHTS,
|
||||
DRAW_IMAGE_LATTICE,
|
||||
|
||||
LAST_DRAWTYPE_ENUM = DRAW_SHADOWED_PICTURE_LIGHTS
|
||||
LAST_DRAWTYPE_ENUM = DRAW_IMAGE_LATTICE
|
||||
};
|
||||
|
||||
// In the 'match' method, this constant will match any flavor of DRAW_BITMAP*
|
||||
|
@ -298,6 +298,18 @@ void SkPicturePlayback::handleOp(SkReadBuffer* reader,
|
||||
reader->readPoint(&loc);
|
||||
canvas->drawImage(image, loc.fX, loc.fY, paint);
|
||||
} break;
|
||||
case DRAW_IMAGE_LATTICE: {
|
||||
const SkPaint* paint = fPictureData->getPaint(reader);
|
||||
const SkImage* image = fPictureData->getImage(reader);
|
||||
SkCanvas::Lattice lattice;
|
||||
lattice.fXCount = reader->readInt();
|
||||
lattice.fXDivs = (const int*) reader->skip(lattice.fXCount * sizeof(int32_t));
|
||||
lattice.fYCount = reader->readInt();
|
||||
lattice.fYDivs = (const int*) reader->skip(lattice.fYCount * sizeof(int32_t));
|
||||
SkRect dst;
|
||||
reader->readRect(&dst);
|
||||
canvas->drawImageLattice(image, lattice, dst, paint);
|
||||
} break;
|
||||
case DRAW_IMAGE_NINE: {
|
||||
const SkPaint* paint = fPictureData->getPaint(reader);
|
||||
const SkImage* image = fPictureData->getImage(reader);
|
||||
|
@ -510,6 +510,24 @@ void SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
|
||||
this->validate(initialOffset, size);
|
||||
}
|
||||
|
||||
void SkPictureRecord::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
|
||||
const SkRect& dst, const SkPaint* paint) {
|
||||
// xCount + xDivs + yCount+ yDivs
|
||||
size_t latticeSize = (1 + lattice.fXCount + 1 + lattice.fYCount) * kUInt32Size;
|
||||
|
||||
// op + paint index + image index + lattice + dst rect
|
||||
size_t size = 3 * kUInt32Size + latticeSize + sizeof(dst);
|
||||
size_t initialOffset = this->addDraw(DRAW_IMAGE_LATTICE, &size);
|
||||
this->addPaintPtr(paint);
|
||||
this->addImage(image);
|
||||
this->addInt(lattice.fXCount);
|
||||
fWriter.writePad(lattice.fXDivs, lattice.fXCount * kUInt32Size);
|
||||
this->addInt(lattice.fYCount);
|
||||
fWriter.writePad(lattice.fYDivs, lattice.fYCount * kUInt32Size);
|
||||
this->addRect(dst);
|
||||
this->validate(initialOffset, size);
|
||||
}
|
||||
|
||||
void SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
|
||||
const SkPaint* paint, SrcRectConstraint constraint) {
|
||||
// id + paint_index + image_index + bool_for_src + constraint
|
||||
|
@ -194,6 +194,8 @@ protected:
|
||||
void onDrawBitmapRect(const SkBitmap&, const SkRect* src, const SkRect& dst, const SkPaint*,
|
||||
SrcRectConstraint) override;
|
||||
void onDrawImage(const SkImage*, SkScalar left, SkScalar top, const SkPaint*) override;
|
||||
void onDrawImageLattice(const SkImage*, const SkCanvas::Lattice& lattice, const SkRect& dst,
|
||||
const SkPaint*) override;
|
||||
void onDrawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,
|
||||
const SkPaint*, SrcRectConstraint) override;
|
||||
void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
|
||||
|
@ -97,6 +97,16 @@ template <> void Draw::draw(const TranslateZ& r) { }
|
||||
|
||||
DRAW(DrawDRRect, drawDRRect(r.outer, r.inner, r.paint));
|
||||
DRAW(DrawImage, drawImage(r.image.get(), r.left, r.top, r.paint));
|
||||
|
||||
template <> void Draw::draw(const DrawImageLattice& r) {
|
||||
SkCanvas::Lattice lattice;
|
||||
lattice.fXCount = r.xCount;
|
||||
lattice.fXDivs = r.xDivs;
|
||||
lattice.fYCount = r.yCount;
|
||||
lattice.fYDivs = r.yDivs;
|
||||
fCanvas->drawImageLattice(r.image.get(), lattice, r.dst, r.paint);
|
||||
}
|
||||
|
||||
DRAW(DrawImageRect, legacy_drawImageRect(r.image.get(), r.src, r.dst, r.paint, r.constraint));
|
||||
DRAW(DrawImageNine, drawImageNine(r.image.get(), r.center, r.dst, r.paint));
|
||||
DRAW(DrawOval, drawOval(r.oval, r.paint));
|
||||
@ -412,6 +422,9 @@ private:
|
||||
|
||||
return this->adjustAndMap(rect, op.paint);
|
||||
}
|
||||
Bounds bounds(const DrawImageLattice& op) const {
|
||||
return this->adjustAndMap(op.dst, op.paint);
|
||||
}
|
||||
Bounds bounds(const DrawImageRect& op) const {
|
||||
return this->adjustAndMap(op.dst, op.paint);
|
||||
}
|
||||
|
@ -211,6 +211,16 @@ void SkRecorder::onDrawImage(const SkImage* image, SkScalar left, SkScalar top,
|
||||
APPEND(DrawImage, this->copy(paint), sk_ref_sp(image), left, top);
|
||||
}
|
||||
|
||||
void SkRecorder::onDrawImageLattice(const SkImage* image,
|
||||
const Lattice& lattice,
|
||||
const SkRect& dst,
|
||||
const SkPaint* paint) {
|
||||
APPEND(DrawImageLattice, this->copy(paint), sk_ref_sp(image),
|
||||
lattice.fXCount, this->copy(lattice.fXDivs, lattice.fXCount),
|
||||
lattice.fYCount, this->copy(lattice.fYDivs, lattice.fYCount), dst);
|
||||
}
|
||||
|
||||
|
||||
void SkRecorder::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
|
||||
const SkPaint* paint, SrcRectConstraint constraint) {
|
||||
APPEND(DrawImageRect, this->copy(paint), sk_ref_sp(image), this->copy(src), dst, constraint);
|
||||
|
@ -111,6 +111,8 @@ public:
|
||||
void onDrawBitmapRect(const SkBitmap&, const SkRect* src, const SkRect& dst, const SkPaint*,
|
||||
SrcRectConstraint) override;
|
||||
void onDrawImage(const SkImage*, SkScalar left, SkScalar top, const SkPaint*) override;
|
||||
void onDrawImageLattice(const SkImage*, const Lattice& lattice, const SkRect& dst,
|
||||
const SkPaint*) override;
|
||||
void onDrawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,
|
||||
const SkPaint*, SrcRectConstraint) override;
|
||||
void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
|
||||
|
@ -24,8 +24,8 @@
|
||||
#include "SkImageCacherator.h"
|
||||
#include "SkImageFilter.h"
|
||||
#include "SkImageFilterCache.h"
|
||||
#include "SkLatticeIter.h"
|
||||
#include "SkMaskFilter.h"
|
||||
#include "SkNinePatchIter.h"
|
||||
#include "SkPathEffect.h"
|
||||
#include "SkPicture.h"
|
||||
#include "SkPictureData.h"
|
||||
@ -1446,7 +1446,7 @@ void SkGpuDevice::drawProducerNine(const SkDraw& draw, GrTextureProducer* produc
|
||||
GrSkFilterQualityToGrFilterMode(paint.getFilterQuality(), *draw.fMatrix, SkMatrix::I(),
|
||||
&doBicubic);
|
||||
if (useFallback || doBicubic || GrTextureParams::kNone_FilterMode != textureFilterMode) {
|
||||
SkNinePatchIter iter(producer->width(), producer->height(), center, dst);
|
||||
SkLatticeIter iter(producer->width(), producer->height(), center, dst);
|
||||
|
||||
SkRect srcR, dstR;
|
||||
while (iter.next(&srcR, &dstR)) {
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include "GrResourceProvider.h"
|
||||
#include "GrVertexBatch.h"
|
||||
#include "SkBitmap.h"
|
||||
#include "SkNinePatchIter.h"
|
||||
#include "SkLatticeIter.h"
|
||||
#include "SkRect.h"
|
||||
|
||||
static sk_sp<GrGeometryProcessor> create_gp(bool readsCoverage) {
|
||||
@ -101,7 +101,7 @@ private:
|
||||
i * kRectsPerInstance * kVertsPerRect * vertexStride;
|
||||
|
||||
const Patch& patch = fPatches[i];
|
||||
SkNinePatchIter iter(fImageWidth, fImageHeight, patch.fCenter, patch.fDst);
|
||||
SkLatticeIter iter(fImageWidth, fImageHeight, patch.fCenter, patch.fDst);
|
||||
|
||||
SkRect srcR, dstR;
|
||||
while (iter.next(&srcR, &dstR)) {
|
||||
|
@ -5,7 +5,7 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkNinePatchIter.h"
|
||||
#include "SkLatticeIter.h"
|
||||
#include "SkPDFCanvas.h"
|
||||
#include "SkPDFDevice.h"
|
||||
|
||||
@ -35,7 +35,7 @@ void SkPDFCanvas::onDrawBitmapNine(const SkBitmap& bitmap,
|
||||
const SkIRect& center,
|
||||
const SkRect& dst,
|
||||
const SkPaint* paint) {
|
||||
SkNinePatchIter iter(bitmap.width(), bitmap.height(), center, dst);
|
||||
SkLatticeIter iter(bitmap.width(), bitmap.height(), center, dst);
|
||||
SkRect srcR, dstR;
|
||||
while (iter.next(&srcR, &dstR)) {
|
||||
this->drawBitmapRect(bitmap, srcR, dstR, paint);
|
||||
@ -46,7 +46,7 @@ void SkPDFCanvas::onDrawImageNine(const SkImage* image,
|
||||
const SkIRect& center,
|
||||
const SkRect& dst,
|
||||
const SkPaint* paint) {
|
||||
SkNinePatchIter iter(image->width(), image->height(), center, dst);
|
||||
SkLatticeIter iter(image->width(), image->height(), center, dst);
|
||||
SkRect srcR, dstR;
|
||||
while (iter.next(&srcR, &dstR)) {
|
||||
this->drawImageRect(image, srcR, dstR, paint);
|
||||
@ -84,3 +84,14 @@ void SkPDFCanvas::onDrawBitmapRect(const SkBitmap& bitmap,
|
||||
SkMatrix::kFill_ScaleToFit));
|
||||
this->drawBitmap(bitmap, 0, 0, paint);
|
||||
}
|
||||
|
||||
void SkPDFCanvas::onDrawImageLattice(const SkImage* image,
|
||||
const Lattice& lattice,
|
||||
const SkRect& dst,
|
||||
const SkPaint* paint) {
|
||||
SkLatticeIter iter(image->width(), image->height(), lattice, dst);
|
||||
SkRect srcR, dstR;
|
||||
while (iter.next(&srcR, &dstR)) {
|
||||
this->drawImageRect(image, srcR, dstR, paint);
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,11 @@ protected:
|
||||
const SkPaint*,
|
||||
SkCanvas::SrcRectConstraint) override;
|
||||
|
||||
void onDrawImageLattice(const SkImage*,
|
||||
const Lattice& lattice,
|
||||
const SkRect& dst,
|
||||
const SkPaint*) override;
|
||||
|
||||
private:
|
||||
typedef SkCanvas INHERITED;
|
||||
};
|
||||
|
@ -994,12 +994,17 @@ static void draw_bitmaps(const SkBitmap bitmap, SkCanvas* canvas) {
|
||||
const SkPaint paint;
|
||||
const SkRect rect = { 5.0f, 5.0f, 8.0f, 8.0f };
|
||||
const SkIRect irect = { 2, 2, 3, 3 };
|
||||
int divs[] = { 2, 3 };
|
||||
SkCanvas::Lattice lattice;
|
||||
lattice.fXCount = lattice.fYCount = 2;
|
||||
lattice.fXDivs = lattice.fYDivs = divs;
|
||||
|
||||
// Don't care what these record, as long as they're legal.
|
||||
canvas->drawBitmap(bitmap, 0.0f, 0.0f, &paint);
|
||||
canvas->drawBitmapRect(bitmap, rect, rect, &paint, SkCanvas::kStrict_SrcRectConstraint);
|
||||
canvas->drawBitmapNine(bitmap, irect, rect, &paint);
|
||||
canvas->drawBitmap(bitmap, 1, 1); // drawSprite
|
||||
canvas->drawBitmapLattice(bitmap, lattice, rect, &paint);
|
||||
}
|
||||
|
||||
static void test_draw_bitmaps(SkCanvas* canvas) {
|
||||
|
Loading…
Reference in New Issue
Block a user