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 class LinebreakPolicy : uint8_t { 80 // Break lines such that they fit in a non-empty paragraph box, horizontally. 81 kParagraph, 82 // Only break lines when requested explicitly (\r), regardless of paragraph box dimensions. 83 kExplicit, 84 }; 85 86 // Initial text direction. 87 enum class Direction : uint8_t { kLTR, kRTL }; 88 89 enum class Capitalization { 90 kNone, 91 kUpperCase, 92 }; 93 94 enum Flags : uint32_t { 95 kNone = 0x00, 96 97 // Split out individual glyphs into separate Fragments 98 // (useful when the caller intends to manipulate glyphs independently). 99 kFragmentGlyphs = 0x01, 100 101 // Compute the advance and ascent for each fragment. 102 kTrackFragmentAdvanceAscent = 0x02, 103 }; 104 105 struct TextDesc { 106 const sk_sp<SkTypeface>& fTypeface; 107 SkScalar fTextSize, 108 fMinTextSize, 109 fMaxTextSize, 110 fLineHeight, 111 fLineShift, 112 fAscent; 113 SkTextUtils::Align fHAlign; 114 VAlign fVAlign; 115 ResizePolicy fResize; 116 LinebreakPolicy fLinebreak; 117 Direction fDirection; 118 Capitalization fCapitalization; 119 uint32_t fFlags; 120 }; 121 122 // Performs text layout along an infinite horizontal line, starting at |textPoint|. 123 // Only explicit line breaks (\r) are observed. 124 static Result Shape(const SkString& text, const TextDesc& desc, const SkPoint& textPoint, 125 const sk_sp<SkFontMgr>&); 126 127 // Performs text layout within |textBox|, injecting line breaks as needed to ensure 128 // horizontal fitting. The result is *not* guaranteed to fit vertically (it may extend 129 // below the box bottom). 130 static Result Shape(const SkString& text, const TextDesc& desc, const SkRect& textBox, 131 const sk_sp<SkFontMgr>&); 132 133 private: 134 Shaper() = delete; 135 }; 136 137 } // namespace skottie 138 139 #endif // SkottieShaper_DEFINED 140