blob: 18fc1d9250f69654c566528d72b3e3c8fdef6d3b [file] [log] [blame]
reed@google.comaf0fa6a2013-03-28 13:39:35 +00001/*
2 * Copyright 2013 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 "SkCanvas.h"
10#include "SkFontMgr.h"
11#include "SkGraphics.h"
12#include "SkTypeface.h"
13
bungeman@google.combfc6cc42013-08-21 15:20:43 +000014#ifdef SK_BUILD_FOR_WIN
reed@google.comd1bcfc92013-08-28 20:31:58 +000015 #include "SkTypeface_win.h"
bungeman@google.combfc6cc42013-08-21 15:20:43 +000016#endif
17
reed@google.comaf0fa6a2013-03-28 13:39:35 +000018// limit this just so we don't take too long to draw
19#define MAX_FAMILIES 30
20
21static SkScalar drawString(SkCanvas* canvas, const SkString& text, SkScalar x,
22 SkScalar y, const SkPaint& paint) {
23 canvas->drawText(text.c_str(), text.size(), x, y, paint);
24 return x + paint.measureText(text.c_str(), text.size());
25}
26
djsollen0d393a92014-08-27 07:03:13 -070027static SkScalar drawCharacter(SkCanvas* canvas, uint32_t character, SkScalar x,
28 SkScalar y, SkPaint& paint, SkFontMgr* fm,
bungemanc9232dc2014-11-10 13:29:33 -080029 const char* fontName, const char* bcp47[], int bcp47Count,
djsollen0d393a92014-08-27 07:03:13 -070030 const SkFontStyle& fontStyle) {
31 // find typeface containing the requested character and draw it
32 SkString ch;
33 ch.appendUnichar(character);
bungeman13b9c952016-05-12 10:09:30 -070034 sk_sp<SkTypeface> typeface(fm->matchFamilyStyleCharacter(fontName, fontStyle,
35 bcp47, bcp47Count, character));
36 paint.setTypeface(typeface);
djsollen0d393a92014-08-27 07:03:13 -070037 x = drawString(canvas, ch, x, y, paint) + 20;
38
halcanary96fcdcc2015-08-27 07:41:13 -070039 if (nullptr == typeface) {
djsollen0d393a92014-08-27 07:03:13 -070040 return x;
41 }
42
43 // repeat the process, but this time use the family name of the typeface
44 // from the first pass. This emulates the behavior in Blink where it
45 // it expects to get the same glyph when following this pattern.
46 SkString familyName;
47 typeface->getFamilyName(&familyName);
bungeman13b9c952016-05-12 10:09:30 -070048 paint.setTypeface(sk_sp<SkTypeface>(fm->legacyCreateTypeface(familyName.c_str(),
49 typeface->fontStyle())));
djsollen0d393a92014-08-27 07:03:13 -070050 return drawString(canvas, ch, x, y, paint) + 20;
51}
52
bungemanc9232dc2014-11-10 13:29:33 -080053static const char* zh = "zh";
54static const char* ja = "ja";
55
reed@google.comaf0fa6a2013-03-28 13:39:35 +000056class FontMgrGM : public skiagm::GM {
57public:
Ben Wagner3546ff12017-01-03 13:32:36 -050058#ifdef SK_LEGACY_FONTMGR_FACTORY
halcanary96fcdcc2015-08-27 07:41:13 -070059 FontMgrGM(SkFontMgr* fontMgr = nullptr) {
reed@google.comaf0fa6a2013-03-28 13:39:35 +000060 SkGraphics::SetFontCacheLimit(16 * 1024 * 1024);
bungeman@google.combfc6cc42013-08-21 15:20:43 +000061
62 fName.set("fontmgr_iter");
bungeman@google.com6eddc772014-03-31 19:18:07 +000063 if (fontMgr) {
bungeman@google.combfc6cc42013-08-21 15:20:43 +000064 fName.append("_factory");
bungeman@google.com6eddc772014-03-31 19:18:07 +000065 fFM.reset(fontMgr);
bungeman@google.combfc6cc42013-08-21 15:20:43 +000066 } else {
67 fFM.reset(SkFontMgr::RefDefault());
68 }
caryclark6531c362015-07-20 13:38:56 -070069 fName.append(sk_tool_utils::platform_os_name());
70 fName.append(sk_tool_utils::platform_extra_config("GDI"));
reed@google.comaf0fa6a2013-03-28 13:39:35 +000071 }
Ben Wagner3546ff12017-01-03 13:32:36 -050072#else
73 FontMgrGM(sk_sp<SkFontMgr> fontMgr = nullptr) {
74 SkGraphics::SetFontCacheLimit(16 * 1024 * 1024);
75
76 fName.set("fontmgr_iter");
77 if (fontMgr) {
78 fName.append("_factory");
79 fFM = std::move(fontMgr);
80 } else {
81 fFM = SkFontMgr::RefDefault();
82 }
83 fName.append(sk_tool_utils::platform_os_name());
84 fName.append(sk_tool_utils::platform_extra_config("GDI"));
85 }
86#endif
reed@google.comaf0fa6a2013-03-28 13:39:35 +000087
88protected:
mtklein36352bf2015-03-25 18:17:31 -070089 SkString onShortName() override {
bungeman@google.combfc6cc42013-08-21 15:20:43 +000090 return fName;
reed@google.comaf0fa6a2013-03-28 13:39:35 +000091 }
92
mtklein36352bf2015-03-25 18:17:31 -070093 SkISize onISize() override {
djsollen0d393a92014-08-27 07:03:13 -070094 return SkISize::Make(1536, 768);
reed@google.comaf0fa6a2013-03-28 13:39:35 +000095 }
96
mtklein36352bf2015-03-25 18:17:31 -070097 void onDraw(SkCanvas* canvas) override {
reed@google.comaf0fa6a2013-03-28 13:39:35 +000098 SkScalar y = 20;
99 SkPaint paint;
100 paint.setAntiAlias(true);
101 paint.setLCDRenderText(true);
102 paint.setSubpixelText(true);
103 paint.setTextSize(17);
skia.committer@gmail.com6acd09e2013-03-29 07:01:22 +0000104
Hal Canarycefc4312016-11-04 16:26:16 -0400105 SkFontMgr* fm = fFM.get();
reed@google.comaf0fa6a2013-03-28 13:39:35 +0000106 int count = SkMin32(fm->countFamilies(), MAX_FAMILIES);
107
108 for (int i = 0; i < count; ++i) {
bungemanc64239a2015-04-29 08:15:31 -0700109 SkString familyName;
110 fm->getFamilyName(i, &familyName);
halcanary96fcdcc2015-08-27 07:41:13 -0700111 paint.setTypeface(nullptr);
bungemanc64239a2015-04-29 08:15:31 -0700112 (void)drawString(canvas, familyName, 20, y, paint);
skia.committer@gmail.com6acd09e2013-03-29 07:01:22 +0000113
reed@google.comaf0fa6a2013-03-28 13:39:35 +0000114 SkScalar x = 220;
reed@google.com964988f2013-03-29 14:57:22 +0000115
Hal Canarycefc4312016-11-04 16:26:16 -0400116 sk_sp<SkFontStyleSet> set(fm->createStyleSet(i));
reed@google.comaf0fa6a2013-03-28 13:39:35 +0000117 for (int j = 0; j < set->count(); ++j) {
118 SkString sname;
119 SkFontStyle fs;
120 set->getStyle(j, &fs, &sname);
bungemanb4bb7d82016-04-27 10:21:04 -0700121 sname.appendf(" [%d %d %d]", fs.weight(), fs.width(), fs.slant());
skia.committer@gmail.com6acd09e2013-03-29 07:01:22 +0000122
bungeman13b9c952016-05-12 10:09:30 -0700123 paint.setTypeface(sk_sp<SkTypeface>(set->createTypeface(j)));
reed@google.comaf0fa6a2013-03-28 13:39:35 +0000124 x = drawString(canvas, sname, x, y, paint) + 20;
djsollen0d393a92014-08-27 07:03:13 -0700125
126 // check to see that we get different glyphs in japanese and chinese
bungemanc64239a2015-04-29 08:15:31 -0700127 x = drawCharacter(canvas, 0x5203, x, y, paint, fm, familyName.c_str(), &zh, 1, fs);
128 x = drawCharacter(canvas, 0x5203, x, y, paint, fm, familyName.c_str(), &ja, 1, fs);
djsollen0d393a92014-08-27 07:03:13 -0700129 // check that emoji characters are found
halcanary96fcdcc2015-08-27 07:41:13 -0700130 x = drawCharacter(canvas, 0x1f601, x, y, paint, fm, familyName.c_str(), nullptr,0, fs);
skia.committer@gmail.com6acd09e2013-03-29 07:01:22 +0000131 }
reed@google.comaf0fa6a2013-03-28 13:39:35 +0000132 y += 24;
133 }
134 }
135
reed@google.comaf0fa6a2013-03-28 13:39:35 +0000136private:
Hal Canarycefc4312016-11-04 16:26:16 -0400137 sk_sp<SkFontMgr> fFM;
bungeman@google.combfc6cc42013-08-21 15:20:43 +0000138 SkString fName;
reed@google.comaf0fa6a2013-03-28 13:39:35 +0000139 typedef GM INHERITED;
140};
141
reed@google.com964988f2013-03-29 14:57:22 +0000142class FontMgrMatchGM : public skiagm::GM {
Hal Canarycefc4312016-11-04 16:26:16 -0400143 sk_sp<SkFontMgr> fFM;
reed@google.com964988f2013-03-29 14:57:22 +0000144
145public:
146 FontMgrMatchGM() : fFM(SkFontMgr::RefDefault()) {
147 SkGraphics::SetFontCacheLimit(16 * 1024 * 1024);
148 }
skia.committer@gmail.comd55846d2013-03-30 07:01:27 +0000149
reed@google.com964988f2013-03-29 14:57:22 +0000150protected:
mtklein36352bf2015-03-25 18:17:31 -0700151 SkString onShortName() override {
caryclark6531c362015-07-20 13:38:56 -0700152 SkString name("fontmgr_match");
153 name.append(sk_tool_utils::platform_os_name());
154 name.append(sk_tool_utils::platform_extra_config("GDI"));
155 return name;
reed@google.com964988f2013-03-29 14:57:22 +0000156 }
skia.committer@gmail.comd55846d2013-03-30 07:01:27 +0000157
mtklein36352bf2015-03-25 18:17:31 -0700158 SkISize onISize() override {
reed@google.com964988f2013-03-29 14:57:22 +0000159 return SkISize::Make(640, 1024);
160 }
161
162 void iterateFamily(SkCanvas* canvas, const SkPaint& paint,
163 SkFontStyleSet* fset) {
164 SkPaint p(paint);
165 SkScalar y = 0;
166
167 for (int j = 0; j < fset->count(); ++j) {
168 SkString sname;
169 SkFontStyle fs;
170 fset->getStyle(j, &fs, &sname);
171
172 sname.appendf(" [%d %d]", fs.weight(), fs.width());
173
bungeman13b9c952016-05-12 10:09:30 -0700174 p.setTypeface(sk_sp<SkTypeface>(fset->createTypeface(j)));
reed@google.com964988f2013-03-29 14:57:22 +0000175 (void)drawString(canvas, sname, 0, y, p);
176 y += 24;
177 }
178 }
179
180 void exploreFamily(SkCanvas* canvas, const SkPaint& paint,
181 SkFontStyleSet* fset) {
182 SkPaint p(paint);
183 SkScalar y = 0;
184
185 for (int weight = 100; weight <= 900; weight += 200) {
186 for (int width = 1; width <= 9; width += 2) {
187 SkFontStyle fs(weight, width, SkFontStyle::kUpright_Slant);
bungeman13b9c952016-05-12 10:09:30 -0700188 sk_sp<SkTypeface> face(fset->matchStyle(fs));
reed@google.com964988f2013-03-29 14:57:22 +0000189 if (face) {
190 SkString str;
191 str.printf("request [%d %d]", fs.weight(), fs.width());
bungeman13b9c952016-05-12 10:09:30 -0700192 p.setTypeface(std::move(face));
reed@google.com964988f2013-03-29 14:57:22 +0000193 (void)drawString(canvas, str, 0, y, p);
194 y += 24;
195 }
196 }
197 }
198 }
skia.committer@gmail.comd55846d2013-03-30 07:01:27 +0000199
mtklein36352bf2015-03-25 18:17:31 -0700200 void onDraw(SkCanvas* canvas) override {
reed@google.com964988f2013-03-29 14:57:22 +0000201 SkPaint paint;
202 paint.setAntiAlias(true);
203 paint.setLCDRenderText(true);
204 paint.setSubpixelText(true);
205 paint.setTextSize(17);
206
mtkleindbfd7ab2016-09-01 11:24:54 -0700207 const char* gNames[] = {
reed@google.com964988f2013-03-29 14:57:22 +0000208 "Helvetica Neue", "Arial"
209 };
210
Hal Canarycefc4312016-11-04 16:26:16 -0400211 sk_sp<SkFontStyleSet> fset;
skia.committer@gmail.comd55846d2013-03-30 07:01:27 +0000212 for (size_t i = 0; i < SK_ARRAY_COUNT(gNames); ++i) {
bungeman@google.com9fc5c682013-11-12 15:25:29 +0000213 fset.reset(fFM->matchFamily(gNames[i]));
214 if (fset->count() > 0) {
reed@google.com964988f2013-03-29 14:57:22 +0000215 break;
216 }
217 }
halcanary96fcdcc2015-08-27 07:41:13 -0700218 if (nullptr == fset.get()) {
reed@google.com964988f2013-03-29 14:57:22 +0000219 return;
220 }
reed@google.com964988f2013-03-29 14:57:22 +0000221
222 canvas->translate(20, 40);
Hal Canarycefc4312016-11-04 16:26:16 -0400223 this->exploreFamily(canvas, paint, fset.get());
reed@google.com964988f2013-03-29 14:57:22 +0000224 canvas->translate(150, 0);
Hal Canarycefc4312016-11-04 16:26:16 -0400225 this->iterateFamily(canvas, paint, fset.get());
reed@google.com964988f2013-03-29 14:57:22 +0000226 }
skia.committer@gmail.comd55846d2013-03-30 07:01:27 +0000227
reed@google.com964988f2013-03-29 14:57:22 +0000228private:
229 typedef GM INHERITED;
230};
231
reeda0c814c2014-10-22 13:20:58 -0700232class FontMgrBoundsGM : public skiagm::GM {
233public:
reed8893e5f2014-12-15 13:27:26 -0800234 FontMgrBoundsGM(double scale, double skew)
235 : fScaleX(SkDoubleToScalar(scale))
236 , fSkewX(SkDoubleToScalar(skew))
237 {
reeda0c814c2014-10-22 13:20:58 -0700238 fName.set("fontmgr_bounds");
reed8893e5f2014-12-15 13:27:26 -0800239 if (scale != 1 || skew != 0) {
240 fName.appendf("_%g_%g", scale, skew);
241 }
caryclark6531c362015-07-20 13:38:56 -0700242 fName.append(sk_tool_utils::platform_os_name());
243 fName.append(sk_tool_utils::platform_extra_config("GDI"));
Ben Wagner3546ff12017-01-03 13:32:36 -0500244#ifdef SK_LEGACY_FONTMGR_FACTORY
reeda0c814c2014-10-22 13:20:58 -0700245 fFM.reset(SkFontMgr::RefDefault());
Ben Wagner3546ff12017-01-03 13:32:36 -0500246#else
247 fFM = SkFontMgr::RefDefault();
248#endif
reeda0c814c2014-10-22 13:20:58 -0700249 }
250
251 static void show_bounds(SkCanvas* canvas, const SkPaint& paint, SkScalar x, SkScalar y,
252 SkColor boundsColor) {
253 const char str[] = "jyHO[]{}@-_&%$";
254
reeda0c814c2014-10-22 13:20:58 -0700255 for (int i = 0; str[i]; ++i) {
256 canvas->drawText(&str[i], 1, x, y, paint);
257 }
tfarinaaa458fb2015-01-05 17:18:51 -0800258
reed8893e5f2014-12-15 13:27:26 -0800259 SkRect r = paint.getFontBounds();
reeda0c814c2014-10-22 13:20:58 -0700260 r.offset(x, y);
261 SkPaint p(paint);
262 p.setColor(boundsColor);
263 canvas->drawRect(r, p);
264 }
265
266protected:
mtklein36352bf2015-03-25 18:17:31 -0700267 SkString onShortName() override {
reeda0c814c2014-10-22 13:20:58 -0700268 return fName;
269 }
tfarinaaa458fb2015-01-05 17:18:51 -0800270
mtklein36352bf2015-03-25 18:17:31 -0700271 SkISize onISize() override {
reeda0c814c2014-10-22 13:20:58 -0700272 return SkISize::Make(1024, 850);
273 }
tfarinaaa458fb2015-01-05 17:18:51 -0800274
mtklein36352bf2015-03-25 18:17:31 -0700275 void onDraw(SkCanvas* canvas) override {
reeda0c814c2014-10-22 13:20:58 -0700276 SkPaint paint;
277 paint.setAntiAlias(true);
278 paint.setSubpixelText(true);
279 paint.setTextSize(100);
280 paint.setStyle(SkPaint::kStroke_Style);
reed8893e5f2014-12-15 13:27:26 -0800281 paint.setTextScaleX(fScaleX);
282 paint.setTextSkewX(fSkewX);
reeda0c814c2014-10-22 13:20:58 -0700283
284 const SkColor boundsColors[2] = { SK_ColorRED, SK_ColorBLUE };
halcanary9d524f22016-03-29 09:03:52 -0700285
Hal Canarycefc4312016-11-04 16:26:16 -0400286 SkFontMgr* fm = fFM.get();
reeda0c814c2014-10-22 13:20:58 -0700287 int count = SkMin32(fm->countFamilies(), 32);
288
289 int index = 0;
290 SkScalar x = 0, y = 0;
291
292 canvas->translate(80, 120);
293
294 for (int i = 0; i < count; ++i) {
Hal Canarycefc4312016-11-04 16:26:16 -0400295 sk_sp<SkFontStyleSet> set(fm->createStyleSet(i));
reeda0c814c2014-10-22 13:20:58 -0700296 for (int j = 0; j < set->count(); ++j) {
bungeman13b9c952016-05-12 10:09:30 -0700297 paint.setTypeface(sk_sp<SkTypeface>(set->createTypeface(j)));
reeda0c814c2014-10-22 13:20:58 -0700298 if (paint.getTypeface()) {
299 show_bounds(canvas, paint, x, y, boundsColors[index & 1]);
300 index += 1;
301 x += 160;
302 if (0 == (index % 6)) {
303 x = 0;
304 y += 160;
305 }
306 if (index >= 30) {
307 return;
308 }
309 }
310 }
311 }
312 }
mtklein1c402922015-01-23 11:07:07 -0800313
reeda0c814c2014-10-22 13:20:58 -0700314private:
Hal Canarycefc4312016-11-04 16:26:16 -0400315 sk_sp<SkFontMgr> fFM;
reeda0c814c2014-10-22 13:20:58 -0700316 SkString fName;
reed8893e5f2014-12-15 13:27:26 -0800317 SkScalar fScaleX, fSkewX;
reeda0c814c2014-10-22 13:20:58 -0700318 typedef GM INHERITED;
319};
320
reed@google.comaf0fa6a2013-03-28 13:39:35 +0000321//////////////////////////////////////////////////////////////////////////////
322
halcanary385fe4d2015-08-26 13:07:48 -0700323DEF_GM(return new FontMgrGM;)
324DEF_GM(return new FontMgrMatchGM;)
325DEF_GM(return new FontMgrBoundsGM(1.0, 0);)
326DEF_GM(return new FontMgrBoundsGM(0.75, 0);)
327DEF_GM(return new FontMgrBoundsGM(1.0, -0.25);)
bungeman@google.combfc6cc42013-08-21 15:20:43 +0000328
329#ifdef SK_BUILD_FOR_WIN
halcanary385fe4d2015-08-26 13:07:48 -0700330DEF_GM(return new FontMgrGM(SkFontMgr_New_DirectWrite());)
bungeman@google.combfc6cc42013-08-21 15:20:43 +0000331#endif