SkAtlasTextTarget.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /*
  2. * Copyright 2017 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/atlastext/SkAtlasTextTarget.h"
  8. #include "include/atlastext/SkAtlasTextContext.h"
  9. #include "include/atlastext/SkAtlasTextFont.h"
  10. #include "include/atlastext/SkAtlasTextRenderer.h"
  11. #include "src/atlastext/SkInternalAtlasTextContext.h"
  12. #include "src/core/SkGlyphRunPainter.h"
  13. #include "src/gpu/GrClip.h"
  14. #include "src/gpu/GrContextPriv.h"
  15. #include "src/gpu/GrDrawingManager.h"
  16. #include "src/gpu/GrMemoryPool.h"
  17. #include "src/gpu/SkGr.h"
  18. #include "src/gpu/ops/GrAtlasTextOp.h"
  19. #include "src/gpu/text/GrTextContext.h"
  20. static constexpr int kMaxBatchLookBack = 10;
  21. SkAtlasTextTarget::SkAtlasTextTarget(sk_sp<SkAtlasTextContext> context, int width, int height,
  22. void* handle)
  23. : fHandle(handle)
  24. , fContext(std::move(context))
  25. , fWidth(width)
  26. , fHeight(height)
  27. , fMatrixStack(sizeof(SkMatrix), 4)
  28. , fSaveCnt(0) {
  29. fMatrixStack.push_back();
  30. this->accessCTM()->reset();
  31. }
  32. SkAtlasTextTarget::~SkAtlasTextTarget() { fContext->renderer()->targetDeleted(fHandle); }
  33. int SkAtlasTextTarget::save() {
  34. const auto& currCTM = this->ctm();
  35. *static_cast<SkMatrix*>(fMatrixStack.push_back()) = currCTM;
  36. return fSaveCnt++;
  37. }
  38. void SkAtlasTextTarget::restore() {
  39. if (fSaveCnt) {
  40. fMatrixStack.pop_back();
  41. fSaveCnt--;
  42. }
  43. }
  44. void SkAtlasTextTarget::restoreToCount(int count) {
  45. while (fSaveCnt > count) {
  46. this->restore();
  47. }
  48. }
  49. void SkAtlasTextTarget::translate(SkScalar dx, SkScalar dy) {
  50. this->accessCTM()->preTranslate(dx, dy);
  51. }
  52. void SkAtlasTextTarget::scale(SkScalar sx, SkScalar sy) { this->accessCTM()->preScale(sx, sy); }
  53. void SkAtlasTextTarget::rotate(SkScalar degrees) { this->accessCTM()->preRotate(degrees); }
  54. void SkAtlasTextTarget::rotate(SkScalar degrees, SkScalar px, SkScalar py) {
  55. this->accessCTM()->preRotate(degrees, px, py);
  56. }
  57. void SkAtlasTextTarget::skew(SkScalar sx, SkScalar sy) { this->accessCTM()->preSkew(sx, sy); }
  58. void SkAtlasTextTarget::concat(const SkMatrix& matrix) { this->accessCTM()->preConcat(matrix); }
  59. //////////////////////////////////////////////////////////////////////////////
  60. static const GrColorSpaceInfo kColorSpaceInfo(GrColorType::kRGBA_8888, kPremul_SkAlphaType,
  61. nullptr);
  62. static const SkSurfaceProps kProps(
  63. SkSurfaceProps::kUseDistanceFieldFonts_Flag, kUnknown_SkPixelGeometry);
  64. //////////////////////////////////////////////////////////////////////////////
  65. class SkInternalAtlasTextTarget : public GrTextTarget, public SkAtlasTextTarget {
  66. public:
  67. SkInternalAtlasTextTarget(sk_sp<SkAtlasTextContext> context,
  68. int width, int height,
  69. void* handle)
  70. : GrTextTarget(width, height, kColorSpaceInfo)
  71. , SkAtlasTextTarget(std::move(context), width, height, handle)
  72. , fGlyphPainter(kProps, kColorSpaceInfo) {
  73. fOpMemoryPool = fContext->internal().grContext()->priv().refOpMemoryPool();
  74. }
  75. ~SkInternalAtlasTextTarget() override {
  76. this->deleteOps();
  77. }
  78. /** GrTextTarget overrides */
  79. void addDrawOp(const GrClip&, std::unique_ptr<GrAtlasTextOp> op) override;
  80. void drawShape(const GrClip&, const SkPaint&, const SkMatrix& viewMatrix,
  81. const GrShape&) override {
  82. SkDebugf("Path glyph??");
  83. }
  84. void makeGrPaint(GrMaskFormat, const SkPaint& skPaint, const SkMatrix&,
  85. GrPaint* grPaint) override {
  86. grPaint->setColor4f(skPaint.getColor4f().premul());
  87. }
  88. GrContext* getContext() override {
  89. return this->context()->internal().grContext();
  90. }
  91. SkGlyphRunListPainter* glyphPainter() override {
  92. return &fGlyphPainter;
  93. }
  94. /** SkAtlasTextTarget overrides */
  95. void drawText(const SkGlyphID[], const SkPoint[], int glyphCnt, uint32_t color,
  96. const SkAtlasTextFont&) override;
  97. void flush() override;
  98. private:
  99. void deleteOps();
  100. uint32_t fColor;
  101. using SkAtlasTextTarget::fWidth;
  102. using SkAtlasTextTarget::fHeight;
  103. SkTArray<std::unique_ptr<GrAtlasTextOp>, true> fOps;
  104. sk_sp<GrOpMemoryPool> fOpMemoryPool;
  105. SkGlyphRunListPainter fGlyphPainter;
  106. };
  107. //////////////////////////////////////////////////////////////////////////////
  108. std::unique_ptr<SkAtlasTextTarget> SkAtlasTextTarget::Make(sk_sp<SkAtlasTextContext> context,
  109. int width, int height, void* handle) {
  110. return std::unique_ptr<SkAtlasTextTarget>(
  111. new SkInternalAtlasTextTarget(std::move(context), width, height, handle));
  112. }
  113. //////////////////////////////////////////////////////////////////////////////
  114. void SkInternalAtlasTextTarget::drawText(const SkGlyphID glyphs[], const SkPoint positions[],
  115. int glyphCnt, uint32_t color,
  116. const SkAtlasTextFont& font) {
  117. SkPaint paint;
  118. paint.setAntiAlias(true);
  119. // The atlas text context does munging of the paint color. We store the client's color here
  120. // and then overwrite the generated op's color when addDrawOp() is called.
  121. fColor = color;
  122. SkSurfaceProps props(SkSurfaceProps::kUseDistanceFieldFonts_Flag, kUnknown_SkPixelGeometry);
  123. auto grContext = this->context()->internal().grContext();
  124. auto atlasTextContext = grContext->priv().drawingManager()->getTextContext();
  125. SkGlyphRunBuilder builder;
  126. builder.drawGlyphsWithPositions(paint, font.makeFont(),
  127. SkSpan<const SkGlyphID>{glyphs, SkTo<size_t>(glyphCnt)},
  128. positions);
  129. auto glyphRunList = builder.useGlyphRunList();
  130. if (!glyphRunList.empty()) {
  131. atlasTextContext->drawGlyphRunList(grContext, this, GrNoClip(), this->ctm(), props,
  132. glyphRunList);
  133. }
  134. }
  135. void SkInternalAtlasTextTarget::addDrawOp(const GrClip& clip, std::unique_ptr<GrAtlasTextOp> op) {
  136. SkASSERT(clip.quickContains(SkRect::MakeIWH(fWidth, fHeight)));
  137. // The SkAtlasTextRenderer currently only handles grayscale SDF glyphs.
  138. if (op->maskType() != GrAtlasTextOp::kGrayscaleDistanceField_MaskType) {
  139. return;
  140. }
  141. const GrCaps& caps = *this->context()->internal().grContext()->priv().caps();
  142. op->finalizeForTextTarget(fColor, caps);
  143. int n = SkTMin(kMaxBatchLookBack, fOps.count());
  144. for (int i = 0; i < n; ++i) {
  145. GrAtlasTextOp* other = fOps.fromBack(i).get();
  146. if (other->combineIfPossible(op.get(), caps) == GrOp::CombineResult::kMerged) {
  147. fOpMemoryPool->release(std::move(op));
  148. return;
  149. }
  150. if (GrRectsOverlap(op->bounds(), other->bounds())) {
  151. break;
  152. }
  153. }
  154. fOps.emplace_back(std::move(op));
  155. }
  156. void SkInternalAtlasTextTarget::deleteOps() {
  157. for (int i = 0; i < fOps.count(); ++i) {
  158. if (fOps[i]) {
  159. fOpMemoryPool->release(std::move(fOps[i]));
  160. }
  161. }
  162. fOps.reset();
  163. }
  164. void SkInternalAtlasTextTarget::flush() {
  165. for (int i = 0; i < fOps.count(); ++i) {
  166. fOps[i]->executeForTextTarget(this);
  167. }
  168. this->context()->internal().flush();
  169. this->deleteOps();
  170. }
  171. void GrAtlasTextOp::finalizeForTextTarget(uint32_t color, const GrCaps& caps) {
  172. // TODO4F: Odd handling of client colors among AtlasTextTarget and AtlasTextRenderer
  173. SkPMColor4f color4f = SkPMColor4f::FromBytes_RGBA(color);
  174. for (int i = 0; i < fGeoCount; ++i) {
  175. fGeoData[i].fColor = color4f;
  176. }
  177. // Atlas text doesn't use MSAA, so no need to handle mixed samples.
  178. // Also, no need to support normalized F16 with manual clamp?
  179. this->finalize(caps, nullptr /* applied clip */, false /* mixed samples */, GrClampType::kAuto);
  180. }
  181. void GrAtlasTextOp::executeForTextTarget(SkAtlasTextTarget* target) {
  182. FlushInfo flushInfo;
  183. SkExclusiveStrikePtr autoGlyphCache;
  184. auto& context = target->context()->internal();
  185. auto glyphCache = context.grContext()->priv().getGrStrikeCache();
  186. auto atlasManager = context.grContext()->priv().getAtlasManager();
  187. auto resourceProvider = context.grContext()->priv().resourceProvider();
  188. unsigned int numProxies;
  189. if (!atlasManager->getProxies(kA8_GrMaskFormat, &numProxies)) {
  190. return;
  191. }
  192. for (int i = 0; i < fGeoCount; ++i) {
  193. // TODO4F: Preserve float colors
  194. GrTextBlob::VertexRegenerator regenerator(
  195. resourceProvider, fGeoData[i].fBlob, fGeoData[i].fRun, fGeoData[i].fSubRun,
  196. fGeoData[i].fViewMatrix, fGeoData[i].fX, fGeoData[i].fY,
  197. fGeoData[i].fColor.toBytes_RGBA(), &context, glyphCache, atlasManager,
  198. &autoGlyphCache);
  199. bool done = false;
  200. while (!done) {
  201. GrTextBlob::VertexRegenerator::Result result;
  202. if (!regenerator.regenerate(&result)) {
  203. break;
  204. }
  205. done = result.fFinished;
  206. context.recordDraw(result.fFirstVertex, result.fGlyphsRegenerated,
  207. fGeoData[i].fViewMatrix, target->handle());
  208. if (!result.fFinished) {
  209. // Make space in the atlas so we can continue generating vertices.
  210. context.flush();
  211. }
  212. }
  213. }
  214. }