• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "gm.h"
9 #include "sk_tool_utils.h"
10 
11 #include "Resources.h"
12 #include "SkCanvas.h"
13 #include "SkGradientShader.h"
14 #include "SkRandomScalerContext.h"
15 #include "SkStream.h"
16 #include "SkSurface.h"
17 #include "SkTextBlob.h"
18 #include "SkTypeface.h"
19 
20 #include "GrContext.h"
21 
22 namespace skiagm {
23 class TextBlobRandomFont : public GM {
24 public:
25     // This gm tests that textblobs can be translated and scaled with a font that returns random
26     // but deterministic masks
TextBlobRandomFont()27     TextBlobRandomFont() { }
28 
29 protected:
onOnceBeforeDraw()30     void onOnceBeforeDraw() override {
31         SkTextBlobBuilder builder;
32 
33         const char* text = "The quick brown fox jumps over the lazy dog.";
34 
35         SkPaint paint;
36         paint.setAntiAlias(true);
37         paint.setColor(SK_ColorMAGENTA);
38 
39         // make textbloben
40         SkFont font;
41         font.setSize(32);
42         font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
43 
44         // Setup our random scaler context
45         auto typeface = sk_tool_utils::create_portable_typeface("sans-serif", SkFontStyle::Bold());
46         if (!typeface) {
47             typeface = SkTypeface::MakeDefault();
48         }
49         font.setTypeface(sk_make_sp<SkRandomTypeface>(std::move(typeface), paint, false));
50 
51         SkScalar y = 0;
52         SkRect bounds;
53         font.measureText(text, strlen(text), kUTF8_SkTextEncoding, &bounds);
54         y -= bounds.fTop;
55         sk_tool_utils::add_to_text_blob(&builder, text, font, 0, y);
56         y += bounds.fBottom;
57 
58         // A8
59         const char* bigtext1 = "The quick brown fox";
60         const char* bigtext2 = "jumps over the lazy dog.";
61         font.setSize(160);
62         font.setSubpixel(false);
63         font.setEdging(SkFont::Edging::kAntiAlias);
64         font.measureText(bigtext1, strlen(bigtext1), kUTF8_SkTextEncoding, &bounds);
65         y -= bounds.fTop;
66         sk_tool_utils::add_to_text_blob(&builder, bigtext1, font, 0, y);
67         y += bounds.fBottom;
68 
69         font.measureText(bigtext2, strlen(bigtext2), kUTF8_SkTextEncoding, &bounds);
70         y -= bounds.fTop;
71         sk_tool_utils::add_to_text_blob(&builder, bigtext2, font, 0, y);
72         y += bounds.fBottom;
73 
74         // color emoji
75         if (sk_sp<SkTypeface> origEmoji = sk_tool_utils::emoji_typeface()) {
76             font.setTypeface(sk_make_sp<SkRandomTypeface>(origEmoji, paint, false));
77             const char* emojiText = sk_tool_utils::emoji_sample_text();
78             font.measureText(emojiText, strlen(emojiText), kUTF8_SkTextEncoding, &bounds);
79             y -= bounds.fTop;
80             sk_tool_utils::add_to_text_blob(&builder, emojiText, font, 0, y);
81             y += bounds.fBottom;
82         }
83 
84         // build
85         fBlob = builder.make();
86     }
87 
onShortName()88     SkString onShortName() override {
89         return SkString("textblobrandomfont");
90     }
91 
onISize()92     SkISize onISize() override {
93         return SkISize::Make(kWidth, kHeight);
94     }
95 
onDraw(SkCanvas * canvas)96     void onDraw(SkCanvas* canvas) override {
97         // This GM exists to test a specific feature of the GPU backend.
98         // This GM uses sk_tool_utils::makeSurface which doesn't work well with vias.
99         // This GM uses SkRandomTypeface which doesn't work well with serialization.
100         if (nullptr == canvas->getGrContext()) {
101             skiagm::GM::DrawGpuOnlyMessage(canvas);
102             return;
103         }
104 
105         canvas->drawColor(SK_ColorWHITE);
106 
107         SkImageInfo info = SkImageInfo::Make(kWidth, kHeight, canvas->imageInfo().colorType(),
108                                              kPremul_SkAlphaType,
109                                              canvas->imageInfo().refColorSpace());
110         SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
111         auto surface(sk_tool_utils::makeSurface(canvas, info, &props));
112         if (!surface) {
113             canvas->drawString("This test requires a surface", 10, 100, SkFont(), SkPaint());
114             return;
115         }
116 
117         SkPaint paint;
118         paint.setAntiAlias(true);
119 
120         SkCanvas* surfaceCanvas = surface->getCanvas();
121 
122         SkScalar stride = SkScalarCeilToScalar(fBlob->bounds().height());
123         SkScalar yOffset = 5;
124 
125         canvas->save();
126         // Originally we would alternate between rotating and not to force blob regeneration,
127         // but that code seems to have rotted. Keeping the rotate to match the old GM as
128         // much as possible, and it seems like a reasonable stress test for transformed
129         // color emoji.
130         canvas->rotate(-0.05f);
131         canvas->drawTextBlob(fBlob, 10, yOffset, paint);
132         yOffset += stride;
133         canvas->restore();
134 
135         // this will test lcd masks when not requested
136         // on cpu this currently causes unspecified behavior, so avoid until it is fixed
137         if (canvas->getGrContext()) {
138             // Rotate in the surface canvas, not the final canvas, to avoid aliasing
139             surfaceCanvas->rotate(-0.05f);
140             surfaceCanvas->drawTextBlob(fBlob, 10, yOffset, paint);
141             surface->draw(canvas, 0, 0, nullptr);
142         }
143         yOffset += stride;
144 
145         // free gpu resources and verify
146         if (canvas->getGrContext()) {
147             canvas->getGrContext()->freeGpuResources();
148         }
149 
150         canvas->rotate(-0.05f);
151         canvas->drawTextBlob(fBlob, 10, yOffset, paint);
152         yOffset += stride;
153     }
154 
155 private:
156     sk_sp<SkTextBlob> fBlob;
157 
158     static constexpr int kWidth = 2000;
159     static constexpr int kHeight = 1600;
160 
161     typedef GM INHERITED;
162 };
163 
164 //////////////////////////////////////////////////////////////////////////////
165 
166 DEF_GM(return new TextBlobRandomFont;)
167 }
168