blob: 1975f998cdc9fa99e8ce5e5ae39b8396b2c6a073 [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);
bungemanc9232dc2014-11-10 13:29:33 -080034 SkTypeface* typeface = fm->matchFamilyStyleCharacter(fontName, fontStyle,
35 bcp47, bcp47Count, character);
djsollen0d393a92014-08-27 07:03:13 -070036 SkSafeUnref(paint.setTypeface(typeface));
37 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);
bungeman11a77c62016-04-12 13:45:06 -070048 SkTypeface* typefaceCopy = fm->legacyCreateTypeface(familyName.c_str(), typeface->fontStyle());
djsollen0d393a92014-08-27 07:03:13 -070049 SkSafeUnref(paint.setTypeface(typefaceCopy));
50 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:
halcanary96fcdcc2015-08-27 07:41:13 -070058 FontMgrGM(SkFontMgr* fontMgr = nullptr) {
reed@google.comaf0fa6a2013-03-28 13:39:35 +000059 SkGraphics::SetFontCacheLimit(16 * 1024 * 1024);
bungeman@google.combfc6cc42013-08-21 15:20:43 +000060
61 fName.set("fontmgr_iter");
bungeman@google.com6eddc772014-03-31 19:18:07 +000062 if (fontMgr) {
bungeman@google.combfc6cc42013-08-21 15:20:43 +000063 fName.append("_factory");
bungeman@google.com6eddc772014-03-31 19:18:07 +000064 fFM.reset(fontMgr);
bungeman@google.combfc6cc42013-08-21 15:20:43 +000065 } else {
66 fFM.reset(SkFontMgr::RefDefault());
67 }
caryclark6531c362015-07-20 13:38:56 -070068 fName.append(sk_tool_utils::platform_os_name());
69 fName.append(sk_tool_utils::platform_extra_config("GDI"));
reed@google.comaf0fa6a2013-03-28 13:39:35 +000070 }
71
72protected:
mtklein36352bf2015-03-25 18:17:31 -070073 SkString onShortName() override {
bungeman@google.combfc6cc42013-08-21 15:20:43 +000074 return fName;
reed@google.comaf0fa6a2013-03-28 13:39:35 +000075 }
76
mtklein36352bf2015-03-25 18:17:31 -070077 SkISize onISize() override {
djsollen0d393a92014-08-27 07:03:13 -070078 return SkISize::Make(1536, 768);
reed@google.comaf0fa6a2013-03-28 13:39:35 +000079 }
80
mtklein36352bf2015-03-25 18:17:31 -070081 void onDraw(SkCanvas* canvas) override {
reed@google.comaf0fa6a2013-03-28 13:39:35 +000082 SkScalar y = 20;
83 SkPaint paint;
84 paint.setAntiAlias(true);
85 paint.setLCDRenderText(true);
86 paint.setSubpixelText(true);
87 paint.setTextSize(17);
skia.committer@gmail.com6acd09e2013-03-29 07:01:22 +000088
bungeman@google.combfc6cc42013-08-21 15:20:43 +000089 SkFontMgr* fm = fFM;
reed@google.comaf0fa6a2013-03-28 13:39:35 +000090 int count = SkMin32(fm->countFamilies(), MAX_FAMILIES);
91
92 for (int i = 0; i < count; ++i) {
bungemanc64239a2015-04-29 08:15:31 -070093 SkString familyName;
94 fm->getFamilyName(i, &familyName);
halcanary96fcdcc2015-08-27 07:41:13 -070095 paint.setTypeface(nullptr);
bungemanc64239a2015-04-29 08:15:31 -070096 (void)drawString(canvas, familyName, 20, y, paint);
skia.committer@gmail.com6acd09e2013-03-29 07:01:22 +000097
reed@google.comaf0fa6a2013-03-28 13:39:35 +000098 SkScalar x = 220;
reed@google.com964988f2013-03-29 14:57:22 +000099
reed@google.comaf0fa6a2013-03-28 13:39:35 +0000100 SkAutoTUnref<SkFontStyleSet> set(fm->createStyleSet(i));
101 for (int j = 0; j < set->count(); ++j) {
102 SkString sname;
103 SkFontStyle fs;
104 set->getStyle(j, &fs, &sname);
bungemanb4bb7d82016-04-27 10:21:04 -0700105 sname.appendf(" [%d %d %d]", fs.weight(), fs.width(), fs.slant());
skia.committer@gmail.com6acd09e2013-03-29 07:01:22 +0000106
reed@google.comaf0fa6a2013-03-28 13:39:35 +0000107 SkSafeUnref(paint.setTypeface(set->createTypeface(j)));
108 x = drawString(canvas, sname, x, y, paint) + 20;
djsollen0d393a92014-08-27 07:03:13 -0700109
110 // check to see that we get different glyphs in japanese and chinese
bungemanc64239a2015-04-29 08:15:31 -0700111 x = drawCharacter(canvas, 0x5203, x, y, paint, fm, familyName.c_str(), &zh, 1, fs);
112 x = drawCharacter(canvas, 0x5203, x, y, paint, fm, familyName.c_str(), &ja, 1, fs);
djsollen0d393a92014-08-27 07:03:13 -0700113 // check that emoji characters are found
halcanary96fcdcc2015-08-27 07:41:13 -0700114 x = drawCharacter(canvas, 0x1f601, x, y, paint, fm, familyName.c_str(), nullptr,0, fs);
skia.committer@gmail.com6acd09e2013-03-29 07:01:22 +0000115 }
reed@google.comaf0fa6a2013-03-28 13:39:35 +0000116 y += 24;
117 }
118 }
119
reed@google.comaf0fa6a2013-03-28 13:39:35 +0000120private:
bungeman@google.combfc6cc42013-08-21 15:20:43 +0000121 SkAutoTUnref<SkFontMgr> fFM;
122 SkString fName;
reed@google.comaf0fa6a2013-03-28 13:39:35 +0000123 typedef GM INHERITED;
124};
125
reed@google.com964988f2013-03-29 14:57:22 +0000126class FontMgrMatchGM : public skiagm::GM {
127 SkAutoTUnref<SkFontMgr> fFM;
128
129public:
130 FontMgrMatchGM() : fFM(SkFontMgr::RefDefault()) {
131 SkGraphics::SetFontCacheLimit(16 * 1024 * 1024);
132 }
skia.committer@gmail.comd55846d2013-03-30 07:01:27 +0000133
reed@google.com964988f2013-03-29 14:57:22 +0000134protected:
mtklein36352bf2015-03-25 18:17:31 -0700135 SkString onShortName() override {
caryclark6531c362015-07-20 13:38:56 -0700136 SkString name("fontmgr_match");
137 name.append(sk_tool_utils::platform_os_name());
138 name.append(sk_tool_utils::platform_extra_config("GDI"));
139 return name;
reed@google.com964988f2013-03-29 14:57:22 +0000140 }
skia.committer@gmail.comd55846d2013-03-30 07:01:27 +0000141
mtklein36352bf2015-03-25 18:17:31 -0700142 SkISize onISize() override {
reed@google.com964988f2013-03-29 14:57:22 +0000143 return SkISize::Make(640, 1024);
144 }
145
146 void iterateFamily(SkCanvas* canvas, const SkPaint& paint,
147 SkFontStyleSet* fset) {
148 SkPaint p(paint);
149 SkScalar y = 0;
150
151 for (int j = 0; j < fset->count(); ++j) {
152 SkString sname;
153 SkFontStyle fs;
154 fset->getStyle(j, &fs, &sname);
155
156 sname.appendf(" [%d %d]", fs.weight(), fs.width());
157
158 SkSafeUnref(p.setTypeface(fset->createTypeface(j)));
159 (void)drawString(canvas, sname, 0, y, p);
160 y += 24;
161 }
162 }
163
164 void exploreFamily(SkCanvas* canvas, const SkPaint& paint,
165 SkFontStyleSet* fset) {
166 SkPaint p(paint);
167 SkScalar y = 0;
168
169 for (int weight = 100; weight <= 900; weight += 200) {
170 for (int width = 1; width <= 9; width += 2) {
171 SkFontStyle fs(weight, width, SkFontStyle::kUpright_Slant);
172 SkTypeface* face = fset->matchStyle(fs);
173 if (face) {
174 SkString str;
175 str.printf("request [%d %d]", fs.weight(), fs.width());
176 p.setTypeface(face)->unref();
177 (void)drawString(canvas, str, 0, y, p);
178 y += 24;
179 }
180 }
181 }
182 }
skia.committer@gmail.comd55846d2013-03-30 07:01:27 +0000183
mtklein36352bf2015-03-25 18:17:31 -0700184 void onDraw(SkCanvas* canvas) override {
reed@google.com964988f2013-03-29 14:57:22 +0000185 SkPaint paint;
186 paint.setAntiAlias(true);
187 paint.setLCDRenderText(true);
188 paint.setSubpixelText(true);
189 paint.setTextSize(17);
190
191 static const char* gNames[] = {
192 "Helvetica Neue", "Arial"
193 };
194
bungeman@google.com9fc5c682013-11-12 15:25:29 +0000195 SkAutoTUnref<SkFontStyleSet> fset;
skia.committer@gmail.comd55846d2013-03-30 07:01:27 +0000196 for (size_t i = 0; i < SK_ARRAY_COUNT(gNames); ++i) {
bungeman@google.com9fc5c682013-11-12 15:25:29 +0000197 fset.reset(fFM->matchFamily(gNames[i]));
198 if (fset->count() > 0) {
reed@google.com964988f2013-03-29 14:57:22 +0000199 break;
200 }
201 }
halcanary96fcdcc2015-08-27 07:41:13 -0700202 if (nullptr == fset.get()) {
reed@google.com964988f2013-03-29 14:57:22 +0000203 return;
204 }
reed@google.com964988f2013-03-29 14:57:22 +0000205
206 canvas->translate(20, 40);
207 this->exploreFamily(canvas, paint, fset);
208 canvas->translate(150, 0);
209 this->iterateFamily(canvas, paint, fset);
210 }
skia.committer@gmail.comd55846d2013-03-30 07:01:27 +0000211
reed@google.com964988f2013-03-29 14:57:22 +0000212private:
213 typedef GM INHERITED;
214};
215
reeda0c814c2014-10-22 13:20:58 -0700216class FontMgrBoundsGM : public skiagm::GM {
217public:
reed8893e5f2014-12-15 13:27:26 -0800218 FontMgrBoundsGM(double scale, double skew)
219 : fScaleX(SkDoubleToScalar(scale))
220 , fSkewX(SkDoubleToScalar(skew))
221 {
reeda0c814c2014-10-22 13:20:58 -0700222 fName.set("fontmgr_bounds");
reed8893e5f2014-12-15 13:27:26 -0800223 if (scale != 1 || skew != 0) {
224 fName.appendf("_%g_%g", scale, skew);
225 }
caryclark6531c362015-07-20 13:38:56 -0700226 fName.append(sk_tool_utils::platform_os_name());
227 fName.append(sk_tool_utils::platform_extra_config("GDI"));
reeda0c814c2014-10-22 13:20:58 -0700228 fFM.reset(SkFontMgr::RefDefault());
229 }
230
231 static void show_bounds(SkCanvas* canvas, const SkPaint& paint, SkScalar x, SkScalar y,
232 SkColor boundsColor) {
233 const char str[] = "jyHO[]{}@-_&%$";
234
reeda0c814c2014-10-22 13:20:58 -0700235 for (int i = 0; str[i]; ++i) {
236 canvas->drawText(&str[i], 1, x, y, paint);
237 }
tfarinaaa458fb2015-01-05 17:18:51 -0800238
reed8893e5f2014-12-15 13:27:26 -0800239 SkRect r = paint.getFontBounds();
reeda0c814c2014-10-22 13:20:58 -0700240 r.offset(x, y);
241 SkPaint p(paint);
242 p.setColor(boundsColor);
243 canvas->drawRect(r, p);
244 }
245
246protected:
mtklein36352bf2015-03-25 18:17:31 -0700247 SkString onShortName() override {
reeda0c814c2014-10-22 13:20:58 -0700248 return fName;
249 }
tfarinaaa458fb2015-01-05 17:18:51 -0800250
mtklein36352bf2015-03-25 18:17:31 -0700251 SkISize onISize() override {
reeda0c814c2014-10-22 13:20:58 -0700252 return SkISize::Make(1024, 850);
253 }
tfarinaaa458fb2015-01-05 17:18:51 -0800254
mtklein36352bf2015-03-25 18:17:31 -0700255 void onDraw(SkCanvas* canvas) override {
reeda0c814c2014-10-22 13:20:58 -0700256 SkPaint paint;
257 paint.setAntiAlias(true);
258 paint.setSubpixelText(true);
259 paint.setTextSize(100);
260 paint.setStyle(SkPaint::kStroke_Style);
reed8893e5f2014-12-15 13:27:26 -0800261 paint.setTextScaleX(fScaleX);
262 paint.setTextSkewX(fSkewX);
reeda0c814c2014-10-22 13:20:58 -0700263
264 const SkColor boundsColors[2] = { SK_ColorRED, SK_ColorBLUE };
halcanary9d524f22016-03-29 09:03:52 -0700265
reeda0c814c2014-10-22 13:20:58 -0700266 SkFontMgr* fm = fFM;
267 int count = SkMin32(fm->countFamilies(), 32);
268
269 int index = 0;
270 SkScalar x = 0, y = 0;
271
272 canvas->translate(80, 120);
273
274 for (int i = 0; i < count; ++i) {
275 SkAutoTUnref<SkFontStyleSet> set(fm->createStyleSet(i));
276 for (int j = 0; j < set->count(); ++j) {
277 SkSafeUnref(paint.setTypeface(set->createTypeface(j)));
278 if (paint.getTypeface()) {
279 show_bounds(canvas, paint, x, y, boundsColors[index & 1]);
280 index += 1;
281 x += 160;
282 if (0 == (index % 6)) {
283 x = 0;
284 y += 160;
285 }
286 if (index >= 30) {
287 return;
288 }
289 }
290 }
291 }
292 }
mtklein1c402922015-01-23 11:07:07 -0800293
reeda0c814c2014-10-22 13:20:58 -0700294private:
295 SkAutoTUnref<SkFontMgr> fFM;
296 SkString fName;
reed8893e5f2014-12-15 13:27:26 -0800297 SkScalar fScaleX, fSkewX;
reeda0c814c2014-10-22 13:20:58 -0700298 typedef GM INHERITED;
299};
300
reed@google.comaf0fa6a2013-03-28 13:39:35 +0000301//////////////////////////////////////////////////////////////////////////////
302
halcanary385fe4d2015-08-26 13:07:48 -0700303DEF_GM(return new FontMgrGM;)
304DEF_GM(return new FontMgrMatchGM;)
305DEF_GM(return new FontMgrBoundsGM(1.0, 0);)
306DEF_GM(return new FontMgrBoundsGM(0.75, 0);)
307DEF_GM(return new FontMgrBoundsGM(1.0, -0.25);)
bungeman@google.combfc6cc42013-08-21 15:20:43 +0000308
309#ifdef SK_BUILD_FOR_WIN
halcanary385fe4d2015-08-26 13:07:48 -0700310DEF_GM(return new FontMgrGM(SkFontMgr_New_DirectWrite());)
bungeman@google.combfc6cc42013-08-21 15:20:43 +0000311#endif