Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
FontToolUtils.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2014 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
9
12#include "include/core/SkFont.h"
18#include "include/core/SkPixelRef.h" // IWYU pragma: keep
23#include "src/base/SkUTF.h"
24#include "src/core/SkOSFile.h"
25#include "tools/Resources.h"
28
29#if defined(SK_BUILD_FOR_WIN) && (defined(SK_FONTMGR_GDI_AVAILABLE) || \
30 defined(SK_FONTMGR_DIRECTWRITE_AVAILABLE))
32#endif
33
34#if defined(SK_BUILD_FOR_ANDROID) && defined(SK_FONTMGR_ANDROID_AVAILABLE)
37#endif
38
39#if defined(SK_FONTMGR_CORETEXT_AVAILABLE) && (defined(SK_BUILD_FOR_IOS) || \
40 defined(SK_BUILD_FOR_MAC))
42#endif
43
44#if defined(SK_FONTMGR_FONTATIONS_AVAILABLE)
46#endif
47
48#if defined(SK_FONTMGR_FONTCONFIG_AVAILABLE)
50#endif
51
52#if defined(SK_FONTMGR_FREETYPE_DIRECTORY_AVAILABLE)
54#endif
55
56#if defined(SK_FONTMGR_FREETYPE_EMPTY_AVAILABLE)
58#endif
59
60namespace ToolUtils {
61
62static DEFINE_bool(nativeFonts,
63 true,
64 "If true, use native font manager and rendering. "
65 "If false, fonts will draw as portably as possible.");
66#if defined(SK_BUILD_FOR_WIN)
67static DEFINE_bool(gdi, false, "Use GDI instead of DirectWrite for font rendering.");
68#endif
69#if defined(SK_FONTMGR_FONTATIONS_AVAILABLE)
70static DEFINE_bool(fontations, false, "Use Fontations for native font rendering.");
71#endif
72
74 static const sk_sp<SkTypeface> planetTypeface = []() {
75 const char* filename;
76#if defined(SK_BUILD_FOR_WIN)
77 filename = "fonts/planetcolr.ttf";
78#elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
79 filename = "fonts/planetsbix.ttf";
80#else
81 filename = "fonts/planetcbdt.ttf";
82#endif
84 if (typeface) {
85 return typeface;
86 }
87 return CreateTestTypeface("Planet", SkFontStyle());
88 }();
89 return planetTypeface;
90}
91
93 static const EmojiTestSample emojiSample = []() {
94 EmojiTestSample sample = {nullptr, ""};
95#if defined(SK_BUILD_FOR_WIN)
97#elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
99#else
101#endif
102 if (sample.typeface) {
103 return sample;
104 }
106 }();
107 return emojiSample;
108}
109
111 EmojiTestSample sample;
112 sample.sampleText = "\U0001F600 \u2662"; // 😀 ♢
113 switch (format) {
115 sample.typeface = CreateTypefaceFromResource("fonts/cbdt.ttf");
116 break;
118 sample.typeface = CreateTypefaceFromResource("fonts/sbix.ttf");
119 break;
121 sample.typeface = CreateTypefaceFromResource("fonts/colr.ttf");
122 break;
124 sample.typeface = CreateTypefaceFromResource("fonts/SampleSVG.ttf");
125 sample.sampleText = "abcdefghij";
126 break;
128 sample.typeface = CreatePortableTypeface("Emoji", SkFontStyle());
129 }
130 return sample;
131}
132
134 switch (format) {
136 return SkString("cbdt");
138 return SkString("sbix");
140 return SkString("colrv0");
142 return SkString("test");
144 return SkString("svg");
145 }
146 return SkString();
147}
148
151 SkFont font;
152 const float upem = 200;
153
154 {
155 SkFontMetrics metrics;
156 metrics.fFlags = 0;
157 metrics.fTop = -200;
158 metrics.fAscent = -150;
159 metrics.fDescent = 50;
160 metrics.fBottom = -75;
161 metrics.fLeading = 10;
162 metrics.fAvgCharWidth = 150;
163 metrics.fMaxCharWidth = 300;
164 metrics.fXMin = -20;
165 metrics.fXMax = 290;
166 metrics.fXHeight = -100;
167 metrics.fCapHeight = 0;
168 metrics.fUnderlineThickness = 5;
169 metrics.fUnderlinePosition = 2;
170 metrics.fStrikeoutThickness = 5;
171 metrics.fStrikeoutPosition = -50;
172 builder.setMetrics(metrics, 1.0f/upem);
173 }
174 builder.setFontStyle(SkFontStyle(367, 3, SkFontStyle::kOblique_Slant));
175
176 const SkMatrix scale = SkMatrix::Scale(1.0f/upem, 1.0f/upem);
177 for (SkGlyphID index = 0; index <= 67; ++index) {
179 width = 100;
180
181 builder.setGlyph(index, width/upem, SkPath::Circle(50, -50, 75).makeTransform(scale));
182 }
183
184 return builder.detach();
185}
186
188 static sk_sp<SkFontMgr> portableFontMgr = MakePortableFontMgr();
189 SkASSERT_RELEASE(portableFontMgr);
190 sk_sp<SkTypeface> face = portableFontMgr->legacyMakeTypeface(name, style);
191 SkASSERT_RELEASE(face);
192 return face;
193}
194
196 // At last check, the default typeface is a serif font.
198 SkASSERT_RELEASE(face);
199 return face;
200}
201
205
206SkBitmap CreateStringBitmap(int w, int h, SkColor c, int x, int y, int textSize,
207 const char* str) {
209 bitmap.allocN32Pixels(w, h);
210 SkCanvas canvas(bitmap);
211
213 paint.setColor(c);
214
215 SkFont font(DefaultPortableTypeface(), textSize);
216
217 canvas.clear(0x00000000);
218 canvas.drawSimpleText(str,
219 strlen(str),
223 font,
224 paint);
225
226 // Tag data as sRGB (without doing any color space conversion). Color-space aware configs
227 // will process this correctly but legacy configs will render as if this returned N32.
230 result.setPixelRef(sk_ref_sp(bitmap.pixelRef()), 0, 0);
231 return result;
232}
233
234sk_sp<SkImage> CreateStringImage(int w, int h, SkColor c, int x, int y, int textSize,
235 const char* str) {
236 return CreateStringBitmap(w, h, c, x, y, textSize, str).asImage();
237}
238
239#ifndef SK_FONT_FILE_PREFIX
240# if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
241# define SK_FONT_FILE_PREFIX "/System/Library/Fonts/"
242# else
243# define SK_FONT_FILE_PREFIX "/usr/share/fonts/"
244# endif
245#endif
246
248 static sk_sp<SkFontMgr> mgr;
249 static SkOnce once;
250 once([] {
251 if (!FLAGS_nativeFonts) {
252 mgr = MakePortableFontMgr();
253 }
254#if defined(SK_BUILD_FOR_WIN) && defined(SK_FONTMGR_GDI_AVAILABLE)
255 else if (FLAGS_gdi) {
256 mgr = SkFontMgr_New_GDI();
257 }
258#endif
259#if defined(SK_FONTMGR_FONTATIONS_AVAILABLE)
260 else if (FLAGS_fontations) {
262 }
263#endif
264 else {
265#if defined(SK_BUILD_FOR_ANDROID) && defined(SK_FONTMGR_ANDROID_AVAILABLE)
266 mgr = SkFontMgr_New_Android(nullptr, std::make_unique<SkFontScanner_FreeType>());
267#elif defined(SK_BUILD_FOR_WIN) && defined(SK_FONTMGR_DIRECTWRITE_AVAILABLE)
268 mgr = SkFontMgr_New_DirectWrite();
269#elif defined(SK_FONTMGR_CORETEXT_AVAILABLE) && (defined(SK_BUILD_FOR_IOS) || \
270 defined(SK_BUILD_FOR_MAC))
271 mgr = SkFontMgr_New_CoreText(nullptr);
272#elif defined(SK_FONTMGR_FONTCONFIG_AVAILABLE)
273 mgr = SkFontMgr_New_FontConfig(nullptr);
274#elif defined(SK_FONTMGR_FREETYPE_DIRECTORY_AVAILABLE)
275 // In particular, this is used on ChromeOS, which is Linux-like but doesn't have
276 // FontConfig.
278#elif defined(SK_FONTMGR_FREETYPE_EMPTY_AVAILABLE)
280#else
281 mgr = SkFontMgr::RefEmpty();
282#endif
283 }
284 SkASSERT_RELEASE(mgr);
285 });
286 return mgr;
287}
288
290 if (!FLAGS_nativeFonts) {
291 return false;
292 }
293#if defined(SK_BUILD_FOR_WIN)
294 if (FLAGS_gdi) {
295 return true;
296 }
297#endif
298 return false;
299}
300
301void UsePortableFontMgr() { FLAGS_nativeFonts = false; }
302
306
310 sk_sp<SkTypeface> face = fm->legacyMakeTypeface(name, style);
311 if (face) {
312 return face;
313 }
314 return CreatePortableTypeface(name, style);
315}
316
317sk_sp<SkTypeface> CreateTypefaceFromResource(const char* resource, int ttcIndex) {
320 return fm->makeFromStream(GetResourceAsStream(resource), ttcIndex);
321}
322
324 return SkFont(DefaultTypeface(), 12);
325}
326
327} // namespace ToolUtils
#define DEFINE_bool(name, defaultValue, helpString)
std::unique_ptr< SkStreamAsset > GetResourceAsStream(const char *resource, bool useFileStream)
Definition Resources.cpp:31
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition SkAlphaType.h:29
#define SkASSERT_RELEASE(cond)
Definition SkAssert.h:100
uint32_t SkColor
Definition SkColor.h:37
SK_API sk_sp< SkFontMgr > SkFontMgr_New_Fontations_Empty()
SK_API sk_sp< SkFontMgr > SkFontMgr_New_Android(const SkFontMgr_Android_CustomFonts *custom)
#define SK_FONT_FILE_PREFIX
SK_API sk_sp< SkFontMgr > SkFontMgr_New_Custom_Directory(const char *dir)
SK_API sk_sp< SkFontMgr > SkFontMgr_New_Custom_Empty()
SK_API sk_sp< SkFontMgr > SkFontMgr_New_FontConfig(FcConfig *fc)
SK_API sk_sp< SkFontMgr > SkFontMgr_New_CoreText(CTFontCollectionRef)
@ kUTF8
uses bytes to represent UTF-8 or ASCII
sk_sp< T > sk_ref_sp(T *obj)
Definition SkRefCnt.h:381
#define SkIntToScalar(x)
Definition SkScalar.h:57
uint16_t SkGlyphID
Definition SkTypes.h:179
sk_sp< SkImage > asImage() const
Definition SkBitmap.cpp:645
bool setInfo(const SkImageInfo &imageInfo, size_t rowBytes=0)
Definition SkBitmap.cpp:114
void drawSimpleText(const void *text, size_t byteLength, SkTextEncoding encoding, SkScalar x, SkScalar y, const SkFont &font, const SkPaint &paint)
void clear(SkColor color)
Definition SkCanvas.h:1199
static sk_sp< SkFontMgr > RefEmpty()
static SkMatrix Scale(SkScalar sx, SkScalar sy)
Definition SkMatrix.h:75
static SkPath Circle(SkScalar center_x, SkScalar center_y, SkScalar radius, SkPathDirection dir=SkPathDirection::kCW)
Definition SkPath.cpp:3530
const Paint & paint
float SkScalar
Definition extension.cpp:12
GAsyncResult * result
uint32_t uint32_t * format
const char * name
Definition fuchsia.cc:50
double y
double x
sk_sp< SkTypeface > DefaultPortableTypeface()
SkFont DefaultPortableFont()
bool FontMgrIsGDI()
void UsePortableFontMgr()
SkString NameForFontFormat(EmojiFontFormat format)
sk_sp< SkTypeface > CreatePortableTypeface(const char *name, SkFontStyle style)
SkFont DefaultFont()
SkBitmap CreateStringBitmap(int w, int h, SkColor c, int x, int y, int textSize, const char *str)
sk_sp< SkTypeface > PlanetTypeface()
sk_sp< SkTypeface > SampleUserTypeface()
sk_sp< SkTypeface > CreateTypefaceFromResource(const char *resource, int ttcIndex)
EmojiTestSample EmojiSample()
sk_sp< SkTypeface > DefaultTypeface()
sk_sp< SkTypeface > CreateTestTypeface(const char *name, SkFontStyle style)
sk_sp< SkImage > CreateStringImage(int w, int h, SkColor c, int x, int y, int textSize, const char *str)
sk_sp< SkFontMgr > TestFontMgr()
SkScalar w
SkScalar h
int32_t width
const Scalar scale
SkScalar fTop
greatest extent above origin of any glyph bounding box, typically negative; deprecated with variable ...
SkScalar fLeading
distance to add between lines, typically positive or zero
SkScalar fAvgCharWidth
average character width, zero if unknown
SkScalar fStrikeoutPosition
distance from baseline to bottom of stroke, typically negative
SkScalar fStrikeoutThickness
strikeout thickness
SkScalar fMaxCharWidth
maximum character width, zero if unknown
SkScalar fBottom
greatest extent below origin of any glyph bounding box, typically positive; deprecated with variable ...
uint32_t fFlags
FontMetricsFlags indicating which metrics are valid.
SkScalar fAscent
distance to reserve above baseline, typically negative
SkScalar fXHeight
height of lower-case 'x', zero if unknown, typically negative
SkScalar fUnderlineThickness
underline thickness
SkScalar fDescent
distance to reserve below baseline, typically positive
SkScalar fCapHeight
height of an upper-case letter, zero if unknown, typically negative
SkScalar fXMin
greatest extent to left of origin of any glyph bounding box, typically negative; deprecated with vari...
SkScalar fUnderlinePosition
distance from baseline to top of stroke, typically positive
SkScalar fXMax
greatest extent to right of origin of any glyph bounding box, typically positive; deprecated with var...
static SkImageInfo MakeS32(int width, int height, SkAlphaType at)
sk_sp< SkTypeface > typeface