Flutter Engine
The Flutter Engine
Classes | Functions | Variables
typeface.cpp File Reference
#include "gm/gm.h"
#include "include/core/SkBlurTypes.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkFont.h"
#include "include/core/SkFontStyle.h"
#include "include/core/SkFontTypes.h"
#include "include/core/SkMaskFilter.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTextBlob.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "include/private/base/SkTemplates.h"
#include "src/core/SkFontPriv.h"
#include "tools/Resources.h"
#include "tools/fonts/FontToolUtils.h"
#include <string.h>
#include <utility>

Go to the source code of this file.

Classes

class  TypefaceStylesGM
 

Functions

static void getGlyphPositions (const SkFont &font, const uint16_t glyphs[], int count, SkScalar x, SkScalar y, SkPoint pos[])
 
static void applyKerning (SkPoint pos[], const int32_t adjustments[], int count, const SkFont &font)
 
static void drawKernText (SkCanvas *canvas, const void *text, size_t len, SkScalar x, SkScalar y, const SkFont &font, const SkPaint &paint)
 
static void draw_typeface_rendering_gm (SkCanvas *canvas, sk_sp< SkTypeface > face, SkGlyphID glyph)
 
 DEF_SIMPLE_GM_CAN_FAIL (typefacerendering, canvas, errMsg, 640, 840)
 
 DEF_SIMPLE_GM_CAN_FAIL (typefacerendering_pfa, canvas, errMsg, 640, 840)
 
 DEF_SIMPLE_GM_CAN_FAIL (typefacerendering_pfb, canvas, errMsg, 640, 840)
 
 DEF_SIMPLE_GM (typeface_styling, canvas, 710, 360)
 

Variables

static constexpr SkFontStyle gStyles []
 
constexpr int gStylesCount = std::size(gStyles)
 

Function Documentation

◆ applyKerning()

static void applyKerning ( SkPoint  pos[],
const int32_t  adjustments[],
int  count,
const SkFont font 
)
static

Definition at line 46 of file typeface.cpp.

47 {
48 SkScalar scale = font.getSize() / font.getTypeface()->getUnitsPerEm();
49
50 SkScalar globalAdj = 0;
51 for (int i = 0; i < count - 1; ++i) {
52 globalAdj += adjustments[i] * scale;
53 pos[i + 1].fX += globalAdj;
54 }
55}
int count
Definition: FontMgrTest.cpp:50
SkPoint pos
float SkScalar
Definition: extension.cpp:12
font
Font Metadata and Metrics.
const Scalar scale
float fX
x-axis value
Definition: SkPoint_impl.h:164

◆ DEF_SIMPLE_GM()

DEF_SIMPLE_GM ( typeface_styling  ,
canvas  ,
710  ,
360   
)

Definition at line 406 of file typeface.cpp.

406 {
407 sk_sp<SkTypeface> face = ToolUtils::CreateTypefaceFromResource("fonts/Roboto-Regular.ttf");
408 if (!face) {
410 }
411 SkFont font(face, 100);
413
414 uint16_t glyphs[1] = { font.unicharToGlyph('A') };
415 SkPoint pos[1] = { {0, 0} };
416
417 auto draw = [&](SkPaint::Style style, float width) {
418 // Draws 3 rows:
419 // 1. normal
420 // 2. emboldened
421 // 3. normal(white) on top of emboldened (to show the delta)
422
424 paint.setStyle(style);
425 paint.setStrokeWidth(width);
426
427 font.setEmbolden(true);
428 canvas->drawGlyphs(1, glyphs, pos, {20, 120*2}, font, paint);
429 canvas->drawGlyphs(1, glyphs, pos, {20, 120*3}, font, paint);
430
431 font.setEmbolden(false);
432 canvas->drawGlyphs(1, glyphs, pos, {20, 120*1}, font, paint);
433 paint.setColor(SK_ColorYELLOW);
434 canvas->drawGlyphs(1, glyphs, pos, {20, 120*3}, font, paint);
435 };
436
437 const struct {
438 SkPaint::Style style;
439 float width;
440 } recs[] = {
446 };
447
448 canvas->translate(0, -20);
449 for (auto r : recs) {
450 draw(r.style, r.width);
451 canvas->translate(100, 0);
452 }
453}
uint16_t glyphs[5]
Definition: FontMgrTest.cpp:46
constexpr SkColor SK_ColorYELLOW
Definition: SkColor.h:139
static void draw(SkCanvas *canvas, SkRect &target, int x, int y)
Definition: aaclip.cpp:27
Definition: SkFont.h:35
@ kAntiAlias
may have transparent pixels on glyph edges
@ kStroke_Style
set to stroke geometry
Definition: SkPaint.h:194
@ kFill_Style
set to fill geometry
Definition: SkPaint.h:193
@ kStrokeAndFill_Style
sets to stroke and fill geometry
Definition: SkPaint.h:195
const Paint & paint
Definition: color_source.cc:38
sk_sp< SkTypeface > DefaultPortableTypeface()
sk_sp< SkTypeface > CreateTypefaceFromResource(const char *resource, int ttcIndex)
int32_t width

◆ DEF_SIMPLE_GM_CAN_FAIL() [1/3]

DEF_SIMPLE_GM_CAN_FAIL ( typefacerendering  ,
canvas  ,
errMsg  ,
640  ,
840   
)

Definition at line 368 of file typeface.cpp.

368 {
369 sk_sp<SkTypeface> face = ToolUtils::CreateTypefaceFromResource("fonts/hintgasp.ttf");
370 if (!face) {
372 }
373 draw_typeface_rendering_gm(canvas, face, face->unicharToGlyph('A'));
374
375 // Should draw nothing and not do anything undefined.
376 draw_typeface_rendering_gm(canvas, face, 0xFFFF);
378}
SkGlyphID unicharToGlyph(SkUnichar unichar) const
Definition: SkTypeface.cpp:363
static void draw_typeface_rendering_gm(SkCanvas *canvas, sk_sp< SkTypeface > face, SkGlyphID glyph)
Definition: typeface.cpp:163

◆ DEF_SIMPLE_GM_CAN_FAIL() [2/3]

DEF_SIMPLE_GM_CAN_FAIL ( typefacerendering_pfa  ,
canvas  ,
errMsg  ,
640  ,
840   
)

Definition at line 383 of file typeface.cpp.

383 {
384 sk_sp<SkTypeface> face = ToolUtils::CreateTypefaceFromResource("fonts/Roboto2-Regular.pfa");
385 if (!face) {
387 }
388 draw_typeface_rendering_gm(canvas, face, face->unicharToGlyph('O'));
390}

◆ DEF_SIMPLE_GM_CAN_FAIL() [3/3]

DEF_SIMPLE_GM_CAN_FAIL ( typefacerendering_pfb  ,
canvas  ,
errMsg  ,
640  ,
840   
)

Definition at line 392 of file typeface.cpp.

392 {
393 sk_sp<SkTypeface> face = ToolUtils::CreateTypefaceFromResource("fonts/Roboto2-Regular.pfb");
394 if (!face) {
396 }
397 draw_typeface_rendering_gm(canvas, face, face->unicharToGlyph('O'));
399}

◆ draw_typeface_rendering_gm()

static void draw_typeface_rendering_gm ( SkCanvas canvas,
sk_sp< SkTypeface face,
SkGlyphID  glyph 
)
static

Definition at line 163 of file typeface.cpp.

163 {
164 struct AliasType {
165 SkFont::Edging edging;
166 bool inLayer;
167 } constexpr aliasTypes[] {
168#ifndef SK_BUILD_FOR_IOS
169 // This gm crashes on iOS when drawing an embedded bitmap when requesting aliased rendering.
170 // The crash looks like
171 // libTrueTypeScaler.dylib`<redacted> + 80
172 // stop reason = EXC_BAD_ACCESS (code=EXC_ARM_DA_ALIGN, address=...)
173 // -> 0x330b19d0 <+80>: strd r2, r3, [r5, #36]
174 // 0x330b19d4 <+84>: movs r3, #0x0
175 // 0x330b19d6 <+86>: add r2, sp, #0x28
176 // 0x330b19d8 <+88>: ldr r0, [r4, #0x4]
177 // Disable testing embedded bitmaps on iOS for now.
178 // See https://bug.skia.org/5530 .
179 { SkFont::Edging::kAlias , false },
180#endif
181 { SkFont::Edging::kAntiAlias , false },
185 };
186
187 // The hintgasp.ttf is designed for the following sizes to be different.
188 // GASP_DOGRAY 0x0002 0<=ppem<=10
189 // GASP_SYMMETRIC_SMOOTHING 0x0008 0<=ppem<=10
190 // GASP_GRIDFIT 0x0001 11<=ppem<=12
191 // GASP_SYMMETRIC_GRIDFIT 0x0004 11<=ppem<=12
192 // GASP_DOGRAY|GASP_GRIDFIT 0x0003 13<=ppem<=14
193 // GASP_SYMMETRIC_SMOOTHING|GASP_SYMMETRIC_GRIDFIT 0x000C 13<=ppem<=14
194 // (neither) 0x0000 15<=ppem
195 // Odd sizes have embedded bitmaps.
196 constexpr SkScalar textSizes[] = { 9, 10, 11, 12, 13, 14, 15, 16 };
197
198 constexpr SkFontHinting hintingTypes[] = {
203 };
204
205 struct SubpixelType {
206 bool requested;
208 } constexpr subpixelTypes[] = {
209 { false, { 0.00, 0.00 } },
210 { true , { 0.00, 0.00 } },
211 { true , { 0.25, 0.00 } },
212 { true , { 0.25, 0.25 } },
213 };
214
215 constexpr bool rotateABitTypes[] = { false, true };
216
217 SkScalar y = 0; // The baseline of the previous output
218 {
220
221 SkFont font(face);
222 font.setEmbeddedBitmaps(true);
223
224 SkScalar x = 0;
225 SkScalar xMax = x;
226 SkScalar xBase = 0;
227 for (const SubpixelType subpixel : subpixelTypes) {
228 y = 0;
229 font.setSubpixel(subpixel.requested);
230
231 for (const AliasType& alias : aliasTypes) {
232 font.setEdging(alias.edging);
233 SkAutoCanvasRestore acr1(canvas, false);
234 if (alias.inLayer) {
235 canvas->saveLayer(nullptr, &paint);
236 }
237
238 for (const SkScalar& textSize : textSizes) {
239 x = xBase + 5;
240 font.setSize(textSize);
241
242 SkScalar dy = SkScalarCeilToScalar(font.getMetrics(nullptr));
243 y += dy;
244 for (const SkFontHinting& hinting : hintingTypes) {
245 font.setHinting(hinting);
246
247 for (const bool& rotateABit : rotateABitTypes) {
248 SkAutoCanvasRestore acr2(canvas, true);
249 if (rotateABit) {
250 canvas->rotate(2, x + subpixel.offset.x(),
251 y + subpixel.offset.y());
252 }
253 canvas->drawSimpleText(&glyph, sizeof(glyph), SkTextEncoding::kGlyphID,
254 x + subpixel.offset.x(),
255 y + subpixel.offset.y(), font, paint);
256
257 SkScalar dx = SkScalarCeilToScalar(font.measureText(
258 &glyph, sizeof(glyph), SkTextEncoding::kGlyphID)) + 5;
259 x += dx;
260 xMax = std::max(x, xMax);
261 }
262 }
263 }
264 y += 10;
265 }
266 xBase = xMax;
267 }
268 }
269
270 constexpr struct StyleTests {
271 SkPaint::Style style;
273 } styleTypes[] = {
274 { SkPaint::kFill_Style, 0.0f},
275 { SkPaint::kStroke_Style, 0.0f},
276 { SkPaint::kStroke_Style, 0.5f},
278 };
279
280 constexpr bool fakeBoldTypes[] = { false, true };
281
282 {
284
285 SkFont font(face, 16);
286
287 SkScalar x = 0;
288 for (const bool& fakeBold : fakeBoldTypes) {
289 SkScalar dy = SkScalarCeilToScalar(font.getMetrics(nullptr));
290 y += dy;
291 x = 5;
292
293 font.setEmbolden(fakeBold);
294 for (const AliasType& alias : aliasTypes) {
295 font.setEdging(alias.edging);
296 SkAutoCanvasRestore acr(canvas, false);
297 if (alias.inLayer) {
298 canvas->saveLayer(nullptr, &paint);
299 }
300 for (const StyleTests& style : styleTypes) {
301 paint.setStyle(style.style);
302 paint.setStrokeWidth(style.strokeWidth);
303 canvas->drawSimpleText(&glyph, sizeof(glyph), SkTextEncoding::kGlyphID,
304 x, y, font, paint);
305
306 SkScalar dx = SkScalarCeilToScalar(font.measureText(
307 &glyph, sizeof(glyph), SkTextEncoding::kGlyphID)) + 5;
308 x += dx;
309 }
310 }
311 y += 10;
312 }
313 }
314
315 constexpr struct MaskTests {
316 SkBlurStyle style;
317 SkScalar sigma;
318 } maskTypes[] = {
323
328
333 };
334
335 {
337
338 SkFont font(face, 16);
339
340 SkScalar x = 0;
341 {
342 for (const AliasType& alias : aliasTypes) {
343 SkScalar dy = SkScalarCeilToScalar(font.getMetrics(nullptr));
344 y += dy;
345 x = 5;
346
347 font.setEdging(alias.edging);
348 SkAutoCanvasRestore acr(canvas, false);
349 if (alias.inLayer) {
350 canvas->saveLayer(nullptr, &paint);
351 }
352 for (const MaskTests& mask : maskTypes) {
353 paint.setMaskFilter(SkMaskFilter::MakeBlur(mask.style, mask.sigma));
354 canvas->drawSimpleText(&glyph, sizeof(glyph), SkTextEncoding::kGlyphID,
355 x, y, font, paint);
356
357 SkScalar dx = SkScalarCeilToScalar(font.measureText(
358 &glyph, sizeof(glyph), SkTextEncoding::kGlyphID)) + 5;
359 x += dx;
360 }
361 paint.setMaskFilter(nullptr);
362 }
363 y += 10;
364 }
365 }
366}
static const int strokeWidth
Definition: BlurTest.cpp:60
SkBlurStyle
Definition: SkBlurTypes.h:11
@ kOuter_SkBlurStyle
nothing inside, fuzzy outside
Definition: SkBlurTypes.h:14
@ kSolid_SkBlurStyle
solid inside, fuzzy outside
Definition: SkBlurTypes.h:13
@ kInner_SkBlurStyle
fuzzy inside, nothing outside
Definition: SkBlurTypes.h:15
@ kNormal_SkBlurStyle
fuzzy inside and outside
Definition: SkBlurTypes.h:12
SkFontHinting
Definition: SkFontTypes.h:18
@ kNormal
glyph outlines modified to improve constrast
@ kNone
glyph outlines unchanged
@ kSlight
minimal modification to improve constrast
@ kFull
modifies glyph outlines for maximum constrast
@ kGlyphID
uses two byte words to represent glyph indices
#define SkScalarCeilToScalar(x)
Definition: SkScalar.h:31
int saveLayer(const SkRect *bounds, const SkPaint *paint)
Definition: SkCanvas.cpp:496
void drawSimpleText(const void *text, size_t byteLength, SkTextEncoding encoding, SkScalar x, SkScalar y, const SkFont &font, const SkPaint &paint)
Definition: SkCanvas.cpp:2413
void rotate(SkScalar degrees)
Definition: SkCanvas.cpp:1300
Edging
Definition: SkFont.h:39
@ kAlias
no transparent pixels on glyph edges
@ kSubpixelAntiAlias
glyph positioned in pixel using transparency
static sk_sp< SkMaskFilter > MakeBlur(SkBlurStyle style, SkScalar sigma, bool respectCTM=true)
static float max(float r, float g, float b)
Definition: hsl.cpp:49
double y
double x
skia_private::AutoTArray< sk_sp< SkImageFilter > > filters TypedMatrix matrix TypedMatrix matrix SkScalar dx
Definition: SkRecords.h:208
SeparatedVector2 offset

◆ drawKernText()

static void drawKernText ( SkCanvas canvas,
const void *  text,
size_t  len,
SkScalar  x,
SkScalar  y,
const SkFont font,
const SkPaint paint 
)
static

Definition at line 57 of file typeface.cpp.

58 {
59 SkTypeface* face = font.getTypeface();
60 if (!face) {
62 return;
63 }
64
65 AutoSTMalloc<128, uint16_t> glyphStorage(len);
66 uint16_t* glyphs = glyphStorage.get();
67 int glyphCount = font.textToGlyphs(text, len, SkTextEncoding::kUTF8, glyphs, len);
68 if (glyphCount < 1) {
69 return;
70 }
71
72 AutoSTMalloc<128, int32_t> adjustmentStorage(glyphCount - 1);
73 int32_t* adjustments = adjustmentStorage.get();
74 if (!face->getKerningPairAdjustments(glyphs, glyphCount, adjustments)) {
76 return;
77 }
78
79
81 auto rec = builder.allocRunPos(font, glyphCount);
82 memcpy(rec.glyphs, glyphs, glyphCount * sizeof(SkGlyphID));
83 getGlyphPositions(font, glyphs, glyphCount, x, y, rec.points());
84 applyKerning(rec.points(), adjustments, glyphCount, font);
85
86 canvas->drawTextBlob(builder.make(), 0, 0, paint);
87}
@ kUTF8
uses bytes to represent UTF-8 or ASCII
uint16_t SkGlyphID
Definition: SkTypes.h:179
void drawTextBlob(const SkTextBlob *blob, SkScalar x, SkScalar y, const SkPaint &paint)
Definition: SkCanvas.cpp:2484
bool getKerningPairAdjustments(const SkGlyphID glyphs[], int count, int32_t adjustments[]) const
Definition: SkTypeface.cpp:441
std::u16string text
static void applyKerning(SkPoint pos[], const int32_t adjustments[], int count, const SkFont &font)
Definition: typeface.cpp:46
static void getGlyphPositions(const SkFont &font, const uint16_t glyphs[], int count, SkScalar x, SkScalar y, SkPoint pos[])
Definition: typeface.cpp:34

◆ getGlyphPositions()

static void getGlyphPositions ( const SkFont font,
const uint16_t  glyphs[],
int  count,
SkScalar  x,
SkScalar  y,
SkPoint  pos[] 
)
static

Definition at line 34 of file typeface.cpp.

35 {
37 SkScalar* widths = widthStorage.get();
38 font.getWidths(glyphs, count, widths);
39
40 for (int i = 0; i < count; ++i) {
41 pos[i].set(x, y);
42 x += widths[i];
43 }
44}
const SkScalar widths[]
Definition: StrokerTest.cpp:39
void set(float x, float y)
Definition: SkPoint_impl.h:200

Variable Documentation

◆ gStyles

constexpr SkFontStyle gStyles[]
staticconstexpr
Initial value:
= {
}
static constexpr SkFontStyle Italic()
Definition: SkFontStyle.h:72
static constexpr SkFontStyle BoldItalic()
Definition: SkFontStyle.h:75
static constexpr SkFontStyle Bold()
Definition: SkFontStyle.h:69
static constexpr SkFontStyle Normal()
Definition: SkFontStyle.h:66

Definition at line 89 of file typeface.cpp.

◆ gStylesCount

constexpr int gStylesCount = std::size(gStyles)
constexpr

Definition at line 96 of file typeface.cpp.