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 "SkCanvas.h"
10 #include "SkFontMgr.h"
11 #include "SkGraphics.h"
12 #include "SkTypeface.h"
13
14 #ifdef SK_BUILD_FOR_WIN
15 #include "SkTypeface_win.h"
16 #endif
17
18 // limit this just so we don't take too long to draw
19 #define MAX_FAMILIES 30
20
drawString(SkCanvas * canvas,const SkString & text,SkScalar x,SkScalar y,const SkPaint & paint)21 static 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
27 class FontMgrGM : public skiagm::GM {
28 public:
FontMgrGM(SkFontMgr * (* factory)()=NULL)29 FontMgrGM(SkFontMgr* (*factory)() = NULL) {
30 SkGraphics::SetFontCacheLimit(16 * 1024 * 1024);
31
32 fName.set("fontmgr_iter");
33 if (factory) {
34 fName.append("_factory");
35 fFM.reset(factory());
36 } else {
37 fFM.reset(SkFontMgr::RefDefault());
38 }
39 }
40
41 protected:
onShortName()42 virtual SkString onShortName() {
43 return fName;
44 }
45
onISize()46 virtual SkISize onISize() {
47 return SkISize::Make(640, 1024);
48 }
49
onDraw(SkCanvas * canvas)50 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
51 SkScalar y = 20;
52 SkPaint paint;
53 paint.setAntiAlias(true);
54 paint.setLCDRenderText(true);
55 paint.setSubpixelText(true);
56 paint.setTextSize(17);
57
58 SkFontMgr* fm = fFM;
59 int count = SkMin32(fm->countFamilies(), MAX_FAMILIES);
60
61 for (int i = 0; i < count; ++i) {
62 SkString fname;
63 fm->getFamilyName(i, &fname);
64 paint.setTypeface(NULL);
65 (void)drawString(canvas, fname, 20, y, paint);
66
67 SkScalar x = 220;
68
69 SkAutoTUnref<SkFontStyleSet> set(fm->createStyleSet(i));
70 for (int j = 0; j < set->count(); ++j) {
71 SkString sname;
72 SkFontStyle fs;
73 set->getStyle(j, &fs, &sname);
74 sname.appendf(" [%d %d %d]", fs.weight(), fs.width(), fs.isItalic());
75
76 SkSafeUnref(paint.setTypeface(set->createTypeface(j)));
77 x = drawString(canvas, sname, x, y, paint) + 20;
78 }
79 y += 24;
80 }
81 }
82
onGetFlags() const83 virtual uint32_t onGetFlags() const SK_OVERRIDE {
84 // fontdescriptors (and therefore serialization) don't yet understand
85 // these new styles, so skip tests that exercise that for now.
86
87 // If certain fonts are picked up (e.g. Microsoft Jhenghei 20MB for Regular, 12MB for Bold),
88 // the resulting pdf can be ~700MB and crashes Chrome's PDF viewer.
89
90 return kSkipPicture_Flag | kSkipPipe_Flag | kSkipPDF_Flag;
91 }
92
93 private:
94 SkAutoTUnref<SkFontMgr> fFM;
95 SkString fName;
96 typedef GM INHERITED;
97 };
98
99 class FontMgrMatchGM : public skiagm::GM {
100 SkAutoTUnref<SkFontMgr> fFM;
101
102 public:
FontMgrMatchGM()103 FontMgrMatchGM() : fFM(SkFontMgr::RefDefault()) {
104 SkGraphics::SetFontCacheLimit(16 * 1024 * 1024);
105 }
106
107 protected:
onShortName()108 virtual SkString onShortName() {
109 return SkString("fontmgr_match");
110 }
111
onISize()112 virtual SkISize onISize() {
113 return SkISize::Make(640, 1024);
114 }
115
iterateFamily(SkCanvas * canvas,const SkPaint & paint,SkFontStyleSet * fset)116 void iterateFamily(SkCanvas* canvas, const SkPaint& paint,
117 SkFontStyleSet* fset) {
118 SkPaint p(paint);
119 SkScalar y = 0;
120
121 for (int j = 0; j < fset->count(); ++j) {
122 SkString sname;
123 SkFontStyle fs;
124 fset->getStyle(j, &fs, &sname);
125
126 sname.appendf(" [%d %d]", fs.weight(), fs.width());
127
128 SkSafeUnref(p.setTypeface(fset->createTypeface(j)));
129 (void)drawString(canvas, sname, 0, y, p);
130 y += 24;
131 }
132 }
133
exploreFamily(SkCanvas * canvas,const SkPaint & paint,SkFontStyleSet * fset)134 void exploreFamily(SkCanvas* canvas, const SkPaint& paint,
135 SkFontStyleSet* fset) {
136 SkPaint p(paint);
137 SkScalar y = 0;
138
139 for (int weight = 100; weight <= 900; weight += 200) {
140 for (int width = 1; width <= 9; width += 2) {
141 SkFontStyle fs(weight, width, SkFontStyle::kUpright_Slant);
142 SkTypeface* face = fset->matchStyle(fs);
143 if (face) {
144 SkString str;
145 str.printf("request [%d %d]", fs.weight(), fs.width());
146 p.setTypeface(face)->unref();
147 (void)drawString(canvas, str, 0, y, p);
148 y += 24;
149 }
150 }
151 }
152 }
153
onDraw(SkCanvas * canvas)154 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
155 SkPaint paint;
156 paint.setAntiAlias(true);
157 paint.setLCDRenderText(true);
158 paint.setSubpixelText(true);
159 paint.setTextSize(17);
160
161 static const char* gNames[] = {
162 "Helvetica Neue", "Arial"
163 };
164
165 SkAutoTUnref<SkFontStyleSet> fset;
166 for (size_t i = 0; i < SK_ARRAY_COUNT(gNames); ++i) {
167 fset.reset(fFM->matchFamily(gNames[i]));
168 if (fset->count() > 0) {
169 break;
170 }
171 }
172 if (NULL == fset.get()) {
173 return;
174 }
175
176 canvas->translate(20, 40);
177 this->exploreFamily(canvas, paint, fset);
178 canvas->translate(150, 0);
179 this->iterateFamily(canvas, paint, fset);
180 }
181
onGetFlags() const182 virtual uint32_t onGetFlags() const SK_OVERRIDE {
183 // fontdescriptors (and therefore serialization) don't yet understand
184 // these new styles, so skip tests that exercise that for now.
185 return kSkipPicture_Flag | kSkipPipe_Flag;
186 }
187
188 private:
189 typedef GM INHERITED;
190 };
191
192 //////////////////////////////////////////////////////////////////////////////
193
194 DEF_GM( return SkNEW(FontMgrGM); )
195 DEF_GM( return SkNEW(FontMgrMatchGM); )
196
197 #ifdef SK_BUILD_FOR_WIN
198 DEF_GM( return SkNEW_ARGS(FontMgrGM, (SkFontMgr_New_DirectWrite)); )
199 #endif
200