Flutter Engine
The Flutter Engine
flippity.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2017 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"
12#include "include/core/SkFont.h"
19#include "include/core/SkRect.h"
21#include "include/core/SkSize.h"
28#include "include/gpu/GrTypes.h"
34#include "tools/ToolUtils.h"
37
38#include <string.h>
39#include <utility>
40
41using namespace skia_private;
42
43static const int kNumMatrices = 6;
44static const int kImageSize = 128;
45static const int kLabelSize = 32;
46static const int kNumLabels = 4;
47static const int kInset = 16;
48
49static const int kCellSize = kImageSize+2*kLabelSize;
50static const int kGMWidth = kNumMatrices*kCellSize;
51static const int kGMHeight = 4*kCellSize;
52
53static const SkPoint kPoints[kNumLabels] = {
54 { 0, kImageSize }, // LL
55 { kImageSize, kImageSize }, // LR
56 { 0, 0 }, // UL
57 { kImageSize, 0 }, // UR
58};
59
61 SkMatrix::MakeAll( 0, -1, 1,
62 -1, 0, 1,
63 0, 0, 1),
64 SkMatrix::MakeAll( 1, 0, 0,
65 0, -1, 1,
66 0, 0, 1),
67 // flip x
68 SkMatrix::MakeAll(-1, 0, 1,
69 0, 1, 0,
70 0, 0, 1),
71 SkMatrix::MakeAll( 0, 1, 0,
72 -1, 0, 1,
73 0, 0, 1),
74 // flip both x & y == rotate 180
75 SkMatrix::MakeAll(-1, 0, 1,
76 0, -1, 1,
77 0, 0, 1),
78 // identity
79 SkMatrix::MakeAll(1, 0, 0,
80 0, 1, 0,
81 0, 0, 1)
82};
83
84
85// Create a fixed size text label like "LL" or "LR".
88 paint.setAntiAlias(true);
89 paint.setColor(color);
90
93 font.setSize(32);
94
96 font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
98
101
102 SkCanvas* canvas = surf->getCanvas();
103
104 canvas->clear(SK_ColorWHITE);
105 canvas->concat(mat);
106 canvas->drawSimpleText(text, strlen(text), SkTextEncoding::kUTF8, 0, 0, font, paint);
107
108 return surf->makeImageSnapshot();
109}
110
111// Create an image with each corner marked w/ "LL", "LR", etc., with the origin either bottom-left
112// or top-left.
114 const TArray<sk_sp<SkImage>>& labels,
115 bool bottomLeftOrigin) {
116 SkASSERT(kNumLabels == labels.size());
117
120 SkBitmap bm;
121 bm.allocPixels(ii);
122
123 {
124 SkCanvas canvas(bm);
125
126 canvas.clear(SK_ColorWHITE);
127 for (int i = 0; i < kNumLabels; ++i) {
128 canvas.drawImage(labels[i],
129 0.0 != kPoints[i].fX ? kPoints[i].fX-kLabelSize-kInset : kInset,
130 0.0 != kPoints[i].fY ? kPoints[i].fY-kLabelSize-kInset : kInset);
131 }
132
133 bm.setImmutable();
134 }
135
136 auto dContext = GrAsDirectContext(mainCanvas->recordingContext());
137 if (dContext && !dContext->abandoned()) {
138 auto origin = bottomLeftOrigin ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin;
139
141 bm.pixmap());
142 if (!view) {
143 return nullptr;
144 }
145
146 return sk_make_sp<SkImage_Ganesh>(
147 sk_ref_sp(dContext), kNeedNewImageUniqueID, std::move(view), ii.colorInfo());
148 }
149
151}
152
153// Here we're converting from a matrix that is intended for UVs to a matrix that is intended
154// for rect geometry used for a drawImage call. They are, in some sense, inverses of each
155// other but we also need a scale to map from the [0..1] uv range to the actual size of
156// image.
157static bool UVMatToGeomMatForImage(SkMatrix* geomMat, const SkMatrix& uvMat) {
158
159 const SkMatrix yFlip = SkMatrix::MakeAll(1, 0, 0, 0, -1, 1, 0, 0, 1);
160
161 SkMatrix tmp = uvMat;
162 tmp.preConcat(yFlip);
163 tmp.preScale(1.0f/kImageSize, 1.0f/kImageSize);
164
165 tmp.postConcat(yFlip);
167
168 return tmp.invert(geomMat);
169}
170
171// This GM exercises drawImage with a set of matrices that use an unusual amount of flips and
172// rotates.
173class FlippityGM : public skiagm::GM {
174public:
176 this->setBGColor(0xFFCCCCCC);
177 }
178
179private:
180 SkString getName() const override { return SkString("flippity"); }
181
182 SkISize getISize() override { return SkISize::Make(kGMWidth, kGMHeight); }
183
184 // Draw the reference image and the four corner labels in the matrix's coordinate space
185 void drawImageWithMatrixAndLabels(SkCanvas* canvas, SkImage* image, int matIndex,
186 bool drawSubset, bool drawScaled) {
187 static const SkRect kSubsets[kNumMatrices] = {
194 };
195
196 SkMatrix imageGeomMat;
197 SkAssertResult(UVMatToGeomMatForImage(&imageGeomMat, kUVMatrices[matIndex]));
198
199 canvas->save();
200
201 // draw the reference image
202 canvas->concat(imageGeomMat);
203 if (drawSubset) {
204 canvas->drawImageRect(image, kSubsets[matIndex],
206 : kSubsets[matIndex],
207 SkSamplingOptions(), nullptr,
209 } else {
210 canvas->drawImage(image, 0, 0);
211 }
212
213 // draw the labels
214 for (int i = 0; i < kNumLabels; ++i) {
215 canvas->drawImage(fLabels[i],
216 0.0f == kPoints[i].fX ? -kLabelSize : kPoints[i].fX,
217 0.0f == kPoints[i].fY ? -kLabelSize : kPoints[i].fY);
218 }
219 canvas->restore();
220 }
221
222 void drawRow(SkCanvas* canvas, bool bottomLeftImage, bool drawSubset, bool drawScaled) {
223
224 canvas->save();
226
227 for (int i = 0; i < kNumMatrices; ++i) {
228 this->drawImageWithMatrixAndLabels(canvas, fReferenceImages[bottomLeftImage].get(),
229 i, drawSubset, drawScaled);
230 canvas->translate(kCellSize, 0);
231 }
232 canvas->restore();
233 }
234
235 void makeLabels() {
236 if (fLabels.size()) {
237 return;
238 }
239
240 static const char* kLabelText[kNumLabels] = { "LL", "LR", "UL", "UR" };
241
242 static const SkColor kLabelColors[kNumLabels] = {
247 };
248
249 for (int i = 0; i < kNumLabels; ++i) {
250 fLabels.push_back(make_text_image(kLabelText[i], kLabelColors[i]));
251 }
252 SkASSERT(kNumLabels == fLabels.size());
253 }
254
255 DrawResult onGpuSetup(SkCanvas* canvas, SkString* errorMsg, GraphiteTestContext*) override {
256 this->makeLabels();
257 fReferenceImages[0] = make_reference_image(canvas, fLabels, false);
258 fReferenceImages[1] = make_reference_image(canvas, fLabels, true);
259 if (!fReferenceImages[0] || !fReferenceImages[1]) {
260 *errorMsg = "Failed to create reference images.";
261 return DrawResult::kFail;
262 }
263
264 return DrawResult::kOk;
265 }
266
267 void onGpuTeardown() override {
268 fLabels.clear();
269 fReferenceImages[0] = fReferenceImages[1] = nullptr;
270 }
271
272 void onDraw(SkCanvas* canvas) override {
273 SkASSERT(fReferenceImages[0] && fReferenceImages[1]);
274
275 canvas->save();
276
277 // Top row gets TL image
278 this->drawRow(canvas, false, false, false);
279
280 canvas->translate(0, kCellSize);
281
282 // Bottom row gets BL image
283 this->drawRow(canvas, true, false, false);
284
285 canvas->translate(0, kCellSize);
286
287 // Third row gets subsets of BL images
288 this->drawRow(canvas, true, true, false);
289
290 canvas->translate(0, kCellSize);
291
292 // Fourth row gets scaled subsets of BL images
293 this->drawRow(canvas, true, true, true);
294
295 canvas->restore();
296
297 // separator grid
298 for (int i = 0; i < 4; ++i) {
299 canvas->drawLine(0, i * kCellSize, kGMWidth, i * kCellSize, SkPaint());
300 }
301 for (int i = 0; i < kNumMatrices; ++i) {
302 canvas->drawLine(i * kCellSize, 0, i * kCellSize, kGMHeight, SkPaint());
303 }
304 }
305
306private:
307 TArray<sk_sp<SkImage>> fLabels;
308 sk_sp<SkImage> fReferenceImages[2];
309
310 using INHERITED = GM;
311};
312
313DEF_GM(return new FlippityGM;)
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
static GrDirectContext * GrAsDirectContext(GrContext_Base *base)
@ kBottomLeft_GrSurfaceOrigin
Definition: GrTypes.h:149
@ kTopLeft_GrSurfaceOrigin
Definition: GrTypes.h:148
@ kOpaque_SkAlphaType
pixel is opaque
Definition: SkAlphaType.h:28
#define SkASSERT(cond)
Definition: SkAssert.h:116
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition: SkColorType.h:24
uint32_t SkColor
Definition: SkColor.h:37
constexpr SkColor SK_ColorCYAN
Definition: SkColor.h:143
constexpr SkColor SK_ColorBLUE
Definition: SkColor.h:135
constexpr SkColor SK_ColorRED
Definition: SkColor.h:126
constexpr SkColor SK_ColorGREEN
Definition: SkColor.h:131
constexpr SkColor SK_ColorWHITE
Definition: SkColor.h:122
@ kUTF8
uses bytes to represent UTF-8 or ASCII
@ kNeedNewImageUniqueID
Definition: SkImage_Base.h:33
sk_sp< T > sk_ref_sp(T *obj)
Definition: SkRefCnt.h:381
void allocPixels(const SkImageInfo &info, size_t rowBytes)
Definition: SkBitmap.cpp:258
void setImmutable()
Definition: SkBitmap.cpp:400
const SkPixmap & pixmap() const
Definition: SkBitmap.h:133
void restore()
Definition: SkCanvas.cpp:461
void drawSimpleText(const void *text, size_t byteLength, SkTextEncoding encoding, SkScalar x, SkScalar y, const SkFont &font, const SkPaint &paint)
Definition: SkCanvas.cpp:2413
void translate(SkScalar dx, SkScalar dy)
Definition: SkCanvas.cpp:1278
virtual GrRecordingContext * recordingContext() const
Definition: SkCanvas.cpp:1637
void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint &paint)
Definition: SkCanvas.cpp:2700
@ kFast_SrcRectConstraint
sample outside bounds; faster
Definition: SkCanvas.h:1543
void clear(SkColor color)
Definition: SkCanvas.h:1199
void drawImageRect(const SkImage *, const SkRect &src, const SkRect &dst, const SkSamplingOptions &, const SkPaint *, SrcRectConstraint)
Definition: SkCanvas.cpp:2333
int save()
Definition: SkCanvas.cpp:447
void concat(const SkMatrix &matrix)
Definition: SkCanvas.cpp:1318
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition: SkCanvas.h:1528
Definition: SkFont.h:35
@ kAntiAlias
may have transparent pixels on glyph edges
static SkMatrix RectToRect(const SkRect &src, const SkRect &dst, ScaleToFit mode=kFill_ScaleToFit)
Definition: SkMatrix.h:157
SkMatrix & postConcat(const SkMatrix &other)
Definition: SkMatrix.cpp:683
SkMatrix & postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
Definition: SkMatrix.cpp:360
static SkMatrix MakeAll(SkScalar scaleX, SkScalar skewX, SkScalar transX, SkScalar skewY, SkScalar scaleY, SkScalar transY, SkScalar pers0, SkScalar pers1, SkScalar pers2)
Definition: SkMatrix.h:179
bool invert(SkMatrix *inverse) const
Definition: SkMatrix.h:1206
SkMatrix & preConcat(const SkMatrix &other)
Definition: SkMatrix.cpp:674
SkMatrix & preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
Definition: SkMatrix.cpp:315
SkCanvas * getCanvas()
Definition: SkSurface.cpp:82
sk_sp< SkImage > makeImageSnapshot()
Definition: SkSurface.cpp:90
int size() const
Definition: SkTArray.h:421
Definition: gm.h:110
GM(SkColor backgroundColor=SK_ColorWHITE)
Definition: gm.cpp:81
skiagm::DrawResult DrawResult
Definition: gm.h:112
void setBGColor(SkColor)
Definition: gm.cpp:159
skiatest::graphite::GraphiteTestContext GraphiteTestContext
Definition: gm.h:113
const Paint & paint
Definition: color_source.cc:38
DlColor color
static bool UVMatToGeomMatForImage(SkMatrix *geomMat, const SkMatrix &uvMat)
Definition: flippity.cpp:157
static sk_sp< SkImage > make_reference_image(SkCanvas *mainCanvas, const TArray< sk_sp< SkImage > > &labels, bool bottomLeftOrigin)
Definition: flippity.cpp:113
static const int kLabelSize
Definition: flippity.cpp:45
static const int kNumMatrices
Definition: flippity.cpp:43
static sk_sp< SkImage > make_text_image(const char *text, SkColor color)
Definition: flippity.cpp:86
static const int kGMWidth
Definition: flippity.cpp:50
static const SkPoint kPoints[kNumLabels]
Definition: flippity.cpp:53
static const SkMatrix kUVMatrices[kNumMatrices]
Definition: flippity.cpp:60
static const int kImageSize
Definition: flippity.cpp:44
static const int kInset
Definition: flippity.cpp:47
static const int kGMHeight
Definition: flippity.cpp:51
static const int kNumLabels
Definition: flippity.cpp:46
static const int kCellSize
Definition: flippity.cpp:49
#define DEF_GM(CODE)
Definition: gm.h:40
std::u16string text
SK_API sk_sp< SkImage > RasterFromBitmap(const SkBitmap &bitmap)
Optional< SkRect > bounds
Definition: SkRecords.h:189
sk_sp< const SkImage > image
Definition: SkRecords.h:269
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
SkFont DefaultPortableFont()
font
Font Metadata and Metrics.
const myers::Point & get(const myers::Segment &)
GrSurfaceProxyView MakeTextureProxyViewFromData(GrDirectContext *dContext, GrRenderable renderable, GrSurfaceOrigin origin, GrCPixmap pixmap)
Definition: ProxyUtils.cpp:56
SkSamplingOptions(SkFilterMode::kLinear))
Definition: SkSize.h:16
static constexpr SkISize Make(int32_t w, int32_t h)
Definition: SkSize.h:20
const SkColorInfo & colorInfo() const
Definition: SkImageInfo.h:404
static SkImageInfo MakeN32Premul(int width, int height)
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition: SkRect.h:659
static constexpr SkRect MakeWH(float w, float h)
Definition: SkRect.h:609