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 Flags : uint32_t { 90 kNone = 0x00, 91 92 // Split out individual glyphs into separate Fragments 93 // (useful when the caller intends to manipulate glyphs independently). 94 kFragmentGlyphs = 0x01, 95 96 // Compute the advance and ascent for each fragment. 97 kTrackFragmentAdvanceAscent = 0x02, 98 }; 99 100 struct TextDesc { 101 const sk_sp<SkTypeface>& fTypeface; 102 SkScalar fTextSize, 103 fMinTextSize, 104 fMaxTextSize, 105 fLineHeight, 106 fLineShift, 107 fAscent; 108 SkTextUtils::Align fHAlign; 109 VAlign fVAlign; 110 ResizePolicy fResize; 111 LinebreakPolicy fLinebreak; 112 Direction fDirection; 113 uint32_t fFlags; 114 }; 115 116 // Performs text layout along an infinite horizontal line, starting at |textPoint|. 117 // Only explicit line breaks (\r) are observed. 118 static Result Shape(const SkString& text, const TextDesc& desc, const SkPoint& textPoint, 119 const sk_sp<SkFontMgr>&); 120 121 // Performs text layout within |textBox|, injecting line breaks as needed to ensure 122 // horizontal fitting. The result is *not* guaranteed to fit vertically (it may extend 123 // below the box bottom). 124 static Result Shape(const SkString& text, const TextDesc& desc, const SkRect& textBox, 125 const sk_sp<SkFontMgr>&); 126 127 private: 128 Shaper() = delete; 129 }; 130 131 } // namespace skottie 132 133 #endif // SkottieShaper_DEFINED 134