1 /* 2 * Copyright 2015 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 8 #ifndef GrAtlasTextOp_DEFINED 9 #define GrAtlasTextOp_DEFINED 10 11 #include "ops/GrMeshDrawOp.h" 12 #include "text/GrAtlasTextContext.h" 13 #include "text/GrDistanceFieldAdjustTable.h" 14 15 class SkAtlasTextTarget; 16 17 class GrAtlasTextOp final : public GrMeshDrawOp { 18 public: 19 DEFINE_OP_CLASS_ID 20 21 ~GrAtlasTextOp() override { 22 for (int i = 0; i < fGeoCount; i++) { 23 fGeoData[i].fBlob->unref(); 24 } 25 } 26 27 static const int kVerticesPerGlyph = GrAtlasTextBlob::kVerticesPerGlyph; 28 static const int kIndicesPerGlyph = 6; 29 30 typedef GrAtlasTextBlob Blob; 31 struct Geometry { 32 SkMatrix fViewMatrix; 33 SkIRect fClipRect; 34 Blob* fBlob; 35 SkScalar fX; 36 SkScalar fY; 37 uint16_t fRun; 38 uint16_t fSubRun; 39 GrColor fColor; 40 }; 41 42 static std::unique_ptr<GrAtlasTextOp> MakeBitmap(GrPaint&& paint, GrMaskFormat maskFormat, 43 int glyphCount, GrAtlasGlyphCache* fontCache) { 44 std::unique_ptr<GrAtlasTextOp> op(new GrAtlasTextOp(std::move(paint))); 45 46 op->fFontCache = fontCache; 47 switch (maskFormat) { 48 case kA8_GrMaskFormat: 49 op->fMaskType = kGrayscaleCoverageMask_MaskType; 50 break; 51 case kA565_GrMaskFormat: 52 op->fMaskType = kLCDCoverageMask_MaskType; 53 break; 54 case kARGB_GrMaskFormat: 55 op->fMaskType = kColorBitmapMask_MaskType; 56 break; 57 } 58 op->fNumGlyphs = glyphCount; 59 op->fGeoCount = 1; 60 op->fLuminanceColor = 0; 61 op->fFontCache = fontCache; 62 return op; 63 } 64 65 static std::unique_ptr<GrAtlasTextOp> MakeDistanceField( 66 GrPaint&& paint, int glyphCount, GrAtlasGlyphCache* fontCache, 67 const GrDistanceFieldAdjustTable* distanceAdjustTable, 68 bool useGammaCorrectDistanceTable, SkColor luminanceColor, bool isLCD, bool useBGR, 69 bool isAntiAliased) { 70 std::unique_ptr<GrAtlasTextOp> op(new GrAtlasTextOp(std::move(paint))); 71 72 op->fFontCache = fontCache; 73 op->fMaskType = !isAntiAliased ? kAliasedDistanceField_MaskType 74 : isLCD ? (useBGR ? kLCDBGRDistanceField_MaskType 75 : kLCDDistanceField_MaskType) 76 : kGrayscaleDistanceField_MaskType; 77 op->fDistanceAdjustTable.reset(SkRef(distanceAdjustTable)); 78 op->fUseGammaCorrectDistanceTable = useGammaCorrectDistanceTable; 79 op->fLuminanceColor = luminanceColor; 80 op->fNumGlyphs = glyphCount; 81 op->fGeoCount = 1; 82 return op; 83 } 84 85 // To avoid even the initial copy of the struct, we have a getter for the first item which 86 // is used to seed the op with its initial geometry. After seeding, the client should call 87 // init() so the op can initialize itself 88 Geometry& geometry() { return fGeoData[0]; } 89 90 /** Called after this->geometry() has been configured. */ 91 void init(); 92 93 const char* name() const override { return "AtlasTextOp"; } 94 95 void visitProxies(const VisitProxyFunc& func) const override { 96 fProcessors.visitProxies(func); 97 98 const sk_sp<GrTextureProxy>* proxies = fFontCache->getProxies(this->maskFormat()); 99 for (int i = 0; i < kMaxTextures; ++i) { 100 if (proxies[i]) { 101 func(proxies[i].get()); 102 } 103 } 104 } 105 106 SkString dumpInfo() const override; 107 108 FixedFunctionFlags fixedFunctionFlags() const override; 109 110 RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip, 111 GrPixelConfigIsClamped dstIsClamped) override; 112 113 enum MaskType { 114 kGrayscaleCoverageMask_MaskType, 115 kLCDCoverageMask_MaskType, 116 kColorBitmapMask_MaskType, 117 kAliasedDistanceField_MaskType, 118 kGrayscaleDistanceField_MaskType, 119 kLCDDistanceField_MaskType, 120 kLCDBGRDistanceField_MaskType, 121 }; 122 123 MaskType maskType() const { return fMaskType; } 124 125 void finalizeForTextTarget(uint32_t color, const GrCaps&); 126 void executeForTextTarget(SkAtlasTextTarget*); 127 128 private: 129 // The minimum number of Geometry we will try to allocate. 130 static constexpr auto kMinGeometryAllocated = 12; 131 132 GrAtlasTextOp(GrPaint&& paint) 133 : INHERITED(ClassID()) 134 , fGeoDataAllocSize(kMinGeometryAllocated) 135 , fSRGBFlags(GrPipeline::SRGBFlagsFromPaint(paint)) 136 , fProcessors(std::move(paint)) {} 137 138 struct FlushInfo { 139 sk_sp<const GrBuffer> fVertexBuffer; 140 sk_sp<const GrBuffer> fIndexBuffer; 141 sk_sp<GrGeometryProcessor> fGeometryProcessor; 142 const GrPipeline* fPipeline; 143 int fGlyphsToFlush; 144 int fVertexOffset; 145 }; 146 147 void onPrepareDraws(Target*) override; 148 149 GrMaskFormat maskFormat() const { 150 switch (fMaskType) { 151 case kLCDCoverageMask_MaskType: 152 return kA565_GrMaskFormat; 153 case kColorBitmapMask_MaskType: 154 return kARGB_GrMaskFormat; 155 case kGrayscaleCoverageMask_MaskType: 156 case kAliasedDistanceField_MaskType: 157 case kGrayscaleDistanceField_MaskType: 158 case kLCDDistanceField_MaskType: 159 case kLCDBGRDistanceField_MaskType: 160 return kA8_GrMaskFormat; 161 } 162 return kA8_GrMaskFormat; // suppress warning 163 } 164 165 bool usesDistanceFields() const { 166 return kAliasedDistanceField_MaskType == fMaskType || 167 kGrayscaleDistanceField_MaskType == fMaskType || 168 kLCDDistanceField_MaskType == fMaskType || 169 kLCDBGRDistanceField_MaskType == fMaskType; 170 } 171 172 bool isLCD() const { 173 return kLCDCoverageMask_MaskType == fMaskType || 174 kLCDDistanceField_MaskType == fMaskType || 175 kLCDBGRDistanceField_MaskType == fMaskType; 176 } 177 178 inline void flush(GrMeshDrawOp::Target* target, FlushInfo* flushInfo) const; 179 180 GrColor color() const { SkASSERT(fGeoCount > 0); return fGeoData[0].fColor; } 181 bool usesLocalCoords() const { return fUsesLocalCoords; } 182 int numGlyphs() const { return fNumGlyphs; } 183 184 bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override; 185 186 static constexpr auto kMaxTextures = 4; 187 188 sk_sp<GrGeometryProcessor> setupDfProcessor() const; 189 190 SkAutoSTMalloc<kMinGeometryAllocated, Geometry> fGeoData; 191 int fGeoDataAllocSize; 192 uint32_t fSRGBFlags; 193 GrProcessorSet fProcessors; 194 bool fUsesLocalCoords; 195 bool fCanCombineOnTouchOrOverlap; 196 int fGeoCount; 197 int fNumGlyphs; 198 MaskType fMaskType; 199 GrAtlasGlyphCache* fFontCache; 200 // Distance field properties 201 sk_sp<const GrDistanceFieldAdjustTable> fDistanceAdjustTable; 202 SkColor fLuminanceColor; 203 bool fUseGammaCorrectDistanceTable; 204 uint32_t fDFGPFlags = 0; 205 206 typedef GrMeshDrawOp INHERITED; 207 }; 208 209 #endif 210