~ubuntu-branches/ubuntu/karmic/gears/karmic

« back to all changes in this revision

Viewing changes to third_party/skia/src/core/SkGlyphCache.h

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Lesicnik
  • Date: 2009-04-30 19:15:25 UTC
  • Revision ID: james.westby@ubuntu.com-20090430191525-0790sb5wzg8ou0xb
Tags: upstream-0.5.21.0~svn3334+dfsg
ImportĀ upstreamĀ versionĀ 0.5.21.0~svn3334+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* libs/graphics/sgl/SkGlyphCache.h
 
2
**
 
3
** Copyright 2006, The Android Open Source Project
 
4
**
 
5
** Licensed under the Apache License, Version 2.0 (the "License"); 
 
6
** you may not use this file except in compliance with the License. 
 
7
** You may obtain a copy of the License at 
 
8
**
 
9
**     http://www.apache.org/licenses/LICENSE-2.0 
 
10
**
 
11
** Unless required by applicable law or agreed to in writing, software 
 
12
** distributed under the License is distributed on an "AS IS" BASIS, 
 
13
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 
14
** See the License for the specific language governing permissions and 
 
15
** limitations under the License.
 
16
*/
 
17
 
 
18
#ifndef SkGlyphCache_DEFINED
 
19
#define SkGlyphCache_DEFINED
 
20
 
 
21
#include "SkBitmap.h"
 
22
#include "SkChunkAlloc.h"
 
23
#include "SkDescriptor.h"
 
24
#include "SkScalerContext.h"
 
25
#include "SkTemplates.h"
 
26
 
 
27
class SkPaint;
 
28
 
 
29
class SkGlyphCache_Globals;
 
30
 
 
31
/** \class SkGlyphCache
 
32
 
 
33
    This class represents a strike: a specific combination of typeface, size,
 
34
    matrix, etc., and holds the glyphs for that strike. Calling any of the
 
35
    getUnichar.../getGlyphID... methods will return the requested glyph,
 
36
    either instantly if it is already cahced, or by first generating it and then
 
37
    adding it to the strike.
 
38
 
 
39
    The strikes are held in a global list, available to all threads. To interact
 
40
    with one, call either VisitCache() or DetachCache().
 
41
*/
 
42
class SkGlyphCache {
 
43
public:
 
44
    /** Returns a glyph with valid fAdvance and fDevKern fields.
 
45
        The remaining fields may be valid, but that is not guaranteed. If you
 
46
        require those, call getUnicharMetrics or getGlyphIDMetrics instead.
 
47
    */
 
48
    const SkGlyph& getUnicharAdvance(SkUnichar);
 
49
    const SkGlyph& getGlyphIDAdvance(uint16_t);
 
50
    
 
51
    /** Returns a glyph with all fields valid except fImage and fPath, which
 
52
        may be null. If they are null, call findImage or findPath for those.
 
53
        If they are not null, then they are valid.
 
54
        
 
55
        This call is potentially slower than the matching ...Advance call. If
 
56
        you only need the fAdvance/fDevKern fields, call those instead.
 
57
    */
 
58
    const SkGlyph& getUnicharMetrics(SkUnichar);
 
59
    const SkGlyph& getGlyphIDMetrics(uint16_t);
 
60
    
 
61
    /** These are variants that take the device position of the glyph. Call
 
62
        these only if you are drawing in subpixel mode. Passing 0, 0 is
 
63
        effectively the same as calling the variants w/o the extra params, tho
 
64
        a tiny bit slower.
 
65
    */
 
66
    const SkGlyph& getUnicharMetrics(SkUnichar, SkFixed x, SkFixed y);
 
67
    const SkGlyph& getGlyphIDMetrics(uint16_t, SkFixed x, SkFixed y);
 
68
    
 
69
    /** Return the glyphID for the specified Unichar. If the char has already
 
70
        been seen, use the existing cache entry. If not, ask the scalercontext
 
71
        to compute it for us.
 
72
    */
 
73
    uint16_t unicharToGlyph(SkUnichar);
 
74
    
 
75
    /** Return the image associated with the glyph. If it has not been generated
 
76
        this will trigger that.
 
77
    */
 
78
    const void* findImage(const SkGlyph&);
 
79
    /** Return the Path associated with the glyph. If it has not been generated
 
80
        this will trigger that.
 
81
    */
 
82
    const SkPath* findPath(const SkGlyph&);
 
83
 
 
84
    /** Return the vertical metrics for this strike.
 
85
    */
 
86
    const SkPaint::FontMetrics& getFontMetricsY() const {
 
87
        return fFontMetricsY;
 
88
    }
 
89
    
 
90
    /*  AuxProc/Data allow a client to associate data with this cache entry.
 
91
        Multiple clients can use this, as their data is keyed with a function
 
92
        pointer. In addition to serving as a key, the function pointer is called
 
93
        with the data when the glyphcache object is deleted, so the client can
 
94
        cleanup their data as well. NOTE: the auxProc must not try to access
 
95
        this glyphcache in any way, since it may be in the process of being
 
96
        deleted.
 
97
    */
 
98
    
 
99
    //! If the proc is found, return true and set *dataPtr to its data
 
100
    bool getAuxProcData(void (*auxProc)(void*), void** dataPtr) const;
 
101
    //! Add a proc/data pair to the glyphcache. proc should be non-null
 
102
    void setAuxProc(void (*auxProc)(void*), void* auxData);
 
103
    //! If found, remove the proc/data pair from the glyphcache (does not
 
104
    //  call the proc)
 
105
    void removeAuxProc(void (*auxProc)(void*));
 
106
 
 
107
    /** Call proc on all cache entries, stopping early if proc returns true.
 
108
        The proc should not create or delete caches, since it could produce
 
109
        deadlock.
 
110
    */
 
111
    static void VisitAllCaches(bool (*proc)(SkGlyphCache*, void*), void* ctx);
 
112
    
 
113
    /** Find a matching cache entry, and call proc() with it. If none is found
 
114
        create a new one. If the proc() returns true, detach the cache and
 
115
        return it, otherwise leave it and return NULL.
 
116
    */
 
117
    static SkGlyphCache* VisitCache(const SkDescriptor* desc,
 
118
                                    bool (*proc)(const SkGlyphCache*, void*),
 
119
                                    void* context);
 
120
    
 
121
    /** Given a strike that was returned by either VisitCache() or DetachCache()
 
122
        add it back into the global cache list (after which the caller should
 
123
        not reference it anymore.
 
124
    */
 
125
    static void AttachCache(SkGlyphCache*);
 
126
 
 
127
    /** Detach a strike from the global cache matching the specified descriptor.
 
128
        Once detached, it can be queried/modified by the current thread, and
 
129
        when finished, be reattached to the global cache with AttachCache().
 
130
        While detached, if another request is made with the same descriptor,
 
131
        a different strike will be generated. This is fine. It does mean we
 
132
        can have more than 1 strike for the same descriptor, but that will
 
133
        eventually get purged, and the win is that different thread will never
 
134
        block each other while a strike is being used.
 
135
    */
 
136
    static SkGlyphCache* DetachCache(const SkDescriptor* desc) {
 
137
        return VisitCache(desc, DetachProc, NULL);
 
138
    }
 
139
 
 
140
    /** Return the approximate number of bytes used by the font cache
 
141
    */
 
142
    static size_t GetCacheUsed();
 
143
 
 
144
    /** This can be called to purge old font data, in an attempt to free
 
145
        enough bytes such that the font cache is not using more than the
 
146
        specified number of bytes. It is thread-safe, and may be called at
 
147
        any time.
 
148
        Return true if some amount of the cache was purged.
 
149
    */
 
150
    static bool SetCacheUsed(size_t bytesUsed);
 
151
 
 
152
private:
 
153
    SkGlyphCache(const SkDescriptor*);
 
154
    ~SkGlyphCache();
 
155
    
 
156
    enum MetricsType {
 
157
        kJustAdvance_MetricsType,
 
158
        kFull_MetricsType
 
159
    };
 
160
 
 
161
    SkGlyph* lookupMetrics(uint32_t id, MetricsType);
 
162
    static bool DetachProc(const SkGlyphCache*, void*) { return true; }
 
163
 
 
164
    void detach(SkGlyphCache** head) {
 
165
        if (fPrev) {
 
166
            fPrev->fNext = fNext;
 
167
        } else {
 
168
            *head = fNext;
 
169
        }
 
170
        if (fNext) {
 
171
            fNext->fPrev = fPrev;
 
172
        }
 
173
        fPrev = fNext = NULL;
 
174
    }
 
175
    
 
176
    void attachToHead(SkGlyphCache** head) {
 
177
        SkASSERT(NULL == fPrev && NULL == fNext);
 
178
        if (*head) {
 
179
            (*head)->fPrev = this;
 
180
            fNext = *head;
 
181
        }
 
182
        *head = this;
 
183
    }
 
184
 
 
185
    SkGlyphCache*       fNext, *fPrev;
 
186
    SkDescriptor*       fDesc;
 
187
    SkScalerContext*    fScalerContext;
 
188
    SkPaint::FontMetrics fFontMetricsY;
 
189
 
 
190
    enum {
 
191
        kHashBits   = 8,
 
192
        kHashCount  = 1 << kHashBits,
 
193
        kHashMask   = kHashCount - 1
 
194
    };
 
195
    SkGlyph*            fGlyphHash[kHashCount];
 
196
    SkTDArray<SkGlyph*> fGlyphArray;
 
197
    SkChunkAlloc        fGlyphAlloc;
 
198
    SkChunkAlloc        fImageAlloc;
 
199
    
 
200
    int fMetricsCount, fAdvanceCount;
 
201
 
 
202
    struct CharGlyphRec {
 
203
        uint32_t    fID;    // unichar + subpixel
 
204
        SkGlyph*    fGlyph;
 
205
    };
 
206
    // no reason to use the same kHashCount as fGlyphHash, but we do for now
 
207
    CharGlyphRec    fCharToGlyphHash[kHashCount];
 
208
    
 
209
    enum {
 
210
        // shift so that the top bits fall into kHashBits region
 
211
        kShiftForHashIndex = SkGlyph::kSubShift +
 
212
                             SkGlyph::kSubBits*2 -
 
213
                             kHashBits
 
214
    };
 
215
 
 
216
    static inline unsigned ID2HashIndex(uint32_t id) {
 
217
        return (id ^ (id >> kShiftForHashIndex)) & kHashMask;
 
218
    }
 
219
    
 
220
    // used to track (approx) how much ram is tied-up in this cache
 
221
    size_t  fMemoryUsed;
 
222
 
 
223
    struct AuxProcRec {
 
224
        AuxProcRec* fNext;
 
225
        void (*fProc)(void*);
 
226
        void* fData;
 
227
    };
 
228
    AuxProcRec* fAuxProcList;
 
229
    void invokeAndRemoveAuxProcs();
 
230
 
 
231
    // This relies on the caller to have already acquired the mutex to access the global cache
 
232
    static size_t InternalFreeCache(SkGlyphCache_Globals*, size_t bytesNeeded);
 
233
 
 
234
    inline static SkGlyphCache* FindTail(SkGlyphCache* head);
 
235
    static size_t ComputeMemoryUsed(const SkGlyphCache* head);
 
236
 
 
237
    friend class SkGlyphCache_Globals;
 
238
};
 
239
 
 
240
class SkAutoGlyphCache {
 
241
public:
 
242
    SkAutoGlyphCache(SkGlyphCache* cache) : fCache(cache) {}
 
243
    SkAutoGlyphCache(const SkDescriptor* desc)
 
244
    {
 
245
        fCache = SkGlyphCache::DetachCache(desc);
 
246
    }
 
247
    SkAutoGlyphCache(const SkPaint& paint, const SkMatrix* matrix)
 
248
    {
 
249
        fCache = paint.detachCache(matrix);
 
250
    }
 
251
    ~SkAutoGlyphCache()
 
252
    {
 
253
        if (fCache)
 
254
            SkGlyphCache::AttachCache(fCache);
 
255
    }
 
256
 
 
257
    SkGlyphCache*   getCache() const { return fCache; }
 
258
 
 
259
    void release()
 
260
    {
 
261
        if (fCache)
 
262
        {
 
263
            SkGlyphCache::AttachCache(fCache);
 
264
            fCache = NULL;
 
265
        }
 
266
    }
 
267
private:
 
268
    SkGlyphCache*   fCache;
 
269
    
 
270
    static bool DetachProc(const SkGlyphCache*, void*);
 
271
};
 
272
 
 
273
#endif
 
274