fontmgr.cpp revision 9fc5c68823c7e39e4769a41713ce070a7780df29
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
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
27class FontMgrGM : public skiagm::GM {
28public:
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
41protected:
42    virtual SkString onShortName() {
43        return fName;
44    }
45
46    virtual SkISize onISize() {
47        return SkISize::Make(640, 1024);
48    }
49
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
83    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
93private:
94    SkAutoTUnref<SkFontMgr> fFM;
95    SkString fName;
96    typedef GM INHERITED;
97};
98
99class FontMgrMatchGM : public skiagm::GM {
100    SkAutoTUnref<SkFontMgr> fFM;
101
102public:
103    FontMgrMatchGM() : fFM(SkFontMgr::RefDefault()) {
104        SkGraphics::SetFontCacheLimit(16 * 1024 * 1024);
105    }
106
107protected:
108    virtual SkString onShortName() {
109        return SkString("fontmgr_match");
110    }
111
112    virtual SkISize onISize() {
113        return SkISize::Make(640, 1024);
114    }
115
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
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
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
182    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
188private:
189    typedef GM INHERITED;
190};
191
192//////////////////////////////////////////////////////////////////////////////
193
194DEF_GM( return SkNEW(FontMgrGM); )
195DEF_GM( return SkNEW(FontMgrMatchGM); )
196
197#ifdef SK_BUILD_FOR_WIN
198    DEF_GM( return SkNEW_ARGS(FontMgrGM, (SkFontMgr_New_DirectWrite)); )
199#endif
200