LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu/text - GrAtlasTextBlob.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 169 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 58 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 GrAtlasTextBlob_DEFINED
       9             : #define GrAtlasTextBlob_DEFINED
      10             : 
      11             : #include "GrAtlasGlyphCache.h"
      12             : #include "GrColor.h"
      13             : #include "GrDrawOpAtlas.h"
      14             : #include "GrMemoryPool.h"
      15             : #include "GrTextUtils.h"
      16             : #include "SkDescriptor.h"
      17             : #include "SkMaskFilter.h"
      18             : #include "SkOpts.h"
      19             : #include "SkPathEffect.h"
      20             : #include "SkRasterizer.h"
      21             : #include "SkSurfaceProps.h"
      22             : #include "SkTInternalLList.h"
      23             : 
      24             : class GrBlobRegenHelper;
      25             : struct GrDistanceFieldAdjustTable;
      26             : class GrMemoryPool;
      27             : class GrLegacyMeshDrawOp;
      28             : class SkDrawFilter;
      29             : class SkTextBlob;
      30             : class SkTextBlobRunIterator;
      31             : 
      32             : // With this flag enabled, the GrAtlasTextContext will, as a sanity check, regenerate every blob
      33             : // that comes in to verify the integrity of its cache
      34             : #define CACHE_SANITY_CHECK 0
      35             : 
      36             : /*
      37             :  * A GrAtlasTextBlob contains a fully processed SkTextBlob, suitable for nearly immediate drawing
      38             :  * on the GPU.  These are initially created with valid positions and colors, but invalid
      39             :  * texture coordinates.  The GrAtlasTextBlob itself has a few Blob-wide properties, and also
      40             :  * consists of a number of runs.  Runs inside a blob are flushed individually so they can be
      41             :  * reordered.
      42             :  *
      43             :  * The only thing(aside from a memcopy) required to flush a GrAtlasTextBlob is to ensure that
      44             :  * the GrAtlas will not evict anything the Blob needs.
      45             :  *
      46             :  * Note: This struct should really be named GrCachedAtasTextBlob, but that is too verbose.
      47             :  *
      48             :  * *WARNING* If you add new fields to this struct, then you may need to to update AssertEqual
      49             :  */
      50             : class GrAtlasTextBlob : public SkNVRefCnt<GrAtlasTextBlob> {
      51             : public:
      52             :     SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrAtlasTextBlob);
      53             : 
      54             :     static sk_sp<GrAtlasTextBlob> Make(GrMemoryPool* pool, int glyphCount, int runCount);
      55             : 
      56             :     struct Key {
      57           0 :         Key() {
      58           0 :             sk_bzero(this, sizeof(Key));
      59           0 :         }
      60             :         uint32_t fUniqueID;
      61             :         // Color may affect the gamma of the mask we generate, but in a fairly limited way.
      62             :         // Each color is assigned to on of a fixed number of buckets based on its
      63             :         // luminance. For each luminance bucket there is a "canonical color" that
      64             :         // represents the bucket.  This functionality is currently only supported for A8
      65             :         SkColor fCanonicalColor;
      66             :         SkPaint::Style fStyle;
      67             :         SkPixelGeometry fPixelGeometry;
      68             :         bool fHasBlur;
      69             :         uint32_t fScalerContextFlags;
      70             : 
      71           0 :         bool operator==(const Key& other) const {
      72           0 :             return 0 == memcmp(this, &other, sizeof(Key));
      73             :         }
      74             :     };
      75             : 
      76           0 :     void setupKey(const GrAtlasTextBlob::Key& key,
      77             :                   const SkMaskFilter::BlurRec& blurRec,
      78             :                   const SkPaint& paint) {
      79           0 :         fKey = key;
      80           0 :         if (key.fHasBlur) {
      81           0 :             fBlurRec = blurRec;
      82             :         }
      83           0 :         if (key.fStyle != SkPaint::kFill_Style) {
      84           0 :             fStrokeInfo.fFrameWidth = paint.getStrokeWidth();
      85           0 :             fStrokeInfo.fMiterLimit = paint.getStrokeMiter();
      86           0 :             fStrokeInfo.fJoin = paint.getStrokeJoin();
      87             :         }
      88           0 :     }
      89             : 
      90           0 :     static const Key& GetKey(const GrAtlasTextBlob& blob) {
      91           0 :         return blob.fKey;
      92             :     }
      93             : 
      94             :     static uint32_t Hash(const Key& key) {
      95             :         return SkOpts::hash(&key, sizeof(Key));
      96             :     }
      97             : 
      98           0 :     void operator delete(void* p) {
      99           0 :         GrAtlasTextBlob* blob = reinterpret_cast<GrAtlasTextBlob*>(p);
     100           0 :         blob->fPool->release(p);
     101           0 :     }
     102             :     void* operator new(size_t) {
     103             :         SkFAIL("All blobs are created by placement new.");
     104             :         return sk_malloc_throw(0);
     105             :     }
     106             : 
     107           0 :     void* operator new(size_t, void* p) { return p; }
     108             :     void operator delete(void* target, void* placement) {
     109             :         ::operator delete(target, placement);
     110             :     }
     111             : 
     112           0 :     bool hasDistanceField() const { return SkToBool(fTextType & kHasDistanceField_TextType); }
     113           0 :     bool hasBitmap() const { return SkToBool(fTextType & kHasBitmap_TextType); }
     114           0 :     void setHasDistanceField() { fTextType |= kHasDistanceField_TextType; }
     115           0 :     void setHasBitmap() { fTextType |= kHasBitmap_TextType; }
     116             : 
     117           0 :     int runCount() const { return fRunCount; }
     118             : 
     119           0 :     void push_back_run(int currRun) {
     120           0 :         SkASSERT(currRun < fRunCount);
     121           0 :         if (currRun > 0) {
     122           0 :             Run::SubRunInfo& newRun = fRuns[currRun].fSubRunInfo.back();
     123           0 :             Run::SubRunInfo& lastRun = fRuns[currRun - 1].fSubRunInfo.back();
     124           0 :             newRun.setAsSuccessor(lastRun);
     125             :         }
     126           0 :     }
     127             : 
     128             :     // sets the last subrun of runIndex to use distance field text
     129           0 :     void setSubRunHasDistanceFields(int runIndex, bool hasLCD) {
     130           0 :         Run& run = fRuns[runIndex];
     131           0 :         Run::SubRunInfo& subRun = run.fSubRunInfo.back();
     132           0 :         subRun.setUseLCDText(hasLCD);
     133           0 :         subRun.setDrawAsDistanceFields();
     134           0 :     }
     135             : 
     136           0 :     void setRunDrawAsPaths(int runIndex) {
     137           0 :         fRuns[runIndex].fDrawAsPaths = true;
     138           0 :     }
     139             : 
     140           0 :     void setMinAndMaxScale(SkScalar scaledMax, SkScalar scaledMin) {
     141             :         // we init fMaxMinScale and fMinMaxScale in the constructor
     142           0 :         fMaxMinScale = SkMaxScalar(scaledMax, fMaxMinScale);
     143           0 :         fMinMaxScale = SkMinScalar(scaledMin, fMinMaxScale);
     144           0 :     }
     145             : 
     146             :     // inits the override descriptor on the current run.  All following subruns must use this
     147             :     // descriptor
     148           0 :     void initOverride(int runIndex) {
     149           0 :         Run& run = fRuns[runIndex];
     150             :         // Push back a new subrun to fill and set the override descriptor
     151           0 :         run.push_back();
     152           0 :         run.fOverrideDescriptor.reset(new SkAutoDescriptor);
     153           0 :     }
     154             : 
     155             :     SkGlyphCache* setupCache(int runIndex,
     156             :                              const SkSurfaceProps& props,
     157             :                              uint32_t scalerContextFlags,
     158             :                              const SkPaint& skPaint,
     159             :                              const SkMatrix* viewMatrix);
     160             : 
     161             :     // Appends a glyph to the blob.  If the glyph is too large, the glyph will be appended
     162             :     // as a path.
     163             :     void appendGlyph(int runIndex,
     164             :                      const SkRect& positions,
     165             :                      GrColor color,
     166             :                      GrAtlasTextStrike* strike,
     167             :                      GrGlyph* glyph,
     168             :                      SkGlyphCache*, const SkGlyph& skGlyph,
     169             :                      SkScalar x, SkScalar y, SkScalar scale, bool treatAsBMP);
     170             : 
     171           0 :     static size_t GetVertexStride(GrMaskFormat maskFormat) {
     172           0 :         switch (maskFormat) {
     173             :             case kA8_GrMaskFormat:
     174           0 :                 return kGrayTextVASize;
     175             :             case kARGB_GrMaskFormat:
     176           0 :                 return kColorTextVASize;
     177             :             default:
     178           0 :                 return kLCDTextVASize;
     179             :         }
     180             :     }
     181             : 
     182             :     bool mustRegenerate(const GrTextUtils::Paint&, const SkMaskFilter::BlurRec& blurRec,
     183             :                         const SkMatrix& viewMatrix, SkScalar x, SkScalar y);
     184             : 
     185             :     // flush a GrAtlasTextBlob associated with a SkTextBlob
     186             :     void flushCached(GrContext* context, GrRenderTargetContext* rtc, const SkTextBlob* blob,
     187             :                      const SkSurfaceProps& props,
     188             :                      const GrDistanceFieldAdjustTable* distanceAdjustTable,
     189             :                      const GrTextUtils::Paint&, SkDrawFilter* drawFilter, const GrClip& clip,
     190             :                      const SkMatrix& viewMatrix, const SkIRect& clipBounds, SkScalar x, SkScalar y);
     191             : 
     192             :     // flush a throwaway GrAtlasTextBlob *not* associated with an SkTextBlob
     193             :     void flushThrowaway(GrContext* context, GrRenderTargetContext* rtc, const SkSurfaceProps& props,
     194             :                         const GrDistanceFieldAdjustTable* distanceAdjustTable,
     195             :                         const GrTextUtils::Paint& paint, const GrClip& clip,
     196             :                         const SkMatrix& viewMatrix, const SkIRect& clipBounds, SkScalar x,
     197             :                         SkScalar y);
     198             : 
     199           0 :     void computeSubRunBounds(SkRect* outBounds, int runIndex, int subRunIndex,
     200             :                              const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
     201             :         // We don't yet position distance field text on the cpu, so we have to map the vertex bounds
     202             :         // into device space.
     203             :         // We handle vertex bounds differently for distance field text and bitmap text because
     204             :         // the vertex bounds of bitmap text are in device space.  If we are flushing multiple runs
     205             :         // from one blob then we are going to pay the price here of mapping the rect for each run.
     206           0 :         const Run& run = fRuns[runIndex];
     207           0 :         const Run::SubRunInfo& subRun = run.fSubRunInfo[subRunIndex];
     208           0 :         *outBounds = subRun.vertexBounds();
     209           0 :         if (subRun.drawAsDistanceFields()) {
     210             :             // Distance field text is positioned with the (X,Y) as part of the glyph position,
     211             :             // and currently the view matrix is applied on the GPU
     212           0 :             outBounds->offset(x - fInitialX, y - fInitialY);
     213           0 :             viewMatrix.mapRect(outBounds);
     214             :         } else {
     215             :             // Bitmap text is fully positioned on the CPU, and offset by an (X,Y) translate in
     216             :             // device space.
     217           0 :             SkMatrix boundsMatrix = fInitialViewMatrixInverse;
     218             : 
     219           0 :             boundsMatrix.postTranslate(-fInitialX, -fInitialY);
     220             : 
     221           0 :             boundsMatrix.postTranslate(x, y);
     222             : 
     223           0 :             boundsMatrix.postConcat(viewMatrix);
     224           0 :             boundsMatrix.mapRect(outBounds);
     225             : 
     226             :             // Due to floating point numerical inaccuracies, we have to round out here
     227           0 :             outBounds->roundOut(outBounds);
     228             :         }
     229           0 :     }
     230             : 
     231             :     // position + local coord
     232             :     static const size_t kColorTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16);
     233             :     static const size_t kGrayTextVASize = sizeof(SkPoint) + sizeof(GrColor) + sizeof(SkIPoint16);
     234             :     static const size_t kLCDTextVASize = kGrayTextVASize;
     235             :     static const size_t kMaxVASize = kGrayTextVASize;
     236             :     static const int kVerticesPerGlyph = 4;
     237             : 
     238             :     static void AssertEqual(const GrAtlasTextBlob&, const GrAtlasTextBlob&);
     239             : 
     240             :     // The color here is the GrPaint color, and it is used to determine whether we
     241             :     // have to regenerate LCD text blobs.
     242             :     // We use this color vs the SkPaint color because it has the colorfilter applied.
     243           0 :     void initReusableBlob(SkColor filteredColor, const SkMatrix& viewMatrix, SkScalar x,
     244             :                           SkScalar y) {
     245           0 :         fFilteredPaintColor = filteredColor;
     246           0 :         this->setupViewMatrix(viewMatrix, x, y);
     247           0 :     }
     248             : 
     249           0 :     void initThrowawayBlob(const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
     250           0 :         this->setupViewMatrix(viewMatrix, x, y);
     251           0 :     }
     252             : 
     253             :     /**
     254             :      * Consecutive calls to regenInOp often use the same SkGlyphCache. If the same instance of
     255             :      * SkAutoGlyphCache is passed to multiple calls of regenInOp then it can save the cost of
     256             :      * multiple detach/attach operations of SkGlyphCache.
     257             :      */
     258             :     void regenInOp(GrDrawOp::Target* target, GrAtlasGlyphCache* fontCache,
     259             :                    GrBlobRegenHelper* helper, int run, int subRun, SkAutoGlyphCache*,
     260             :                    size_t vertexStride, const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
     261             :                    GrColor color, void** vertices, size_t* byteCount, int* glyphCount);
     262             : 
     263             :     const Key& key() const { return fKey; }
     264             : 
     265           0 :     ~GrAtlasTextBlob() {
     266           0 :         for (int i = 0; i < fRunCount; i++) {
     267           0 :             fRuns[i].~Run();
     268             :         }
     269           0 :     }
     270             : 
     271             :     ////////////////////////////////////////////////////////////////////////////////////////////////
     272             :     // Internal test methods
     273             :     std::unique_ptr<GrLegacyMeshDrawOp> test_makeOp(
     274             :             int glyphCount, int run, int subRun, const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
     275             :             const GrTextUtils::Paint& paint, const SkSurfaceProps& props,
     276             :             const GrDistanceFieldAdjustTable* distanceAdjustTable, GrAtlasGlyphCache* cache);
     277             : 
     278             : private:
     279           0 :     GrAtlasTextBlob()
     280           0 :         : fMaxMinScale(-SK_ScalarMax)
     281             :         , fMinMaxScale(SK_ScalarMax)
     282           0 :         , fTextType(0) {}
     283             : 
     284             :     void appendLargeGlyph(GrGlyph* glyph, SkGlyphCache* cache, const SkGlyph& skGlyph,
     285             :                           SkScalar x, SkScalar y, SkScalar scale, bool treatAsBMP);
     286             : 
     287             :     inline void flushRun(GrRenderTargetContext* rtc, const GrClip&, int run,
     288             :                          const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
     289             :                          const GrTextUtils::Paint& paint, const SkSurfaceProps& props,
     290             :                          const GrDistanceFieldAdjustTable* distanceAdjustTable,
     291             :                          GrAtlasGlyphCache* cache);
     292             : 
     293             :     void flushBigGlyphs(GrContext* context, GrRenderTargetContext* rtc, const GrClip& clip,
     294             :                         const SkPaint& paint, const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
     295             :                         const SkIRect& clipBounds);
     296             : 
     297             :     void flushRunAsPaths(GrContext* context, GrRenderTargetContext* rtc,
     298             :                          const SkSurfaceProps& props, const SkTextBlobRunIterator& it,
     299             :                          const GrClip& clip, const GrTextUtils::Paint& paint,
     300             :                          SkDrawFilter* drawFilter, const SkMatrix& viewMatrix,
     301             :                          const SkIRect& clipBounds, SkScalar x, SkScalar y);
     302             : 
     303             :     // This function will only be called when we are generating a blob from scratch. We record the
     304             :     // initial view matrix and initial offsets(x,y), because we record vertex bounds relative to
     305             :     // these numbers.  When blobs are reused with new matrices, we need to return to model space so
     306             :     // we can update the vertex bounds appropriately.
     307           0 :     void setupViewMatrix(const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
     308           0 :         fInitialViewMatrix = viewMatrix;
     309           0 :         if (!viewMatrix.invert(&fInitialViewMatrixInverse)) {
     310           0 :             fInitialViewMatrixInverse = SkMatrix::I();
     311           0 :             SkDebugf("Could not invert viewmatrix\n");
     312             :         }
     313           0 :         fInitialX = x;
     314           0 :         fInitialY = y;
     315             : 
     316             :         // make sure all initial subruns have the correct VM and X/Y applied
     317           0 :         for (int i = 0; i < fRunCount; i++) {
     318           0 :             fRuns[i].fSubRunInfo[0].init(fInitialViewMatrix, x, y);
     319             :         }
     320           0 :     }
     321             : 
     322             :     /*
     323             :      * Each Run inside of the blob can have its texture coordinates regenerated if required.
     324             :      * To determine if regeneration is necessary, fAtlasGeneration is used.  If there have been
     325             :      * any evictions inside of the atlas, then we will simply regenerate Runs.  We could track
     326             :      * this at a more fine grained level, but its not clear if this is worth it, as evictions
     327             :      * should be fairly rare.
     328             :      *
     329             :      * One additional point, each run can contain glyphs with any of the three mask formats.
     330             :      * We call these SubRuns.  Because a subrun must be a contiguous range, we have to create
     331             :      * a new subrun each time the mask format changes in a run.  In theory, a run can have as
     332             :      * many SubRuns as it has glyphs, ie if a run alternates between color emoji and A8.  In
     333             :      * practice, the vast majority of runs have only a single subrun.
     334             :      *
     335             :      * Finally, for runs where the entire thing is too large for the GrAtlasTextContext to
     336             :      * handle, we have a bit to mark the run as flusahable via rendering as paths.  It is worth
     337             :      * pointing. It would be a bit expensive to figure out ahead of time whether or not a run
     338             :      * can flush in this manner, so we always allocate vertices for the run, regardless of
     339             :      * whether or not it is too large.  The benefit of this strategy is that we can always reuse
     340             :      * a blob allocation regardless of viewmatrix changes.  We could store positions for these
     341             :      * glyphs.  However, its not clear if this is a win because we'd still have to either go the
     342             :      * glyph cache to get the path at flush time, or hold onto the path in the cache, which
     343             :      * would greatly increase the memory of these cached items.
     344             :      */
     345           0 :     struct Run {
     346           0 :         Run()
     347           0 :             : fInitialized(false)
     348           0 :             , fDrawAsPaths(false) {
     349             :             // To ensure we always have one subrun, we push back a fresh run here
     350           0 :             fSubRunInfo.push_back();
     351           0 :         }
     352           0 :         struct SubRunInfo {
     353           0 :             SubRunInfo()
     354           0 :                     : fAtlasGeneration(GrDrawOpAtlas::kInvalidAtlasGeneration)
     355             :                     , fVertexStartIndex(0)
     356             :                     , fVertexEndIndex(0)
     357             :                     , fGlyphStartIndex(0)
     358             :                     , fGlyphEndIndex(0)
     359             :                     , fColor(GrColor_ILLEGAL)
     360             :                     , fMaskFormat(kA8_GrMaskFormat)
     361             :                     , fDrawAsDistanceFields(false)
     362           0 :                     , fUseLCDText(false) {
     363           0 :                 fVertexBounds.setLargestInverted();
     364           0 :             }
     365           0 :             SubRunInfo(const SubRunInfo& that)
     366           0 :                 : fBulkUseToken(that.fBulkUseToken)
     367             :                 , fStrike(SkSafeRef(that.fStrike.get()))
     368             :                 , fCurrentViewMatrix(that.fCurrentViewMatrix)
     369             :                 , fVertexBounds(that.fVertexBounds)
     370           0 :                 , fAtlasGeneration(that.fAtlasGeneration)
     371           0 :                 , fVertexStartIndex(that.fVertexStartIndex)
     372           0 :                 , fVertexEndIndex(that.fVertexEndIndex)
     373           0 :                 , fGlyphStartIndex(that.fGlyphStartIndex)
     374           0 :                 , fGlyphEndIndex(that.fGlyphEndIndex)
     375           0 :                 , fX(that.fX)
     376           0 :                 , fY(that.fY)
     377           0 :                 , fColor(that.fColor)
     378           0 :                 , fMaskFormat(that.fMaskFormat)
     379           0 :                 , fDrawAsDistanceFields(that.fDrawAsDistanceFields)
     380           0 :                 , fUseLCDText(that.fUseLCDText) {
     381           0 :             }
     382             : 
     383             :             // TODO when this object is more internal, drop the privacy
     384           0 :             void resetBulkUseToken() { fBulkUseToken.reset(); }
     385           0 :             GrDrawOpAtlas::BulkUseTokenUpdater* bulkUseToken() { return &fBulkUseToken; }
     386           0 :             void setStrike(GrAtlasTextStrike* strike) { fStrike.reset(SkRef(strike)); }
     387           0 :             GrAtlasTextStrike* strike() const { return fStrike.get(); }
     388             : 
     389           0 :             void setAtlasGeneration(uint64_t atlasGeneration) { fAtlasGeneration = atlasGeneration;}
     390           0 :             uint64_t atlasGeneration() const { return fAtlasGeneration; }
     391             : 
     392           0 :             size_t byteCount() const { return fVertexEndIndex - fVertexStartIndex; }
     393           0 :             size_t vertexStartIndex() const { return fVertexStartIndex; }
     394           0 :             size_t vertexEndIndex() const { return fVertexEndIndex; }
     395           0 :             void appendVertices(size_t vertexStride) {
     396           0 :                 fVertexEndIndex += vertexStride * kVerticesPerGlyph;
     397           0 :             }
     398             : 
     399           0 :             uint32_t glyphCount() const { return fGlyphEndIndex - fGlyphStartIndex; }
     400           0 :             uint32_t glyphStartIndex() const { return fGlyphStartIndex; }
     401           0 :             uint32_t glyphEndIndex() const { return fGlyphEndIndex; }
     402           0 :             void glyphAppended() { fGlyphEndIndex++; }
     403           0 :             void setColor(GrColor color) { fColor = color; }
     404           0 :             GrColor color() const { return fColor; }
     405           0 :             void setMaskFormat(GrMaskFormat format) { fMaskFormat = format; }
     406           0 :             GrMaskFormat maskFormat() const { return fMaskFormat; }
     407             : 
     408           0 :             void setAsSuccessor(const SubRunInfo& prev) {
     409           0 :                 fGlyphStartIndex = prev.glyphEndIndex();
     410           0 :                 fGlyphEndIndex = prev.glyphEndIndex();
     411             : 
     412           0 :                 fVertexStartIndex = prev.vertexEndIndex();
     413           0 :                 fVertexEndIndex = prev.vertexEndIndex();
     414             : 
     415             :                 // copy over viewmatrix settings
     416           0 :                 this->init(prev.fCurrentViewMatrix, prev.fX, prev.fY);
     417           0 :             }
     418             : 
     419           0 :             const SkRect& vertexBounds() const { return fVertexBounds; }
     420           0 :             void joinGlyphBounds(const SkRect& glyphBounds) {
     421           0 :                 fVertexBounds.joinNonEmptyArg(glyphBounds);
     422           0 :             }
     423             : 
     424           0 :             void init(const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
     425           0 :                 fCurrentViewMatrix = viewMatrix;
     426           0 :                 fX = x;
     427           0 :                 fY = y;
     428           0 :             }
     429             : 
     430             :             // This function assumes the translation will be applied before it is called again
     431             :             void computeTranslation(const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
     432             :                                     SkScalar*transX, SkScalar* transY);
     433             : 
     434             :             // df properties
     435           0 :             void setUseLCDText(bool useLCDText) { fUseLCDText = useLCDText; }
     436           0 :             bool hasUseLCDText() const { return fUseLCDText; }
     437           0 :             void setDrawAsDistanceFields() { fDrawAsDistanceFields = true; }
     438           0 :             bool drawAsDistanceFields() const { return fDrawAsDistanceFields; }
     439             : 
     440             :         private:
     441             :             GrDrawOpAtlas::BulkUseTokenUpdater fBulkUseToken;
     442             :             sk_sp<GrAtlasTextStrike> fStrike;
     443             :             SkMatrix fCurrentViewMatrix;
     444             :             SkRect fVertexBounds;
     445             :             uint64_t fAtlasGeneration;
     446             :             size_t fVertexStartIndex;
     447             :             size_t fVertexEndIndex;
     448             :             uint32_t fGlyphStartIndex;
     449             :             uint32_t fGlyphEndIndex;
     450             :             SkScalar fX;
     451             :             SkScalar fY;
     452             :             GrColor fColor;
     453             :             GrMaskFormat fMaskFormat;
     454             :             bool fDrawAsDistanceFields; // df property
     455             :             bool fUseLCDText; // df property
     456             :         };
     457             : 
     458           0 :         SubRunInfo& push_back() {
     459             :             // Forward glyph / vertex information to seed the new sub run
     460           0 :             SubRunInfo& newSubRun = fSubRunInfo.push_back();
     461           0 :             const SubRunInfo& prevSubRun = fSubRunInfo.fromBack(1);
     462             : 
     463           0 :             newSubRun.setAsSuccessor(prevSubRun);
     464           0 :             return newSubRun;
     465             :         }
     466             :         static const int kMinSubRuns = 1;
     467             :         sk_sp<SkTypeface> fTypeface;
     468             :         SkSTArray<kMinSubRuns, SubRunInfo> fSubRunInfo;
     469             :         SkAutoDescriptor fDescriptor;
     470             : 
     471             :         // Effects from the paint that are used to build a SkScalerContext.
     472             :         sk_sp<SkPathEffect> fPathEffect;
     473             :         sk_sp<SkRasterizer> fRasterizer;
     474             :         sk_sp<SkMaskFilter> fMaskFilter;
     475             : 
     476             :         // Distance field text cannot draw coloremoji, and so has to fall back.  However,
     477             :         // though the distance field text and the coloremoji may share the same run, they
     478             :         // will have different descriptors.  If fOverrideDescriptor is non-nullptr, then it
     479             :         // will be used in place of the run's descriptor to regen texture coords
     480             :         std::unique_ptr<SkAutoDescriptor> fOverrideDescriptor; // df properties
     481             :         bool fInitialized;
     482             :         bool fDrawAsPaths;
     483             :     };
     484             : 
     485             :     template <bool regenPos, bool regenCol, bool regenTexCoords, bool regenGlyphs>
     486             :     void regenInOp(GrDrawOp::Target* target, GrAtlasGlyphCache* fontCache, GrBlobRegenHelper* helper,
     487             :                    Run* run, Run::SubRunInfo* info, SkAutoGlyphCache*, int glyphCount,
     488             :                    size_t vertexStride, GrColor color, SkScalar transX, SkScalar transY) const;
     489             : 
     490             :     inline std::unique_ptr<GrLegacyMeshDrawOp> makeOp(
     491             :             const Run::SubRunInfo& info, int glyphCount, int run, int subRun,
     492             :             const SkMatrix& viewMatrix, SkScalar x, SkScalar y, const GrTextUtils::Paint& paint,
     493             :             const SkSurfaceProps& props, const GrDistanceFieldAdjustTable* distanceAdjustTable,
     494             :             bool useGammaCorrectDistanceTable, GrAtlasGlyphCache* cache);
     495             : 
     496           0 :     struct BigGlyph {
     497           0 :         BigGlyph(const SkPath& path, SkScalar vx, SkScalar vy, SkScalar scale, bool treatAsBMP)
     498           0 :             : fPath(path)
     499             :             , fScale(scale)
     500             :             , fX(vx)
     501             :             , fY(vy)
     502           0 :             , fTreatAsBMP(treatAsBMP) {}
     503             :         SkPath fPath;
     504             :         SkScalar fScale;
     505             :         SkScalar fX;
     506             :         SkScalar fY;
     507             :         bool fTreatAsBMP;
     508             :     };
     509             : 
     510             :     struct StrokeInfo {
     511             :         SkScalar fFrameWidth;
     512             :         SkScalar fMiterLimit;
     513             :         SkPaint::Join fJoin;
     514             :     };
     515             : 
     516             :     enum TextType {
     517             :         kHasDistanceField_TextType = 0x1,
     518             :         kHasBitmap_TextType = 0x2,
     519             :     };
     520             : 
     521             :     // all glyph / vertex offsets are into these pools.
     522             :     unsigned char* fVertices;
     523             :     GrGlyph** fGlyphs;
     524             :     Run* fRuns;
     525             :     GrMemoryPool* fPool;
     526             :     SkMaskFilter::BlurRec fBlurRec;
     527             :     StrokeInfo fStrokeInfo;
     528             :     SkTArray<BigGlyph> fBigGlyphs;
     529             :     Key fKey;
     530             :     SkMatrix fInitialViewMatrix;
     531             :     SkMatrix fInitialViewMatrixInverse;
     532             :     size_t fSize;
     533             :     SkColor fFilteredPaintColor;
     534             :     SkScalar fInitialX;
     535             :     SkScalar fInitialY;
     536             : 
     537             :     // We can reuse distance field text, but only if the new viewmatrix would not result in
     538             :     // a mip change.  Because there can be multiple runs in a blob, we track the overall
     539             :     // maximum minimum scale, and minimum maximum scale, we can support before we need to regen
     540             :     SkScalar fMaxMinScale;
     541             :     SkScalar fMinMaxScale;
     542             :     int fRunCount;
     543             :     uint8_t fTextType;
     544             : };
     545             : 
     546             : #endif

Generated by: LCOV version 1.13