123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- /*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "include/atlastext/SkAtlasTextTarget.h"
- #include "include/atlastext/SkAtlasTextContext.h"
- #include "include/atlastext/SkAtlasTextFont.h"
- #include "include/atlastext/SkAtlasTextRenderer.h"
- #include "src/atlastext/SkInternalAtlasTextContext.h"
- #include "src/core/SkGlyphRunPainter.h"
- #include "src/gpu/GrClip.h"
- #include "src/gpu/GrContextPriv.h"
- #include "src/gpu/GrDrawingManager.h"
- #include "src/gpu/GrMemoryPool.h"
- #include "src/gpu/SkGr.h"
- #include "src/gpu/ops/GrAtlasTextOp.h"
- #include "src/gpu/text/GrTextContext.h"
- static constexpr int kMaxBatchLookBack = 10;
- SkAtlasTextTarget::SkAtlasTextTarget(sk_sp<SkAtlasTextContext> context, int width, int height,
- void* handle)
- : fHandle(handle)
- , fContext(std::move(context))
- , fWidth(width)
- , fHeight(height)
- , fMatrixStack(sizeof(SkMatrix), 4)
- , fSaveCnt(0) {
- fMatrixStack.push_back();
- this->accessCTM()->reset();
- }
- SkAtlasTextTarget::~SkAtlasTextTarget() { fContext->renderer()->targetDeleted(fHandle); }
- int SkAtlasTextTarget::save() {
- const auto& currCTM = this->ctm();
- *static_cast<SkMatrix*>(fMatrixStack.push_back()) = currCTM;
- return fSaveCnt++;
- }
- void SkAtlasTextTarget::restore() {
- if (fSaveCnt) {
- fMatrixStack.pop_back();
- fSaveCnt--;
- }
- }
- void SkAtlasTextTarget::restoreToCount(int count) {
- while (fSaveCnt > count) {
- this->restore();
- }
- }
- void SkAtlasTextTarget::translate(SkScalar dx, SkScalar dy) {
- this->accessCTM()->preTranslate(dx, dy);
- }
- void SkAtlasTextTarget::scale(SkScalar sx, SkScalar sy) { this->accessCTM()->preScale(sx, sy); }
- void SkAtlasTextTarget::rotate(SkScalar degrees) { this->accessCTM()->preRotate(degrees); }
- void SkAtlasTextTarget::rotate(SkScalar degrees, SkScalar px, SkScalar py) {
- this->accessCTM()->preRotate(degrees, px, py);
- }
- void SkAtlasTextTarget::skew(SkScalar sx, SkScalar sy) { this->accessCTM()->preSkew(sx, sy); }
- void SkAtlasTextTarget::concat(const SkMatrix& matrix) { this->accessCTM()->preConcat(matrix); }
- //////////////////////////////////////////////////////////////////////////////
- static const GrColorSpaceInfo kColorSpaceInfo(GrColorType::kRGBA_8888, kPremul_SkAlphaType,
- nullptr);
- static const SkSurfaceProps kProps(
- SkSurfaceProps::kUseDistanceFieldFonts_Flag, kUnknown_SkPixelGeometry);
- //////////////////////////////////////////////////////////////////////////////
- class SkInternalAtlasTextTarget : public GrTextTarget, public SkAtlasTextTarget {
- public:
- SkInternalAtlasTextTarget(sk_sp<SkAtlasTextContext> context,
- int width, int height,
- void* handle)
- : GrTextTarget(width, height, kColorSpaceInfo)
- , SkAtlasTextTarget(std::move(context), width, height, handle)
- , fGlyphPainter(kProps, kColorSpaceInfo) {
- fOpMemoryPool = fContext->internal().grContext()->priv().refOpMemoryPool();
- }
- ~SkInternalAtlasTextTarget() override {
- this->deleteOps();
- }
- /** GrTextTarget overrides */
- void addDrawOp(const GrClip&, std::unique_ptr<GrAtlasTextOp> op) override;
- void drawShape(const GrClip&, const SkPaint&, const SkMatrix& viewMatrix,
- const GrShape&) override {
- SkDebugf("Path glyph??");
- }
- void makeGrPaint(GrMaskFormat, const SkPaint& skPaint, const SkMatrix&,
- GrPaint* grPaint) override {
- grPaint->setColor4f(skPaint.getColor4f().premul());
- }
- GrContext* getContext() override {
- return this->context()->internal().grContext();
- }
- SkGlyphRunListPainter* glyphPainter() override {
- return &fGlyphPainter;
- }
- /** SkAtlasTextTarget overrides */
- void drawText(const SkGlyphID[], const SkPoint[], int glyphCnt, uint32_t color,
- const SkAtlasTextFont&) override;
- void flush() override;
- private:
- void deleteOps();
- uint32_t fColor;
- using SkAtlasTextTarget::fWidth;
- using SkAtlasTextTarget::fHeight;
- SkTArray<std::unique_ptr<GrAtlasTextOp>, true> fOps;
- sk_sp<GrOpMemoryPool> fOpMemoryPool;
- SkGlyphRunListPainter fGlyphPainter;
- };
- //////////////////////////////////////////////////////////////////////////////
- std::unique_ptr<SkAtlasTextTarget> SkAtlasTextTarget::Make(sk_sp<SkAtlasTextContext> context,
- int width, int height, void* handle) {
- return std::unique_ptr<SkAtlasTextTarget>(
- new SkInternalAtlasTextTarget(std::move(context), width, height, handle));
- }
- //////////////////////////////////////////////////////////////////////////////
- void SkInternalAtlasTextTarget::drawText(const SkGlyphID glyphs[], const SkPoint positions[],
- int glyphCnt, uint32_t color,
- const SkAtlasTextFont& font) {
- SkPaint paint;
- paint.setAntiAlias(true);
- // The atlas text context does munging of the paint color. We store the client's color here
- // and then overwrite the generated op's color when addDrawOp() is called.
- fColor = color;
- SkSurfaceProps props(SkSurfaceProps::kUseDistanceFieldFonts_Flag, kUnknown_SkPixelGeometry);
- auto grContext = this->context()->internal().grContext();
- auto atlasTextContext = grContext->priv().drawingManager()->getTextContext();
- SkGlyphRunBuilder builder;
- builder.drawGlyphsWithPositions(paint, font.makeFont(),
- SkSpan<const SkGlyphID>{glyphs, SkTo<size_t>(glyphCnt)},
- positions);
- auto glyphRunList = builder.useGlyphRunList();
- if (!glyphRunList.empty()) {
- atlasTextContext->drawGlyphRunList(grContext, this, GrNoClip(), this->ctm(), props,
- glyphRunList);
- }
- }
- void SkInternalAtlasTextTarget::addDrawOp(const GrClip& clip, std::unique_ptr<GrAtlasTextOp> op) {
- SkASSERT(clip.quickContains(SkRect::MakeIWH(fWidth, fHeight)));
- // The SkAtlasTextRenderer currently only handles grayscale SDF glyphs.
- if (op->maskType() != GrAtlasTextOp::kGrayscaleDistanceField_MaskType) {
- return;
- }
- const GrCaps& caps = *this->context()->internal().grContext()->priv().caps();
- op->finalizeForTextTarget(fColor, caps);
- int n = SkTMin(kMaxBatchLookBack, fOps.count());
- for (int i = 0; i < n; ++i) {
- GrAtlasTextOp* other = fOps.fromBack(i).get();
- if (other->combineIfPossible(op.get(), caps) == GrOp::CombineResult::kMerged) {
- fOpMemoryPool->release(std::move(op));
- return;
- }
- if (GrRectsOverlap(op->bounds(), other->bounds())) {
- break;
- }
- }
- fOps.emplace_back(std::move(op));
- }
- void SkInternalAtlasTextTarget::deleteOps() {
- for (int i = 0; i < fOps.count(); ++i) {
- if (fOps[i]) {
- fOpMemoryPool->release(std::move(fOps[i]));
- }
- }
- fOps.reset();
- }
- void SkInternalAtlasTextTarget::flush() {
- for (int i = 0; i < fOps.count(); ++i) {
- fOps[i]->executeForTextTarget(this);
- }
- this->context()->internal().flush();
- this->deleteOps();
- }
- void GrAtlasTextOp::finalizeForTextTarget(uint32_t color, const GrCaps& caps) {
- // TODO4F: Odd handling of client colors among AtlasTextTarget and AtlasTextRenderer
- SkPMColor4f color4f = SkPMColor4f::FromBytes_RGBA(color);
- for (int i = 0; i < fGeoCount; ++i) {
- fGeoData[i].fColor = color4f;
- }
- // Atlas text doesn't use MSAA, so no need to handle mixed samples.
- // Also, no need to support normalized F16 with manual clamp?
- this->finalize(caps, nullptr /* applied clip */, false /* mixed samples */, GrClampType::kAuto);
- }
- void GrAtlasTextOp::executeForTextTarget(SkAtlasTextTarget* target) {
- FlushInfo flushInfo;
- SkExclusiveStrikePtr autoGlyphCache;
- auto& context = target->context()->internal();
- auto glyphCache = context.grContext()->priv().getGrStrikeCache();
- auto atlasManager = context.grContext()->priv().getAtlasManager();
- auto resourceProvider = context.grContext()->priv().resourceProvider();
- unsigned int numProxies;
- if (!atlasManager->getProxies(kA8_GrMaskFormat, &numProxies)) {
- return;
- }
- for (int i = 0; i < fGeoCount; ++i) {
- // TODO4F: Preserve float colors
- GrTextBlob::VertexRegenerator regenerator(
- resourceProvider, fGeoData[i].fBlob, fGeoData[i].fRun, fGeoData[i].fSubRun,
- fGeoData[i].fViewMatrix, fGeoData[i].fX, fGeoData[i].fY,
- fGeoData[i].fColor.toBytes_RGBA(), &context, glyphCache, atlasManager,
- &autoGlyphCache);
- bool done = false;
- while (!done) {
- GrTextBlob::VertexRegenerator::Result result;
- if (!regenerator.regenerate(&result)) {
- break;
- }
- done = result.fFinished;
- context.recordDraw(result.fFirstVertex, result.fGlyphsRegenerated,
- fGeoData[i].fViewMatrix, target->handle());
- if (!result.fFinished) {
- // Make space in the atlas so we can continue generating vertices.
- context.flush();
- }
- }
- }
- }
|