LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkGlyphCache.h (source / functions) Hit Total Coverage
Test: output.info Lines: 18 28 64.3 %
Date: 2017-07-14 16:53:18 Functions: 8 14 57.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2006 The Android Open Source Project
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
       5             :  */
       6             : 
       7             : #ifndef SkGlyphCache_DEFINED
       8             : #define SkGlyphCache_DEFINED
       9             : 
      10             : #include "SkArenaAlloc.h"
      11             : #include "SkBitmap.h"
      12             : #include "SkDescriptor.h"
      13             : #include "SkGlyph.h"
      14             : #include "SkPaint.h"
      15             : #include "SkTHash.h"
      16             : #include "SkScalerContext.h"
      17             : #include "SkTemplates.h"
      18             : #include "SkTDArray.h"
      19             : #include <memory>
      20             : 
      21             : class SkTraceMemoryDump;
      22             : 
      23             : class SkGlyphCache_Globals;
      24             : 
      25             : /** \class SkGlyphCache
      26             : 
      27             :     This class represents a strike: a specific combination of typeface, size, matrix, etc., and
      28             :     holds the glyphs for that strike. Calling any of the getUnichar.../getGlyphID... methods will
      29             :     return the requested glyph, either instantly if it is already cached, or by first generating
      30             :     it and then adding it to the strike.
      31             : 
      32             :     The strikes are held in a global list, available to all threads. To interact with one, call
      33             :     either VisitCache() or DetachCache().
      34             : */
      35             : class SkGlyphCache {
      36             : public:
      37             :     /** Returns a glyph with valid fAdvance and fDevKern fields. The remaining fields may be
      38             :         valid, but that is not guaranteed. If you require those, call getUnicharMetrics or
      39             :         getGlyphIDMetrics instead.
      40             :     */
      41             :     const SkGlyph& getUnicharAdvance(SkUnichar);
      42             :     const SkGlyph& getGlyphIDAdvance(SkGlyphID);
      43             : 
      44             :     /** Returns a glyph with all fields valid except fImage and fPath, which may be null. If they
      45             :         are null, call findImage or findPath for those. If they are not null, then they are valid.
      46             : 
      47             :         This call is potentially slower than the matching ...Advance call. If you only need the
      48             :         fAdvance/fDevKern fields, call those instead.
      49             :     */
      50             :     const SkGlyph& getUnicharMetrics(SkUnichar);
      51             :     const SkGlyph& getGlyphIDMetrics(SkGlyphID);
      52             : 
      53             :     /** These are variants that take the device position of the glyph. Call these only if you are
      54             :         drawing in subpixel mode. Passing 0, 0 is effectively the same as calling the variants
      55             :         w/o the extra params, though a tiny bit slower.
      56             :     */
      57             :     const SkGlyph& getUnicharMetrics(SkUnichar, SkFixed x, SkFixed y);
      58             :     const SkGlyph& getGlyphIDMetrics(uint16_t, SkFixed x, SkFixed y);
      59             : 
      60             :     /** Return the glyphID for the specified Unichar. If the char has already been seen, use the
      61             :         existing cache entry. If not, ask the scalercontext to compute it for us.
      62             :     */
      63             :     SkGlyphID unicharToGlyph(SkUnichar);
      64             : 
      65             :     /** Map the glyph to its Unicode equivalent. Unmappable glyphs map to a character code of zero.
      66             :     */
      67             :     SkUnichar glyphToUnichar(SkGlyphID);
      68             : 
      69             :     /** Returns the number of glyphs for this strike.
      70             :     */
      71             :     unsigned getGlyphCount() const;
      72             : 
      73             :     /** Return the number of glyphs currently cached. */
      74             :     int countCachedGlyphs() const;
      75             : 
      76             :     /** Return the image associated with the glyph. If it has not been generated this will
      77             :         trigger that.
      78             :     */
      79             :     const void* findImage(const SkGlyph&);
      80             : 
      81             :     /** If the advance axis intersects the glyph's path, append the positions scaled and offset
      82             :         to the array (if non-null), and set the count to the updated array length.
      83             :     */
      84             :     void findIntercepts(const SkScalar bounds[2], SkScalar scale, SkScalar xPos,
      85             :                         bool yAxis, SkGlyph* , SkScalar* array, int* count);
      86             : 
      87             :     /** Return the Path associated with the glyph. If it has not been generated this will trigger
      88             :         that.
      89             :     */
      90             :     const SkPath* findPath(const SkGlyph&);
      91             : 
      92             :     /** Return the vertical metrics for this strike.
      93             :     */
      94           0 :     const SkPaint::FontMetrics& getFontMetrics() const {
      95           0 :         return fFontMetrics;
      96             :     }
      97             : 
      98           0 :     const SkDescriptor& getDescriptor() const { return *fDesc; }
      99             : 
     100             :     SkMask::Format getMaskFormat() const {
     101             :         return fScalerContext->getMaskFormat();
     102             :     }
     103             : 
     104          21 :     bool isSubpixel() const {
     105          21 :         return fScalerContext->isSubpixel();
     106             :     }
     107             : 
     108             :     /** Return the approx RAM usage for this cache. */
     109           0 :     size_t getMemoryUsed() const { return fMemoryUsed; }
     110             : 
     111             :     void dump() const;
     112             : 
     113          21 :     SkScalerContext* getScalerContext() const { return fScalerContext.get(); }
     114             : 
     115             :     /** Find a matching cache entry, and call proc() with it. If none is found create a new one.
     116             :         If the proc() returns true, detach the cache and return it, otherwise leave it and return
     117             :         nullptr.
     118             :     */
     119             :     static SkGlyphCache* VisitCache(SkTypeface*, const SkScalerContextEffects&, const SkDescriptor*,
     120             :                                     bool (*proc)(const SkGlyphCache*, void*),
     121             :                                     void* context);
     122             : 
     123             :     /** Given a strike that was returned by either VisitCache() or DetachCache() add it back into
     124             :         the global cache list (after which the caller should not reference it anymore.
     125             :     */
     126             :     static void AttachCache(SkGlyphCache*);
     127             :     using AttachCacheFunctor = SkFunctionWrapper<void, SkGlyphCache, AttachCache>;
     128             : 
     129             :     /** Detach a strike from the global cache matching the specified descriptor. Once detached,
     130             :         it can be queried/modified by the current thread, and when finished, be reattached to the
     131             :         global cache with AttachCache(). While detached, if another request is made with the same
     132             :         descriptor, a different strike will be generated. This is fine. It does mean we can have
     133             :         more than 1 strike for the same descriptor, but that will eventually get purged, and the
     134             :         win is that different thread will never block each other while a strike is being used.
     135             :     */
     136          21 :     static SkGlyphCache* DetachCache(SkTypeface* typeface, const SkScalerContextEffects& effects,
     137             :                                      const SkDescriptor* desc) {
     138          21 :         return VisitCache(typeface, effects, desc, DetachProc, nullptr);
     139             :     }
     140             : 
     141             :     static void Dump();
     142             : 
     143             :     /** Dump memory usage statistics of all the attaches caches in the process using the
     144             :         SkTraceMemoryDump interface.
     145             :     */
     146             :     static void DumpMemoryStatistics(SkTraceMemoryDump* dump);
     147             : 
     148             :     typedef void (*Visitor)(const SkGlyphCache&, void* context);
     149             :     static void VisitAll(Visitor, void* context);
     150             : 
     151             : #ifdef SK_DEBUG
     152             :     void validate() const;
     153             : #else
     154             :     void validate() const {}
     155             : #endif
     156             : 
     157             :     class AutoValidate : SkNoncopyable {
     158             :     public:
     159         450 :         AutoValidate(const SkGlyphCache* cache) : fCache(cache) {
     160         450 :             if (fCache) {
     161         450 :                 fCache->validate();
     162             :             }
     163         450 :         }
     164         900 :         ~AutoValidate() {
     165         450 :             if (fCache) {
     166         450 :                 fCache->validate();
     167             :             }
     168         450 :         }
     169             :         void forget() {
     170             :             fCache = nullptr;
     171             :         }
     172             :     private:
     173             :         const SkGlyphCache* fCache;
     174             :     };
     175             : 
     176             : private:
     177             :     friend class SkGlyphCache_Globals;
     178             : 
     179             :     enum MetricsType {
     180             :         kJustAdvance_MetricsType,
     181             :         kFull_MetricsType
     182             :     };
     183             : 
     184             :     enum {
     185             :         kHashBits           = 8,
     186             :         kHashCount          = 1 << kHashBits,
     187             :         kHashMask           = kHashCount - 1
     188             :     };
     189             : 
     190           0 :     struct CharGlyphRec {
     191             :         SkPackedUnicharID fPackedUnicharID;
     192             :         SkPackedGlyphID fPackedGlyphID;
     193             :     };
     194             : 
     195             :     SkGlyphCache(const SkDescriptor*, std::unique_ptr<SkScalerContext>);
     196             :     ~SkGlyphCache();
     197             : 
     198             :     // Return the SkGlyph* associated with MakeID. The id parameter is the
     199             :     // combined glyph/x/y id generated by MakeID. If it is just a glyph id
     200             :     // then x and y are assumed to be zero.
     201             :     SkGlyph* lookupByPackedGlyphID(SkPackedGlyphID packedGlyphID, MetricsType type);
     202             : 
     203             :     // Return a SkGlyph* associated with unicode id and position x and y.
     204             :     SkGlyph* lookupByChar(SkUnichar id, MetricsType type, SkFixed x = 0, SkFixed y = 0);
     205             : 
     206             :     // Return a new SkGlyph for the glyph ID and subpixel position id. Limit the amount
     207             :     // of work using type.
     208             :     SkGlyph* allocateNewGlyph(SkPackedGlyphID packedGlyphID, MetricsType type);
     209             : 
     210          21 :     static bool DetachProc(const SkGlyphCache*, void*) { return true; }
     211             : 
     212             :     // The id arg is a combined id generated by MakeID.
     213             :     CharGlyphRec* getCharGlyphRec(SkPackedUnicharID id);
     214             : 
     215             :     static void OffsetResults(const SkGlyph::Intercept* intercept, SkScalar scale,
     216             :                               SkScalar xPos, SkScalar* array, int* count);
     217             :     static void AddInterval(SkScalar val, SkGlyph::Intercept* intercept);
     218             :     static void AddPoints(const SkPoint* pts, int ptCount, const SkScalar bounds[2],
     219             :                           bool yAxis, SkGlyph::Intercept* intercept);
     220             :     static void AddLine(const SkPoint pts[2], SkScalar axis, bool yAxis,
     221             :                         SkGlyph::Intercept* intercept);
     222             :     static void AddQuad(const SkPoint pts[2], SkScalar axis, bool yAxis,
     223             :                         SkGlyph::Intercept* intercept);
     224             :     static void AddCubic(const SkPoint pts[3], SkScalar axis, bool yAxis,
     225             :                          SkGlyph::Intercept* intercept);
     226             :     static const SkGlyph::Intercept* MatchBounds(const SkGlyph* glyph,
     227             :                                                  const SkScalar bounds[2]);
     228             : 
     229             :     SkGlyphCache*          fNext;
     230             :     SkGlyphCache*          fPrev;
     231             :     const std::unique_ptr<SkDescriptor> fDesc;
     232             :     const std::unique_ptr<SkScalerContext> fScalerContext;
     233             :     SkPaint::FontMetrics   fFontMetrics;
     234             : 
     235             :     // Map from a combined GlyphID and sub-pixel position to a SkGlyph.
     236             :     SkTHashTable<SkGlyph, SkPackedGlyphID, SkGlyph::HashTraits> fGlyphMap;
     237             : 
     238             :     // so we don't grow our arrays a lot
     239             :     static constexpr size_t kMinGlyphCount = 8;
     240             :     static constexpr size_t kMinGlyphImageSize = 16 /* height */ * 8 /* width */;
     241             :     static constexpr size_t kMinAllocAmount = kMinGlyphImageSize * kMinGlyphCount;
     242             : 
     243             :     SkArenaAlloc            fAlloc {kMinAllocAmount};
     244             : 
     245             :     std::unique_ptr<CharGlyphRec[]> fPackedUnicharIDToPackedGlyphID;
     246             : 
     247             :     // used to track (approx) how much ram is tied-up in this cache
     248             :     size_t                  fMemoryUsed;
     249             : };
     250             : 
     251          21 : class SkAutoGlyphCache : public std::unique_ptr<SkGlyphCache, SkGlyphCache::AttachCacheFunctor> {
     252             : public:
     253             :     /** deprecated: use get() */
     254           0 :     SkGlyphCache* getCache() const { return this->get(); }
     255             :     SkAutoGlyphCache() = default;
     256             :     SkAutoGlyphCache(SkGlyphCache* cache) : INHERITED(cache) {}
     257             :     SkAutoGlyphCache(SkTypeface* typeface, const SkScalerContextEffects& effects,
     258             :                      const SkDescriptor* desc)
     259             :         : INHERITED(SkGlyphCache::DetachCache(typeface, effects, desc))
     260             :     {}
     261             :     /** deprecated: always enables fake gamma */
     262           0 :     SkAutoGlyphCache(const SkPaint& paint,
     263             :                      const SkSurfaceProps* surfaceProps,
     264             :                      const SkMatrix* matrix)
     265           0 :         : INHERITED(paint.detachCache(surfaceProps,
     266             :                                       SkPaint::kFakeGammaAndBoostContrast_ScalerContextFlags,
     267           0 :                                       matrix))
     268           0 :     {}
     269          21 :     SkAutoGlyphCache(const SkPaint& paint,
     270             :                      const SkSurfaceProps* surfaceProps,
     271             :                      uint32_t scalerContextFlags,
     272             :                      const SkMatrix* matrix)
     273          21 :         : INHERITED(paint.detachCache(surfaceProps, scalerContextFlags, matrix))
     274          21 :     {}
     275             : private:
     276             :     using INHERITED = std::unique_ptr<SkGlyphCache, SkGlyphCache::AttachCacheFunctor>;
     277             : };
     278             : 
     279             : class SkAutoGlyphCacheNoGamma : public SkAutoGlyphCache {
     280             : public:
     281             :     SkAutoGlyphCacheNoGamma(const SkPaint& paint,
     282             :                             const SkSurfaceProps* surfaceProps,
     283             :                             const SkMatrix* matrix)
     284             :         : SkAutoGlyphCache(paint, surfaceProps, SkPaint::kNone_ScalerContextFlags, matrix)
     285             :     {}
     286             : };
     287             : #define SkAutoGlyphCache(...) SK_REQUIRE_LOCAL_VAR(SkAutoGlyphCache)
     288             : #define SkAutoGlyphCacheNoGamma(...) SK_REQUIRE_LOCAL_VAR(SkAutoGlyphCacheNoGamma)
     289             : 
     290             : #endif

Generated by: LCOV version 1.13