SkTextBlob.cpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922
  1. /*
  2. * Copyright 2014 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 "include/core/SkRSXform.h"
  8. #include "include/core/SkTextBlob.h"
  9. #include "include/core/SkTypeface.h"
  10. #include "src/core/SkFontPriv.h"
  11. #include "src/core/SkGlyphRun.h"
  12. #include "src/core/SkPaintPriv.h"
  13. #include "src/core/SkReadBuffer.h"
  14. #include "src/core/SkSafeMath.h"
  15. #include "src/core/SkStrikeCache.h"
  16. #include "src/core/SkStrikeSpec.h"
  17. #include "src/core/SkTextBlobPriv.h"
  18. #include "src/core/SkWriteBuffer.h"
  19. #include <atomic>
  20. #include <limits>
  21. #include <new>
  22. #if SK_SUPPORT_GPU
  23. #include "src/gpu/text/GrTextBlobCache.h"
  24. #endif
  25. namespace {
  26. struct RunFontStorageEquivalent {
  27. SkScalar fSize, fScaleX;
  28. void* fTypeface;
  29. SkScalar fSkewX;
  30. uint32_t fFlags;
  31. };
  32. static_assert(sizeof(SkFont) == sizeof(RunFontStorageEquivalent), "runfont_should_stay_packed");
  33. }
  34. size_t SkTextBlob::RunRecord::StorageSize(uint32_t glyphCount, uint32_t textSize,
  35. SkTextBlob::GlyphPositioning positioning,
  36. SkSafeMath* safe) {
  37. static_assert(SkIsAlign4(sizeof(SkScalar)), "SkScalar size alignment");
  38. auto glyphSize = safe->mul(glyphCount, sizeof(uint16_t)),
  39. posSize = safe->mul(PosCount(glyphCount, positioning, safe), sizeof(SkScalar));
  40. // RunRecord object + (aligned) glyph buffer + position buffer
  41. auto size = sizeof(SkTextBlob::RunRecord);
  42. size = safe->add(size, safe->alignUp(glyphSize, 4));
  43. size = safe->add(size, posSize);
  44. if (textSize) { // Extended run.
  45. size = safe->add(size, sizeof(uint32_t));
  46. size = safe->add(size, safe->mul(glyphCount, sizeof(uint32_t)));
  47. size = safe->add(size, textSize);
  48. }
  49. return safe->alignUp(size, sizeof(void*));
  50. }
  51. const SkTextBlob::RunRecord* SkTextBlob::RunRecord::First(const SkTextBlob* blob) {
  52. // The first record (if present) is stored following the blob object.
  53. // (aligned up to make the RunRecord aligned too)
  54. return reinterpret_cast<const RunRecord*>(SkAlignPtr((uintptr_t)(blob + 1)));
  55. }
  56. const SkTextBlob::RunRecord* SkTextBlob::RunRecord::Next(const RunRecord* run) {
  57. return SkToBool(run->fFlags & kLast_Flag) ? nullptr : NextUnchecked(run);
  58. }
  59. namespace {
  60. struct RunRecordStorageEquivalent {
  61. SkFont fFont;
  62. SkPoint fOffset;
  63. uint32_t fCount;
  64. uint32_t fFlags;
  65. SkDEBUGCODE(unsigned fMagic;)
  66. };
  67. }
  68. void SkTextBlob::RunRecord::validate(const uint8_t* storageTop) const {
  69. SkASSERT(kRunRecordMagic == fMagic);
  70. SkASSERT((uint8_t*)NextUnchecked(this) <= storageTop);
  71. SkASSERT(glyphBuffer() + fCount <= (uint16_t*)posBuffer());
  72. SkASSERT(posBuffer() + fCount * ScalarsPerGlyph(positioning())
  73. <= (SkScalar*)NextUnchecked(this));
  74. if (isExtended()) {
  75. SkASSERT(textSize() > 0);
  76. SkASSERT(textSizePtr() < (uint32_t*)NextUnchecked(this));
  77. SkASSERT(clusterBuffer() < (uint32_t*)NextUnchecked(this));
  78. SkASSERT(textBuffer() + textSize() <= (char*)NextUnchecked(this));
  79. }
  80. static_assert(sizeof(SkTextBlob::RunRecord) == sizeof(RunRecordStorageEquivalent),
  81. "runrecord_should_stay_packed");
  82. }
  83. const SkTextBlob::RunRecord* SkTextBlob::RunRecord::NextUnchecked(const RunRecord* run) {
  84. SkSafeMath safe;
  85. auto res = reinterpret_cast<const RunRecord*>(
  86. reinterpret_cast<const uint8_t*>(run)
  87. + StorageSize(run->glyphCount(), run->textSize(), run->positioning(), &safe));
  88. SkASSERT(safe);
  89. return res;
  90. }
  91. size_t SkTextBlob::RunRecord::PosCount(uint32_t glyphCount,
  92. SkTextBlob::GlyphPositioning positioning,
  93. SkSafeMath* safe) {
  94. return safe->mul(glyphCount, ScalarsPerGlyph(positioning));
  95. }
  96. uint32_t* SkTextBlob::RunRecord::textSizePtr() const {
  97. // textSize follows the position buffer.
  98. SkASSERT(isExtended());
  99. SkSafeMath safe;
  100. auto res = (uint32_t*)(&this->posBuffer()[PosCount(fCount, positioning(), &safe)]);
  101. SkASSERT(safe);
  102. return res;
  103. }
  104. void SkTextBlob::RunRecord::grow(uint32_t count) {
  105. SkScalar* initialPosBuffer = posBuffer();
  106. uint32_t initialCount = fCount;
  107. fCount += count;
  108. // Move the initial pos scalars to their new location.
  109. size_t copySize = initialCount * sizeof(SkScalar) * ScalarsPerGlyph(positioning());
  110. SkASSERT((uint8_t*)posBuffer() + copySize <= (uint8_t*)NextUnchecked(this));
  111. // memmove, as the buffers may overlap
  112. memmove(posBuffer(), initialPosBuffer, copySize);
  113. }
  114. static int32_t next_id() {
  115. static std::atomic<int32_t> nextID{1};
  116. int32_t id;
  117. do {
  118. id = nextID++;
  119. } while (id == SK_InvalidGenID);
  120. return id;
  121. }
  122. SkTextBlob::SkTextBlob(const SkRect& bounds)
  123. : fBounds(bounds)
  124. , fUniqueID(next_id())
  125. , fCacheID(SK_InvalidUniqueID) {}
  126. SkTextBlob::~SkTextBlob() {
  127. #if SK_SUPPORT_GPU
  128. if (SK_InvalidUniqueID != fCacheID.load()) {
  129. GrTextBlobCache::PostPurgeBlobMessage(fUniqueID, fCacheID);
  130. }
  131. #endif
  132. const auto* run = RunRecord::First(this);
  133. do {
  134. const auto* nextRun = RunRecord::Next(run);
  135. SkDEBUGCODE(run->validate((uint8_t*)this + fStorageSize);)
  136. run->~RunRecord();
  137. run = nextRun;
  138. } while (run);
  139. }
  140. namespace {
  141. union PositioningAndExtended {
  142. int32_t intValue;
  143. struct {
  144. uint8_t positioning;
  145. uint8_t extended;
  146. uint16_t padding;
  147. };
  148. };
  149. static_assert(sizeof(PositioningAndExtended) == sizeof(int32_t), "");
  150. } // namespace
  151. enum SkTextBlob::GlyphPositioning : uint8_t {
  152. kDefault_Positioning = 0, // Default glyph advances -- zero scalars per glyph.
  153. kHorizontal_Positioning = 1, // Horizontal positioning -- one scalar per glyph.
  154. kFull_Positioning = 2, // Point positioning -- two scalars per glyph.
  155. kRSXform_Positioning = 3, // RSXform positioning -- four scalars per glyph.
  156. };
  157. unsigned SkTextBlob::ScalarsPerGlyph(GlyphPositioning pos) {
  158. const uint8_t gScalarsPerPositioning[] = {
  159. 0, // kDefault_Positioning
  160. 1, // kHorizontal_Positioning
  161. 2, // kFull_Positioning
  162. 4, // kRSXform_Positioning
  163. };
  164. SkASSERT((unsigned)pos <= 3);
  165. return gScalarsPerPositioning[pos];
  166. }
  167. void SkTextBlob::operator delete(void* p) {
  168. sk_free(p);
  169. }
  170. void* SkTextBlob::operator new(size_t) {
  171. SK_ABORT("All blobs are created by placement new.");
  172. return sk_malloc_throw(0);
  173. }
  174. void* SkTextBlob::operator new(size_t, void* p) {
  175. return p;
  176. }
  177. SkTextBlobRunIterator::SkTextBlobRunIterator(const SkTextBlob* blob)
  178. : fCurrentRun(SkTextBlob::RunRecord::First(blob)) {
  179. SkDEBUGCODE(fStorageTop = (uint8_t*)blob + blob->fStorageSize;)
  180. }
  181. void SkTextBlobRunIterator::next() {
  182. SkASSERT(!this->done());
  183. if (!this->done()) {
  184. SkDEBUGCODE(fCurrentRun->validate(fStorageTop);)
  185. fCurrentRun = SkTextBlob::RunRecord::Next(fCurrentRun);
  186. }
  187. }
  188. SkTextBlobRunIterator::GlyphPositioning SkTextBlobRunIterator::positioning() const {
  189. SkASSERT(!this->done());
  190. static_assert(static_cast<GlyphPositioning>(SkTextBlob::kDefault_Positioning) ==
  191. kDefault_Positioning, "");
  192. static_assert(static_cast<GlyphPositioning>(SkTextBlob::kHorizontal_Positioning) ==
  193. kHorizontal_Positioning, "");
  194. static_assert(static_cast<GlyphPositioning>(SkTextBlob::kFull_Positioning) ==
  195. kFull_Positioning, "");
  196. static_assert(static_cast<GlyphPositioning>(SkTextBlob::kRSXform_Positioning) ==
  197. kRSXform_Positioning, "");
  198. return SkTo<GlyphPositioning>(fCurrentRun->positioning());
  199. }
  200. bool SkTextBlobRunIterator::isLCD() const {
  201. return fCurrentRun->font().getEdging() == SkFont::Edging::kSubpixelAntiAlias;
  202. }
  203. SkTextBlobBuilder::SkTextBlobBuilder()
  204. : fStorageSize(0)
  205. , fStorageUsed(0)
  206. , fRunCount(0)
  207. , fDeferredBounds(false)
  208. , fLastRun(0) {
  209. fBounds.setEmpty();
  210. }
  211. SkTextBlobBuilder::~SkTextBlobBuilder() {
  212. if (nullptr != fStorage.get()) {
  213. // We are abandoning runs and must destruct the associated font data.
  214. // The easiest way to accomplish that is to use the blob destructor.
  215. this->make();
  216. }
  217. }
  218. SkRect SkTextBlobBuilder::TightRunBounds(const SkTextBlob::RunRecord& run) {
  219. const SkFont& font = run.font();
  220. SkRect bounds;
  221. if (SkTextBlob::kDefault_Positioning == run.positioning()) {
  222. font.measureText(run.glyphBuffer(), run.glyphCount() * sizeof(uint16_t),
  223. SkTextEncoding::kGlyphID, &bounds);
  224. return bounds.makeOffset(run.offset().x(), run.offset().y());
  225. }
  226. SkAutoSTArray<16, SkRect> glyphBounds(run.glyphCount());
  227. font.getBounds(run.glyphBuffer(), run.glyphCount(), glyphBounds.get(), nullptr);
  228. SkASSERT(SkTextBlob::kFull_Positioning == run.positioning() ||
  229. SkTextBlob::kHorizontal_Positioning == run.positioning());
  230. // kFull_Positioning => [ x, y, x, y... ]
  231. // kHorizontal_Positioning => [ x, x, x... ]
  232. // (const y applied by runBounds.offset(run->offset()) later)
  233. const SkScalar horizontalConstY = 0;
  234. const SkScalar* glyphPosX = run.posBuffer();
  235. const SkScalar* glyphPosY = (run.positioning() == SkTextBlob::kFull_Positioning) ?
  236. glyphPosX + 1 : &horizontalConstY;
  237. const unsigned posXInc = SkTextBlob::ScalarsPerGlyph(run.positioning());
  238. const unsigned posYInc = (run.positioning() == SkTextBlob::kFull_Positioning) ?
  239. posXInc : 0;
  240. bounds.setEmpty();
  241. for (unsigned i = 0; i < run.glyphCount(); ++i) {
  242. bounds.join(glyphBounds[i].makeOffset(*glyphPosX, *glyphPosY));
  243. glyphPosX += posXInc;
  244. glyphPosY += posYInc;
  245. }
  246. SkASSERT((void*)glyphPosX <= SkTextBlob::RunRecord::Next(&run));
  247. return bounds.makeOffset(run.offset().x(), run.offset().y());
  248. }
  249. static SkRect map_quad_to_rect(const SkRSXform& xform, const SkRect& rect) {
  250. return SkMatrix().setRSXform(xform).mapRect(rect);
  251. }
  252. SkRect SkTextBlobBuilder::ConservativeRunBounds(const SkTextBlob::RunRecord& run) {
  253. SkASSERT(run.glyphCount() > 0);
  254. SkASSERT(SkTextBlob::kFull_Positioning == run.positioning() ||
  255. SkTextBlob::kHorizontal_Positioning == run.positioning() ||
  256. SkTextBlob::kRSXform_Positioning == run.positioning());
  257. const SkRect fontBounds = SkFontPriv::GetFontBounds(run.font());
  258. if (fontBounds.isEmpty()) {
  259. // Empty font bounds are likely a font bug. TightBounds has a better chance of
  260. // producing useful results in this case.
  261. return TightRunBounds(run);
  262. }
  263. // Compute the glyph position bbox.
  264. SkRect bounds;
  265. switch (run.positioning()) {
  266. case SkTextBlob::kHorizontal_Positioning: {
  267. const SkScalar* glyphPos = run.posBuffer();
  268. SkASSERT((void*)(glyphPos + run.glyphCount()) <= SkTextBlob::RunRecord::Next(&run));
  269. SkScalar minX = *glyphPos;
  270. SkScalar maxX = *glyphPos;
  271. for (unsigned i = 1; i < run.glyphCount(); ++i) {
  272. SkScalar x = glyphPos[i];
  273. minX = SkMinScalar(x, minX);
  274. maxX = SkMaxScalar(x, maxX);
  275. }
  276. bounds.setLTRB(minX, 0, maxX, 0);
  277. } break;
  278. case SkTextBlob::kFull_Positioning: {
  279. const SkPoint* glyphPosPts = run.pointBuffer();
  280. SkASSERT((void*)(glyphPosPts + run.glyphCount()) <= SkTextBlob::RunRecord::Next(&run));
  281. bounds.setBounds(glyphPosPts, run.glyphCount());
  282. } break;
  283. case SkTextBlob::kRSXform_Positioning: {
  284. const SkRSXform* xform = run.xformBuffer();
  285. SkASSERT((void*)(xform + run.glyphCount()) <= SkTextBlob::RunRecord::Next(&run));
  286. bounds = map_quad_to_rect(xform[0], fontBounds);
  287. for (unsigned i = 1; i < run.glyphCount(); ++i) {
  288. bounds.join(map_quad_to_rect(xform[i], fontBounds));
  289. }
  290. } break;
  291. default:
  292. SK_ABORT("unsupported positioning mode");
  293. }
  294. if (run.positioning() != SkTextBlob::kRSXform_Positioning) {
  295. // Expand by typeface glyph bounds.
  296. bounds.fLeft += fontBounds.left();
  297. bounds.fTop += fontBounds.top();
  298. bounds.fRight += fontBounds.right();
  299. bounds.fBottom += fontBounds.bottom();
  300. }
  301. // Offset by run position.
  302. return bounds.makeOffset(run.offset().x(), run.offset().y());
  303. }
  304. void SkTextBlobBuilder::updateDeferredBounds() {
  305. SkASSERT(!fDeferredBounds || fRunCount > 0);
  306. if (!fDeferredBounds) {
  307. return;
  308. }
  309. SkASSERT(fLastRun >= SkAlignPtr(sizeof(SkTextBlob)));
  310. SkTextBlob::RunRecord* run = reinterpret_cast<SkTextBlob::RunRecord*>(fStorage.get() +
  311. fLastRun);
  312. // FIXME: we should also use conservative bounds for kDefault_Positioning.
  313. SkRect runBounds = SkTextBlob::kDefault_Positioning == run->positioning() ?
  314. TightRunBounds(*run) : ConservativeRunBounds(*run);
  315. fBounds.join(runBounds);
  316. fDeferredBounds = false;
  317. }
  318. void SkTextBlobBuilder::reserve(size_t size) {
  319. SkSafeMath safe;
  320. // We don't currently pre-allocate, but maybe someday...
  321. if (safe.add(fStorageUsed, size) <= fStorageSize && safe) {
  322. return;
  323. }
  324. if (0 == fRunCount) {
  325. SkASSERT(nullptr == fStorage.get());
  326. SkASSERT(0 == fStorageSize);
  327. SkASSERT(0 == fStorageUsed);
  328. // the first allocation also includes blob storage
  329. // aligned up to a pointer alignment so SkTextBlob::RunRecords after it stay aligned.
  330. fStorageUsed = SkAlignPtr(sizeof(SkTextBlob));
  331. }
  332. fStorageSize = safe.add(fStorageUsed, size);
  333. // FYI: This relies on everything we store being relocatable, particularly SkPaint.
  334. // Also, this is counting on the underlying realloc to throw when passed max().
  335. fStorage.realloc(safe ? fStorageSize : std::numeric_limits<size_t>::max());
  336. }
  337. bool SkTextBlobBuilder::mergeRun(const SkFont& font, SkTextBlob::GlyphPositioning positioning,
  338. uint32_t count, SkPoint offset) {
  339. if (0 == fLastRun) {
  340. SkASSERT(0 == fRunCount);
  341. return false;
  342. }
  343. SkASSERT(fLastRun >= SkAlignPtr(sizeof(SkTextBlob)));
  344. SkTextBlob::RunRecord* run = reinterpret_cast<SkTextBlob::RunRecord*>(fStorage.get() +
  345. fLastRun);
  346. SkASSERT(run->glyphCount() > 0);
  347. if (run->textSize() != 0) {
  348. return false;
  349. }
  350. if (run->positioning() != positioning
  351. || run->font() != font
  352. || (run->glyphCount() + count < run->glyphCount())) {
  353. return false;
  354. }
  355. // we can merge same-font/same-positioning runs in the following cases:
  356. // * fully positioned run following another fully positioned run
  357. // * horizontally postioned run following another horizontally positioned run with the same
  358. // y-offset
  359. if (SkTextBlob::kFull_Positioning != positioning
  360. && (SkTextBlob::kHorizontal_Positioning != positioning
  361. || run->offset().y() != offset.y())) {
  362. return false;
  363. }
  364. SkSafeMath safe;
  365. size_t sizeDelta =
  366. SkTextBlob::RunRecord::StorageSize(run->glyphCount() + count, 0, positioning, &safe) -
  367. SkTextBlob::RunRecord::StorageSize(run->glyphCount() , 0, positioning, &safe);
  368. if (!safe) {
  369. return false;
  370. }
  371. this->reserve(sizeDelta);
  372. // reserve may have realloced
  373. run = reinterpret_cast<SkTextBlob::RunRecord*>(fStorage.get() + fLastRun);
  374. uint32_t preMergeCount = run->glyphCount();
  375. run->grow(count);
  376. // Callers expect the buffers to point at the newly added slice, ant not at the beginning.
  377. fCurrentRunBuffer.glyphs = run->glyphBuffer() + preMergeCount;
  378. fCurrentRunBuffer.pos = run->posBuffer()
  379. + preMergeCount * SkTextBlob::ScalarsPerGlyph(positioning);
  380. fStorageUsed += sizeDelta;
  381. SkASSERT(fStorageUsed <= fStorageSize);
  382. run->validate(fStorage.get() + fStorageUsed);
  383. return true;
  384. }
  385. void SkTextBlobBuilder::allocInternal(const SkFont& font,
  386. SkTextBlob::GlyphPositioning positioning,
  387. int count, int textSize, SkPoint offset,
  388. const SkRect* bounds) {
  389. if (count <= 0 || textSize < 0) {
  390. fCurrentRunBuffer = { nullptr, nullptr, nullptr, nullptr };
  391. return;
  392. }
  393. if (textSize != 0 || !this->mergeRun(font, positioning, count, offset)) {
  394. this->updateDeferredBounds();
  395. SkSafeMath safe;
  396. size_t runSize = SkTextBlob::RunRecord::StorageSize(count, textSize, positioning, &safe);
  397. if (!safe) {
  398. fCurrentRunBuffer = { nullptr, nullptr, nullptr, nullptr };
  399. return;
  400. }
  401. this->reserve(runSize);
  402. SkASSERT(fStorageUsed >= SkAlignPtr(sizeof(SkTextBlob)));
  403. SkASSERT(fStorageUsed + runSize <= fStorageSize);
  404. SkTextBlob::RunRecord* run = new (fStorage.get() + fStorageUsed)
  405. SkTextBlob::RunRecord(count, textSize, offset, font, positioning);
  406. fCurrentRunBuffer.glyphs = run->glyphBuffer();
  407. fCurrentRunBuffer.pos = run->posBuffer();
  408. fCurrentRunBuffer.utf8text = run->textBuffer();
  409. fCurrentRunBuffer.clusters = run->clusterBuffer();
  410. fLastRun = fStorageUsed;
  411. fStorageUsed += runSize;
  412. fRunCount++;
  413. SkASSERT(fStorageUsed <= fStorageSize);
  414. run->validate(fStorage.get() + fStorageUsed);
  415. }
  416. SkASSERT(textSize > 0 || nullptr == fCurrentRunBuffer.utf8text);
  417. SkASSERT(textSize > 0 || nullptr == fCurrentRunBuffer.clusters);
  418. if (!fDeferredBounds) {
  419. if (bounds) {
  420. fBounds.join(*bounds);
  421. } else {
  422. fDeferredBounds = true;
  423. }
  424. }
  425. }
  426. // SkFont versions
  427. const SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRun(const SkFont& font, int count,
  428. SkScalar x, SkScalar y,
  429. const SkRect* bounds) {
  430. this->allocInternal(font, SkTextBlob::kDefault_Positioning, count, 0, {x, y}, bounds);
  431. return fCurrentRunBuffer;
  432. }
  433. const SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRunPosH(const SkFont& font, int count,
  434. SkScalar y,
  435. const SkRect* bounds) {
  436. this->allocInternal(font, SkTextBlob::kHorizontal_Positioning, count, 0, {0, y}, bounds);
  437. return fCurrentRunBuffer;
  438. }
  439. const SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRunPos(const SkFont& font, int count,
  440. const SkRect* bounds) {
  441. this->allocInternal(font, SkTextBlob::kFull_Positioning, count, 0, {0, 0}, bounds);
  442. return fCurrentRunBuffer;
  443. }
  444. const SkTextBlobBuilder::RunBuffer&
  445. SkTextBlobBuilder::allocRunRSXform(const SkFont& font, int count) {
  446. this->allocInternal(font, SkTextBlob::kRSXform_Positioning, count, 0, {0, 0}, nullptr);
  447. return fCurrentRunBuffer;
  448. }
  449. const SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRunText(const SkFont& font, int count,
  450. SkScalar x, SkScalar y,
  451. int textByteCount,
  452. SkString lang,
  453. const SkRect* bounds) {
  454. this->allocInternal(font,
  455. SkTextBlob::kDefault_Positioning,
  456. count,
  457. textByteCount,
  458. SkPoint::Make(x, y),
  459. bounds);
  460. return fCurrentRunBuffer;
  461. }
  462. const SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRunTextPosH(const SkFont& font, int count,
  463. SkScalar y,
  464. int textByteCount,
  465. SkString lang,
  466. const SkRect* bounds) {
  467. this->allocInternal(font,
  468. SkTextBlob::kHorizontal_Positioning,
  469. count,
  470. textByteCount,
  471. SkPoint::Make(0, y),
  472. bounds);
  473. return fCurrentRunBuffer;
  474. }
  475. const SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRunTextPos(const SkFont& font, int count,
  476. int textByteCount,
  477. SkString lang,
  478. const SkRect *bounds) {
  479. this->allocInternal(font,
  480. SkTextBlob::kFull_Positioning,
  481. count, textByteCount,
  482. SkPoint::Make(0, 0),
  483. bounds);
  484. return fCurrentRunBuffer;
  485. }
  486. const SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRunRSXform(const SkFont& font, int count,
  487. int textByteCount,
  488. SkString lang,
  489. const SkRect* bounds) {
  490. this->allocInternal(font,
  491. SkTextBlob::kRSXform_Positioning,
  492. count,
  493. textByteCount,
  494. {0, 0},
  495. bounds);
  496. return fCurrentRunBuffer;
  497. }
  498. sk_sp<SkTextBlob> SkTextBlobBuilder::make() {
  499. if (!fRunCount) {
  500. // We don't instantiate empty blobs.
  501. SkASSERT(!fStorage.get());
  502. SkASSERT(fStorageUsed == 0);
  503. SkASSERT(fStorageSize == 0);
  504. SkASSERT(fLastRun == 0);
  505. SkASSERT(fBounds.isEmpty());
  506. return nullptr;
  507. }
  508. this->updateDeferredBounds();
  509. // Tag the last run as such.
  510. auto* lastRun = reinterpret_cast<SkTextBlob::RunRecord*>(fStorage.get() + fLastRun);
  511. lastRun->fFlags |= SkTextBlob::RunRecord::kLast_Flag;
  512. SkTextBlob* blob = new (fStorage.release()) SkTextBlob(fBounds);
  513. SkDEBUGCODE(const_cast<SkTextBlob*>(blob)->fStorageSize = fStorageSize;)
  514. SkDEBUGCODE(
  515. SkSafeMath safe;
  516. size_t validateSize = SkAlignPtr(sizeof(SkTextBlob));
  517. for (const auto* run = SkTextBlob::RunRecord::First(blob); run;
  518. run = SkTextBlob::RunRecord::Next(run)) {
  519. validateSize += SkTextBlob::RunRecord::StorageSize(
  520. run->fCount, run->textSize(), run->positioning(), &safe);
  521. run->validate(reinterpret_cast<const uint8_t*>(blob) + fStorageUsed);
  522. fRunCount--;
  523. }
  524. SkASSERT(validateSize == fStorageUsed);
  525. SkASSERT(fRunCount == 0);
  526. SkASSERT(safe);
  527. )
  528. fStorageUsed = 0;
  529. fStorageSize = 0;
  530. fRunCount = 0;
  531. fLastRun = 0;
  532. fBounds.setEmpty();
  533. return sk_sp<SkTextBlob>(blob);
  534. }
  535. ///////////////////////////////////////////////////////////////////////////////////////////////////
  536. void SkTextBlobPriv::Flatten(const SkTextBlob& blob, SkWriteBuffer& buffer) {
  537. // seems like we could skip this, and just recompute bounds in unflatten, but
  538. // some cc_unittests fail if we remove this...
  539. buffer.writeRect(blob.bounds());
  540. SkTextBlobRunIterator it(&blob);
  541. while (!it.done()) {
  542. SkASSERT(it.glyphCount() > 0);
  543. buffer.write32(it.glyphCount());
  544. PositioningAndExtended pe;
  545. pe.intValue = 0;
  546. pe.positioning = it.positioning();
  547. SkASSERT((int32_t)it.positioning() == pe.intValue); // backwards compat.
  548. uint32_t textSize = it.textSize();
  549. pe.extended = textSize > 0;
  550. buffer.write32(pe.intValue);
  551. if (pe.extended) {
  552. buffer.write32(textSize);
  553. }
  554. buffer.writePoint(it.offset());
  555. SkFontPriv::Flatten(it.font(), buffer);
  556. buffer.writeByteArray(it.glyphs(), it.glyphCount() * sizeof(uint16_t));
  557. buffer.writeByteArray(it.pos(),
  558. it.glyphCount() * sizeof(SkScalar) *
  559. SkTextBlob::ScalarsPerGlyph(
  560. SkTo<SkTextBlob::GlyphPositioning>(it.positioning())));
  561. if (pe.extended) {
  562. buffer.writeByteArray(it.clusters(), sizeof(uint32_t) * it.glyphCount());
  563. buffer.writeByteArray(it.text(), it.textSize());
  564. }
  565. it.next();
  566. }
  567. // Marker for the last run (0 is not a valid glyph count).
  568. buffer.write32(0);
  569. }
  570. sk_sp<SkTextBlob> SkTextBlobPriv::MakeFromBuffer(SkReadBuffer& reader) {
  571. SkRect bounds;
  572. reader.readRect(&bounds);
  573. SkTextBlobBuilder blobBuilder;
  574. SkSafeMath safe;
  575. for (;;) {
  576. int glyphCount = reader.read32();
  577. if (glyphCount == 0) {
  578. // End-of-runs marker.
  579. break;
  580. }
  581. PositioningAndExtended pe;
  582. pe.intValue = reader.read32();
  583. const auto pos = SkTo<SkTextBlob::GlyphPositioning>(pe.positioning);
  584. if (glyphCount <= 0 || pos > SkTextBlob::kRSXform_Positioning) {
  585. return nullptr;
  586. }
  587. int textSize = pe.extended ? reader.read32() : 0;
  588. if (textSize < 0) {
  589. return nullptr;
  590. }
  591. SkPoint offset;
  592. reader.readPoint(&offset);
  593. SkFont font;
  594. if (reader.isVersionLT(SkReadBuffer::kSerializeFonts_Version)) {
  595. SkPaint paint;
  596. reader.readPaint(&paint, &font);
  597. } else {
  598. SkFontPriv::Unflatten(&font, reader);
  599. }
  600. // Compute the expected size of the buffer and ensure we have enough to deserialize
  601. // a run before allocating it.
  602. const size_t glyphSize = safe.mul(glyphCount, sizeof(uint16_t)),
  603. posSize =
  604. safe.mul(glyphCount, safe.mul(sizeof(SkScalar),
  605. SkTextBlob::ScalarsPerGlyph(pos))),
  606. clusterSize = pe.extended ? safe.mul(glyphCount, sizeof(uint32_t)) : 0;
  607. const size_t totalSize =
  608. safe.add(safe.add(glyphSize, posSize), safe.add(clusterSize, textSize));
  609. if (!reader.isValid() || !safe || totalSize > reader.available()) {
  610. return nullptr;
  611. }
  612. const SkTextBlobBuilder::RunBuffer* buf = nullptr;
  613. switch (pos) {
  614. case SkTextBlob::kDefault_Positioning:
  615. buf = &blobBuilder.allocRunText(font, glyphCount, offset.x(), offset.y(),
  616. textSize, SkString(), &bounds);
  617. break;
  618. case SkTextBlob::kHorizontal_Positioning:
  619. buf = &blobBuilder.allocRunTextPosH(font, glyphCount, offset.y(),
  620. textSize, SkString(), &bounds);
  621. break;
  622. case SkTextBlob::kFull_Positioning:
  623. buf = &blobBuilder.allocRunTextPos(font, glyphCount, textSize, SkString(), &bounds);
  624. break;
  625. case SkTextBlob::kRSXform_Positioning:
  626. buf = &blobBuilder.allocRunRSXform(font, glyphCount, textSize, SkString(), &bounds);
  627. break;
  628. }
  629. if (!buf->glyphs ||
  630. !buf->pos ||
  631. (pe.extended && (!buf->clusters || !buf->utf8text))) {
  632. return nullptr;
  633. }
  634. if (!reader.readByteArray(buf->glyphs, glyphSize) ||
  635. !reader.readByteArray(buf->pos, posSize)) {
  636. return nullptr;
  637. }
  638. if (pe.extended) {
  639. if (!reader.readByteArray(buf->clusters, clusterSize) ||
  640. !reader.readByteArray(buf->utf8text, textSize)) {
  641. return nullptr;
  642. }
  643. }
  644. }
  645. return blobBuilder.make();
  646. }
  647. sk_sp<SkTextBlob> SkTextBlob::MakeFromText(const void* text, size_t byteLength, const SkFont& font,
  648. SkTextEncoding encoding) {
  649. // Note: we deliberately promote this to fully positioned blobs, since we'd have to pay the
  650. // same cost down stream (i.e. computing bounds), so its cheaper to pay the cost once now.
  651. const int count = font.countText(text, byteLength, encoding);
  652. SkTextBlobBuilder builder;
  653. auto buffer = builder.allocRunPos(font, count);
  654. font.textToGlyphs(text, byteLength, encoding, buffer.glyphs, count);
  655. font.getPos(buffer.glyphs, count, buffer.points(), {0, 0});
  656. return builder.make();
  657. }
  658. sk_sp<SkTextBlob> SkTextBlob::MakeFromPosText(const void* text, size_t byteLength,
  659. const SkPoint pos[], const SkFont& font,
  660. SkTextEncoding encoding) {
  661. const int count = font.countText(text, byteLength, encoding);
  662. SkTextBlobBuilder builder;
  663. auto buffer = builder.allocRunPos(font, count);
  664. font.textToGlyphs(text, byteLength, encoding, buffer.glyphs, count);
  665. memcpy(buffer.points(), pos, count * sizeof(SkPoint));
  666. return builder.make();
  667. }
  668. sk_sp<SkTextBlob> SkTextBlob::MakeFromPosTextH(const void* text, size_t byteLength,
  669. const SkScalar xpos[], SkScalar constY,
  670. const SkFont& font, SkTextEncoding encoding) {
  671. const int count = font.countText(text, byteLength, encoding);
  672. SkTextBlobBuilder builder;
  673. auto buffer = builder.allocRunPosH(font, count, constY);
  674. font.textToGlyphs(text, byteLength, encoding, buffer.glyphs, count);
  675. memcpy(buffer.pos, xpos, count * sizeof(SkScalar));
  676. return builder.make();
  677. }
  678. sk_sp<SkTextBlob> SkTextBlob::MakeFromRSXform(const void* text, size_t byteLength,
  679. const SkRSXform xform[], const SkFont& font,
  680. SkTextEncoding encoding) {
  681. const int count = font.countText(text, byteLength, encoding);
  682. SkTextBlobBuilder builder;
  683. auto buffer = builder.allocRunRSXform(font, count);
  684. font.textToGlyphs(text, byteLength, encoding, buffer.glyphs, count);
  685. memcpy(buffer.xforms(), xform, count * sizeof(SkRSXform));
  686. return builder.make();
  687. }
  688. sk_sp<SkData> SkTextBlob::serialize(const SkSerialProcs& procs) const {
  689. SkBinaryWriteBuffer buffer;
  690. buffer.setSerialProcs(procs);
  691. SkTextBlobPriv::Flatten(*this, buffer);
  692. size_t total = buffer.bytesWritten();
  693. sk_sp<SkData> data = SkData::MakeUninitialized(total);
  694. buffer.writeToMemory(data->writable_data());
  695. return data;
  696. }
  697. sk_sp<SkTextBlob> SkTextBlob::Deserialize(const void* data, size_t length,
  698. const SkDeserialProcs& procs) {
  699. SkReadBuffer buffer(data, length);
  700. buffer.setDeserialProcs(procs);
  701. return SkTextBlobPriv::MakeFromBuffer(buffer);
  702. }
  703. ///////////////////////////////////////////////////////////////////////////////////////////////////
  704. size_t SkTextBlob::serialize(const SkSerialProcs& procs, void* memory, size_t memory_size) const {
  705. SkBinaryWriteBuffer buffer(memory, memory_size);
  706. buffer.setSerialProcs(procs);
  707. SkTextBlobPriv::Flatten(*this, buffer);
  708. return buffer.usingInitialStorage() ? buffer.bytesWritten() : 0u;
  709. }
  710. ///////////////////////////////////////////////////////////////////////////////////////////////////
  711. namespace {
  712. int get_glyph_run_intercepts(const SkGlyphRun& glyphRun,
  713. const SkPaint& paint,
  714. const SkScalar bounds[2],
  715. SkScalar intervals[],
  716. int* intervalCount) {
  717. SkScalar scale = SK_Scalar1;
  718. SkPaint interceptPaint{paint};
  719. SkFont interceptFont{glyphRun.font()};
  720. interceptPaint.setMaskFilter(nullptr); // don't want this affecting our path-cache lookup
  721. // can't use our canonical size if we need to apply path effects
  722. if (interceptPaint.getPathEffect() == nullptr) {
  723. // If the wrong size is going to be used, don't hint anything.
  724. interceptFont.setHinting(SkFontHinting::kNone);
  725. interceptFont.setSubpixel(true);
  726. scale = interceptFont.getSize() / SkFontPriv::kCanonicalTextSizeForPaths;
  727. interceptFont.setSize(SkIntToScalar(SkFontPriv::kCanonicalTextSizeForPaths));
  728. // Note: fScale can be zero here (even if it wasn't before the divide). It can also
  729. // be very very small. We call sk_ieee_float_divide below to ensure IEEE divide behavior,
  730. // since downstream we will check for the resulting coordinates being non-finite anyway.
  731. // Thus we don't need to check for zero here.
  732. if (interceptPaint.getStrokeWidth() > 0
  733. && interceptPaint.getStyle() != SkPaint::kFill_Style) {
  734. interceptPaint.setStrokeWidth(
  735. sk_ieee_float_divide(interceptPaint.getStrokeWidth(), scale));
  736. }
  737. }
  738. interceptPaint.setStyle(SkPaint::kFill_Style);
  739. interceptPaint.setPathEffect(nullptr);
  740. SkStrikeSpec strikeSpec = SkStrikeSpec::MakeWithNoDevice(interceptFont, &interceptPaint);
  741. auto cache = strikeSpec.findOrCreateExclusiveStrike();
  742. SkScalar xOffset = 0;
  743. SkScalar xPos = xOffset;
  744. SkScalar prevAdvance = 0;
  745. // The typeface is scaled, so un-scale the bounds to be in the space of the typeface.
  746. SkScalar scaledBounds[2] = {bounds[0] / scale, bounds[1] / scale};
  747. const SkPoint* posCursor = glyphRun.positions().begin();
  748. for (auto glyphID : glyphRun.glyphsIDs()) {
  749. SkPoint pos = *posCursor++;
  750. SkGlyph* glyph = cache->glyph(glyphID);
  751. xPos += prevAdvance * scale;
  752. prevAdvance = glyph->advanceX();
  753. if (cache->preparePath(glyph) != nullptr) {
  754. cache->findIntercepts(scaledBounds, scale, pos.x(), glyph, intervals, intervalCount);
  755. }
  756. }
  757. return *intervalCount;
  758. }
  759. } // namespace
  760. int SkTextBlob::getIntercepts(const SkScalar bounds[2], SkScalar intervals[],
  761. const SkPaint* paint) const {
  762. SkTLazy<SkPaint> defaultPaint;
  763. if (paint == nullptr) {
  764. defaultPaint.init();
  765. paint = defaultPaint.get();
  766. }
  767. SkGlyphRunBuilder builder;
  768. builder.textBlobToGlyphRunListIgnoringRSXForm(*paint, *this, SkPoint{0, 0});
  769. auto glyphRunList = builder.useGlyphRunList();
  770. int intervalCount = 0;
  771. for (const SkGlyphRun& glyphRun : glyphRunList) {
  772. intervalCount = get_glyph_run_intercepts(glyphRun, *paint, bounds, intervals, &intervalCount);
  773. }
  774. return intervalCount;
  775. }