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