42static bool is_one_to_one(
const char utf8[],
size_t utf8Begin,
size_t utf8End,
43 std::vector<uint32_t>& clusters) {
44 size_t lastUtf8Index = utf8End;
46 auto checkCluster = [&](
size_t clusterIndex) {
47 if (clusters[clusterIndex] >= lastUtf8Index) {
50 size_t utf8ClusterSize = lastUtf8Index - clusters[clusterIndex];
54 lastUtf8Index = clusters[clusterIndex];
58 if (clusters.front() <= clusters.back()) {
60 size_t clusterCursor = clusters.size();
61 while (clusterCursor > 0) {
62 if (!checkCluster(--clusterCursor)) {
return false; }
66 size_t clusterCursor = 0;
67 while (clusterCursor < clusters.size()) {
68 if (!checkCluster(clusterCursor++)) {
return false; }
80 info.fFont.getTypeface()->getFamilyName(&fontName);
86 if (
info.fBidiLevel > 0) {
87 std::string bidiType =
info.fBidiLevel % 2 == 0 ?
"left-to-right" :
"right-to-left";
88 std::string bidiOutput = bidiType +
" lvl " + std::to_string(
info.fBidiLevel);
93 std::string utf8{&fUTF8[
info.utf8Range.begin()],
info.utf8Range.size()};
97 for (
auto glyphID : fGlyphs) {
103 for (
auto cluster : fClusters) {
109 info.utf8Range.begin(),
info.utf8Range.end(),
114 this->displayMToN(codePointCount, utf1to1, glyph1to1);
118 if (
info.glyphCount > 1) {
119 fJSONWriter->
beginArray(
"horizontal positions",
false);
120 for (
auto position : fPositions) {
127 for (
size_t i = 1; i <
info.glyphCount; i++) {
128 fJSONWriter->
appendFloat(fPositions[i].fX - fPositions[i-1].fX);
130 SkPoint lastAdvance =
info.fAdvance - (fPositions.back() - fPositions.front());
141 if (clusters.
front() <= clusters.
back()) {
143 size_t glyphStartIndex = 0;
144 for (
size_t glyphEndIndex = 0; glyphEndIndex < clusters.
size(); glyphEndIndex++) {
146 if (clusters[glyphStartIndex] == clusters[glyphEndIndex]) {
continue; }
148 processMToN(glyphStartIndex, glyphEndIndex,
149 clusters[glyphStartIndex], clusters[glyphEndIndex]);
151 glyphStartIndex = glyphEndIndex;
154 processMToN(glyphStartIndex, clusters.
size(), clusters[glyphStartIndex], utf8End);
159 size_t glyphStartIndex = 0;
160 uint32_t utf8EndIndex = utf8End;
161 for (
size_t glyphEndIndex = 0; glyphEndIndex < clusters.
size(); glyphEndIndex++) {
163 if (clusters[glyphStartIndex] == clusters[glyphEndIndex]) {
continue; }
165 processMToN(glyphStartIndex, glyphEndIndex,
166 clusters[glyphStartIndex], utf8EndIndex);
168 utf8EndIndex = clusters[glyphStartIndex];
169 glyphStartIndex = glyphEndIndex;
171 processMToN(glyphStartIndex, clusters.
size(), utf8Begin, clusters[glyphStartIndex-1]);
180 size_t glyphRangeStart, glyphRangeEnd;
181 uint32_t utf8RangeStart, utf8RangeEnd;
183 auto resetRanges = [&]() {
184 glyphRangeStart = std::numeric_limits<size_t>::max();
186 utf8RangeStart = std::numeric_limits<uint32_t>::max();
190 auto checkRangesAndProcess = [&]() {
191 if (glyphRangeStart < glyphRangeEnd) {
192 size_t glyphRangeCount = glyphRangeEnd - glyphRangeStart;
197 processMToN(glyphRangeCount, utf8Span, glyphSpan);
202 auto gatherRuns = [&](
size_t glyphStartIndex,
size_t glyphEndIndex,
203 uint32_t utf8StartIndex, uint32_t utf8EndIndex) {
204 int possibleCount =
SkUTF::CountUTF8(&utf8[utf8StartIndex], utf8EndIndex - utf8StartIndex);
205 if (possibleCount == -1) {
return; }
206 size_t codePointCount = SkTo<size_t>(possibleCount);
207 if (codePointCount == 1 && glyphEndIndex - glyphStartIndex == 1) {
208 glyphRangeStart = std::min(glyphRangeStart, glyphStartIndex);
209 glyphRangeEnd = std::max(glyphRangeEnd, glyphEndIndex );
210 utf8RangeStart = std::min(utf8RangeStart, utf8StartIndex );
211 utf8RangeEnd = std::max(utf8RangeEnd, utf8EndIndex );
213 checkRangesAndProcess();
217 glyphEndIndex - glyphStartIndex};
219 processMToN(codePointCount, utf8Span, glyphSpan);
225 checkRangesAndProcess();
static void VisualizeClusters(const char utf8[], size_t utf8Begin, size_t utf8End, SkSpan< const SkGlyphID > glyphIDs, SkSpan< const uint32_t > clusters, const VisualizeClustersCallback &processMToN)