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 #ifdef ENABLE_TEXT_ENHANCE 65 std::unique_ptr<ParagraphLineFetcher> buildLineFetcher() override; 66 #endif 67 // Support for "Client" unicode 68 SkSpan<char> getText() override; 69 const ParagraphStyle& getParagraphStyle() const override; 70 71 #if !defined(SK_DISABLE_LEGACY_CLIENT_UNICODE) && defined(SK_UNICODE_CLIENT_IMPLEMENTATION) 72 void setWordsUtf8(std::vector<SkUnicode::Position> wordsUtf8) override; 73 void setWordsUtf16(std::vector<SkUnicode::Position> wordsUtf16) override; 74 75 void setGraphemeBreaksUtf8(std::vector<SkUnicode::Position> graphemesUtf8) override; 76 void setGraphemeBreaksUtf16(std::vector<SkUnicode::Position> graphemesUtf16) override; 77 78 void setLineBreaksUtf8(std::vector<SkUnicode::LineBreakBefore> lineBreaksUtf8) override; 79 void setLineBreaksUtf16(std::vector<SkUnicode::LineBreakBefore> lineBreaksUtf16) override; 80 81 std::tuple<std::vector<SkUnicode::Position>, 82 std::vector<SkUnicode::Position>, 83 std::vector<SkUnicode::LineBreakBefore>> getClientICUData()84 getClientICUData() const override { 85 return { fWordsUtf16, fGraphemeBreaksUtf8, fLineBreaksUtf8 }; 86 } 87 SetUnicode(sk_sp<SkUnicode> unicode)88 void SetUnicode(sk_sp<SkUnicode> unicode) override { 89 fUnicode = std::move(unicode); 90 } 91 #endif 92 // Support for Flutter optimization 93 void Reset() override; 94 95 static std::unique_ptr<ParagraphBuilder> make(const ParagraphStyle& style, 96 sk_sp<FontCollection> fontCollection, 97 sk_sp<SkUnicode> unicode); 98 99 100 #if !defined(SK_DISABLE_LEGACY_PARAGRAPH_UNICODE) 101 // Just until we fix all the code; calls icu::make inside 102 static std::unique_ptr<ParagraphBuilder> make(const ParagraphStyle& style, 103 sk_sp<FontCollection> fontCollection); 104 #endif 105 106 static bool RequiresClientICU(); 107 protected: 108 void startStyledBlock(); 109 void endRunIfNeeded(); 110 const TextStyle& internalPeekStyle(); 111 void addPlaceholder(const PlaceholderStyle& placeholderStyle, bool lastOne); 112 void finalize(); 113 114 SkString fUtf8; 115 skia_private::STArray<4, TextStyle, true> fTextStyles; 116 skia_private::STArray<4, Block, true> fStyledBlocks; 117 skia_private::STArray<4, Placeholder, true> fPlaceholders; 118 sk_sp<FontCollection> fFontCollection; 119 ParagraphStyle fParagraphStyle; 120 121 sk_sp<SkUnicode> fUnicode; 122 private: 123 SkOnce fillUTF16MappingOnce; 124 void ensureUTF16Mapping(); 125 skia_private::TArray<TextIndex, true> fUTF8IndexForUTF16Index; 126 skia_private::TArray<TextIndex, true> fUTF16IndexForUTF8Index; 127 #if defined(SK_UNICODE_CLIENT_IMPLEMENTATION) 128 bool fTextIsFinalized; 129 bool fUsingClientInfo; 130 std::vector<SkUnicode::Position> fWordsUtf16; 131 std::vector<SkUnicode::Position> fGraphemeBreaksUtf8; 132 std::vector<SkUnicode::LineBreakBefore> fLineBreaksUtf8; 133 #endif 134 }; 135 } // namespace textlayout 136 } // namespace skia 137 138 #endif // ParagraphBuilderImpl_DEFINED 139