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 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: 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: 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 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: 103 FontMgrMatchGM() : fFM(SkFontMgr::RefDefault()) { 104 SkGraphics::SetFontCacheLimit(16 * 1024 * 1024); 105 } 106 107 protected: 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 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