blob: d5e2b45c6ea1d4f32203290d3f12e66eeeb94ba3 [file] [log] [blame]
msarettc573a402016-08-02 08:05:56 -07001/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "gm.h"
9#include "SkSurface.h"
10
msarett71df2d72016-09-30 12:41:42 -070011static sk_sp<SkSurface> make_surface(SkCanvas* root, int N, int padLeft, int padTop,
12 int padRight, int padBottom) {
13 SkImageInfo info = SkImageInfo::MakeN32Premul(N + padLeft + padRight, N + padTop + padBottom);
msarettc573a402016-08-02 08:05:56 -070014 auto surface = root->makeSurface(info);
15 if (!surface) {
16 surface = SkSurface::MakeRaster(info);
17 }
msarett71df2d72016-09-30 12:41:42 -070018
msarettc573a402016-08-02 08:05:56 -070019 return surface;
20}
21
msarett71df2d72016-09-30 12:41:42 -070022static sk_sp<SkImage> make_image(SkCanvas* root, int* xDivs, int* yDivs, int padLeft, int padTop,
23 int padRight, int padBottom) {
msarettc573a402016-08-02 08:05:56 -070024 const int kCap = 28;
25 const int kMid = 8;
26 const int kSize = 2*kCap + 3*kMid;
27
msarett71df2d72016-09-30 12:41:42 -070028 auto surface(make_surface(root, kSize, padLeft, padTop, padRight, padBottom));
msarettc573a402016-08-02 08:05:56 -070029 SkCanvas* canvas = surface->getCanvas();
msarett71df2d72016-09-30 12:41:42 -070030 canvas->translate((float) padLeft, (float) padTop);
msarettc573a402016-08-02 08:05:56 -070031
32 SkRect r = SkRect::MakeWH(SkIntToScalar(kSize), SkIntToScalar(kSize));
33 const SkScalar strokeWidth = SkIntToScalar(6);
34 const SkScalar radius = SkIntToScalar(kCap) - strokeWidth/2;
35
msarett71df2d72016-09-30 12:41:42 -070036 xDivs[0] = kCap + padLeft;
37 yDivs[0] = kCap + padTop;
38 xDivs[1] = kCap + kMid + padLeft;
39 yDivs[1] = kCap + kMid + padTop;
40 xDivs[2] = kCap + 2 * kMid + padLeft;
41 yDivs[2] = kCap + 2 * kMid + padTop;
42 xDivs[3] = kCap + 3 * kMid + padLeft;
43 yDivs[3] = kCap + 3 * kMid + padTop;
msarettc573a402016-08-02 08:05:56 -070044
45 SkPaint paint;
46 paint.setAntiAlias(true);
47
48 paint.setColor(0xFFFFFF00);
49 canvas->drawRoundRect(r, radius, radius, paint);
50
51 r.setXYWH(SkIntToScalar(kCap), 0, SkIntToScalar(kMid), SkIntToScalar(kSize));
52 paint.setColor(0x8800FF00);
53 canvas->drawRect(r, paint);
54 r.setXYWH(SkIntToScalar(kCap + kMid), 0, SkIntToScalar(kMid), SkIntToScalar(kSize));
55 paint.setColor(0x880000FF);
56 canvas->drawRect(r, paint);
57 r.setXYWH(SkIntToScalar(kCap + 2*kMid), 0, SkIntToScalar(kMid), SkIntToScalar(kSize));
58 paint.setColor(0x88FF00FF);
59 canvas->drawRect(r, paint);
60
61 r.setXYWH(0, SkIntToScalar(kCap), SkIntToScalar(kSize), SkIntToScalar(kMid));
62 paint.setColor(0x8800FF00);
63 canvas->drawRect(r, paint);
64 r.setXYWH(0, SkIntToScalar(kCap + kMid), SkIntToScalar(kSize), SkIntToScalar(kMid));
65 paint.setColor(0x880000FF);
66 canvas->drawRect(r, paint);
67 r.setXYWH(0, SkIntToScalar(kCap + 2*kMid), SkIntToScalar(kSize), SkIntToScalar(kMid));
68 paint.setColor(0x88FF00FF);
69 canvas->drawRect(r, paint);
70
71 return surface->makeImageSnapshot();
72}
73
74static void image_to_bitmap(const SkImage* image, SkBitmap* bm) {
75 SkImageInfo info = SkImageInfo::MakeN32Premul(image->width(), image->height());
76 bm->allocPixels(info);
77 image->readPixels(info, bm->getPixels(), bm->rowBytes(), 0, 0);
78}
79
80/**
81 * This is similar to NinePatchStretchGM, but it also tests "ninepatch" images with more
82 * than nine patches.
83 */
84class LatticeGM : public skiagm::GM {
85public:
86 LatticeGM() {}
87
88protected:
89 SkString onShortName() override {
90 return SkString("lattice");
91 }
92
93 SkISize onISize() override {
msarett71df2d72016-09-30 12:41:42 -070094 return SkISize::Make(800, 800);
msarettc573a402016-08-02 08:05:56 -070095 }
96
msarett71df2d72016-09-30 12:41:42 -070097 void onDrawHelper(SkCanvas* canvas, int padLeft, int padTop, int padRight, int padBottom) {
98 canvas->save();
99
msarettc573a402016-08-02 08:05:56 -0700100 int xDivs[5];
101 int yDivs[5];
msarett71df2d72016-09-30 12:41:42 -0700102 xDivs[0] = padLeft;
103 yDivs[0] = padTop;
msarettc573a402016-08-02 08:05:56 -0700104
105 SkBitmap bitmap;
msarett71df2d72016-09-30 12:41:42 -0700106 sk_sp<SkImage> image = make_image(canvas, xDivs + 1, yDivs + 1, padLeft, padTop,
107 padRight, padBottom);
msarettc573a402016-08-02 08:05:56 -0700108 image_to_bitmap(image.get(), &bitmap);
109
Hal Canaryfafe1352017-04-11 12:12:02 -0400110 const SkSize size[] = {
msarettc573a402016-08-02 08:05:56 -0700111 { 50, 50, }, // shrink in both axes
112 { 50, 200, }, // shrink in X
113 { 200, 50, }, // shrink in Y
114 { 200, 200, },
115 };
116
117 canvas->drawImage(image, 10, 10, nullptr);
118
119 SkScalar x = SkIntToScalar(100);
120 SkScalar y = SkIntToScalar(100);
121
122 SkCanvas::Lattice lattice;
123 lattice.fXCount = 4;
124 lattice.fXDivs = xDivs + 1;
125 lattice.fYCount = 4;
126 lattice.fYDivs = yDivs + 1;
Stan Ilievca8c0952017-12-11 13:01:58 -0500127 lattice.fRectTypes = nullptr;
128 lattice.fColors = nullptr;
msarettc573a402016-08-02 08:05:56 -0700129
msarett71df2d72016-09-30 12:41:42 -0700130 SkIRect bounds = SkIRect::MakeLTRB(padLeft, padTop,
131 image->width() - padRight, image->height() - padBottom);
132 lattice.fBounds = (bounds == SkIRect::MakeWH(image->width(), image->height())) ?
133 nullptr : &bounds;
134
msarettc573a402016-08-02 08:05:56 -0700135 for (int iy = 0; iy < 2; ++iy) {
136 for (int ix = 0; ix < 2; ++ix) {
137 int i = ix * 2 + iy;
138 SkRect r = SkRect::MakeXYWH(x + ix * 60, y + iy * 60,
139 size[i].width(), size[i].height());
140 canvas->drawBitmapLattice(bitmap, lattice, r);
141 }
142 }
143
Stan Ilievca8c0952017-12-11 13:01:58 -0500144 // Provide hints about 3 solid color rects. These colors match
145 // what was already in the bitmap.
146 int fixedColorX[3] = {2, 4, 1};
147 int fixedColorY[3] = {1, 1, 2};
148 SkColor fixedColor[3] = {SK_ColorBLACK, SK_ColorBLACK, SK_ColorBLACK};
149 const SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType,
150 kUnpremul_SkAlphaType);
151 for (int rectNum = 0; rectNum < 3; rectNum++) {
152 int srcX = xDivs[fixedColorX[rectNum]-1];
153 int srcY = yDivs[fixedColorY[rectNum]-1];
154 image->readPixels(info, &fixedColor[rectNum], 4, srcX, srcY);
155 }
156
msarettc573a402016-08-02 08:05:56 -0700157 // Include the degenerate first div. While normally the first patch is "scalable",
158 // this will mean that the first non-degenerate patch is "fixed".
159 lattice.fXCount = 5;
160 lattice.fXDivs = xDivs;
161 lattice.fYCount = 5;
162 lattice.fYDivs = yDivs;
163
msarett0764efe2016-09-02 11:24:30 -0700164 // Let's skip a few rects.
Stan Ilievca8c0952017-12-11 13:01:58 -0500165 SkCanvas::Lattice::RectType flags[36];
166 sk_bzero(flags, 36 * sizeof(SkCanvas::Lattice::RectType));
167 flags[4] = SkCanvas::Lattice::kTransparent;
168 flags[9] = SkCanvas::Lattice::kTransparent;
169 flags[12] = SkCanvas::Lattice::kTransparent;
170 flags[19] = SkCanvas::Lattice::kTransparent;
171 for (int rectNum = 0; rectNum < 3; rectNum++) {
172 flags[fixedColorY[rectNum]*6 + fixedColorX[rectNum]]
173 = SkCanvas::Lattice::kFixedColor;
174 }
175 lattice.fRectTypes = flags;
176
177 SkColor colors[36];
178 sk_bzero(colors, 36 * sizeof(SkColor));
179 for (int rectNum = 0; rectNum < 3; rectNum++) {
180 colors[fixedColorY[rectNum]*6 + fixedColorX[rectNum]]
181 = fixedColor[rectNum];
182 }
183
184 lattice.fColors = colors;
msarett0764efe2016-09-02 11:24:30 -0700185
msarettc573a402016-08-02 08:05:56 -0700186 canvas->translate(400, 0);
187 for (int iy = 0; iy < 2; ++iy) {
188 for (int ix = 0; ix < 2; ++ix) {
189 int i = ix * 2 + iy;
190 SkRect r = SkRect::MakeXYWH(x + ix * 60, y + iy * 60,
191 size[i].width(), size[i].height());
192 canvas->drawImageLattice(image.get(), lattice, r);
193 }
194 }
msarett71df2d72016-09-30 12:41:42 -0700195
196 canvas->restore();
197 }
198
199 void onDraw(SkCanvas* canvas) override {
200 this->onDrawHelper(canvas, 0, 0, 0, 0);
201 canvas->translate(0.0f, 400.0f);
202 this->onDrawHelper(canvas, 3, 7, 4, 11);
msarettc573a402016-08-02 08:05:56 -0700203 }
204
205private:
206 typedef skiagm::GM INHERITED;
207};
208DEF_GM( return new LatticeGM; )
Stan Ilievca8c0952017-12-11 13:01:58 -0500209
210
211// LatticeGM2 exercises code paths that draw fixed color and 1x1 rectangles.
212class LatticeGM2 : public skiagm::GM {
213public:
214 LatticeGM2() {}
215 SkString onShortName() override {
216 return SkString("lattice2");
217 }
218
219 SkISize onISize() override {
220 return SkISize::Make(800, 800);
221 }
222
223 sk_sp<SkImage> makeImage(SkCanvas* root, int padLeft, int padTop, int padRight, int padBottom) {
224 const int kSize = 80;
225 auto surface(make_surface(root, kSize, padLeft, padTop, padRight, padBottom));
226 SkCanvas* canvas = surface->getCanvas();;
227 SkPaint paint;
228 paint.setAntiAlias(false);
229 SkRect r;
230
231 //first line
232 r.setXYWH(0, 0, 4, 1); //4x1 green rect
233 paint.setColor(0xFF00FF00);
234 canvas->drawRect(r, paint);
235
236 r.setXYWH(4, 0, 1, 1); //1x1 blue pixel -> draws as rectangle
237 paint.setColor(0xFF0000FF);
238 canvas->drawRect(r, paint);
239
240 r.setXYWH(5, 0, kSize-5, 1); //the rest of the line is red
241 paint.setColor(0xFFFF0000);
242 canvas->drawRect(r, paint);
243
244
245 //second line -> draws as fixed color rectangles
246 r.setXYWH(0, 1, 4, 1); //4x1 red rect
247 paint.setColor(0xFFFF0000);
248 canvas->drawRect(r, paint);
249
250 r.setXYWH(4, 1, 1, 1); //1x1 blue pixel with alpha
251 paint.setColor(0x880000FF);
252 canvas->drawRect(r, paint);
253
254 r.setXYWH(5, 1, kSize-5, 1); //the rest of the line is green
255 paint.setColor(0xFF00FF00);
256 canvas->drawRect(r, paint);
257
258
259 //third line - does not draw, because it is transparent
260 r.setXYWH(0, 2, 4, kSize-2); //4x78 green rect
261 paint.setColor(0xFF00FF00);
262 canvas->drawRect(r, paint);
263
264 r.setXYWH(4, 2, 1, kSize-2); //1x78 red pixel with alpha
265 paint.setColor(0x88FF0000);
266 canvas->drawRect(r, paint);
267
268 r.setXYWH(5, 2, kSize-5, kSize-2); //the rest of the image is blue
269 paint.setColor(0xFF0000FF);
270 canvas->drawRect(r, paint);
271
272 return surface->makeImageSnapshot();
273 }
274
275 void onDrawHelper(SkCanvas* canvas, int padLeft, int padTop, int padRight, int padBottom,
276 SkPaint& paint) {
277 int xDivs[2] = {4, 5};
278 int yDivs[2] = {1, 2};
279
280 canvas->save();
281
282 sk_sp<SkImage> image = makeImage(canvas, padLeft, padTop, padRight, padBottom);
283
284 canvas->drawImage(image, 10, 10, nullptr);
285
286 SkCanvas::Lattice lattice;
287 lattice.fXCount = 2;
288 lattice.fXDivs = xDivs;
289 lattice.fYCount = 2;
290 lattice.fYDivs = yDivs;
291 lattice.fBounds = nullptr;
292
293 SkCanvas::Lattice::RectType flags[9];
294 sk_bzero(flags, 9 * sizeof(SkCanvas::Lattice::RectType));
295 flags[3] = SkCanvas::Lattice::kFixedColor;
296 flags[4] = SkCanvas::Lattice::kFixedColor;
297 flags[5] = SkCanvas::Lattice::kFixedColor;
298
299 flags[6] = SkCanvas::Lattice::kTransparent;
300 flags[7] = SkCanvas::Lattice::kTransparent;
301 flags[8] = SkCanvas::Lattice::kTransparent;
302 lattice.fRectTypes = flags;
303
304 SkColor colors[9] = {SK_ColorBLACK, SK_ColorBLACK, SK_ColorBLACK,
305 0xFFFF0000, 0x880000FF, 0xFF00FF00,
306 SK_ColorBLACK, SK_ColorBLACK, SK_ColorBLACK};
307 lattice.fColors = colors;
308 paint.setColor(0xFFFFFFFF);
309 canvas->drawImageLattice(image.get(), lattice,
310 SkRect::MakeXYWH(100, 100, 200, 200), &paint);
311
312 //draw the same content with alpha
313 canvas->translate(400, 0);
314 paint.setColor(0x80000FFF);
315 canvas->drawImageLattice(image.get(), lattice,
316 SkRect::MakeXYWH(100, 100, 200, 200), &paint);
317
318 canvas->restore();
319 }
320
321 void onDraw(SkCanvas* canvas) override {
322
323 //draw a rectangle in the background with transparent pixels
324 SkPaint paint;
325 paint.setColor(0x7F123456);
326 paint.setBlendMode(SkBlendMode::kSrc);
327 canvas->drawRect( SkRect::MakeXYWH(300, 0, 300, 800), paint);
328
329 //draw image lattice with kSrcOver blending
330 paint.setBlendMode(SkBlendMode::kSrcOver);
331 this->onDrawHelper(canvas, 0, 0, 0, 0, paint);
332
333 //draw image lattice with kSrcATop blending
334 canvas->translate(0.0f, 400.0f);
335 paint.setBlendMode(SkBlendMode::kSrcATop);
336 this->onDrawHelper(canvas, 0, 0, 0, 0, paint);
337 }
338
339private:
340 typedef skiagm::GM INHERITED;
341};
342DEF_GM( return new LatticeGM2; )
343
344
345