/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
 */

#ifndef SkGlyphCache_DEFINED
#define SkGlyphCache_DEFINED

#include "SkBitmap.h"
#include "SkChunkAlloc.h"
#include "SkDescriptor.h"
#include "SkGlyph.h"
#include "SkMutex.h"
#include "SkTHash.h"
#include "SkScalerContext.h"
#include "SkSharedMutex.h"
#include "SkSpinlock.h"
#include "SkTemplates.h"
#include "SkTDArray.h"

class SkPaint;
class SkTraceMemoryDump;

class SkGlyphCache_Globals;

/** \class SkGlyphCache

    This class represents a strike: a specific combination of typeface, size, matrix, etc., and
    holds the glyphs for that strike. Calling any of the getUnichar.../getGlyphID... methods will
    return the requested glyph, either instantly if it is already cached, or by first generating
    it and then adding it to the strike.

    The strikes are held in a global list, available to all threads. To interact with one, call
    either VisitCache() or DetachCache().
*/
class SkGlyphCache {
public:
    /** Returns a glyph with valid fAdvance and fDevKern fields. The remaining fields may be
        valid, but that is not guaranteed. If you require those, call getUnicharMetrics or
        getGlyphIDMetrics instead.
    */
    const SkGlyph& getUnicharAdvance(SkUnichar);
    const SkGlyph& getGlyphIDAdvance(uint16_t);

    /** Returns a glyph with all fields valid except fImage and fPath, which may be null. If they
        are null, call findImage or findPath for those. If they are not null, then they are valid.

        This call is potentially slower than the matching ...Advance call. If you only need the
        fAdvance/fDevKern fields, call those instead.
    */
    const SkGlyph& getUnicharMetrics(SkUnichar);
    const SkGlyph& getGlyphIDMetrics(uint16_t);

    /** These are variants that take the device position of the glyph. Call these only if you are
        drawing in subpixel mode. Passing 0, 0 is effectively the same as calling the variants
        w/o the extra params, though a tiny bit slower.
    */
    const SkGlyph& getUnicharMetrics(SkUnichar, SkFixed x, SkFixed y);
    const SkGlyph& getGlyphIDMetrics(uint16_t, SkFixed x, SkFixed y);

    /** Return the glyphID for the specified Unichar. If the char has already been seen, use the
        existing cache entry. If not, ask the scalercontext to compute it for us.
    */
    uint16_t unicharToGlyph(SkUnichar);

    /** Map the glyph to its Unicode equivalent. Unmappable glyphs map to a character code of zero.
    */
    SkUnichar glyphToUnichar(uint16_t);

    /** Returns the number of glyphs for this strike.
    */
    unsigned getGlyphCount() const;

    /** Return the number of glyphs currently cached. */
    int countCachedGlyphs() const;

    /** Return the image associated with the glyph. If it has not been generated this will
        trigger that.
    */
    const void* findImage(const SkGlyph&);

    /** Return the Path associated with the glyph. If it has not been generated this will trigger
        that.
    */
    const SkPath* findPath(const SkGlyph&);

    /** Return the vertical metrics for this strike.
    */
    const SkPaint::FontMetrics& getFontMetrics() const {
        return fFontMetrics;
    }

    const SkDescriptor& getDescriptor() const { return *fDesc; }

    SkMask::Format getMaskFormat() const {
        return fScalerContext->getMaskFormat();
    }

    bool isSubpixel() const {
        return fScalerContext->isSubpixel();
    }

    /** Return the approx RAM usage for this cache. */
    size_t getMemoryUsed() const { return fMemoryUsed; }

    void dump() const;

    /** AuxProc/Data allow a client to associate data with this cache entry. Multiple clients can
        use this, as their data is keyed with a function pointer. In addition to serving as a
        key, the function pointer is called with the data when the glyphcache object is deleted,
        so the client can cleanup their data as well.
        NOTE: the auxProc must not try to access this glyphcache in any way, since it may be in
        the process of being deleted.
    */

    //! If the proc is found, return true and set *dataPtr to its data
    bool getAuxProcData(void (*auxProc)(void*), void** dataPtr) const;

    //! Add a proc/data pair to the glyphcache. proc should be non-null
    void setAuxProc(void (*auxProc)(void*), void* auxData);

    SkScalerContext* getScalerContext() const { return fScalerContext; }

    struct GlyphAndCache {
        SkGlyphCache* cache;
        const SkGlyph* glyph;
    };

    static void OnceFillInImage(GlyphAndCache gc);

    static void OnceFillInPath(GlyphAndCache gc);

    typedef bool (*VisitProc)(const SkGlyphCache*, void*);

    /** Find a matching cache entry, and call proc() with it. If none is found create a new one.
        If the proc() returns true, detach the cache and return it, otherwise leave it and return
        nullptr.
    */
    static SkGlyphCache* VisitCache(SkTypeface*, const SkDescriptor* desc,
                                    VisitProc proc,
                                    void* context);

    /** Given a strike that was returned by either VisitCache() or DetachCache() add it back into
        the global cache list (after which the caller should not reference it anymore.
    */
    static void AttachCache(SkGlyphCache*);

    /** Detach a strike from the global cache matching the specified descriptor. Once detached,
        it can be queried/modified by the current thread, and when finished, be reattached to the
        global cache with AttachCache(). While detached, if another request is made with the same
        descriptor, a different strike will be generated. This is fine. It does mean we can have
        more than 1 strike for the same descriptor, but that will eventually get purged, and the
        win is that different thread will never block each other while a strike is being used.
    */
    static SkGlyphCache* DetachCache(SkTypeface* typeface, const SkDescriptor* desc) {
        return VisitCache(typeface, desc, DetachProc, nullptr);
    }

    static void Dump();

    /** Dump memory usage statistics of all the attaches caches in the process using the
        SkTraceMemoryDump interface.
    */
    static void DumpMemoryStatistics(SkTraceMemoryDump* dump);

    typedef void (*Visitor)(const SkGlyphCache&, void* context);
    static void VisitAll(Visitor, void* context);

#ifdef SK_DEBUG
    void validate() const;
#else
    void validate() const {}
#endif

    class AutoValidate : SkNoncopyable {
    public:
        AutoValidate(const SkGlyphCache* cache) : fCache(cache) {
            if (fCache) {
                fCache->validate();
            }
        }
        ~AutoValidate() {
            if (fCache) {
                fCache->validate();
            }
        }
        void forget() {
            fCache = nullptr;
        }
    private:
        const SkGlyphCache* fCache;
    };

private:
    friend class SkGlyphCache_Globals;

    typedef uint32_t PackedGlyphID;    // glyph-index + subpixel-pos
    typedef uint32_t PackedUnicharID;  // unichar + subpixel-pos

    struct CharGlyphRec {
        class HashTraits {
        public:
            static PackedUnicharID GetKey(const CharGlyphRec& rec) {
                return rec.fPackedUnicharID;
            }
            static uint32_t Hash(PackedUnicharID unicharID) {
                return SkChecksum::CheapMix(unicharID);
            }
        };
        PackedUnicharID fPackedUnicharID;
        PackedGlyphID fPackedGlyphID;
    };

    struct AuxProcRec {
        AuxProcRec* fNext;
        void (*fProc)(void*);
        void* fData;
    };

    // SkGlyphCache takes ownership of the scalercontext.
    SkGlyphCache(SkTypeface*, const SkDescriptor*, SkScalerContext*);
    ~SkGlyphCache();

    // Increase the memory used keeping the cache and the global size in sync.
    void increaseMemoryUsed(size_t used);

    // Return the SkGlyph* associated with MakeID. The id parameter is the
    // combined glyph/x/y id generated by MakeID. If it is just a glyph id
    // then x and y are assumed to be zero.
    SkGlyph* lookupByPackedGlyphID(PackedGlyphID packedGlyphID);

    // Return a SkGlyph* associated with unicode id and position x and y.
    SkGlyph* lookupByChar(SkUnichar id, SkFixed x = 0, SkFixed y = 0);

    // Return a new SkGlyph for the glyph ID and subpixel position id.
    SkGlyph* allocateNewGlyph(PackedGlyphID packedGlyphID);

    // Add the full metrics to an existing glyph.
    void addFullMetrics(SkGlyph* glyph);

    static bool DetachProc(const SkGlyphCache*, void*) { return true; }

    CharGlyphRec PackedUnicharIDtoCharGlyphRec(PackedUnicharID packedUnicharID);

    // The id arg is a combined id generated by MakeID.
    CharGlyphRec* getCharGlyphRec(PackedUnicharID id);

    inline static SkGlyphCache* FindTail(SkGlyphCache* head);

    // The following are protected by the SkGlyphCache_Globals fLock mutex.
    // Note: the following fields are protected by a mutex in a different class.
    SkGlyphCache*          fNext;
    SkGlyphCache*          fPrev;
    SkDescriptor* const    fDesc;
    SkPaint::FontMetrics   fFontMetrics;
    int                    fRefCount;

    // The following fields are protected by fMapMutex.
    mutable SkSharedMutex fMapMutex;
    // Map from a combined GlyphID and sub-pixel position to a SkGlyph.
    SkTHashTable<SkGlyph, PackedGlyphID, SkGlyph::HashTraits> fGlyphMap;
    SkChunkAlloc           fGlyphAlloc;
    typedef SkTHashTable<CharGlyphRec, PackedUnicharID, CharGlyphRec::HashTraits>
            PackedUnicharIDToPackedGlyphIDMap;
    SkAutoTDelete<PackedUnicharIDToPackedGlyphIDMap> fPackedUnicharIDToPackedGlyphID;
    // used to track (approx) how much ram is tied-up in this cache
    size_t                 fMemoryUsed;

    // The FScalerMutex protects the following fields. It is mainly used to ensure single-threaded
    // access to the font scaler, but it also protects the fAuxProcList.
    mutable SkMutex        fScalerMutex;
    SkScalerContext* const fScalerContext;
    AuxProcRec*            fAuxProcList;

    // BEWARE: Mutex ordering
    // If you need to hold both fMapMutex and fScalerMutex then fMapMutex must be held first.
};

class SkAutoGlyphCacheBase {
public:
    SkGlyphCache* getCache() const { return fCache; }

    void release() {
        if (fCache) {
            SkGlyphCache::AttachCache(fCache);
            fCache = nullptr;
        }
    }

protected:
    // Hide the constructors so we can't create one of these directly. Create SkAutoGlyphCache or
    // SkAutoGlyphCacheNoCache instead.
    SkAutoGlyphCacheBase(SkGlyphCache* cache) : fCache(cache) {}
    SkAutoGlyphCacheBase(SkTypeface* typeface, const SkDescriptor* desc) {
        fCache = SkGlyphCache::DetachCache(typeface, desc);
    }
    SkAutoGlyphCacheBase(const SkPaint& /*paint*/,
                         const SkSurfaceProps* /*surfaceProps*/,
                         const SkMatrix* /*matrix*/) {
        fCache = nullptr;
    }
    SkAutoGlyphCacheBase() {
        fCache = nullptr;
    }
    ~SkAutoGlyphCacheBase() {
        if (fCache) {
            SkGlyphCache::AttachCache(fCache);
        }
    }

    SkGlyphCache*   fCache;

private:
    static bool DetachProc(const SkGlyphCache*, void*);
};

class SkAutoGlyphCache : public SkAutoGlyphCacheBase {
public:
    SkAutoGlyphCache(SkGlyphCache* cache) : SkAutoGlyphCacheBase(cache) {}
    SkAutoGlyphCache(SkTypeface* typeface, const SkDescriptor* desc) :
        SkAutoGlyphCacheBase(typeface, desc) {}
    SkAutoGlyphCache(const SkPaint& paint,
                     const SkSurfaceProps* surfaceProps,
                     const SkMatrix* matrix) {
        fCache = paint.detachCache(surfaceProps, matrix, false);
    }

private:
    SkAutoGlyphCache() : SkAutoGlyphCacheBase() {}
};
#define SkAutoGlyphCache(...) SK_REQUIRE_LOCAL_VAR(SkAutoGlyphCache)

class SkAutoGlyphCacheNoGamma : public SkAutoGlyphCacheBase {
public:
    SkAutoGlyphCacheNoGamma(SkGlyphCache* cache) : SkAutoGlyphCacheBase(cache) {}
    SkAutoGlyphCacheNoGamma(SkTypeface* typeface, const SkDescriptor* desc) :
        SkAutoGlyphCacheBase(typeface, desc) {}
    SkAutoGlyphCacheNoGamma(const SkPaint& paint,
                            const SkSurfaceProps* surfaceProps,
                            const SkMatrix* matrix) {
        fCache = paint.detachCache(surfaceProps, matrix, true);
    }

private:
    SkAutoGlyphCacheNoGamma() : SkAutoGlyphCacheBase() {}
};
#define SkAutoGlyphCacheNoGamma(...) SK_REQUIRE_LOCAL_VAR(SkAutoGlyphCacheNoGamma)

#endif
