TextLayoutCache.h revision a4f5aa87c73de7a2581dc4dd72e0f90ccea79a18
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 <SkAutoKern.h>
34
35#include <unicode/ubidi.h>
36#include <unicode/ushape.h>
37#include "HarfbuzzSkia.h"
38#include "harfbuzz-shaper.h"
39
40#include <android_runtime/AndroidRuntime.h>
41
42#define UNICODE_NOT_A_CHAR              0xffff
43#define UNICODE_ZWSP                    0x200b
44#define UNICODE_FIRST_LOW_SURROGATE     0xdc00
45#define UNICODE_FIRST_HIGH_SURROGATE    0xd800
46#define UNICODE_FIRST_PRIVATE_USE       0xe000
47#define UNICODE_FIRST_RTL_CHAR          0x0590
48
49// Temporary buffer size
50#define CHAR_BUFFER_SIZE 80
51
52// Converts a number of mega-bytes into bytes
53#define MB(s) s * 1024 * 1024
54
55// Define the default cache size in Mb
56#define DEFAULT_TEXT_LAYOUT_CACHE_SIZE_IN_MB 0.250f
57
58// Define the interval in number of cache hits between two statistics dump
59#define DEFAULT_DUMP_STATS_CACHE_HIT_INTERVAL 100
60
61namespace android {
62
63/**
64 * TextLayoutCacheKey is the Cache key
65 */
66class TextLayoutCacheKey {
67public:
68    TextLayoutCacheKey();
69
70    TextLayoutCacheKey(const SkPaint* paint, const UChar* text, size_t start, size_t count,
71            size_t contextCount, int dirFlags);
72
73    TextLayoutCacheKey(const TextLayoutCacheKey& other);
74
75    /**
76     * We need to copy the text when we insert the key into the cache itself.
77     * We don't need to copy the text when we are only comparing keys.
78     */
79    void internalTextCopy();
80
81    /**
82     * Get the size of the Cache key.
83     */
84    size_t getSize() const;
85
86    static int compare(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs);
87
88private:
89    const UChar* text; // if text is NULL, use textCopy
90    String16 textCopy;
91    size_t start;
92    size_t count;
93    size_t contextCount;
94    int dirFlags;
95    SkTypeface* typeface;
96    SkScalar textSize;
97    SkScalar textSkewX;
98    SkScalar textScaleX;
99    uint32_t flags;
100    SkPaint::Hinting hinting;
101
102    inline const UChar* getText() const { return text ? text : textCopy.string(); }
103
104}; // TextLayoutCacheKey
105
106inline int strictly_order_type(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs) {
107    return TextLayoutCacheKey::compare(lhs, rhs) < 0;
108}
109
110inline int compare_type(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs) {
111    return TextLayoutCacheKey::compare(lhs, rhs);
112}
113
114/*
115 * TextLayoutCacheValue is the Cache value
116 */
117class TextLayoutCacheValue : public RefBase {
118public:
119    TextLayoutCacheValue();
120
121    void setElapsedTime(uint32_t time);
122    uint32_t getElapsedTime();
123
124    void computeValues(SkPaint* paint, const UChar* chars, size_t start, size_t count,
125            size_t contextCount, int dirFlags);
126
127    inline const jfloat* getAdvances() const { return mAdvances.array(); }
128    inline size_t getAdvancesCount() const { return mAdvances.size(); }
129    inline jfloat getTotalAdvance() const { return mTotalAdvance; }
130    inline const jchar* getGlyphs() const { return mGlyphs.array(); }
131    inline size_t getGlyphsCount() const { return mGlyphs.size(); }
132
133    /**
134     * Get the size of the Cache entry
135     */
136    size_t getSize() const;
137
138private:
139    /**
140     * Advances vector
141     */
142    Vector<jfloat> mAdvances;
143
144    /**
145     * Total number of advances
146     */
147    jfloat mTotalAdvance;
148
149    /**
150     * Glyphs vector
151     */
152    Vector<jchar> mGlyphs;
153
154    /**
155     * Time for computing the values (in milliseconds)
156     */
157    uint32_t mElapsedTime;
158
159    static void computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars,
160            size_t start, size_t count, size_t contextCount, int dirFlags,
161            Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
162            Vector<jchar>* const outGlyphs);
163
164    static void computeRunValuesWithHarfbuzz(SkPaint* paint, const UChar* chars,
165            size_t count, bool isRTL,
166            Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
167            Vector<jchar>* const outGlyphs);
168
169    static void initShaperItem(HB_ShaperItem& shaperItem, HB_FontRec* font, FontData* fontData,
170            SkPaint* paint, const UChar* chars, size_t count);
171
172    static void freeShaperItem(HB_ShaperItem& shaperItem);
173
174    static unsigned shapeFontRun(HB_ShaperItem& shaperItem, SkPaint* paint,
175            size_t count, bool isRTL);
176
177    static SkTypeface* getCachedTypeface(SkTypeface** typeface, const char path[]);
178
179    static void deleteGlyphArrays(HB_ShaperItem& shaperItem);
180
181    static void createGlyphArrays(HB_ShaperItem& shaperItem, int size);
182
183}; // TextLayoutCacheValue
184
185/**
186 * Cache of text layout information.
187 */
188class TextLayoutCache : public OnEntryRemoved<TextLayoutCacheKey, sp<TextLayoutCacheValue> >,
189        public Singleton<TextLayoutCache>
190{
191public:
192    TextLayoutCache();
193
194    virtual ~TextLayoutCache();
195
196    bool isInitialized() {
197        return mInitialized;
198    }
199
200    /**
201     * Used as a callback when an entry is removed from the cache
202     * Do not invoke directly
203     */
204    void operator()(TextLayoutCacheKey& text, sp<TextLayoutCacheValue>& desc);
205
206    sp<TextLayoutCacheValue> getValue(SkPaint* paint, const jchar* text, jint start, jint count,
207            jint contextCount, jint dirFlags);
208
209    /**
210     * Clear the cache
211     */
212    void clear();
213
214private:
215    Mutex mLock;
216    bool mInitialized;
217
218    GenerationCache<TextLayoutCacheKey, sp<TextLayoutCacheValue> > mCache;
219
220    uint32_t mSize;
221    uint32_t mMaxSize;
222
223    uint32_t mCacheHitCount;
224    uint64_t mNanosecondsSaved;
225
226    uint64_t mCacheStartTime;
227
228    RtlDebugLevel mDebugLevel;
229    bool mDebugEnabled;
230
231    /*
232     * Class initialization
233     */
234    void init();
235
236    /**
237     * Dump Cache statistics
238     */
239    void dumpCacheStats();
240
241}; // TextLayoutCache
242
243} // namespace android
244#endif /* ANDROID_TEXT_LAYOUT_CACHE_H */
245
246