add a new hsl GM
[platform/upstream/libSkiaSharp.git] / gm / fontmgr.cpp
1 /*
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 "sk_tool_utils.h"
10 #include "SkCanvas.h"
11 #include "SkFontMgr.h"
12 #include "SkGraphics.h"
13 #include "SkTypeface.h"
14
15 #ifdef SK_BUILD_FOR_WIN
16     #include "SkTypeface_win.h"
17 #endif
18
19 // limit this just so we don't take too long to draw
20 #define MAX_FAMILIES    30
21
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());
26 }
27
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
33     SkString ch;
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;
39
40     if (nullptr == typeface) {
41         return x;
42     }
43
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.
47     SkString familyName;
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;
52 }
53
54 static const char* zh = "zh";
55 static const char* ja = "ja";
56
57 class FontMgrGM : public skiagm::GM {
58 public:
59     FontMgrGM(sk_sp<SkFontMgr> fontMgr = nullptr) {
60         SkGraphics::SetFontCacheLimit(16 * 1024 * 1024);
61
62         fName.set("fontmgr_iter");
63         if (fontMgr) {
64             fName.append("_factory");
65             fFM = std::move(fontMgr);
66         } else {
67             fFM = SkFontMgr::RefDefault();
68         }
69         fName.append(sk_tool_utils::platform_os_name());
70         fName.append(sk_tool_utils::platform_extra_config("GDI"));
71     }
72
73 protected:
74     SkString onShortName() override {
75         return fName;
76     }
77
78     SkISize onISize() override {
79         return SkISize::Make(1536, 768);
80     }
81
82     void onDraw(SkCanvas* canvas) override {
83         SkScalar y = 20;
84         SkPaint paint;
85         paint.setAntiAlias(true);
86         paint.setLCDRenderText(true);
87         paint.setSubpixelText(true);
88         paint.setTextSize(17);
89
90         SkFontMgr* fm = fFM.get();
91         int count = SkMin32(fm->countFamilies(), MAX_FAMILIES);
92
93         for (int i = 0; i < count; ++i) {
94             SkString familyName;
95             fm->getFamilyName(i, &familyName);
96             paint.setTypeface(nullptr);
97             (void)drawString(canvas, familyName, 20, y, paint);
98
99             SkScalar x = 220;
100
101             sk_sp<SkFontStyleSet> set(fm->createStyleSet(i));
102             for (int j = 0; j < set->count(); ++j) {
103                 SkString sname;
104                 SkFontStyle fs;
105                 set->getStyle(j, &fs, &sname);
106                 sname.appendf(" [%d %d %d]", fs.weight(), fs.width(), fs.slant());
107
108                 paint.setTypeface(sk_sp<SkTypeface>(set->createTypeface(j)));
109                 x = drawString(canvas, sname, x, y, paint) + 20;
110
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);
116             }
117             y += 24;
118         }
119     }
120
121 private:
122     sk_sp<SkFontMgr> fFM;
123     SkString fName;
124     typedef GM INHERITED;
125 };
126
127 class FontMgrMatchGM : public skiagm::GM {
128     sk_sp<SkFontMgr> fFM;
129
130 public:
131     FontMgrMatchGM() : fFM(SkFontMgr::RefDefault()) {
132         SkGraphics::SetFontCacheLimit(16 * 1024 * 1024);
133     }
134
135 protected:
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"));
140         return name;
141     }
142
143     SkISize onISize() override {
144         return SkISize::Make(640, 1024);
145     }
146
147     void iterateFamily(SkCanvas* canvas, const SkPaint& paint,
148                        SkFontStyleSet* fset) {
149         SkPaint p(paint);
150         SkScalar y = 0;
151
152         for (int j = 0; j < fset->count(); ++j) {
153             SkString sname;
154             SkFontStyle fs;
155             fset->getStyle(j, &fs, &sname);
156
157             sname.appendf(" [%d %d]", fs.weight(), fs.width());
158
159             p.setTypeface(sk_sp<SkTypeface>(fset->createTypeface(j)));
160             (void)drawString(canvas, sname, 0, y, p);
161             y += 24;
162         }
163     }
164
165     void exploreFamily(SkCanvas* canvas, const SkPaint& paint,
166                        SkFontStyleSet* fset) {
167         SkPaint p(paint);
168         SkScalar y = 0;
169
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));
174                 if (face) {
175                     SkString str;
176                     str.printf("request [%d %d]", fs.weight(), fs.width());
177                     p.setTypeface(std::move(face));
178                     (void)drawString(canvas, str, 0, y, p);
179                     y += 24;
180                 }
181             }
182         }
183     }
184
185     void onDraw(SkCanvas* canvas) override {
186         SkPaint paint;
187         paint.setAntiAlias(true);
188         paint.setLCDRenderText(true);
189         paint.setSubpixelText(true);
190         paint.setTextSize(17);
191
192         const char* gNames[] = {
193             "Helvetica Neue", "Arial"
194         };
195
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) {
200                 break;
201             }
202         }
203         if (nullptr == fset.get()) {
204             return;
205         }
206
207         canvas->translate(20, 40);
208         this->exploreFamily(canvas, paint, fset.get());
209         canvas->translate(150, 0);
210         this->iterateFamily(canvas, paint, fset.get());
211     }
212
213 private:
214     typedef GM INHERITED;
215 };
216
217 class FontMgrBoundsGM : public skiagm::GM {
218 public:
219     FontMgrBoundsGM(double scale, double skew)
220         : fScaleX(SkDoubleToScalar(scale))
221         , fSkewX(SkDoubleToScalar(skew))
222     {
223         fName.set("fontmgr_bounds");
224         if (scale != 1 || skew != 0) {
225             fName.appendf("_%g_%g", scale, skew);
226         }
227         fName.append(sk_tool_utils::platform_os_name());
228         fName.append(sk_tool_utils::platform_extra_config("GDI"));
229         fFM = SkFontMgr::RefDefault();
230     }
231
232     static void show_bounds(SkCanvas* canvas, const SkPaint& paint, SkScalar x, SkScalar y,
233                             SkColor boundsColor) {
234         const char str[] = "jyHO[]{}@-_&%$";
235
236         for (int i = 0; str[i]; ++i) {
237             canvas->drawText(&str[i], 1, x, y, paint);
238         }
239
240         SkRect r = paint.getFontBounds();
241         r.offset(x, y);
242         SkPaint p(paint);
243         p.setColor(boundsColor);
244         canvas->drawRect(r, p);
245     }
246
247 protected:
248     SkString onShortName() override {
249         return fName;
250     }
251
252     SkISize onISize() override {
253         return SkISize::Make(1024, 850);
254     }
255
256     void onDraw(SkCanvas* canvas) override {
257         SkPaint paint;
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);
264
265         const SkColor boundsColors[2] = { SK_ColorRED, SK_ColorBLUE };
266
267         SkFontMgr* fm = fFM.get();
268         int count = SkMin32(fm->countFamilies(), 32);
269
270         int index = 0;
271         SkScalar x = 0, y = 0;
272
273         canvas->translate(80, 120);
274
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]);
281                     index += 1;
282                     x += 160;
283                     if (0 == (index % 6)) {
284                         x = 0;
285                         y += 160;
286                     }
287                     if (index >= 30) {
288                         return;
289                     }
290                 }
291             }
292         }
293     }
294
295 private:
296     sk_sp<SkFontMgr> fFM;
297     SkString fName;
298     SkScalar fScaleX, fSkewX;
299     typedef GM INHERITED;
300 };
301
302 //////////////////////////////////////////////////////////////////////////////
303
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);)
309
310 #ifdef SK_BUILD_FOR_WIN
311 DEF_GM(return new FontMgrGM(SkFontMgr_New_DirectWrite());)
312 #endif