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.h"
17
18 #include "GrContext.h"
19 #include "GrContextPriv.h"
20 #include "GrContextOptions.h"
21 #include "SkCanvas.h"
22 #include "SkGraphics.h"
23 #include "SkImage.h"
24 #include "SkTypeface.h"
25 #include "gm.h"
26
27 #include "sk_tool_utils.h"
28
make_blob(const SkString & text,const SkFont & font)29 static sk_sp<SkTextBlob> make_blob(const SkString& text, const SkFont& font) {
30 size_t len = text.size();
31 SkAutoTArray<SkScalar> pos(len);
32 SkAutoTArray<SkGlyphID> glyphs(len);
33
34 font.textToGlyphs(text.c_str(), len, SkTextEncoding::kUTF8, glyphs.get(), len);
35 font.getXPos(glyphs.get(), len, pos.get());
36 return SkTextBlob::MakeFromPosTextH(text.c_str(), len, pos.get(), 0, font);
37 }
38
39 class FontRegenGM : public skiagm::GpuGM {
40 public:
FontRegenGM()41 FontRegenGM() {
42 this->setBGColor(SK_ColorLTGRAY);
43 }
44
modifyGrContextOptions(GrContextOptions * options)45 void modifyGrContextOptions(GrContextOptions* options) override {
46 options->fGlyphCacheTextureMaximumBytes = 0;
47 options->fAllowMultipleGlyphCacheTextures = GrContextOptions::Enable::kNo;
48 }
49
50 protected:
onShortName()51 SkString onShortName() override {
52 SkString name("fontregen");
53 return name;
54 }
55
onISize()56 SkISize onISize() override { return SkISize::Make(kSize, kSize); }
57
onOnceBeforeDraw()58 void onOnceBeforeDraw() override {
59 auto tf = sk_tool_utils::create_portable_typeface("sans-serif", SkFontStyle::Normal());
60
61 static const SkString kTexts[] = {
62 SkString("abcdefghijklmnopqrstuvwxyz"),
63 SkString("ABCDEFGHI"),
64 SkString("NOPQRSTUV")
65 };
66
67 SkFont font;
68 font.setEdging(SkFont::Edging::kAntiAlias);
69 font.setSubpixel(false);
70 font.setSize(80);
71 font.setTypeface(tf);
72
73 fBlobs[0] = make_blob(kTexts[0], font);
74 font.setSize(162);
75 fBlobs[1] = make_blob(kTexts[1], font);
76 fBlobs[2] = make_blob(kTexts[2], font);
77 }
78
onDraw(GrContext * context,GrRenderTargetContext *,SkCanvas * canvas)79 void onDraw(GrContext* context, GrRenderTargetContext*, SkCanvas* canvas) override {
80 SkPaint paint;
81 paint.setColor(SK_ColorBLACK);
82 canvas->drawTextBlob(fBlobs[0], 10, 80, paint);
83 canvas->drawTextBlob(fBlobs[1], 10, 225, paint);
84 context->flush();
85
86 paint.setColor(0xFF010101);
87 canvas->drawTextBlob(fBlobs[0], 10, 305, paint);
88 canvas->drawTextBlob(fBlobs[2], 10, 465, paint);
89
90 // Debugging tool for GPU.
91 static const bool kShowAtlas = false;
92 if (kShowAtlas) {
93 auto img = context->priv().testingOnly_getFontAtlasImage(kA8_GrMaskFormat);
94 canvas->drawImage(img, 200, 0);
95 }
96 }
97
98 private:
99 static constexpr SkScalar kSize = 512;
100
101 sk_sp<SkTextBlob> fBlobs[3];
102 typedef GM INHERITED;
103 };
104
105 constexpr SkScalar FontRegenGM::kSize;
106
107 //////////////////////////////////////////////////////////////////////////////
108
109 DEF_GM(return new FontRegenGM())
110