SkGlyph.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. /*
  2. * Copyright 2018 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/core/SkGlyph.h"
  8. #include "src/core/SkArenaAlloc.h"
  9. #include "src/core/SkMakeUnique.h"
  10. #include "src/core/SkScalerContext.h"
  11. #include "src/pathops/SkPathOpsCubic.h"
  12. #include "src/pathops/SkPathOpsQuad.h"
  13. SkMask SkGlyph::mask() const {
  14. // getMetrics had to be called.
  15. SkASSERT(fMaskFormat != MASK_FORMAT_UNKNOWN);
  16. SkMask mask;
  17. mask.fImage = (uint8_t*)fImage;
  18. mask.fBounds.set(fLeft, fTop, fLeft + fWidth, fTop + fHeight);
  19. mask.fRowBytes = this->rowBytes();
  20. mask.fFormat = static_cast<SkMask::Format>(fMaskFormat);
  21. return mask;
  22. }
  23. SkMask SkGlyph::mask(SkPoint position) const {
  24. SkMask answer = this->mask();
  25. answer.fBounds.offset(SkScalarFloorToInt(position.x()), SkScalarFloorToInt(position.y()));
  26. return answer;
  27. }
  28. void SkGlyph::zeroMetrics() {
  29. fAdvanceX = 0;
  30. fAdvanceY = 0;
  31. fWidth = 0;
  32. fHeight = 0;
  33. fTop = 0;
  34. fLeft = 0;
  35. }
  36. static size_t bits_to_bytes(size_t bits) {
  37. return (bits + 7) >> 3;
  38. }
  39. static size_t format_alignment(SkMask::Format format) {
  40. switch (format) {
  41. case SkMask::kBW_Format:
  42. case SkMask::kA8_Format:
  43. case SkMask::k3D_Format:
  44. case SkMask::kSDF_Format:
  45. return alignof(uint8_t);
  46. case SkMask::kARGB32_Format:
  47. return alignof(uint32_t);
  48. case SkMask::kLCD16_Format:
  49. return alignof(uint16_t);
  50. default:
  51. SK_ABORT("Unknown mask format.");
  52. break;
  53. }
  54. return 0;
  55. }
  56. static size_t format_rowbytes(int width, SkMask::Format format) {
  57. return format == SkMask::kBW_Format ? bits_to_bytes(width)
  58. : width * format_alignment(format);
  59. }
  60. SkGlyph::SkGlyph(const SkGlyphPrototype& p)
  61. : fWidth{p.width}
  62. , fHeight{p.height}
  63. , fTop{p.top}
  64. , fLeft{p.left}
  65. , fAdvanceX{p.advanceX}
  66. , fAdvanceY{p.advanceY}
  67. , fMaskFormat{(uint8_t)p.maskFormat}
  68. , fForceBW{p.forceBW}
  69. , fID{p.id}
  70. {}
  71. size_t SkGlyph::formatAlignment() const {
  72. return format_alignment(this->maskFormat());
  73. }
  74. size_t SkGlyph::allocImage(SkArenaAlloc* alloc) {
  75. SkASSERT(!this->isEmpty());
  76. auto size = this->imageSize();
  77. fImage = alloc->makeBytesAlignedTo(size, this->formatAlignment());
  78. return size;
  79. }
  80. bool SkGlyph::setImage(SkArenaAlloc* alloc, SkScalerContext* scalerContext) {
  81. if (!this->setImageHasBeenCalled()) {
  82. // It used to be that getImage() could change the fMaskFormat. Extra checking to make
  83. // sure there are no regressions.
  84. SkDEBUGCODE(SkMask::Format oldFormat = this->maskFormat());
  85. this->allocImage(alloc);
  86. scalerContext->getImage(*this);
  87. SkASSERT(oldFormat == this->maskFormat());
  88. return true;
  89. }
  90. return false;
  91. }
  92. bool SkGlyph::setImage(SkArenaAlloc* alloc, const void* image) {
  93. if (!this->setImageHasBeenCalled()) {
  94. this->allocImage(alloc);
  95. memcpy(fImage, image, this->imageSize());
  96. return true;
  97. }
  98. return false;
  99. }
  100. bool SkGlyph::setMetricsAndImage(SkArenaAlloc* alloc, const SkGlyph& from) {
  101. if (fImage == nullptr) {
  102. fAdvanceX = from.fAdvanceX;
  103. fAdvanceY = from.fAdvanceY;
  104. fWidth = from.fWidth;
  105. fHeight = from.fHeight;
  106. fTop = from.fTop;
  107. fLeft = from.fLeft;
  108. fForceBW = from.fForceBW;
  109. fMaskFormat = from.fMaskFormat;
  110. return this->setImage(alloc, from.image());
  111. }
  112. return false;
  113. }
  114. size_t SkGlyph::rowBytes() const {
  115. return format_rowbytes(fWidth, (SkMask::Format)fMaskFormat);
  116. }
  117. size_t SkGlyph::rowBytesUsingFormat(SkMask::Format format) const {
  118. return format_rowbytes(fWidth, format);
  119. }
  120. size_t SkGlyph::imageSize() const {
  121. if (this->isEmpty() || this->imageTooLarge()) { return 0; }
  122. size_t size = this->rowBytes() * fHeight;
  123. if (fMaskFormat == SkMask::k3D_Format) {
  124. size *= 3;
  125. }
  126. return size;
  127. }
  128. void SkGlyph::installPath(SkArenaAlloc* alloc, const SkPath* path) {
  129. SkASSERT(fPathData == nullptr);
  130. SkASSERT(!this->setPathHasBeenCalled());
  131. fPathData = alloc->make<SkGlyph::PathData>();
  132. if (path != nullptr) {
  133. fPathData->fPath = *path;
  134. fPathData->fPath.updateBoundsCache();
  135. fPathData->fPath.getGenerationID();
  136. fPathData->fHasPath = true;
  137. }
  138. }
  139. bool SkGlyph::setPath(SkArenaAlloc* alloc, SkScalerContext* scalerContext) {
  140. if (!this->setPathHasBeenCalled()) {
  141. SkPath path;
  142. if (scalerContext->getPath(this->getPackedID(), &path)) {
  143. this->installPath(alloc, &path);
  144. } else {
  145. this->installPath(alloc, nullptr);
  146. }
  147. return this->path() != nullptr;
  148. }
  149. return false;
  150. }
  151. bool SkGlyph::setPath(SkArenaAlloc* alloc, const SkPath* path) {
  152. if (!this->setPathHasBeenCalled()) {
  153. this->installPath(alloc, path);
  154. return this->path() != nullptr;
  155. }
  156. return false;
  157. }
  158. const SkPath* SkGlyph::path() const {
  159. // setPath must have been called previously.
  160. SkASSERT(this->setPathHasBeenCalled());
  161. if (fPathData->fHasPath) {
  162. return &fPathData->fPath;
  163. }
  164. return nullptr;
  165. }
  166. static std::tuple<SkScalar, SkScalar> calculate_path_gap(
  167. SkScalar topOffset, SkScalar bottomOffset, const SkPath& path) {
  168. // Left and Right of an ever expanding gap around the path.
  169. SkScalar left = SK_ScalarMax,
  170. right = SK_ScalarMin;
  171. auto expandGap = [&left, &right](SkScalar v) {
  172. left = SkTMin(left, v);
  173. right = SkTMax(right, v);
  174. };
  175. // Handle all the different verbs for the path.
  176. SkPoint pts[4];
  177. auto addLine = [&expandGap, &pts](SkScalar offset) {
  178. SkScalar t = sk_ieee_float_divide(offset - pts[0].fY, pts[1].fY - pts[0].fY);
  179. if (0 <= t && t < 1) { // this handles divide by zero above
  180. expandGap(pts[0].fX + t * (pts[1].fX - pts[0].fX));
  181. }
  182. };
  183. auto addQuad = [&expandGap, &pts](SkScalar offset) {
  184. SkDQuad quad;
  185. quad.set(pts);
  186. double roots[2];
  187. int count = quad.horizontalIntersect(offset, roots);
  188. while (--count >= 0) {
  189. expandGap(quad.ptAtT(roots[count]).asSkPoint().fX);
  190. }
  191. };
  192. auto addCubic = [&expandGap, &pts](SkScalar offset) {
  193. SkDCubic cubic;
  194. cubic.set(pts);
  195. double roots[3];
  196. int count = cubic.horizontalIntersect(offset, roots);
  197. while (--count >= 0) {
  198. expandGap(cubic.ptAtT(roots[count]).asSkPoint().fX);
  199. }
  200. };
  201. // Handle when a verb's points are in the gap between top and bottom.
  202. auto addPts = [&expandGap, &pts, topOffset, bottomOffset](int ptCount) {
  203. for (int i = 0; i < ptCount; ++i) {
  204. if (topOffset < pts[i].fY && pts[i].fY < bottomOffset) {
  205. expandGap(pts[i].fX);
  206. }
  207. }
  208. };
  209. SkPath::Iter iter(path, false);
  210. SkPath::Verb verb;
  211. while (SkPath::kDone_Verb != (verb = iter.next(pts))) {
  212. switch (verb) {
  213. case SkPath::kMove_Verb: {
  214. break;
  215. }
  216. case SkPath::kLine_Verb: {
  217. addLine(topOffset);
  218. addLine(bottomOffset);
  219. addPts(2);
  220. break;
  221. }
  222. case SkPath::kQuad_Verb: {
  223. SkScalar quadTop = SkTMin(SkTMin(pts[0].fY, pts[1].fY), pts[2].fY);
  224. if (bottomOffset < quadTop) { break; }
  225. SkScalar quadBottom = SkTMax(SkTMax(pts[0].fY, pts[1].fY), pts[2].fY);
  226. if (topOffset > quadBottom) { break; }
  227. addQuad(topOffset);
  228. addQuad(bottomOffset);
  229. addPts(3);
  230. break;
  231. }
  232. case SkPath::kConic_Verb: {
  233. SkASSERT(0); // no support for text composed of conics
  234. break;
  235. }
  236. case SkPath::kCubic_Verb: {
  237. SkScalar quadTop =
  238. SkTMin(SkTMin(SkTMin(pts[0].fY, pts[1].fY), pts[2].fY), pts[3].fY);
  239. if (bottomOffset < quadTop) { break; }
  240. SkScalar quadBottom =
  241. SkTMax(SkTMax(SkTMax(pts[0].fY, pts[1].fY), pts[2].fY), pts[3].fY);
  242. if (topOffset > quadBottom) { break; }
  243. addCubic(topOffset);
  244. addCubic(bottomOffset);
  245. addPts(4);
  246. break;
  247. }
  248. case SkPath::kClose_Verb: {
  249. break;
  250. }
  251. default: {
  252. SkASSERT(0);
  253. break;
  254. }
  255. }
  256. }
  257. return std::tie(left, right);
  258. }
  259. void SkGlyph::ensureIntercepts(const SkScalar* bounds, SkScalar scale, SkScalar xPos,
  260. SkScalar* array, int* count, SkArenaAlloc* alloc) {
  261. auto offsetResults = [scale, xPos](
  262. const SkGlyph::Intercept* intercept,SkScalar* array, int* count) {
  263. if (array) {
  264. array += *count;
  265. for (int index = 0; index < 2; index++) {
  266. *array++ = intercept->fInterval[index] * scale + xPos;
  267. }
  268. }
  269. *count += 2;
  270. };
  271. const SkGlyph::Intercept* match =
  272. [this](const SkScalar bounds[2]) -> const SkGlyph::Intercept* {
  273. if (!fPathData) {
  274. return nullptr;
  275. }
  276. const SkGlyph::Intercept* intercept = fPathData->fIntercept;
  277. while (intercept) {
  278. if (bounds[0] == intercept->fBounds[0] && bounds[1] == intercept->fBounds[1]) {
  279. return intercept;
  280. }
  281. intercept = intercept->fNext;
  282. }
  283. return nullptr;
  284. }(bounds);
  285. if (match) {
  286. if (match->fInterval[0] < match->fInterval[1]) {
  287. offsetResults(match, array, count);
  288. }
  289. return;
  290. }
  291. SkGlyph::Intercept* intercept = alloc->make<SkGlyph::Intercept>();
  292. intercept->fNext = fPathData->fIntercept;
  293. intercept->fBounds[0] = bounds[0];
  294. intercept->fBounds[1] = bounds[1];
  295. intercept->fInterval[0] = SK_ScalarMax;
  296. intercept->fInterval[1] = SK_ScalarMin;
  297. fPathData->fIntercept = intercept;
  298. const SkPath* path = &(fPathData->fPath);
  299. const SkRect& pathBounds = path->getBounds();
  300. if (pathBounds.fBottom < bounds[0] || bounds[1] < pathBounds.fTop) {
  301. return;
  302. }
  303. std::tie(intercept->fInterval[0], intercept->fInterval[1])
  304. = calculate_path_gap(bounds[0], bounds[1], *path);
  305. if (intercept->fInterval[0] >= intercept->fInterval[1]) {
  306. intercept->fInterval[0] = SK_ScalarMax;
  307. intercept->fInterval[1] = SK_ScalarMin;
  308. return;
  309. }
  310. offsetResults(intercept, array, count);
  311. }