1cb93a386Sopenharmony_ci                                           /*
2cb93a386Sopenharmony_ci* Copyright 2022 Google Inc.
3cb93a386Sopenharmony_ci*
4cb93a386Sopenharmony_ci* Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci* found in the LICENSE file.
6cb93a386Sopenharmony_ci*/
7cb93a386Sopenharmony_ci#include "include/core/SkSpan.h"
8cb93a386Sopenharmony_ci#include "include/core/SkString.h"
9cb93a386Sopenharmony_ci#include "include/core/SkTypes.h"
10cb93a386Sopenharmony_ci#include "include/private/SkBitmaskEnum.h"
11cb93a386Sopenharmony_ci#include "include/private/SkTArray.h"
12cb93a386Sopenharmony_ci#include "include/private/SkTo.h"
13cb93a386Sopenharmony_ci#include "modules/skunicode/include/SkUnicode.h"
14cb93a386Sopenharmony_ci#include "modules/skunicode/src/SkUnicode_client.h"
15cb93a386Sopenharmony_ci#include "modules/skunicode/src/SkUnicode_icu_bidi.h"
16cb93a386Sopenharmony_ci#include "src/utils/SkUTF.h"
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_ci#include <algorithm>
19cb93a386Sopenharmony_ci#include <cstdint>
20cb93a386Sopenharmony_ci#include <memory>
21cb93a386Sopenharmony_ci#include <string>
22cb93a386Sopenharmony_ci#include <utility>
23cb93a386Sopenharmony_ci#include <vector>
24cb93a386Sopenharmony_ci#include <array>
25cb93a386Sopenharmony_ci#include <unicode/ubidi.h>
26cb93a386Sopenharmony_ci#include <unicode/ubrk.h>
27cb93a386Sopenharmony_ci#include <unicode/uchar.h>
28cb93a386Sopenharmony_ci#include <unicode/uloc.h>
29cb93a386Sopenharmony_ci#include <unicode/uscript.h>
30cb93a386Sopenharmony_ci#include <unicode/ustring.h>
31cb93a386Sopenharmony_ci#include <unicode/utext.h>
32cb93a386Sopenharmony_ci#include <unicode/utypes.h>
33cb93a386Sopenharmony_ci
34cb93a386Sopenharmony_ci
35cb93a386Sopenharmony_ci#ifndef SK_UNICODE_ICU_IMPLEMENTATION
36cb93a386Sopenharmony_ci
37cb93a386Sopenharmony_ciconst char* SkUnicode_IcuBidi::errorName(UErrorCode status) {
38cb93a386Sopenharmony_ci    return u_errorName_skia(status);
39cb93a386Sopenharmony_ci}
40cb93a386Sopenharmony_civoid SkUnicode_IcuBidi::bidi_close(UBiDi* bidi) {
41cb93a386Sopenharmony_ci    ubidi_close_skia(bidi);
42cb93a386Sopenharmony_ci}
43cb93a386Sopenharmony_ciUBiDiDirection SkUnicode_IcuBidi::bidi_getDirection(const UBiDi* bidi) {
44cb93a386Sopenharmony_ci    return ubidi_getDirection_skia(bidi);
45cb93a386Sopenharmony_ci}
46cb93a386Sopenharmony_ciSkBidiIterator::Position SkUnicode_IcuBidi::bidi_getLength(const UBiDi* bidi) {
47cb93a386Sopenharmony_ci    return ubidi_getLength_skia(bidi);
48cb93a386Sopenharmony_ci}
49cb93a386Sopenharmony_ciSkBidiIterator::Level SkUnicode_IcuBidi::bidi_getLevelAt(const UBiDi* bidi, int pos) {
50cb93a386Sopenharmony_ci    return ubidi_getLevelAt_skia(bidi, pos);
51cb93a386Sopenharmony_ci}
52cb93a386Sopenharmony_ciUBiDi* SkUnicode_IcuBidi::bidi_openSized(int32_t maxLength, int32_t maxRunCount, UErrorCode* pErrorCode) {
53cb93a386Sopenharmony_ci    return ubidi_openSized_skia(maxLength, maxRunCount, pErrorCode);
54cb93a386Sopenharmony_ci}
55cb93a386Sopenharmony_civoid SkUnicode_IcuBidi::bidi_setPara(UBiDi* bidi,
56cb93a386Sopenharmony_ci                         const UChar* text,
57cb93a386Sopenharmony_ci                         int32_t length,
58cb93a386Sopenharmony_ci                         UBiDiLevel paraLevel,
59cb93a386Sopenharmony_ci                         UBiDiLevel* embeddingLevels,
60cb93a386Sopenharmony_ci                         UErrorCode* status) {
61cb93a386Sopenharmony_ci    return ubidi_setPara_skia(bidi, text, length, paraLevel, embeddingLevels, status);
62cb93a386Sopenharmony_ci}
63cb93a386Sopenharmony_civoid SkUnicode_IcuBidi::bidi_reorderVisual(const SkUnicode::BidiLevel runLevels[],
64cb93a386Sopenharmony_ci                               int levelsCount,
65cb93a386Sopenharmony_ci                               int32_t logicalFromVisual[]) {
66cb93a386Sopenharmony_ci    ubidi_reorderVisual_skia(runLevels, levelsCount, logicalFromVisual);
67cb93a386Sopenharmony_ci}
68cb93a386Sopenharmony_ci#endif
69cb93a386Sopenharmony_ci
70cb93a386Sopenharmony_ciclass SkUnicode_client : public SkUnicode {
71cb93a386Sopenharmony_cipublic:
72cb93a386Sopenharmony_ci    struct Data {
73cb93a386Sopenharmony_ci        SkSpan<const char> fText8;
74cb93a386Sopenharmony_ci        SkSpan<const char16_t> fText16;
75cb93a386Sopenharmony_ci        std::vector<Position> fWords;
76cb93a386Sopenharmony_ci        std::vector<SkUnicode::Position> fGraphemeBreaks;
77cb93a386Sopenharmony_ci        std::vector<SkUnicode::LineBreakBefore> fLineBreaks;
78cb93a386Sopenharmony_ci        Data(SkSpan<char> text,
79cb93a386Sopenharmony_ci             std::vector<SkUnicode::Position> words,
80cb93a386Sopenharmony_ci             std::vector<SkUnicode::Position> graphemeBreaks,
81cb93a386Sopenharmony_ci             std::vector<SkUnicode::LineBreakBefore> lineBreaks)
82cb93a386Sopenharmony_ci            : fText8(text)
83cb93a386Sopenharmony_ci            , fText16(SkSpan<const char16_t>(nullptr, 0))
84cb93a386Sopenharmony_ci            , fWords(std::move(words))
85cb93a386Sopenharmony_ci            , fGraphemeBreaks(std::move(graphemeBreaks))
86cb93a386Sopenharmony_ci            , fLineBreaks(std::move(lineBreaks)) {
87cb93a386Sopenharmony_ci        }
88cb93a386Sopenharmony_ci
89cb93a386Sopenharmony_ci        void reset() {
90cb93a386Sopenharmony_ci            fText8 = SkSpan<const char>(nullptr, 0);
91cb93a386Sopenharmony_ci            fText16 = SkSpan<const char16_t>(nullptr, 0);
92cb93a386Sopenharmony_ci            fGraphemeBreaks.clear();
93cb93a386Sopenharmony_ci            fLineBreaks.clear();
94cb93a386Sopenharmony_ci        }
95cb93a386Sopenharmony_ci    };
96cb93a386Sopenharmony_ci    SkUnicode_client() = delete;
97cb93a386Sopenharmony_ci    SkUnicode_client(SkSpan<char> text,
98cb93a386Sopenharmony_ci                     std::vector<SkUnicode::Position> words,
99cb93a386Sopenharmony_ci                     std::vector<SkUnicode::Position> graphemeBreaks,
100cb93a386Sopenharmony_ci                     std::vector<SkUnicode::LineBreakBefore> lineBreaks)
101cb93a386Sopenharmony_ci            : fData(std::make_shared<Data>(text,
102cb93a386Sopenharmony_ci                                           std::move(words),
103cb93a386Sopenharmony_ci                                           std::move(graphemeBreaks),
104cb93a386Sopenharmony_ci                                           std::move(lineBreaks))) { }
105cb93a386Sopenharmony_ci    SkUnicode_client(const SkUnicode_client* origin)
106cb93a386Sopenharmony_ci            : fData(origin->fData) {}
107cb93a386Sopenharmony_ci
108cb93a386Sopenharmony_ci
109cb93a386Sopenharmony_ci    std::unique_ptr<SkUnicode> copy() override {
110cb93a386Sopenharmony_ci        return std::make_unique<SkUnicode_client>(this);
111cb93a386Sopenharmony_ci    }
112cb93a386Sopenharmony_ci
113cb93a386Sopenharmony_ci    ~SkUnicode_client() override = default;
114cb93a386Sopenharmony_ci
115cb93a386Sopenharmony_ci    void reset() { fData->reset(); }
116cb93a386Sopenharmony_ci    // For SkShaper
117cb93a386Sopenharmony_ci    std::unique_ptr<SkBidiIterator> makeBidiIterator(const uint16_t text[], int count,
118cb93a386Sopenharmony_ci                                                     SkBidiIterator::Direction dir) override;
119cb93a386Sopenharmony_ci    std::unique_ptr<SkBidiIterator> makeBidiIterator(const char text[],
120cb93a386Sopenharmony_ci                                                     int count,
121cb93a386Sopenharmony_ci                                                     SkBidiIterator::Direction dir) override;
122cb93a386Sopenharmony_ci    std::unique_ptr<SkBreakIterator> makeBreakIterator(const char locale[],
123cb93a386Sopenharmony_ci                                                       BreakType breakType) override;
124cb93a386Sopenharmony_ci    std::unique_ptr<SkBreakIterator> makeBreakIterator(BreakType breakType) override;
125cb93a386Sopenharmony_ci    // For SkParagraph
126cb93a386Sopenharmony_ci    bool getBidiRegions(const char utf8[],
127cb93a386Sopenharmony_ci                        int utf8Units,
128cb93a386Sopenharmony_ci                        TextDirection dir,
129cb93a386Sopenharmony_ci                        std::vector<BidiRegion>* results) override {
130cb93a386Sopenharmony_ci        return SkUnicode::extractBidi(utf8, utf8Units, dir, results);
131cb93a386Sopenharmony_ci    }
132cb93a386Sopenharmony_ci
133cb93a386Sopenharmony_ci    // TODO: Take if from the Client or hard code here?
134cb93a386Sopenharmony_ci    static bool isControl(SkUnichar utf8) {
135cb93a386Sopenharmony_ci        return (utf8 < ' ') || (utf8 >= 0x7f && utf8 <= 0x9f) ||
136cb93a386Sopenharmony_ci               (utf8 >= 0x200D && utf8 <= 0x200F) ||
137cb93a386Sopenharmony_ci               (utf8 >= 0x202A && utf8 <= 0x202E);
138cb93a386Sopenharmony_ci    }
139cb93a386Sopenharmony_ci
140cb93a386Sopenharmony_ci    static bool isWhitespace(SkUnichar unichar) {
141cb93a386Sopenharmony_ci        static constexpr std::array<SkUnichar, 21> whitespaces {
142cb93a386Sopenharmony_ci                0x0009, // character tabulation
143cb93a386Sopenharmony_ci                0x000A, // line feed
144cb93a386Sopenharmony_ci                0x000B, // line tabulation
145cb93a386Sopenharmony_ci                0x000C, // form feed
146cb93a386Sopenharmony_ci                0x000D, // carriage return
147cb93a386Sopenharmony_ci                0x0020, // space
148cb93a386Sopenharmony_ci              //0x0085, // next line
149cb93a386Sopenharmony_ci              //0x00A0, // no-break space
150cb93a386Sopenharmony_ci                0x1680, // ogham space mark
151cb93a386Sopenharmony_ci                0x2000, // en quad
152cb93a386Sopenharmony_ci                0x2001, // em quad
153cb93a386Sopenharmony_ci                0x2002, // en space
154cb93a386Sopenharmony_ci                0x2003, // em space
155cb93a386Sopenharmony_ci                0x2004, // three-per-em space
156cb93a386Sopenharmony_ci                0x2005, // four-per-em space
157cb93a386Sopenharmony_ci                0x2006, // six-per-em space
158cb93a386Sopenharmony_ci              //0x2007, // figure space
159cb93a386Sopenharmony_ci                0x2008, // punctuation space
160cb93a386Sopenharmony_ci                0x2009, // thin space
161cb93a386Sopenharmony_ci                0x200A, // hair space
162cb93a386Sopenharmony_ci                0x2028, // line separator
163cb93a386Sopenharmony_ci                0x2029, // paragraph separator
164cb93a386Sopenharmony_ci              //0x202F, // narrow no-break space
165cb93a386Sopenharmony_ci                0x205F, // medium mathematical space
166cb93a386Sopenharmony_ci                0x3000};// ideographic space
167cb93a386Sopenharmony_ci        return std::find(whitespaces.begin(), whitespaces.end(), unichar) != whitespaces.end();
168cb93a386Sopenharmony_ci    }
169cb93a386Sopenharmony_ci
170cb93a386Sopenharmony_ci    static bool isSpace(SkUnichar unichar) {
171cb93a386Sopenharmony_ci        static constexpr std::array<SkUnichar, 25> spaces {
172cb93a386Sopenharmony_ci                0x0009, // character tabulation
173cb93a386Sopenharmony_ci                0x000A, // line feed
174cb93a386Sopenharmony_ci                0x000B, // line tabulation
175cb93a386Sopenharmony_ci                0x000C, // form feed
176cb93a386Sopenharmony_ci                0x000D, // carriage return
177cb93a386Sopenharmony_ci                0x0020, // space
178cb93a386Sopenharmony_ci                0x0085, // next line
179cb93a386Sopenharmony_ci                0x00A0, // no-break space
180cb93a386Sopenharmony_ci                0x1680, // ogham space mark
181cb93a386Sopenharmony_ci                0x2000, // en quad
182cb93a386Sopenharmony_ci                0x2001, // em quad
183cb93a386Sopenharmony_ci                0x2002, // en space
184cb93a386Sopenharmony_ci                0x2003, // em space
185cb93a386Sopenharmony_ci                0x2004, // three-per-em space
186cb93a386Sopenharmony_ci                0x2005, // four-per-em space
187cb93a386Sopenharmony_ci                0x2006, // six-per-em space
188cb93a386Sopenharmony_ci                0x2007, // figure space
189cb93a386Sopenharmony_ci                0x2008, // punctuation space
190cb93a386Sopenharmony_ci                0x2009, // thin space
191cb93a386Sopenharmony_ci                0x200A, // hair space
192cb93a386Sopenharmony_ci                0x2028, // line separator
193cb93a386Sopenharmony_ci                0x2029, // paragraph separator
194cb93a386Sopenharmony_ci                0x202F, // narrow no-break space
195cb93a386Sopenharmony_ci                0x205F, // medium mathematical space
196cb93a386Sopenharmony_ci                0x3000}; // ideographic space
197cb93a386Sopenharmony_ci        return std::find(spaces.begin(), spaces.end(), unichar) != spaces.end();
198cb93a386Sopenharmony_ci    }
199cb93a386Sopenharmony_ci
200cb93a386Sopenharmony_ci    static bool isTabulation(SkUnichar utf8) {
201cb93a386Sopenharmony_ci        return utf8 == '\t';
202cb93a386Sopenharmony_ci    }
203cb93a386Sopenharmony_ci
204cb93a386Sopenharmony_ci    static bool isHardBreak(SkUnichar utf8) {
205cb93a386Sopenharmony_ci        return utf8 == '\n';
206cb93a386Sopenharmony_ci    }
207cb93a386Sopenharmony_ci
208cb93a386Sopenharmony_ci    static bool isIdeographic(SkUnichar unichar) {
209cb93a386Sopenharmony_ci        static constexpr std::array<std::pair<SkUnichar, SkUnichar>, 8> ranges {{
210cb93a386Sopenharmony_ci            {4352,   4607}, // Hangul Jamo
211cb93a386Sopenharmony_ci            {11904, 42191}, // CJK_Radicals
212cb93a386Sopenharmony_ci            {43072, 43135}, // Phags_Pa
213cb93a386Sopenharmony_ci            {44032, 55215}, // Hangul_Syllables
214cb93a386Sopenharmony_ci            {63744, 64255}, // CJK_Compatibility_Ideographs
215cb93a386Sopenharmony_ci            {65072, 65103}, // CJK_Compatibility_Forms
216cb93a386Sopenharmony_ci            {65381, 65500}, // Katakana_Hangul_Halfwidth
217cb93a386Sopenharmony_ci            {131072, 196607} // Supplementary_Ideographic_Plane
218cb93a386Sopenharmony_ci        }};
219cb93a386Sopenharmony_ci        for (auto range : ranges) {
220cb93a386Sopenharmony_ci            if (range.first <= unichar && range.second > unichar) {
221cb93a386Sopenharmony_ci                return true;
222cb93a386Sopenharmony_ci            }
223cb93a386Sopenharmony_ci        }
224cb93a386Sopenharmony_ci        return false;
225cb93a386Sopenharmony_ci    }
226cb93a386Sopenharmony_ci
227cb93a386Sopenharmony_ci    bool computeCodeUnitFlags(char utf8[],
228cb93a386Sopenharmony_ci                              int utf8Units,
229cb93a386Sopenharmony_ci                              bool replaceTabs,
230cb93a386Sopenharmony_ci                              SkTArray<SkUnicode::CodeUnitFlags, true>* results) override {
231cb93a386Sopenharmony_ci        results->clear();
232cb93a386Sopenharmony_ci        results->push_back_n(utf8Units + 1, CodeUnitFlags::kNoCodeUnitFlag);
233cb93a386Sopenharmony_ci        for (auto& lineBreak : fData->fLineBreaks) {
234cb93a386Sopenharmony_ci            (*results)[lineBreak.pos] |=
235cb93a386Sopenharmony_ci                lineBreak.breakType == LineBreakType::kHardLineBreak
236cb93a386Sopenharmony_ci                    ? CodeUnitFlags::kHardLineBreakBefore
237cb93a386Sopenharmony_ci                    : CodeUnitFlags::kSoftLineBreakBefore;
238cb93a386Sopenharmony_ci        }
239cb93a386Sopenharmony_ci        for (auto& grapheme : fData->fGraphemeBreaks) {
240cb93a386Sopenharmony_ci            (*results)[grapheme] |= CodeUnitFlags::kGraphemeStart;
241cb93a386Sopenharmony_ci        }
242cb93a386Sopenharmony_ci        const char* current = utf8;
243cb93a386Sopenharmony_ci        const char* end = utf8 + utf8Units;
244cb93a386Sopenharmony_ci        while (current < end) {
245cb93a386Sopenharmony_ci            auto before = current - utf8;
246cb93a386Sopenharmony_ci            SkUnichar unichar = SkUTF::NextUTF8(&current, end);
247cb93a386Sopenharmony_ci            if (unichar < 0) unichar = 0xFFFD;
248cb93a386Sopenharmony_ci            auto after = current - utf8;
249cb93a386Sopenharmony_ci            if (replaceTabs && SkUnicode_client::isTabulation(unichar)) {
250cb93a386Sopenharmony_ci                results->at(before) |= SkUnicode::kTabulation;
251cb93a386Sopenharmony_ci                if (replaceTabs) {
252cb93a386Sopenharmony_ci                    unichar = ' ';
253cb93a386Sopenharmony_ci                    utf8[before] = ' ';
254cb93a386Sopenharmony_ci                }
255cb93a386Sopenharmony_ci            }
256cb93a386Sopenharmony_ci            for (auto i = before; i < after; ++i) {
257cb93a386Sopenharmony_ci                if (SkUnicode_client::isSpace(unichar)) {
258cb93a386Sopenharmony_ci                    results->at(i) |= SkUnicode::kPartOfIntraWordBreak;
259cb93a386Sopenharmony_ci                }
260cb93a386Sopenharmony_ci                if (SkUnicode_client::isWhitespace(unichar)) {
261cb93a386Sopenharmony_ci                    results->at(i) |= SkUnicode::kPartOfWhiteSpaceBreak;
262cb93a386Sopenharmony_ci                }
263cb93a386Sopenharmony_ci                if (SkUnicode_client::isControl(unichar)) {
264cb93a386Sopenharmony_ci                    results->at(i) |= SkUnicode::kControl;
265cb93a386Sopenharmony_ci                }
266cb93a386Sopenharmony_ci                if (SkUnicode_client::isIdeographic(unichar)) {
267cb93a386Sopenharmony_ci                    results->at(i) |= SkUnicode::kIdeographic;
268cb93a386Sopenharmony_ci                }
269cb93a386Sopenharmony_ci            }
270cb93a386Sopenharmony_ci        }
271cb93a386Sopenharmony_ci        return true;
272cb93a386Sopenharmony_ci    }
273cb93a386Sopenharmony_ci
274cb93a386Sopenharmony_ci    bool computeCodeUnitFlags(char16_t utf16[], int utf16Units, bool replaceTabs,
275cb93a386Sopenharmony_ci                          SkTArray<SkUnicode::CodeUnitFlags, true>* results) override {
276cb93a386Sopenharmony_ci        results->clear();
277cb93a386Sopenharmony_ci        results->push_back_n(utf16Units + 1, CodeUnitFlags::kNoCodeUnitFlag);
278cb93a386Sopenharmony_ci        for (auto& lineBreak : fData->fLineBreaks) {
279cb93a386Sopenharmony_ci            (*results)[lineBreak.pos] |=
280cb93a386Sopenharmony_ci                lineBreak.breakType == LineBreakType::kHardLineBreak
281cb93a386Sopenharmony_ci                    ? CodeUnitFlags::kHardLineBreakBefore
282cb93a386Sopenharmony_ci                    : CodeUnitFlags::kSoftLineBreakBefore;
283cb93a386Sopenharmony_ci        }
284cb93a386Sopenharmony_ci        for (auto& grapheme : fData->fGraphemeBreaks) {
285cb93a386Sopenharmony_ci            (*results)[grapheme] |= CodeUnitFlags::kGraphemeStart;
286cb93a386Sopenharmony_ci        }
287cb93a386Sopenharmony_ci        return true;
288cb93a386Sopenharmony_ci    }
289cb93a386Sopenharmony_ci
290cb93a386Sopenharmony_ci    bool getWords(const char utf8[], int utf8Units, const char* locale, std::vector<Position>* results) override {
291cb93a386Sopenharmony_ci        *results = fData->fWords;
292cb93a386Sopenharmony_ci        return true;
293cb93a386Sopenharmony_ci    }
294cb93a386Sopenharmony_ci
295cb93a386Sopenharmony_ci    SkString toUpper(const SkString& str) override {
296cb93a386Sopenharmony_ci        SkASSERT(false);
297cb93a386Sopenharmony_ci        return SkString(fData->fText8.data(), fData->fText8.size());
298cb93a386Sopenharmony_ci    }
299cb93a386Sopenharmony_ci
300cb93a386Sopenharmony_ci    void reorderVisual(const BidiLevel runLevels[],
301cb93a386Sopenharmony_ci                       int levelsCount,
302cb93a386Sopenharmony_ci                       int32_t logicalFromVisual[]) override {
303cb93a386Sopenharmony_ci        SkUnicode_IcuBidi::bidi_reorderVisual(runLevels, levelsCount, logicalFromVisual);
304cb93a386Sopenharmony_ci    }
305cb93a386Sopenharmony_ciprivate:
306cb93a386Sopenharmony_ci    friend class SkBreakIterator_client;
307cb93a386Sopenharmony_ci
308cb93a386Sopenharmony_ci    std::shared_ptr<Data> fData;
309cb93a386Sopenharmony_ci};
310cb93a386Sopenharmony_ci
311cb93a386Sopenharmony_ciclass SkBreakIterator_client: public SkBreakIterator {
312cb93a386Sopenharmony_ci    std::shared_ptr<SkUnicode_client::Data> fData;
313cb93a386Sopenharmony_ci    Position fLastResult;
314cb93a386Sopenharmony_ci    Position fStart;
315cb93a386Sopenharmony_ci    Position fEnd;
316cb93a386Sopenharmony_cipublic:
317cb93a386Sopenharmony_ci    explicit SkBreakIterator_client(std::shared_ptr<SkUnicode_client::Data> data) : fData(data) { }
318cb93a386Sopenharmony_ci    Position first() override
319cb93a386Sopenharmony_ci      { return fData->fLineBreaks[fStart + (fLastResult = 0)].pos; }
320cb93a386Sopenharmony_ci    Position current() override
321cb93a386Sopenharmony_ci      { return fData->fLineBreaks[fStart + fLastResult].pos; }
322cb93a386Sopenharmony_ci    Position next() override
323cb93a386Sopenharmony_ci      { return fData->fLineBreaks[fStart + fLastResult + 1].pos; }
324cb93a386Sopenharmony_ci    Status status() override {
325cb93a386Sopenharmony_ci        return fData->fLineBreaks[fStart + fLastResult].breakType ==
326cb93a386Sopenharmony_ci                       SkUnicode::LineBreakType::kHardLineBreak
327cb93a386Sopenharmony_ci                       ? SkUnicode::CodeUnitFlags::kHardLineBreakBefore
328cb93a386Sopenharmony_ci                       : SkUnicode::CodeUnitFlags::kSoftLineBreakBefore;
329cb93a386Sopenharmony_ci    }
330cb93a386Sopenharmony_ci    bool isDone() override { return fStart + fLastResult == fEnd; }
331cb93a386Sopenharmony_ci    bool setText(const char utftext8[], int utf8Units) override {
332cb93a386Sopenharmony_ci        SkASSERT(utftext8 >= fData->fText8.data() &&
333cb93a386Sopenharmony_ci                 utf8Units <= SkToS16(fData->fText8.size()));
334cb93a386Sopenharmony_ci        fStart = utftext8 - fData->fText8.data();
335cb93a386Sopenharmony_ci        fEnd = fStart + utf8Units;
336cb93a386Sopenharmony_ci        fLastResult = 0;
337cb93a386Sopenharmony_ci        return true;
338cb93a386Sopenharmony_ci    }
339cb93a386Sopenharmony_ci    bool setText(const char16_t utftext16[], int utf16Units) override {
340cb93a386Sopenharmony_ci        SkASSERT(utftext16 >= fData->fText16.data() &&
341cb93a386Sopenharmony_ci                 utf16Units <= SkToS16(fData->fText16.size()));
342cb93a386Sopenharmony_ci        fStart = utftext16 - fData->fText16.data();
343cb93a386Sopenharmony_ci        fEnd = fStart + utf16Units;
344cb93a386Sopenharmony_ci        fLastResult = 0;
345cb93a386Sopenharmony_ci        return true;
346cb93a386Sopenharmony_ci    }
347cb93a386Sopenharmony_ci};
348cb93a386Sopenharmony_cistd::unique_ptr<SkBidiIterator> SkUnicode_client::makeBidiIterator(const uint16_t text[], int count,
349cb93a386Sopenharmony_ci                                                 SkBidiIterator::Direction dir) {
350cb93a386Sopenharmony_ci    return SkUnicode::makeBidiIterator(text, count, dir);
351cb93a386Sopenharmony_ci}
352cb93a386Sopenharmony_cistd::unique_ptr<SkBidiIterator> SkUnicode_client::makeBidiIterator(const char text[],
353cb93a386Sopenharmony_ci                                                 int count,
354cb93a386Sopenharmony_ci                                                 SkBidiIterator::Direction dir) {
355cb93a386Sopenharmony_ci    return SkUnicode::makeBidiIterator(text, count, dir);
356cb93a386Sopenharmony_ci}
357cb93a386Sopenharmony_cistd::unique_ptr<SkBreakIterator> SkUnicode_client::makeBreakIterator(const char locale[],
358cb93a386Sopenharmony_ci                                                   BreakType breakType) {
359cb93a386Sopenharmony_ci    return std::make_unique<SkBreakIterator_client>(fData);
360cb93a386Sopenharmony_ci}
361cb93a386Sopenharmony_cistd::unique_ptr<SkBreakIterator> SkUnicode_client::makeBreakIterator(BreakType breakType) {
362cb93a386Sopenharmony_ci    return std::make_unique<SkBreakIterator_client>(fData);
363cb93a386Sopenharmony_ci}
364cb93a386Sopenharmony_ci
365cb93a386Sopenharmony_cistd::unique_ptr<SkUnicode> SkUnicode::MakeClientBasedUnicode(
366cb93a386Sopenharmony_ci        SkSpan<char> text,
367cb93a386Sopenharmony_ci        std::vector<SkUnicode::Position> words,
368cb93a386Sopenharmony_ci        std::vector<SkUnicode::Position> graphemeBreaks,
369cb93a386Sopenharmony_ci        std::vector<SkUnicode::LineBreakBefore> lineBreaks) {
370cb93a386Sopenharmony_ci    return std::make_unique<SkUnicode_client>(text, words, graphemeBreaks, lineBreaks);
371cb93a386Sopenharmony_ci}
372cb93a386Sopenharmony_ci
373