1 /* 2 * Copyright 2018 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 "SkFont.h" 12 #include "SkColorPriv.h" 13 #include "SkColorFilter.h" 14 #include "SkImage.h" 15 #include "SkRandom.h" 16 #include "SkTime.h" 17 #include "SkTypeface.h" 18 #include "Timer.h" 19 20 #if SK_SUPPORT_GPU 21 #include "GrContext.h" 22 #endif 23 24 // Create an animation of a bunch of letters that rotate in place. This is intended to stress 25 // the glyph atlas and test that we don't see corruption or bad slowdowns. 26 class FlutterAnimateView : public Sample { 27 public: FlutterAnimateView()28 FlutterAnimateView() : fCurrTime(0), fResetTime(0) {} 29 30 protected: onOnceBeforeDraw()31 void onOnceBeforeDraw() override { 32 fTypeface = SkTypeface::MakeFromFile("/skimages/samplefont.ttf"); 33 initChars(); 34 } 35 onQuery(Sample::Event * evt)36 bool onQuery(Sample::Event* evt) override { 37 if (Sample::TitleQ(*evt)) { 38 Sample::TitleR(evt, "FlutterAnimate"); 39 return true; 40 } 41 42 return this->INHERITED::onQuery(evt); 43 } 44 onDrawContent(SkCanvas * canvas)45 void onDrawContent(SkCanvas* canvas) override { 46 SkFont font(fTypeface, 50); 47 SkPaint paint; 48 paint.setFilterQuality(kMedium_SkFilterQuality); 49 50 // rough center of each glyph 51 static constexpr auto kMidX = 35; 52 static constexpr auto kMidY = 50; 53 54 canvas->clear(SK_ColorWHITE); 55 for (int i = 0; i < kNumChars; ++i) { 56 canvas->save(); 57 double rot = SkScalarInterp(fChars[i].fStartRotation, fChars[i].fEndRotation, 58 fCurrTime/kDuration); 59 canvas->translate(fChars[i].fPosition.fX + kMidX, fChars[i].fPosition.fY - kMidY); 60 canvas->rotate(SkRadiansToDegrees(rot)); 61 canvas->translate(-35,+50); 62 canvas->drawString(fChars[i].fChar, 0, 0, font, paint); 63 canvas->restore(); 64 } 65 } 66 onAnimate(const SkAnimTimer & timer)67 bool onAnimate(const SkAnimTimer& timer) override { 68 fCurrTime = timer.secs() - fResetTime; 69 if (fCurrTime > kDuration) { 70 this->initChars(); 71 fResetTime = timer.secs(); 72 fCurrTime = 0; 73 } 74 75 return true; 76 } 77 78 private: initChars()79 void initChars() { 80 for (int i = 0; i < kNumChars; ++i) { 81 char c = fRand.nextULessThan(26) + 65; 82 fChars[i].fChar[0] = c; 83 fChars[i].fChar[1] = '\0'; 84 fChars[i].fPosition = SkPoint::Make(fRand.nextF()*748 + 10, fRand.nextF()*1004 + 10); 85 fChars[i].fStartRotation = fRand.nextF(); 86 fChars[i].fEndRotation = fRand.nextF() * 20 - 10; 87 } 88 } 89 90 static constexpr double kDuration = 5.0; 91 double fCurrTime; 92 double fResetTime; 93 SkRandom fRand; 94 95 struct AnimatedChar { 96 char fChar[2]; 97 SkPoint fPosition; 98 SkScalar fStartRotation; 99 SkScalar fEndRotation; 100 }; 101 sk_sp<SkTypeface> fTypeface; 102 static constexpr int kNumChars = 40; 103 AnimatedChar fChars[kNumChars]; 104 105 typedef Sample INHERITED; 106 }; 107 108 ////////////////////////////////////////////////////////////////////////////// 109 110 DEF_SAMPLE( return new FlutterAnimateView(); ) 111