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