• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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