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 static SkScalar drawCharacter(SkCanvas* canvas, uint32_t character, SkScalar x, 28 SkScalar y, SkPaint& paint, SkFontMgr* fm, 29 const char* fontName, const char* bpc47, 30 const SkFontStyle& fontStyle) { 31 // find typeface containing the requested character and draw it 32 SkString ch; 33 ch.appendUnichar(character); 34 #ifdef SK_FM_NEW_MATCH_FAMILY_STYLE_CHARACTER 35 SkTypeface* typeface = fm->matchFamilyStyleCharacter(fontName, fontStyle, &bpc47, 1, character); 36 #else 37 SkTypeface* typeface = fm->matchFamilyStyleCharacter(fontName, fontStyle, bpc47, character); 38 #endif 39 SkSafeUnref(paint.setTypeface(typeface)); 40 x = drawString(canvas, ch, x, y, paint) + 20; 41 42 if (NULL == typeface) { 43 return x; 44 } 45 46 // repeat the process, but this time use the family name of the typeface 47 // from the first pass. This emulates the behavior in Blink where it 48 // it expects to get the same glyph when following this pattern. 49 SkString familyName; 50 typeface->getFamilyName(&familyName); 51 SkTypeface* typefaceCopy = fm->legacyCreateTypeface(familyName.c_str(), typeface->style()); 52 SkSafeUnref(paint.setTypeface(typefaceCopy)); 53 return drawString(canvas, ch, x, y, paint) + 20; 54 } 55 56 class FontMgrGM : public skiagm::GM { 57 public: 58 FontMgrGM(SkFontMgr* fontMgr = NULL) { 59 SkGraphics::SetFontCacheLimit(16 * 1024 * 1024); 60 61 fName.set("fontmgr_iter"); 62 if (fontMgr) { 63 fName.append("_factory"); 64 fFM.reset(fontMgr); 65 } else { 66 fFM.reset(SkFontMgr::RefDefault()); 67 } 68 } 69 70 protected: 71 virtual SkString onShortName() { 72 return fName; 73 } 74 75 virtual SkISize onISize() { 76 return SkISize::Make(1536, 768); 77 } 78 79 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { 80 SkScalar y = 20; 81 SkPaint paint; 82 paint.setAntiAlias(true); 83 paint.setLCDRenderText(true); 84 paint.setSubpixelText(true); 85 paint.setTextSize(17); 86 87 SkFontMgr* fm = fFM; 88 int count = SkMin32(fm->countFamilies(), MAX_FAMILIES); 89 90 for (int i = 0; i < count; ++i) { 91 SkString fname; 92 fm->getFamilyName(i, &fname); 93 paint.setTypeface(NULL); 94 (void)drawString(canvas, fname, 20, y, paint); 95 96 SkScalar x = 220; 97 98 SkAutoTUnref<SkFontStyleSet> set(fm->createStyleSet(i)); 99 for (int j = 0; j < set->count(); ++j) { 100 SkString sname; 101 SkFontStyle fs; 102 set->getStyle(j, &fs, &sname); 103 sname.appendf(" [%d %d %d]", fs.weight(), fs.width(), fs.isItalic()); 104 105 SkSafeUnref(paint.setTypeface(set->createTypeface(j))); 106 x = drawString(canvas, sname, x, y, paint) + 20; 107 108 // check to see that we get different glyphs in japanese and chinese 109 x = drawCharacter(canvas, 0x5203, x, y, paint, fm, fName.c_str(), "zh", fs); 110 x = drawCharacter(canvas, 0x5203, x, y, paint, fm, fName.c_str(), "ja", fs); 111 // check that emoji characters are found 112 x = drawCharacter(canvas, 0x1f601, x, y, paint, fm, fName.c_str(), NULL, fs); 113 } 114 y += 24; 115 } 116 } 117 118 virtual uint32_t onGetFlags() const SK_OVERRIDE { 119 // fontdescriptors (and therefore serialization) don't yet understand 120 // these new styles, so skip tests that exercise that for now. 121 122 // If certain fonts are picked up (e.g. Microsoft Jhenghei 20MB for Regular, 12MB for Bold), 123 // the resulting pdf can be ~700MB and crashes Chrome's PDF viewer. 124 125 return kSkipPicture_Flag | kSkipPipe_Flag | kSkipPDF_Flag; 126 } 127 128 private: 129 SkAutoTUnref<SkFontMgr> fFM; 130 SkString fName; 131 typedef GM INHERITED; 132 }; 133 134 class FontMgrMatchGM : public skiagm::GM { 135 SkAutoTUnref<SkFontMgr> fFM; 136 137 public: 138 FontMgrMatchGM() : fFM(SkFontMgr::RefDefault()) { 139 SkGraphics::SetFontCacheLimit(16 * 1024 * 1024); 140 } 141 142 protected: 143 virtual SkString onShortName() { 144 return SkString("fontmgr_match"); 145 } 146 147 virtual SkISize onISize() { 148 return SkISize::Make(640, 1024); 149 } 150 151 void iterateFamily(SkCanvas* canvas, const SkPaint& paint, 152 SkFontStyleSet* fset) { 153 SkPaint p(paint); 154 SkScalar y = 0; 155 156 for (int j = 0; j < fset->count(); ++j) { 157 SkString sname; 158 SkFontStyle fs; 159 fset->getStyle(j, &fs, &sname); 160 161 sname.appendf(" [%d %d]", fs.weight(), fs.width()); 162 163 SkSafeUnref(p.setTypeface(fset->createTypeface(j))); 164 (void)drawString(canvas, sname, 0, y, p); 165 y += 24; 166 } 167 } 168 169 void exploreFamily(SkCanvas* canvas, const SkPaint& paint, 170 SkFontStyleSet* fset) { 171 SkPaint p(paint); 172 SkScalar y = 0; 173 174 for (int weight = 100; weight <= 900; weight += 200) { 175 for (int width = 1; width <= 9; width += 2) { 176 SkFontStyle fs(weight, width, SkFontStyle::kUpright_Slant); 177 SkTypeface* face = fset->matchStyle(fs); 178 if (face) { 179 SkString str; 180 str.printf("request [%d %d]", fs.weight(), fs.width()); 181 p.setTypeface(face)->unref(); 182 (void)drawString(canvas, str, 0, y, p); 183 y += 24; 184 } 185 } 186 } 187 } 188 189 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { 190 SkPaint paint; 191 paint.setAntiAlias(true); 192 paint.setLCDRenderText(true); 193 paint.setSubpixelText(true); 194 paint.setTextSize(17); 195 196 static const char* gNames[] = { 197 "Helvetica Neue", "Arial" 198 }; 199 200 SkAutoTUnref<SkFontStyleSet> fset; 201 for (size_t i = 0; i < SK_ARRAY_COUNT(gNames); ++i) { 202 fset.reset(fFM->matchFamily(gNames[i])); 203 if (fset->count() > 0) { 204 break; 205 } 206 } 207 if (NULL == fset.get()) { 208 return; 209 } 210 211 canvas->translate(20, 40); 212 this->exploreFamily(canvas, paint, fset); 213 canvas->translate(150, 0); 214 this->iterateFamily(canvas, paint, fset); 215 } 216 217 virtual uint32_t onGetFlags() const SK_OVERRIDE { 218 // fontdescriptors (and therefore serialization) don't yet understand 219 // these new styles, so skip tests that exercise that for now. 220 return kSkipPicture_Flag | kSkipPipe_Flag; 221 } 222 223 private: 224 typedef GM INHERITED; 225 }; 226 227 ////////////////////////////////////////////////////////////////////////////// 228 229 DEF_GM( return SkNEW(FontMgrGM); ) 230 DEF_GM( return SkNEW(FontMgrMatchGM); ) 231 232 #ifdef SK_BUILD_FOR_WIN 233 DEF_GM( return SkNEW_ARGS(FontMgrGM, (SkFontMgr_New_DirectWrite())); ) 234 #endif 235