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 #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