| /* | 
 |  * 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 "src/gpu/ops/GrMeshDrawOp.h" | 
 | #include "src/gpu/text/GrDistanceFieldAdjustTable.h" | 
 | #include "src/gpu/text/GrTextBlob.h" | 
 |  | 
 | class GrRecordingContext; | 
 | class SkAtlasTextTarget; | 
 |  | 
 | 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(GrRecordingContext*, | 
 |                                                      GrPaint&&, | 
 |                                                      GrMaskFormat, | 
 |                                                      int glyphCount, | 
 |                                                      bool needsTransform); | 
 |  | 
 |     static std::unique_ptr<GrAtlasTextOp> MakeDistanceField( | 
 |             GrRecordingContext*, | 
 |             GrPaint&&, | 
 |             int glyphCount, | 
 |             const GrDistanceFieldAdjustTable*, | 
 |             bool useGammaCorrectDistanceTable, | 
 |             SkColor luminanceColor, | 
 |             const SkSurfaceProps&, | 
 |             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) const override; | 
 |  | 
 | #ifdef SK_DEBUG | 
 |     SkString dumpInfo() const override; | 
 | #endif | 
 |  | 
 |     FixedFunctionFlags fixedFunctionFlags() const override; | 
 |  | 
 |     GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, | 
 |                                       bool hasMixedSampledCoverage, GrClampType) 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; | 
 |         GrPipeline::FixedDynamicState* fFixedDynamicState; | 
 |         int fGlyphsToFlush; | 
 |         int fVertexOffset; | 
 |     }; | 
 |  | 
 |     void onPrepareDraws(Target*) override; | 
 |     void onExecute(GrOpFlushState*, const SkRect& chainBounds) 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 |