Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
animated_image_orientation.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2020 Google LLC
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"
14#include "include/core/SkData.h"
21#include "tools/Resources.h"
22
23static sk_sp<SkPicture> post_processor(const SkRect& bounds) {
24 int radius = (bounds.width() + bounds.height()) / 6;
25 SkPathBuilder pathBuilder;
27 .addRRect(SkRRect::MakeRectXY(bounds, radius, radius));
28
30 paint.setAntiAlias(true);
31 paint.setColor(SK_ColorTRANSPARENT);
32 paint.setBlendMode(SkBlendMode::kSrc);
33
34 SkPictureRecorder recorder;
35 auto* canvas = recorder.beginRecording(bounds);
36 canvas->drawPath(pathBuilder.detach(), paint);
37 return recorder.finishRecordingAsPicture();
38}
39
41 const char* fPath;
42 const char* fName;
43 const int fStep;
44 const SkIRect fCropRect;
45 SkISize fSize;
46 int fTranslate;
47 sk_sp<SkData> fData;
48
49 static const int kMaxFrames = 2;
50
51 void init() {
52 if (!fData) {
53 fData = GetResourceAsData(fPath);
54 auto codec = SkCodec::MakeFromData(fData);
55 auto dimensions = codec->dimensions();
56
57 fTranslate = std::max(dimensions.width(), dimensions.height()) // may be rotated
58 * 1.25f // will be scaled up
59 + 2; // padding
60
61 fSize = { fTranslate * kMaxFrames
62 * 2 // crop and no-crop
63 * 2, // post-process and no post-process
64 fTranslate * 4 // 4 scales
65 * 2 }; // makePictureSnapshot and getCurrentFrame
66 }
67 }
68public:
69 AnimatedImageGM(const char* path, const char* name, int step, SkIRect cropRect)
70 : fPath(path)
71 , fName(name)
72 , fStep(step)
73 , fCropRect(cropRect)
74 , fSize{0, 0}
75 , fTranslate(0)
76 {}
77 ~AnimatedImageGM() override = default;
78
79 SkString getName() const override { return SkStringPrintf("%s_animated_image", fName); }
80
81 SkISize getISize() override {
82 this->init();
83 return fSize;
84 }
85
86 void onDraw(SkCanvas* canvas) override {
87 this->init();
88 for (bool usePic : { true, false }) {
89 auto drawProc = [canvas, usePic](const sk_sp<SkAnimatedImage>& animatedImage) {
90 if (usePic) {
91 sk_sp<SkPicture> pic = animatedImage->makePictureSnapshot();
92 canvas->drawPicture(pic);
93 } else {
94 auto image = animatedImage->getCurrentFrame();
95 canvas->drawImage(image, 0, 0);
96 }
97 };
98 for (float scale : { 1.25f, 1.0f, .75f, .5f }) {
99 canvas->save();
100 for (bool doCrop : { false, true }) {
101 for (bool doPostProcess : { false, true }) {
102 auto codec = SkCodec::MakeFromData(fData);
103 const auto origin = codec->getOrigin();
104 auto androidCodec = SkAndroidCodec::MakeFromCodec(std::move(codec));
105 auto info = androidCodec->getInfo();
106 const auto unscaledSize = SkEncodedOriginSwapsWidthHeight(origin)
107 ? SkISize{ info.height(), info.width() } : info.dimensions();
108
109 SkISize scaledSize = { SkScalarFloorToInt(unscaledSize.width() * scale) ,
110 SkScalarFloorToInt(unscaledSize.height() * scale) };
111 info = info.makeDimensions(scaledSize);
112
113 auto cropRect = SkIRect::MakeSize(scaledSize);
114 if (doCrop) {
115 auto matrix = SkMatrix::RectToRect(SkRect::Make(unscaledSize),
116 SkRect::Make(scaledSize));
117 matrix.preConcat(SkEncodedOriginToMatrix(origin,
118 unscaledSize.width(), unscaledSize.height()));
119 SkRect cropRectFloat = SkRect::Make(fCropRect);
120 matrix.mapRect(&cropRectFloat);
121 cropRectFloat.roundOut(&cropRect);
122 }
123
124 sk_sp<SkPicture> postProcessor = doPostProcess
125 ? post_processor(SkRect::Make(cropRect.size())) : nullptr;
126 auto animatedImage = SkAnimatedImage::Make(std::move(androidCodec),
127 info, cropRect, std::move(postProcessor));
128 animatedImage->setRepetitionCount(0);
129
130 for (int frame = 0; frame < kMaxFrames; frame++) {
131 {
132 SkAutoCanvasRestore acr(canvas, doCrop);
133 if (doCrop) {
134 canvas->translate(cropRect.left(), cropRect.top());
135 }
136 drawProc(animatedImage);
137 }
138
139 canvas->translate(fTranslate, 0);
140 const auto duration = animatedImage->currentFrameDuration();
142 break;
143 }
144 for (int i = 0; i < fStep; i++) {
145 animatedImage->decodeNextFrame();
146 }
147 }
148 }
149 }
150 canvas->restore();
151 canvas->translate(0, fTranslate);
152 }
153 }
154 }
155};
156
157DEF_GM( return new AnimatedImageGM("images/stoplight_h.webp", "stoplight", 2,
158 // Deliberately not centered in X or Y, and shows all three
159 // lights, but otherwise arbitrary.
160 SkIRect::MakeLTRB(5, 6, 11, 29)); )
161DEF_GM( return new AnimatedImageGM("images/flightAnim.gif", "flight", 20,
162 // Deliberately starts in the upper left corner to exercise
163 // a special case, but otherwise arbitrary.
164 SkIRect::MakeLTRB(0, 0, 300, 200)); )
SkPath fPath
static int step(int x, SkScalar min, SkScalar max)
Definition BlurTest.cpp:215
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
const char * fName
sk_sp< SkData > GetResourceAsData(const char *resource)
Definition Resources.cpp:42
constexpr SkColor SK_ColorTRANSPARENT
Definition SkColor.h:99
static bool SkEncodedOriginSwapsWidthHeight(SkEncodedOrigin origin)
static SkMatrix SkEncodedOriginToMatrix(SkEncodedOrigin origin, int w, int h)
#define SkScalarFloorToInt(x)
Definition SkScalar.h:35
SK_API SkString static SkString SkStringPrintf()
Definition SkString.h:287
static sk_sp< SkPicture > post_processor(const SkRect &bounds)
SkString getName() const override
AnimatedImageGM(const char *path, const char *name, int step, SkIRect cropRect)
void onDraw(SkCanvas *canvas) override
~AnimatedImageGM() override=default
static std::unique_ptr< SkAndroidCodec > MakeFromCodec(std::unique_ptr< SkCodec >)
static sk_sp< SkAnimatedImage > Make(std::unique_ptr< SkAndroidCodec >, const SkImageInfo &info, SkIRect cropRect, sk_sp< SkPicture > postProcess)
static constexpr int kFinished
void restore()
Definition SkCanvas.cpp:465
void translate(SkScalar dx, SkScalar dy)
int save()
Definition SkCanvas.cpp:451
void drawPath(const SkPath &path, const SkPaint &paint)
void drawPicture(const SkPicture *picture)
Definition SkCanvas.h:1961
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition SkCanvas.h:1528
static std::unique_ptr< SkCodec > MakeFromData(sk_sp< SkData >, SkSpan< const SkCodecs::Decoder > decoders, SkPngChunkReader *=nullptr)
Definition SkCodec.cpp:241
static SkMatrix RectToRect(const SkRect &src, const SkRect &dst, ScaleToFit mode=kFill_ScaleToFit)
Definition SkMatrix.h:157
SkPathBuilder & setFillType(SkPathFillType ft)
SkPathBuilder & addRRect(const SkRRect &, SkPathDirection, unsigned startIndex)
SkCanvas * beginRecording(const SkRect &bounds, sk_sp< SkBBoxHierarchy > bbh)
sk_sp< SkPicture > finishRecordingAsPicture()
static SkRRect MakeRectXY(const SkRect &rect, SkScalar xRad, SkScalar yRad)
Definition SkRRect.h:180
const Paint & paint
sk_sp< SkImage > image
Definition examples.cpp:29
double duration
Definition examples.cpp:30
double frame
Definition examples.cpp:31
const char * name
Definition fuchsia.cc:50
#define DEF_GM(CODE)
Definition gm.h:40
const Scalar scale
static constexpr SkIRect MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b)
Definition SkRect.h:91
static constexpr SkIRect MakeSize(const SkISize &size)
Definition SkRect.h:66
constexpr int32_t height() const
Definition SkSize.h:37
static SkRect Make(const SkISize &size)
Definition SkRect.h:669
void roundOut(SkIRect *dst) const
Definition SkRect.h:1241