blob: 54704ec741f2767969cfeea5c532a879447480e8 [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>
Raph Leviend98efca2012-10-25 23:17:33 -070025#include <utils/LruCache.h>
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -080026#include <utils/KeyedVector.h>
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -070027#include <utils/RefBase.h>
Fabrice Di Meglio163268b2011-09-07 18:12:11 -070028#include <utils/Singleton.h>
Fabrice Di Megliod313c662011-02-24 19:56:18 -080029
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -070030#include <SkAutoKern.h>
Kristian Monsen2d76d4f2013-01-15 19:23:21 -080031#include <SkPaint.h>
32#include <SkTemplates.h>
33#include <SkTypeface.h>
34#include <SkUtils.h>
Fabrice Di Megliod313c662011-02-24 19:56:18 -080035
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -070036#include <unicode/ubidi.h>
Fabrice Di Meglio902a5b32011-12-08 18:59:14 -080037#include <unicode/unistr.h>
38
Raph Levienaaedde52012-10-30 15:55:33 -070039#include <hb.h>
Fabrice Di Megliod313c662011-02-24 19:56:18 -080040
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
Raph Levien161ebab2012-07-18 15:57:15 -070057#define DEFAULT_TEXT_LAYOUT_CACHE_SIZE_IN_MB 0.500f
Fabrice Di Megliod313c662011-02-24 19:56:18 -080058
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:
Fabrice Di Meglio48796a82011-04-05 15:22:41 -070069 TextLayoutCacheKey();
Fabrice Di Megliod313c662011-02-24 19:56:18 -080070
Fabrice Di Meglio5c863f72011-10-05 18:11:59 -070071 TextLayoutCacheKey(const SkPaint* paint, const UChar* text, size_t start, size_t count,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -070072 size_t contextCount, int dirFlags);
Fabrice Di Megliod313c662011-02-24 19:56:18 -080073
Fabrice Di Meglioe74fef32011-09-18 14:30:21 -070074 TextLayoutCacheKey(const TextLayoutCacheKey& other);
75
Fabrice Di Meglio48796a82011-04-05 15:22:41 -070076 /**
Fabrice Di Megliod313c662011-02-24 19:56:18 -080077 * Get the size of the Cache key.
78 */
Jeff Brown06daa7b2011-11-11 15:14:56 -080079 size_t getSize() const;
Fabrice Di Megliod313c662011-02-24 19:56:18 -080080
Fabrice Di Meglio717060b2011-09-27 15:53:42 -070081 static int compare(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs);
82
Raph Levien832815c2012-10-02 10:30:41 -070083 inline const UChar* getText() const { return textCopy.string(); }
84
Raph Leviend98efca2012-10-25 23:17:33 -070085 bool operator==(const TextLayoutCacheKey& other) const {
86 return compare(*this, other) == 0;
87 }
88
89 bool operator!=(const TextLayoutCacheKey& other) const {
90 return compare(*this, other) != 0;
91 }
92
93 hash_t hash() const;
Fabrice Di Megliod313c662011-02-24 19:56:18 -080094private:
Fabrice Di Megliod313c662011-02-24 19:56:18 -080095 String16 textCopy;
Fabrice Di Meglio5c863f72011-10-05 18:11:59 -070096 size_t start;
Fabrice Di Meglio9c418db2011-09-18 12:54:38 -070097 size_t count;
Fabrice Di Meglio5c863f72011-10-05 18:11:59 -070098 size_t contextCount;
Fabrice Di Meglioda12f382013-03-15 11:26:56 -070099 int dirFlags;
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800100 SkTypeface* typeface;
Fabrice Di Meglioaabe5372011-03-30 16:06:02 -0700101 SkScalar textSize;
102 SkScalar textSkewX;
103 SkScalar textScaleX;
104 uint32_t flags;
105 SkPaint::Hinting hinting;
Derek Sollenbergerd7a80772013-05-28 10:44:26 -0400106 SkPaintOptionsAndroid paintOpts;
Fabrice Di Meglioe74fef32011-09-18 14:30:21 -0700107
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800108}; // TextLayoutCacheKey
109
Fabrice Di Meglio717060b2011-09-27 15:53:42 -0700110inline int strictly_order_type(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs) {
111 return TextLayoutCacheKey::compare(lhs, rhs) < 0;
112}
113
114inline int compare_type(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs) {
115 return TextLayoutCacheKey::compare(lhs, rhs);
116}
117
Raph Leviend98efca2012-10-25 23:17:33 -0700118inline hash_t hash_type(const TextLayoutCacheKey& key) {
119 return key.hash();
120}
121
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800122/*
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800123 * TextLayoutValue is the Cache value
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800124 */
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800125class TextLayoutValue : public RefBase {
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800126public:
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800127 TextLayoutValue(size_t contextCount);
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800128
Fabrice Di Meglio48796a82011-04-05 15:22:41 -0700129 void setElapsedTime(uint32_t time);
130 uint32_t getElapsedTime();
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800131
Fabrice Di Meglio5c863f72011-10-05 18:11:59 -0700132 inline const jfloat* getAdvances() const { return mAdvances.array(); }
133 inline size_t getAdvancesCount() const { return mAdvances.size(); }
134 inline jfloat getTotalAdvance() const { return mTotalAdvance; }
Chris Craik41541822013-05-03 16:35:54 -0700135 inline const SkRect& getBounds() const { return mBounds; }
Fabrice Di Meglio5c863f72011-10-05 18:11:59 -0700136 inline const jchar* getGlyphs() const { return mGlyphs.array(); }
137 inline size_t getGlyphsCount() const { return mGlyphs.size(); }
Raph Levien2301d322012-07-17 16:39:49 -0700138 inline const jfloat* getPos() const { return mPos.array(); }
139 inline size_t getPosCount() const { return mPos.size(); }
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800140
141 /**
Fabrice Di Meglio4dd99e52011-09-19 10:47:10 -0700142 * Advances vector
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700143 */
Fabrice Di Meglio4dd99e52011-09-19 10:47:10 -0700144 Vector<jfloat> mAdvances;
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800145
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700146 /**
147 * Total number of advances
148 */
149 jfloat mTotalAdvance;
150
151 /**
Chris Craik41541822013-05-03 16:35:54 -0700152 * Bounds containing all glyphs
153 */
154 SkRect mBounds;
155
156 /**
Fabrice Di Meglio4dd99e52011-09-19 10:47:10 -0700157 * Glyphs vector
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700158 */
Fabrice Di Meglio4dd99e52011-09-19 10:47:10 -0700159 Vector<jchar> mGlyphs;
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700160
161 /**
Raph Levien2301d322012-07-17 16:39:49 -0700162 * Pos vector (2 * i is x pos, 2 * i + 1 is y pos, same as drawPosText)
163 */
164 Vector<jfloat> mPos;
165
166 /**
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800167 * Get the size of the Cache entry
168 */
169 size_t getSize() const;
170
171private:
172 /**
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700173 * Time for computing the values (in milliseconds)
174 */
175 uint32_t mElapsedTime;
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800176
Fabrice Di Meglio48796a82011-04-05 15:22:41 -0700177}; // TextLayoutCacheValue
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800178
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700179/**
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800180 * The TextLayoutShaper is responsible for shaping (with the Harfbuzz library)
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700181 */
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800182class TextLayoutShaper {
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800183public:
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800184 TextLayoutShaper();
185 virtual ~TextLayoutShaper();
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800186
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800187 void computeValues(TextLayoutValue* value, const SkPaint* paint, const UChar* chars,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700188 size_t start, size_t count, size_t contextCount, int dirFlags);
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800189
Fabrice Di Meglio15cc68c2012-05-15 14:47:03 -0700190 void purgeCaches();
191
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800192private:
193 /**
Raph Levienaaedde52012-10-30 15:55:33 -0700194 * Harfbuzz buffer for shaping
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800195 */
Raph Levienaaedde52012-10-30 15:55:33 -0700196 hb_buffer_t* mBuffer;
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800197
198 /**
199 * Skia Paint used for shaping
200 */
201 SkPaint mShapingPaint;
202
203 /**
Fabrice Di Meglio902a5b32011-12-08 18:59:14 -0800204 * Cache of Harfbuzz faces
205 */
Raph Levienaaedde52012-10-30 15:55:33 -0700206 KeyedVector<SkFontID, hb_face_t*> mCachedHBFaces;
Fabrice Di Meglio902a5b32011-12-08 18:59:14 -0800207
Billy Hewlettd6deccb2012-06-22 10:30:55 -0700208 SkTypeface* typefaceForScript(const SkPaint* paint, SkTypeface* typeface,
Raph Levienaaedde52012-10-30 15:55:33 -0700209 hb_script_t script);
Raph Levien1637dcd2012-05-02 10:41:14 -0700210
Raph Levienaaedde52012-10-30 15:55:33 -0700211 size_t shapeFontRun(const SkPaint* paint);
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800212
Fabrice Di Megliobd901de2012-01-20 17:41:55 -0800213 void computeValues(const SkPaint* paint, const UChar* chars,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700214 size_t start, size_t count, size_t contextCount, int dirFlags,
Chris Craik41541822013-05-03 16:35:54 -0700215 Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, SkRect* outBounds,
Raph Levien2301d322012-07-17 16:39:49 -0700216 Vector<jchar>* const outGlyphs, Vector<jfloat>* const outPos);
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800217
Fabrice Di Megliobd901de2012-01-20 17:41:55 -0800218 void computeRunValues(const SkPaint* paint, const UChar* chars,
Raph Levienaaedde52012-10-30 15:55:33 -0700219 size_t start, size_t count, size_t contextCount, bool isRTL,
Chris Craik41541822013-05-03 16:35:54 -0700220 Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, SkRect* outBounds,
Raph Levien2301d322012-07-17 16:39:49 -0700221 Vector<jchar>* const outGlyphs, Vector<jfloat>* const outPos);
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800222
Raph Levienaaedde52012-10-30 15:55:33 -0700223 SkTypeface* setCachedTypeface(SkTypeface** typeface, hb_script_t script, SkTypeface::Style style);
224 hb_face_t* referenceCachedHBFace(SkTypeface* typeface);
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800225
Raph Levienaaedde52012-10-30 15:55:33 -0700226 bool isComplexScript(hb_script_t script);
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800227}; // TextLayoutShaper
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800228
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800229/**
230 * Cache of text layout information.
231 */
232class TextLayoutCache : private OnEntryRemoved<TextLayoutCacheKey, sp<TextLayoutValue> >
233{
234public:
235 TextLayoutCache(TextLayoutShaper* shaper);
236
237 ~TextLayoutCache();
238
239 bool isInitialized() {
240 return mInitialized;
241 }
242
243 /**
244 * Used as a callback when an entry is removed from the cache
245 * Do not invoke directly
246 */
247 void operator()(TextLayoutCacheKey& text, sp<TextLayoutValue>& desc);
248
249 sp<TextLayoutValue> getValue(const SkPaint* paint, const jchar* text, jint start,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700250 jint count, jint contextCount, jint dirFlags);
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800251
252 /**
253 * Clear the cache
254 */
Raph Levien13ba4e42012-09-12 15:15:51 -0700255 void purgeCaches();
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800256
257private:
258 TextLayoutShaper* mShaper;
259 Mutex mLock;
260 bool mInitialized;
261
Raph Leviend98efca2012-10-25 23:17:33 -0700262 LruCache<TextLayoutCacheKey, sp<TextLayoutValue> > mCache;
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800263
264 uint32_t mSize;
265 uint32_t mMaxSize;
266
267 uint32_t mCacheHitCount;
268 uint64_t mNanosecondsSaved;
269
270 uint64_t mCacheStartTime;
271
272 RtlDebugLevel mDebugLevel;
273 bool mDebugEnabled;
274
275 /*
276 * Class initialization
277 */
278 void init();
279
280 /**
281 * Dump Cache statistics
282 */
283 void dumpCacheStats();
284
285}; // TextLayoutCache
286
287/**
288 * The TextLayoutEngine is reponsible for computing TextLayoutValues
289 */
290class TextLayoutEngine : public Singleton<TextLayoutEngine> {
291public:
292 TextLayoutEngine();
293 virtual ~TextLayoutEngine();
294
Raph Levien832815c2012-10-02 10:30:41 -0700295 /**
296 * Note: this method currently does a defensive copy of the text argument, in case
297 * there is concurrent mutation of it. The contract may change, and may in the
298 * future require the caller to guarantee that the contents will not change during
299 * the call. Be careful of this when doing optimization.
300 **/
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800301 sp<TextLayoutValue> getValue(const SkPaint* paint, const jchar* text, jint start,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700302 jint count, jint contextCount, jint dirFlags);
Fabrice Di Meglio30ca5cd2012-05-07 17:45:44 -0700303
304 void purgeCaches();
305
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800306private:
307 TextLayoutCache* mTextLayoutCache;
308 TextLayoutShaper* mShaper;
309}; // TextLayoutEngine
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800310
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800311} // namespace android
312#endif /* ANDROID_TEXT_LAYOUT_CACHE_H */
313