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 "sk_tool_utils.h" 10 #include "SkCanvas.h" 11 #include "SkCommonFlags.h" 12 #include "SkFontMetrics.h" 13 #include "SkFontMgr.h" 14 #include "SkFontPriv.h" 15 #include "SkPath.h" 16 #include "SkGraphics.h" 17 #include "SkTypeface.h" 18 19 // limit this just so we don't take too long to draw 20 #define MAX_FAMILIES 30 21 22 static SkScalar drawString(SkCanvas* canvas, const SkString& text, SkScalar x, 23 SkScalar y, const SkFont& font) { 24 canvas->drawString(text, x, y, font, SkPaint()); 25 return x + font.measureText(text.c_str(), text.size(), kUTF8_SkTextEncoding); 26 } 27 28 static SkScalar drawCharacter(SkCanvas* canvas, uint32_t character, SkScalar x, 29 SkScalar y, const SkFont& origFont, SkFontMgr* fm, 30 const char* fontName, const char* bcp47[], int bcp47Count, 31 const SkFontStyle& fontStyle) { 32 SkFont font = origFont; 33 // find typeface containing the requested character and draw it 34 SkString ch; 35 ch.appendUnichar(character); 36 sk_sp<SkTypeface> typeface(fm->matchFamilyStyleCharacter(fontName, fontStyle, 37 bcp47, bcp47Count, character)); 38 font.setTypeface(typeface); 39 x = drawString(canvas, ch, x, y, font) + 20; 40 41 if (nullptr == typeface) { 42 return x; 43 } 44 45 // repeat the process, but this time use the family name of the typeface 46 // from the first pass. This emulates the behavior in Blink where it 47 // it expects to get the same glyph when following this pattern. 48 SkString familyName; 49 typeface->getFamilyName(&familyName); 50 font.setTypeface(fm->legacyMakeTypeface(familyName.c_str(), typeface->fontStyle())); 51 return drawString(canvas, ch, x, y, font) + 20; 52 } 53 54 static const char* zh = "zh"; 55 static const char* ja = "ja"; 56 57 class FontMgrGM : public skiagm::GM { 58 public: 59 FontMgrGM() { 60 SkGraphics::SetFontCacheLimit(16 * 1024 * 1024); 61 62 fName.set("fontmgr_iter"); 63 fFM = SkFontMgr::RefDefault(); 64 fName.append(sk_tool_utils::platform_font_manager()); 65 } 66 67 protected: 68 SkString onShortName() override { 69 return fName; 70 } 71 72 SkISize onISize() override { 73 return SkISize::Make(1536, 768); 74 } 75 76 void onDraw(SkCanvas* canvas) override { 77 SkScalar y = 20; 78 SkFont font; 79 font.setEdging(SkFont::Edging::kSubpixelAntiAlias); 80 font.setSubpixel(true); 81 font.setSize(17); 82 83 SkFontMgr* fm = fFM.get(); 84 int count = SkMin32(fm->countFamilies(), MAX_FAMILIES); 85 86 for (int i = 0; i < count; ++i) { 87 SkString familyName; 88 fm->getFamilyName(i, &familyName); 89 font.setTypeface(nullptr); 90 (void)drawString(canvas, familyName, 20, y, font); 91 92 SkScalar x = 220; 93 94 sk_sp<SkFontStyleSet> set(fm->createStyleSet(i)); 95 for (int j = 0; j < set->count(); ++j) { 96 SkString sname; 97 SkFontStyle fs; 98 set->getStyle(j, &fs, &sname); 99 sname.appendf(" [%d %d %d]", fs.weight(), fs.width(), fs.slant()); 100 101 font.setTypeface(sk_sp<SkTypeface>(set->createTypeface(j))); 102 x = drawString(canvas, sname, x, y, font) + 20; 103 104 // check to see that we get different glyphs in japanese and chinese 105 x = drawCharacter(canvas, 0x5203, x, y, font, fm, familyName.c_str(), &zh, 1, fs); 106 x = drawCharacter(canvas, 0x5203, x, y, font, fm, familyName.c_str(), &ja, 1, fs); 107 // check that emoji characters are found 108 x = drawCharacter(canvas, 0x1f601, x, y, font, fm, familyName.c_str(), nullptr,0, fs); 109 } 110 y += 24; 111 } 112 } 113 114 private: 115 sk_sp<SkFontMgr> fFM; 116 SkString fName; 117 typedef GM INHERITED; 118 }; 119 120 class FontMgrMatchGM : public skiagm::GM { 121 sk_sp<SkFontMgr> fFM; 122 123 public: 124 FontMgrMatchGM() : fFM(SkFontMgr::RefDefault()) { 125 SkGraphics::SetFontCacheLimit(16 * 1024 * 1024); 126 } 127 128 protected: 129 SkString onShortName() override { 130 SkString name("fontmgr_match"); 131 name.append(sk_tool_utils::platform_font_manager()); 132 return name; 133 } 134 135 SkISize onISize() override { 136 return SkISize::Make(640, 1024); 137 } 138 139 void iterateFamily(SkCanvas* canvas, const SkFont& font, SkFontStyleSet* fset) { 140 SkFont f(font); 141 SkScalar y = 0; 142 143 for (int j = 0; j < fset->count(); ++j) { 144 SkString sname; 145 SkFontStyle fs; 146 fset->getStyle(j, &fs, &sname); 147 148 sname.appendf(" [%d %d]", fs.weight(), fs.width()); 149 150 f.setTypeface(sk_sp<SkTypeface>(fset->createTypeface(j))); 151 (void)drawString(canvas, sname, 0, y, f); 152 y += 24; 153 } 154 } 155 156 void exploreFamily(SkCanvas* canvas, const SkFont& font, SkFontStyleSet* fset) { 157 SkFont f(font); 158 SkScalar y = 0; 159 160 for (int weight = 100; weight <= 900; weight += 200) { 161 for (int width = 1; width <= 9; width += 2) { 162 SkFontStyle fs(weight, width, SkFontStyle::kUpright_Slant); 163 sk_sp<SkTypeface> face(fset->matchStyle(fs)); 164 if (face) { 165 SkString str; 166 str.printf("request [%d %d]", fs.weight(), fs.width()); 167 f.setTypeface(std::move(face)); 168 (void)drawString(canvas, str, 0, y, f); 169 y += 24; 170 } 171 } 172 } 173 } 174 175 void onDraw(SkCanvas* canvas) override { 176 SkFont font; 177 font.setEdging(SkFont::Edging::kSubpixelAntiAlias); 178 font.setSubpixel(true); 179 font.setSize(17); 180 181 const char* gNames[] = { 182 "Helvetica Neue", "Arial", "sans" 183 }; 184 185 sk_sp<SkFontStyleSet> fset; 186 for (size_t i = 0; i < SK_ARRAY_COUNT(gNames); ++i) { 187 fset.reset(fFM->matchFamily(gNames[i])); 188 if (fset->count() > 0) { 189 break; 190 } 191 } 192 if (nullptr == fset.get()) { 193 return; 194 } 195 196 canvas->translate(20, 40); 197 this->exploreFamily(canvas, font, fset.get()); 198 canvas->translate(150, 0); 199 this->iterateFamily(canvas, font, fset.get()); 200 } 201 202 private: 203 typedef GM INHERITED; 204 }; 205 206 class FontMgrBoundsGM : public skiagm::GM { 207 public: 208 FontMgrBoundsGM(double scale, double skew) 209 : fScaleX(SkDoubleToScalar(scale)) 210 , fSkewX(SkDoubleToScalar(skew)) 211 { 212 fName.set("fontmgr_bounds"); 213 if (scale != 1 || skew != 0) { 214 fName.appendf("_%g_%g", scale, skew); 215 } 216 fName.append(sk_tool_utils::platform_font_manager()); 217 fFM = SkFontMgr::RefDefault(); 218 } 219 220 static void show_bounds(SkCanvas* canvas, const SkFont& font, SkScalar x, SkScalar y, 221 SkColor boundsColor) 222 { 223 SkRect fontBounds = SkFontPriv::GetFontBounds(font).makeOffset(x, y); 224 225 SkPaint boundsPaint; 226 boundsPaint.setAntiAlias(true); 227 boundsPaint.setColor(boundsColor); 228 boundsPaint.setStyle(SkPaint::kStroke_Style); 229 canvas->drawRect(fontBounds, boundsPaint); 230 231 SkFontMetrics fm; 232 font.getMetrics(&fm); 233 SkPaint metricsPaint(boundsPaint); 234 metricsPaint.setStyle(SkPaint::kFill_Style); 235 metricsPaint.setAlpha(0x40); 236 if ((fm.fFlags & SkFontMetrics::kUnderlinePositionIsValid_Flag) && 237 (fm.fFlags & SkFontMetrics::kUnderlinePositionIsValid_Flag)) 238 { 239 SkRect underline{ fontBounds.fLeft, fm.fUnderlinePosition+y, 240 fontBounds.fRight, fm.fUnderlinePosition+y + fm.fUnderlineThickness }; 241 canvas->drawRect(underline, metricsPaint); 242 } 243 244 if ((fm.fFlags & SkFontMetrics::kStrikeoutPositionIsValid_Flag) && 245 (fm.fFlags & SkFontMetrics::kStrikeoutPositionIsValid_Flag)) 246 { 247 SkRect strikeout{ fontBounds.fLeft, fm.fStrikeoutPosition+y - fm.fStrikeoutThickness, 248 fontBounds.fRight, fm.fStrikeoutPosition+y }; 249 canvas->drawRect(strikeout, metricsPaint); 250 } 251 252 SkGlyphID left = 0, right = 0, top = 0, bottom = 0; 253 { 254 int numGlyphs = font.getTypefaceOrDefault()->countGlyphs(); 255 SkRect min = {0, 0, 0, 0}; 256 for (int i = 0; i < numGlyphs; ++i) { 257 SkGlyphID glyphId = i; 258 SkRect cur; 259 font.getBounds(&glyphId, 1, &cur, nullptr); 260 if (cur.fLeft < min.fLeft ) { min.fLeft = cur.fLeft; left = i; } 261 if (cur.fTop < min.fTop ) { min.fTop = cur.fTop ; top = i; } 262 if (min.fRight < cur.fRight ) { min.fRight = cur.fRight; right = i; } 263 if (min.fBottom < cur.fBottom) { min.fBottom = cur.fBottom; bottom = i; } 264 } 265 } 266 SkGlyphID str[] = { left, right, top, bottom }; 267 SkPoint location[] = { 268 {fontBounds.left(), fontBounds.centerY()}, 269 {fontBounds.right(), fontBounds.centerY()}, 270 {fontBounds.centerX(), fontBounds.top()}, 271 {fontBounds.centerX(), fontBounds.bottom()} 272 }; 273 274 SkFont labelFont; 275 labelFont.setEdging(SkFont::Edging::kAntiAlias); 276 labelFont.setTypeface(sk_tool_utils::create_portable_typeface()); 277 278 if (FLAGS_veryVerbose) { 279 SkString name; 280 font.getTypefaceOrDefault()->getFamilyName(&name); 281 canvas->drawString(name, fontBounds.fLeft, fontBounds.fBottom, labelFont, SkPaint()); 282 } 283 for (size_t i = 0; i < SK_ARRAY_COUNT(str); ++i) { 284 SkPath path; 285 font.getPath(str[i], &path); 286 path.offset(x, y); 287 SkPaint::Style style = path.isEmpty() ? SkPaint::kFill_Style : SkPaint::kStroke_Style; 288 SkPaint glyphPaint; 289 glyphPaint.setStyle(style); 290 canvas->drawSimpleText(&str[i], sizeof(str[0]), kGlyphID_SkTextEncoding, x, y, font, glyphPaint); 291 292 if (FLAGS_veryVerbose) { 293 SkString glyphStr; 294 glyphStr.appendS32(str[i]); 295 canvas->drawString(glyphStr, location[i].fX, location[i].fY, labelFont, SkPaint()); 296 } 297 298 } 299 300 } 301 302 protected: 303 SkString onShortName() override { 304 return fName; 305 } 306 307 SkISize onISize() override { 308 return SkISize::Make(1024, 850); 309 } 310 311 void onDraw(SkCanvas* canvas) override { 312 SkFont font; 313 font.setEdging(SkFont::Edging::kAntiAlias); 314 font.setSubpixel(true); 315 font.setSize(100); 316 font.setScaleX(fScaleX); 317 font.setSkewX(fSkewX); 318 319 const SkColor boundsColors[2] = { SK_ColorRED, SK_ColorBLUE }; 320 321 SkFontMgr* fm = fFM.get(); 322 int count = SkMin32(fm->countFamilies(), 32); 323 324 int index = 0; 325 SkScalar x = 0, y = 0; 326 327 canvas->translate(10, 120); 328 329 for (int i = 0; i < count; ++i) { 330 sk_sp<SkFontStyleSet> set(fm->createStyleSet(i)); 331 for (int j = 0; j < set->count() && j < 3; ++j) { 332 font.setTypeface(sk_sp<SkTypeface>(set->createTypeface(j))); 333 // Fonts with lots of glyphs are interesting, but can take a long time to find 334 // the glyphs which make up the maximum extent. 335 if (font.getTypefaceOrDefault() && font.getTypefaceOrDefault()->countGlyphs() < 1000) { 336 SkRect fontBounds = SkFontPriv::GetFontBounds(font); 337 x -= fontBounds.fLeft; 338 show_bounds(canvas, font, x, y, boundsColors[index & 1]); 339 x += fontBounds.fRight + 20; 340 index += 1; 341 if (x > 900) { 342 x = 0; 343 y += 160; 344 } 345 if (y >= 700) { 346 return; 347 } 348 } 349 } 350 } 351 } 352 353 private: 354 sk_sp<SkFontMgr> fFM; 355 SkString fName; 356 SkScalar fScaleX, fSkewX; 357 typedef GM INHERITED; 358 }; 359 360 ////////////////////////////////////////////////////////////////////////////// 361 362 DEF_GM(return new FontMgrGM;) 363 DEF_GM(return new FontMgrMatchGM;) 364 DEF_GM(return new FontMgrBoundsGM(1.0, 0);) 365 DEF_GM(return new FontMgrBoundsGM(0.75, 0);) 366 DEF_GM(return new FontMgrBoundsGM(1.0, -0.25);) 367