Home | History | Annotate | Download | only in ops
      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 
     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 
     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 
     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
     84     Geometry& geometry() { return fGeoData[0]; }
     85 
     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 
     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 
    116     GrAtlasTextOp() : INHERITED(ClassID()) {}  // initialized in factory functions.
    117 
    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 
    132     bool usesDistanceFields() const {
    133         return kGrayscaleDistanceField_MaskType == fMaskType ||
    134                kLCDDistanceField_MaskType == fMaskType;
    135     }
    136 
    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 
    143     GrColor color() const { return fColor; }
    144     const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
    145     bool usesLocalCoords() const { return fUsesLocalCoords; }
    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:
    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