blob: 690caacd6c65c009c13f3a3c7bea8fbb983b90cb [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>
26#include <utils/Compare.h>
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -070027#include <utils/RefBase.h>
Fabrice Di Megliod313c662011-02-24 19:56:18 -080028
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -070029#include <SkPaint.h>
30#include <SkTemplates.h>
31#include <SkUtils.h>
32#include <SkScalerContext.h>
33#include <SkAutoKern.h>
Fabrice Di Megliod313c662011-02-24 19:56:18 -080034
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -070035#include <unicode/ubidi.h>
36#include <unicode/ushape.h>
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -080037#include "HarfbuzzSkia.h"
38#include "harfbuzz-shaper.h"
Fabrice Di Megliod313c662011-02-24 19:56:18 -080039
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
Fabrice Di Meglio010d5c42011-04-21 15:33:50 -070056#define DEFAULT_TEXT_LAYOUT_CACHE_SIZE_IN_MB 0.250f
Fabrice Di Megliod313c662011-02-24 19:56:18 -080057
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:
Fabrice Di Meglio48796a82011-04-05 15:22:41 -070068 TextLayoutCacheKey();
Fabrice Di Megliod313c662011-02-24 19:56:18 -080069
70 TextLayoutCacheKey(const SkPaint* paint,
71 const UChar* text, size_t start, size_t count,
Fabrice Di Meglio48796a82011-04-05 15:22:41 -070072 size_t contextCount, int dirFlags);
Fabrice Di Megliod313c662011-02-24 19:56:18 -080073
Fabrice Di Meglio48796a82011-04-05 15:22:41 -070074 bool operator<(const TextLayoutCacheKey& rhs) const;
Fabrice Di Megliod313c662011-02-24 19:56:18 -080075
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 */
Fabrice Di Meglio48796a82011-04-05 15:22:41 -070085 size_t getSize();
Fabrice Di Megliod313c662011-02-24 19:56:18 -080086
87private:
88 const UChar* text;
89 String16 textCopy;
90 size_t start;
91 size_t count;
92 size_t contextCount;
93 int dirFlags;
Fabrice Di Megliod313c662011-02-24 19:56:18 -080094 SkTypeface* typeface;
Fabrice Di Meglioaabe5372011-03-30 16:06:02 -070095 SkScalar textSize;
96 SkScalar textSkewX;
97 SkScalar textScaleX;
98 uint32_t flags;
99 SkPaint::Hinting hinting;
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800100}; // TextLayoutCacheKey
101
102/*
Fabrice Di Meglio48796a82011-04-05 15:22:41 -0700103 * TextLayoutCacheValue is the Cache value
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800104 */
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700105class TextLayoutCacheValue : public RefBase {
106protected:
107 ~TextLayoutCacheValue();
108
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800109public:
Fabrice Di Meglio48796a82011-04-05 15:22:41 -0700110 TextLayoutCacheValue();
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800111
Fabrice Di Meglio48796a82011-04-05 15:22:41 -0700112 void setElapsedTime(uint32_t time);
113 uint32_t getElapsedTime();
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800114
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700115 void computeValues(SkPaint* paint, const UChar* chars, size_t start, size_t count,
Fabrice Di Meglio48796a82011-04-05 15:22:41 -0700116 size_t contextCount, int dirFlags);
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800117
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700118 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; }
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800123
124 /**
125 * Get the size of the Cache entry
126 */
Fabrice Di Meglio48796a82011-04-05 15:22:41 -0700127 size_t getSize();
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800128
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800129 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,
Fabrice Di Meglio48796a82011-04-05 15:22:41 -0700131 int dirFlags);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800132
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,
Fabrice Di Meglio48796a82011-04-05 15:22:41 -0700135 int dirFlags);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800136
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700137 static void computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start,
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800138 size_t count, size_t contextCount, int dirFlags,
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700139 jfloat* outAdvances, jfloat* outTotalAdvance,
140 jchar** outGlyphs, size_t* outGlyphsCount);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800141
142 static void computeAdvancesWithICU(SkPaint* paint, const UChar* chars, size_t start,
143 size_t count, size_t contextCount, int dirFlags,
Fabrice Di Meglio48796a82011-04-05 15:22:41 -0700144 jfloat* outAdvances, jfloat* outTotalAdvance);
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800145
146private:
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700147 /**
148 * Advances array
149 */
150 jfloat* mAdvances;
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800151
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700152 /**
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;
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800176
Fabrice Di Meglio48796a82011-04-05 15:22:41 -0700177 static void deleteGlyphArrays(HB_ShaperItem* shaperItem);
178 static void createGlyphArrays(HB_ShaperItem* shaperItem, int size);
179 static void resetGlyphArrays(HB_ShaperItem* shaperItem);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800180
Fabrice Di Meglio689e5152011-04-13 16:07:37 -0700181 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);
Fabrice Di Meglio48796a82011-04-05 15:22:41 -0700185}; // TextLayoutCacheValue
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800186
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700187/**
188 * Cache of text layout information.
189 */
190class TextLayoutCache : public OnEntryRemoved<TextLayoutCacheKey, sp<TextLayoutCacheValue> >
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800191{
192public:
193 TextLayoutCache();
194 TextLayoutCache(uint32_t maxByteSize);
195
196 virtual ~TextLayoutCache();
197
198 bool isInitialized() {
199 return mInitialized;
200 }
201
202 /**
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700203 * Used as a callback when an entry is removed from the cache
204 * Do not invoke directly
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800205 */
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700206 void operator()(TextLayoutCacheKey& text, sp<TextLayoutCacheValue>& desc);
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800207
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700208 sp<TextLayoutCacheValue> getValue(SkPaint* paint,
209 const jchar* text, jint start, jint count, jint contextCount, jint dirFlags);
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800210
211 /**
212 * Clear the cache
213 */
214 void clear();
215
216 /**
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700217 * Sets the maximum size of the cache in bytes
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800218 */
219 void setMaxSize(uint32_t maxSize);
220
221 /**
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700222 * Returns the maximum size of the cache in bytes
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800223 */
224 uint32_t getMaxSize();
225
226 /**
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700227 * Returns the current size of the cache in bytes
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800228 */
229 uint32_t getSize();
230
231private:
232 Mutex mLock;
233 bool mInitialized;
234
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700235 GenerationCache<TextLayoutCacheKey, sp<TextLayoutCacheValue> > mCache;
Fabrice Di Megliod313c662011-02-24 19:56:18 -0800236
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