Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
ParagraphBuilderImpl.cpp
Go to the documentation of this file.
1// Copyright 2019 Google LLC.
3
14
15#if !defined(SK_DISABLE_LEGACY_PARAGRAPH_UNICODE)
16#if defined(SK_UNICODE_ICU_IMPLEMENTATION)
18#endif
19
20#if defined(SK_UNICODE_LIBGRAPHEME_IMPLEMENTATION)
22#endif
23
24#if defined(SK_UNICODE_ICU4X_IMPLEMENTATION)
26#endif
27
28#if defined(SK_UNICODE_CLIENT_IMPLEMENTATION)
30#endif
31
32#endif // !defined(SK_DISABLE_LEGACY_PARAGRAPH_UNICODE)
33
34#include <memory>
35#include <utility>
36
37namespace skia {
38namespace textlayout {
39
40#if !defined(SK_DISABLE_LEGACY_PARAGRAPH_UNICODE)
41
42namespace {
43// TODO(kjlubick,jlavrova) Remove these defines by having clients register something or somehow
44// plumbing this all into the animation builder factories.
46#ifdef SK_UNICODE_ICU_IMPLEMENTATION
47 if (auto unicode = SkUnicodes::ICU::Make()) {
48 return unicode;
49 }
50#endif
51#ifdef SK_UNICODE_ICU4X_IMPLEMENTATION
52 if (auto unicode = SkUnicodes::ICU4X::Make()) {
53 return unicode;
54 }
55#endif
56#ifdef SK_UNICODE_LIBGRAPHEME_IMPLEMENTATION
57 if (auto unicode = SkUnicodes::Libgrapheme::Make()) {
58 return unicode;
59 }
60#endif
61 return nullptr;
62}
63}
64
65std::unique_ptr<ParagraphBuilder> ParagraphBuilder::make(const ParagraphStyle& style,
66 sk_sp<FontCollection> fontCollection) {
67 return ParagraphBuilderImpl::make(style, std::move(fontCollection), get_unicode());
68}
69
70std::unique_ptr<ParagraphBuilder> ParagraphBuilderImpl::make(const ParagraphStyle& style,
71 sk_sp<FontCollection> fontCollection) {
72 return std::make_unique<ParagraphBuilderImpl>(style, std::move(fontCollection), get_unicode());
73}
74
76 const ParagraphStyle& style, sk_sp<FontCollection> fontCollection)
77 : ParagraphBuilderImpl(style, std::move(fontCollection), get_unicode())
78{ }
79
80#endif // !defined(SK_DISABLE_LEGACY_PARAGRAPH_UNICODE)
81
82std::unique_ptr<ParagraphBuilder> ParagraphBuilder::make(const ParagraphStyle& style,
83 sk_sp<FontCollection> fontCollection,
84 sk_sp<SkUnicode> unicode) {
85 return ParagraphBuilderImpl::make(style, std::move(fontCollection), std::move(unicode));
86}
87
88std::unique_ptr<ParagraphBuilder> ParagraphBuilderImpl::make(const ParagraphStyle& style,
89 sk_sp<FontCollection> fontCollection,
90 sk_sp<SkUnicode> unicode) {
91 return std::make_unique<ParagraphBuilderImpl>(style, std::move(fontCollection),
92 std::move(unicode));
93}
94
96 const ParagraphStyle& style, sk_sp<FontCollection> fontCollection, sk_sp<SkUnicode> unicode)
98 , fUtf8()
99 , fFontCollection(std::move(fontCollection))
100 , fParagraphStyle(style)
101 , fUnicode(std::move(unicode))
102#if defined(SK_UNICODE_CLIENT_IMPLEMENTATION)
103 , fTextIsFinalized(false)
104 , fUsingClientInfo(false)
105#endif
106{
109}
110
112
114 fTextStyles.push_back(style);
115 if (!fStyledBlocks.empty() && fStyledBlocks.back().fRange.end == fUtf8.size() &&
116 fStyledBlocks.back().fStyle == style) {
117 // Just continue with the same style
118 } else {
119 // Go with the new style
121 }
122}
123
125 if (!fTextStyles.empty()) {
126 fTextStyles.pop_back();
127 } else {
128 // In this case we use paragraph style and skip Pop operation
129 SkDEBUGF("SkParagraphBuilder.Pop() called too many times.\n");
130 }
131
132 this->startStyledBlock();
133}
134
136 if (fTextStyles.empty()) {
138 } else {
139 return fTextStyles.back();
140 }
141}
142
146
147void ParagraphBuilderImpl::addText(const std::u16string& text) {
148#if defined(SK_UNICODE_CLIENT_IMPLEMENTATION)
149 SkASSERT(!fTextIsFinalized);
150#endif
152 fUtf8.append(utf8);
153}
154
156#if defined(SK_UNICODE_CLIENT_IMPLEMENTATION)
157 SkASSERT(!fTextIsFinalized);
158#endif
160}
161
162void ParagraphBuilderImpl::addText(const char* text, size_t len) {
163#if defined(SK_UNICODE_CLIENT_IMPLEMENTATION)
164 SkASSERT(!fTextIsFinalized);
165#endif
166 fUtf8.append(text, len);
167}
168
170#if defined(SK_UNICODE_CLIENT_IMPLEMENTATION)
171 SkASSERT(!fTextIsFinalized);
172#endif
173 addPlaceholder(placeholderStyle, false);
174}
175
176void ParagraphBuilderImpl::addPlaceholder(const PlaceholderStyle& placeholderStyle, bool lastOne) {
177#if defined(SK_UNICODE_CLIENT_IMPLEMENTATION)
178 // The very last placeholder is added automatically
179 // and only AFTER finalize() is called
180 SkASSERT(!fTextIsFinalized || lastOne);
181#endif
182 if (!fUtf8.isEmpty() && !lastOne) {
183 // We keep the very last text style
184 this->endRunIfNeeded();
185 }
186
187 BlockRange stylesBefore(fPlaceholders.empty() ? 0 : fPlaceholders.back().fBlocksBefore.end + 1,
188 fStyledBlocks.size());
189 TextRange textBefore(fPlaceholders.empty() ? 0 : fPlaceholders.back().fRange.end,
190 fUtf8.size());
191 auto start = fUtf8.size();
192 auto topStyle = internalPeekStyle();
193 if (!lastOne) {
194 pushStyle(topStyle.cloneForPlaceholder());
195 addText(std::u16string(1ull, 0xFFFC));
196 pop();
197 }
198 auto end = fUtf8.size();
199 fPlaceholders.emplace_back(start, end, placeholderStyle, topStyle, stylesBefore, textBefore);
200}
201
203 if (fStyledBlocks.empty()) {
204 return;
205 }
206
207 auto& last = fStyledBlocks.back();
208 if (last.fRange.start == fUtf8.size()) {
209 fStyledBlocks.pop_back();
210 } else {
211 last.fRange.end = fUtf8.size();
212 }
213}
214
219
221#if defined(SK_UNICODE_CLIENT_IMPLEMENTATION)
222 if (fTextIsFinalized) {
223 return;
224 }
225#endif
226 if (!fUtf8.isEmpty()) {
227 this->endRunIfNeeded();
228 }
229
230#if defined(SK_UNICODE_CLIENT_IMPLEMENTATION)
231 fTextIsFinalized = true;
232#endif
233}
234
235std::unique_ptr<Paragraph> ParagraphBuilderImpl::Build() {
236 this->finalize();
237 // Add one fake placeholder with the rest of the text
238 this->addPlaceholder(PlaceholderStyle(), true);
239
240 fUTF8IndexForUTF16Index.clear();
241 fUTF16IndexForUTF8Index.clear();
242#if !defined(SK_DISABLE_LEGACY_PARAGRAPH_UNICODE) && defined(SK_UNICODE_CLIENT_IMPLEMENTATION)
243 if (fUsingClientInfo && !fUnicode) {
244 // This is the place where SkUnicode is paired with SkParagraph
246 std::move(fWordsUtf16),
247 std::move(fGraphemeBreaksUtf8),
248 std::move(fLineBreaksUtf8));
249 }
250#endif
251
253 return std::make_unique<ParagraphImpl>(
255}
256
258 this->finalize();
259 return SkSpan<char>(fUtf8.isEmpty() ? nullptr : fUtf8.data(), fUtf8.size());
260}
261
265
266void ParagraphBuilderImpl::ensureUTF16Mapping() {
267 fillUTF16MappingOnce([&] {
269 this->getText(),
270 [&](size_t index) { fUTF8IndexForUTF16Index.emplace_back(index); },
271 [&](size_t index) { fUTF16IndexForUTF8Index.emplace_back(index); });
272 });
273}
274
275#if !defined(SK_DISABLE_LEGACY_CLIENT_UNICODE) && defined(SK_UNICODE_CLIENT_IMPLEMENTATION)
276void ParagraphBuilderImpl::setWordsUtf8(std::vector<SkUnicode::Position> wordsUtf8) {
277 ensureUTF16Mapping();
278 std::vector<SkUnicode::Position> wordsUtf16;
279 for (SkUnicode::Position indexUtf8: wordsUtf8) {
280 wordsUtf16.emplace_back(fUTF16IndexForUTF8Index[indexUtf8]);
281 }
282 setWordsUtf16(wordsUtf16);
283}
284
285void ParagraphBuilderImpl::setWordsUtf16(std::vector<SkUnicode::Position> wordsUtf16) {
286 fUsingClientInfo = true;
287 fWordsUtf16 = std::move(wordsUtf16);
288}
289
290void ParagraphBuilderImpl::setGraphemeBreaksUtf8(std::vector<SkUnicode::Position> graphemeBreaksUtf8) {
291 fUsingClientInfo = true;
292 fGraphemeBreaksUtf8 = std::move(graphemeBreaksUtf8);
293}
294
295void ParagraphBuilderImpl::setGraphemeBreaksUtf16(std::vector<SkUnicode::Position> graphemeBreaksUtf16) {
296 ensureUTF16Mapping();
297 std::vector<SkUnicode::Position> graphemeBreaksUtf8;
298 for (SkUnicode::Position indexUtf16: graphemeBreaksUtf16) {
299 graphemeBreaksUtf8.emplace_back(fUTF8IndexForUTF16Index[indexUtf16]);
300 }
301 setGraphemeBreaksUtf8(graphemeBreaksUtf8);
302}
303
304void ParagraphBuilderImpl::setLineBreaksUtf8(std::vector<SkUnicode::LineBreakBefore> lineBreaksUtf8) {
305 fUsingClientInfo = true;
306 fLineBreaksUtf8 = std::move(lineBreaksUtf8);
307}
308
309void ParagraphBuilderImpl::setLineBreaksUtf16(std::vector<SkUnicode::LineBreakBefore> lineBreaksUtf16) {
310 ensureUTF16Mapping();
311 std::vector<SkUnicode::LineBreakBefore> lineBreaksUtf8;
312 for (SkUnicode::LineBreakBefore lineBreakUtf16: lineBreaksUtf16) {
313 lineBreaksUtf8.emplace_back(SkUnicode::LineBreakBefore(
314 fUTF8IndexForUTF16Index[lineBreakUtf16.pos], lineBreakUtf16.breakType));
315 }
316 setLineBreaksUtf8(lineBreaksUtf8);
317}
318#endif
319
321
322 fTextStyles.clear();
323 fUtf8.reset();
324 fStyledBlocks.clear();
325 fPlaceholders.clear();
326 fUTF8IndexForUTF16Index.clear();
327 fUTF16IndexForUTF8Index.clear();
328#if defined(SK_UNICODE_CLIENT_IMPLEMENTATION)
329 fWordsUtf16.clear();
330 fGraphemeBreaksUtf8.clear();
331 fLineBreaksUtf8.clear();
332 fTextIsFinalized = false;
333#endif
335}
336
338#if defined(SK_UNICODE_CLIENT_IMPLEMENTATION)
339 return true;
340#else
341 return false;
342#endif
343}
344
345} // namespace textlayout
346} // namespace skia
#define SkASSERT_RELEASE(cond)
Definition SkAssert.h:100
#define SkASSERT(cond)
Definition SkAssert.h:116
#define SkDEBUGF(...)
Definition SkDebug.h:24
size_t size() const
Definition SkString.h:131
const char * data() const
Definition SkString.h:132
bool isEmpty() const
Definition SkString.h:130
void append(const char text[])
Definition SkString.h:203
void reset()
Definition SkString.cpp:358
size_t Position
Definition SkUnicode.h:98
static SkString convertUtf16ToUtf8(const char16_t *utf16, int utf16Units)
Definition SkUnicode.cpp:14
static bool extractUtfConversionMapping(SkSpan< const char > utf8, Appender8 &&appender8, Appender16 &&appender16)
Definition SkUnicode.h:193
void addPlaceholder(const PlaceholderStyle &placeholderStyle) override
skia_private::STArray< 4, Block, true > fStyledBlocks
skia_private::STArray< 4, Placeholder, true > fPlaceholders
ParagraphBuilderImpl(const ParagraphStyle &style, sk_sp< FontCollection > fontCollection, sk_sp< SkUnicode > unicode)
void addText(const std::u16string &text) override
const ParagraphStyle & getParagraphStyle() const override
skia_private::STArray< 4, TextStyle, true > fTextStyles
void pushStyle(const TextStyle &style) override
static std::unique_ptr< ParagraphBuilder > make(const ParagraphStyle &style, sk_sp< FontCollection > fontCollection, sk_sp< SkUnicode > unicode)
std::unique_ptr< Paragraph > Build() override
static std::unique_ptr< ParagraphBuilder > make(const ParagraphStyle &style, sk_sp< FontCollection > fontCollection, sk_sp< SkUnicode > unicode)
T & emplace_back(Args &&... args)
Definition SkTArray.h:243
if(end==-1)
glong glong end
std::u16string text
SKUNICODE_API sk_sp< SkUnicode > Make(SkSpan< char > text, std::vector< SkUnicode::Position > words, std::vector< SkUnicode::Position > graphemeBreaks, std::vector< SkUnicode::LineBreakBefore > lineBreaks)
SKUNICODE_API sk_sp< SkUnicode > Make()
SKUNICODE_API sk_sp< SkUnicode > Make()
SKUNICODE_API sk_sp< SkUnicode > Make()
Definition ref_ptr.h:256
static sk_sp< SkUnicode > get_unicode()
const TextStyle & getTextStyle() const