blob: 12a0c3d5ea087fb632e3c98e0f792958fa0e2c6d [file] [log] [blame]
jvanverth9564ce62014-09-16 05:45:19 -07001/*
2 * Copyright 2011 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 */
Hal Canaryc640d0d2018-06-13 09:59:02 -04007
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
9#include "include/core/SkCanvas.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040010#include "include/core/SkColor.h"
11#include "include/core/SkColorSpace.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "include/core/SkFont.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040013#include "include/core/SkFontStyle.h"
14#include "include/core/SkFontTypes.h"
15#include "include/core/SkImageInfo.h"
16#include "include/core/SkMatrix.h"
17#include "include/core/SkPaint.h"
18#include "include/core/SkPoint.h"
19#include "include/core/SkRect.h"
20#include "include/core/SkRefCnt.h"
21#include "include/core/SkScalar.h"
22#include "include/core/SkSize.h"
23#include "include/core/SkString.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050024#include "include/core/SkSurface.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040025#include "include/core/SkSurfaceProps.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050026#include "include/core/SkTextBlob.h"
27#include "include/core/SkTypeface.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040028#include "include/core/SkTypes.h"
Kevin Lubick77472bf2023-03-24 07:11:17 -040029#include "include/gpu/GpuTypes.h"
Kevin Lubick5c93acf2023-05-09 12:11:43 -040030#include "include/gpu/ganesh/SkSurfaceGanesh.h"
Kevin Lubick46572b42023-01-18 13:11:06 -050031#include "include/private/base/SkTemplates.h"
Kevin Lubick19936eb2023-01-05 09:00:37 -050032#include "include/private/base/SkTo.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050033#include "tools/ToolUtils.h"
Kevin Lubicke836c3a2023-10-20 06:55:35 -040034#include "tools/fonts/FontToolUtils.h"
jvanverth9564ce62014-09-16 05:45:19 -070035
Ben Wagner7fde8e12019-05-01 17:28:53 -040036#include <string.h>
37
Herb Derby3b3bcf02023-01-17 15:12:15 -050038using namespace skia_private;
39
jvanverthfca302c2014-10-20 13:12:54 -070040class DFTextGM : public skiagm::GM {
jvanverth9564ce62014-09-16 05:45:19 -070041public:
42 DFTextGM() {
43 this->setBGColor(0xFFFFFFFF);
jvanverth9564ce62014-09-16 05:45:19 -070044 }
45
46protected:
mtklein36352bf2015-03-25 18:17:31 -070047 void onOnceBeforeDraw() override {
Kevin Lubicke836c3a2023-10-20 06:55:35 -040048 fEmojiTypeface = ToolUtils::EmojiTypeface();
49 fEmojiText = ToolUtils::EmojiSampleText();
jvanverthfca302c2014-10-20 13:12:54 -070050 }
51
Leandro Lovisolo24fa2112023-08-15 19:05:17 +000052 SkString getName() const override { return SkString("dftext"); }
jvanverth9564ce62014-09-16 05:45:19 -070053
Leandro Lovisolo8f023882023-08-15 21:13:52 +000054 SkISize getISize() override { return SkISize::Make(1024, 768); }
jvanverth9564ce62014-09-16 05:45:19 -070055
John Stiles1cf2c8d2020-08-13 22:58:04 -040056 void onDraw(SkCanvas* inputCanvas) override {
jvanverthed14f1d2014-10-06 12:50:54 -070057 SkScalar textSizes[] = { 9.0f, 9.0f*2.0f, 9.0f*5.0f, 9.0f*2.0f*5.0f };
jvanverth9564ce62014-09-16 05:45:19 -070058 SkScalar scales[] = { 2.0f*5.0f, 5.0f, 2.0f, 1.0f };
59
60 // set up offscreen rendering with distance field text
Robert Phillips16bf7d32020-07-07 10:20:27 -040061 auto ctx = inputCanvas->recordingContext();
Leandro Lovisolo8f023882023-08-15 21:13:52 +000062 SkISize size = getISize();
brianosman52ede1d2016-06-20 08:25:02 -070063 SkImageInfo info = SkImageInfo::MakeN32(size.width(), size.height(), kPremul_SkAlphaType,
Mike Reed693fdbd2017-01-12 10:13:40 -050064 inputCanvas->imageInfo().refColorSpace());
Ben Wagnerae4bb982020-09-24 14:49:00 -040065 SkSurfaceProps inputProps;
66 inputCanvas->getProps(&inputProps);
67 SkSurfaceProps props(SkSurfaceProps::kUseDeviceIndependentFonts_Flag | inputProps.flags(),
68 inputProps.pixelGeometry());
Kevin Lubick5c93acf2023-05-09 12:11:43 -040069 auto surface(SkSurfaces::RenderTarget(ctx, skgpu::Budgeted::kNo, info, 0, &props));
reede8f30622016-03-23 18:59:25 -070070 SkCanvas* canvas = surface ? surface->getCanvas() : inputCanvas;
jvanverthf9669f42014-10-07 07:59:45 -070071 // init our new canvas with the old canvas's matrix
Mike Reed1a4140e2020-12-03 11:21:31 -050072 canvas->setMatrix(inputCanvas->getLocalToDeviceAs3x3());
jvanverth76ce81e2014-09-22 14:26:53 -070073 // apply global scale to test glyph positioning
74 canvas->scale(1.05f, 1.05f);
jvanverth9564ce62014-09-16 05:45:19 -070075 canvas->clear(0xffffffff);
76
77 SkPaint paint;
78 paint.setAntiAlias(true);
jvanverth4854d132015-06-22 06:46:56 -070079
Kevin Lubicke836c3a2023-10-20 06:55:35 -040080 SkFont font(ToolUtils::CreatePortableTypeface("serif", SkFontStyle()));
Mike Reed42e7a7e2018-12-13 16:42:53 -050081 font.setSubpixel(true);
jvanverth9564ce62014-09-16 05:45:19 -070082
83 const char* text = "Hamburgefons";
84 const size_t textLen = strlen(text);
85
86 // check scaling up
87 SkScalar x = SkIntToScalar(0);
88 SkScalar y = SkIntToScalar(78);
Herb Derbyc37b3862022-06-21 09:49:17 -040089 for (size_t i = 0; i < std::size(textSizes); ++i) {
jvanverth9564ce62014-09-16 05:45:19 -070090 SkAutoCanvasRestore acr(canvas, true);
91 canvas->translate(x, y);
92 canvas->scale(scales[i], scales[i]);
Mike Reed42e7a7e2018-12-13 16:42:53 -050093 font.setSize(textSizes[i]);
Ben Wagner51e15a62019-05-07 15:38:46 -040094 canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, 0, 0, font, paint);
Mike Reed42e7a7e2018-12-13 16:42:53 -050095 y += font.getMetrics(nullptr)*scales[i];
jvanverth9564ce62014-09-16 05:45:19 -070096 }
97
98 // check rotation
99 for (size_t i = 0; i < 5; ++i) {
100 SkScalar rotX = SkIntToScalar(10);
101 SkScalar rotY = y;
102
103 SkAutoCanvasRestore acr(canvas, true);
104 canvas->translate(SkIntToScalar(10 + i * 200), -80);
bungeman7438bfc2016-07-12 15:01:19 -0700105 canvas->rotate(SkIntToScalar(i * 5), rotX, rotY);
jvanverth9564ce62014-09-16 05:45:19 -0700106 for (int ps = 6; ps <= 32; ps += 3) {
Mike Reed42e7a7e2018-12-13 16:42:53 -0500107 font.setSize(SkIntToScalar(ps));
Ben Wagner51e15a62019-05-07 15:38:46 -0400108 canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, rotX, rotY, font, paint);
Mike Reed42e7a7e2018-12-13 16:42:53 -0500109 rotY += font.getMetrics(nullptr);
jvanverth9564ce62014-09-16 05:45:19 -0700110 }
111 }
112
113 // check scaling down
Mike Reed42e7a7e2018-12-13 16:42:53 -0500114 font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
jvanverth76ce81e2014-09-22 14:26:53 -0700115 x = SkIntToScalar(680);
jvanverth9564ce62014-09-16 05:45:19 -0700116 y = SkIntToScalar(20);
Herb Derbyc37b3862022-06-21 09:49:17 -0400117 size_t arraySize = std::size(textSizes);
jvanverth9564ce62014-09-16 05:45:19 -0700118 for (size_t i = 0; i < arraySize; ++i) {
119 SkAutoCanvasRestore acr(canvas, true);
120 canvas->translate(x, y);
121 SkScalar scaleFactor = SkScalarInvert(scales[arraySize - i - 1]);
122 canvas->scale(scaleFactor, scaleFactor);
Mike Reed42e7a7e2018-12-13 16:42:53 -0500123 font.setSize(textSizes[i]);
Ben Wagner51e15a62019-05-07 15:38:46 -0400124 canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, 0, 0, font, paint);
Mike Reed42e7a7e2018-12-13 16:42:53 -0500125 y += font.getMetrics(nullptr)*scaleFactor;
jvanverth9564ce62014-09-16 05:45:19 -0700126 }
127
jvanverth76ce81e2014-09-22 14:26:53 -0700128 // check pos text
129 {
130 SkAutoCanvasRestore acr(canvas, true);
131
132 canvas->scale(2.0f, 2.0f);
133
Herb Derby3b3bcf02023-01-17 15:12:15 -0500134 AutoTArray<SkGlyphID> glyphs(SkToInt(textLen));
Ben Wagner51e15a62019-05-07 15:38:46 -0400135 int count = font.textToGlyphs(text, textLen, SkTextEncoding::kUTF8, glyphs.get(), textLen);
Herb Derby3b3bcf02023-01-17 15:12:15 -0500136 AutoTArray<SkPoint> pos(count);
Mike Reed42e7a7e2018-12-13 16:42:53 -0500137 font.setSize(textSizes[0]);
138 font.getPos(glyphs.get(), count, pos.get(), {340, 75});
jvanverth76ce81e2014-09-22 14:26:53 -0700139
Mike Reed42e7a7e2018-12-13 16:42:53 -0500140 auto blob = SkTextBlob::MakeFromPosText(glyphs.get(), count * sizeof(SkGlyphID),
Ben Wagner51e15a62019-05-07 15:38:46 -0400141 pos.get(), font, SkTextEncoding::kGlyphID);
Mike Reed42e7a7e2018-12-13 16:42:53 -0500142 canvas->drawTextBlob(blob, 0, 0, paint);
jvanverth76ce81e2014-09-22 14:26:53 -0700143 }
144
145
jvanverth9564ce62014-09-16 05:45:19 -0700146 // check gamma-corrected blending
147 const SkColor fg[] = {
148 0xFFFFFFFF,
149 0xFFFFFF00, 0xFFFF00FF, 0xFF00FFFF,
150 0xFFFF0000, 0xFF00FF00, 0xFF0000FF,
151 0xFF000000,
152 };
153
caryclarkc3dcb672015-07-21 12:27:36 -0700154 paint.setColor(0xFFF7F3F7);
caryclarkba9757a2015-07-23 14:07:58 -0700155 SkRect r = SkRect::MakeLTRB(670, 215, 820, 397);
jvanverth9564ce62014-09-16 05:45:19 -0700156 canvas->drawRect(r, paint);
157
jvanverth76ce81e2014-09-22 14:26:53 -0700158 x = SkIntToScalar(680);
caryclarkba9757a2015-07-23 14:07:58 -0700159 y = SkIntToScalar(235);
Mike Reed42e7a7e2018-12-13 16:42:53 -0500160 font.setSize(SkIntToScalar(19));
Herb Derbyc37b3862022-06-21 09:49:17 -0400161 for (size_t i = 0; i < std::size(fg); ++i) {
jvanverth9564ce62014-09-16 05:45:19 -0700162 paint.setColor(fg[i]);
163
Ben Wagner51e15a62019-05-07 15:38:46 -0400164 canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, x, y, font, paint);
Mike Reed42e7a7e2018-12-13 16:42:53 -0500165 y += font.getMetrics(nullptr);
jvanverth9564ce62014-09-16 05:45:19 -0700166 }
167
caryclarkc3dcb672015-07-21 12:27:36 -0700168 paint.setColor(0xFF181C18);
caryclarkba9757a2015-07-23 14:07:58 -0700169 r = SkRect::MakeLTRB(820, 215, 970, 397);
jvanverth9564ce62014-09-16 05:45:19 -0700170 canvas->drawRect(r, paint);
171
jvanverth76ce81e2014-09-22 14:26:53 -0700172 x = SkIntToScalar(830);
caryclarkba9757a2015-07-23 14:07:58 -0700173 y = SkIntToScalar(235);
Mike Reed42e7a7e2018-12-13 16:42:53 -0500174 font.setSize(SkIntToScalar(19));
Herb Derbyc37b3862022-06-21 09:49:17 -0400175 for (size_t i = 0; i < std::size(fg); ++i) {
jvanverth9564ce62014-09-16 05:45:19 -0700176 paint.setColor(fg[i]);
177
Ben Wagner51e15a62019-05-07 15:38:46 -0400178 canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, x, y, font, paint);
Mike Reed42e7a7e2018-12-13 16:42:53 -0500179 y += font.getMetrics(nullptr);
jvanverth9564ce62014-09-16 05:45:19 -0700180 }
181
jvanverth354eba52015-03-16 11:32:49 -0700182 // check skew
183 {
Mike Reed42e7a7e2018-12-13 16:42:53 -0500184 font.setEdging(SkFont::Edging::kAntiAlias);
jvanverth354eba52015-03-16 11:32:49 -0700185 SkAutoCanvasRestore acr(canvas, true);
186 canvas->skew(0.0f, 0.151515f);
Mike Reed42e7a7e2018-12-13 16:42:53 -0500187 font.setSize(SkIntToScalar(32));
Ben Wagner51e15a62019-05-07 15:38:46 -0400188 canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, 745, 70, font, paint);
jvanverth354eba52015-03-16 11:32:49 -0700189 }
190 {
Mike Reed42e7a7e2018-12-13 16:42:53 -0500191 font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
jvanverth354eba52015-03-16 11:32:49 -0700192 SkAutoCanvasRestore acr(canvas, true);
193 canvas->skew(0.5f, 0.0f);
Mike Reed42e7a7e2018-12-13 16:42:53 -0500194 font.setSize(SkIntToScalar(32));
Ben Wagner51e15a62019-05-07 15:38:46 -0400195 canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, 580, 125, font, paint);
jvanverth354eba52015-03-16 11:32:49 -0700196 }
197
Jim Van Verth2525a372018-06-07 09:41:28 -0400198 // check perspective
199 {
Mike Reed42e7a7e2018-12-13 16:42:53 -0500200 font.setEdging(SkFont::Edging::kAntiAlias);
Jim Van Verth2525a372018-06-07 09:41:28 -0400201 SkAutoCanvasRestore acr(canvas, true);
202 SkMatrix persp;
203 persp.setAll(0.9839f, 0, 0,
204 0.2246f, 0.6829f, 0,
205 0.0002352f, -0.0003844f, 1);
206 canvas->concat(persp);
207 canvas->translate(1100, -295);
Mike Reed42e7a7e2018-12-13 16:42:53 -0500208 font.setSize(37.5f);
Ben Wagner51e15a62019-05-07 15:38:46 -0400209 canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, 0, 0, font, paint);
Jim Van Verth2525a372018-06-07 09:41:28 -0400210 }
211 {
Mike Reed42e7a7e2018-12-13 16:42:53 -0500212 font.setSubpixel(false);
213 font.setEdging(SkFont::Edging::kAlias);
Jim Van Verth2525a372018-06-07 09:41:28 -0400214 SkAutoCanvasRestore acr(canvas, true);
215 SkMatrix persp;
216 persp.setAll(0.9839f, 0, 0,
217 0.2246f, 0.6829f, 0,
218 0.0002352f, -0.0003844f, 1);
219 canvas->concat(persp);
220 canvas->translate(1075, -245);
Jim Van Verth4ba1a6f2018-06-07 19:54:17 +0000221 canvas->scale(375, 375);
Mike Reed42e7a7e2018-12-13 16:42:53 -0500222 font.setSize(0.1f);
Ben Wagner51e15a62019-05-07 15:38:46 -0400223 canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, 0, 0, font, paint);
Jim Van Verth2525a372018-06-07 09:41:28 -0400224 }
225
jvanverthfca302c2014-10-20 13:12:54 -0700226 // check color emoji
caryclarkc3dcb672015-07-21 12:27:36 -0700227 if (fEmojiTypeface) {
Mike Reed42e7a7e2018-12-13 16:42:53 -0500228 SkFont emoiFont;
229 emoiFont.setSubpixel(true);
230 emoiFont.setTypeface(fEmojiTypeface);
231 emoiFont.setSize(SkIntToScalar(19));
Jim Van Verthb384ddd2022-07-29 14:39:52 -0400232 canvas->drawSimpleText(fEmojiText, strlen(fEmojiText), SkTextEncoding::kUTF8, 670, 90,
233 emoiFont, paint);
caryclarkc3dcb672015-07-21 12:27:36 -0700234 }
Jim Van Verth2525a372018-06-07 09:41:28 -0400235
jvanverth9564ce62014-09-16 05:45:19 -0700236 // render offscreen buffer
jvanverth76ce81e2014-09-22 14:26:53 -0700237 if (surface) {
jvanverthf9669f42014-10-07 07:59:45 -0700238 SkAutoCanvasRestore acr(inputCanvas, true);
239 // since we prepended this matrix already, we blit using identity
240 inputCanvas->resetMatrix();
Mike Reed07c5f522021-01-23 12:23:23 -0500241 inputCanvas->drawImage(surface->makeImageSnapshot().get(), 0, 0);
jvanverth76ce81e2014-09-22 14:26:53 -0700242 }
jvanverth9564ce62014-09-16 05:45:19 -0700243 }
244
245private:
bungeman13b9c952016-05-12 10:09:30 -0700246 sk_sp<SkTypeface> fEmojiTypeface;
caryclarkc3dcb672015-07-21 12:27:36 -0700247 const char* fEmojiText;
jvanverthfca302c2014-10-20 13:12:54 -0700248
John Stiles7571f9e2020-09-02 22:42:33 -0400249 using INHERITED = skiagm::GM;
jvanverth9564ce62014-09-16 05:45:19 -0700250};
251
halcanary385fe4d2015-08-26 13:07:48 -0700252DEF_GM(return new DFTextGM;)