Flutter Engine
The Flutter Engine
imagemagnifier.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2012 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"
24#include "src/base/SkRandom.h"
25#include "tools/ToolUtils.h"
28
29#include <utility>
30
31#define WIDTH 500
32#define HEIGHT 500
33
34static void draw_content(SkCanvas* canvas, float maxTextSize, int count) {
35 const char* str = "The quick brown fox jumped over the lazy dog.";
36 SkRandom rand;
38 for (int i = 0; i < count; ++i) {
39 int x = rand.nextULessThan(WIDTH);
40 int y = rand.nextULessThan(HEIGHT);
42 paint.setColor(ToolUtils::color_to_565(rand.nextBits(24) | 0xFF000000));
43 font.setSize(rand.nextRangeScalar(0, maxTextSize));
45 }
46}
47
48DEF_SIMPLE_GM_BG(imagemagnifier, canvas, WIDTH, HEIGHT, SK_ColorBLACK) {
49 SkPaint filterPaint;
50 filterPaint.setImageFilter(
52 SkFilterMode::kLinear, nullptr));
53 canvas->saveLayer(nullptr, &filterPaint);
54 draw_content(canvas, 300.f, 25);
55 canvas->restore();
56}
57
58////////////////////////////////////////////////////////////////////////////////
59#define WIDTH_HEIGHT 256
60
63 bitmap.allocN32Pixels(WIDTH_HEIGHT, WIDTH_HEIGHT);
64 SkCanvas canvas(bitmap);
65
66 canvas.clear(0x0);
67
69 paint.setColor(SK_ColorBLUE);
70
71 for (float pos = 0; pos < WIDTH_HEIGHT; pos += 16) {
74 }
75
78 result.setPixelRef(sk_ref_sp(bitmap.pixelRef()), 0, 0);
79
80 return result.asImage();
81}
82
83DEF_SIMPLE_GM_BG(imagemagnifier_cropped, canvas, WIDTH_HEIGHT, WIDTH_HEIGHT, SK_ColorBLACK) {
85
86 // Crop out a 16 pixel ring around the result
87 const SkIRect cropRect = SkIRect::MakeXYWH(16, 16, WIDTH_HEIGHT-32, WIDTH_HEIGHT-32);
88
89 SkPaint filterPaint;
92 WIDTH_HEIGHT / (WIDTH_HEIGHT - 96.f), 64.f, {},
93 std::move(imageSource), &cropRect));
94
95 canvas->saveLayer(nullptr, &filterPaint);
96 canvas->restore();
97}
98
100public:
101 ImageMagnifierBounds() : fX(0.f), fY(0.f) {}
102
103protected:
104 SkString getName() const override { return SkString("imagemagnifier_bounds"); }
105 SkISize getISize() override { return SkISize::Make(768, 512); }
106
107 bool onAnimate(double nanos) override {
108 fX = TimeUtils::SineWave(nanos, 10.f, 0.f, -200.f, 200.f);
109 fY = TimeUtils::SineWave(nanos, 10.f, 3.f, -200.f, 200.f);
110 return true;
111 }
112
113 void onDraw(SkCanvas* canvas) override {
114 this->drawRow(canvas, 16.f); // fish eye distortion
115 canvas->translate(0.f, 256.f);
116 this->drawRow(canvas, 0.f); // no distortion, just zoom
117 }
118
119private:
120
121 void drawRow(SkCanvas* canvas, float inset) {
122 // Draw the magnifier two ways: backdrop filtered and then through a saveLayer with a
123 // regular filter. Lastly draw the un-filtered input. Relevant bounds are displayed on
124 // top of the rendering:
125 // - black = the lens bounding box
126 // - red = the clipped inset lens bounds
127 // - blue = the source of the undistorted magnified content
128 auto drawBorder = [canvas](SkRect rect, SkColor color,
129 float width, float borderInset = 0.f) {
132 paint.setStrokeWidth(width);
133 paint.setColor(color);
134 paint.setAntiAlias(true);
135
136 // This draws the original rect (unrounded) when borderInset = 0
137 rect.inset(borderInset, borderInset);
138 canvas->drawRRect(SkRRect::MakeRectXY(rect, borderInset, borderInset), paint);
139 };
140
141 // Logically there is a 'widgetBounds' that is the region of pixels to
142 // be filled with magnified content. Pixels inside widgetBounds are
143 // scaled up by a factor of 'zoomAmount', with a non linear distortion
144 // applied to pixels up to 'inset' inside 'widgetBounds'. The specific
145 // linearly scaled region is termed the 'srcRect' and is adjusted
146 // dynamically if parts of 'widgetBounds' are offscreen.
147 SkRect widgetBounds = {16.f, 24.f, 220.f, 248.f};
148 widgetBounds.offset(fX, fY); // animating helps highlight magnifier behavior
149
150 constexpr float kZoomAmount = 2.5f;
151
152 // The available content for backdrops, which clips the widgetBounds as it animates.
153 constexpr SkRect kOutBounds = {0.f, 0.f, 256.f, 256.f};
154
155 // The filter responds to any crop (explicit or from missing backdrop content). Compute
156 // the corresponding clipped bounds and source bounds for visualization purposes.
157 SkPoint zoomCenter = widgetBounds.center();
158 SkRect clippedWidget = widgetBounds;
159 SkAssertResult(clippedWidget.intersect(kOutBounds));
160 zoomCenter = {SkTPin(zoomCenter.fX, clippedWidget.fLeft, clippedWidget.fRight),
161 SkTPin(zoomCenter.fY, clippedWidget.fTop, clippedWidget.fBottom)};
162 zoomCenter = zoomCenter * (1.f - 1.f / kZoomAmount);
163 SkRect srcRect = {clippedWidget.fLeft / kZoomAmount + zoomCenter.fX,
164 clippedWidget.fTop / kZoomAmount + zoomCenter.fY,
165 clippedWidget.fRight / kZoomAmount + zoomCenter.fX,
166 clippedWidget.fBottom / kZoomAmount + zoomCenter.fY};
167
168 // Internally, the magnifier filter performs equivalent calculations but responds to the
169 // canvas matrix and available input automatically.
170 sk_sp<SkImageFilter> magnifier =
171 SkImageFilters::Magnifier(widgetBounds, kZoomAmount, inset,
172 SkFilterMode::kLinear, nullptr, kOutBounds);
173
174 // Draw once as a backdrop filter
175 canvas->save();
176 canvas->clipRect(kOutBounds);
177 draw_content(canvas, 32.f, 350);
178 canvas->saveLayer({nullptr, nullptr, magnifier.get(), 0});
179 canvas->restore();
180
181 drawBorder(widgetBounds, SK_ColorBLACK, 2.f);
182 if (inset > 0.f) {
183 drawBorder(clippedWidget, SK_ColorRED, 2.f, inset);
184 }
185 canvas->restore();
186
187 // Draw once as a regular filter
188 canvas->save();
189 canvas->translate(256.f, 0.f);
190 canvas->clipRect(kOutBounds);
191
193 paint.setImageFilter(magnifier);
194 canvas->saveLayer(nullptr, &paint);
195 draw_content(canvas, 32.f, 350);
196 canvas->restore();
197
198 drawBorder(widgetBounds, SK_ColorBLACK, 2.f);
199 if (inset > 0.f) {
200 drawBorder(clippedWidget, SK_ColorRED, 2.f, inset);
201 }
202 canvas->restore();
203
204 // Draw once unfiltered
205 canvas->save();
206 canvas->translate(512.f, 0.f);
207 canvas->clipRect(kOutBounds);
208 draw_content(canvas, 32.f, 350);
209
210 drawBorder(widgetBounds, SK_ColorBLACK, 2.f);
211 drawBorder(srcRect, SK_ColorBLUE, 2.f, inset / kZoomAmount);
212 canvas->restore();
213 }
214
215private:
216 SkScalar fX;
217 SkScalar fY;
218};
219
220DEF_GM(return new ImageMagnifierBounds(); )
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
int count
Definition: FontMgrTest.cpp:50
SkPoint pos
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition: SkAlphaType.h:29
uint32_t SkColor
Definition: SkColor.h:37
constexpr SkColor SK_ColorBLUE
Definition: SkColor.h:135
constexpr SkColor SK_ColorRED
Definition: SkColor.h:126
constexpr SkColor SK_ColorBLACK
Definition: SkColor.h:103
sk_sp< T > sk_ref_sp(T *obj)
Definition: SkRefCnt.h:381
#define SkIntToScalar(x)
Definition: SkScalar.h:57
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
Definition: SkTPin.h:19
void onDraw(SkCanvas *canvas) override
SkString getName() const override
bool onAnimate(double nanos) override
SkISize getISize() override
int saveLayer(const SkRect *bounds, const SkPaint *paint)
Definition: SkCanvas.cpp:496
void clipRect(const SkRect &rect, SkClipOp op, bool doAntiAlias)
Definition: SkCanvas.cpp:1361
void restore()
Definition: SkCanvas.cpp:461
void translate(SkScalar dx, SkScalar dy)
Definition: SkCanvas.cpp:1278
void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint &paint)
Definition: SkCanvas.cpp:2700
void clear(SkColor color)
Definition: SkCanvas.h:1199
void drawRRect(const SkRRect &rrect, const SkPaint &paint)
Definition: SkCanvas.cpp:1705
int save()
Definition: SkCanvas.cpp:447
void drawString(const char str[], SkScalar x, SkScalar y, const SkFont &font, const SkPaint &paint)
Definition: SkCanvas.h:1803
Definition: SkFont.h:35
static sk_sp< SkImageFilter > Magnifier(const SkRect &lensBounds, SkScalar zoomAmount, SkScalar inset, const SkSamplingOptions &sampling, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Image(sk_sp< SkImage > image, const SkRect &srcRect, const SkRect &dstRect, const SkSamplingOptions &sampling)
void setImageFilter(sk_sp< SkImageFilter > imageFilter)
@ kStroke_Style
set to stroke geometry
Definition: SkPaint.h:194
static SkRRect MakeRectXY(const SkRect &rect, SkScalar xRad, SkScalar yRad)
Definition: SkRRect.h:180
SkScalar nextRangeScalar(SkScalar min, SkScalar max)
Definition: SkRandom.h:106
uint32_t nextULessThan(uint32_t count)
Definition: SkRandom.h:93
uint32_t nextBits(unsigned bitCount)
Definition: SkRandom.h:72
T * get() const
Definition: SkRefCnt.h:303
Definition: gm.h:110
SkScalar width()
Definition: gm.h:159
const Paint & paint
Definition: color_source.cc:38
DlColor color
float SkScalar
Definition: extension.cpp:12
GAsyncResult * result
#define DEF_GM(CODE)
Definition: gm.h:40
#define WIDTH
#define WIDTH_HEIGHT
static void draw_content(SkCanvas *canvas, float maxTextSize, int count)
DEF_SIMPLE_GM_BG(imagemagnifier, canvas, WIDTH, HEIGHT, SK_ColorBLACK)
static sk_sp< SkImage > make_img()
#define HEIGHT
double y
double x
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
static float SineWave(double time, float periodInSecs, float phaseInSecs, float min, float max)
Definition: TimeUtils.h:48
SkFont DefaultPortableFont()
SkColor color_to_565(SkColor color)
Definition: ToolUtils.cpp:139
Definition: bitmap.py:1
font
Font Metadata and Metrics.
static SkRect inset(const SkRect &r)
Definition: SkRect.h:32
static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h)
Definition: SkRect.h:104
Definition: SkSize.h:16
static constexpr SkISize Make(int32_t w, int32_t h)
Definition: SkSize.h:20
static SkImageInfo MakeS32(int width, int height, SkAlphaType at)
float fX
x-axis value
Definition: SkPoint_impl.h:164
float fY
y-axis value
Definition: SkPoint_impl.h:165
SkScalar fBottom
larger y-axis bounds
Definition: extension.cpp:17
bool intersect(const SkRect &r)
Definition: SkRect.cpp:114
SkScalar fLeft
smaller x-axis bounds
Definition: extension.cpp:14
SkScalar fRight
larger x-axis bounds
Definition: extension.cpp:16
void offset(float dx, float dy)
Definition: SkRect.h:1016
constexpr SkPoint center() const
Definition: SkRect.h:792
static constexpr SkRect MakeWH(float w, float h)
Definition: SkRect.h:609
SkScalar fTop
smaller y-axis bounds
Definition: extension.cpp:15