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 "SkCanvas.h" 10 #include "SkUTF.h" 11 #include "SkColorPriv.h" 12 #include "SkColorFilter.h" 13 #include "SkImage.h" 14 #include "SkRandom.h" 15 #include "SkTime.h" 16 #include "SkTypeface.h" 17 #include "Timer.h" 18 19 #if SK_SUPPORT_GPU 20 #include "GrContext.h" 21 #include "GrContextPriv.h" 22 #endif 23 24 SkRandom gRand; 25 26 static void DrawTheText(SkCanvas* canvas, const char text[], size_t length, SkScalar x, SkScalar y, 27 const SkFont& font, const SkPaint& paint) { 28 SkFont f(font); 29 f.setSubpixel(true); 30 canvas->drawSimpleText(text, length, kUTF8_SkTextEncoding, x, y, f, paint); 31 } 32 33 // This sample demonstrates the cache behavior of bitmap vs. distance field text 34 // It renders variously sized text with an animated scale and rotation. 35 // Specifically one should: 36 // use 'D' to toggle between bitmap and distance field fonts 37 // use '2' to toggle between scaling the image by 2x 38 // -- this feature boosts the rendering out of the small point-size 39 // SDF-text special case (which falls back to bitmap fonts for small points) 40 41 class AnimatedTextView : public Sample { 42 public: 43 AnimatedTextView() : fScale(1.0f), fScaleInc(0.1f), fRotation(0.0f), fSizeScale(1) { 44 fCurrentTime = 0; 45 fTimer.start(); 46 memset(fTimes, 0, sizeof(fTimes)); 47 } 48 49 protected: 50 bool onQuery(Sample::Event* evt) override { 51 if (Sample::TitleQ(*evt)) { 52 Sample::TitleR(evt, "AnimatedText"); 53 return true; 54 } 55 56 SkUnichar uni; 57 if (Sample::CharQ(*evt, &uni)) { 58 if ('2' == uni) { 59 if (fSizeScale == 2) { 60 fSizeScale = 1; 61 } else { 62 fSizeScale = 2; 63 } 64 return true; 65 } 66 } 67 return this->INHERITED::onQuery(evt); 68 } 69 70 void onDrawContent(SkCanvas* canvas) override { 71 SkFont font(SkTypeface::MakeFromFile("/skimages/samplefont.ttf")); 72 73 SkPaint paint; 74 paint.setAntiAlias(true); 75 paint.setFilterQuality(kMedium_SkFilterQuality); 76 77 SkString outString("fps: "); 78 fTimer.end(); 79 80 // TODO: generalize this timing code in utils 81 fTimes[fCurrentTime] = (float)(fTimer.fWall); 82 fCurrentTime = (fCurrentTime + 1) & 0x1f; 83 84 float meanTime = 0.0f; 85 for (int i = 0; i < 32; ++i) { 86 meanTime += fTimes[i]; 87 } 88 meanTime /= 32.f; 89 SkScalar fps = 1000.f / meanTime; 90 outString.appendScalar(fps); 91 outString.append(" ms: "); 92 outString.appendScalar(meanTime); 93 94 SkString modeString("Text scale: "); 95 modeString.appendU32(fSizeScale); 96 modeString.append("x"); 97 98 fTimer.start(); 99 100 canvas->save(); 101 102 #if SK_SUPPORT_GPU 103 GrContext* grContext = canvas->getGrContext(); 104 if (grContext) { 105 sk_sp<SkImage> image = grContext->priv().testingOnly_getFontAtlasImage( 106 GrMaskFormat::kA8_GrMaskFormat); 107 canvas->drawImageRect(image, 108 SkRect::MakeXYWH(512.0f, 10.0f, 512.0f, 512.0f), &paint); 109 } 110 #endif 111 canvas->translate(180, 180); 112 canvas->rotate(fRotation); 113 canvas->scale(fScale, fScale); 114 canvas->translate(-180, -180); 115 116 const char* text = "Hamburgefons"; 117 size_t length = strlen(text); 118 119 SkScalar y = SkIntToScalar(0); 120 for (int i = 12; i <= 26; i++) { 121 font.setSize(SkIntToScalar(i*fSizeScale)); 122 y += font.getSpacing(); 123 DrawTheText(canvas, text, length, SkIntToScalar(110), y, font, paint); 124 } 125 canvas->restore(); 126 127 font.setSize(16); 128 // canvas->drawString(outString, 512.f, 540.f, paint); 129 canvas->drawString(modeString, 768.f, 540.f, font, paint); 130 } 131 132 bool onAnimate(const SkAnimTimer& timer) override { 133 // We add noise to the scale and rotation animations to 134 // keep the font atlas from falling into a steady state 135 fRotation += (1.0f + gRand.nextRangeF(-0.1f, 0.1f)); 136 fScale += (fScaleInc + gRand.nextRangeF(-0.025f, 0.025f)); 137 if (fScale >= 2.0f) { 138 fScaleInc = -0.1f; 139 } else if (fScale <= 1.0f) { 140 fScaleInc = 0.1f; 141 } 142 return true; 143 } 144 145 private: 146 float fScale; 147 float fScaleInc; 148 float fRotation; 149 int fSizeScale; 150 151 WallTimer fTimer; 152 float fTimes[32]; 153 int fCurrentTime; 154 155 156 typedef Sample INHERITED; 157 }; 158 159 ////////////////////////////////////////////////////////////////////////////// 160 161 DEF_SAMPLE( return new AnimatedTextView(); ) 162