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 GrAtlasTextOp final : public GrMeshDrawOp { 16 public: 17 DEFINE_OP_CLASS_ID 18 ~GrAtlasTextOp()19 ~GrAtlasTextOp() override { 20 for (int i = 0; i < fGeoCount; i++) { 21 fGeoData[i].fBlob->unref(); 22 } 23 } 24 25 static const int kVerticesPerGlyph = GrAtlasTextBlob::kVerticesPerGlyph; 26 static const int kIndicesPerGlyph = 6; 27 28 typedef GrAtlasTextBlob Blob; 29 struct Geometry { 30 SkMatrix fViewMatrix; 31 Blob* fBlob; 32 SkScalar fX; 33 SkScalar fY; 34 int fRun; 35 int fSubRun; 36 GrColor fColor; 37 }; 38 MakeBitmap(GrPaint && paint,GrMaskFormat maskFormat,int glyphCount,GrAtlasGlyphCache * fontCache)39 static std::unique_ptr<GrAtlasTextOp> MakeBitmap(GrPaint&& paint, GrMaskFormat maskFormat, 40 int glyphCount, GrAtlasGlyphCache* fontCache) { 41 std::unique_ptr<GrAtlasTextOp> op(new GrAtlasTextOp(std::move(paint))); 42 43 op->fFontCache = fontCache; 44 switch (maskFormat) { 45 case kA8_GrMaskFormat: 46 op->fMaskType = kGrayscaleCoverageMask_MaskType; 47 break; 48 case kA565_GrMaskFormat: 49 op->fMaskType = kLCDCoverageMask_MaskType; 50 break; 51 case kARGB_GrMaskFormat: 52 op->fMaskType = kColorBitmapMask_MaskType; 53 break; 54 } 55 op->fNumGlyphs = glyphCount; 56 op->fGeoCount = 1; 57 op->fLuminanceColor = 0; 58 op->fFontCache = fontCache; 59 return op; 60 } 61 MakeDistanceField(GrPaint && paint,int glyphCount,GrAtlasGlyphCache * fontCache,const GrDistanceFieldAdjustTable * distanceAdjustTable,bool useGammaCorrectDistanceTable,SkColor luminanceColor,bool isLCD,bool useBGR,bool isAntiAliased)62 static std::unique_ptr<GrAtlasTextOp> MakeDistanceField( 63 GrPaint&& paint, int glyphCount, GrAtlasGlyphCache* fontCache, 64 const GrDistanceFieldAdjustTable* distanceAdjustTable, 65 bool useGammaCorrectDistanceTable, SkColor luminanceColor, bool isLCD, bool useBGR, 66 bool isAntiAliased) { 67 std::unique_ptr<GrAtlasTextOp> op(new GrAtlasTextOp(std::move(paint))); 68 69 op->fFontCache = fontCache; 70 op->fMaskType = !isAntiAliased ? kAliasedDistanceField_MaskType 71 : isLCD ? (useBGR ? kLCDBGRDistanceField_MaskType 72 : kLCDDistanceField_MaskType) 73 : kGrayscaleDistanceField_MaskType; 74 op->fDistanceAdjustTable.reset(SkRef(distanceAdjustTable)); 75 op->fUseGammaCorrectDistanceTable = useGammaCorrectDistanceTable; 76 op->fLuminanceColor = luminanceColor; 77 op->fNumGlyphs = glyphCount; 78 op->fGeoCount = 1; 79 return op; 80 } 81 82 // To avoid even the initial copy of the struct, we have a getter for the first item which 83 // is used to seed the op with its initial geometry. After seeding, the client should call 84 // init() so the op can initialize itself geometry()85 Geometry& geometry() { return fGeoData[0]; } 86 init()87 void init() { 88 const Geometry& geo = fGeoData[0]; 89 fColor = geo.fColor; 90 SkRect bounds; 91 geo.fBlob->computeSubRunBounds(&bounds, geo.fRun, geo.fSubRun, geo.fViewMatrix, geo.fX, 92 geo.fY); 93 // We don't have tight bounds on the glyph paths in device space. For the purposes of bounds 94 // we treat this as a set of non-AA rects rendered with a texture. 95 this->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo); 96 } 97 name()98 const char* name() const override { return "AtlasTextOp"; } 99 100 SkString dumpInfo() const override; 101 102 FixedFunctionFlags fixedFunctionFlags() const override; 103 104 RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip) override; 105 106 private: GrAtlasTextOp(GrPaint && paint)107 GrAtlasTextOp(GrPaint&& paint) 108 : INHERITED(ClassID()) 109 , fColor(paint.getColor()) 110 , fSRGBFlags(GrPipeline::SRGBFlagsFromPaint(paint)) 111 , fProcessors(std::move(paint)) {} 112 113 struct FlushInfo { 114 sk_sp<const GrBuffer> fVertexBuffer; 115 sk_sp<const GrBuffer> fIndexBuffer; 116 sk_sp<GrGeometryProcessor> fGeometryProcessor; 117 const GrPipeline* fPipeline; 118 int fGlyphsToFlush; 119 int fVertexOffset; 120 }; 121 122 void onPrepareDraws(Target* target) const override; 123 maskFormat()124 GrMaskFormat maskFormat() const { 125 switch (fMaskType) { 126 case kLCDCoverageMask_MaskType: 127 return kA565_GrMaskFormat; 128 case kColorBitmapMask_MaskType: 129 return kARGB_GrMaskFormat; 130 case kGrayscaleCoverageMask_MaskType: 131 case kAliasedDistanceField_MaskType: 132 case kGrayscaleDistanceField_MaskType: 133 case kLCDDistanceField_MaskType: 134 case kLCDBGRDistanceField_MaskType: 135 return kA8_GrMaskFormat; 136 } 137 return kA8_GrMaskFormat; // suppress warning 138 } 139 usesDistanceFields()140 bool usesDistanceFields() const { 141 return kAliasedDistanceField_MaskType == fMaskType || 142 kGrayscaleDistanceField_MaskType == fMaskType || 143 kLCDDistanceField_MaskType == fMaskType || 144 kLCDBGRDistanceField_MaskType == fMaskType; 145 } 146 isLCD()147 bool isLCD() const { 148 return kLCDCoverageMask_MaskType == fMaskType || 149 kLCDDistanceField_MaskType == fMaskType || 150 kLCDBGRDistanceField_MaskType == fMaskType; 151 } 152 153 inline void flush(GrMeshDrawOp::Target* target, FlushInfo* flushInfo) const; 154 color()155 GrColor color() const { return fColor; } viewMatrix()156 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } usesLocalCoords()157 bool usesLocalCoords() const { return fUsesLocalCoords; } numGlyphs()158 int numGlyphs() const { return fNumGlyphs; } 159 160 bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override; 161 162 // TODO just use class params 163 sk_sp<GrGeometryProcessor> setupDfProcessor(const SkMatrix& viewMatrix, SkColor luminanceColor, 164 GrColor color, sk_sp<GrTextureProxy> proxy) const; 165 166 167 // The minimum number of Geometry we will try to allocate. 168 enum { kMinGeometryAllocated = 4 }; 169 170 enum MaskType { 171 kGrayscaleCoverageMask_MaskType, 172 kLCDCoverageMask_MaskType, 173 kColorBitmapMask_MaskType, 174 kAliasedDistanceField_MaskType, 175 kGrayscaleDistanceField_MaskType, 176 kLCDDistanceField_MaskType, 177 kLCDBGRDistanceField_MaskType, 178 }; 179 180 SkAutoSTMalloc<kMinGeometryAllocated, Geometry> fGeoData; 181 GrColor fColor; 182 uint32_t fSRGBFlags; 183 GrProcessorSet fProcessors; 184 bool fUsesLocalCoords; 185 bool fCanCombineOnTouchOrOverlap; 186 int fGeoCount; 187 int fNumGlyphs; 188 MaskType fMaskType; 189 GrAtlasGlyphCache* fFontCache; 190 // Distance field properties 191 sk_sp<const GrDistanceFieldAdjustTable> fDistanceAdjustTable; 192 SkColor fLuminanceColor; 193 bool fUseGammaCorrectDistanceTable; 194 195 friend class GrBlobRegenHelper; // Needs to trigger flushes 196 197 typedef GrMeshDrawOp INHERITED; 198 }; 199 200 /* 201 * A simple helper class to abstract the interface GrAtlasTextBlob needs to regenerate itself. 202 * It'd be nicer if this was nested, but we need to forward declare it in GrAtlasTextBlob.h 203 */ 204 class GrBlobRegenHelper { 205 public: GrBlobRegenHelper(const GrAtlasTextOp * op,GrMeshDrawOp::Target * target,GrAtlasTextOp::FlushInfo * flushInfo)206 GrBlobRegenHelper(const GrAtlasTextOp* op, GrMeshDrawOp::Target* target, 207 GrAtlasTextOp::FlushInfo* flushInfo) 208 : fOp(op), fTarget(target), fFlushInfo(flushInfo) {} 209 210 void flush(); 211 212 void incGlyphCount(int glyphCount = 1) { fFlushInfo->fGlyphsToFlush += glyphCount; } 213 214 private: 215 const GrAtlasTextOp* fOp; 216 GrMeshDrawOp::Target* fTarget; 217 GrAtlasTextOp::FlushInfo* fFlushInfo; 218 }; 219 220 #endif 221