SkGlyphRun.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. /*
  2. * Copyright 2018 The Android Open Source Project
  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/core/SkGlyphRun.h"
  8. #include "include/core/SkFont.h"
  9. #include "include/core/SkPaint.h"
  10. #include "include/core/SkTextBlob.h"
  11. #include "include/private/SkTo.h"
  12. #include "src/core/SkDevice.h"
  13. #include "src/core/SkFontPriv.h"
  14. #include "src/core/SkStrike.h"
  15. #include "src/core/SkStrikeCache.h"
  16. #include "src/core/SkStrikeSpec.h"
  17. #include "src/core/SkTextBlobPriv.h"
  18. #include "src/core/SkUtils.h"
  19. // -- SkGlyphRun -----------------------------------------------------------------------------------
  20. SkGlyphRun::SkGlyphRun(const SkFont& font,
  21. SkSpan<const SkPoint> positions,
  22. SkSpan<const SkGlyphID> glyphIDs,
  23. SkSpan<const char> text,
  24. SkSpan<const uint32_t> clusters)
  25. : fPositions{positions}
  26. , fGlyphIDs{glyphIDs}
  27. , fText{text}
  28. , fClusters{clusters}
  29. , fFont{font} {}
  30. SkGlyphRun::SkGlyphRun(const SkGlyphRun& that, const SkFont& font)
  31. : fPositions{that.fPositions}
  32. , fGlyphIDs{that.fGlyphIDs}
  33. , fText{that.fText}
  34. , fClusters{that.fClusters}
  35. , fFont{font} {}
  36. void SkGlyphRun::filloutGlyphsAndPositions(SkGlyphID* glyphIDs, SkPoint* positions) {
  37. memcpy(glyphIDs, fGlyphIDs.data(), fGlyphIDs.size_bytes());
  38. memcpy(positions, fPositions.data(), fPositions.size_bytes());
  39. }
  40. // -- SkGlyphRunList -------------------------------------------------------------------------------
  41. SkGlyphRunList::SkGlyphRunList() = default;
  42. SkGlyphRunList::SkGlyphRunList(
  43. const SkPaint& paint,
  44. const SkTextBlob* blob,
  45. SkPoint origin,
  46. SkSpan<const SkGlyphRun> glyphRunList)
  47. : fOriginalPaint{&paint}
  48. , fOriginalTextBlob{blob}
  49. , fOrigin{origin}
  50. , fGlyphRuns{glyphRunList} { }
  51. SkGlyphRunList::SkGlyphRunList(const SkGlyphRun& glyphRun, const SkPaint& paint)
  52. : fOriginalPaint{&paint}
  53. , fOriginalTextBlob{nullptr}
  54. , fOrigin{SkPoint::Make(0, 0)}
  55. , fGlyphRuns{SkSpan<const SkGlyphRun>{&glyphRun, 1}} {}
  56. uint64_t SkGlyphRunList::uniqueID() const {
  57. return fOriginalTextBlob != nullptr ? fOriginalTextBlob->uniqueID()
  58. : SK_InvalidUniqueID;
  59. }
  60. bool SkGlyphRunList::anyRunsLCD() const {
  61. for (const auto& r : fGlyphRuns) {
  62. if (r.font().getEdging() == SkFont::Edging::kSubpixelAntiAlias) {
  63. return true;
  64. }
  65. }
  66. return false;
  67. }
  68. bool SkGlyphRunList::anyRunsSubpixelPositioned() const {
  69. for (const auto& r : fGlyphRuns) {
  70. if (r.font().isSubpixel()) {
  71. return true;
  72. }
  73. }
  74. return false;
  75. }
  76. bool SkGlyphRunList::allFontsFinite() const {
  77. for (const auto& r : fGlyphRuns) {
  78. if (!SkFontPriv::IsFinite(r.font())) {
  79. return false;
  80. }
  81. }
  82. return true;
  83. }
  84. void SkGlyphRunList::temporaryShuntBlobNotifyAddedToCache(uint32_t cacheID) const {
  85. SkASSERT(fOriginalTextBlob != nullptr);
  86. fOriginalTextBlob->notifyAddedToCache(cacheID);
  87. }
  88. // -- SkGlyphIDSet ---------------------------------------------------------------------------------
  89. // A faster set implementation that does not need any initialization, and reading the set items
  90. // is order the number of items, and not the size of the universe.
  91. // This implementation is based on the paper by Briggs and Torczon, "An Efficient Representation
  92. // for Sparse Sets"
  93. //
  94. // This implementation assumes that the unique glyphs added are appended to a vector that may
  95. // already have unique glyph from a previous computation. This allows the packing of multiple
  96. // UniqueID sequences in a single vector.
  97. SkSpan<const SkGlyphID> SkGlyphIDSet::uniquifyGlyphIDs(
  98. uint32_t universeSize,
  99. SkSpan<const SkGlyphID> glyphIDs,
  100. SkGlyphID* uniqueGlyphIDs,
  101. uint16_t* denseIndices) {
  102. static constexpr SkGlyphID kUndefGlyph{0};
  103. if (universeSize > fUniverseToUniqueSize) {
  104. fUniverseToUnique.reset(universeSize);
  105. fUniverseToUniqueSize = universeSize;
  106. // If the following bzero becomes a performance problem, the memory can be marked as
  107. // initialized for valgrind and msan.
  108. // valgrind = VALGRIND_MAKE_MEM_DEFINED(fUniverseToUnique, universeSize * sizeof(SkGlyphID))
  109. // msan = sk_msan_mark_initialized(fUniverseToUnique, universeSize * sizeof(SkGlyphID))
  110. sk_bzero(fUniverseToUnique, universeSize * sizeof(SkGlyphID));
  111. }
  112. // No need to clear fUniverseToUnique here... the set insertion algorithm is designed to work
  113. // correctly even when the fUniverseToUnique buffer is uninitialized!
  114. size_t uniqueSize = 0;
  115. size_t denseIndicesCursor = 0;
  116. for (auto glyphID : glyphIDs) {
  117. // If the glyphID is not in range then it is the undefined glyph.
  118. if (glyphID >= universeSize) {
  119. glyphID = kUndefGlyph;
  120. }
  121. // The index into the unique ID vector.
  122. auto uniqueIndex = fUniverseToUnique[glyphID];
  123. if (uniqueIndex >= uniqueSize || uniqueGlyphIDs[uniqueIndex] != glyphID) {
  124. uniqueIndex = SkTo<uint16_t>(uniqueSize);
  125. uniqueGlyphIDs[uniqueSize] = glyphID;
  126. fUniverseToUnique[glyphID] = uniqueIndex;
  127. uniqueSize += 1;
  128. }
  129. denseIndices[denseIndicesCursor++] = uniqueIndex;
  130. }
  131. // If we're hanging onto these arrays for a long time, we don't want their size to drift
  132. // endlessly upwards. It's unusual to see a typeface with more than 4096 possible glyphs.
  133. if (fUniverseToUniqueSize > 4096) {
  134. fUniverseToUnique.reset(4096);
  135. sk_bzero(fUniverseToUnique, 4096 * sizeof(SkGlyphID));
  136. fUniverseToUniqueSize = 4096;
  137. }
  138. return SkSpan<const SkGlyphID>(uniqueGlyphIDs, uniqueSize);
  139. }
  140. // -- SkGlyphRunBuilder ----------------------------------------------------------------------------
  141. void SkGlyphRunBuilder::drawTextUTF8(const SkPaint& paint, const SkFont& font, const void* bytes,
  142. size_t byteLength, SkPoint origin) {
  143. auto glyphIDs = textToGlyphIDs(font, bytes, byteLength, SkTextEncoding::kUTF8);
  144. if (!glyphIDs.empty()) {
  145. this->initialize(glyphIDs.size());
  146. this->simplifyDrawText(font, glyphIDs, origin, fPositions);
  147. }
  148. this->makeGlyphRunList(paint, nullptr, SkPoint::Make(0, 0));
  149. }
  150. void SkGlyphRunBuilder::drawTextBlob(const SkPaint& paint, const SkTextBlob& blob, SkPoint origin,
  151. SkBaseDevice* device) {
  152. // Figure out all the storage needed to pre-size everything below.
  153. size_t totalGlyphs = 0;
  154. for (SkTextBlobRunIterator it(&blob); !it.done(); it.next()) {
  155. totalGlyphs += it.glyphCount();
  156. }
  157. // Pre-size all the buffers so they don't move during processing.
  158. this->initialize(totalGlyphs);
  159. SkPoint* positions = fPositions;
  160. for (SkTextBlobRunIterator it(&blob); !it.done(); it.next()) {
  161. if (it.positioning() != SkTextBlobRunIterator::kRSXform_Positioning) {
  162. simplifyTextBlobIgnoringRSXForm(paint, it, positions);
  163. } else {
  164. // Handle kRSXform_Positioning
  165. if (!this->empty()) {
  166. this->makeGlyphRunList(paint, &blob, origin);
  167. device->drawGlyphRunList(this->useGlyphRunList());
  168. }
  169. device->drawGlyphRunRSXform(it.font(), it.glyphs(), (const SkRSXform*)it.pos(),
  170. it.glyphCount(), origin, paint);
  171. // re-init in case we keep looping and need the builder again
  172. this->initialize(totalGlyphs);
  173. }
  174. positions += it.glyphCount();
  175. }
  176. if (!this->empty()) {
  177. this->makeGlyphRunList(paint, &blob, origin);
  178. device->drawGlyphRunList(this->useGlyphRunList());
  179. }
  180. }
  181. void SkGlyphRunBuilder::textBlobToGlyphRunListIgnoringRSXForm(
  182. const SkPaint& paint, const SkTextBlob& blob, SkPoint origin) {
  183. // Figure out all the storage needed to pre-size everything below.
  184. size_t totalGlyphs = 0;
  185. for (SkTextBlobRunIterator it(&blob); !it.done(); it.next()) {
  186. totalGlyphs += it.glyphCount();
  187. }
  188. // Pre-size all the buffers so they don't move during processing.
  189. this->initialize(totalGlyphs);
  190. SkPoint* positions = fPositions;
  191. for (SkTextBlobRunIterator it(&blob); !it.done(); it.next()) {
  192. simplifyTextBlobIgnoringRSXForm(paint, it, positions);
  193. positions += it.glyphCount();
  194. }
  195. if (!this->empty()) {
  196. this->makeGlyphRunList(paint, &blob, origin);
  197. }
  198. }
  199. void SkGlyphRunBuilder::simplifyTextBlobIgnoringRSXForm(const SkPaint& paint,
  200. const SkTextBlobRunIterator& it,
  201. SkPoint* positions) {
  202. size_t runSize = it.glyphCount();
  203. auto text = SkSpan<const char>(it.text(), it.textSize());
  204. auto clusters = SkSpan<const uint32_t>(it.clusters(), runSize);
  205. const SkPoint& offset = it.offset();
  206. auto glyphIDs = SkSpan<const SkGlyphID>{it.glyphs(), runSize};
  207. switch (it.positioning()) {
  208. case SkTextBlobRunIterator::kDefault_Positioning: {
  209. this->simplifyDrawText(
  210. it.font(), glyphIDs, offset, positions, text, clusters);
  211. break;
  212. }
  213. case SkTextBlobRunIterator::kHorizontal_Positioning: {
  214. auto constY = offset.y();
  215. this->simplifyDrawPosTextH(
  216. it.font(), glyphIDs, it.pos(), constY, positions, text, clusters);
  217. break;
  218. }
  219. case SkTextBlobRunIterator::kFull_Positioning: {
  220. this->simplifyDrawPosText(
  221. it.font(), glyphIDs, (const SkPoint*) it.pos(), text, clusters);
  222. break;
  223. }
  224. case SkTextBlobRunIterator::kRSXform_Positioning: break;
  225. }
  226. }
  227. void SkGlyphRunBuilder::drawGlyphsWithPositions(const SkPaint& paint, const SkFont& font,
  228. SkSpan<const SkGlyphID> glyphIDs, const SkPoint* pos) {
  229. if (!glyphIDs.empty()) {
  230. this->initialize(glyphIDs.size());
  231. this->simplifyDrawPosText(font, glyphIDs, pos);
  232. this->makeGlyphRunList(paint, nullptr, SkPoint::Make(0, 0));
  233. }
  234. }
  235. const SkGlyphRunList& SkGlyphRunBuilder::useGlyphRunList() {
  236. return fGlyphRunList;
  237. }
  238. void SkGlyphRunBuilder::initialize(size_t totalRunSize) {
  239. if (totalRunSize > fMaxTotalRunSize) {
  240. fMaxTotalRunSize = totalRunSize;
  241. fPositions.reset(fMaxTotalRunSize);
  242. }
  243. fGlyphRunListStorage.clear();
  244. }
  245. SkSpan<const SkGlyphID> SkGlyphRunBuilder::textToGlyphIDs(
  246. const SkFont& font, const void* bytes, size_t byteLength, SkTextEncoding encoding) {
  247. if (encoding != SkTextEncoding::kGlyphID) {
  248. int count = font.countText(bytes, byteLength, encoding);
  249. if (count > 0) {
  250. fScratchGlyphIDs.resize(count);
  251. font.textToGlyphs(bytes, byteLength, encoding, fScratchGlyphIDs.data(), count);
  252. return SkMakeSpan(fScratchGlyphIDs);
  253. } else {
  254. return SkSpan<const SkGlyphID>();
  255. }
  256. } else {
  257. return SkSpan<const SkGlyphID>((const SkGlyphID*)bytes, byteLength / 2);
  258. }
  259. }
  260. void SkGlyphRunBuilder::makeGlyphRun(
  261. const SkFont& font,
  262. SkSpan<const SkGlyphID> glyphIDs,
  263. SkSpan<const SkPoint> positions,
  264. SkSpan<const char> text,
  265. SkSpan<const uint32_t> clusters) {
  266. // Ignore empty runs.
  267. if (!glyphIDs.empty()) {
  268. fGlyphRunListStorage.emplace_back(
  269. font,
  270. positions,
  271. glyphIDs,
  272. text,
  273. clusters);
  274. }
  275. }
  276. void SkGlyphRunBuilder::makeGlyphRunList(
  277. const SkPaint& paint, const SkTextBlob* blob, SkPoint origin) {
  278. fGlyphRunList.~SkGlyphRunList();
  279. new (&fGlyphRunList) SkGlyphRunList{
  280. paint, blob, origin, SkMakeSpan(fGlyphRunListStorage)};
  281. }
  282. void SkGlyphRunBuilder::simplifyDrawText(
  283. const SkFont& font, SkSpan<const SkGlyphID> glyphIDs,
  284. SkPoint origin, SkPoint* positions,
  285. SkSpan<const char> text, SkSpan<const uint32_t> clusters) {
  286. SkASSERT(!glyphIDs.empty());
  287. auto runSize = glyphIDs.size();
  288. if (!glyphIDs.empty()) {
  289. SkStrikeSpec strikeSpec = SkStrikeSpec::MakeWithNoDevice(font);
  290. SkBulkGlyphMetrics storage{strikeSpec};
  291. auto glyphs = storage.glyphs(glyphIDs);
  292. SkPoint endOfLastGlyph = origin;
  293. SkPoint* cursor = positions;
  294. for (auto glyph : glyphs) {
  295. *cursor++ = endOfLastGlyph;
  296. endOfLastGlyph += glyph->advanceVector();
  297. }
  298. this->makeGlyphRun(
  299. font,
  300. glyphIDs,
  301. SkSpan<const SkPoint>{positions, runSize},
  302. text,
  303. clusters);
  304. }
  305. }
  306. void SkGlyphRunBuilder::simplifyDrawPosTextH(
  307. const SkFont& font, SkSpan<const SkGlyphID> glyphIDs,
  308. const SkScalar* xpos, SkScalar constY, SkPoint* positions,
  309. SkSpan<const char> text, SkSpan<const uint32_t> clusters) {
  310. auto posCursor = positions;
  311. for (auto x : SkSpan<const SkScalar>{xpos, glyphIDs.size()}) {
  312. *posCursor++ = SkPoint::Make(x, constY);
  313. }
  314. simplifyDrawPosText(font, glyphIDs, positions, text, clusters);
  315. }
  316. void SkGlyphRunBuilder::simplifyDrawPosText(
  317. const SkFont& font, SkSpan<const SkGlyphID> glyphIDs,
  318. const SkPoint* pos,
  319. SkSpan<const char> text, SkSpan<const uint32_t> clusters) {
  320. auto runSize = glyphIDs.size();
  321. this->makeGlyphRun(
  322. font,
  323. glyphIDs,
  324. SkSpan<const SkPoint>{pos, runSize},
  325. text,
  326. clusters);
  327. }