1
/* libs/graphics/sgl/SkGlyphCache.h
3
** Copyright 2006, The Android Open Source Project
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
9
** http://www.apache.org/licenses/LICENSE-2.0
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.
18
#ifndef SkGlyphCache_DEFINED
19
#define SkGlyphCache_DEFINED
22
#include "SkChunkAlloc.h"
23
#include "SkDescriptor.h"
24
#include "SkScalerContext.h"
25
#include "SkTemplates.h"
29
class SkGlyphCache_Globals;
31
/** \class SkGlyphCache
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.
39
The strikes are held in a global list, available to all threads. To interact
40
with one, call either VisitCache() or DetachCache().
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.
48
const SkGlyph& getUnicharAdvance(SkUnichar);
49
const SkGlyph& getGlyphIDAdvance(uint16_t);
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.
55
This call is potentially slower than the matching ...Advance call. If
56
you only need the fAdvance/fDevKern fields, call those instead.
58
const SkGlyph& getUnicharMetrics(SkUnichar);
59
const SkGlyph& getGlyphIDMetrics(uint16_t);
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
66
const SkGlyph& getUnicharMetrics(SkUnichar, SkFixed x, SkFixed y);
67
const SkGlyph& getGlyphIDMetrics(uint16_t, SkFixed x, SkFixed y);
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
73
uint16_t unicharToGlyph(SkUnichar);
75
/** Return the image associated with the glyph. If it has not been generated
76
this will trigger that.
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.
82
const SkPath* findPath(const SkGlyph&);
84
/** Return the vertical metrics for this strike.
86
const SkPaint::FontMetrics& getFontMetricsY() const {
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
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
105
void removeAuxProc(void (*auxProc)(void*));
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
111
static void VisitAllCaches(bool (*proc)(SkGlyphCache*, void*), void* ctx);
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.
117
static SkGlyphCache* VisitCache(const SkDescriptor* desc,
118
bool (*proc)(const SkGlyphCache*, void*),
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.
125
static void AttachCache(SkGlyphCache*);
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.
136
static SkGlyphCache* DetachCache(const SkDescriptor* desc) {
137
return VisitCache(desc, DetachProc, NULL);
140
/** Return the approximate number of bytes used by the font cache
142
static size_t GetCacheUsed();
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
148
Return true if some amount of the cache was purged.
150
static bool SetCacheUsed(size_t bytesUsed);
153
SkGlyphCache(const SkDescriptor*);
157
kJustAdvance_MetricsType,
161
SkGlyph* lookupMetrics(uint32_t id, MetricsType);
162
static bool DetachProc(const SkGlyphCache*, void*) { return true; }
164
void detach(SkGlyphCache** head) {
166
fPrev->fNext = fNext;
171
fNext->fPrev = fPrev;
173
fPrev = fNext = NULL;
176
void attachToHead(SkGlyphCache** head) {
177
SkASSERT(NULL == fPrev && NULL == fNext);
179
(*head)->fPrev = this;
185
SkGlyphCache* fNext, *fPrev;
187
SkScalerContext* fScalerContext;
188
SkPaint::FontMetrics fFontMetricsY;
192
kHashCount = 1 << kHashBits,
193
kHashMask = kHashCount - 1
195
SkGlyph* fGlyphHash[kHashCount];
196
SkTDArray<SkGlyph*> fGlyphArray;
197
SkChunkAlloc fGlyphAlloc;
198
SkChunkAlloc fImageAlloc;
200
int fMetricsCount, fAdvanceCount;
202
struct CharGlyphRec {
203
uint32_t fID; // unichar + subpixel
206
// no reason to use the same kHashCount as fGlyphHash, but we do for now
207
CharGlyphRec fCharToGlyphHash[kHashCount];
210
// shift so that the top bits fall into kHashBits region
211
kShiftForHashIndex = SkGlyph::kSubShift +
212
SkGlyph::kSubBits*2 -
216
static inline unsigned ID2HashIndex(uint32_t id) {
217
return (id ^ (id >> kShiftForHashIndex)) & kHashMask;
220
// used to track (approx) how much ram is tied-up in this cache
225
void (*fProc)(void*);
228
AuxProcRec* fAuxProcList;
229
void invokeAndRemoveAuxProcs();
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);
234
inline static SkGlyphCache* FindTail(SkGlyphCache* head);
235
static size_t ComputeMemoryUsed(const SkGlyphCache* head);
237
friend class SkGlyphCache_Globals;
240
class SkAutoGlyphCache {
242
SkAutoGlyphCache(SkGlyphCache* cache) : fCache(cache) {}
243
SkAutoGlyphCache(const SkDescriptor* desc)
245
fCache = SkGlyphCache::DetachCache(desc);
247
SkAutoGlyphCache(const SkPaint& paint, const SkMatrix* matrix)
249
fCache = paint.detachCache(matrix);
254
SkGlyphCache::AttachCache(fCache);
257
SkGlyphCache* getCache() const { return fCache; }
263
SkGlyphCache::AttachCache(fCache);
268
SkGlyphCache* fCache;
270
static bool DetachProc(const SkGlyphCache*, void*);