• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 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 "include/core/SkCanvas.h"
9 #include "include/core/SkDrawable.h"
10 #include "include/core/SkFont.h"
11 #include "include/core/SkPath.h"
12 #include "include/core/SkRSXform.h"
13 #include "include/core/SkSurface.h"
14 #include "include/utils/SkTextUtils.h"
15 #include "src/base/SkRandom.h"
16 #include "src/core/SkPaintPriv.h"
17 #include "tools/viewer/Slide.h"
18 
19 typedef void (*DrawAtlasProc)(SkCanvas*, SkImage*, const SkRSXform[], const SkRect[],
20                               const SkColor[], int, const SkRect*, const SkSamplingOptions&,
21                               const SkPaint*);
22 
draw_atlas(SkCanvas * canvas,SkImage * atlas,const SkRSXform xform[],const SkRect tex[],const SkColor colors[],int count,const SkRect * cull,const SkSamplingOptions & sampling,const SkPaint * paint)23 static void draw_atlas(SkCanvas* canvas, SkImage* atlas, const SkRSXform xform[],
24                        const SkRect tex[], const SkColor colors[], int count, const SkRect* cull,
25                        const SkSamplingOptions& sampling, const SkPaint* paint) {
26     canvas->drawAtlas(atlas, xform, tex, colors, count, SkBlendMode::kModulate,
27                       sampling, cull, paint);
28 }
29 
draw_atlas_sim(SkCanvas * canvas,SkImage * atlas,const SkRSXform xform[],const SkRect tex[],const SkColor colors[],int count,const SkRect * cull,const SkSamplingOptions & sampling,const SkPaint * paint)30 static void draw_atlas_sim(SkCanvas* canvas, SkImage* atlas, const SkRSXform xform[],
31                            const SkRect tex[], const SkColor colors[], int count, const SkRect* cull,
32                            const SkSamplingOptions& sampling, const SkPaint* paint) {
33     for (int i = 0; i < count; ++i) {
34         SkMatrix matrix;
35         matrix.setRSXform(xform[i]);
36 
37         canvas->save();
38         canvas->concat(matrix);
39         canvas->drawImageRect(atlas, tex[i], tex[i].makeOffset(-tex[i].x(), -tex[i].y()),
40                               sampling, paint, SkCanvas::kFast_SrcRectConstraint);
41         canvas->restore();
42     }
43 }
44 
make_atlas(int atlasSize,int cellSize)45 static sk_sp<SkImage> make_atlas(int atlasSize, int cellSize) {
46     SkImageInfo info = SkImageInfo::MakeN32Premul(atlasSize, atlasSize);
47     auto surface(SkSurface::MakeRaster(info));
48     SkCanvas* canvas = surface->getCanvas();
49 
50     SkPaint paint;
51     SkRandom rand;
52 
53     const SkScalar half = cellSize * SK_ScalarHalf;
54     const char* s = "01234567890!@#$%^&*=+<>?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
55     SkFont font(nullptr, 28);
56 
57     int i = 0;
58     for (int y = 0; y < atlasSize; y += cellSize) {
59         for (int x = 0; x < atlasSize; x += cellSize) {
60             paint.setColor(rand.nextU());
61             paint.setAlpha(0xFF);
62             int index = i % strlen(s);
63             SkTextUtils::Draw(canvas, &s[index], 1, SkTextEncoding::kUTF8,
64                               x + half, y + half + half/2, font, paint,
65                               SkTextUtils::kCenter_Align);
66             i += 1;
67         }
68     }
69     return surface->makeImageSnapshot();
70 }
71 
72 class DrawAtlasDrawable : public SkDrawable {
73     enum {
74         kMaxScale = 2,
75         kCellSize = 32,
76         kAtlasSize = 512,
77     };
78 
79     struct Rec {
80         SkPoint     fCenter;
81         SkVector    fVelocity;
82         SkScalar    fScale;
83         SkScalar    fDScale;
84         SkScalar    fRadian;
85         SkScalar    fDRadian;
86         SkScalar    fAlpha;
87         SkScalar    fDAlpha;
88 
advanceDrawAtlasDrawable::Rec89         void advance(const SkRect& bounds) {
90             fCenter += fVelocity;
91             if (fCenter.fX > bounds.right()) {
92                 SkASSERT(fVelocity.fX > 0);
93                 fVelocity.fX = -fVelocity.fX;
94             } else if (fCenter.fX < bounds.left()) {
95                 SkASSERT(fVelocity.fX < 0);
96                 fVelocity.fX = -fVelocity.fX;
97             }
98             if (fCenter.fY > bounds.bottom()) {
99                 if (fVelocity.fY > 0) {
100                     fVelocity.fY = -fVelocity.fY;
101                 }
102             } else if (fCenter.fY < bounds.top()) {
103                 if (fVelocity.fY < 0) {
104                     fVelocity.fY = -fVelocity.fY;
105                 }
106             }
107 
108             fScale += fDScale;
109             if (fScale > 2 || fScale < SK_Scalar1/2) {
110                 fDScale = -fDScale;
111             }
112 
113             fRadian += fDRadian;
114             fRadian = SkScalarMod(fRadian, 2 * SK_ScalarPI);
115 
116             fAlpha += fDAlpha;
117             if (fAlpha > 1) {
118                 fAlpha = 1;
119                 fDAlpha = -fDAlpha;
120             } else if (fAlpha < 0) {
121                 fAlpha = 0;
122                 fDAlpha = -fDAlpha;
123             }
124         }
125 
asRSXformDrawAtlasDrawable::Rec126         SkRSXform asRSXform() const {
127             return SkRSXform::MakeFromRadians(fScale, fRadian, fCenter.x(), fCenter.y(),
128                                               SkScalarHalf(kCellSize), SkScalarHalf(kCellSize));
129         }
130     };
131 
132     DrawAtlasProc fProc;
133 
134     enum {
135         N = 256,
136     };
137 
138     sk_sp<SkImage> fAtlas;
139     Rec         fRec[N];
140     SkRect      fTex[N];
141     SkRect      fBounds;
142     bool        fUseColors;
143 
144 public:
DrawAtlasDrawable(DrawAtlasProc proc,const SkRect & r)145     DrawAtlasDrawable(DrawAtlasProc proc, const SkRect& r)
146         : fProc(proc), fBounds(r), fUseColors(false)
147     {
148         SkRandom rand;
149         fAtlas = make_atlas(kAtlasSize, kCellSize);
150         const SkScalar kMaxSpeed = 5;
151         const SkScalar cell = SkIntToScalar(kCellSize);
152         int i = 0;
153         for (int y = 0; y < kAtlasSize; y += kCellSize) {
154             for (int x = 0; x < kAtlasSize; x += kCellSize) {
155                 const SkScalar sx = SkIntToScalar(x);
156                 const SkScalar sy = SkIntToScalar(y);
157                 fTex[i].setXYWH(sx, sy, cell, cell);
158 
159                 fRec[i].fCenter.set(sx + cell/2, sy + 3*cell/4);
160                 fRec[i].fVelocity.fX = rand.nextSScalar1() * kMaxSpeed;
161                 fRec[i].fVelocity.fY = rand.nextSScalar1() * kMaxSpeed;
162                 fRec[i].fScale = 1;
163                 fRec[i].fDScale = rand.nextSScalar1() / 16;
164                 fRec[i].fRadian = 0;
165                 fRec[i].fDRadian = rand.nextSScalar1() / 8;
166                 fRec[i].fAlpha = rand.nextUScalar1();
167                 fRec[i].fDAlpha = rand.nextSScalar1() / 10;
168                 i += 1;
169             }
170         }
171     }
172 
toggleUseColors()173     void toggleUseColors() {
174         fUseColors = !fUseColors;
175     }
176 
177 protected:
onDraw(SkCanvas * canvas)178     void onDraw(SkCanvas* canvas) override {
179         SkRSXform xform[N];
180         SkColor colors[N];
181 
182         for (int i = 0; i < N; ++i) {
183             fRec[i].advance(fBounds);
184             xform[i] = fRec[i].asRSXform();
185             if (fUseColors) {
186                 colors[i] = SkColorSetARGB((int)(fRec[i].fAlpha * 0xFF), 0xFF, 0xFF, 0xFF);
187             }
188         }
189         SkPaint paint;
190         SkSamplingOptions sampling(SkFilterMode::kLinear);
191 
192         const SkRect cull = this->getBounds();
193         const SkColor* colorsPtr = fUseColors ? colors : nullptr;
194         fProc(canvas, fAtlas.get(), xform, fTex, colorsPtr, N, &cull, sampling, &paint);
195     }
196 
onGetBounds()197     SkRect onGetBounds() override {
198         const SkScalar border = kMaxScale * kCellSize;
199         SkRect r = fBounds;
200         r.outset(border, border);
201         return r;
202     }
203 
204 private:
205     using INHERITED = SkDrawable;
206 };
207 
208 class DrawAtlasSlide : public Slide {
209     DrawAtlasProc fProc;
210     sk_sp<DrawAtlasDrawable> fDrawable;
211 
212 public:
DrawAtlasSlide(const char name[],DrawAtlasProc proc)213     DrawAtlasSlide(const char name[], DrawAtlasProc proc) : fProc(proc) { fName = name; }
214 
onChar(SkUnichar uni)215     bool onChar(SkUnichar uni) override {
216             switch (uni) {
217                 case 'C': fDrawable->toggleUseColors(); return true;
218                 default: break;
219             }
220             return false;
221     }
222 
draw(SkCanvas * canvas)223     void draw(SkCanvas* canvas) override {
224         canvas->drawDrawable(fDrawable.get());
225     }
226 
animate(double)227     bool animate(double /*nanos*/) override { return true; }
228 #if 0
229     // TODO: switch over to use this for our animation
230     bool animate(double nanos) override {
231         SkScalar angle = SkDoubleToScalar(fmod(1e-9 * nanos * 360 / 24, 360));
232         fAnimatingDrawable->setSweep(angle);
233         return true;
234     }
235 #endif
236 
load(SkScalar winWidth,SkScalar winHeight)237     void load(SkScalar winWidth, SkScalar winHeight) override {
238         fDrawable = sk_make_sp<DrawAtlasDrawable>(fProc, SkRect::Make(this->getDimensions()));
239     }
240 
getDimensions() const241     SkISize getDimensions() const override { return {640, 480}; }
242 };
243 
244 //////////////////////////////////////////////////////////////////////////////
245 
246 DEF_SLIDE( return new DrawAtlasSlide("DrawAtlas", draw_atlas); )
247 DEF_SLIDE( return new DrawAtlasSlide("DrawAtlasSim", draw_atlas_sim); )
248