1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2016 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "gm/gm.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBitmap.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBlendMode.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImage.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageInfo.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkMalloc.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h"
25*c8dee2aaSAndroid Build Coastguard Worker
make_surface(SkCanvas * root,int N,int padLeft,int padTop,int padRight,int padBottom)26*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkSurface> make_surface(SkCanvas* root, int N, int padLeft, int padTop,
27*c8dee2aaSAndroid Build Coastguard Worker int padRight, int padBottom) {
28*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo info = SkImageInfo::MakeN32Premul(N + padLeft + padRight, N + padTop + padBottom);
29*c8dee2aaSAndroid Build Coastguard Worker return ToolUtils::makeSurface(root, info);
30*c8dee2aaSAndroid Build Coastguard Worker }
31*c8dee2aaSAndroid Build Coastguard Worker
make_image(SkCanvas * root,int * xDivs,int * yDivs,int padLeft,int padTop,int padRight,int padBottom)32*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkImage> make_image(SkCanvas* root, int* xDivs, int* yDivs, int padLeft, int padTop,
33*c8dee2aaSAndroid Build Coastguard Worker int padRight, int padBottom) {
34*c8dee2aaSAndroid Build Coastguard Worker const int kCap = 28;
35*c8dee2aaSAndroid Build Coastguard Worker const int kMid = 8;
36*c8dee2aaSAndroid Build Coastguard Worker const int kSize = 2*kCap + 3*kMid;
37*c8dee2aaSAndroid Build Coastguard Worker
38*c8dee2aaSAndroid Build Coastguard Worker auto surface(make_surface(root, kSize, padLeft, padTop, padRight, padBottom));
39*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* canvas = surface->getCanvas();
40*c8dee2aaSAndroid Build Coastguard Worker canvas->translate((float) padLeft, (float) padTop);
41*c8dee2aaSAndroid Build Coastguard Worker
42*c8dee2aaSAndroid Build Coastguard Worker SkRect r = SkRect::MakeWH(SkIntToScalar(kSize), SkIntToScalar(kSize));
43*c8dee2aaSAndroid Build Coastguard Worker const SkScalar strokeWidth = SkIntToScalar(6);
44*c8dee2aaSAndroid Build Coastguard Worker const SkScalar radius = SkIntToScalar(kCap) - strokeWidth/2;
45*c8dee2aaSAndroid Build Coastguard Worker
46*c8dee2aaSAndroid Build Coastguard Worker xDivs[0] = kCap + padLeft;
47*c8dee2aaSAndroid Build Coastguard Worker yDivs[0] = kCap + padTop;
48*c8dee2aaSAndroid Build Coastguard Worker xDivs[1] = kCap + kMid + padLeft;
49*c8dee2aaSAndroid Build Coastguard Worker yDivs[1] = kCap + kMid + padTop;
50*c8dee2aaSAndroid Build Coastguard Worker xDivs[2] = kCap + 2 * kMid + padLeft;
51*c8dee2aaSAndroid Build Coastguard Worker yDivs[2] = kCap + 2 * kMid + padTop;
52*c8dee2aaSAndroid Build Coastguard Worker xDivs[3] = kCap + 3 * kMid + padLeft;
53*c8dee2aaSAndroid Build Coastguard Worker yDivs[3] = kCap + 3 * kMid + padTop;
54*c8dee2aaSAndroid Build Coastguard Worker
55*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
56*c8dee2aaSAndroid Build Coastguard Worker paint.setAntiAlias(true);
57*c8dee2aaSAndroid Build Coastguard Worker
58*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0xFFFFFF00);
59*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRoundRect(r, radius, radius, paint);
60*c8dee2aaSAndroid Build Coastguard Worker
61*c8dee2aaSAndroid Build Coastguard Worker r.setXYWH(SkIntToScalar(kCap), 0, SkIntToScalar(kMid), SkIntToScalar(kSize));
62*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0x8800FF00);
63*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, paint);
64*c8dee2aaSAndroid Build Coastguard Worker r.setXYWH(SkIntToScalar(kCap + kMid), 0, SkIntToScalar(kMid), SkIntToScalar(kSize));
65*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0x880000FF);
66*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, paint);
67*c8dee2aaSAndroid Build Coastguard Worker r.setXYWH(SkIntToScalar(kCap + 2*kMid), 0, SkIntToScalar(kMid), SkIntToScalar(kSize));
68*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0x88FF00FF);
69*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, paint);
70*c8dee2aaSAndroid Build Coastguard Worker
71*c8dee2aaSAndroid Build Coastguard Worker r.setXYWH(0, SkIntToScalar(kCap), SkIntToScalar(kSize), SkIntToScalar(kMid));
72*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0x8800FF00);
73*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, paint);
74*c8dee2aaSAndroid Build Coastguard Worker r.setXYWH(0, SkIntToScalar(kCap + kMid), SkIntToScalar(kSize), SkIntToScalar(kMid));
75*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0x880000FF);
76*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, paint);
77*c8dee2aaSAndroid Build Coastguard Worker r.setXYWH(0, SkIntToScalar(kCap + 2*kMid), SkIntToScalar(kSize), SkIntToScalar(kMid));
78*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0x88FF00FF);
79*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, paint);
80*c8dee2aaSAndroid Build Coastguard Worker
81*c8dee2aaSAndroid Build Coastguard Worker return surface->makeImageSnapshot();
82*c8dee2aaSAndroid Build Coastguard Worker }
83*c8dee2aaSAndroid Build Coastguard Worker
image_to_bitmap(GrDirectContext * dContext,const SkImage * image,SkBitmap * bm)84*c8dee2aaSAndroid Build Coastguard Worker static void image_to_bitmap(GrDirectContext* dContext, const SkImage* image, SkBitmap* bm) {
85*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo info = SkImageInfo::MakeN32Premul(image->width(), image->height());
86*c8dee2aaSAndroid Build Coastguard Worker bm->allocPixels(info);
87*c8dee2aaSAndroid Build Coastguard Worker image->readPixels(dContext, info, bm->getPixels(), bm->rowBytes(), 0, 0);
88*c8dee2aaSAndroid Build Coastguard Worker }
89*c8dee2aaSAndroid Build Coastguard Worker
90*c8dee2aaSAndroid Build Coastguard Worker /**
91*c8dee2aaSAndroid Build Coastguard Worker * This is similar to NinePatchStretchGM, but it also tests "ninepatch" images with more
92*c8dee2aaSAndroid Build Coastguard Worker * than nine patches.
93*c8dee2aaSAndroid Build Coastguard Worker */
94*c8dee2aaSAndroid Build Coastguard Worker class LatticeGM : public skiagm::GM {
95*c8dee2aaSAndroid Build Coastguard Worker public:
LatticeGM()96*c8dee2aaSAndroid Build Coastguard Worker LatticeGM() {}
97*c8dee2aaSAndroid Build Coastguard Worker
98*c8dee2aaSAndroid Build Coastguard Worker protected:
getName() const99*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override { return SkString("lattice"); }
100*c8dee2aaSAndroid Build Coastguard Worker
getISize()101*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override { return SkISize::Make(800, 800); }
102*c8dee2aaSAndroid Build Coastguard Worker
onDrawHelper(GrDirectContext * dContext,SkCanvas * canvas,int padLeft,int padTop,int padRight,int padBottom)103*c8dee2aaSAndroid Build Coastguard Worker void onDrawHelper(GrDirectContext* dContext, SkCanvas* canvas, int padLeft, int padTop,
104*c8dee2aaSAndroid Build Coastguard Worker int padRight, int padBottom) {
105*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
106*c8dee2aaSAndroid Build Coastguard Worker
107*c8dee2aaSAndroid Build Coastguard Worker int xDivs[5];
108*c8dee2aaSAndroid Build Coastguard Worker int yDivs[5];
109*c8dee2aaSAndroid Build Coastguard Worker xDivs[0] = padLeft;
110*c8dee2aaSAndroid Build Coastguard Worker yDivs[0] = padTop;
111*c8dee2aaSAndroid Build Coastguard Worker
112*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bitmap;
113*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> image = make_image(canvas, xDivs + 1, yDivs + 1, padLeft, padTop,
114*c8dee2aaSAndroid Build Coastguard Worker padRight, padBottom);
115*c8dee2aaSAndroid Build Coastguard Worker image_to_bitmap(dContext, image.get(), &bitmap);
116*c8dee2aaSAndroid Build Coastguard Worker
117*c8dee2aaSAndroid Build Coastguard Worker const SkSize size[] = {
118*c8dee2aaSAndroid Build Coastguard Worker { 50, 50, }, // shrink in both axes
119*c8dee2aaSAndroid Build Coastguard Worker { 50, 200, }, // shrink in X
120*c8dee2aaSAndroid Build Coastguard Worker { 200, 50, }, // shrink in Y
121*c8dee2aaSAndroid Build Coastguard Worker { 200, 200, },
122*c8dee2aaSAndroid Build Coastguard Worker };
123*c8dee2aaSAndroid Build Coastguard Worker
124*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(image, 10, 10);
125*c8dee2aaSAndroid Build Coastguard Worker
126*c8dee2aaSAndroid Build Coastguard Worker SkScalar x = SkIntToScalar(100);
127*c8dee2aaSAndroid Build Coastguard Worker SkScalar y = SkIntToScalar(100);
128*c8dee2aaSAndroid Build Coastguard Worker
129*c8dee2aaSAndroid Build Coastguard Worker SkCanvas::Lattice lattice;
130*c8dee2aaSAndroid Build Coastguard Worker lattice.fXCount = 4;
131*c8dee2aaSAndroid Build Coastguard Worker lattice.fXDivs = xDivs + 1;
132*c8dee2aaSAndroid Build Coastguard Worker lattice.fYCount = 4;
133*c8dee2aaSAndroid Build Coastguard Worker lattice.fYDivs = yDivs + 1;
134*c8dee2aaSAndroid Build Coastguard Worker lattice.fRectTypes = nullptr;
135*c8dee2aaSAndroid Build Coastguard Worker lattice.fColors = nullptr;
136*c8dee2aaSAndroid Build Coastguard Worker
137*c8dee2aaSAndroid Build Coastguard Worker SkIRect bounds = SkIRect::MakeLTRB(padLeft, padTop,
138*c8dee2aaSAndroid Build Coastguard Worker image->width() - padRight, image->height() - padBottom);
139*c8dee2aaSAndroid Build Coastguard Worker lattice.fBounds = (bounds == SkIRect::MakeWH(image->width(), image->height())) ?
140*c8dee2aaSAndroid Build Coastguard Worker nullptr : &bounds;
141*c8dee2aaSAndroid Build Coastguard Worker
142*c8dee2aaSAndroid Build Coastguard Worker for (int iy = 0; iy < 2; ++iy) {
143*c8dee2aaSAndroid Build Coastguard Worker for (int ix = 0; ix < 2; ++ix) {
144*c8dee2aaSAndroid Build Coastguard Worker int i = ix * 2 + iy;
145*c8dee2aaSAndroid Build Coastguard Worker SkRect r = SkRect::MakeXYWH(x + ix * 60, y + iy * 60,
146*c8dee2aaSAndroid Build Coastguard Worker size[i].width(), size[i].height());
147*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImageLattice(image.get(), lattice, r);
148*c8dee2aaSAndroid Build Coastguard Worker }
149*c8dee2aaSAndroid Build Coastguard Worker }
150*c8dee2aaSAndroid Build Coastguard Worker
151*c8dee2aaSAndroid Build Coastguard Worker // Provide hints about 3 solid color rects. These colors match
152*c8dee2aaSAndroid Build Coastguard Worker // what was already in the bitmap.
153*c8dee2aaSAndroid Build Coastguard Worker int fixedColorX[3] = {2, 4, 1};
154*c8dee2aaSAndroid Build Coastguard Worker int fixedColorY[3] = {1, 1, 2};
155*c8dee2aaSAndroid Build Coastguard Worker SkColor fixedColor[3] = {SK_ColorBLACK, SK_ColorBLACK, SK_ColorBLACK};
156*c8dee2aaSAndroid Build Coastguard Worker const SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType,
157*c8dee2aaSAndroid Build Coastguard Worker kUnpremul_SkAlphaType);
158*c8dee2aaSAndroid Build Coastguard Worker for (int rectNum = 0; rectNum < 3; rectNum++) {
159*c8dee2aaSAndroid Build Coastguard Worker int srcX = xDivs[fixedColorX[rectNum]-1];
160*c8dee2aaSAndroid Build Coastguard Worker int srcY = yDivs[fixedColorY[rectNum]-1];
161*c8dee2aaSAndroid Build Coastguard Worker image->readPixels(dContext, info, &fixedColor[rectNum], 4, srcX, srcY);
162*c8dee2aaSAndroid Build Coastguard Worker }
163*c8dee2aaSAndroid Build Coastguard Worker
164*c8dee2aaSAndroid Build Coastguard Worker // Include the degenerate first div. While normally the first patch is "scalable",
165*c8dee2aaSAndroid Build Coastguard Worker // this will mean that the first non-degenerate patch is "fixed".
166*c8dee2aaSAndroid Build Coastguard Worker lattice.fXCount = 5;
167*c8dee2aaSAndroid Build Coastguard Worker lattice.fXDivs = xDivs;
168*c8dee2aaSAndroid Build Coastguard Worker lattice.fYCount = 5;
169*c8dee2aaSAndroid Build Coastguard Worker lattice.fYDivs = yDivs;
170*c8dee2aaSAndroid Build Coastguard Worker
171*c8dee2aaSAndroid Build Coastguard Worker // Let's skip a few rects.
172*c8dee2aaSAndroid Build Coastguard Worker SkCanvas::Lattice::RectType flags[36];
173*c8dee2aaSAndroid Build Coastguard Worker sk_bzero(flags, 36 * sizeof(SkCanvas::Lattice::RectType));
174*c8dee2aaSAndroid Build Coastguard Worker flags[4] = SkCanvas::Lattice::kTransparent;
175*c8dee2aaSAndroid Build Coastguard Worker flags[9] = SkCanvas::Lattice::kTransparent;
176*c8dee2aaSAndroid Build Coastguard Worker flags[12] = SkCanvas::Lattice::kTransparent;
177*c8dee2aaSAndroid Build Coastguard Worker flags[19] = SkCanvas::Lattice::kTransparent;
178*c8dee2aaSAndroid Build Coastguard Worker for (int rectNum = 0; rectNum < 3; rectNum++) {
179*c8dee2aaSAndroid Build Coastguard Worker flags[fixedColorY[rectNum]*6 + fixedColorX[rectNum]]
180*c8dee2aaSAndroid Build Coastguard Worker = SkCanvas::Lattice::kFixedColor;
181*c8dee2aaSAndroid Build Coastguard Worker }
182*c8dee2aaSAndroid Build Coastguard Worker lattice.fRectTypes = flags;
183*c8dee2aaSAndroid Build Coastguard Worker
184*c8dee2aaSAndroid Build Coastguard Worker SkColor colors[36];
185*c8dee2aaSAndroid Build Coastguard Worker sk_bzero(colors, 36 * sizeof(SkColor));
186*c8dee2aaSAndroid Build Coastguard Worker for (int rectNum = 0; rectNum < 3; rectNum++) {
187*c8dee2aaSAndroid Build Coastguard Worker colors[fixedColorY[rectNum]*6 + fixedColorX[rectNum]]
188*c8dee2aaSAndroid Build Coastguard Worker = fixedColor[rectNum];
189*c8dee2aaSAndroid Build Coastguard Worker }
190*c8dee2aaSAndroid Build Coastguard Worker
191*c8dee2aaSAndroid Build Coastguard Worker lattice.fColors = colors;
192*c8dee2aaSAndroid Build Coastguard Worker
193*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(400, 0);
194*c8dee2aaSAndroid Build Coastguard Worker for (int iy = 0; iy < 2; ++iy) {
195*c8dee2aaSAndroid Build Coastguard Worker for (int ix = 0; ix < 2; ++ix) {
196*c8dee2aaSAndroid Build Coastguard Worker int i = ix * 2 + iy;
197*c8dee2aaSAndroid Build Coastguard Worker SkRect r = SkRect::MakeXYWH(x + ix * 60, y + iy * 60,
198*c8dee2aaSAndroid Build Coastguard Worker size[i].width(), size[i].height());
199*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImageLattice(image.get(), lattice, r);
200*c8dee2aaSAndroid Build Coastguard Worker }
201*c8dee2aaSAndroid Build Coastguard Worker }
202*c8dee2aaSAndroid Build Coastguard Worker
203*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
204*c8dee2aaSAndroid Build Coastguard Worker }
205*c8dee2aaSAndroid Build Coastguard Worker
onDraw(SkCanvas * canvas,SkString * errorMsg)206*c8dee2aaSAndroid Build Coastguard Worker DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
207*c8dee2aaSAndroid Build Coastguard Worker auto rContext = canvas->recordingContext();
208*c8dee2aaSAndroid Build Coastguard Worker auto dContext = GrAsDirectContext(rContext);
209*c8dee2aaSAndroid Build Coastguard Worker if (rContext && !dContext) {
210*c8dee2aaSAndroid Build Coastguard Worker *errorMsg = "not supported in ddl";
211*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kSkip;
212*c8dee2aaSAndroid Build Coastguard Worker }
213*c8dee2aaSAndroid Build Coastguard Worker this->onDrawHelper(dContext, canvas, 0, 0, 0, 0);
214*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0.0f, 400.0f);
215*c8dee2aaSAndroid Build Coastguard Worker this->onDrawHelper(dContext, canvas, 3, 7, 4, 11);
216*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kOk;
217*c8dee2aaSAndroid Build Coastguard Worker }
218*c8dee2aaSAndroid Build Coastguard Worker
219*c8dee2aaSAndroid Build Coastguard Worker private:
220*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = skiagm::GM;
221*c8dee2aaSAndroid Build Coastguard Worker };
222*c8dee2aaSAndroid Build Coastguard Worker DEF_GM( return new LatticeGM; )
223*c8dee2aaSAndroid Build Coastguard Worker
224*c8dee2aaSAndroid Build Coastguard Worker
225*c8dee2aaSAndroid Build Coastguard Worker // LatticeGM2 exercises code paths that draw fixed color and 1x1 rectangles.
226*c8dee2aaSAndroid Build Coastguard Worker class LatticeGM2 : public skiagm::GM {
227*c8dee2aaSAndroid Build Coastguard Worker public:
LatticeGM2()228*c8dee2aaSAndroid Build Coastguard Worker LatticeGM2() {}
getName() const229*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override { return SkString("lattice2"); }
230*c8dee2aaSAndroid Build Coastguard Worker
getISize()231*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override { return SkISize::Make(800, 800); }
232*c8dee2aaSAndroid Build Coastguard Worker
makeImage(SkCanvas * root,int padLeft,int padTop,int padRight,int padBottom)233*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> makeImage(SkCanvas* root, int padLeft, int padTop, int padRight, int padBottom) {
234*c8dee2aaSAndroid Build Coastguard Worker const int kSize = 80;
235*c8dee2aaSAndroid Build Coastguard Worker auto surface(make_surface(root, kSize, padLeft, padTop, padRight, padBottom));
236*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* canvas = surface->getCanvas();
237*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
238*c8dee2aaSAndroid Build Coastguard Worker paint.setAntiAlias(false);
239*c8dee2aaSAndroid Build Coastguard Worker SkRect r;
240*c8dee2aaSAndroid Build Coastguard Worker
241*c8dee2aaSAndroid Build Coastguard Worker //first line
242*c8dee2aaSAndroid Build Coastguard Worker r.setXYWH(0, 0, 4, 1); //4x1 green rect
243*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0xFF00FF00);
244*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, paint);
245*c8dee2aaSAndroid Build Coastguard Worker
246*c8dee2aaSAndroid Build Coastguard Worker r.setXYWH(4, 0, 1, 1); //1x1 blue pixel -> draws as rectangle
247*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0xFF0000FF);
248*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, paint);
249*c8dee2aaSAndroid Build Coastguard Worker
250*c8dee2aaSAndroid Build Coastguard Worker r.setXYWH(5, 0, kSize-5, 1); //the rest of the line is red
251*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0xFFFF0000);
252*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, paint);
253*c8dee2aaSAndroid Build Coastguard Worker
254*c8dee2aaSAndroid Build Coastguard Worker
255*c8dee2aaSAndroid Build Coastguard Worker //second line -> draws as fixed color rectangles
256*c8dee2aaSAndroid Build Coastguard Worker r.setXYWH(0, 1, 4, 1); //4x1 red rect
257*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0xFFFF0000);
258*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, paint);
259*c8dee2aaSAndroid Build Coastguard Worker
260*c8dee2aaSAndroid Build Coastguard Worker r.setXYWH(4, 1, 1, 1); //1x1 blue pixel with alpha
261*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0x880000FF);
262*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, paint);
263*c8dee2aaSAndroid Build Coastguard Worker
264*c8dee2aaSAndroid Build Coastguard Worker r.setXYWH(5, 1, kSize-5, 1); //the rest of the line is green
265*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0xFF00FF00);
266*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, paint);
267*c8dee2aaSAndroid Build Coastguard Worker
268*c8dee2aaSAndroid Build Coastguard Worker
269*c8dee2aaSAndroid Build Coastguard Worker //third line - does not draw, because it is transparent
270*c8dee2aaSAndroid Build Coastguard Worker r.setXYWH(0, 2, 4, kSize-2); //4x78 green rect
271*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0xFF00FF00);
272*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, paint);
273*c8dee2aaSAndroid Build Coastguard Worker
274*c8dee2aaSAndroid Build Coastguard Worker r.setXYWH(4, 2, 1, kSize-2); //1x78 red pixel with alpha
275*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0x88FF0000);
276*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, paint);
277*c8dee2aaSAndroid Build Coastguard Worker
278*c8dee2aaSAndroid Build Coastguard Worker r.setXYWH(5, 2, kSize-5, kSize-2); //the rest of the image is blue
279*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0xFF0000FF);
280*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, paint);
281*c8dee2aaSAndroid Build Coastguard Worker
282*c8dee2aaSAndroid Build Coastguard Worker return surface->makeImageSnapshot();
283*c8dee2aaSAndroid Build Coastguard Worker }
284*c8dee2aaSAndroid Build Coastguard Worker
onDrawHelper(SkCanvas * canvas,int padLeft,int padTop,int padRight,int padBottom,SkPaint & paint)285*c8dee2aaSAndroid Build Coastguard Worker void onDrawHelper(SkCanvas* canvas, int padLeft, int padTop, int padRight, int padBottom,
286*c8dee2aaSAndroid Build Coastguard Worker SkPaint& paint) {
287*c8dee2aaSAndroid Build Coastguard Worker int xDivs[2] = {4, 5};
288*c8dee2aaSAndroid Build Coastguard Worker int yDivs[2] = {1, 2};
289*c8dee2aaSAndroid Build Coastguard Worker
290*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
291*c8dee2aaSAndroid Build Coastguard Worker
292*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> image = makeImage(canvas, padLeft, padTop, padRight, padBottom);
293*c8dee2aaSAndroid Build Coastguard Worker
294*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(image, 10, 10);
295*c8dee2aaSAndroid Build Coastguard Worker
296*c8dee2aaSAndroid Build Coastguard Worker SkCanvas::Lattice lattice;
297*c8dee2aaSAndroid Build Coastguard Worker lattice.fXCount = 2;
298*c8dee2aaSAndroid Build Coastguard Worker lattice.fXDivs = xDivs;
299*c8dee2aaSAndroid Build Coastguard Worker lattice.fYCount = 2;
300*c8dee2aaSAndroid Build Coastguard Worker lattice.fYDivs = yDivs;
301*c8dee2aaSAndroid Build Coastguard Worker lattice.fBounds = nullptr;
302*c8dee2aaSAndroid Build Coastguard Worker
303*c8dee2aaSAndroid Build Coastguard Worker SkCanvas::Lattice::RectType flags[9];
304*c8dee2aaSAndroid Build Coastguard Worker sk_bzero(flags, 9 * sizeof(SkCanvas::Lattice::RectType));
305*c8dee2aaSAndroid Build Coastguard Worker flags[3] = SkCanvas::Lattice::kFixedColor;
306*c8dee2aaSAndroid Build Coastguard Worker flags[4] = SkCanvas::Lattice::kFixedColor;
307*c8dee2aaSAndroid Build Coastguard Worker flags[5] = SkCanvas::Lattice::kFixedColor;
308*c8dee2aaSAndroid Build Coastguard Worker
309*c8dee2aaSAndroid Build Coastguard Worker flags[6] = SkCanvas::Lattice::kTransparent;
310*c8dee2aaSAndroid Build Coastguard Worker flags[7] = SkCanvas::Lattice::kTransparent;
311*c8dee2aaSAndroid Build Coastguard Worker flags[8] = SkCanvas::Lattice::kTransparent;
312*c8dee2aaSAndroid Build Coastguard Worker lattice.fRectTypes = flags;
313*c8dee2aaSAndroid Build Coastguard Worker
314*c8dee2aaSAndroid Build Coastguard Worker SkColor colors[9] = {SK_ColorBLACK, SK_ColorBLACK, SK_ColorBLACK,
315*c8dee2aaSAndroid Build Coastguard Worker 0xFFFF0000, 0x880000FF, 0xFF00FF00,
316*c8dee2aaSAndroid Build Coastguard Worker SK_ColorBLACK, SK_ColorBLACK, SK_ColorBLACK};
317*c8dee2aaSAndroid Build Coastguard Worker lattice.fColors = colors;
318*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0xFFFFFFFF);
319*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImageLattice(image.get(), lattice,
320*c8dee2aaSAndroid Build Coastguard Worker SkRect::MakeXYWH(100, 100, 200, 200),
321*c8dee2aaSAndroid Build Coastguard Worker SkFilterMode::kNearest, &paint);
322*c8dee2aaSAndroid Build Coastguard Worker
323*c8dee2aaSAndroid Build Coastguard Worker //draw the same content with alpha
324*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(400, 0);
325*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0x80000FFF);
326*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImageLattice(image.get(), lattice,
327*c8dee2aaSAndroid Build Coastguard Worker SkRect::MakeXYWH(100, 100, 200, 200),
328*c8dee2aaSAndroid Build Coastguard Worker SkFilterMode::kNearest, &paint);
329*c8dee2aaSAndroid Build Coastguard Worker
330*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
331*c8dee2aaSAndroid Build Coastguard Worker }
332*c8dee2aaSAndroid Build Coastguard Worker
onDraw(SkCanvas * canvas)333*c8dee2aaSAndroid Build Coastguard Worker void onDraw(SkCanvas* canvas) override {
334*c8dee2aaSAndroid Build Coastguard Worker
335*c8dee2aaSAndroid Build Coastguard Worker //draw a rectangle in the background with transparent pixels
336*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
337*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0x7F123456);
338*c8dee2aaSAndroid Build Coastguard Worker paint.setBlendMode(SkBlendMode::kSrc);
339*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect( SkRect::MakeXYWH(300, 0, 300, 800), paint);
340*c8dee2aaSAndroid Build Coastguard Worker
341*c8dee2aaSAndroid Build Coastguard Worker //draw image lattice with kSrcOver blending
342*c8dee2aaSAndroid Build Coastguard Worker paint.setBlendMode(SkBlendMode::kSrcOver);
343*c8dee2aaSAndroid Build Coastguard Worker this->onDrawHelper(canvas, 0, 0, 0, 0, paint);
344*c8dee2aaSAndroid Build Coastguard Worker
345*c8dee2aaSAndroid Build Coastguard Worker //draw image lattice with kSrcATop blending
346*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0.0f, 400.0f);
347*c8dee2aaSAndroid Build Coastguard Worker paint.setBlendMode(SkBlendMode::kSrcATop);
348*c8dee2aaSAndroid Build Coastguard Worker this->onDrawHelper(canvas, 0, 0, 0, 0, paint);
349*c8dee2aaSAndroid Build Coastguard Worker }
350*c8dee2aaSAndroid Build Coastguard Worker
351*c8dee2aaSAndroid Build Coastguard Worker private:
352*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = skiagm::GM;
353*c8dee2aaSAndroid Build Coastguard Worker };
354*c8dee2aaSAndroid Build Coastguard Worker DEF_GM( return new LatticeGM2; )
355*c8dee2aaSAndroid Build Coastguard Worker
356*c8dee2aaSAndroid Build Coastguard Worker // Code paths that incorporate the paint color when drawing the lattice (using an alpha image)
357*c8dee2aaSAndroid Build Coastguard Worker DEF_SIMPLE_GM_BG(lattice_alpha, canvas, 120, 120, SK_ColorWHITE) {
358*c8dee2aaSAndroid Build Coastguard Worker auto surface = ToolUtils::makeSurface(canvas, SkImageInfo::MakeA8(100, 100));
359*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->clear(0);
360*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->drawCircle(50, 50, 50, SkPaint());
361*c8dee2aaSAndroid Build Coastguard Worker auto image = surface->makeImageSnapshot();
362*c8dee2aaSAndroid Build Coastguard Worker
363*c8dee2aaSAndroid Build Coastguard Worker int divs[] = { 20, 40, 60, 80 };
364*c8dee2aaSAndroid Build Coastguard Worker
365*c8dee2aaSAndroid Build Coastguard Worker SkCanvas::Lattice lattice;
366*c8dee2aaSAndroid Build Coastguard Worker lattice.fXCount = 4;
367*c8dee2aaSAndroid Build Coastguard Worker lattice.fXDivs = divs;
368*c8dee2aaSAndroid Build Coastguard Worker lattice.fYCount = 4;
369*c8dee2aaSAndroid Build Coastguard Worker lattice.fYDivs = divs;
370*c8dee2aaSAndroid Build Coastguard Worker lattice.fRectTypes = nullptr;
371*c8dee2aaSAndroid Build Coastguard Worker lattice.fColors = nullptr;
372*c8dee2aaSAndroid Build Coastguard Worker lattice.fBounds = nullptr;
373*c8dee2aaSAndroid Build Coastguard Worker
374*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
375*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(SK_ColorMAGENTA);
376*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImageLattice(image.get(), lattice, SkRect::MakeWH(120, 120),
377*c8dee2aaSAndroid Build Coastguard Worker SkFilterMode::kNearest, &paint);
378*c8dee2aaSAndroid Build Coastguard Worker }
379*c8dee2aaSAndroid Build Coastguard Worker
make_symmetry_test_image()380*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkImage> make_symmetry_test_image() {
381*c8dee2aaSAndroid Build Coastguard Worker auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(8, 8));
382*c8dee2aaSAndroid Build Coastguard Worker auto canvas = surface->getCanvas();
383*c8dee2aaSAndroid Build Coastguard Worker canvas->drawColor(SK_ColorBLUE);
384*c8dee2aaSAndroid Build Coastguard Worker SkPaint p;
385*c8dee2aaSAndroid Build Coastguard Worker p.setColor(SK_ColorGREEN);
386*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(SkRect::MakeXYWH(2, 2, 4, 4), p);
387*c8dee2aaSAndroid Build Coastguard Worker return surface->makeImageSnapshot();
388*c8dee2aaSAndroid Build Coastguard Worker }
389*c8dee2aaSAndroid Build Coastguard Worker
390*c8dee2aaSAndroid Build Coastguard Worker // b/349428795 : A nine-patch should be able to have zero-sized regions on either end. Before
391*c8dee2aaSAndroid Build Coastguard Worker // fixing the bug, it only worked on the left/top, leading to non-symmetric results in this GM.
392*c8dee2aaSAndroid Build Coastguard Worker // Correct rendering is for each row to be symmetric.
393*c8dee2aaSAndroid Build Coastguard Worker DEF_SIMPLE_GM(ninepatch_edge_case_349428795, canvas, 500, 150) {
394*c8dee2aaSAndroid Build Coastguard Worker auto nine = make_symmetry_test_image();
395*c8dee2aaSAndroid Build Coastguard Worker
396*c8dee2aaSAndroid Build Coastguard Worker for (int i = -1; i < 6; i++) {
397*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImageNine(nine.get(),
398*c8dee2aaSAndroid Build Coastguard Worker SkIRect::MakeXYWH(i, 2, 4, 4),
399*c8dee2aaSAndroid Build Coastguard Worker SkRect::MakeXYWH(i * 70 + 80, 10, 64, 64),
400*c8dee2aaSAndroid Build Coastguard Worker SkFilterMode::kLinear);
401*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImageNine(nine.get(),
402*c8dee2aaSAndroid Build Coastguard Worker SkIRect::MakeXYWH(2, i, 4, 4),
403*c8dee2aaSAndroid Build Coastguard Worker SkRect::MakeXYWH(i * 70 + 80, 80, 64, 64),
404*c8dee2aaSAndroid Build Coastguard Worker SkFilterMode::kLinear);
405*c8dee2aaSAndroid Build Coastguard Worker }
406*c8dee2aaSAndroid Build Coastguard Worker }
407