grab from latest android



git-svn-id: http://skia.googlecode.com/svn/trunk@27 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gl/SkGLTextCache.h b/src/gl/SkGLTextCache.h
new file mode 100644
index 0000000..eb552aa
--- /dev/null
+++ b/src/gl/SkGLTextCache.h
@@ -0,0 +1,86 @@
+#ifndef SkGLTextCache_DEFINED
+#define SkGLTextCache_DEFINED
+
+#include "SkGL.h"
+
+class SkGlyph;
+
+class SkGLTextCache {
+public:
+    SkGLTextCache();
+    ~SkGLTextCache();
+    
+    /** Delete all of the strikes in the cache. Pass true if the texture IDs are
+        still valid, in which case glDeleteTextures will be called. Pass false
+        if they are invalid (e.g. the gl-context has changed), in which case
+        they will just be abandoned.
+    */
+    void deleteAllStrikes(bool texturesAreValid);
+
+    class Strike {
+    public:
+        int width() const { return fStrikeWidth; }
+        int height() const { return fStrikeHeight; }
+        GLuint texture() const { return fTexName; }
+        int widthShift() const { return fStrikeWidthShift; }
+        int heightShift() const { return fStrikeHeightShift; }
+
+        // call this to force us to ignore the texture name in our destructor
+        // only call it right before our destructor
+        void abandonTexture() { fTexName = 0; }
+
+    private:
+        // if next is non-null, its height must match our height
+        Strike(Strike* next, int width, int height);
+        ~Strike();
+
+        Strike* findGlyph(const SkGlyph&, int* offset);
+        Strike* addGlyphAndBind(const SkGlyph&, const uint8_t*, int* offset);
+
+        enum {
+            kMinStrikeWidth = 1024,
+            kMaxGlyphCount = 256
+        };
+
+        Strike*     fNext;
+        GLuint      fTexName;
+        uint32_t    fGlyphIDArray[kMaxGlyphCount];  // stores glyphIDs
+        uint16_t    fGlyphOffsetX[kMaxGlyphCount];  // stores x-offsets
+        uint16_t    fGlyphCount;
+        uint16_t    fNextFreeOffsetX;
+        uint16_t    fStrikeWidth;
+        uint16_t    fStrikeHeight;
+        uint8_t     fStrikeWidthShift;      // pow2(fStrikeWidth)
+        uint8_t     fStrikeHeightShift;     // pow2(fStrikeHeight)
+
+        friend class SkGLTextCache;
+    };
+
+    /** If found, returns the exact strike containing it (there may be more than
+        one with a given height), and sets offset to the offset for that glyph
+        (if not null). Does NOT bind the texture.
+        If not found, returns null and ignores offset param.
+    */
+    Strike* findGlyph(const SkGlyph&, int* offset);
+
+    /** Adds the specified glyph to this list of strikes, returning the new
+        head of the list. If offset is not null, it is set to the offset
+        for this glyph within the strike. The associated texture is bound
+        to the gl context.
+     */
+    Strike* addGlyphAndBind(const SkGlyph&, const uint8_t image[], int* offset);
+
+private:
+    enum {
+        // greater than this we won't cache
+        kMaxGlyphHeightShift = 9,
+        
+        kMaxGlyphHeight = 1 << kMaxGlyphHeightShift,
+        kMaxStrikeListCount = kMaxGlyphHeightShift + 1
+    };
+
+    // heads of the N families, one for each pow2 height
+    Strike* fStrikeList[kMaxStrikeListCount];
+};
+
+#endif