xref: /aosp_15_r20/external/skia/include/core/SkFont.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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 
8 #ifndef SkFont_DEFINED
9 #define SkFont_DEFINED
10 
11 #include "include/core/SkRect.h"
12 #include "include/core/SkRefCnt.h"
13 #include "include/core/SkScalar.h"
14 #include "include/core/SkTypeface.h"
15 #include "include/core/SkTypes.h"
16 #include "include/private/base/SkTo.h"
17 #include "include/private/base/SkTypeTraits.h"
18 
19 #include <cstddef>
20 #include <cstdint>
21 #include <type_traits>
22 #include <vector>
23 
24 class SkMatrix;
25 class SkPaint;
26 class SkPath;
27 enum class SkFontHinting;
28 enum class SkTextEncoding;
29 struct SkFontMetrics;
30 struct SkPoint;
31 
32 /** \class SkFont
33     SkFont controls options applied when drawing and measuring text.
34 */
35 class SK_API SkFont {
36 public:
37     /** Whether edge pixels draw opaque or with partial transparency.
38     */
39     enum class Edging {
40         kAlias,              //!< no transparent pixels on glyph edges
41         kAntiAlias,          //!< may have transparent pixels on glyph edges
42         kSubpixelAntiAlias,  //!< glyph positioned in pixel using transparency
43     };
44 
45     /** Constructs SkFont with default values.
46 
47         @return  default initialized SkFont
48     */
49     SkFont();
50 
51     /** Constructs SkFont with default values with SkTypeface and size in points.
52 
53         @param typeface  font and style used to draw and measure text
54         @param size      typographic height of text
55         @return          initialized SkFont
56     */
57     SkFont(sk_sp<SkTypeface> typeface, SkScalar size);
58 
59     /** Constructs SkFont with default values with SkTypeface.
60 
61         @param typeface  font and style used to draw and measure text
62         @return          initialized SkFont
63     */
64     explicit SkFont(sk_sp<SkTypeface> typeface);
65 
66 
67     /** Constructs SkFont with default values with SkTypeface and size in points,
68         horizontal scale, and horizontal skew. Horizontal scale emulates condensed
69         and expanded fonts. Horizontal skew emulates oblique fonts.
70 
71         @param typeface  font and style used to draw and measure text
72         @param size      typographic height of text
73         @param scaleX    text horizontal scale
74         @param skewX     additional shear on x-axis relative to y-axis
75         @return          initialized SkFont
76     */
77     SkFont(sk_sp<SkTypeface> typeface, SkScalar size, SkScalar scaleX, SkScalar skewX);
78 
79 
80     /** Compares SkFont and font, and returns true if they are equivalent.
81         May return false if SkTypeface has identical contents but different pointers.
82 
83         @param font  font to compare
84         @return      true if SkFont pair are equivalent
85     */
86     bool operator==(const SkFont& font) const;
87 
88     /** Compares SkFont and font, and returns true if they are not equivalent.
89         May return true if SkTypeface has identical contents but different pointers.
90 
91         @param font  font to compare
92         @return      true if SkFont pair are not equivalent
93     */
94     bool operator!=(const SkFont& font) const { return !(*this == font); }
95 
96     /** If true, instructs the font manager to always hint glyphs.
97         Returned value is only meaningful if platform uses FreeType as the font manager.
98 
99         @return  true if all glyphs are hinted
100     */
isForceAutoHinting()101     bool isForceAutoHinting() const { return SkToBool(fFlags & kForceAutoHinting_PrivFlag); }
102 
103     /** Returns true if font engine may return glyphs from font bitmaps instead of from outlines.
104 
105         @return  true if glyphs may be font bitmaps
106     */
isEmbeddedBitmaps()107     bool isEmbeddedBitmaps() const { return SkToBool(fFlags & kEmbeddedBitmaps_PrivFlag); }
108 
109     /** Returns true if glyphs may be drawn at sub-pixel offsets.
110 
111         @return  true if glyphs may be drawn at sub-pixel offsets.
112     */
isSubpixel()113     bool isSubpixel() const { return SkToBool(fFlags & kSubpixel_PrivFlag); }
114 
115     /** Returns true if font and glyph metrics are requested to be linearly scalable.
116 
117         @return  true if font and glyph metrics are requested to be linearly scalable.
118     */
isLinearMetrics()119     bool isLinearMetrics() const { return SkToBool(fFlags & kLinearMetrics_PrivFlag); }
120 
121     /** Returns true if bold is approximated by increasing the stroke width when creating glyph
122         bitmaps from outlines.
123 
124         @return  bold is approximated through stroke width
125     */
isEmbolden()126     bool isEmbolden() const { return SkToBool(fFlags & kEmbolden_PrivFlag); }
127 
128     /** Returns true if baselines will be snapped to pixel positions when the current transformation
129         matrix is axis aligned.
130 
131         @return  baselines may be snapped to pixels
132      */
isBaselineSnap()133     bool isBaselineSnap() const { return SkToBool(fFlags & kBaselineSnap_PrivFlag); }
134 
135     /** Sets whether to always hint glyphs.
136         If forceAutoHinting is set, instructs the font manager to always hint glyphs.
137 
138         Only affects platforms that use FreeType as the font manager.
139 
140         @param forceAutoHinting  setting to always hint glyphs
141     */
142     void setForceAutoHinting(bool forceAutoHinting);
143 
144     /** Requests, but does not require, to use bitmaps in fonts instead of outlines.
145 
146         @param embeddedBitmaps  setting to use bitmaps in fonts
147     */
148     void setEmbeddedBitmaps(bool embeddedBitmaps);
149 
150     /** Requests, but does not require, that glyphs respect sub-pixel positioning.
151 
152         @param subpixel  setting for sub-pixel positioning
153     */
154     void setSubpixel(bool subpixel);
155 
156     /** Requests, but does not require, linearly scalable font and glyph metrics.
157 
158         For outline fonts 'true' means font and glyph metrics should ignore hinting and rounding.
159         Note that some bitmap formats may not be able to scale linearly and will ignore this flag.
160 
161         @param linearMetrics  setting for linearly scalable font and glyph metrics.
162     */
163     void setLinearMetrics(bool linearMetrics);
164 
165     /** Increases stroke width when creating glyph bitmaps to approximate a bold typeface.
166 
167         @param embolden  setting for bold approximation
168     */
169     void setEmbolden(bool embolden);
170 
171     /** Requests that baselines be snapped to pixels when the current transformation matrix is axis
172         aligned.
173 
174         @param baselineSnap  setting for baseline snapping to pixels
175     */
176     void setBaselineSnap(bool baselineSnap);
177 
178     /** Whether edge pixels draw opaque or with partial transparency.
179     */
getEdging()180     Edging getEdging() const { return (Edging)fEdging; }
181 
182     /** Requests, but does not require, that edge pixels draw opaque or with
183         partial transparency.
184     */
185     void setEdging(Edging edging);
186 
187     /** Sets level of glyph outline adjustment.
188         Does not check for valid values of hintingLevel.
189     */
190     void setHinting(SkFontHinting hintingLevel);
191 
192     /** Returns level of glyph outline adjustment.
193      */
getHinting()194     SkFontHinting getHinting() const { return (SkFontHinting)fHinting; }
195 
196     /** Returns a font with the same attributes of this font, but with the specified size.
197         Returns nullptr if size is less than zero, infinite, or NaN.
198 
199         @param size  typographic height of text
200         @return      initialized SkFont
201      */
202     SkFont makeWithSize(SkScalar size) const;
203 
204     /** Does not alter SkTypeface SkRefCnt.
205 
206         @return  non-null SkTypeface
207     */
getTypeface()208     SkTypeface* getTypeface() const {
209         SkASSERT(fTypeface);
210         return fTypeface.get();
211     }
212 
213     /** Returns text size in points.
214 
215         @return  typographic height of text
216     */
getSize()217     SkScalar    getSize() const { return fSize; }
218 
219     /** Returns text scale on x-axis.
220         Default value is 1.
221 
222         @return  text horizontal scale
223     */
getScaleX()224     SkScalar    getScaleX() const { return fScaleX; }
225 
226     /** Returns text skew on x-axis.
227         Default value is zero.
228 
229         @return  additional shear on x-axis relative to y-axis
230     */
getSkewX()231     SkScalar    getSkewX() const { return fSkewX; }
232 
233     /** Increases SkTypeface SkRefCnt by one.
234 
235         @return  A non-null SkTypeface.
236     */
refTypeface()237     sk_sp<SkTypeface> refTypeface() const {
238         SkASSERT(fTypeface);
239         return fTypeface;
240     }
241 
242     /** Sets SkTypeface to typeface, decreasing SkRefCnt of the previous SkTypeface.
243         Pass nullptr to clear SkTypeface and use an empty typeface (which draws nothing).
244         Increments tf SkRefCnt by one.
245 
246         @param tf  font and style used to draw text
247     */
248     void setTypeface(sk_sp<SkTypeface> tf);
249 
250     /** Sets text size in points.
251         Has no effect if textSize is not greater than or equal to zero.
252 
253         @param textSize  typographic height of text
254     */
255     void setSize(SkScalar textSize);
256 
257     /** Sets text scale on x-axis.
258         Default value is 1.
259 
260         @param scaleX  text horizontal scale
261     */
262     void setScaleX(SkScalar scaleX);
263 
264     /** Sets text skew on x-axis.
265         Default value is zero.
266 
267         @param skewX  additional shear on x-axis relative to y-axis
268     */
269     void setSkewX(SkScalar skewX);
270 
271     /** Converts text into glyph indices.
272         Returns the number of glyph indices represented by text.
273         SkTextEncoding specifies how text represents characters or glyphs.
274         glyphs may be nullptr, to compute the glyph count.
275 
276         Does not check text for valid character codes or valid glyph indices.
277 
278         If byteLength equals zero, returns zero.
279         If byteLength includes a partial character, the partial character is ignored.
280 
281         If encoding is SkTextEncoding::kUTF8 and text contains an invalid UTF-8 sequence,
282         zero is returned.
283 
284         When encoding is SkTextEncoding::kUTF8, SkTextEncoding::kUTF16, or
285         SkTextEncoding::kUTF32; then each Unicode codepoint is mapped to a
286         single glyph.  This function uses the default character-to-glyph
287         mapping from the SkTypeface and maps characters not found in the
288         SkTypeface to zero.
289 
290         If maxGlyphCount is not sufficient to store all the glyphs, no glyphs are copied.
291         The total glyph count is returned for subsequent buffer reallocation.
292 
293         @param text          character storage encoded with SkTextEncoding
294         @param byteLength    length of character storage in bytes
295         @param glyphs        storage for glyph indices; may be nullptr
296         @param maxGlyphCount storage capacity
297         @return              number of glyphs represented by text of length byteLength
298     */
299     int textToGlyphs(const void* text, size_t byteLength, SkTextEncoding encoding,
300                      SkGlyphID glyphs[], int maxGlyphCount) const;
301 
302     /** Returns glyph index for Unicode character.
303 
304         If the character is not supported by the SkTypeface, returns 0.
305 
306         @param uni  Unicode character
307         @return     glyph index
308     */
309     SkGlyphID unicharToGlyph(SkUnichar uni) const;
310 
311     void unicharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const;
312 
313     /** Returns number of glyphs represented by text.
314 
315         If encoding is SkTextEncoding::kUTF8, SkTextEncoding::kUTF16, or
316         SkTextEncoding::kUTF32; then each Unicode codepoint is mapped to a
317         single glyph.
318 
319         @param text          character storage encoded with SkTextEncoding
320         @param byteLength    length of character storage in bytes
321         @return              number of glyphs represented by text of length byteLength
322     */
countText(const void * text,size_t byteLength,SkTextEncoding encoding)323     int countText(const void* text, size_t byteLength, SkTextEncoding encoding) const {
324         return this->textToGlyphs(text, byteLength, encoding, nullptr, 0);
325     }
326 
327     /** Returns the advance width of text.
328         The advance is the normal distance to move before drawing additional text.
329         Returns the bounding box of text if bounds is not nullptr.
330 
331         @param text        character storage encoded with SkTextEncoding
332         @param byteLength  length of character storage in bytes
333         @param bounds      returns bounding box relative to (0, 0) if not nullptr
334         @return            the sum of the default advance widths
335     */
336     SkScalar measureText(const void* text, size_t byteLength, SkTextEncoding encoding,
337                          SkRect* bounds = nullptr) const {
338         return this->measureText(text, byteLength, encoding, bounds, nullptr);
339     }
340 
341     /** Returns the advance width of text.
342         The advance is the normal distance to move before drawing additional text.
343         Returns the bounding box of text if bounds is not nullptr. The paint
344         stroke settings, mask filter, or path effect may modify the bounds.
345 
346         @param text        character storage encoded with SkTextEncoding
347         @param byteLength  length of character storage in bytes
348         @param bounds      returns bounding box relative to (0, 0) if not nullptr
349         @param paint       optional; may be nullptr
350         @return            the sum of the default advance widths
351     */
352     SkScalar measureText(const void* text, size_t byteLength, SkTextEncoding encoding,
353                          SkRect* bounds, const SkPaint* paint) const;
354 
355     /** DEPRECATED
356         Retrieves the advance and bounds for each glyph in glyphs.
357         Both widths and bounds may be nullptr.
358         If widths is not nullptr, widths must be an array of count entries.
359         if bounds is not nullptr, bounds must be an array of count entries.
360 
361         @param glyphs      array of glyph indices to be measured
362         @param count       number of glyphs
363         @param widths      returns text advances for each glyph; may be nullptr
364         @param bounds      returns bounds for each glyph relative to (0, 0); may be nullptr
365     */
getWidths(const SkGlyphID glyphs[],int count,SkScalar widths[],SkRect bounds[])366     void getWidths(const SkGlyphID glyphs[], int count, SkScalar widths[], SkRect bounds[]) const {
367         this->getWidthsBounds(glyphs, count, widths, bounds, nullptr);
368     }
369 
370     // DEPRECATED
getWidths(const SkGlyphID glyphs[],int count,SkScalar widths[],std::nullptr_t)371     void getWidths(const SkGlyphID glyphs[], int count, SkScalar widths[], std::nullptr_t) const {
372         this->getWidths(glyphs, count, widths);
373     }
374 
375     /** Retrieves the advance and bounds for each glyph in glyphs.
376         Both widths and bounds may be nullptr.
377         If widths is not nullptr, widths must be an array of count entries.
378         if bounds is not nullptr, bounds must be an array of count entries.
379 
380         @param glyphs      array of glyph indices to be measured
381         @param count       number of glyphs
382         @param widths      returns text advances for each glyph
383      */
getWidths(const SkGlyphID glyphs[],int count,SkScalar widths[])384     void getWidths(const SkGlyphID glyphs[], int count, SkScalar widths[]) const {
385         this->getWidthsBounds(glyphs, count, widths, nullptr, nullptr);
386     }
387 
388     /** Retrieves the advance and bounds for each glyph in glyphs.
389         Both widths and bounds may be nullptr.
390         If widths is not nullptr, widths must be an array of count entries.
391         if bounds is not nullptr, bounds must be an array of count entries.
392 
393         @param glyphs      array of glyph indices to be measured
394         @param count       number of glyphs
395         @param widths      returns text advances for each glyph; may be nullptr
396         @param bounds      returns bounds for each glyph relative to (0, 0); may be nullptr
397         @param paint       optional, specifies stroking, SkPathEffect and SkMaskFilter
398      */
399     void getWidthsBounds(const SkGlyphID glyphs[], int count, SkScalar widths[], SkRect bounds[],
400                          const SkPaint* paint) const;
401 
402 
403     /** Retrieves the bounds for each glyph in glyphs.
404         bounds must be an array of count entries.
405         If paint is not nullptr, its stroking, SkPathEffect, and SkMaskFilter fields are respected.
406 
407         @param glyphs      array of glyph indices to be measured
408         @param count       number of glyphs
409         @param bounds      returns bounds for each glyph relative to (0, 0); may be nullptr
410         @param paint       optional, specifies stroking, SkPathEffect, and SkMaskFilter
411      */
getBounds(const SkGlyphID glyphs[],int count,SkRect bounds[],const SkPaint * paint)412     void getBounds(const SkGlyphID glyphs[], int count, SkRect bounds[],
413                    const SkPaint* paint) const {
414         this->getWidthsBounds(glyphs, count, nullptr, bounds, paint);
415     }
416 
417     /** Retrieves the positions for each glyph, beginning at the specified origin. The caller
418         must allocated at least count number of elements in the pos[] array.
419 
420         @param glyphs   array of glyph indices to be positioned
421         @param count    number of glyphs
422         @param pos      returns glyphs positions
423         @param origin   location of the first glyph. Defaults to {0, 0}.
424      */
425     void getPos(const SkGlyphID glyphs[], int count, SkPoint pos[], SkPoint origin = {0, 0}) const;
426 
427     /** Retrieves the x-positions for each glyph, beginning at the specified origin. The caller
428         must allocated at least count number of elements in the xpos[] array.
429 
430         @param glyphs   array of glyph indices to be positioned
431         @param count    number of glyphs
432         @param xpos     returns glyphs x-positions
433         @param origin   x-position of the first glyph. Defaults to 0.
434      */
435     void getXPos(const SkGlyphID glyphs[], int count, SkScalar xpos[], SkScalar origin = 0) const;
436 
437     /** Returns intervals [start, end] describing lines parallel to the advance that intersect
438      *  with the glyphs.
439      *
440      *  @param glyphs   the glyphs to intersect
441      *  @param count    the number of glyphs and positions
442      *  @param pos      the position of each glyph
443      *  @param top      the top of the line intersecting
444      *  @param bottom   the bottom of the line intersecting
445         @return         array of pairs of x values [start, end]. May be empty.
446      */
447     std::vector<SkScalar> getIntercepts(const SkGlyphID glyphs[], int count, const SkPoint pos[],
448                                         SkScalar top, SkScalar bottom,
449                                         const SkPaint* = nullptr) const;
450 
451     /** Modifies path to be the outline of the glyph.
452         If the glyph has an outline, modifies path to be the glyph's outline and returns true.
453         The glyph outline may be empty. Degenerate contours in the glyph outline will be skipped.
454         If glyph is described by a bitmap, returns false and ignores path parameter.
455 
456         @param glyphID  index of glyph
457         @param path     pointer to existing SkPath
458         @return         true if glyphID is described by path
459      */
460     bool getPath(SkGlyphID glyphID, SkPath* path) const;
461 
462     /** Returns path corresponding to glyph array.
463 
464         @param glyphIDs      array of glyph indices
465         @param count         number of glyphs
466         @param glyphPathProc function returning one glyph description as path
467         @param ctx           function context
468    */
469     void getPaths(const SkGlyphID glyphIDs[], int count,
470                   void (*glyphPathProc)(const SkPath* pathOrNull, const SkMatrix& mx, void* ctx),
471                   void* ctx) const;
472 
473     /** Returns SkFontMetrics associated with SkTypeface.
474         The return value is the recommended spacing between lines: the sum of metrics
475         descent, ascent, and leading.
476         If metrics is not nullptr, SkFontMetrics is copied to metrics.
477         Results are scaled by text size but does not take into account
478         dimensions required by text scale, text skew, fake bold,
479         style stroke, and SkPathEffect.
480 
481         @param metrics  storage for SkFontMetrics; may be nullptr
482         @return         recommended spacing between lines
483     */
484     SkScalar getMetrics(SkFontMetrics* metrics) const;
485 
486     /** Returns the recommended spacing between lines: the sum of metrics
487         descent, ascent, and leading.
488         Result is scaled by text size but does not take into account
489         dimensions required by stroking and SkPathEffect.
490         Returns the same result as getMetrics().
491 
492         @return  recommended spacing between lines
493     */
getSpacing()494     SkScalar getSpacing() const { return this->getMetrics(nullptr); }
495 
496     /** Dumps fields of the font to SkDebugf. May change its output over time, so clients should
497      *  not rely on this for anything specific. Used to aid in debugging.
498      */
499     void dump() const;
500 
501     using sk_is_trivially_relocatable = std::true_type;
502 
503 private:
504     enum PrivFlags {
505         kForceAutoHinting_PrivFlag      = 1 << 0,
506         kEmbeddedBitmaps_PrivFlag       = 1 << 1,
507         kSubpixel_PrivFlag              = 1 << 2,
508         kLinearMetrics_PrivFlag         = 1 << 3,
509         kEmbolden_PrivFlag              = 1 << 4,
510         kBaselineSnap_PrivFlag          = 1 << 5,
511     };
512 
513     static constexpr unsigned kAllFlags = kForceAutoHinting_PrivFlag
514                                         | kEmbeddedBitmaps_PrivFlag
515                                         | kSubpixel_PrivFlag
516                                         | kLinearMetrics_PrivFlag
517                                         | kEmbolden_PrivFlag
518                                         | kBaselineSnap_PrivFlag;
519 
520     sk_sp<SkTypeface> fTypeface;
521     SkScalar    fSize;
522     SkScalar    fScaleX;
523     SkScalar    fSkewX;
524     uint8_t     fFlags;
525     uint8_t     fEdging;
526     uint8_t     fHinting;
527 
528     static_assert(::sk_is_trivially_relocatable<decltype(fTypeface)>::value);
529 
530     SkScalar setupForAsPaths(SkPaint*);
531     bool hasSomeAntiAliasing() const;
532 
533     friend class SkFontPriv;
534     friend class SkGlyphRunListPainterCPU;
535     friend class SkStrikeSpec;
536     friend class SkRemoteGlyphCacheTest;
537 };
538 
539 #endif
540