blob: 510aa18f6788367163d685179e9a94e7e280a406 [file] [log] [blame]
Fabrice Di Megliod313c662011-02-24 19:56:18 -08001/*
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
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -070022#include <stddef.h>
Fabrice Di Megliod313c662011-02-24 19:56:18 -080023#include <utils/threads.h>
24#include <utils/String16.h>
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -070025#include <utils/GenerationCache.h>
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -080026#include <utils/KeyedVector.h>
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -070027#include <utils/Compare.h>
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -070028#include <utils/RefBase.h>
Fabrice Di Meglio163268b2011-09-07 18:12:11 -070029#include <utils/Singleton.h>
Fabrice Di Megliod313c662011-02-24 19:56:18 -080030
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -070031#include <SkPaint.h>
32#include <SkTemplates.h>
33#include <SkUtils.h>
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -070034#include <SkAutoKern.h>
Fabrice Di Megliod313c662011-02-24 19:56:18 -080035
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -070036#include <unicode/ubidi.h>
37#include <unicode/ushape.h>
Fabrice Di Meglio902a5b32011-12-08 18:59:14 -080038#include <unicode/unistr.h>
39
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -080040#include "HarfbuzzSkia.h"
41#include "harfbuzz-shaper.h"
Fabrice Di Megliod313c662011-02-24 19:56:18 -080042
43#include <android_runtime/AndroidRuntime.h>
44
45#define UNICODE_NOT_A_CHAR 0xffff
46#define UNICODE_ZWSP 0x200b
47#define UNICODE_FIRST_LOW_SURROGATE 0xdc00
48#define UNICODE_FIRST_HIGH_SURROGATE 0xd800
49#define UNICODE_FIRST_PRIVATE_USE 0xe000
50#define UNICODE_FIRST_RTL_CHAR 0x0590
51
52// Temporary buffer size
53#define CHAR_BUFFER_SIZE 80
54
55// Converts a number of mega-bytes into bytes
56#define MB(s) s * 1024 * 1024
57
58// Define the default cache size in Mb
Fabrice Di Meglio010d5c42011-04-21 15:33:50 -070059#define DEFAULT_TEXT_LAYOUT_CACHE_SIZE_IN_MB 0.250f
Fabrice Di Megliod313c662011-02-24 19:56:18 -080060
61// Define the interval in number of cache hits between two statistics dump
62#define DEFAULT_DUMP_STATS_CACHE_HIT_INTERVAL 100
63
64namespace android {
65
66/**
67 * TextLayoutCacheKey is the Cache key
68 */
69class TextLayoutCacheKey {
70public:
Fabrice Di Meglio48796a82011-04-05 15:22:41 -070071 TextLayoutCacheKey();
Fabrice Di Megliod313c662011-02-24 19:56:18 -080072
Fabrice Di Meglio5c863f72011-10-05 18:11:59 -070073 TextLayoutCacheKey(const SkPaint* paint, const UChar* text, size_t start, size_t count,
74 size_t contextCount, int dirFlags);
Fabrice Di Megliod313c662011-02-24 19:56:18 -080075
Fabrice Di Meglioe74fef32011-09-18 14:30:21 -070076 TextLayoutCacheKey(const TextLayoutCacheKey& other);
77
Fabrice Di Meglio48796a82011-04-05 15:22:41 -070078 /**
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();
Fabrice Di Megliod313c662011-02-24 19:56:18 -080083
84 /**
85 * Get the size of the Cache key.
86 */
Jeff Brown06daa7b2011-11-11 15:14:56 -080087 size_t getSize() const;
Fabrice Di Megliod313c662011-02-24 19:56:18 -080088
Fabrice Di Meglio717060b2011-09-27 15:53:42 -070089 static int compare(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs);
90
Fabrice Di Megliod313c662011-02-24 19:56:18 -080091private:
Fabrice Di Meglioe74fef32011-09-18 14:30:21 -070092 const UChar* text; // if text is NULL, use textCopy
Fabrice Di Megliod313c662011-02-24 19:56:18 -080093 String16 textCopy;
Fabrice Di Meglio5c863f72011-10-05 18:11:59 -070094 size_t start;
Fabrice Di Meglio9c418db2011-09-18 12:54:38 -070095 size_t count;
Fabrice Di Meglio5c863f72011-10-05 18:11:59 -070096 size_t contextCount;
Fabrice Di Megliod313c662011-02-24 19:56:18 -080097 int dirFlags;
Fabrice Di Megliod313c662011-02-24 19:56:18 -080098 SkTypeface* typeface;
Fabrice Di Meglioaabe5372011-03-30 16:06:02 -070099 SkScalar textSize;
100 SkScalar textSkewX;
101 SkScalar textScaleX;
102 uint32_t flags;
103 SkPaint::Hinting hinting;
Fabrice Di Meglioe74fef32011-09-18 14:30:21 -0700104
Fabrice Di Meglio717060b2011-09-27 15:53:42 -0700105 inline const UChar* getText() const { return text ? text : textCopy.string(); }
106
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800107}; // TextLayoutCacheKey
108
Fabrice Di Meglio717060b2011-09-27 15:53:42 -0700109inline int strictly_order_type(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs) {
110 return TextLayoutCacheKey::compare(lhs, rhs) < 0;
111}
112
113inline int compare_type(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs) {
114 return TextLayoutCacheKey::compare(lhs, rhs);
115}
116
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800117/*
Fabrice Di Meglio48796a82011-04-05 15:22:41 -0700118 * TextLayoutCacheValue is the Cache value
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800119 */
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700120class TextLayoutCacheValue : public RefBase {
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800121public:
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800122 TextLayoutCacheValue(size_t contextCount);
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800123
Fabrice Di Meglio48796a82011-04-05 15:22:41 -0700124 void setElapsedTime(uint32_t time);
125 uint32_t getElapsedTime();
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800126
Fabrice Di Meglio5c863f72011-10-05 18:11:59 -0700127 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(); }
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800132
133 /**
Fabrice Di Meglio4dd99e52011-09-19 10:47:10 -0700134 * Advances vector
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700135 */
Fabrice Di Meglio4dd99e52011-09-19 10:47:10 -0700136 Vector<jfloat> mAdvances;
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800137
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700138 /**
139 * Total number of advances
140 */
141 jfloat mTotalAdvance;
142
143 /**
Fabrice Di Meglio4dd99e52011-09-19 10:47:10 -0700144 * Glyphs vector
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700145 */
Fabrice Di Meglio4dd99e52011-09-19 10:47:10 -0700146 Vector<jchar> mGlyphs;
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700147
148 /**
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800149 * Get the size of the Cache entry
150 */
151 size_t getSize() const;
152
153private:
154 /**
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700155 * Time for computing the values (in milliseconds)
156 */
157 uint32_t mElapsedTime;
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800158
Fabrice Di Meglio48796a82011-04-05 15:22:41 -0700159}; // TextLayoutCacheValue
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800160
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700161/**
162 * Cache of text layout information.
163 */
Fabrice Di Meglio163268b2011-09-07 18:12:11 -0700164class TextLayoutCache : public OnEntryRemoved<TextLayoutCacheKey, sp<TextLayoutCacheValue> >,
165 public Singleton<TextLayoutCache>
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800166{
167public:
168 TextLayoutCache();
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800169
170 virtual ~TextLayoutCache();
171
172 bool isInitialized() {
173 return mInitialized;
174 }
175
176 /**
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700177 * Used as a callback when an entry is removed from the cache
178 * Do not invoke directly
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800179 */
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700180 void operator()(TextLayoutCacheKey& text, sp<TextLayoutCacheValue>& desc);
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800181
Fabrice Di Meglio5c863f72011-10-05 18:11:59 -0700182 sp<TextLayoutCacheValue> getValue(SkPaint* paint, const jchar* text, jint start, jint count,
183 jint contextCount, jint dirFlags);
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800184
185 /**
186 * Clear the cache
187 */
188 void clear();
189
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800190private:
191 Mutex mLock;
192 bool mInitialized;
193
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700194 GenerationCache<TextLayoutCacheKey, sp<TextLayoutCacheValue> > mCache;
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800195
196 uint32_t mSize;
197 uint32_t mMaxSize;
198
199 uint32_t mCacheHitCount;
200 uint64_t mNanosecondsSaved;
201
202 uint64_t mCacheStartTime;
203
204 RtlDebugLevel mDebugLevel;
205 bool mDebugEnabled;
206
207 /*
208 * Class initialization
209 */
210 void init();
211
212 /**
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800213 * Dump Cache statistics
214 */
215 void dumpCacheStats();
Fabrice Di Meglio5c863f72011-10-05 18:11:59 -0700216
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800217}; // TextLayoutCache
218
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800219/**
220 * The TextLayoutEngine is responsible for shaping with Harfbuzz library
221 */
222class TextLayoutEngine : public Singleton<TextLayoutEngine> {
223public:
224 TextLayoutEngine();
225 virtual ~TextLayoutEngine();
226
227 void computeValues(TextLayoutCacheValue* value, SkPaint* paint, const UChar* chars,
228 size_t start, size_t count, size_t contextCount, int dirFlags);
229
230private:
231 /**
232 * Harfbuzz shaper item
233 */
234 HB_ShaperItem mShaperItem;
235
236 /**
237 * Harfbuzz font
238 */
239 HB_FontRec mFontRec;
240
241 /**
242 * Skia Paint used for shaping
243 */
244 SkPaint mShapingPaint;
245
246 /**
247 * Skia typefaces cached for shaping
248 */
249 SkTypeface* mDefaultTypeface;
250 SkTypeface* mArabicTypeface;
251 SkTypeface* mHebrewRegularTypeface;
252 SkTypeface* mHebrewBoldTypeface;
Fabrice Di Meglio65194ad2011-12-13 16:26:08 -0800253 SkTypeface* mBengaliTypeface;
Fabrice Di Meglioa4d07702011-12-13 18:52:13 -0800254 SkTypeface* mThaiTypeface;
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800255
Fabrice Di Meglio902a5b32011-12-08 18:59:14 -0800256 /**
257 * Cache of Harfbuzz faces
258 */
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800259 KeyedVector<SkFontID, HB_Face> mCachedHBFaces;
260
Fabrice Di Meglio902a5b32011-12-08 18:59:14 -0800261 /**
262 * Cache of glyph array size
263 */
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800264 size_t mShaperItemGlyphArraySize;
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800265
Fabrice Di Meglio902a5b32011-12-08 18:59:14 -0800266 /**
267 * Buffer for containing the ICU normalized form of a run
268 */
269 UnicodeString mNormalizedString;
270
271 /**
272 * Buffer for normalizing a piece of a run with ICU
273 */
274 UnicodeString mBuffer;
275
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800276 size_t shapeFontRun(SkPaint* paint, bool isRTL);
277
Fabrice Di Meglio56e6e542011-11-30 15:48:18 -0800278 void computeValues(SkPaint* paint, const UChar* chars,
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800279 size_t start, size_t count, size_t contextCount, int dirFlags,
280 Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
281 Vector<jchar>* const outGlyphs);
282
Fabrice Di Meglio56e6e542011-11-30 15:48:18 -0800283 void computeRunValues(SkPaint* paint, const UChar* chars,
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800284 size_t count, bool isRTL,
285 Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
286 Vector<jchar>* const outGlyphs);
287
288 SkTypeface* getCachedTypeface(SkTypeface** typeface, const char path[]);
289 HB_Face getCachedHBFace(SkTypeface* typeface);
290
291 void ensureShaperItemGlyphArrays(size_t size);
292 void createShaperItemGlyphArrays(size_t size);
293 void deleteShaperItemGlyphArrays();
294
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800295}; // TextLayoutEngine
296
297
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800298} // namespace android
299#endif /* ANDROID_TEXT_LAYOUT_CACHE_H */
300