2 * Copyright 2013 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
9 #include "sk_tool_utils.h"
11 #include "SkFontMgr.h"
12 #include "SkGraphics.h"
13 #include "SkTypeface.h"
15 #ifdef SK_BUILD_FOR_WIN
16 #include "SkTypeface_win.h"
19 // limit this just so we don't take too long to draw
20 #define MAX_FAMILIES 30
22 static SkScalar drawString(SkCanvas* canvas, const SkString& text, SkScalar x,
23 SkScalar y, const SkPaint& paint) {
24 canvas->drawString(text, x, y, paint);
25 return x + paint.measureText(text.c_str(), text.size());
28 static SkScalar drawCharacter(SkCanvas* canvas, uint32_t character, SkScalar x,
29 SkScalar y, SkPaint& paint, SkFontMgr* fm,
30 const char* fontName, const char* bcp47[], int bcp47Count,
31 const SkFontStyle& fontStyle) {
32 // find typeface containing the requested character and draw it
34 ch.appendUnichar(character);
35 sk_sp<SkTypeface> typeface(fm->matchFamilyStyleCharacter(fontName, fontStyle,
36 bcp47, bcp47Count, character));
37 paint.setTypeface(typeface);
38 x = drawString(canvas, ch, x, y, paint) + 20;
40 if (nullptr == typeface) {
44 // repeat the process, but this time use the family name of the typeface
45 // from the first pass. This emulates the behavior in Blink where it
46 // it expects to get the same glyph when following this pattern.
48 typeface->getFamilyName(&familyName);
49 paint.setTypeface(sk_sp<SkTypeface>(fm->legacyCreateTypeface(familyName.c_str(),
50 typeface->fontStyle())));
51 return drawString(canvas, ch, x, y, paint) + 20;
54 static const char* zh = "zh";
55 static const char* ja = "ja";
57 class FontMgrGM : public skiagm::GM {
59 FontMgrGM(sk_sp<SkFontMgr> fontMgr = nullptr) {
60 SkGraphics::SetFontCacheLimit(16 * 1024 * 1024);
62 fName.set("fontmgr_iter");
64 fName.append("_factory");
65 fFM = std::move(fontMgr);
67 fFM = SkFontMgr::RefDefault();
69 fName.append(sk_tool_utils::platform_os_name());
70 fName.append(sk_tool_utils::platform_extra_config("GDI"));
74 SkString onShortName() override {
78 SkISize onISize() override {
79 return SkISize::Make(1536, 768);
82 void onDraw(SkCanvas* canvas) override {
85 paint.setAntiAlias(true);
86 paint.setLCDRenderText(true);
87 paint.setSubpixelText(true);
88 paint.setTextSize(17);
90 SkFontMgr* fm = fFM.get();
91 int count = SkMin32(fm->countFamilies(), MAX_FAMILIES);
93 for (int i = 0; i < count; ++i) {
95 fm->getFamilyName(i, &familyName);
96 paint.setTypeface(nullptr);
97 (void)drawString(canvas, familyName, 20, y, paint);
101 sk_sp<SkFontStyleSet> set(fm->createStyleSet(i));
102 for (int j = 0; j < set->count(); ++j) {
105 set->getStyle(j, &fs, &sname);
106 sname.appendf(" [%d %d %d]", fs.weight(), fs.width(), fs.slant());
108 paint.setTypeface(sk_sp<SkTypeface>(set->createTypeface(j)));
109 x = drawString(canvas, sname, x, y, paint) + 20;
111 // check to see that we get different glyphs in japanese and chinese
112 x = drawCharacter(canvas, 0x5203, x, y, paint, fm, familyName.c_str(), &zh, 1, fs);
113 x = drawCharacter(canvas, 0x5203, x, y, paint, fm, familyName.c_str(), &ja, 1, fs);
114 // check that emoji characters are found
115 x = drawCharacter(canvas, 0x1f601, x, y, paint, fm, familyName.c_str(), nullptr,0, fs);
122 sk_sp<SkFontMgr> fFM;
124 typedef GM INHERITED;
127 class FontMgrMatchGM : public skiagm::GM {
128 sk_sp<SkFontMgr> fFM;
131 FontMgrMatchGM() : fFM(SkFontMgr::RefDefault()) {
132 SkGraphics::SetFontCacheLimit(16 * 1024 * 1024);
136 SkString onShortName() override {
137 SkString name("fontmgr_match");
138 name.append(sk_tool_utils::platform_os_name());
139 name.append(sk_tool_utils::platform_extra_config("GDI"));
143 SkISize onISize() override {
144 return SkISize::Make(640, 1024);
147 void iterateFamily(SkCanvas* canvas, const SkPaint& paint,
148 SkFontStyleSet* fset) {
152 for (int j = 0; j < fset->count(); ++j) {
155 fset->getStyle(j, &fs, &sname);
157 sname.appendf(" [%d %d]", fs.weight(), fs.width());
159 p.setTypeface(sk_sp<SkTypeface>(fset->createTypeface(j)));
160 (void)drawString(canvas, sname, 0, y, p);
165 void exploreFamily(SkCanvas* canvas, const SkPaint& paint,
166 SkFontStyleSet* fset) {
170 for (int weight = 100; weight <= 900; weight += 200) {
171 for (int width = 1; width <= 9; width += 2) {
172 SkFontStyle fs(weight, width, SkFontStyle::kUpright_Slant);
173 sk_sp<SkTypeface> face(fset->matchStyle(fs));
176 str.printf("request [%d %d]", fs.weight(), fs.width());
177 p.setTypeface(std::move(face));
178 (void)drawString(canvas, str, 0, y, p);
185 void onDraw(SkCanvas* canvas) override {
187 paint.setAntiAlias(true);
188 paint.setLCDRenderText(true);
189 paint.setSubpixelText(true);
190 paint.setTextSize(17);
192 const char* gNames[] = {
193 "Helvetica Neue", "Arial"
196 sk_sp<SkFontStyleSet> fset;
197 for (size_t i = 0; i < SK_ARRAY_COUNT(gNames); ++i) {
198 fset.reset(fFM->matchFamily(gNames[i]));
199 if (fset->count() > 0) {
203 if (nullptr == fset.get()) {
207 canvas->translate(20, 40);
208 this->exploreFamily(canvas, paint, fset.get());
209 canvas->translate(150, 0);
210 this->iterateFamily(canvas, paint, fset.get());
214 typedef GM INHERITED;
217 class FontMgrBoundsGM : public skiagm::GM {
219 FontMgrBoundsGM(double scale, double skew)
220 : fScaleX(SkDoubleToScalar(scale))
221 , fSkewX(SkDoubleToScalar(skew))
223 fName.set("fontmgr_bounds");
224 if (scale != 1 || skew != 0) {
225 fName.appendf("_%g_%g", scale, skew);
227 fName.append(sk_tool_utils::platform_os_name());
228 fName.append(sk_tool_utils::platform_extra_config("GDI"));
229 fFM = SkFontMgr::RefDefault();
232 static void show_bounds(SkCanvas* canvas, const SkPaint& paint, SkScalar x, SkScalar y,
233 SkColor boundsColor) {
234 const char str[] = "jyHO[]{}@-_&%$";
236 for (int i = 0; str[i]; ++i) {
237 canvas->drawText(&str[i], 1, x, y, paint);
240 SkRect r = paint.getFontBounds();
243 p.setColor(boundsColor);
244 canvas->drawRect(r, p);
248 SkString onShortName() override {
252 SkISize onISize() override {
253 return SkISize::Make(1024, 850);
256 void onDraw(SkCanvas* canvas) override {
258 paint.setAntiAlias(true);
259 paint.setSubpixelText(true);
260 paint.setTextSize(100);
261 paint.setStyle(SkPaint::kStroke_Style);
262 paint.setTextScaleX(fScaleX);
263 paint.setTextSkewX(fSkewX);
265 const SkColor boundsColors[2] = { SK_ColorRED, SK_ColorBLUE };
267 SkFontMgr* fm = fFM.get();
268 int count = SkMin32(fm->countFamilies(), 32);
271 SkScalar x = 0, y = 0;
273 canvas->translate(80, 120);
275 for (int i = 0; i < count; ++i) {
276 sk_sp<SkFontStyleSet> set(fm->createStyleSet(i));
277 for (int j = 0; j < set->count(); ++j) {
278 paint.setTypeface(sk_sp<SkTypeface>(set->createTypeface(j)));
279 if (paint.getTypeface()) {
280 show_bounds(canvas, paint, x, y, boundsColors[index & 1]);
283 if (0 == (index % 6)) {
296 sk_sp<SkFontMgr> fFM;
298 SkScalar fScaleX, fSkewX;
299 typedef GM INHERITED;
302 //////////////////////////////////////////////////////////////////////////////
304 DEF_GM(return new FontMgrGM;)
305 DEF_GM(return new FontMgrMatchGM;)
306 DEF_GM(return new FontMgrBoundsGM(1.0, 0);)
307 DEF_GM(return new FontMgrBoundsGM(0.75, 0);)
308 DEF_GM(return new FontMgrBoundsGM(1.0, -0.25);)
310 #ifdef SK_BUILD_FOR_WIN
311 DEF_GM(return new FontMgrGM(SkFontMgr_New_DirectWrite());)