reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 1 | #ifndef SkGLTextCache_DEFINED |
| 2 | #define SkGLTextCache_DEFINED |
| 3 | |
| 4 | #include "SkGL.h" |
| 5 | |
| 6 | class SkGlyph; |
| 7 | |
| 8 | class SkGLTextCache { |
| 9 | public: |
| 10 | SkGLTextCache(); |
| 11 | ~SkGLTextCache(); |
| 12 | |
| 13 | /** Delete all of the strikes in the cache. Pass true if the texture IDs are |
| 14 | still valid, in which case glDeleteTextures will be called. Pass false |
| 15 | if they are invalid (e.g. the gl-context has changed), in which case |
| 16 | they will just be abandoned. |
| 17 | */ |
| 18 | void deleteAllStrikes(bool texturesAreValid); |
| 19 | |
| 20 | class Strike { |
| 21 | public: |
| 22 | int width() const { return fStrikeWidth; } |
| 23 | int height() const { return fStrikeHeight; } |
| 24 | GLuint texture() const { return fTexName; } |
| 25 | int widthShift() const { return fStrikeWidthShift; } |
| 26 | int heightShift() const { return fStrikeHeightShift; } |
| 27 | |
| 28 | // call this to force us to ignore the texture name in our destructor |
| 29 | // only call it right before our destructor |
| 30 | void abandonTexture() { fTexName = 0; } |
| 31 | |
| 32 | private: |
| 33 | // if next is non-null, its height must match our height |
| 34 | Strike(Strike* next, int width, int height); |
| 35 | ~Strike(); |
| 36 | |
| 37 | Strike* findGlyph(const SkGlyph&, int* offset); |
| 38 | Strike* addGlyphAndBind(const SkGlyph&, const uint8_t*, int* offset); |
| 39 | |
| 40 | enum { |
| 41 | kMinStrikeWidth = 1024, |
| 42 | kMaxGlyphCount = 256 |
| 43 | }; |
| 44 | |
| 45 | Strike* fNext; |
| 46 | GLuint fTexName; |
| 47 | uint32_t fGlyphIDArray[kMaxGlyphCount]; // stores glyphIDs |
| 48 | uint16_t fGlyphOffsetX[kMaxGlyphCount]; // stores x-offsets |
| 49 | uint16_t fGlyphCount; |
| 50 | uint16_t fNextFreeOffsetX; |
| 51 | uint16_t fStrikeWidth; |
| 52 | uint16_t fStrikeHeight; |
| 53 | uint8_t fStrikeWidthShift; // pow2(fStrikeWidth) |
| 54 | uint8_t fStrikeHeightShift; // pow2(fStrikeHeight) |
| 55 | |
| 56 | friend class SkGLTextCache; |
| 57 | }; |
| 58 | |
| 59 | /** If found, returns the exact strike containing it (there may be more than |
| 60 | one with a given height), and sets offset to the offset for that glyph |
| 61 | (if not null). Does NOT bind the texture. |
| 62 | If not found, returns null and ignores offset param. |
| 63 | */ |
| 64 | Strike* findGlyph(const SkGlyph&, int* offset); |
| 65 | |
| 66 | /** Adds the specified glyph to this list of strikes, returning the new |
| 67 | head of the list. If offset is not null, it is set to the offset |
| 68 | for this glyph within the strike. The associated texture is bound |
| 69 | to the gl context. |
| 70 | */ |
| 71 | Strike* addGlyphAndBind(const SkGlyph&, const uint8_t image[], int* offset); |
| 72 | |
| 73 | private: |
| 74 | enum { |
| 75 | // greater than this we won't cache |
| 76 | kMaxGlyphHeightShift = 9, |
| 77 | |
| 78 | kMaxGlyphHeight = 1 << kMaxGlyphHeightShift, |
| 79 | kMaxStrikeListCount = kMaxGlyphHeightShift + 1 |
| 80 | }; |
| 81 | |
| 82 | // heads of the N families, one for each pow2 height |
| 83 | Strike* fStrikeList[kMaxStrikeListCount]; |
| 84 | }; |
| 85 | |
| 86 | #endif |