1 | /* |
2 | * Copyright 2019 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 SkottieShaper_DEFINED |
9 | #define SkottieShaper_DEFINED |
10 | |
11 | #include "include/core/SkPoint.h" |
12 | #include "include/utils/SkTextUtils.h" |
13 | |
14 | #include <vector> |
15 | |
16 | class SkFontMgr; |
17 | class SkTextBlob; |
18 | |
19 | namespace skottie { |
20 | |
21 | // Helper implementing After Effects text shaping semantics on top of SkShaper. |
22 | |
23 | class Shaper final { |
24 | public: |
25 | struct Fragment { |
26 | sk_sp<SkTextBlob> fBlob; |
27 | SkPoint fPos; |
28 | |
29 | // Only valid for kFragmentGlyphs |
30 | float fAdvance, |
31 | fAscent; |
32 | uint32_t fLineIndex; // 0-based index for the line this fragment belongs to. |
33 | bool fIsWhitespace; // True if the first code point in the corresponding |
34 | // cluster is whitespace. |
35 | }; |
36 | |
37 | struct Result { |
38 | std::vector<Fragment> fFragments; |
39 | size_t fMissingGlyphCount = 0; |
40 | |
41 | SkRect computeVisualBounds() const; |
42 | }; |
43 | |
44 | enum class VAlign : uint8_t { |
45 | // Align the first line typographical top with the text box top (AE box text). |
46 | kTop, |
47 | // Align the first line typographical baseline with the text box top (AE point text). |
48 | kTopBaseline, |
49 | |
50 | // Skottie vertical alignment extensions: these are based on an extent box defined (in Y) as |
51 | // |
52 | // ------------------------------------------------------ |
53 | // MIN(visual_top_extent , typographical_top_extent ) |
54 | // |
55 | // ... |
56 | // |
57 | // MAX(visual_bottom_extent, typographical_bottom_extent) |
58 | // ------------------------------------------------------ |
59 | |
60 | // extent box top -> text box top |
61 | kVisualTop, |
62 | // extent box center -> text box center |
63 | kVisualCenter, |
64 | // extent box bottom -> text box bottom |
65 | kVisualBottom, |
66 | }; |
67 | |
68 | enum class ResizePolicy : uint8_t { |
69 | // Use the specified text size. |
70 | kNone, |
71 | // Resize the text such that the extent box fits (snuggly) in the text box, |
72 | // both horizontally and vertically. |
73 | kScaleToFit, |
74 | // Same kScaleToFit if the text doesn't fit at the specified font size. |
75 | // Otherwise, same as kNone. |
76 | kDownscaleToFit, |
77 | }; |
78 | |
79 | enum Flags : uint32_t { |
80 | kNone = 0x00, |
81 | |
82 | // Split out individual glyphs into separate Fragments |
83 | // (useful when the caller intends to manipulate glyphs independently). |
84 | kFragmentGlyphs = 0x01, |
85 | |
86 | // Compute the advance and ascent for each fragment. |
87 | kTrackFragmentAdvanceAscent = 0x02, |
88 | }; |
89 | |
90 | struct TextDesc { |
91 | const sk_sp<SkTypeface>& fTypeface; |
92 | SkScalar fTextSize, |
93 | fLineHeight, |
94 | fAscent; |
95 | SkTextUtils::Align fHAlign; |
96 | VAlign fVAlign; |
97 | ResizePolicy fResize; |
98 | uint32_t fFlags; |
99 | }; |
100 | |
101 | // Performs text layout along an infinite horizontal line, starting at |textPoint|. |
102 | // Only explicit line breaks (\r) are observed. |
103 | static Result Shape(const SkString& text, const TextDesc& desc, const SkPoint& textPoint, |
104 | const sk_sp<SkFontMgr>&); |
105 | |
106 | // Performs text layout within |textBox|, injecting line breaks as needed to ensure |
107 | // horizontal fitting. The result is *not* guaranteed to fit vertically (it may extend |
108 | // below the box bottom). |
109 | static Result Shape(const SkString& text, const TextDesc& desc, const SkRect& textBox, |
110 | const sk_sp<SkFontMgr>&); |
111 | |
112 | private: |
113 | Shaper() = delete; |
114 | }; |
115 | |
116 | } // namespace skottie |
117 | |
118 | #endif // SkottieShaper_DEFINED |
119 | |