blob: fd9ccb100010eaa9a79104f08e07ffdb84789d12 [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 Meglio9f82b582011-03-08 12:02:59 -080038#include "HarfbuzzSkia.h"
39#include "harfbuzz-shaper.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
Fabrice Di Meglio010d5c42011-04-21 15:33:50 -070057#define DEFAULT_TEXT_LAYOUT_CACHE_SIZE_IN_MB 0.250f
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,
72 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 /**
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();
Fabrice Di Megliod313c662011-02-24 19:56:18 -080081
82 /**
83 * Get the size of the Cache key.
84 */
Jeff Brown06daa7b2011-11-11 15:14:56 -080085 size_t getSize() const;
Fabrice Di Megliod313c662011-02-24 19:56:18 -080086
Fabrice Di Meglio717060b2011-09-27 15:53:42 -070087 static int compare(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs);
88
Fabrice Di Megliod313c662011-02-24 19:56:18 -080089private:
Fabrice Di Meglioe74fef32011-09-18 14:30:21 -070090 const UChar* text; // if text is NULL, use textCopy
Fabrice Di Megliod313c662011-02-24 19:56:18 -080091 String16 textCopy;
Fabrice Di Meglio5c863f72011-10-05 18:11:59 -070092 size_t start;
Fabrice Di Meglio9c418db2011-09-18 12:54:38 -070093 size_t count;
Fabrice Di Meglio5c863f72011-10-05 18:11:59 -070094 size_t contextCount;
Fabrice Di Megliod313c662011-02-24 19:56:18 -080095 int dirFlags;
Fabrice Di Megliod313c662011-02-24 19:56:18 -080096 SkTypeface* typeface;
Fabrice Di Meglioaabe5372011-03-30 16:06:02 -070097 SkScalar textSize;
98 SkScalar textSkewX;
99 SkScalar textScaleX;
100 uint32_t flags;
101 SkPaint::Hinting hinting;
Fabrice Di Meglioe74fef32011-09-18 14:30:21 -0700102
Fabrice Di Meglio717060b2011-09-27 15:53:42 -0700103 inline const UChar* getText() const { return text ? text : textCopy.string(); }
104
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800105}; // TextLayoutCacheKey
106
Fabrice Di Meglio717060b2011-09-27 15:53:42 -0700107inline int strictly_order_type(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs) {
108 return TextLayoutCacheKey::compare(lhs, rhs) < 0;
109}
110
111inline int compare_type(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs) {
112 return TextLayoutCacheKey::compare(lhs, rhs);
113}
114
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800115/*
Fabrice Di Meglio48796a82011-04-05 15:22:41 -0700116 * TextLayoutCacheValue is the Cache value
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800117 */
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700118class TextLayoutCacheValue : public RefBase {
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800119public:
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800120 TextLayoutCacheValue(size_t contextCount);
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800121
Fabrice Di Meglio48796a82011-04-05 15:22:41 -0700122 void setElapsedTime(uint32_t time);
123 uint32_t getElapsedTime();
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800124
Fabrice Di Meglio5c863f72011-10-05 18:11:59 -0700125 inline const jfloat* getAdvances() const { return mAdvances.array(); }
126 inline size_t getAdvancesCount() const { return mAdvances.size(); }
127 inline jfloat getTotalAdvance() const { return mTotalAdvance; }
128 inline const jchar* getGlyphs() const { return mGlyphs.array(); }
129 inline size_t getGlyphsCount() const { return mGlyphs.size(); }
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800130
131 /**
Fabrice Di Meglio4dd99e52011-09-19 10:47:10 -0700132 * Advances vector
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700133 */
Fabrice Di Meglio4dd99e52011-09-19 10:47:10 -0700134 Vector<jfloat> mAdvances;
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800135
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700136 /**
137 * Total number of advances
138 */
139 jfloat mTotalAdvance;
140
141 /**
Fabrice Di Meglio4dd99e52011-09-19 10:47:10 -0700142 * Glyphs vector
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700143 */
Fabrice Di Meglio4dd99e52011-09-19 10:47:10 -0700144 Vector<jchar> mGlyphs;
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700145
146 /**
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800147 * Get the size of the Cache entry
148 */
149 size_t getSize() const;
150
151private:
152 /**
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700153 * Time for computing the values (in milliseconds)
154 */
155 uint32_t mElapsedTime;
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800156
Fabrice Di Meglio48796a82011-04-05 15:22:41 -0700157}; // TextLayoutCacheValue
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800158
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700159/**
160 * Cache of text layout information.
161 */
Fabrice Di Meglio163268b2011-09-07 18:12:11 -0700162class TextLayoutCache : public OnEntryRemoved<TextLayoutCacheKey, sp<TextLayoutCacheValue> >,
163 public Singleton<TextLayoutCache>
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800164{
165public:
166 TextLayoutCache();
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800167
168 virtual ~TextLayoutCache();
169
170 bool isInitialized() {
171 return mInitialized;
172 }
173
174 /**
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700175 * Used as a callback when an entry is removed from the cache
176 * Do not invoke directly
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800177 */
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700178 void operator()(TextLayoutCacheKey& text, sp<TextLayoutCacheValue>& desc);
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800179
Fabrice Di Meglio5c863f72011-10-05 18:11:59 -0700180 sp<TextLayoutCacheValue> getValue(SkPaint* paint, const jchar* text, jint start, jint count,
181 jint contextCount, jint dirFlags);
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800182
183 /**
184 * Clear the cache
185 */
186 void clear();
187
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800188private:
189 Mutex mLock;
190 bool mInitialized;
191
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700192 GenerationCache<TextLayoutCacheKey, sp<TextLayoutCacheValue> > mCache;
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800193
194 uint32_t mSize;
195 uint32_t mMaxSize;
196
197 uint32_t mCacheHitCount;
198 uint64_t mNanosecondsSaved;
199
200 uint64_t mCacheStartTime;
201
202 RtlDebugLevel mDebugLevel;
203 bool mDebugEnabled;
204
205 /*
206 * Class initialization
207 */
208 void init();
209
210 /**
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800211 * Dump Cache statistics
212 */
213 void dumpCacheStats();
Fabrice Di Meglio5c863f72011-10-05 18:11:59 -0700214
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800215}; // TextLayoutCache
216
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800217/**
218 * The TextLayoutEngine is responsible for shaping with Harfbuzz library
219 */
220class TextLayoutEngine : public Singleton<TextLayoutEngine> {
221public:
222 TextLayoutEngine();
223 virtual ~TextLayoutEngine();
224
225 void computeValues(TextLayoutCacheValue* value, SkPaint* paint, const UChar* chars,
226 size_t start, size_t count, size_t contextCount, int dirFlags);
227
228private:
229 /**
230 * Harfbuzz shaper item
231 */
232 HB_ShaperItem mShaperItem;
233
234 /**
235 * Harfbuzz font
236 */
237 HB_FontRec mFontRec;
238
239 /**
240 * Skia Paint used for shaping
241 */
242 SkPaint mShapingPaint;
243
244 /**
245 * Skia typefaces cached for shaping
246 */
247 SkTypeface* mDefaultTypeface;
248 SkTypeface* mArabicTypeface;
249 SkTypeface* mHebrewRegularTypeface;
250 SkTypeface* mHebrewBoldTypeface;
251
252 KeyedVector<SkFontID, HB_Face> mCachedHBFaces;
253
254 size_t mShaperItemGlyphArraySize;
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800255
256 size_t shapeFontRun(SkPaint* paint, bool isRTL);
257
Fabrice Di Meglio56e6e542011-11-30 15:48:18 -0800258 void computeValues(SkPaint* paint, const UChar* chars,
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800259 size_t start, size_t count, size_t contextCount, int dirFlags,
260 Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
261 Vector<jchar>* const outGlyphs);
262
Fabrice Di Meglio56e6e542011-11-30 15:48:18 -0800263 void computeRunValues(SkPaint* paint, const UChar* chars,
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800264 size_t count, bool isRTL,
265 Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
266 Vector<jchar>* const outGlyphs);
267
268 SkTypeface* getCachedTypeface(SkTypeface** typeface, const char path[]);
269 HB_Face getCachedHBFace(SkTypeface* typeface);
270
271 void ensureShaperItemGlyphArrays(size_t size);
272 void createShaperItemGlyphArrays(size_t size);
273 void deleteShaperItemGlyphArrays();
274
Fabrice Di Meglio0af10b52011-11-18 17:36:41 -0800275}; // TextLayoutEngine
276
277
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800278} // namespace android
279#endif /* ANDROID_TEXT_LAYOUT_CACHE_H */
280