/* * Copyright 2015 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef GrAtlasTextOp_DEFINED #define GrAtlasTextOp_DEFINED #include "ops/GrMeshDrawOp.h" #include "text/GrTextBlob.h" #include "text/GrDistanceFieldAdjustTable.h" class SkAtlasTextTarget; class GrContext; class GrAtlasTextOp final : public GrMeshDrawOp { public: DEFINE_OP_CLASS_ID ~GrAtlasTextOp() override { for (int i = 0; i < fGeoCount; i++) { fGeoData[i].fBlob->unref(); } } static const int kVerticesPerGlyph = GrTextBlob::kVerticesPerGlyph; static const int kIndicesPerGlyph = 6; typedef GrTextBlob Blob; struct Geometry { SkMatrix fViewMatrix; SkIRect fClipRect; Blob* fBlob; SkScalar fX; SkScalar fY; uint16_t fRun; uint16_t fSubRun; SkPMColor4f fColor; }; static std::unique_ptr<GrAtlasTextOp> MakeBitmap(GrContext* context, GrPaint&& paint, GrMaskFormat maskFormat, int glyphCount, bool needsTransform); static std::unique_ptr<GrAtlasTextOp> MakeDistanceField( GrContext* context, GrPaint&& paint, int glyphCount, const GrDistanceFieldAdjustTable* distanceAdjustTable, bool useGammaCorrectDistanceTable, SkColor luminanceColor, const SkSurfaceProps& props, bool isAntiAliased, bool useLCD); // To avoid even the initial copy of the struct, we have a getter for the first item which // is used to seed the op with its initial geometry. After seeding, the client should call // init() so the op can initialize itself Geometry& geometry() { return fGeoData[0]; } /** Called after this->geometry() has been configured. */ void init(); const char* name() const override { return "AtlasTextOp"; } void visitProxies(const VisitProxyFunc& func, VisitorType) const override; #ifdef SK_DEBUG SkString dumpInfo() const override; #endif FixedFunctionFlags fixedFunctionFlags() const override; GrProcessorSet::Analysis finalize(const GrCaps& caps, const GrAppliedClip* clip) override; enum MaskType { kGrayscaleCoverageMask_MaskType, kLCDCoverageMask_MaskType, kColorBitmapMask_MaskType, kAliasedDistanceField_MaskType, kGrayscaleDistanceField_MaskType, kLCDDistanceField_MaskType, kLCDBGRDistanceField_MaskType, }; MaskType maskType() const { return fMaskType; } void finalizeForTextTarget(uint32_t color, const GrCaps&); void executeForTextTarget(SkAtlasTextTarget*); private: friend class GrOpMemoryPool; // for ctor // The minimum number of Geometry we will try to allocate. static constexpr auto kMinGeometryAllocated = 12; GrAtlasTextOp(GrPaint&& paint) : INHERITED(ClassID()) , fGeoDataAllocSize(kMinGeometryAllocated) , fProcessors(std::move(paint)) {} struct FlushInfo { sk_sp<const GrBuffer> fVertexBuffer; sk_sp<const GrBuffer> fIndexBuffer; sk_sp<GrGeometryProcessor> fGeometryProcessor; const GrPipeline* fPipeline; GrPipeline::FixedDynamicState* fFixedDynamicState; int fGlyphsToFlush; int fVertexOffset; }; void onPrepareDraws(Target*) override; GrMaskFormat maskFormat() const { switch (fMaskType) { case kLCDCoverageMask_MaskType: return kA565_GrMaskFormat; case kColorBitmapMask_MaskType: return kARGB_GrMaskFormat; case kGrayscaleCoverageMask_MaskType: case kAliasedDistanceField_MaskType: case kGrayscaleDistanceField_MaskType: case kLCDDistanceField_MaskType: case kLCDBGRDistanceField_MaskType: return kA8_GrMaskFormat; } return kA8_GrMaskFormat; // suppress warning } bool usesDistanceFields() const { return kAliasedDistanceField_MaskType == fMaskType || kGrayscaleDistanceField_MaskType == fMaskType || kLCDDistanceField_MaskType == fMaskType || kLCDBGRDistanceField_MaskType == fMaskType; } bool isLCD() const { return kLCDCoverageMask_MaskType == fMaskType || kLCDDistanceField_MaskType == fMaskType || kLCDBGRDistanceField_MaskType == fMaskType; } inline void flush(GrMeshDrawOp::Target* target, FlushInfo* flushInfo) const; const SkPMColor4f& color() const { SkASSERT(fGeoCount > 0); return fGeoData[0].fColor; } bool usesLocalCoords() const { return fUsesLocalCoords; } int numGlyphs() const { return fNumGlyphs; } CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override; sk_sp<GrGeometryProcessor> setupDfProcessor(const GrShaderCaps& caps, const sk_sp<GrTextureProxy>* proxies, unsigned int numActiveProxies) const; SkAutoSTMalloc<kMinGeometryAllocated, Geometry> fGeoData; int fGeoDataAllocSize; GrProcessorSet fProcessors; struct { uint32_t fUsesLocalCoords : 1; uint32_t fUseGammaCorrectDistanceTable : 1; uint32_t fNeedsGlyphTransform : 1; }; int fGeoCount; int fNumGlyphs; MaskType fMaskType; // Distance field properties sk_sp<const GrDistanceFieldAdjustTable> fDistanceAdjustTable; SkColor fLuminanceColor; uint32_t fDFGPFlags = 0; typedef GrMeshDrawOp INHERITED; }; #endif