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