1 // Copyright 2019 Google LLC. 2 #ifndef ParagraphBuilderImpl_DEFINED 3 #define ParagraphBuilderImpl_DEFINED 4 5 #include <memory> 6 #include <stack> 7 #include <string> 8 #include <tuple> 9 #include "include/private/base/SkOnce.h" 10 #include "include/private/base/SkTArray.h" 11 #include "modules/skparagraph/include/FontCollection.h" 12 #include "modules/skparagraph/include/Paragraph.h" 13 #include "modules/skparagraph/include/ParagraphBuilder.h" 14 #include "modules/skparagraph/include/ParagraphStyle.h" 15 #include "modules/skparagraph/include/TextStyle.h" 16 17 namespace skia { 18 namespace textlayout { 19 20 class ParagraphBuilderImpl : public ParagraphBuilder { 21 public: 22 ParagraphBuilderImpl(const ParagraphStyle& style, 23 sk_sp<FontCollection> fontCollection, 24 sk_sp<SkUnicode> unicode); 25 26 #if !defined(SK_DISABLE_LEGACY_PARAGRAPH_UNICODE) 27 // Just until we fix all the code; calls icu::make inside 28 ParagraphBuilderImpl(const ParagraphStyle& style, sk_sp<FontCollection> fontCollection); 29 #endif 30 31 ~ParagraphBuilderImpl() override; 32 33 // Push a style to the stack. The corresponding text added with AddText will 34 // use the top-most style. 35 void pushStyle(const TextStyle& style) override; 36 37 // Remove a style from the stack. Useful to apply different styles to chunks 38 // of text such as bolding. 39 // Example: 40 // builder.PushStyle(normal_style); 41 // builder.AddText("Hello this is normal. "); 42 // 43 // builder.PushStyle(bold_style); 44 // builder.AddText("And this is BOLD. "); 45 // 46 // builder.Pop(); 47 // builder.AddText(" Back to normal again."); 48 void pop() override; 49 50 TextStyle peekStyle() override; 51 52 // Adds text to the builder. Forms the proper runs to use the upper-most style 53 // on the style_stack. 54 void addText(const std::u16string& text) override; 55 56 // Adds text to the builder, using the top-most style on on the style_stack. 57 void addText(const char* text) override; // Don't use this one - going away soon 58 void addText(const char* text, size_t len) override; 59 60 void addPlaceholder(const PlaceholderStyle& placeholderStyle) override; 61 62 // Constructs a SkParagraph object that can be used to layout and paint the text to a SkCanvas. 63 std::unique_ptr<Paragraph> Build() override; 64 65 // Support for "Client" unicode 66 SkSpan<char> getText() override; 67 const ParagraphStyle& getParagraphStyle() const override; 68 69 #if !defined(SK_DISABLE_LEGACY_CLIENT_UNICODE) && defined(SK_UNICODE_CLIENT_IMPLEMENTATION) 70 void setWordsUtf8(std::vector<SkUnicode::Position> wordsUtf8) override; 71 void setWordsUtf16(std::vector<SkUnicode::Position> wordsUtf16) override; 72 73 void setGraphemeBreaksUtf8(std::vector<SkUnicode::Position> graphemesUtf8) override; 74 void setGraphemeBreaksUtf16(std::vector<SkUnicode::Position> graphemesUtf16) override; 75 76 void setLineBreaksUtf8(std::vector<SkUnicode::LineBreakBefore> lineBreaksUtf8) override; 77 void setLineBreaksUtf16(std::vector<SkUnicode::LineBreakBefore> lineBreaksUtf16) override; 78 79 std::tuple<std::vector<SkUnicode::Position>, 80 std::vector<SkUnicode::Position>, 81 std::vector<SkUnicode::LineBreakBefore>> getClientICUData()82 getClientICUData() const override { 83 return { fWordsUtf16, fGraphemeBreaksUtf8, fLineBreaksUtf8 }; 84 } 85 SetUnicode(sk_sp<SkUnicode> unicode)86 void SetUnicode(sk_sp<SkUnicode> unicode) override { 87 fUnicode = std::move(unicode); 88 } 89 #endif 90 // Support for Flutter optimization 91 void Reset() override; 92 93 static std::unique_ptr<ParagraphBuilder> make(const ParagraphStyle& style, 94 sk_sp<FontCollection> fontCollection, 95 sk_sp<SkUnicode> unicode); 96 97 98 #if !defined(SK_DISABLE_LEGACY_PARAGRAPH_UNICODE) 99 // Just until we fix all the code; calls icu::make inside 100 static std::unique_ptr<ParagraphBuilder> make(const ParagraphStyle& style, 101 sk_sp<FontCollection> fontCollection); 102 #endif 103 104 static bool RequiresClientICU(); 105 protected: 106 void startStyledBlock(); 107 void endRunIfNeeded(); 108 const TextStyle& internalPeekStyle(); 109 void addPlaceholder(const PlaceholderStyle& placeholderStyle, bool lastOne); 110 void finalize(); 111 112 SkString fUtf8; 113 skia_private::STArray<4, TextStyle, true> fTextStyles; 114 skia_private::STArray<4, Block, true> fStyledBlocks; 115 skia_private::STArray<4, Placeholder, true> fPlaceholders; 116 sk_sp<FontCollection> fFontCollection; 117 ParagraphStyle fParagraphStyle; 118 119 sk_sp<SkUnicode> fUnicode; 120 private: 121 SkOnce fillUTF16MappingOnce; 122 void ensureUTF16Mapping(); 123 skia_private::TArray<TextIndex, true> fUTF8IndexForUTF16Index; 124 skia_private::TArray<TextIndex, true> fUTF16IndexForUTF8Index; 125 #if defined(SK_UNICODE_CLIENT_IMPLEMENTATION) 126 bool fTextIsFinalized; 127 bool fUsingClientInfo; 128 std::vector<SkUnicode::Position> fWordsUtf16; 129 std::vector<SkUnicode::Position> fGraphemeBreaksUtf8; 130 std::vector<SkUnicode::LineBreakBefore> fLineBreaksUtf8; 131 #endif 132 }; 133 } // namespace textlayout 134 } // namespace skia 135 136 #endif // ParagraphBuilderImpl_DEFINED 137