blob: 87dabf652643d356e949939974968644768cdc5e [file] [log] [blame]
joshualitt44c48512015-08-01 07:33:41 -07001/*
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"
Mike Klein33d20552017-03-22 13:47:51 -04009#include "sk_tool_utils.h"
joshualitt44c48512015-08-01 07:33:41 -070010
11#include "Resources.h"
12#include "SkCanvas.h"
13#include "SkGradientShader.h"
Mike Klein10d66cc2017-11-10 11:33:43 -050014#include "SkRandomScalerContext.h"
joshualitt44c48512015-08-01 07:33:41 -070015#include "SkStream.h"
16#include "SkSurface.h"
17#include "SkTextBlob.h"
18#include "SkTypeface.h"
joshualitt44c48512015-08-01 07:33:41 -070019
joshualitt44c48512015-08-01 07:33:41 -070020#include "GrContext.h"
21
22namespace skiagm {
23class TextBlobRandomFont : public GM {
24public:
25 // This gm tests that textblobs can be translated and scaled with a font that returns random
26 // but deterministic masks
27 TextBlobRandomFont() { }
28
29protected:
30 void onOnceBeforeDraw() override {
31 SkTextBlobBuilder builder;
32
33 const char* text = "The quick brown fox jumps over the lazy dog.";
34
35 // make textbloben
36 SkPaint paint;
37 paint.setTextSize(32);
Ben Wagner20fa1e92018-04-30 15:39:15 -040038 paint.setAntiAlias(true);
joshualitt44c48512015-08-01 07:33:41 -070039 paint.setLCDRenderText(true);
40
41 // Setup our random scaler context
Ben Wagner20fa1e92018-04-30 15:39:15 -040042 auto typeface = sk_tool_utils::create_portable_typeface("sans-serif", SkFontStyle::Bold());
43 if (!typeface) {
44 typeface = SkTypeface::MakeDefault();
joshualitt44c48512015-08-01 07:33:41 -070045 }
Ben Wagner20fa1e92018-04-30 15:39:15 -040046 paint.setColor(SK_ColorMAGENTA);
47 paint.setTypeface(sk_make_sp<SkRandomTypeface>(std::move(typeface), paint, false));
joshualitt44c48512015-08-01 07:33:41 -070048
Ben Wagner20fa1e92018-04-30 15:39:15 -040049 SkScalar y = 0;
joshualitt44c48512015-08-01 07:33:41 -070050 SkRect bounds;
51 paint.measureText(text, strlen(text), &bounds);
Ben Wagner20fa1e92018-04-30 15:39:15 -040052 y -= bounds.fTop;
53 sk_tool_utils::add_to_text_blob(&builder, text, paint, 0, y);
54 y += bounds.fBottom;
joshualitt44c48512015-08-01 07:33:41 -070055
56 // A8
joshualittd45fb5a2015-08-01 10:33:40 -070057 const char* bigtext1 = "The quick brown fox";
58 const char* bigtext2 = "jumps over the lazy dog.";
59 paint.setTextSize(160);
joshualitt44c48512015-08-01 07:33:41 -070060 paint.setSubpixelText(false);
61 paint.setLCDRenderText(false);
joshualittd45fb5a2015-08-01 10:33:40 -070062 paint.measureText(bigtext1, strlen(bigtext1), &bounds);
Ben Wagner20fa1e92018-04-30 15:39:15 -040063 y -= bounds.fTop;
64 sk_tool_utils::add_to_text_blob(&builder, bigtext1, paint, 0, y);
65 y += bounds.fBottom;
joshualittd45fb5a2015-08-01 10:33:40 -070066
67 paint.measureText(bigtext2, strlen(bigtext2), &bounds);
Ben Wagner20fa1e92018-04-30 15:39:15 -040068 y -= bounds.fTop;
69 sk_tool_utils::add_to_text_blob(&builder, bigtext2, paint, 0, y);
70 y += bounds.fBottom;
joshualittd45fb5a2015-08-01 10:33:40 -070071
72 // color emoji
Mike Kleinb251b722017-11-13 11:03:16 -050073 if (sk_sp<SkTypeface> origEmoji = sk_tool_utils::emoji_typeface()) {
Ben Wagner20fa1e92018-04-30 15:39:15 -040074 paint.setTypeface(sk_make_sp<SkRandomTypeface>(origEmoji, paint, false));
joshualittd45fb5a2015-08-01 10:33:40 -070075 const char* emojiText = sk_tool_utils::emoji_sample_text();
76 paint.measureText(emojiText, strlen(emojiText), &bounds);
Ben Wagner20fa1e92018-04-30 15:39:15 -040077 y -= bounds.fTop;
78 sk_tool_utils::add_to_text_blob(&builder, emojiText, paint, 0, y);
79 y += bounds.fBottom;
joshualittd45fb5a2015-08-01 10:33:40 -070080 }
joshualitt44c48512015-08-01 07:33:41 -070081
82 // build
fmalita37283c22016-09-13 10:00:23 -070083 fBlob = builder.make();
joshualitt44c48512015-08-01 07:33:41 -070084 }
85
86 SkString onShortName() override {
87 return SkString("textblobrandomfont");
88 }
89
90 SkISize onISize() override {
91 return SkISize::Make(kWidth, kHeight);
92 }
93
94 void onDraw(SkCanvas* canvas) override {
95 // This GM exists to test a specific feature of the GPU backend.
Ben Wagner20fa1e92018-04-30 15:39:15 -040096 // This GM uses sk_tool_utils::makeSurface which doesn't work well with vias.
97 // This GM uses SkRandomTypeface which doesn't work well with serialization.
halcanary96fcdcc2015-08-27 07:41:13 -070098 if (nullptr == canvas->getGrContext()) {
halcanary2a243382015-09-09 08:16:41 -070099 skiagm::GM::DrawGpuOnlyMessage(canvas);
joshualitt44c48512015-08-01 07:33:41 -0700100 return;
101 }
102
103 canvas->drawColor(sk_tool_utils::color_to_565(SK_ColorWHITE));
104
Brian Osmanf9412802016-12-02 12:07:17 -0500105 SkImageInfo info = SkImageInfo::Make(kWidth, kHeight, canvas->imageInfo().colorType(),
106 kPremul_SkAlphaType,
Mike Reed693fdbd2017-01-12 10:13:40 -0500107 canvas->imageInfo().refColorSpace());
brianosman3a0dbde2016-07-26 11:36:05 -0700108 SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
Mike Reed46596ae2018-01-02 15:40:29 -0500109 auto surface(sk_tool_utils::makeSurface(canvas, info, &props));
Ben Wagner20fa1e92018-04-30 15:39:15 -0400110 if (!surface) {
joshualitt44c48512015-08-01 07:33:41 -0700111 const char* text = "This test requires a surface";
112 size_t len = strlen(text);
113 SkPaint paint;
114 canvas->drawText(text, len, 10, 100, paint);
Ben Wagner20fa1e92018-04-30 15:39:15 -0400115 return;
116 }
117
118 SkPaint paint;
119 paint.setAntiAlias(true);
120
Jim Van Verth30f64e42018-05-24 14:32:26 -0400121 SkCanvas* surfaceCanvas = surface->getCanvas();
Ben Wagner20fa1e92018-04-30 15:39:15 -0400122
123 SkScalar stride = SkScalarCeilToScalar(fBlob->bounds().height());
124 SkScalar yOffset = 5;
Ben Wagner20fa1e92018-04-30 15:39:15 -0400125
Jim Van Verth30f64e42018-05-24 14:32:26 -0400126 canvas->save();
127 // Originally we would alternate between rotating and not to force blob regeneration,
128 // but that code seems to have rotted. Keeping the rotate to match the old GM as
129 // much as possible, and it seems like a reasonable stress test for transformed
130 // color emoji.
131 canvas->rotate(-0.05f);
132 canvas->drawTextBlob(fBlob, 10, yOffset, paint);
133 yOffset += stride;
134 canvas->restore();
Ben Wagner20fa1e92018-04-30 15:39:15 -0400135
Jim Van Verth30f64e42018-05-24 14:32:26 -0400136 // this will test lcd masks when not requested
137 // on cpu this currently causes unspecified behavior, so avoid until it is fixed
138 if (canvas->getGrContext()) {
139 // Rotate in the surface canvas, not the final canvas, to avoid aliasing
140 surfaceCanvas->rotate(-0.05f);
141 surfaceCanvas->drawTextBlob(fBlob, 10, yOffset, paint);
142 surface->draw(canvas, 0, 0, nullptr);
joshualitt44c48512015-08-01 07:33:41 -0700143 }
Jim Van Verth30f64e42018-05-24 14:32:26 -0400144 yOffset += stride;
145
146 // free gpu resources and verify
147 if (canvas->getGrContext()) {
148 canvas->getGrContext()->freeGpuResources();
149 }
150
151 canvas->rotate(-0.05f);
152 canvas->drawTextBlob(fBlob, 10, yOffset, paint);
153 yOffset += stride;
joshualitt44c48512015-08-01 07:33:41 -0700154 }
155
156private:
fmalita37283c22016-09-13 10:00:23 -0700157 sk_sp<SkTextBlob> fBlob;
joshualitt44c48512015-08-01 07:33:41 -0700158
mtkleindbfd7ab2016-09-01 11:24:54 -0700159 static constexpr int kWidth = 2000;
160 static constexpr int kHeight = 1600;
joshualitt44c48512015-08-01 07:33:41 -0700161
162 typedef GM INHERITED;
163};
164
165//////////////////////////////////////////////////////////////////////////////
166
halcanary385fe4d2015-08-26 13:07:48 -0700167DEF_GM(return new TextBlobRandomFont;)
joshualitt44c48512015-08-01 07:33:41 -0700168}