Flutter Engine
The Flutter Engine
SkUnicode_client.cpp
Go to the documentation of this file.
1/*
2* Copyright 2022 Google Inc.
3*
4* Use of this source code is governed by a BSD-style license that can be
5* found in the LICENSE file.
6*/
8
19#include "src/base/SkUTF.h"
20
21#include <algorithm>
22#include <cstdint>
23#include <memory>
24#include <string>
25#include <utility>
26#include <vector>
27#include <array>
28#include <unicode/ubidi.h>
29#include <unicode/ubrk.h>
30#include <unicode/uchar.h>
31#include <unicode/uloc.h>
32#include <unicode/uscript.h>
33#include <unicode/ustring.h>
34#include <unicode/utext.h>
35#include <unicode/utypes.h>
36
37using namespace skia_private;
38
40public:
41 struct Data {
44 std::vector<Position> fWords;
45 std::vector<SkUnicode::Position> fGraphemeBreaks;
46 std::vector<SkUnicode::LineBreakBefore> fLineBreaks;
48 std::vector<SkUnicode::Position> words,
49 std::vector<SkUnicode::Position> graphemeBreaks,
50 std::vector<SkUnicode::LineBreakBefore> lineBreaks)
51 : fText8(text)
52 , fText16(SkSpan<const char16_t>(nullptr, 0))
53 , fWords(std::move(words))
54 , fGraphemeBreaks(std::move(graphemeBreaks))
55 , fLineBreaks(std::move(lineBreaks)) {
56 }
57
58 void reset() {
59 fText8 = SkSpan<const char>(nullptr, 0);
60 fText16 = SkSpan<const char16_t>(nullptr, 0);
61 fGraphemeBreaks.clear();
62 fLineBreaks.clear();
63 }
64 };
65 SkUnicode_client() = delete;
67 std::vector<SkUnicode::Position> words,
68 std::vector<SkUnicode::Position> graphemeBreaks,
69 std::vector<SkUnicode::LineBreakBefore> lineBreaks)
70 : fData(std::make_shared<Data>(text,
71 std::move(words),
72 std::move(graphemeBreaks),
73 std::move(lineBreaks))) { }
74
75 ~SkUnicode_client() override = default;
76
77 void reset() { fData->reset(); }
78 // For SkShaper
79 std::unique_ptr<SkBidiIterator> makeBidiIterator(const uint16_t text[], int count,
81 std::unique_ptr<SkBidiIterator> makeBidiIterator(const char text[],
82 int count,
84 std::unique_ptr<SkBreakIterator> makeBreakIterator(const char locale[],
85 BreakType breakType) override;
86 std::unique_ptr<SkBreakIterator> makeBreakIterator(BreakType breakType) override;
87 // For SkParagraph
88 bool getBidiRegions(const char utf8[],
89 int utf8Units,
91 std::vector<BidiRegion>* results) override {
92 return fBidiFact->ExtractBidi(utf8, utf8Units, dir, results);
93 }
94
95 bool getUtf8Words(const char utf8[],
96 int utf8Units,
97 const char* locale,
98 std::vector<Position>* results) override {
99 SkDEBUGF("Method 'getUtf8Words' is not implemented\n");
100 return false;
101 }
102
103 bool getSentences(const char utf8[],
104 int utf8Units,
105 const char* locale,
106 std::vector<SkUnicode::Position>* results) override {
107 SkDEBUGF("Method 'getSentences' is not implemented\n");
108 return false;
109 }
110
112 int utf8Units,
113 bool replaceTabs,
114 TArray<SkUnicode::CodeUnitFlags, true>* results) override {
115 results->clear();
116 results->push_back_n(utf8Units + 1, CodeUnitFlags::kNoCodeUnitFlag);
117 for (auto& lineBreak : fData->fLineBreaks) {
118 (*results)[lineBreak.pos] |=
119 lineBreak.breakType == LineBreakType::kHardLineBreak
120 ? CodeUnitFlags::kHardLineBreakBefore
121 : CodeUnitFlags::kSoftLineBreakBefore;
122 }
123 for (auto& grapheme : fData->fGraphemeBreaks) {
124 (*results)[grapheme] |= CodeUnitFlags::kGraphemeStart;
125 }
126 const char* current = utf8;
127 const char* end = utf8 + utf8Units;
128 while (current < end) {
129 auto before = current - utf8;
130 SkUnichar unichar = SkUTF::NextUTF8(&current, end);
131 if (unichar < 0) unichar = 0xFFFD;
132 auto after = current - utf8;
133 if (replaceTabs && this->isTabulation(unichar)) {
134 results->at(before) |= SkUnicode::kTabulation;
135 if (replaceTabs) {
136 unichar = ' ';
137 utf8[before] = ' ';
138 }
139 }
140 for (auto i = before; i < after; ++i) {
141 if (this->isSpace(unichar)) {
143 }
144 if (this->isWhitespace(unichar)) {
146 }
147 if (this->isControl(unichar)) {
148 results->at(i) |= SkUnicode::kControl;
149 }
150 }
151 }
152 return true;
153 }
154
155 bool computeCodeUnitFlags(char16_t utf16[], int utf16Units, bool replaceTabs,
156 TArray<SkUnicode::CodeUnitFlags, true>* results) override {
157 results->clear();
158 results->push_back_n(utf16Units + 1, CodeUnitFlags::kNoCodeUnitFlag);
159 for (auto& lineBreak : fData->fLineBreaks) {
160 (*results)[lineBreak.pos] |=
161 lineBreak.breakType == LineBreakType::kHardLineBreak
162 ? CodeUnitFlags::kHardLineBreakBefore
163 : CodeUnitFlags::kSoftLineBreakBefore;
164 }
165 for (auto& grapheme : fData->fGraphemeBreaks) {
166 (*results)[grapheme] |= CodeUnitFlags::kGraphemeStart;
167 }
168 return true;
169 }
170
171 bool getWords(const char utf8[], int utf8Units, const char* locale, std::vector<Position>* results) override {
172 *results = fData->fWords;
173 return true;
174 }
175
176 SkString toUpper(const SkString& str) override {
177 return this->toUpper(str, nullptr);
178 }
179
180 SkString toUpper(const SkString& str, const char* locale) override {
181 return SkString(fData->fText8.data(), fData->fText8.size());
182 }
183
184 void reorderVisual(const BidiLevel runLevels[],
185 int levelsCount,
186 int32_t logicalFromVisual[]) override {
187 fBidiFact->bidi_reorderVisual(runLevels, levelsCount, logicalFromVisual);
188 }
189private:
191
192 std::shared_ptr<Data> fData;
193 sk_sp<SkBidiFactory> fBidiFact = sk_make_sp<SkBidiSubsetFactory>();
194};
195
197 std::shared_ptr<SkUnicode_client::Data> fData;
198 Position fLastResult;
199 Position fStart;
200 Position fEnd;
201public:
202 explicit SkBreakIterator_client(std::shared_ptr<SkUnicode_client::Data> data) : fData(data) { }
203 Position first() override
204 { return fData->fLineBreaks[fStart + (fLastResult = 0)].pos; }
205 Position current() override
206 { return fData->fLineBreaks[fStart + fLastResult].pos; }
207 Position next() override
208 { return fData->fLineBreaks[fStart + fLastResult + 1].pos; }
209 Status status() override {
210 return fData->fLineBreaks[fStart + fLastResult].breakType ==
212 ? SkUnicode::CodeUnitFlags::kHardLineBreakBefore
213 : SkUnicode::CodeUnitFlags::kSoftLineBreakBefore;
214 }
215 bool isDone() override { return fStart + fLastResult == fEnd; }
216 bool setText(const char utftext8[], int utf8Units) override {
217 SkASSERT(utftext8 >= fData->fText8.data() &&
218 utf8Units <= SkToS16(fData->fText8.size()));
219 fStart = utftext8 - fData->fText8.data();
220 fEnd = fStart + utf8Units;
221 fLastResult = 0;
222 return true;
223 }
224 bool setText(const char16_t utftext16[], int utf16Units) override {
225 SkASSERT(utftext16 >= fData->fText16.data() &&
226 utf16Units <= SkToS16(fData->fText16.size()));
227 fStart = utftext16 - fData->fText16.data();
228 fEnd = fStart + utf16Units;
229 fLastResult = 0;
230 return true;
231 }
232};
233std::unique_ptr<SkBidiIterator> SkUnicode_client::makeBidiIterator(const uint16_t text[], int count,
235 return fBidiFact->MakeIterator(text, count, dir);
236}
237std::unique_ptr<SkBidiIterator> SkUnicode_client::makeBidiIterator(const char text[],
238 int count,
240 return fBidiFact->MakeIterator(text, count, dir);
241}
242std::unique_ptr<SkBreakIterator> SkUnicode_client::makeBreakIterator(const char locale[],
243 BreakType breakType) {
244 return std::make_unique<SkBreakIterator_client>(fData);
245}
246std::unique_ptr<SkBreakIterator> SkUnicode_client::makeBreakIterator(BreakType breakType) {
247 return std::make_unique<SkBreakIterator_client>(fData);
248}
249
250namespace SkUnicodes::Client {
253 std::vector<SkUnicode::Position> words,
254 std::vector<SkUnicode::Position> graphemeBreaks,
255 std::vector<SkUnicode::LineBreakBefore> lineBreaks) {
256 return sk_make_sp<SkUnicode_client>(text,
257 std::move(words),
258 std::move(graphemeBreaks),
259 std::move(lineBreaks));
260}
261}
262
263
int count
Definition: FontMgrTest.cpp:50
SkPoint pos
#define SkASSERT(cond)
Definition: SkAssert.h:116
#define SkDEBUGF(...)
Definition: SkDebug.h:24
constexpr int16_t SkToS16(S x)
Definition: SkTo.h:23
int32_t SkUnichar
Definition: SkTypes.h:175
bool ExtractBidi(const char utf8[], int utf8Units, SkUnicode::TextDirection dir, std::vector< SkUnicode::BidiRegion > *bidiRegions) const
virtual void bidi_reorderVisual(const SkUnicode::BidiLevel runLevels[], int levelsCount, int32_t logicalFromVisual[]) const =0
std::unique_ptr< SkBidiIterator > MakeIterator(const uint16_t utf16[], int utf16Units, SkBidiIterator::Direction dir) const
SkBreakIterator_client(std::shared_ptr< SkUnicode_client::Data > data)
Status status() override
Position first() override
bool setText(const char16_t utftext16[], int utf16Units) override
Position next() override
bool setText(const char utftext8[], int utf8Units) override
Position current() override
int32_t Position
Definition: SkUnicode.h:65
int32_t Status
Definition: SkUnicode.h:66
bool isTabulation(SkUnichar utf8) override
bool isSpace(SkUnichar utf8) override
bool isControl(SkUnichar utf8) override
bool isWhitespace(SkUnichar utf8) override
bool getBidiRegions(const char utf8[], int utf8Units, TextDirection dir, std::vector< BidiRegion > *results) override
SkUnicode_client(SkSpan< char > text, std::vector< SkUnicode::Position > words, std::vector< SkUnicode::Position > graphemeBreaks, std::vector< SkUnicode::LineBreakBefore > lineBreaks)
void reorderVisual(const BidiLevel runLevels[], int levelsCount, int32_t logicalFromVisual[]) override
std::unique_ptr< SkBidiIterator > makeBidiIterator(const uint16_t text[], int count, SkBidiIterator::Direction dir) override
SkString toUpper(const SkString &str, const char *locale) override
bool getSentences(const char utf8[], int utf8Units, const char *locale, std::vector< SkUnicode::Position > *results) override
SkUnicode_client()=delete
~SkUnicode_client() override=default
SkString toUpper(const SkString &str) override
bool computeCodeUnitFlags(char utf8[], int utf8Units, bool replaceTabs, TArray< SkUnicode::CodeUnitFlags, true > *results) override
bool computeCodeUnitFlags(char16_t utf16[], int utf16Units, bool replaceTabs, TArray< SkUnicode::CodeUnitFlags, true > *results) override
bool getUtf8Words(const char utf8[], int utf8Units, const char *locale, std::vector< Position > *results) override
std::unique_ptr< SkBreakIterator > makeBreakIterator(const char locale[], BreakType breakType) override
bool getWords(const char utf8[], int utf8Units, const char *locale, std::vector< Position > *results) override
uint8_t BidiLevel
Definition: SkUnicode.h:99
@ kPartOfWhiteSpaceBreak
Definition: SkUnicode.h:81
@ kTabulation
Definition: SkUnicode.h:87
@ kControl
Definition: SkUnicode.h:86
@ kPartOfIntraWordBreak
Definition: SkUnicode.h:85
T * push_back_n(int n)
Definition: SkTArray.h:267
glong glong end
std::u16string text
SK_SPI SkUnichar NextUTF8(const char **ptr, const char *end)
Definition: SkUTF.cpp:118
SKUNICODE_API sk_sp< SkUnicode > Make(SkSpan< char > text, std::vector< SkUnicode::Position > words, std::vector< SkUnicode::Position > graphemeBreaks, std::vector< SkUnicode::LineBreakBefore > lineBreaks)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets dir
Definition: switches.h:145
Definition: ref_ptr.h:256
SkSpan< const char16_t > fText16
Data(SkSpan< char > text, std::vector< SkUnicode::Position > words, std::vector< SkUnicode::Position > graphemeBreaks, std::vector< SkUnicode::LineBreakBefore > lineBreaks)
std::vector< Position > fWords
std::vector< SkUnicode::Position > fGraphemeBreaks
SkSpan< const char > fText8
std::vector< SkUnicode::LineBreakBefore > fLineBreaks
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63