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