blob: 6d7055912f148a05bc85c928ce2da8942111303d [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
joshualitt44c48512015-08-01 07:33:41 -070034namespace skiagm {
Robert Phillipsedcd4312021-06-03 10:14:16 -040035class TextBlobRandomFont : public GM {
joshualitt44c48512015-08-01 07:33:41 -070036public:
37 // This gm tests that textblobs can be translated and scaled with a font that returns random
38 // but deterministic masks
39 TextBlobRandomFont() { }
40
41protected:
42 void onOnceBeforeDraw() override {
43 SkTextBlobBuilder builder;
44
45 const char* text = "The quick brown fox jumps over the lazy dog.";
46
joshualitt44c48512015-08-01 07:33:41 -070047 SkPaint paint;
Ben Wagner20fa1e92018-04-30 15:39:15 -040048 paint.setAntiAlias(true);
Mike Reedea8900e2018-12-22 17:37:30 -050049 paint.setColor(SK_ColorMAGENTA);
50
51 // make textbloben
52 SkFont font;
53 font.setSize(32);
54 font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
joshualitt44c48512015-08-01 07:33:41 -070055
56 // Setup our random scaler context
Mike Kleinea3f0142019-03-20 11:12:10 -050057 auto typeface = ToolUtils::create_portable_typeface("sans-serif", SkFontStyle::Bold());
Ben Wagner20fa1e92018-04-30 15:39:15 -040058 if (!typeface) {
59 typeface = SkTypeface::MakeDefault();
joshualitt44c48512015-08-01 07:33:41 -070060 }
Mike Reedea8900e2018-12-22 17:37:30 -050061 font.setTypeface(sk_make_sp<SkRandomTypeface>(std::move(typeface), paint, false));
joshualitt44c48512015-08-01 07:33:41 -070062
Ben Wagner20fa1e92018-04-30 15:39:15 -040063 SkScalar y = 0;
joshualitt44c48512015-08-01 07:33:41 -070064 SkRect bounds;
Ben Wagner51e15a62019-05-07 15:38:46 -040065 font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
Ben Wagner20fa1e92018-04-30 15:39:15 -040066 y -= bounds.fTop;
Mike Kleinea3f0142019-03-20 11:12:10 -050067 ToolUtils::add_to_text_blob(&builder, text, font, 0, y);
Ben Wagner20fa1e92018-04-30 15:39:15 -040068 y += bounds.fBottom;
joshualitt44c48512015-08-01 07:33:41 -070069
70 // A8
joshualittd45fb5a2015-08-01 10:33:40 -070071 const char* bigtext1 = "The quick brown fox";
72 const char* bigtext2 = "jumps over the lazy dog.";
Mike Reedea8900e2018-12-22 17:37:30 -050073 font.setSize(160);
74 font.setSubpixel(false);
75 font.setEdging(SkFont::Edging::kAntiAlias);
Ben Wagner51e15a62019-05-07 15:38:46 -040076 font.measureText(bigtext1, strlen(bigtext1), SkTextEncoding::kUTF8, &bounds);
Ben Wagner20fa1e92018-04-30 15:39:15 -040077 y -= bounds.fTop;
Mike Kleinea3f0142019-03-20 11:12:10 -050078 ToolUtils::add_to_text_blob(&builder, bigtext1, font, 0, y);
Ben Wagner20fa1e92018-04-30 15:39:15 -040079 y += bounds.fBottom;
joshualittd45fb5a2015-08-01 10:33:40 -070080
Ben Wagner51e15a62019-05-07 15:38:46 -040081 font.measureText(bigtext2, strlen(bigtext2), SkTextEncoding::kUTF8, &bounds);
Ben Wagner20fa1e92018-04-30 15:39:15 -040082 y -= bounds.fTop;
Mike Kleinea3f0142019-03-20 11:12:10 -050083 ToolUtils::add_to_text_blob(&builder, bigtext2, font, 0, y);
Ben Wagner20fa1e92018-04-30 15:39:15 -040084 y += bounds.fBottom;
joshualittd45fb5a2015-08-01 10:33:40 -070085
86 // color emoji
Mike Kleinea3f0142019-03-20 11:12:10 -050087 if (sk_sp<SkTypeface> origEmoji = ToolUtils::emoji_typeface()) {
Mike Reedea8900e2018-12-22 17:37:30 -050088 font.setTypeface(sk_make_sp<SkRandomTypeface>(origEmoji, paint, false));
Mike Kleinea3f0142019-03-20 11:12:10 -050089 const char* emojiText = ToolUtils::emoji_sample_text();
Ben Wagner51e15a62019-05-07 15:38:46 -040090 font.measureText(emojiText, strlen(emojiText), SkTextEncoding::kUTF8, &bounds);
Ben Wagner20fa1e92018-04-30 15:39:15 -040091 y -= bounds.fTop;
Mike Kleinea3f0142019-03-20 11:12:10 -050092 ToolUtils::add_to_text_blob(&builder, emojiText, font, 0, y);
Ben Wagner20fa1e92018-04-30 15:39:15 -040093 y += bounds.fBottom;
joshualittd45fb5a2015-08-01 10:33:40 -070094 }
joshualitt44c48512015-08-01 07:33:41 -070095
96 // build
fmalita37283c22016-09-13 10:00:23 -070097 fBlob = builder.make();
joshualitt44c48512015-08-01 07:33:41 -070098 }
99
100 SkString onShortName() override {
101 return SkString("textblobrandomfont");
102 }
103
104 SkISize onISize() override {
105 return SkISize::Make(kWidth, kHeight);
106 }
107
Robert Phillipsedcd4312021-06-03 10:14:16 -0400108 DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
109 if (!canvas->recordingContext()) {
110 *errorMsg = "Active context required to create SkSurface";
111 return DrawResult::kSkip;
112 }
113
114 auto dContext = GrAsDirectContext(canvas->recordingContext());
115
joshualitt44c48512015-08-01 07:33:41 -0700116 // This GM exists to test a specific feature of the GPU backend.
Mike Kleinea3f0142019-03-20 11:12:10 -0500117 // This GM uses ToolUtils::makeSurface which doesn't work well with vias.
Ben Wagner20fa1e92018-04-30 15:39:15 -0400118 // This GM uses SkRandomTypeface which doesn't work well with serialization.
Mike Kleind46dce32018-08-16 10:17:03 -0400119 canvas->drawColor(SK_ColorWHITE);
joshualitt44c48512015-08-01 07:33:41 -0700120
Brian Osmanf9412802016-12-02 12:07:17 -0500121 SkImageInfo info = SkImageInfo::Make(kWidth, kHeight, canvas->imageInfo().colorType(),
122 kPremul_SkAlphaType,
Mike Reed693fdbd2017-01-12 10:13:40 -0500123 canvas->imageInfo().refColorSpace());
brianosman3a0dbde2016-07-26 11:36:05 -0700124 SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
Mike Kleinea3f0142019-03-20 11:12:10 -0500125 auto surface(ToolUtils::makeSurface(canvas, info, &props));
Ben Wagner20fa1e92018-04-30 15:39:15 -0400126 if (!surface) {
Chris Dalton50e24d72019-02-07 16:20:09 -0700127 *errorMsg = "This test requires a surface";
128 return DrawResult::kFail;
Ben Wagner20fa1e92018-04-30 15:39:15 -0400129 }
130
131 SkPaint paint;
132 paint.setAntiAlias(true);
133
Jim Van Verth30f64e42018-05-24 14:32:26 -0400134 SkCanvas* surfaceCanvas = surface->getCanvas();
Ben Wagner20fa1e92018-04-30 15:39:15 -0400135
136 SkScalar stride = SkScalarCeilToScalar(fBlob->bounds().height());
137 SkScalar yOffset = 5;
Ben Wagner20fa1e92018-04-30 15:39:15 -0400138
Jim Van Verth30f64e42018-05-24 14:32:26 -0400139 canvas->save();
140 // Originally we would alternate between rotating and not to force blob regeneration,
141 // but that code seems to have rotted. Keeping the rotate to match the old GM as
142 // much as possible, and it seems like a reasonable stress test for transformed
143 // color emoji.
144 canvas->rotate(-0.05f);
145 canvas->drawTextBlob(fBlob, 10, yOffset, paint);
146 yOffset += stride;
147 canvas->restore();
Ben Wagner20fa1e92018-04-30 15:39:15 -0400148
Chris Dalton3a778372019-02-07 15:23:36 -0700149 // Rotate in the surface canvas, not the final canvas, to avoid aliasing
150 surfaceCanvas->rotate(-0.05f);
151 surfaceCanvas->drawTextBlob(fBlob, 10, yOffset, paint);
Mike Reedb746b1f2021-01-06 08:43:51 -0500152 surface->draw(canvas, 0, 0);
Jim Van Verth30f64e42018-05-24 14:32:26 -0400153 yOffset += stride;
154
Robert Phillipsedcd4312021-06-03 10:14:16 -0400155 if (dContext) {
Robert Phillips95c250c2020-06-29 15:36:12 -0400156 // free gpu resources and verify
Robert Phillipsedcd4312021-06-03 10:14:16 -0400157 dContext->freeGpuResources();
Robert Phillips95c250c2020-06-29 15:36:12 -0400158 }
Jim Van Verth30f64e42018-05-24 14:32:26 -0400159
160 canvas->rotate(-0.05f);
161 canvas->drawTextBlob(fBlob, 10, yOffset, paint);
162 yOffset += stride;
Chris Dalton50e24d72019-02-07 16:20:09 -0700163 return DrawResult::kOk;
joshualitt44c48512015-08-01 07:33:41 -0700164 }
165
166private:
fmalita37283c22016-09-13 10:00:23 -0700167 sk_sp<SkTextBlob> fBlob;
joshualitt44c48512015-08-01 07:33:41 -0700168
Brian Salomon9fa47cc2021-10-08 18:48:26 -0400169 inline static constexpr int kWidth = 2000;
170 inline static constexpr int kHeight = 1600;
joshualitt44c48512015-08-01 07:33:41 -0700171
John Stiles7571f9e2020-09-02 22:42:33 -0400172 using INHERITED = GM;
joshualitt44c48512015-08-01 07:33:41 -0700173};
174
175//////////////////////////////////////////////////////////////////////////////
176
halcanary385fe4d2015-08-26 13:07:48 -0700177DEF_GM(return new TextBlobRandomFont;)
John Stilesa6841be2020-08-06 14:11:56 -0400178} // namespace skiagm