xref: /aosp_15_r20/external/skia/tools/viewer/AnimatedTextSlide.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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 "include/core/SkCanvas.h"
9 #include "include/core/SkColorFilter.h"
10 #include "include/core/SkColorPriv.h"
11 #include "include/core/SkFont.h"
12 #include "include/core/SkFontMgr.h"
13 #include "include/core/SkImage.h"
14 #include "include/core/SkTypeface.h"
15 #include "src/base/SkRandom.h"
16 #include "src/base/SkTime.h"
17 #include "src/base/SkUTF.h"
18 #include "tools/fonts/FontToolUtils.h"
19 #include "tools/viewer/Slide.h"
20 
21 #if defined(SK_GANESH)
22 #include "include/gpu/ganesh/GrDirectContext.h"
23 #include "src/gpu/ganesh/GrDirectContextPriv.h"
24 
25 using MaskFormat = skgpu::MaskFormat;
26 #endif
27 
28 SkRandom gRand;
29 
DrawTheText(SkCanvas * canvas,const char text[],size_t length,SkScalar x,SkScalar y,const SkFont & font,const SkPaint & paint)30 static void DrawTheText(SkCanvas* canvas, const char text[], size_t length, SkScalar x, SkScalar y,
31                         const SkFont& font, const SkPaint& paint) {
32     SkFont f(font);
33     f.setSubpixel(true);
34     canvas->drawSimpleText(text, length, SkTextEncoding::kUTF8, x, y, f, paint);
35 }
36 
37 // This sample demonstrates the cache behavior of bitmap vs. distance field text
38 // It renders variously sized text with an animated scale and rotation.
39 // Specifically one should:
40 //   use 'D' to toggle between bitmap and distance field fonts
41 //   use '2' to toggle between scaling the image by 2x
42 //            -- this feature boosts the rendering out of the small point-size
43 //               SDF-text special case (which falls back to bitmap fonts for small points)
44 
45 class AnimatedTextSlide : public Slide {
46     float fScale = 1;
47     float fScaleInc = 0.1f;
48     float fRotation = 0;
49     int   fSizeScale = 1;
50 
51 public:
AnimatedTextSlide()52     AnimatedTextSlide() { fName = "AnimatedText"; }
53 
onChar(SkUnichar uni)54     bool onChar(SkUnichar uni) override {
55             if ('2' == uni) {
56                 if (fSizeScale == 2) {
57                     fSizeScale = 1;
58                 } else {
59                     fSizeScale = 2;
60                 }
61                 return true;
62             }
63             return false;
64     }
65 
draw(SkCanvas * canvas)66     void draw(SkCanvas* canvas) override {
67         SkFont font(ToolUtils::TestFontMgr()->makeFromFile("/skimages/samplefont.ttf"));
68 
69         SkPaint paint;
70         paint.setAntiAlias(true);
71 
72         canvas->save();
73 
74 #if defined(SK_GANESH)
75         auto direct = GrAsDirectContext(canvas->recordingContext());
76         if (direct) {
77             SkSamplingOptions sampling(SkFilterMode::kLinear, SkMipmapMode::kNearest);
78             sk_sp<SkImage> image = direct->priv().testingOnly_getFontAtlasImage(MaskFormat::kA8);
79             const SkRect rect = SkRect::MakeXYWH(512.0f, 10.0f, 512.0f, 512.0f);
80             canvas->drawImageRect(image.get(), rect, rect, sampling, &paint,
81                                   SkCanvas::kFast_SrcRectConstraint);
82         }
83 #endif
84         canvas->translate(180, 180);
85         canvas->rotate(fRotation);
86         canvas->scale(fScale, fScale);
87         canvas->translate(-180, -180);
88 
89         const char* text = "Hamburgefons";
90         size_t length = strlen(text);
91 
92         SkScalar y = SkIntToScalar(0);
93         for (int i = 12; i <= 26; i++) {
94             font.setSize(SkIntToScalar(i*fSizeScale));
95             y += font.getSpacing();
96             DrawTheText(canvas, text, length, SkIntToScalar(110), y, font, paint);
97         }
98         canvas->restore();
99 
100         font.setSize(16);
101     }
102 
animate(double nanos)103     bool animate(double nanos) override {
104         // TODO: use nanos
105         // We add noise to the scale and rotation animations to
106         // keep the font atlas from falling into a steady state
107         fRotation += (1.0f + gRand.nextRangeF(-0.1f, 0.1f));
108         fScale += (fScaleInc + gRand.nextRangeF(-0.025f, 0.025f));
109         if (fScale >= 2.0f) {
110             fScaleInc = -0.1f;
111         } else if (fScale <= 1.0f) {
112             fScaleInc = 0.1f;
113         }
114         return true;
115     }
116 };
117 
118 DEF_SLIDE( return new AnimatedTextSlide(); )
119