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 27static SkScalar drawCharacter(SkCanvas* canvas, uint32_t character, SkScalar x, 28 SkScalar y, SkPaint& paint, SkFontMgr* fm, 29 const char* fontName, const char* bcp47[], int bcp47Count, 30 const SkFontStyle& fontStyle) { 31 // find typeface containing the requested character and draw it 32 SkString ch; 33 ch.appendUnichar(character); 34 SkTypeface* typeface = fm->matchFamilyStyleCharacter(fontName, fontStyle, 35 bcp47, bcp47Count, character); 36 SkSafeUnref(paint.setTypeface(typeface)); 37 x = drawString(canvas, ch, x, y, paint) + 20; 38 39 if (nullptr == typeface) { 40 return x; 41 } 42 43 // repeat the process, but this time use the family name of the typeface 44 // from the first pass. This emulates the behavior in Blink where it 45 // it expects to get the same glyph when following this pattern. 46 SkString familyName; 47 typeface->getFamilyName(&familyName); 48 SkTypeface* typefaceCopy = fm->legacyCreateTypeface(familyName.c_str(), typeface->style()); 49 SkSafeUnref(paint.setTypeface(typefaceCopy)); 50 return drawString(canvas, ch, x, y, paint) + 20; 51} 52 53static const char* zh = "zh"; 54static const char* ja = "ja"; 55 56class FontMgrGM : public skiagm::GM { 57public: 58 FontMgrGM(SkFontMgr* fontMgr = nullptr) { 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 fName.append(sk_tool_utils::platform_os_name()); 69 fName.append(sk_tool_utils::platform_extra_config("GDI")); 70 } 71 72protected: 73 SkString onShortName() override { 74 return fName; 75 } 76 77 SkISize onISize() override { 78 return SkISize::Make(1536, 768); 79 } 80 81 void onDraw(SkCanvas* canvas) override { 82 SkScalar y = 20; 83 SkPaint paint; 84 paint.setAntiAlias(true); 85 paint.setLCDRenderText(true); 86 paint.setSubpixelText(true); 87 paint.setTextSize(17); 88 89 SkFontMgr* fm = fFM; 90 int count = SkMin32(fm->countFamilies(), MAX_FAMILIES); 91 92 for (int i = 0; i < count; ++i) { 93 SkString familyName; 94 fm->getFamilyName(i, &familyName); 95 paint.setTypeface(nullptr); 96 (void)drawString(canvas, familyName, 20, y, paint); 97 98 SkScalar x = 220; 99 100 SkAutoTUnref<SkFontStyleSet> set(fm->createStyleSet(i)); 101 for (int j = 0; j < set->count(); ++j) { 102 SkString sname; 103 SkFontStyle fs; 104 set->getStyle(j, &fs, &sname); 105 sname.appendf(" [%d %d %d]", fs.weight(), fs.width(), fs.isItalic()); 106 107 SkSafeUnref(paint.setTypeface(set->createTypeface(j))); 108 x = drawString(canvas, sname, x, y, paint) + 20; 109 110 // check to see that we get different glyphs in japanese and chinese 111 x = drawCharacter(canvas, 0x5203, x, y, paint, fm, familyName.c_str(), &zh, 1, fs); 112 x = drawCharacter(canvas, 0x5203, x, y, paint, fm, familyName.c_str(), &ja, 1, fs); 113 // check that emoji characters are found 114 x = drawCharacter(canvas, 0x1f601, x, y, paint, fm, familyName.c_str(), nullptr,0, fs); 115 } 116 y += 24; 117 } 118 } 119 120private: 121 SkAutoTUnref<SkFontMgr> fFM; 122 SkString fName; 123 typedef GM INHERITED; 124}; 125 126class FontMgrMatchGM : public skiagm::GM { 127 SkAutoTUnref<SkFontMgr> fFM; 128 129public: 130 FontMgrMatchGM() : fFM(SkFontMgr::RefDefault()) { 131 SkGraphics::SetFontCacheLimit(16 * 1024 * 1024); 132 } 133 134protected: 135 SkString onShortName() override { 136 SkString name("fontmgr_match"); 137 name.append(sk_tool_utils::platform_os_name()); 138 name.append(sk_tool_utils::platform_extra_config("GDI")); 139 return name; 140 } 141 142 SkISize onISize() override { 143 return SkISize::Make(640, 1024); 144 } 145 146 void iterateFamily(SkCanvas* canvas, const SkPaint& paint, 147 SkFontStyleSet* fset) { 148 SkPaint p(paint); 149 SkScalar y = 0; 150 151 for (int j = 0; j < fset->count(); ++j) { 152 SkString sname; 153 SkFontStyle fs; 154 fset->getStyle(j, &fs, &sname); 155 156 sname.appendf(" [%d %d]", fs.weight(), fs.width()); 157 158 SkSafeUnref(p.setTypeface(fset->createTypeface(j))); 159 (void)drawString(canvas, sname, 0, y, p); 160 y += 24; 161 } 162 } 163 164 void exploreFamily(SkCanvas* canvas, const SkPaint& paint, 165 SkFontStyleSet* fset) { 166 SkPaint p(paint); 167 SkScalar y = 0; 168 169 for (int weight = 100; weight <= 900; weight += 200) { 170 for (int width = 1; width <= 9; width += 2) { 171 SkFontStyle fs(weight, width, SkFontStyle::kUpright_Slant); 172 SkTypeface* face = fset->matchStyle(fs); 173 if (face) { 174 SkString str; 175 str.printf("request [%d %d]", fs.weight(), fs.width()); 176 p.setTypeface(face)->unref(); 177 (void)drawString(canvas, str, 0, y, p); 178 y += 24; 179 } 180 } 181 } 182 } 183 184 void onDraw(SkCanvas* canvas) override { 185 SkPaint paint; 186 paint.setAntiAlias(true); 187 paint.setLCDRenderText(true); 188 paint.setSubpixelText(true); 189 paint.setTextSize(17); 190 191 static const char* gNames[] = { 192 "Helvetica Neue", "Arial" 193 }; 194 195 SkAutoTUnref<SkFontStyleSet> fset; 196 for (size_t i = 0; i < SK_ARRAY_COUNT(gNames); ++i) { 197 fset.reset(fFM->matchFamily(gNames[i])); 198 if (fset->count() > 0) { 199 break; 200 } 201 } 202 if (nullptr == fset.get()) { 203 return; 204 } 205 206 canvas->translate(20, 40); 207 this->exploreFamily(canvas, paint, fset); 208 canvas->translate(150, 0); 209 this->iterateFamily(canvas, paint, fset); 210 } 211 212private: 213 typedef GM INHERITED; 214}; 215 216class FontMgrBoundsGM : public skiagm::GM { 217public: 218 FontMgrBoundsGM(double scale, double skew) 219 : fScaleX(SkDoubleToScalar(scale)) 220 , fSkewX(SkDoubleToScalar(skew)) 221 { 222 fName.set("fontmgr_bounds"); 223 if (scale != 1 || skew != 0) { 224 fName.appendf("_%g_%g", scale, skew); 225 } 226 fName.append(sk_tool_utils::platform_os_name()); 227 fName.append(sk_tool_utils::platform_extra_config("GDI")); 228 fFM.reset(SkFontMgr::RefDefault()); 229 } 230 231 static void show_bounds(SkCanvas* canvas, const SkPaint& paint, SkScalar x, SkScalar y, 232 SkColor boundsColor) { 233 const char str[] = "jyHO[]{}@-_&%$"; 234 235 for (int i = 0; str[i]; ++i) { 236 canvas->drawText(&str[i], 1, x, y, paint); 237 } 238 239 SkRect r = paint.getFontBounds(); 240 r.offset(x, y); 241 SkPaint p(paint); 242 p.setColor(boundsColor); 243 canvas->drawRect(r, p); 244 } 245 246protected: 247 SkString onShortName() override { 248 return fName; 249 } 250 251 SkISize onISize() override { 252 return SkISize::Make(1024, 850); 253 } 254 255 void onDraw(SkCanvas* canvas) override { 256 SkPaint paint; 257 paint.setAntiAlias(true); 258 paint.setSubpixelText(true); 259 paint.setTextSize(100); 260 paint.setStyle(SkPaint::kStroke_Style); 261 paint.setTextScaleX(fScaleX); 262 paint.setTextSkewX(fSkewX); 263 264 const SkColor boundsColors[2] = { SK_ColorRED, SK_ColorBLUE }; 265 266 SkFontMgr* fm = fFM; 267 int count = SkMin32(fm->countFamilies(), 32); 268 269 int index = 0; 270 SkScalar x = 0, y = 0; 271 272 canvas->translate(80, 120); 273 274 for (int i = 0; i < count; ++i) { 275 SkAutoTUnref<SkFontStyleSet> set(fm->createStyleSet(i)); 276 for (int j = 0; j < set->count(); ++j) { 277 SkSafeUnref(paint.setTypeface(set->createTypeface(j))); 278 if (paint.getTypeface()) { 279 show_bounds(canvas, paint, x, y, boundsColors[index & 1]); 280 index += 1; 281 x += 160; 282 if (0 == (index % 6)) { 283 x = 0; 284 y += 160; 285 } 286 if (index >= 30) { 287 return; 288 } 289 } 290 } 291 } 292 } 293 294private: 295 SkAutoTUnref<SkFontMgr> fFM; 296 SkString fName; 297 SkScalar fScaleX, fSkewX; 298 typedef GM INHERITED; 299}; 300 301////////////////////////////////////////////////////////////////////////////// 302 303DEF_GM(return new FontMgrGM;) 304DEF_GM(return new FontMgrMatchGM;) 305DEF_GM(return new FontMgrBoundsGM(1.0, 0);) 306DEF_GM(return new FontMgrBoundsGM(0.75, 0);) 307DEF_GM(return new FontMgrBoundsGM(1.0, -0.25);) 308 309#ifdef SK_BUILD_FOR_WIN 310DEF_GM(return new FontMgrGM(SkFontMgr_New_DirectWrite());) 311#endif 312