TextLayoutCache.h revision d686d76814f18061e06995df0d5de9feb9f70a7e
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ANDROID_TEXT_LAYOUT_CACHE_H
18#define ANDROID_TEXT_LAYOUT_CACHE_H
19
20#include "RtlProperties.h"
21
22#include <stddef.h>
23#include <utils/threads.h>
24#include <utils/String16.h>
25#include <utils/GenerationCache.h>
26#include <utils/Compare.h>
27#include <utils/RefBase.h>
28#include <utils/Singleton.h>
29
30#include <SkPaint.h>
31#include <SkTemplates.h>
32#include <SkUtils.h>
33#include <SkScalerContext.h>
34#include <SkAutoKern.h>
35
36#include <unicode/ubidi.h>
37#include <unicode/ushape.h>
38#include "HarfbuzzSkia.h"
39#include "harfbuzz-shaper.h"
40
41#include <android_runtime/AndroidRuntime.h>
42
43#define UNICODE_NOT_A_CHAR              0xffff
44#define UNICODE_ZWSP                    0x200b
45#define UNICODE_FIRST_LOW_SURROGATE     0xdc00
46#define UNICODE_FIRST_HIGH_SURROGATE    0xd800
47#define UNICODE_FIRST_PRIVATE_USE       0xe000
48#define UNICODE_FIRST_RTL_CHAR          0x0590
49
50// Temporary buffer size
51#define CHAR_BUFFER_SIZE 80
52
53// Converts a number of mega-bytes into bytes
54#define MB(s) s * 1024 * 1024
55
56// Define the default cache size in Mb
57#define DEFAULT_TEXT_LAYOUT_CACHE_SIZE_IN_MB 0.250f
58
59// Define the interval in number of cache hits between two statistics dump
60#define DEFAULT_DUMP_STATS_CACHE_HIT_INTERVAL 100
61
62namespace android {
63
64/**
65 * TextLayoutCacheKey is the Cache key
66 */
67class TextLayoutCacheKey {
68public:
69    TextLayoutCacheKey();
70
71    TextLayoutCacheKey(const SkPaint* paint,
72            const UChar* text, size_t contextCount, int dirFlags);
73
74    TextLayoutCacheKey(const TextLayoutCacheKey& other);
75
76    bool operator<(const TextLayoutCacheKey& rhs) const;
77
78    /**
79     * We need to copy the text when we insert the key into the cache itself.
80     * We don't need to copy the text when we are only comparing keys.
81     */
82    void internalTextCopy();
83
84    /**
85     * Get the size of the Cache key.
86     */
87    size_t getSize();
88
89private:
90    const UChar* text; // if text is NULL, use textCopy
91    String16 textCopy;
92    size_t contextCount;
93    int dirFlags;
94    SkTypeface* typeface;
95    SkScalar textSize;
96    SkScalar textSkewX;
97    SkScalar textScaleX;
98    uint32_t flags;
99    SkPaint::Hinting hinting;
100
101    inline const UChar* getText() const {
102        return text ? text : textCopy.string();
103    }
104}; // TextLayoutCacheKey
105
106/*
107 * TextLayoutCacheValue is the Cache value
108 */
109class TextLayoutCacheValue : public RefBase {
110protected:
111    ~TextLayoutCacheValue();
112
113public:
114    TextLayoutCacheValue();
115
116    void setElapsedTime(uint32_t time);
117    uint32_t getElapsedTime();
118
119    void computeValues(SkPaint* paint, const UChar* chars, size_t contextCount, int dirFlags);
120
121    void getAdvances(size_t start, size_t count, jfloat* outAdvances);
122
123    jfloat getTotalAdvance(size_t start, size_t count);
124
125    void getGlyphsIndexAndCount(size_t start, size_t count, size_t* outStartIndex,
126            size_t* outGlyphsCount);
127
128    void getGlyphs(size_t startIndex, size_t count, jchar* outGlyphs);
129
130    /**
131     * Get the size of the Cache entry
132     */
133    size_t getSize();
134
135    static void setupShaperItem(HB_ShaperItem* shaperItem, HB_FontRec* font, FontData* fontData,
136            SkPaint* paint, const UChar* chars, size_t contextCount, bool isRTL);
137
138    static void shapeWithHarfbuzz(HB_ShaperItem* shaperItem, HB_FontRec* font, FontData* fontData,
139            SkPaint* paint, const UChar* chars, size_t contextCount, bool isRTL);
140
141    static void computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars,
142            size_t contextCount, int dirFlags,
143            jfloat* outAdvances, jfloat* outTotalAdvance,
144            jchar** outGlyphs, size_t* outGlyphsCount, unsigned short** outLogClusters);
145
146    static void computeAdvancesWithICU(SkPaint* paint, const UChar* chars, size_t start,
147            size_t count, size_t contextCount, int dirFlags,
148            jfloat* outAdvances, jfloat* outTotalAdvance);
149
150private:
151    /**
152     * Advances array
153     */
154    jfloat* mAdvances;
155
156    /**
157     * Total number of advances
158     */
159    jfloat mTotalAdvance;
160
161    /**
162     * Allocated size for advances array
163     */
164    size_t mAdvancesCount;
165
166    /**
167     * Glyphs array
168     */
169    jchar* mGlyphs;
170
171    /**
172     * Total number of glyphs
173     */
174    size_t mGlyphsCount;
175
176    /**
177     * Harfbuzz Log Clusters
178     */
179    unsigned short* mLogClusters;
180
181    /**
182     * Time for computing the values (in milliseconds)
183     */
184    uint32_t mElapsedTime;
185
186    static void deleteGlyphArrays(HB_ShaperItem* shaperItem);
187    static void createGlyphArrays(HB_ShaperItem* shaperItem, int size);
188    static void resetGlyphArrays(HB_ShaperItem* shaperItem);
189
190    static void computeRunValuesWithHarfbuzz(SkPaint* paint, const UChar* chars,
191            size_t contextCount, bool isRTL,
192            jfloat* outAdvances, jfloat* outTotalAdvance,
193            jchar** outGlyphs, size_t* outGlyphsCount, unsigned short** outLogClusters);
194}; // TextLayoutCacheValue
195
196/**
197 * Cache of text layout information.
198 */
199class TextLayoutCache : public OnEntryRemoved<TextLayoutCacheKey, sp<TextLayoutCacheValue> >,
200        public Singleton<TextLayoutCache>
201{
202public:
203    TextLayoutCache();
204
205    virtual ~TextLayoutCache();
206
207    bool isInitialized() {
208        return mInitialized;
209    }
210
211    /**
212     * Used as a callback when an entry is removed from the cache
213     * Do not invoke directly
214     */
215    void operator()(TextLayoutCacheKey& text, sp<TextLayoutCacheValue>& desc);
216
217    sp<TextLayoutCacheValue> getValue(SkPaint* paint, const jchar* text, jint contextCount,
218            jint dirFlags);
219
220    /**
221     * Clear the cache
222     */
223    void clear();
224
225    /**
226     * Sets the maximum size of the cache in bytes
227     */
228    void setMaxSize(uint32_t maxSize);
229
230    /**
231     * Returns the maximum size of the cache in bytes
232     */
233    uint32_t getMaxSize();
234
235    /**
236     * Returns the current size of the cache in bytes
237     */
238    uint32_t getSize();
239
240private:
241    Mutex mLock;
242    bool mInitialized;
243
244    GenerationCache<TextLayoutCacheKey, sp<TextLayoutCacheValue> > mCache;
245
246    uint32_t mSize;
247    uint32_t mMaxSize;
248
249    uint32_t mCacheHitCount;
250    uint64_t mNanosecondsSaved;
251
252    uint64_t mCacheStartTime;
253
254    RtlDebugLevel mDebugLevel;
255    bool mDebugEnabled;
256
257    /*
258     * Class initialization
259     */
260    void init();
261
262    /**
263     * Remove oldest entries until we are having enough space
264     */
265    void removeOldests();
266
267    /**
268     * Dump Cache statistics
269     */
270    void dumpCacheStats();
271}; // TextLayoutCache
272
273} // namespace android
274#endif /* ANDROID_TEXT_LAYOUT_CACHE_H */
275
276