xref: /aosp_15_r20/external/skia/gm/lattice.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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