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