fontmgr.cpp 13 KB

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