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