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
16class SkFontMgr;
17class SkTextBlob;
18
19namespace skottie {
20
21// Helper implementing After Effects text shaping semantics on top of SkShaper.
22
23class Shaper final {
24public:
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
112private:
113 Shaper() = delete;
114};
115
116} // namespace skottie
117
118#endif // SkottieShaper_DEFINED
119