SkShaperJSONWriter.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*
  2. * Copyright 2019 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. */
  7. #include "src/utils/SkShaperJSONWriter.h"
  8. #include <algorithm>
  9. #include <limits>
  10. #include <string>
  11. #include "src/utils/SkJSONWriter.h"
  12. #include "src/utils/SkUTF.h"
  13. SkShaperJSONWriter::SkShaperJSONWriter(SkJSONWriter* JSONWriter, const char* utf8, size_t size)
  14. : fJSONWriter{JSONWriter}
  15. , fUTF8{utf8, size} {}
  16. void SkShaperJSONWriter::beginLine() { }
  17. void SkShaperJSONWriter::runInfo(const SkShaper::RunHandler::RunInfo& info) { }
  18. void SkShaperJSONWriter::commitRunInfo() { }
  19. SkShaper::RunHandler::Buffer
  20. SkShaperJSONWriter::runBuffer(const SkShaper::RunHandler::RunInfo& info) {
  21. fGlyphs.resize(info.glyphCount);
  22. fPositions.resize(info.glyphCount);
  23. fClusters.resize(info.glyphCount);
  24. return {fGlyphs.data(), fPositions.data(), nullptr, fClusters.data(), {0, 0}};
  25. }
  26. static bool is_one_to_one(const char utf8[], size_t utf8Begin, size_t utf8End,
  27. std::vector<uint32_t>& clusters) {
  28. size_t lastUtf8Index = utf8End;
  29. auto checkCluster = [&](size_t clusterIndex) {
  30. if (clusters[clusterIndex] >= lastUtf8Index) {
  31. return false;
  32. }
  33. size_t utf8ClusterSize = lastUtf8Index - clusters[clusterIndex];
  34. if (SkUTF::CountUTF8(&utf8[clusters[clusterIndex]], utf8ClusterSize) != 1) {
  35. return false;
  36. }
  37. lastUtf8Index = clusters[clusterIndex];
  38. return true;
  39. };
  40. if (clusters.front() <= clusters.back()) {
  41. // left-to-right clusters
  42. size_t clusterCursor = clusters.size();
  43. while (clusterCursor > 0) {
  44. if (!checkCluster(--clusterCursor)) { return false; }
  45. }
  46. } else {
  47. // right-to-left clusters
  48. size_t clusterCursor = 0;
  49. while (clusterCursor < clusters.size()) {
  50. if (!checkCluster(clusterCursor++)) { return false; }
  51. }
  52. }
  53. return true;
  54. }
  55. void SkShaperJSONWriter::commitRunBuffer(const SkShaper::RunHandler::RunInfo& info) {
  56. fJSONWriter->beginObject("run", true);
  57. // Font name
  58. SkString fontName;
  59. info.fFont.getTypeface()->getFamilyName(&fontName);
  60. fJSONWriter->appendString("font name", fontName.c_str());
  61. // Font size
  62. fJSONWriter->appendFloat("font size", info.fFont.getSize());
  63. if (info.fBidiLevel > 0) {
  64. std::string bidiType = info.fBidiLevel % 2 == 0 ? "left-to-right" : "right-to-left";
  65. std::string bidiOutput = bidiType + " lvl " + std::to_string(info.fBidiLevel);
  66. fJSONWriter->appendString("BiDi", bidiOutput.c_str());
  67. }
  68. if (is_one_to_one(fUTF8.c_str(), info.utf8Range.begin(), info.utf8Range.end(), fClusters)) {
  69. std::string utf8{&fUTF8[info.utf8Range.begin()], info.utf8Range.size()};
  70. fJSONWriter->appendString("UTF8", utf8.c_str());
  71. fJSONWriter->beginArray("glyphs", false);
  72. for (auto glyphID : fGlyphs) {
  73. fJSONWriter->appendU32(glyphID);
  74. }
  75. fJSONWriter->endArray();
  76. fJSONWriter->beginArray("clusters", false);
  77. for (auto cluster : fClusters) {
  78. fJSONWriter->appendU32(cluster);
  79. }
  80. fJSONWriter->endArray();
  81. } else {
  82. VisualizeClusters(fUTF8.c_str(),
  83. info.utf8Range.begin(), info.utf8Range.end(),
  84. SkMakeSpan(fGlyphs),
  85. SkMakeSpan(fClusters),
  86. [this](size_t codePointCount, SkSpan<const char> utf1to1,
  87. SkSpan<const SkGlyphID> glyph1to1) {
  88. this->displayMToN(codePointCount, utf1to1, glyph1to1);
  89. });
  90. }
  91. if (info.glyphCount > 1) {
  92. fJSONWriter->beginArray("horizontal positions", false);
  93. for (auto position : fPositions) {
  94. fJSONWriter->appendFloat(position.x());
  95. }
  96. fJSONWriter->endArray();
  97. }
  98. fJSONWriter->beginArray("advances", false);
  99. for (size_t i = 1; i < info.glyphCount; i++) {
  100. fJSONWriter->appendFloat(fPositions[i].fX - fPositions[i-1].fX);
  101. }
  102. SkPoint lastAdvance = info.fAdvance - (fPositions.back() - fPositions.front());
  103. fJSONWriter->appendFloat(lastAdvance.fX);
  104. fJSONWriter->endArray();
  105. fJSONWriter->endObject();
  106. }
  107. void SkShaperJSONWriter::BreakupClusters(size_t utf8Begin, size_t utf8End,
  108. SkSpan<const uint32_t> clusters,
  109. const BreakupCluastersCallback& processMToN) {
  110. if (clusters.front() <= clusters.back()) {
  111. // Handle left-to-right text direction
  112. size_t glyphStartIndex = 0;
  113. for (size_t glyphEndIndex = 0; glyphEndIndex < clusters.size(); glyphEndIndex++) {
  114. if (clusters[glyphStartIndex] == clusters[glyphEndIndex]) { continue; }
  115. processMToN(glyphStartIndex, glyphEndIndex,
  116. clusters[glyphStartIndex], clusters[glyphEndIndex]);
  117. glyphStartIndex = glyphEndIndex;
  118. }
  119. processMToN(glyphStartIndex, clusters.size(), clusters[glyphStartIndex], utf8End);
  120. } else {
  121. // Handle right-to-left text direction.
  122. SkASSERT(clusters.size() >= 2);
  123. size_t glyphStartIndex = 0;
  124. uint32_t utf8EndIndex = utf8End;
  125. for (size_t glyphEndIndex = 0; glyphEndIndex < clusters.size(); glyphEndIndex++) {
  126. if (clusters[glyphStartIndex] == clusters[glyphEndIndex]) { continue; }
  127. processMToN(glyphStartIndex, glyphEndIndex,
  128. clusters[glyphStartIndex], utf8EndIndex);
  129. utf8EndIndex = clusters[glyphStartIndex];
  130. glyphStartIndex = glyphEndIndex;
  131. }
  132. processMToN(glyphStartIndex, clusters.size(), utf8Begin, clusters[glyphStartIndex-1]);
  133. }
  134. }
  135. void SkShaperJSONWriter::VisualizeClusters(const char* utf8, size_t utf8Begin, size_t utf8End,
  136. SkSpan<const SkGlyphID> glyphIDs,
  137. SkSpan<const uint32_t> clusters,
  138. const VisualizeClustersCallback& processMToN) {
  139. size_t glyphRangeStart, glyphRangeEnd;
  140. uint32_t utf8RangeStart, utf8RangeEnd;
  141. auto resetRanges = [&]() {
  142. glyphRangeStart = std::numeric_limits<size_t>::max();
  143. glyphRangeEnd = 0;
  144. utf8RangeStart = std::numeric_limits<uint32_t>::max();
  145. utf8RangeEnd = 0;
  146. };
  147. auto checkRangesAndProcess = [&]() {
  148. if (glyphRangeStart < glyphRangeEnd) {
  149. size_t glyphRangeCount = glyphRangeEnd - glyphRangeStart;
  150. SkSpan<const char> utf8Span{&utf8[utf8RangeStart], utf8RangeEnd - utf8RangeStart};
  151. SkSpan<const SkGlyphID> glyphSpan{&glyphIDs[glyphRangeStart], glyphRangeCount};
  152. // Glyph count is the same as codepoint count for 1:1.
  153. processMToN(glyphRangeCount, utf8Span, glyphSpan);
  154. }
  155. resetRanges();
  156. };
  157. auto gatherRuns = [&](size_t glyphStartIndex, size_t glyphEndIndex,
  158. uint32_t utf8StartIndex, uint32_t utf8EndIndex) {
  159. int possibleCount = SkUTF::CountUTF8(&utf8[utf8StartIndex], utf8EndIndex - utf8StartIndex);
  160. if (possibleCount == -1) { return; }
  161. size_t codePointCount = SkTo<size_t>(possibleCount);
  162. if (codePointCount == 1 && glyphEndIndex - glyphStartIndex == 1) {
  163. glyphRangeStart = std::min(glyphRangeStart, glyphStartIndex);
  164. glyphRangeEnd = std::max(glyphRangeEnd, glyphEndIndex );
  165. utf8RangeStart = std::min(utf8RangeStart, utf8StartIndex );
  166. utf8RangeEnd = std::max(utf8RangeEnd, utf8EndIndex );
  167. } else {
  168. checkRangesAndProcess();
  169. SkSpan<const char> utf8Span{&utf8[utf8StartIndex], utf8EndIndex - utf8StartIndex};
  170. SkSpan<const SkGlyphID> glyphSpan{&glyphIDs[glyphStartIndex],
  171. glyphEndIndex - glyphStartIndex};
  172. processMToN(codePointCount, utf8Span, glyphSpan);
  173. }
  174. };
  175. resetRanges();
  176. BreakupClusters(utf8Begin, utf8End, clusters, gatherRuns);
  177. checkRangesAndProcess();
  178. }
  179. void SkShaperJSONWriter::displayMToN(size_t codePointCount,
  180. SkSpan<const char> utf8,
  181. SkSpan<const SkGlyphID> glyphIDs) {
  182. std::string nString = std::to_string(codePointCount);
  183. std::string mString = std::to_string(glyphIDs.size());
  184. std::string clusterName = "cluster " + nString + " to " + mString;
  185. fJSONWriter->beginObject(clusterName.c_str(), true);
  186. std::string utf8String{utf8.data(), utf8.size()};
  187. fJSONWriter->appendString("UTF", utf8String.c_str());
  188. fJSONWriter->beginArray("glyphsIDs", false);
  189. for (auto glyphID : glyphIDs) {
  190. fJSONWriter->appendU32(glyphID);
  191. }
  192. fJSONWriter->endArray();
  193. fJSONWriter->endObject();
  194. }