1 /*
2 * Copyright 2014 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/gm.h"
9 #include "include/core/SkCanvas.h"
10 #include "include/core/SkColor.h"
11 #include "include/core/SkMatrix.h"
12 #include "include/core/SkPaint.h"
13 #include "include/core/SkPicture.h"
14 #include "include/core/SkPictureRecorder.h"
15 #include "include/core/SkPoint.h"
16 #include "include/core/SkRect.h"
17 #include "include/core/SkRefCnt.h"
18 #include "include/core/SkScalar.h"
19 #include "include/core/SkShader.h"
20 #include "include/core/SkSize.h"
21 #include "include/core/SkString.h"
22 #include "include/core/SkTileMode.h"
23 #include "include/core/SkTypes.h"
24
25 constexpr SkScalar kPictureSize = SK_Scalar1;
26 constexpr SkScalar kFillSize = 100;
27 constexpr unsigned kRowSize = 6;
28
29 constexpr struct {
30 SkScalar x, y, w, h;
31 SkScalar offsetX, offsetY;
32 } tiles[] = {
33 { 0, 0, 1, 1, 0, 0 },
34 { -0.5f, -0.5f, 1, 1, 0, 0 },
35 { 0.5f, 0.5f, 1, 1, 0, 0 },
36
37 { 0, 0, 1.5f, 1.5f, 0, 0 },
38 { -0.5f, -0.5f, 1.5f, 1.5f, 0, 0 },
39 { 0.5f, 0.5f, 1.5f, 1.5f, 0, 0 },
40
41 { 0, 0, 0.5f, 0.5f, 0, 0 },
42 { 0.25f, 0.25f, 0.5f, 0.5f, 0, 0 },
43 { -0.25f, -0.25f, 0.5f, 0.5f, 0, 0 },
44
45 { 0, 0, 1, 1, 0.5f, 0.5f },
46 { -0.5f, -0.5f, 1, 1, 0.5f, 0.5f },
47 { 0.5f, 0.5f, 1, 1, 0.5f, 0.5f },
48
49 { 0, 0, 1.5f, 1.5f, 0.5f, 0.5f },
50 { -0.5f, -0.5f, 1.5f, 1.5f, 0.5f, 0.5f },
51 { 0.5f, 0.5f, 1.5f, 1.5f, 0.5f, 0.5f },
52
53 { 0, 0, 1.5f, 1, 0, 0 },
54 { -0.5f, -0.5f, 1.5f, 1, 0, 0 },
55 { 0.5f, 0.5f, 1.5f, 1, 0, 0 },
56
57 { 0, 0, 0.5f, 1, 0, 0 },
58 { 0.25f, 0.25f, 0.5f, 1, 0, 0 },
59 { -0.25f, -0.25f, 0.5f, 1, 0, 0 },
60
61 { 0, 0, 1, 1.5f, 0, 0 },
62 { -0.5f, -0.5f, 1, 1.5f, 0, 0 },
63 { 0.5f, 0.5f, 1, 1.5f, 0, 0 },
64
65 { 0, 0, 1, 0.5f, 0, 0 },
66 { 0.25f, 0.25f, 1, 0.5f, 0, 0 },
67 { -0.25f, -0.25f, 1, 0.5f, 0, 0 },
68 };
69
draw_scene(SkCanvas * canvas,SkScalar pictureSize)70 static void draw_scene(SkCanvas* canvas, SkScalar pictureSize) {
71 canvas->clear(SK_ColorWHITE);
72
73 SkPaint paint;
74 paint.setColor(SK_ColorGREEN);
75 paint.setStyle(SkPaint::kFill_Style);
76 paint.setAntiAlias(true);
77
78 canvas->drawCircle(pictureSize / 4, pictureSize / 4, pictureSize / 4, paint);
79 canvas->drawRect(SkRect::MakeXYWH(pictureSize / 2, pictureSize / 2,
80 pictureSize / 2, pictureSize / 2), paint);
81
82 paint.setColor(SK_ColorRED);
83 canvas->drawLine(pictureSize / 2, pictureSize * 1 / 3,
84 pictureSize / 2, pictureSize * 2 / 3, paint);
85 canvas->drawLine(pictureSize * 1 / 3, pictureSize / 2,
86 pictureSize * 2 / 3, pictureSize / 2, paint);
87
88 paint.setColor(SK_ColorBLACK);
89 paint.setStyle(SkPaint::kStroke_Style);
90 canvas->drawRect(SkRect::MakeWH(pictureSize, pictureSize), paint);
91 }
92
93 class PictureShaderTileGM : public skiagm::GM {
94 protected:
95
onShortName()96 SkString onShortName() override {
97 return SkString("pictureshadertile");
98 }
99
onISize()100 SkISize onISize() override {
101 return SkISize::Make(800, 600);
102 }
103
onOnceBeforeDraw()104 void onOnceBeforeDraw() override {
105 SkPictureRecorder recorder;
106 SkCanvas* pictureCanvas = recorder.beginRecording(kPictureSize, kPictureSize);
107 draw_scene(pictureCanvas, kPictureSize);
108 sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
109
110 SkPoint offset = SkPoint::Make(100, 100);
111 pictureCanvas = recorder.beginRecording(SkRect::MakeXYWH(offset.x(), offset.y(),
112 kPictureSize, kPictureSize));
113 pictureCanvas->translate(offset.x(), offset.y());
114 draw_scene(pictureCanvas, kPictureSize);
115 sk_sp<SkPicture> offsetPicture(recorder.finishRecordingAsPicture());
116
117 for (unsigned i = 0; i < SK_ARRAY_COUNT(tiles); ++i) {
118 SkRect tile = SkRect::MakeXYWH(tiles[i].x * kPictureSize,
119 tiles[i].y * kPictureSize,
120 tiles[i].w * kPictureSize,
121 tiles[i].h * kPictureSize);
122 SkMatrix localMatrix;
123 localMatrix.setTranslate(tiles[i].offsetX * kPictureSize,
124 tiles[i].offsetY * kPictureSize);
125 localMatrix.postScale(kFillSize / (2 * kPictureSize),
126 kFillSize / (2 * kPictureSize));
127
128 sk_sp<SkPicture> pictureRef = picture;
129 SkRect* tilePtr = &tile;
130
131 if (tile == SkRect::MakeWH(kPictureSize, kPictureSize)) {
132 // When the tile == picture bounds, exercise the picture + offset path.
133 pictureRef = offsetPicture;
134 tilePtr = nullptr;
135 }
136
137 fShaders[i] = pictureRef->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat,
138 SkFilterMode::kNearest, &localMatrix, tilePtr);
139 }
140 }
141
onDraw(SkCanvas * canvas)142 void onDraw(SkCanvas* canvas) override {
143 canvas->clear(SK_ColorBLACK);
144
145 SkPaint paint;
146 paint.setStyle(SkPaint::kFill_Style);
147
148 for (unsigned i = 0; i < SK_ARRAY_COUNT(fShaders); ++i) {
149 paint.setShader(fShaders[i]);
150
151 canvas->save();
152 canvas->translate((i % kRowSize) * kFillSize * 1.1f,
153 (i / kRowSize) * kFillSize * 1.1f);
154 canvas->drawRect(SkRect::MakeWH(kFillSize, kFillSize), paint);
155 canvas->restore();
156 }
157 }
158
159 private:
160 sk_sp<SkShader> fShaders[SK_ARRAY_COUNT(tiles)];
161
162 using INHERITED = GM;
163 };
164
165 DEF_GM(return new PictureShaderTileGM;)
166