1 | /* |
2 | * Copyright 2018 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 SkFontPriv_DEFINED |
9 | #define SkFontPriv_DEFINED |
10 | |
11 | #include "include/core/SkFont.h" |
12 | #include "include/core/SkMatrix.h" |
13 | #include "include/core/SkTypeface.h" |
14 | |
15 | class SkReadBuffer; |
16 | class SkWriteBuffer; |
17 | |
18 | class SkFontPriv { |
19 | public: |
20 | /* This is the size we use when we ask for a glyph's path. We then |
21 | * post-transform it as we draw to match the request. |
22 | * This is done to try to re-use cache entries for the path. |
23 | * |
24 | * This value is somewhat arbitrary. In theory, it could be 1, since |
25 | * we store paths as floats. However, we get the path from the font |
26 | * scaler, and it may represent its paths as fixed-point (or 26.6), |
27 | * so we shouldn't ask for something too big (might overflow 16.16) |
28 | * or too small (underflow 26.6). |
29 | * |
30 | * This value could track kMaxSizeForGlyphCache, assuming the above |
31 | * constraints, but since we ask for unhinted paths, the two values |
32 | * need not match per-se. |
33 | */ |
34 | static constexpr int kCanonicalTextSizeForPaths = 64; |
35 | |
36 | /** |
37 | * Return a matrix that applies the paint's text values: size, scale, skew |
38 | */ |
39 | static SkMatrix MakeTextMatrix(SkScalar size, SkScalar scaleX, SkScalar skewX) { |
40 | SkMatrix m = SkMatrix::MakeScale(size * scaleX, size); |
41 | if (skewX) { |
42 | m.postSkew(skewX, 0); |
43 | } |
44 | return m; |
45 | } |
46 | |
47 | static SkMatrix MakeTextMatrix(const SkFont& font) { |
48 | return MakeTextMatrix(font.getSize(), font.getScaleX(), font.getSkewX()); |
49 | } |
50 | |
51 | static void ScaleFontMetrics(SkFontMetrics*, SkScalar); |
52 | |
53 | /** |
54 | Returns the union of bounds of all glyphs. |
55 | Returned dimensions are computed by font manager from font data, |
56 | ignoring SkPaint::Hinting. Includes font metrics, but not fake bold or SkPathEffect. |
57 | |
58 | If text size is large, text scale is one, and text skew is zero, |
59 | returns the bounds as: |
60 | { SkFontMetrics::fXMin, SkFontMetrics::fTop, SkFontMetrics::fXMax, SkFontMetrics::fBottom }. |
61 | |
62 | @return union of bounds of all glyphs |
63 | */ |
64 | static SkRect GetFontBounds(const SkFont&); |
65 | |
66 | static bool IsFinite(const SkFont& font) { |
67 | return SkScalarIsFinite(font.getSize()) && |
68 | SkScalarIsFinite(font.getScaleX()) && |
69 | SkScalarIsFinite(font.getSkewX()); |
70 | } |
71 | |
72 | // Returns the number of elements (characters or glyphs) in the array. |
73 | static int CountTextElements(const void* text, size_t byteLength, SkTextEncoding); |
74 | |
75 | static void GlyphsToUnichars(const SkFont&, const uint16_t glyphs[], int count, SkUnichar[]); |
76 | |
77 | static void Flatten(const SkFont&, SkWriteBuffer& buffer); |
78 | static bool Unflatten(SkFont*, SkReadBuffer& buffer); |
79 | |
80 | static inline uint8_t Flags(const SkFont& font) { return font.fFlags; } |
81 | }; |
82 | |
83 | class SkAutoToGlyphs { |
84 | public: |
85 | SkAutoToGlyphs(const SkFont& font, const void* text, size_t length, SkTextEncoding encoding) { |
86 | if (encoding == SkTextEncoding::kGlyphID || length == 0) { |
87 | fGlyphs = reinterpret_cast<const uint16_t*>(text); |
88 | fCount = length >> 1; |
89 | } else { |
90 | fCount = font.countText(text, length, encoding); |
91 | if (fCount < 0) { |
92 | fCount = 0; |
93 | } |
94 | fStorage.reset(fCount); |
95 | font.textToGlyphs(text, length, encoding, fStorage.get(), fCount); |
96 | fGlyphs = fStorage.get(); |
97 | } |
98 | } |
99 | |
100 | int count() const { return fCount; } |
101 | const uint16_t* glyphs() const { return fGlyphs; } |
102 | |
103 | private: |
104 | SkAutoSTArray<32, uint16_t> fStorage; |
105 | const uint16_t* fGlyphs; |
106 | int fCount; |
107 | }; |
108 | |
109 | #endif |
110 | |