Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / core / SkGlyphCache.h
1
2 /*
3  * Copyright 2006 The Android Open Source Project
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8
9
10 #ifndef SkGlyphCache_DEFINED
11 #define SkGlyphCache_DEFINED
12
13 #include "SkBitmap.h"
14 #include "SkChunkAlloc.h"
15 #include "SkDescriptor.h"
16 #include "SkGlyph.h"
17 #include "SkScalerContext.h"
18 #include "SkTemplates.h"
19 #include "SkTDArray.h"
20
21 struct SkDeviceProperties;
22 class SkPaint;
23
24 class SkGlyphCache_Globals;
25
26 /** \class SkGlyphCache
27
28     This class represents a strike: a specific combination of typeface, size,
29     matrix, etc., and holds the glyphs for that strike. Calling any of the
30     getUnichar.../getGlyphID... methods will return the requested glyph,
31     either instantly if it is already cached, or by first generating it and then
32     adding it to the strike.
33
34     The strikes are held in a global list, available to all threads. To interact
35     with one, call either VisitCache() or DetachCache().
36 */
37 class SkGlyphCache {
38 public:
39     /** Returns a glyph with valid fAdvance and fDevKern fields.
40         The remaining fields may be valid, but that is not guaranteed. If you
41         require those, call getUnicharMetrics or getGlyphIDMetrics instead.
42     */
43     const SkGlyph& getUnicharAdvance(SkUnichar);
44     const SkGlyph& getGlyphIDAdvance(uint16_t);
45
46     /** Returns a glyph with all fields valid except fImage and fPath, which
47         may be null. If they are null, call findImage or findPath for those.
48         If they are not null, then they are valid.
49
50         This call is potentially slower than the matching ...Advance call. If
51         you only need the fAdvance/fDevKern fields, call those instead.
52     */
53     const SkGlyph& getUnicharMetrics(SkUnichar);
54     const SkGlyph& getGlyphIDMetrics(uint16_t);
55
56     /** These are variants that take the device position of the glyph. Call
57         these only if you are drawing in subpixel mode. Passing 0, 0 is
58         effectively the same as calling the variants w/o the extra params, tho
59         a tiny bit slower.
60     */
61     const SkGlyph& getUnicharMetrics(SkUnichar, SkFixed x, SkFixed y);
62     const SkGlyph& getGlyphIDMetrics(uint16_t, SkFixed x, SkFixed y);
63
64     /** Return the glyphID for the specified Unichar. If the char has already
65         been seen, use the existing cache entry. If not, ask the scalercontext
66         to compute it for us.
67     */
68     uint16_t unicharToGlyph(SkUnichar);
69
70     /** Map the glyph to its Unicode equivalent. Unmappable glyphs map to
71         a character code of zero.
72     */
73     SkUnichar glyphToUnichar(uint16_t);
74
75     /** Returns the number of glyphs for this strike.
76     */
77     unsigned getGlyphCount();
78
79     /** Return the image associated with the glyph. If it has not been generated
80         this will trigger that.
81     */
82     const void* findImage(const SkGlyph&);
83     /** Return the Path associated with the glyph. If it has not been generated
84         this will trigger that.
85     */
86     const SkPath* findPath(const SkGlyph&);
87     /** Return the distance field associated with the glyph. If it has not been generated
88      this will trigger that.
89      */
90     const void* findDistanceField(const SkGlyph&);
91
92     /** Return the vertical metrics for this strike.
93     */
94     const SkPaint::FontMetrics& getFontMetrics() const {
95         return fFontMetrics;
96     }
97
98     const SkDescriptor& getDescriptor() const { return *fDesc; }
99
100     SkMask::Format getMaskFormat() const {
101         return fScalerContext->getMaskFormat();
102     }
103
104     bool isSubpixel() const {
105         return fScalerContext->isSubpixel();
106     }
107
108     /*  AuxProc/Data allow a client to associate data with this cache entry.
109         Multiple clients can use this, as their data is keyed with a function
110         pointer. In addition to serving as a key, the function pointer is called
111         with the data when the glyphcache object is deleted, so the client can
112         cleanup their data as well. NOTE: the auxProc must not try to access
113         this glyphcache in any way, since it may be in the process of being
114         deleted.
115     */
116
117     //! If the proc is found, return true and set *dataPtr to its data
118     bool getAuxProcData(void (*auxProc)(void*), void** dataPtr) const;
119     //! Add a proc/data pair to the glyphcache. proc should be non-null
120     void setAuxProc(void (*auxProc)(void*), void* auxData);
121
122     SkScalerContext* getScalerContext() const { return fScalerContext; }
123
124     /** Find a matching cache entry, and call proc() with it. If none is found
125         create a new one. If the proc() returns true, detach the cache and
126         return it, otherwise leave it and return NULL.
127     */
128     static SkGlyphCache* VisitCache(SkTypeface*, const SkDescriptor* desc,
129                                     bool (*proc)(const SkGlyphCache*, void*),
130                                     void* context);
131
132     /** Given a strike that was returned by either VisitCache() or DetachCache()
133         add it back into the global cache list (after which the caller should
134         not reference it anymore.
135     */
136     static void AttachCache(SkGlyphCache*);
137
138     /** Detach a strike from the global cache matching the specified descriptor.
139         Once detached, it can be queried/modified by the current thread, and
140         when finished, be reattached to the global cache with AttachCache().
141         While detached, if another request is made with the same descriptor,
142         a different strike will be generated. This is fine. It does mean we
143         can have more than 1 strike for the same descriptor, but that will
144         eventually get purged, and the win is that different thread will never
145         block each other while a strike is being used.
146     */
147     static SkGlyphCache* DetachCache(SkTypeface* typeface,
148                                      const SkDescriptor* desc) {
149         return VisitCache(typeface, desc, DetachProc, NULL);
150     }
151
152 #ifdef SK_DEBUG
153     void validate() const;
154 #else
155     void validate() const {}
156 #endif
157
158     class AutoValidate : SkNoncopyable {
159     public:
160         AutoValidate(const SkGlyphCache* cache) : fCache(cache) {
161             if (fCache) {
162                 fCache->validate();
163             }
164         }
165         ~AutoValidate() {
166             if (fCache) {
167                 fCache->validate();
168             }
169         }
170         void forget() {
171             fCache = NULL;
172         }
173     private:
174         const SkGlyphCache* fCache;
175     };
176
177 private:
178     // we take ownership of the scalercontext
179     SkGlyphCache(SkTypeface*, const SkDescriptor*, SkScalerContext*);
180     ~SkGlyphCache();
181
182     enum MetricsType {
183         kJustAdvance_MetricsType,
184         kFull_MetricsType
185     };
186
187     SkGlyph* lookupMetrics(uint32_t id, MetricsType);
188     static bool DetachProc(const SkGlyphCache*, void*) { return true; }
189
190     SkGlyphCache*       fNext, *fPrev;
191     SkDescriptor*       fDesc;
192     SkScalerContext*    fScalerContext;
193     SkPaint::FontMetrics fFontMetrics;
194
195     enum {
196         kHashBits   = 8,
197         kHashCount  = 1 << kHashBits,
198         kHashMask   = kHashCount - 1
199     };
200     SkGlyph*            fGlyphHash[kHashCount];
201     SkTDArray<SkGlyph*> fGlyphArray;
202     SkChunkAlloc        fGlyphAlloc;
203
204     struct CharGlyphRec {
205         uint32_t    fID;    // unichar + subpixel
206         SkGlyph*    fGlyph;
207     };
208     // no reason to use the same kHashCount as fGlyphHash, but we do for now
209     CharGlyphRec    fCharToGlyphHash[kHashCount];
210
211     static inline unsigned ID2HashIndex(uint32_t id) {
212         id ^= id >> 16;
213         id ^= id >> 8;
214         return id & kHashMask;
215     }
216
217     // used to track (approx) how much ram is tied-up in this cache
218     size_t  fMemoryUsed;
219
220     struct AuxProcRec {
221         AuxProcRec* fNext;
222         void (*fProc)(void*);
223         void* fData;
224     };
225     AuxProcRec* fAuxProcList;
226     void invokeAndRemoveAuxProcs();
227
228     inline static SkGlyphCache* FindTail(SkGlyphCache* head);
229
230     friend class SkGlyphCache_Globals;
231 };
232
233 class SkAutoGlyphCacheBase {
234 public:
235     SkGlyphCache* getCache() const { return fCache; }
236
237     void release() {
238         if (fCache) {
239             SkGlyphCache::AttachCache(fCache);
240             fCache = NULL;
241         }
242     }
243
244 protected:
245     // Hide the constructors so we can't create one of these directly.
246     // Create SkAutoGlyphCache or SkAutoGlyphCacheNoCache instead.
247     SkAutoGlyphCacheBase(SkGlyphCache* cache) : fCache(cache) {}
248     SkAutoGlyphCacheBase(SkTypeface* typeface, const SkDescriptor* desc) {
249         fCache = SkGlyphCache::DetachCache(typeface, desc);
250     }
251     SkAutoGlyphCacheBase(const SkPaint& paint,
252                          const SkDeviceProperties* deviceProperties,
253                          const SkMatrix* matrix) {
254         fCache = NULL;
255     }
256     SkAutoGlyphCacheBase() {
257         fCache = NULL;
258     }
259     ~SkAutoGlyphCacheBase() {
260         if (fCache) {
261             SkGlyphCache::AttachCache(fCache);
262         }
263     }
264
265     SkGlyphCache*   fCache;
266
267 private:
268     static bool DetachProc(const SkGlyphCache*, void*);
269 };
270
271 class SkAutoGlyphCache : public SkAutoGlyphCacheBase {
272 public:
273     SkAutoGlyphCache(SkGlyphCache* cache) : SkAutoGlyphCacheBase(cache) {}
274     SkAutoGlyphCache(SkTypeface* typeface, const SkDescriptor* desc) :
275         SkAutoGlyphCacheBase(typeface, desc) {}
276     SkAutoGlyphCache(const SkPaint& paint,
277                      const SkDeviceProperties* deviceProperties,
278                      const SkMatrix* matrix) {
279         fCache = paint.detachCache(deviceProperties, matrix, false);
280     }
281
282 private:
283     SkAutoGlyphCache() : SkAutoGlyphCacheBase() {}
284 };
285 #define SkAutoGlyphCache(...) SK_REQUIRE_LOCAL_VAR(SkAutoGlyphCache)
286
287 class SkAutoGlyphCacheNoGamma : public SkAutoGlyphCacheBase {
288 public:
289     SkAutoGlyphCacheNoGamma(SkGlyphCache* cache) : SkAutoGlyphCacheBase(cache) {}
290     SkAutoGlyphCacheNoGamma(SkTypeface* typeface, const SkDescriptor* desc) :
291         SkAutoGlyphCacheBase(typeface, desc) {}
292     SkAutoGlyphCacheNoGamma(const SkPaint& paint,
293                             const SkDeviceProperties* deviceProperties,
294                             const SkMatrix* matrix) {
295         fCache = paint.detachCache(deviceProperties, matrix, true);
296     }
297
298 private:
299     SkAutoGlyphCacheNoGamma() : SkAutoGlyphCacheBase() {}
300 };
301 #define SkAutoGlyphCacheNoGamma(...) SK_REQUIRE_LOCAL_VAR(SkAutoGlyphCacheNoGamma)
302
303 #endif