SkStrike.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /*
  2. * Copyright 2006 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/SkStrike.h"
  8. #include "include/core/SkGraphics.h"
  9. #include "include/core/SkPath.h"
  10. #include "include/core/SkTypeface.h"
  11. #include "include/private/SkMutex.h"
  12. #include "include/private/SkOnce.h"
  13. #include "include/private/SkTemplates.h"
  14. #include "src/core/SkMakeUnique.h"
  15. #include <cctype>
  16. SkStrike::SkStrike(
  17. const SkDescriptor& desc,
  18. std::unique_ptr<SkScalerContext> scaler,
  19. const SkFontMetrics& fontMetrics)
  20. : fDesc{desc}
  21. , fScalerContext{std::move(scaler)}
  22. , fFontMetrics{fontMetrics}
  23. , fIsSubpixel{fScalerContext->isSubpixel()}
  24. , fAxisAlignment{fScalerContext->computeAxisAlignmentForHText()}
  25. {
  26. SkASSERT(fScalerContext != nullptr);
  27. fMemoryUsed = sizeof(*this);
  28. }
  29. #ifdef SK_DEBUG
  30. #define VALIDATE() AutoValidate av(this)
  31. #else
  32. #define VALIDATE()
  33. #endif
  34. // -- glyph creation -------------------------------------------------------------------------------
  35. SkGlyph* SkStrike::makeGlyph(SkPackedGlyphID packedGlyphID) {
  36. fMemoryUsed += sizeof(SkGlyph);
  37. SkGlyph* glyph = fAlloc.make<SkGlyph>(packedGlyphID);
  38. fGlyphMap.set(glyph);
  39. return glyph;
  40. }
  41. SkGlyph* SkStrike::glyph(SkPackedGlyphID packedGlyphID) {
  42. VALIDATE();
  43. SkGlyph* glyph = fGlyphMap.findOrNull(packedGlyphID);
  44. if (glyph == nullptr) {
  45. glyph = this->makeGlyph(packedGlyphID);
  46. fScalerContext->getMetrics(glyph);
  47. }
  48. return glyph;
  49. }
  50. SkGlyph* SkStrike::glyph(SkGlyphID glyphID) {
  51. return this->glyph(SkPackedGlyphID{glyphID});
  52. }
  53. SkGlyph* SkStrike::glyph(SkGlyphID glyphID, SkPoint position) {
  54. const SkFixed maskX = (!fIsSubpixel || fAxisAlignment == kY_SkAxisAlignment) ? 0 : ~0;
  55. const SkFixed maskY = (!fIsSubpixel || fAxisAlignment == kX_SkAxisAlignment) ? 0 : ~0;
  56. SkFixed subX = SkScalarToFixed(position.x()) & maskX,
  57. subY = SkScalarToFixed(position.y()) & maskY;
  58. return this->glyph(SkPackedGlyphID{glyphID, subX, subY});
  59. }
  60. SkGlyph* SkStrike::glyphFromPrototype(const SkGlyphPrototype& p, void* image) {
  61. SkGlyph* glyph = fGlyphMap.findOrNull(p.id);
  62. if (glyph == nullptr) {
  63. fMemoryUsed += sizeof(SkGlyph);
  64. glyph = fAlloc.make<SkGlyph>(p);
  65. fGlyphMap.set(glyph);
  66. }
  67. if (glyph->setImage(&fAlloc, image)) {
  68. fMemoryUsed += glyph->imageSize();
  69. }
  70. return glyph;
  71. }
  72. SkGlyph* SkStrike::glyphOrNull(SkPackedGlyphID id) const {
  73. return fGlyphMap.findOrNull(id);
  74. }
  75. const SkPath* SkStrike::preparePath(SkGlyph* glyph) {
  76. if (glyph->setPath(&fAlloc, fScalerContext.get())) {
  77. fMemoryUsed += glyph->path()->approximateBytesUsed();
  78. }
  79. return glyph->path();
  80. }
  81. const SkPath* SkStrike::preparePath(SkGlyph* glyph, const SkPath* path) {
  82. if (glyph->setPath(&fAlloc, path)) {
  83. fMemoryUsed += glyph->path()->approximateBytesUsed();
  84. }
  85. return glyph->path();
  86. }
  87. const SkDescriptor& SkStrike::getDescriptor() const {
  88. return *fDesc.getDesc();
  89. }
  90. unsigned SkStrike::getGlyphCount() const {
  91. return fScalerContext->getGlyphCount();
  92. }
  93. int SkStrike::countCachedGlyphs() const {
  94. return fGlyphMap.count();
  95. }
  96. SkSpan<const SkGlyph*> SkStrike::internalPrepare(
  97. SkSpan<const SkGlyphID> glyphIDs, PathDetail pathDetail, const SkGlyph** results) {
  98. const SkGlyph** cursor = results;
  99. for (auto glyphID : glyphIDs) {
  100. SkGlyph* glyphPtr = this->glyph(glyphID);
  101. if (pathDetail == kMetricsAndPath) {
  102. this->preparePath(glyphPtr);
  103. }
  104. *cursor++ = glyphPtr;
  105. }
  106. return {results, glyphIDs.size()};
  107. }
  108. const void* SkStrike::prepareImage(SkGlyph* glyph) {
  109. if (glyph->setImage(&fAlloc, fScalerContext.get())) {
  110. fMemoryUsed += glyph->imageSize();
  111. }
  112. return glyph->image();
  113. }
  114. SkGlyph* SkStrike::mergeGlyphAndImage(SkPackedGlyphID toID, const SkGlyph& from) {
  115. SkGlyph* glyph = fGlyphMap.findOrNull(toID);
  116. if (glyph == nullptr) {
  117. glyph = this->makeGlyph(toID);
  118. }
  119. if (glyph->setMetricsAndImage(&fAlloc, from)) {
  120. fMemoryUsed += glyph->imageSize();
  121. }
  122. return glyph;
  123. }
  124. bool SkStrike::belongsToCache(const SkGlyph* glyph) const {
  125. return glyph && fGlyphMap.findOrNull(glyph->getPackedID()) == glyph;
  126. }
  127. const SkGlyph* SkStrike::getCachedGlyphAnySubPix(SkGlyphID glyphID,
  128. SkPackedGlyphID vetoID) const {
  129. for (SkFixed subY = 0; subY < SK_Fixed1; subY += SK_FixedQuarter) {
  130. for (SkFixed subX = 0; subX < SK_Fixed1; subX += SK_FixedQuarter) {
  131. SkPackedGlyphID packedGlyphID{glyphID, subX, subY};
  132. if (packedGlyphID == vetoID) continue;
  133. if (SkGlyph* glyphPtr = fGlyphMap.findOrNull(packedGlyphID)) {
  134. return glyphPtr;
  135. }
  136. }
  137. }
  138. return nullptr;
  139. }
  140. SkVector SkStrike::rounding() const {
  141. return SkStrikeCommon::PixelRounding(fIsSubpixel, fAxisAlignment);
  142. }
  143. SkSpan<const SkGlyph*> SkStrike::metrics(SkSpan<const SkGlyphID> glyphIDs,
  144. const SkGlyph* results[]) {
  145. return this->internalPrepare(glyphIDs, kMetricsOnly, results);
  146. }
  147. SkSpan<const SkGlyph*> SkStrike::preparePaths(SkSpan<const SkGlyphID> glyphIDs,
  148. const SkGlyph* results[]) {
  149. return this->internalPrepare(glyphIDs, kMetricsAndPath, results);
  150. }
  151. SkSpan<const SkGlyph*>
  152. SkStrike::prepareImages(SkSpan<const SkPackedGlyphID> glyphIDs, const SkGlyph* results[]) {
  153. const SkGlyph** cursor = results;
  154. for (auto glyphID : glyphIDs) {
  155. SkGlyph* glyphPtr = this->glyph(glyphID);
  156. (void)this->prepareImage(glyphPtr);
  157. *cursor++ = glyphPtr;
  158. }
  159. return {results, glyphIDs.size()};
  160. }
  161. // N.B. This glyphMetrics call culls all the glyphs which will not display based on a non-finite
  162. // position or that there are no mask pixels.
  163. SkSpan<const SkGlyphPos>
  164. SkStrike::prepareForDrawing(const SkPackedGlyphID packedGlyphIDs[], const SkPoint positions[],
  165. size_t n,
  166. int maxDimension, PreparationDetail detail, SkGlyphPos results[]) {
  167. size_t drawableGlyphCount = 0;
  168. for (size_t i = 0; i < n; i++) {
  169. SkPoint pos = positions[i];
  170. if (SkScalarsAreFinite(pos.x(), pos.y())) {
  171. SkGlyph* glyphPtr = this->glyph(packedGlyphIDs[i]);
  172. if (!glyphPtr->isEmpty()) {
  173. results[drawableGlyphCount++] = {i, glyphPtr, pos};
  174. if (glyphPtr->maxDimension() <= maxDimension) {
  175. // The glyph fits; ensure the image if needed.
  176. if (detail == SkStrikeInterface::kImageIfNeeded) {
  177. this->prepareImage(glyphPtr);
  178. }
  179. } else if (!glyphPtr->isColor()) {
  180. // The out of atlas glyph is not color so we can draw it using paths.
  181. this->preparePath(glyphPtr);
  182. } else {
  183. // This will be handled by the fallback strike.
  184. SkASSERT(glyphPtr->maxDimension() > maxDimension && glyphPtr->isColor());
  185. }
  186. }
  187. }
  188. }
  189. return SkSpan<const SkGlyphPos>{results, drawableGlyphCount};
  190. }
  191. void SkStrike::findIntercepts(const SkScalar bounds[2], SkScalar scale, SkScalar xPos,
  192. SkGlyph* glyph, SkScalar* array, int* count) {
  193. glyph->ensureIntercepts(bounds, scale, xPos, array, count, &fAlloc);
  194. }
  195. void SkStrike::dump() const {
  196. const SkTypeface* face = fScalerContext->getTypeface();
  197. const SkScalerContextRec& rec = fScalerContext->getRec();
  198. SkMatrix matrix;
  199. rec.getSingleMatrix(&matrix);
  200. matrix.preScale(SkScalarInvert(rec.fTextSize), SkScalarInvert(rec.fTextSize));
  201. SkString name;
  202. face->getFamilyName(&name);
  203. SkString msg;
  204. SkFontStyle style = face->fontStyle();
  205. msg.printf("cache typeface:%x %25s:(%d,%d,%d)\n %s glyphs:%3d",
  206. face->uniqueID(), name.c_str(), style.weight(), style.width(), style.slant(),
  207. rec.dump().c_str(), fGlyphMap.count());
  208. SkDebugf("%s\n", msg.c_str());
  209. }
  210. void SkStrike::onAboutToExitScope() { }
  211. #ifdef SK_DEBUG
  212. void SkStrike::forceValidate() const {
  213. size_t memoryUsed = sizeof(*this);
  214. fGlyphMap.foreach ([&memoryUsed](const SkGlyph* glyphPtr) {
  215. memoryUsed += sizeof(SkGlyph);
  216. if (glyphPtr->setImageHasBeenCalled()) {
  217. memoryUsed += glyphPtr->imageSize();
  218. }
  219. if (glyphPtr->setPathHasBeenCalled() && glyphPtr->path() != nullptr) {
  220. memoryUsed += glyphPtr->path()->approximateBytesUsed();
  221. }
  222. });
  223. SkASSERT(fMemoryUsed == memoryUsed);
  224. }
  225. void SkStrike::validate() const {
  226. #ifdef SK_DEBUG_GLYPH_CACHE
  227. forceValidate();
  228. #endif
  229. }
  230. #endif // SK_DEBUG