TextLayoutCache.h revision 163268b3a8d4dd7e650e6c540f832bf60f6bf4c9
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 start, size_t count,
73            size_t contextCount, int dirFlags);
74
75    bool operator<(const TextLayoutCacheKey& rhs) const;
76
77    /**
78     * We need to copy the text when we insert the key into the cache itself.
79     * We don't need to copy the text when we are only comparing keys.
80     */
81    void internalTextCopy();
82
83    /**
84     * Get the size of the Cache key.
85     */
86    size_t getSize();
87
88private:
89    const UChar* text;
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}; // TextLayoutCacheKey
102
103/*
104 * TextLayoutCacheValue is the Cache value
105 */
106class TextLayoutCacheValue : public RefBase {
107protected:
108    ~TextLayoutCacheValue();
109
110public:
111    TextLayoutCacheValue();
112
113    void setElapsedTime(uint32_t time);
114    uint32_t getElapsedTime();
115
116    void computeValues(SkPaint* paint, const UChar* chars, size_t start, size_t count,
117            size_t contextCount, int dirFlags);
118
119    inline const jfloat* getAdvances() const { return mAdvances; }
120    inline size_t getAdvancesCount() const { return mAdvancesCount; }
121    inline jfloat getTotalAdvance() const { return mTotalAdvance; }
122    inline const jchar* getGlyphs() const { return mGlyphs; }
123    inline size_t getGlyphsCount() const { return mGlyphsCount; }
124
125    /**
126     * Get the size of the Cache entry
127     */
128    size_t getSize();
129
130    static void setupShaperItem(HB_ShaperItem* shaperItem, HB_FontRec* font, FontData* fontData,
131            SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount,
132            bool isRTL);
133
134    static void shapeWithHarfbuzz(HB_ShaperItem* shaperItem, HB_FontRec* font, FontData* fontData,
135            SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount,
136            bool isRTL);
137
138    static void computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start,
139            size_t count, size_t contextCount, int dirFlags,
140            jfloat* outAdvances, jfloat* outTotalAdvance,
141            jchar** outGlyphs, size_t* outGlyphsCount);
142
143    static void computeAdvancesWithICU(SkPaint* paint, const UChar* chars, size_t start,
144            size_t count, size_t contextCount, int dirFlags,
145            jfloat* outAdvances, jfloat* outTotalAdvance);
146
147private:
148    /**
149     * Advances array
150     */
151    jfloat* mAdvances;
152
153    /**
154     * Total number of advances
155     */
156    jfloat mTotalAdvance;
157
158    /**
159     * Allocated size for advances array
160     */
161    size_t mAdvancesCount;
162
163    /**
164     * Glyphs array
165     */
166    jchar* mGlyphs;
167
168    /**
169     * Total number of glyphs
170     */
171    size_t mGlyphsCount;
172
173    /**
174     * Time for computing the values (in milliseconds)
175     */
176    uint32_t mElapsedTime;
177
178    static void deleteGlyphArrays(HB_ShaperItem* shaperItem);
179    static void createGlyphArrays(HB_ShaperItem* shaperItem, int size);
180    static void resetGlyphArrays(HB_ShaperItem* shaperItem);
181
182    static void computeRunValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start,
183            size_t count, size_t contextCount, bool isRTL,
184            jfloat* outAdvances, jfloat* outTotalAdvance,
185            jchar** outGlyphs, size_t* outGlyphsCount);
186}; // TextLayoutCacheValue
187
188/**
189 * Cache of text layout information.
190 */
191class TextLayoutCache : public OnEntryRemoved<TextLayoutCacheKey, sp<TextLayoutCacheValue> >,
192        public Singleton<TextLayoutCache>
193{
194public:
195    TextLayoutCache();
196
197    virtual ~TextLayoutCache();
198
199    bool isInitialized() {
200        return mInitialized;
201    }
202
203    /**
204     * Used as a callback when an entry is removed from the cache
205     * Do not invoke directly
206     */
207    void operator()(TextLayoutCacheKey& text, sp<TextLayoutCacheValue>& desc);
208
209    sp<TextLayoutCacheValue> getValue(SkPaint* paint,
210            const jchar* text, jint start, jint count, jint contextCount, jint dirFlags);
211
212    /**
213     * Clear the cache
214     */
215    void clear();
216
217    /**
218     * Sets the maximum size of the cache in bytes
219     */
220    void setMaxSize(uint32_t maxSize);
221
222    /**
223     * Returns the maximum size of the cache in bytes
224     */
225    uint32_t getMaxSize();
226
227    /**
228     * Returns the current size of the cache in bytes
229     */
230    uint32_t getSize();
231
232private:
233    Mutex mLock;
234    bool mInitialized;
235
236    GenerationCache<TextLayoutCacheKey, sp<TextLayoutCacheValue> > mCache;
237
238    uint32_t mSize;
239    uint32_t mMaxSize;
240
241    uint32_t mCacheHitCount;
242    uint64_t mNanosecondsSaved;
243
244    uint64_t mCacheStartTime;
245
246    RtlDebugLevel mDebugLevel;
247    bool mDebugEnabled;
248
249    /*
250     * Class initialization
251     */
252    void init();
253
254    /**
255     * Remove oldest entries until we are having enough space
256     */
257    void removeOldests();
258
259    /**
260     * Dump Cache statistics
261     */
262    void dumpCacheStats();
263}; // TextLayoutCache
264
265} // namespace android
266#endif /* ANDROID_TEXT_LAYOUT_CACHE_H */
267
268