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