xref: /aosp_15_r20/external/skia/gm/fontregen.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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 // GM to stress TextBlob regeneration and the GPU font cache
9 // It's not necessary to run this with CPU configs
10 //
11 // The point here is to draw a set of text that will fit in one Plot, and then some large
12 // text. After a flush we draw the first set of text again with a slightly different color,
13 // and then enough new large text to spill the entire atlas. What *should* happen is that
14 // the Plot with the first set of text will not get overwritten by the new large text.
15 
16 #include "gm/gm.h"
17 #include "include/core/SkCanvas.h"
18 #include "include/core/SkColor.h"
19 #include "include/core/SkFont.h"
20 #include "include/core/SkFontMgr.h"
21 #include "include/core/SkFontStyle.h"
22 #include "include/core/SkFontTypes.h"
23 #include "include/core/SkPaint.h"
24 #include "include/core/SkRefCnt.h"
25 #include "include/core/SkScalar.h"
26 #include "include/core/SkSize.h"
27 #include "include/core/SkString.h"
28 #include "include/core/SkTextBlob.h"
29 #include "include/core/SkTypeface.h"
30 #include "include/core/SkTypes.h"
31 #include "include/gpu/ganesh/GrContextOptions.h"
32 #include "include/gpu/ganesh/GrDirectContext.h"
33 #include "include/gpu/ganesh/GrRecordingContext.h"
34 #include "include/private/base/SkTemplates.h"
35 #include "include/private/gpu/ganesh/GrTypesPriv.h"
36 #include "src/gpu/ganesh/GrDirectContextPriv.h"
37 #include "tools/ToolUtils.h"
38 #include "tools/fonts/FontToolUtils.h"
39 
40 #if defined(SK_GRAPHITE)
41 #include "include/gpu/graphite/ContextOptions.h"
42 #endif
43 
44 using namespace skia_private;
45 using MaskFormat = skgpu::MaskFormat;
46 
make_blob(const SkString & text,const SkFont & font)47 static sk_sp<SkTextBlob> make_blob(const SkString& text, const SkFont& font) {
48     size_t len = text.size();
49     AutoTArray<SkScalar>  pos(len);
50     AutoTArray<SkGlyphID> glyphs(len);
51 
52     font.textToGlyphs(text.c_str(), len, SkTextEncoding::kUTF8, glyphs.get(), len);
53     font.getXPos(glyphs.get(), len, pos.get());
54     return SkTextBlob::MakeFromPosTextH(text.c_str(), len, pos.get(), 0, font);
55 }
56 
57 class FontRegenGM : public skiagm::GM {
58 
modifyGrContextOptions(GrContextOptions * options)59     void modifyGrContextOptions(GrContextOptions* options) override {
60         options->fGlyphCacheTextureMaximumBytes = 0;
61         options->fAllowMultipleGlyphCacheTextures = GrContextOptions::Enable::kNo;
62     }
63 
64 #if defined(SK_GRAPHITE)
modifyGraphiteContextOptions(skgpu::graphite::ContextOptions * options) const65     void modifyGraphiteContextOptions(skgpu::graphite::ContextOptions* options) const override {
66         options->fGlyphCacheTextureMaximumBytes = 0;
67         options->fAllowMultipleAtlasTextures = false;
68     }
69 #endif
70 
getName() const71     SkString getName() const override { return SkString("fontregen"); }
72 
getISize()73     SkISize getISize() override { return {kSize, kSize}; }
74 
onOnceBeforeDraw()75     void onOnceBeforeDraw() override {
76         this->setBGColor(SK_ColorLTGRAY);
77 
78         auto tf = ToolUtils::CreatePortableTypeface("sans-serif", SkFontStyle::Normal());
79 
80         static const SkString kTexts[] = {
81             SkString("abcdefghijklmnopqrstuvwxyz"),
82             SkString("ABCDEFGHI"),
83             SkString("NOPQRSTUV")
84         };
85 
86         SkFont font;
87         font.setEdging(SkFont::Edging::kAntiAlias);
88         font.setSubpixel(false);
89         font.setSize(80);
90         font.setTypeface(tf);
91 
92         fBlobs[0] = make_blob(kTexts[0], font);
93         font.setSize(162);
94         fBlobs[1] = make_blob(kTexts[1], font);
95         fBlobs[2] = make_blob(kTexts[2], font);
96     }
97 
onDraw(SkCanvas * canvas,SkString * errorMsg)98     DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
99 
100 
101         SkPaint paint;
102         paint.setColor(SK_ColorBLACK);
103         canvas->drawTextBlob(fBlobs[0], 10, 80, paint);
104         canvas->drawTextBlob(fBlobs[1], 10, 225, paint);
105 
106         auto dContext = GrAsDirectContext(canvas->recordingContext());
107         if (dContext) {
108             dContext->flushAndSubmit();
109         }
110 
111         paint.setColor(0xFF010101);
112         canvas->drawTextBlob(fBlobs[0], 10, 305, paint);
113         canvas->drawTextBlob(fBlobs[2], 10, 465, paint);
114 
115         //  Debugging tool for GPU.
116         static const bool kShowAtlas = false;
117         if (kShowAtlas && dContext) {
118             auto img = dContext->priv().testingOnly_getFontAtlasImage(MaskFormat::kA8);
119             canvas->drawImage(img, 200, 0);
120         }
121 
122         return DrawResult::kOk;
123     }
124 
125 private:
126     inline static constexpr int kSize = 512;
127 
128     sk_sp<SkTextBlob> fBlobs[3];
129     using INHERITED = GM;
130 };
131 
132 //////////////////////////////////////////////////////////////////////////////
133 
134 DEF_GM(return new FontRegenGM())
135 
136 ///////////////////////////////////////////////////////////////////////////////
137 
138 class BadAppleGM : public skiagm::GM {
getName() const139     SkString getName() const override { return SkString("badapple"); }
140 
getISize()141     SkISize getISize() override { return {kSize, kSize}; }
142 
onOnceBeforeDraw()143     void onOnceBeforeDraw() override {
144         this->setBGColor(SK_ColorWHITE);
145         auto fm = ToolUtils::TestFontMgr();
146 
147         static const SkString kTexts[] = {
148                 SkString("Meet"),
149                 SkString("iPad Pro"),
150         };
151 
152         SkFont font = ToolUtils::DefaultPortableFont();
153         font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
154         font.setSubpixel(true);
155         font.setSize(256);
156 
157         fBlobs[0] = make_blob(kTexts[0], font);
158         fBlobs[1] = make_blob(kTexts[1], font);
159     }
160 
onDraw(SkCanvas * canvas)161     void onDraw(SkCanvas* canvas) override {
162         SkPaint paint;
163         paint.setColor(0xFF111111);
164         canvas->drawTextBlob(fBlobs[0], 10, 260, paint);
165         canvas->drawTextBlob(fBlobs[1], 10, 500, paint);
166     }
167 
168 private:
169     inline static constexpr int kSize = 512;
170 
171     sk_sp<SkTextBlob> fBlobs[3];
172     using INHERITED = GM;
173 };
174 
175 //////////////////////////////////////////////////////////////////////////////
176 
177 DEF_GM(return new BadAppleGM())
178