1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkGlyphCache_DEFINED
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGlyphCache_DEFINED
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBitmap.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkChunkAlloc.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDescriptor.h"
16bbe50131413098bffed9186660c41f047d881596bungeman@google.com#include "SkGlyph.h"
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScalerContext.h"
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplates.h"
19227b516f233df5870d79d3f8dcbdaa02336b7356mike@reedtribe.org#include "SkTDArray.h"
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.comstruct SkDeviceProperties;
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkPaint;
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkGlyphCache_Globals;
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** \class SkGlyphCache
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    This class represents a strike: a specific combination of typeface, size,
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix, etc., and holds the glyphs for that strike. Calling any of the
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    getUnichar.../getGlyphID... methods will return the requested glyph,
3153e1e4d88a06db62898a3bf75751c042729d7160commit-bot@chromium.org    either instantly if it is already cached, or by first generating it and then
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    adding it to the strike.
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The strikes are held in a global list, available to all threads. To interact
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    with one, call either VisitCache() or DetachCache().
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkGlyphCache {
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns a glyph with valid fAdvance and fDevKern fields.
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        The remaining fields may be valid, but that is not guaranteed. If you
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        require those, call getUnicharMetrics or getGlyphIDMetrics instead.
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkGlyph& getUnicharAdvance(SkUnichar);
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkGlyph& getGlyphIDAdvance(uint16_t);
4598539c607b05f7e25406ae873bf1b24154a36a6freed@google.com
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns a glyph with all fields valid except fImage and fPath, which
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        may be null. If they are null, call findImage or findPath for those.
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        If they are not null, then they are valid.
4998539c607b05f7e25406ae873bf1b24154a36a6freed@google.com
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        This call is potentially slower than the matching ...Advance call. If
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        you only need the fAdvance/fDevKern fields, call those instead.
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkGlyph& getUnicharMetrics(SkUnichar);
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkGlyph& getGlyphIDMetrics(uint16_t);
5598539c607b05f7e25406ae873bf1b24154a36a6freed@google.com
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** These are variants that take the device position of the glyph. Call
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        these only if you are drawing in subpixel mode. Passing 0, 0 is
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        effectively the same as calling the variants w/o the extra params, tho
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        a tiny bit slower.
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkGlyph& getUnicharMetrics(SkUnichar, SkFixed x, SkFixed y);
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkGlyph& getGlyphIDMetrics(uint16_t, SkFixed x, SkFixed y);
6398539c607b05f7e25406ae873bf1b24154a36a6freed@google.com
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Return the glyphID for the specified Unichar. If the char has already
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        been seen, use the existing cache entry. If not, ask the scalercontext
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        to compute it for us.
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t unicharToGlyph(SkUnichar);
6998539c607b05f7e25406ae873bf1b24154a36a6freed@google.com
709d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    /** Map the glyph to its Unicode equivalent. Unmappable glyphs map to
719d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com        a character code of zero.
729d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    */
739d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    SkUnichar glyphToUnichar(uint16_t);
749d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com
750bc7bf5fe418191473f8325d89dd9e74be3ff928ctguil@chromium.org    /** Returns the number of glyphs for this strike.
760bc7bf5fe418191473f8325d89dd9e74be3ff928ctguil@chromium.org    */
770bc7bf5fe418191473f8325d89dd9e74be3ff928ctguil@chromium.org    unsigned getGlyphCount();
780bc7bf5fe418191473f8325d89dd9e74be3ff928ctguil@chromium.org
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Return the image associated with the glyph. If it has not been generated
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this will trigger that.
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const void* findImage(const SkGlyph&);
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Return the Path associated with the glyph. If it has not been generated
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this will trigger that.
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPath* findPath(const SkGlyph&);
87762cd804375ff8478427dba4fe29379562b8fb60commit-bot@chromium.org    /** Return the distance field associated with the glyph. If it has not been generated
88762cd804375ff8478427dba4fe29379562b8fb60commit-bot@chromium.org     this will trigger that.
89762cd804375ff8478427dba4fe29379562b8fb60commit-bot@chromium.org     */
90762cd804375ff8478427dba4fe29379562b8fb60commit-bot@chromium.org    const void* findDistanceField(const SkGlyph&);
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Return the vertical metrics for this strike.
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
940a01f5a2c44f3d6a7fa2d3c837f46894d9b29e5dreed@google.com    const SkPaint::FontMetrics& getFontMetrics() const {
950a01f5a2c44f3d6a7fa2d3c837f46894d9b29e5dreed@google.com        return fFontMetrics;
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
97f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
98f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    const SkDescriptor& getDescriptor() const { return *fDesc; }
99f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
10098539c607b05f7e25406ae873bf1b24154a36a6freed@google.com    SkMask::Format getMaskFormat() const {
10198539c607b05f7e25406ae873bf1b24154a36a6freed@google.com        return fScalerContext->getMaskFormat();
10298539c607b05f7e25406ae873bf1b24154a36a6freed@google.com    }
10398539c607b05f7e25406ae873bf1b24154a36a6freed@google.com
104abf00aaaa0262905ad19b0a0ed654c87276490fcreed@google.com    bool isSubpixel() const {
105abf00aaaa0262905ad19b0a0ed654c87276490fcreed@google.com        return fScalerContext->isSubpixel();
106abf00aaaa0262905ad19b0a0ed654c87276490fcreed@google.com    }
107abf00aaaa0262905ad19b0a0ed654c87276490fcreed@google.com
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  AuxProc/Data allow a client to associate data with this cache entry.
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        Multiple clients can use this, as their data is keyed with a function
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        pointer. In addition to serving as a key, the function pointer is called
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        with the data when the glyphcache object is deleted, so the client can
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        cleanup their data as well. NOTE: the auxProc must not try to access
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this glyphcache in any way, since it may be in the process of being
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        deleted.
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
11698539c607b05f7e25406ae873bf1b24154a36a6freed@google.com
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    //! If the proc is found, return true and set *dataPtr to its data
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool getAuxProcData(void (*auxProc)(void*), void** dataPtr) const;
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    //! Add a proc/data pair to the glyphcache. proc should be non-null
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void setAuxProc(void (*auxProc)(void*), void* auxData);
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12215eeca00684b4d5baad8e47c5b2f77404b978cb0djsollen@google.com    SkScalerContext* getScalerContext() const { return fScalerContext; }
12315eeca00684b4d5baad8e47c5b2f77404b978cb0djsollen@google.com
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Find a matching cache entry, and call proc() with it. If none is found
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        create a new one. If the proc() returns true, detach the cache and
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return it, otherwise leave it and return NULL.
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
12890808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.com    static SkGlyphCache* VisitCache(SkTypeface*, const SkDescriptor* desc,
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                    bool (*proc)(const SkGlyphCache*, void*),
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                    void* context);
13198539c607b05f7e25406ae873bf1b24154a36a6freed@google.com
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Given a strike that was returned by either VisitCache() or DetachCache()
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        add it back into the global cache list (after which the caller should
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        not reference it anymore.
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void AttachCache(SkGlyphCache*);
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Detach a strike from the global cache matching the specified descriptor.
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        Once detached, it can be queried/modified by the current thread, and
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        when finished, be reattached to the global cache with AttachCache().
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        While detached, if another request is made with the same descriptor,
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        a different strike will be generated. This is fine. It does mean we
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        can have more than 1 strike for the same descriptor, but that will
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        eventually get purged, and the win is that different thread will never
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        block each other while a strike is being used.
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
14790808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.com    static SkGlyphCache* DetachCache(SkTypeface* typeface,
14890808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.com                                     const SkDescriptor* desc) {
14990808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.com        return VisitCache(typeface, desc, DetachProc, NULL);
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
152f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com#ifdef SK_DEBUG
153f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    void validate() const;
154f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com#else
155f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    void validate() const {}
156f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com#endif
157f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
158f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    class AutoValidate : SkNoncopyable {
159f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    public:
160f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        AutoValidate(const SkGlyphCache* cache) : fCache(cache) {
161f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com            if (fCache) {
162f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com                fCache->validate();
163f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com            }
164f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        }
165f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        ~AutoValidate() {
166f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com            if (fCache) {
167f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com                fCache->validate();
168f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com            }
169f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        }
170f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        void forget() {
171f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com            fCache = NULL;
172f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        }
173f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    private:
174f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        const SkGlyphCache* fCache;
175f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    };
17698539c607b05f7e25406ae873bf1b24154a36a6freed@google.com
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
1784b60dbe661feadc276f911ee6dfc2058e5aea7careed@google.com    // we take ownership of the scalercontext
1794b60dbe661feadc276f911ee6dfc2058e5aea7careed@google.com    SkGlyphCache(SkTypeface*, const SkDescriptor*, SkScalerContext*);
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~SkGlyphCache();
18198539c607b05f7e25406ae873bf1b24154a36a6freed@google.com
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    enum MetricsType {
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kJustAdvance_MetricsType,
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kFull_MetricsType
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkGlyph* lookupMetrics(uint32_t id, MetricsType);
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static bool DetachProc(const SkGlyphCache*, void*) { return true; }
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkGlyphCache*       fNext, *fPrev;
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDescriptor*       fDesc;
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalerContext*    fScalerContext;
1930a01f5a2c44f3d6a7fa2d3c837f46894d9b29e5dreed@google.com    SkPaint::FontMetrics fFontMetrics;
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    enum {
196262ff953a7f7e9e07b8fa9a792ade920aa5dd926reed@google.com        kHashBits   = 8,
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kHashCount  = 1 << kHashBits,
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kHashMask   = kHashCount - 1
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkGlyph*            fGlyphHash[kHashCount];
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkTDArray<SkGlyph*> fGlyphArray;
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkChunkAlloc        fGlyphAlloc;
20398539c607b05f7e25406ae873bf1b24154a36a6freed@google.com
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    struct CharGlyphRec {
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint32_t    fID;    // unichar + subpixel
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkGlyph*    fGlyph;
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // no reason to use the same kHashCount as fGlyphHash, but we do for now
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    CharGlyphRec    fCharToGlyphHash[kHashCount];
21098539c607b05f7e25406ae873bf1b24154a36a6freed@google.com
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static inline unsigned ID2HashIndex(uint32_t id) {
212b8b619a15874f376196e3e6a8190ba4e3df0058breed@google.com        id ^= id >> 16;
213b8b619a15874f376196e3e6a8190ba4e3df0058breed@google.com        id ^= id >> 8;
214b8b619a15874f376196e3e6a8190ba4e3df0058breed@google.com        return id & kHashMask;
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21698539c607b05f7e25406ae873bf1b24154a36a6freed@google.com
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // used to track (approx) how much ram is tied-up in this cache
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    size_t  fMemoryUsed;
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    struct AuxProcRec {
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        AuxProcRec* fNext;
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        void (*fProc)(void*);
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        void* fData;
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    AuxProcRec* fAuxProcList;
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void invokeAndRemoveAuxProcs();
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    inline static SkGlyphCache* FindTail(SkGlyphCache* head);
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    friend class SkGlyphCache_Globals;
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2332d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverthclass SkAutoGlyphCacheBase {
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2352d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    SkGlyphCache* getCache() const { return fCache; }
2362d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
2372d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    void release() {
238d11f0e0173b349bfac3c98f6d32c10dc7e1ba1famike@reedtribe.org        if (fCache) {
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkGlyphCache::AttachCache(fCache);
2402d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth            fCache = NULL;
241d11f0e0173b349bfac3c98f6d32c10dc7e1ba1famike@reedtribe.org        }
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2442d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverthprotected:
2452d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    // Hide the constructors so we can't create one of these directly.
2462d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    // Create SkAutoGlyphCache or SkAutoGlyphCacheNoCache instead.
2472d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    SkAutoGlyphCacheBase(SkGlyphCache* cache) : fCache(cache) {}
2482d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    SkAutoGlyphCacheBase(SkTypeface* typeface, const SkDescriptor* desc) {
2492d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        fCache = SkGlyphCache::DetachCache(typeface, desc);
2502d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    }
2512d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    SkAutoGlyphCacheBase(const SkPaint& paint,
2522d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                         const SkDeviceProperties* deviceProperties,
2532d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                         const SkMatrix* matrix) {
2542d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        fCache = NULL;
2552d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    }
2562d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    SkAutoGlyphCacheBase() {
2572d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        fCache = NULL;
2582d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    }
2592d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    ~SkAutoGlyphCacheBase() {
260d11f0e0173b349bfac3c98f6d32c10dc7e1ba1famike@reedtribe.org        if (fCache) {
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkGlyphCache::AttachCache(fCache);
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2644d517fdbb145cb95e5e935470df331e1b6667cfcjvanverth
265919ed4c73633e92bfc6694161360c5c3f45728e8scroggo    SkGlyphCache*   fCache;
266919ed4c73633e92bfc6694161360c5c3f45728e8scroggo
2672d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverthprivate:
268919ed4c73633e92bfc6694161360c5c3f45728e8scroggo    static bool DetachProc(const SkGlyphCache*, void*);
269919ed4c73633e92bfc6694161360c5c3f45728e8scroggo};
2702d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
2712d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverthclass SkAutoGlyphCache : public SkAutoGlyphCacheBase {
2722d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverthpublic:
2732d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    SkAutoGlyphCache(SkGlyphCache* cache) : SkAutoGlyphCacheBase(cache) {}
2742d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    SkAutoGlyphCache(SkTypeface* typeface, const SkDescriptor* desc) :
2752d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        SkAutoGlyphCacheBase(typeface, desc) {}
2762d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    SkAutoGlyphCache(const SkPaint& paint,
2772d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                     const SkDeviceProperties* deviceProperties,
2782d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                     const SkMatrix* matrix) {
2792d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        fCache = paint.detachCache(deviceProperties, matrix, false);
2802d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    }
2812d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
2822d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverthprivate:
2832d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    SkAutoGlyphCache() : SkAutoGlyphCacheBase() {}
2842d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth};
285919ed4c73633e92bfc6694161360c5c3f45728e8scroggo#define SkAutoGlyphCache(...) SK_REQUIRE_LOCAL_VAR(SkAutoGlyphCache)
2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2872d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverthclass SkAutoGlyphCacheNoGamma : public SkAutoGlyphCacheBase {
2882d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverthpublic:
2892d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    SkAutoGlyphCacheNoGamma(SkGlyphCache* cache) : SkAutoGlyphCacheBase(cache) {}
2902d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    SkAutoGlyphCacheNoGamma(SkTypeface* typeface, const SkDescriptor* desc) :
2912d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        SkAutoGlyphCacheBase(typeface, desc) {}
2922d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    SkAutoGlyphCacheNoGamma(const SkPaint& paint,
2932d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                            const SkDeviceProperties* deviceProperties,
2942d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                            const SkMatrix* matrix) {
2952d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        fCache = paint.detachCache(deviceProperties, matrix, true);
2962d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    }
2972d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
2982d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverthprivate:
2992d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    SkAutoGlyphCacheNoGamma() : SkAutoGlyphCacheBase() {}
3002d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth};
3012d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#define SkAutoGlyphCacheNoGamma(...) SK_REQUIRE_LOCAL_VAR(SkAutoGlyphCacheNoGamma)
3022d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
304