blob: 1aa50e2fb9c0ceac606d5a049629269ed1f5e26c [file] [log] [blame]
jvanverth629162d2015-11-08 08:07:24 -08001/*
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
Ben Wagnerb2c4ea62018-08-08 11:36:17 -04008#include "Sample.h"
jvanverth629162d2015-11-08 08:07:24 -08009#include "SkCanvas.h"
Hal Canaryea60b952018-08-21 11:45:46 -040010#include "SkUTF.h"
jvanverth629162d2015-11-08 08:07:24 -080011#include "SkColorPriv.h"
12#include "SkColorFilter.h"
Florin Malitaab244f02017-05-03 19:16:58 +000013#include "SkImage.h"
jvanverth629162d2015-11-08 08:07:24 -080014#include "SkRandom.h"
jvanverth629162d2015-11-08 08:07:24 -080015#include "SkTime.h"
16#include "SkTypeface.h"
jvanverth629162d2015-11-08 08:07:24 -080017#include "Timer.h"
18
kkinnunen83a5d422015-11-17 09:38:05 -080019#if SK_SUPPORT_GPU
jvanverth629162d2015-11-08 08:07:24 -080020#include "GrContext.h"
Robert Phillips0c4b7b12018-03-06 08:20:37 -050021#include "GrContextPriv.h"
kkinnunen83a5d422015-11-17 09:38:05 -080022#endif
jvanverth629162d2015-11-08 08:07:24 -080023
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
Ben Wagnerb2c4ea62018-08-08 11:36:17 -040042class AnimatedTextView : public Sample {
jvanverth629162d2015-11-08 08:07:24 -080043public:
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:
Ben Wagnerb2c4ea62018-08-08 11:36:17 -040051 bool onQuery(Sample::Event* evt) override {
52 if (Sample::TitleQ(*evt)) {
53 Sample::TitleR(evt, "AnimatedText");
jvanverth629162d2015-11-08 08:07:24 -080054 return true;
55 }
56
57 SkUnichar uni;
Ben Wagnerb2c4ea62018-08-08 11:36:17 -040058 if (Sample::CharQ(*evt, &uni)) {
jvanverth629162d2015-11-08 08:07:24 -080059 if ('2' == uni) {
60 if (fSizeScale == 2) {
61 fSizeScale = 1;
62 } else {
63 fSizeScale = 2;
64 }
65 return true;
66 }
67 }
68 return this->INHERITED::onQuery(evt);
69 }
70
71 void onDrawContent(SkCanvas* canvas) override {
72 SkPaint paint;
bungeman13b9c952016-05-12 10:09:30 -070073 paint.setTypeface(SkTypeface::MakeFromFile("/skimages/samplefont.ttf"));
jvanverth629162d2015-11-08 08:07:24 -080074 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
jvanverth629162d2015-11-08 08:07:24 -0800103 GrContext* grContext = canvas->getGrContext();
104 if (grContext) {
Robert Phillips0c4b7b12018-03-06 08:20:37 -0500105 sk_sp<SkImage> image = grContext->contextPriv().getFontAtlasImage_ForTesting(
106 GrMaskFormat::kA8_GrMaskFormat);
Robert Phillips22f4a1f2016-12-20 08:57:26 -0500107 canvas->drawImageRect(image,
108 SkRect::MakeXYWH(512.0f, 10.0f, 512.0f, 512.0f), &paint);
jvanverth629162d2015-11-08 08:07:24 -0800109 }
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 paint.setTextSize(SkIntToScalar(i*fSizeScale));
122 y += paint.getFontSpacing();
123 DrawTheText(canvas, text, length, SkIntToScalar(110), y, paint);
124 }
125 canvas->restore();
126
127 paint.setTextSize(16);
Cary Clark2a475ea2017-04-28 15:35:12 -0400128// canvas->drawString(outString, 512.f, 540.f, paint);
129 canvas->drawString(modeString, 768.f, 540.f, paint);
jvanverth629162d2015-11-08 08:07:24 -0800130 }
131
132 bool onAnimate(const SkAnimTimer& timer) override {
halcanary9d524f22016-03-29 09:03:52 -0700133 // We add noise to the scale and rotation animations to
jvanverth629162d2015-11-08 08:07:24 -0800134 // 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
145private:
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
Ben Wagnerb2c4ea62018-08-08 11:36:17 -0400156 typedef Sample INHERITED;
jvanverth629162d2015-11-08 08:07:24 -0800157};
158
159//////////////////////////////////////////////////////////////////////////////
160
Ben Wagnerb2c4ea62018-08-08 11:36:17 -0400161DEF_SAMPLE( return new AnimatedTextView(); )