• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/GrContextOptions.h"
32 #include "include/gpu/GrDirectContext.h"
33 #include "include/gpu/GrRecordingContext.h"
34 #include "include/private/GrTypesPriv.h"
35 #include "include/private/SkTemplates.h"
36 #include "src/gpu/GrDirectContextPriv.h"
37 #include "tools/ToolUtils.h"
38 
make_blob(const SkString & text,const SkFont & font)39 static sk_sp<SkTextBlob> make_blob(const SkString& text, const SkFont& font) {
40     size_t len = text.size();
41     SkAutoTArray<SkScalar>  pos(len);
42     SkAutoTArray<SkGlyphID> glyphs(len);
43 
44     font.textToGlyphs(text.c_str(), len, SkTextEncoding::kUTF8, glyphs.get(), len);
45     font.getXPos(glyphs.get(), len, pos.get());
46     return SkTextBlob::MakeFromPosTextH(text.c_str(), len, pos.get(), 0, font);
47 }
48 
49 class FontRegenGM : public skiagm::GM {
50 
modifyGrContextOptions(GrContextOptions * options)51     void modifyGrContextOptions(GrContextOptions* options) override {
52         options->fGlyphCacheTextureMaximumBytes = 0;
53         options->fAllowMultipleGlyphCacheTextures = GrContextOptions::Enable::kNo;
54     }
55 
onShortName()56     SkString onShortName() override { return SkString("fontregen"); }
57 
onISize()58     SkISize onISize() override { return {kSize, kSize}; }
59 
onOnceBeforeDraw()60     void onOnceBeforeDraw() override {
61         this->setBGColor(SK_ColorLTGRAY);
62 
63         auto tf = ToolUtils::create_portable_typeface("sans-serif", SkFontStyle::Normal());
64 
65         static const SkString kTexts[] = {
66             SkString("abcdefghijklmnopqrstuvwxyz"),
67             SkString("ABCDEFGHI"),
68             SkString("NOPQRSTUV")
69         };
70 
71         SkFont font;
72         font.setEdging(SkFont::Edging::kAntiAlias);
73         font.setSubpixel(false);
74         font.setSize(80);
75         font.setTypeface(tf);
76 
77         fBlobs[0] = make_blob(kTexts[0], font);
78         font.setSize(162);
79         fBlobs[1] = make_blob(kTexts[1], font);
80         fBlobs[2] = make_blob(kTexts[2], font);
81     }
82 
onDraw(SkCanvas * canvas,SkString * errorMsg)83     DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
84         auto dContext = GrAsDirectContext(canvas->recordingContext());
85         if (!dContext) {
86             *errorMsg = "GPU-specific";
87             return DrawResult::kSkip;
88         }
89 
90         SkPaint paint;
91         paint.setColor(SK_ColorBLACK);
92         canvas->drawTextBlob(fBlobs[0], 10, 80, paint);
93         canvas->drawTextBlob(fBlobs[1], 10, 225, paint);
94         dContext->flushAndSubmit();
95 
96         paint.setColor(0xFF010101);
97         canvas->drawTextBlob(fBlobs[0], 10, 305, paint);
98         canvas->drawTextBlob(fBlobs[2], 10, 465, paint);
99 
100         //  Debugging tool for GPU.
101         static const bool kShowAtlas = false;
102         if (kShowAtlas) {
103             auto img = dContext->priv().testingOnly_getFontAtlasImage(kA8_GrMaskFormat);
104             canvas->drawImage(img, 200, 0);
105         }
106 
107         return DrawResult::kOk;
108     }
109 
110 private:
111     inline static constexpr int kSize = 512;
112 
113     sk_sp<SkTextBlob> fBlobs[3];
114     using INHERITED = GM;
115 };
116 
117 //////////////////////////////////////////////////////////////////////////////
118 
119 DEF_GM(return new FontRegenGM())
120 
121 ///////////////////////////////////////////////////////////////////////////////
122 
123 class BadAppleGM : public skiagm::GM {
124 
onShortName()125     SkString onShortName() override { return SkString("badapple"); }
126 
onISize()127     SkISize onISize() override { return {kSize, kSize}; }
128 
onOnceBeforeDraw()129     void onOnceBeforeDraw() override {
130         this->setBGColor(SK_ColorWHITE);
131         auto fm = SkFontMgr::RefDefault();
132 
133         static const SkString kTexts[] = {
134                 SkString("Meet"),
135                 SkString("iPad Pro"),
136         };
137 
138         SkFont font;
139         font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
140         font.setSubpixel(true);
141         font.setSize(256);
142 
143         fBlobs[0] = make_blob(kTexts[0], font);
144         fBlobs[1] = make_blob(kTexts[1], font);
145     }
146 
onDraw(SkCanvas * canvas)147     void onDraw(SkCanvas* canvas) override {
148         SkPaint paint;
149         paint.setColor(0xFF111111);
150         canvas->drawTextBlob(fBlobs[0], 10, 260, paint);
151         canvas->drawTextBlob(fBlobs[1], 10, 500, paint);
152     }
153 
154 private:
155     inline static constexpr int kSize = 512;
156 
157     sk_sp<SkTextBlob> fBlobs[3];
158     using INHERITED = GM;
159 };
160 
161 //////////////////////////////////////////////////////////////////////////////
162 
163 DEF_GM(return new BadAppleGM())
164