blob: d8a2a30ecd25d03b97a4eb4a9ecf0a1b027e7aa7 [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -05009#include "include/core/SkCanvas.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040010#include "include/core/SkColor.h"
11#include "include/core/SkColorSpace.h"
12#include "include/core/SkFont.h"
13#include "include/core/SkFontStyle.h"
14#include "include/core/SkFontTypes.h"
15#include "include/core/SkImageInfo.h"
16#include "include/core/SkPaint.h"
17#include "include/core/SkRect.h"
18#include "include/core/SkRefCnt.h"
19#include "include/core/SkScalar.h"
20#include "include/core/SkSize.h"
21#include "include/core/SkString.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050022#include "include/core/SkSurface.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040023#include "include/core/SkSurfaceProps.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050024#include "include/core/SkTextBlob.h"
25#include "include/core/SkTypeface.h"
Robert Phillipsb7bfbc22020-07-01 12:55:01 -040026#include "include/gpu/GrDirectContext.h"
27#include "include/gpu/GrRecordingContext.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040028#include "tools/ToolUtils.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050029#include "tools/fonts/RandomScalerContext.h"
joshualitt44c48512015-08-01 07:33:41 -070030
Ben Wagner7fde8e12019-05-01 17:28:53 -040031#include <string.h>
32#include <utility>
33
34class GrRenderTargetContext;
joshualitt44c48512015-08-01 07:33:41 -070035
36namespace skiagm {
Chris Dalton3a778372019-02-07 15:23:36 -070037class TextBlobRandomFont : public GpuGM {
joshualitt44c48512015-08-01 07:33:41 -070038public:
39 // This gm tests that textblobs can be translated and scaled with a font that returns random
40 // but deterministic masks
41 TextBlobRandomFont() { }
42
43protected:
44 void onOnceBeforeDraw() override {
45 SkTextBlobBuilder builder;
46
47 const char* text = "The quick brown fox jumps over the lazy dog.";
48
joshualitt44c48512015-08-01 07:33:41 -070049 SkPaint paint;
Ben Wagner20fa1e92018-04-30 15:39:15 -040050 paint.setAntiAlias(true);
Mike Reedea8900e2018-12-22 17:37:30 -050051 paint.setColor(SK_ColorMAGENTA);
52
53 // make textbloben
54 SkFont font;
55 font.setSize(32);
56 font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
joshualitt44c48512015-08-01 07:33:41 -070057
58 // Setup our random scaler context
Mike Kleinea3f0142019-03-20 11:12:10 -050059 auto typeface = ToolUtils::create_portable_typeface("sans-serif", SkFontStyle::Bold());
Ben Wagner20fa1e92018-04-30 15:39:15 -040060 if (!typeface) {
61 typeface = SkTypeface::MakeDefault();
joshualitt44c48512015-08-01 07:33:41 -070062 }
Mike Reedea8900e2018-12-22 17:37:30 -050063 font.setTypeface(sk_make_sp<SkRandomTypeface>(std::move(typeface), paint, false));
joshualitt44c48512015-08-01 07:33:41 -070064
Ben Wagner20fa1e92018-04-30 15:39:15 -040065 SkScalar y = 0;
joshualitt44c48512015-08-01 07:33:41 -070066 SkRect bounds;
Ben Wagner51e15a62019-05-07 15:38:46 -040067 font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
Ben Wagner20fa1e92018-04-30 15:39:15 -040068 y -= bounds.fTop;
Mike Kleinea3f0142019-03-20 11:12:10 -050069 ToolUtils::add_to_text_blob(&builder, text, font, 0, y);
Ben Wagner20fa1e92018-04-30 15:39:15 -040070 y += bounds.fBottom;
joshualitt44c48512015-08-01 07:33:41 -070071
72 // A8
joshualittd45fb5a2015-08-01 10:33:40 -070073 const char* bigtext1 = "The quick brown fox";
74 const char* bigtext2 = "jumps over the lazy dog.";
Mike Reedea8900e2018-12-22 17:37:30 -050075 font.setSize(160);
76 font.setSubpixel(false);
77 font.setEdging(SkFont::Edging::kAntiAlias);
Ben Wagner51e15a62019-05-07 15:38:46 -040078 font.measureText(bigtext1, strlen(bigtext1), SkTextEncoding::kUTF8, &bounds);
Ben Wagner20fa1e92018-04-30 15:39:15 -040079 y -= bounds.fTop;
Mike Kleinea3f0142019-03-20 11:12:10 -050080 ToolUtils::add_to_text_blob(&builder, bigtext1, font, 0, y);
Ben Wagner20fa1e92018-04-30 15:39:15 -040081 y += bounds.fBottom;
joshualittd45fb5a2015-08-01 10:33:40 -070082
Ben Wagner51e15a62019-05-07 15:38:46 -040083 font.measureText(bigtext2, strlen(bigtext2), SkTextEncoding::kUTF8, &bounds);
Ben Wagner20fa1e92018-04-30 15:39:15 -040084 y -= bounds.fTop;
Mike Kleinea3f0142019-03-20 11:12:10 -050085 ToolUtils::add_to_text_blob(&builder, bigtext2, font, 0, y);
Ben Wagner20fa1e92018-04-30 15:39:15 -040086 y += bounds.fBottom;
joshualittd45fb5a2015-08-01 10:33:40 -070087
88 // color emoji
Mike Kleinea3f0142019-03-20 11:12:10 -050089 if (sk_sp<SkTypeface> origEmoji = ToolUtils::emoji_typeface()) {
Mike Reedea8900e2018-12-22 17:37:30 -050090 font.setTypeface(sk_make_sp<SkRandomTypeface>(origEmoji, paint, false));
Mike Kleinea3f0142019-03-20 11:12:10 -050091 const char* emojiText = ToolUtils::emoji_sample_text();
Ben Wagner51e15a62019-05-07 15:38:46 -040092 font.measureText(emojiText, strlen(emojiText), SkTextEncoding::kUTF8, &bounds);
Ben Wagner20fa1e92018-04-30 15:39:15 -040093 y -= bounds.fTop;
Mike Kleinea3f0142019-03-20 11:12:10 -050094 ToolUtils::add_to_text_blob(&builder, emojiText, font, 0, y);
Ben Wagner20fa1e92018-04-30 15:39:15 -040095 y += bounds.fBottom;
joshualittd45fb5a2015-08-01 10:33:40 -070096 }
joshualitt44c48512015-08-01 07:33:41 -070097
98 // build
fmalita37283c22016-09-13 10:00:23 -070099 fBlob = builder.make();
joshualitt44c48512015-08-01 07:33:41 -0700100 }
101
102 SkString onShortName() override {
103 return SkString("textblobrandomfont");
104 }
105
106 SkISize onISize() override {
107 return SkISize::Make(kWidth, kHeight);
108 }
109
Robert Phillips95c250c2020-06-29 15:36:12 -0400110 DrawResult onDraw(GrRecordingContext* context, GrRenderTargetContext*, SkCanvas* canvas,
Chris Dalton50e24d72019-02-07 16:20:09 -0700111 SkString* errorMsg) override {
joshualitt44c48512015-08-01 07:33:41 -0700112 // This GM exists to test a specific feature of the GPU backend.
Mike Kleinea3f0142019-03-20 11:12:10 -0500113 // This GM uses ToolUtils::makeSurface which doesn't work well with vias.
Ben Wagner20fa1e92018-04-30 15:39:15 -0400114 // This GM uses SkRandomTypeface which doesn't work well with serialization.
Mike Kleind46dce32018-08-16 10:17:03 -0400115 canvas->drawColor(SK_ColorWHITE);
joshualitt44c48512015-08-01 07:33:41 -0700116
Brian Osmanf9412802016-12-02 12:07:17 -0500117 SkImageInfo info = SkImageInfo::Make(kWidth, kHeight, canvas->imageInfo().colorType(),
118 kPremul_SkAlphaType,
Mike Reed693fdbd2017-01-12 10:13:40 -0500119 canvas->imageInfo().refColorSpace());
brianosman3a0dbde2016-07-26 11:36:05 -0700120 SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
Mike Kleinea3f0142019-03-20 11:12:10 -0500121 auto surface(ToolUtils::makeSurface(canvas, info, &props));
Ben Wagner20fa1e92018-04-30 15:39:15 -0400122 if (!surface) {
Chris Dalton50e24d72019-02-07 16:20:09 -0700123 *errorMsg = "This test requires a surface";
124 return DrawResult::kFail;
Ben Wagner20fa1e92018-04-30 15:39:15 -0400125 }
126
127 SkPaint paint;
128 paint.setAntiAlias(true);
129
Jim Van Verth30f64e42018-05-24 14:32:26 -0400130 SkCanvas* surfaceCanvas = surface->getCanvas();
Ben Wagner20fa1e92018-04-30 15:39:15 -0400131
132 SkScalar stride = SkScalarCeilToScalar(fBlob->bounds().height());
133 SkScalar yOffset = 5;
Ben Wagner20fa1e92018-04-30 15:39:15 -0400134
Jim Van Verth30f64e42018-05-24 14:32:26 -0400135 canvas->save();
136 // Originally we would alternate between rotating and not to force blob regeneration,
137 // but that code seems to have rotted. Keeping the rotate to match the old GM as
138 // much as possible, and it seems like a reasonable stress test for transformed
139 // color emoji.
140 canvas->rotate(-0.05f);
141 canvas->drawTextBlob(fBlob, 10, yOffset, paint);
142 yOffset += stride;
143 canvas->restore();
Ben Wagner20fa1e92018-04-30 15:39:15 -0400144
Chris Dalton3a778372019-02-07 15:23:36 -0700145 // Rotate in the surface canvas, not the final canvas, to avoid aliasing
146 surfaceCanvas->rotate(-0.05f);
147 surfaceCanvas->drawTextBlob(fBlob, 10, yOffset, paint);
148 surface->draw(canvas, 0, 0, nullptr);
Jim Van Verth30f64e42018-05-24 14:32:26 -0400149 yOffset += stride;
150
Robert Phillipsf8f45d92020-07-01 11:11:18 -0400151 if (auto direct = context->asDirectContext()) {
Robert Phillips95c250c2020-06-29 15:36:12 -0400152 // free gpu resources and verify
Robert Phillips44333c52020-06-30 13:28:00 -0400153 direct->freeGpuResources();
Robert Phillips95c250c2020-06-29 15:36:12 -0400154 }
Jim Van Verth30f64e42018-05-24 14:32:26 -0400155
156 canvas->rotate(-0.05f);
157 canvas->drawTextBlob(fBlob, 10, yOffset, paint);
158 yOffset += stride;
Chris Dalton50e24d72019-02-07 16:20:09 -0700159 return DrawResult::kOk;
joshualitt44c48512015-08-01 07:33:41 -0700160 }
161
162private:
fmalita37283c22016-09-13 10:00:23 -0700163 sk_sp<SkTextBlob> fBlob;
joshualitt44c48512015-08-01 07:33:41 -0700164
mtkleindbfd7ab2016-09-01 11:24:54 -0700165 static constexpr int kWidth = 2000;
166 static constexpr int kHeight = 1600;
joshualitt44c48512015-08-01 07:33:41 -0700167
168 typedef GM INHERITED;
169};
170
171//////////////////////////////////////////////////////////////////////////////
172
halcanary385fe4d2015-08-26 13:07:48 -0700173DEF_GM(return new TextBlobRandomFont;)
joshualitt44c48512015-08-01 07:33:41 -0700174}