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