TextLayoutCache.h revision 13ba4e478d19001ddb6828bd1fd8fbc1e0cb208f
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/KeyedVector.h> 27#include <utils/Compare.h> 28#include <utils/RefBase.h> 29#include <utils/Singleton.h> 30 31#include <SkPaint.h> 32#include <SkTemplates.h> 33#include <SkUtils.h> 34#include <SkAutoKern.h> 35#include <SkLanguage.h> 36 37#include <unicode/ubidi.h> 38#include <unicode/ushape.h> 39#include <unicode/unistr.h> 40 41#include "HarfbuzzSkia.h" 42#include "harfbuzz-shaper.h" 43 44#include <android_runtime/AndroidRuntime.h> 45 46#define UNICODE_NOT_A_CHAR 0xffff 47#define UNICODE_ZWSP 0x200b 48#define UNICODE_FIRST_LOW_SURROGATE 0xdc00 49#define UNICODE_FIRST_HIGH_SURROGATE 0xd800 50#define UNICODE_FIRST_PRIVATE_USE 0xe000 51#define UNICODE_FIRST_RTL_CHAR 0x0590 52 53// Temporary buffer size 54#define CHAR_BUFFER_SIZE 80 55 56// Converts a number of mega-bytes into bytes 57#define MB(s) s * 1024 * 1024 58 59// Define the default cache size in Mb 60#define DEFAULT_TEXT_LAYOUT_CACHE_SIZE_IN_MB 0.500f 61 62// Define the interval in number of cache hits between two statistics dump 63#define DEFAULT_DUMP_STATS_CACHE_HIT_INTERVAL 100 64 65namespace android { 66 67/** 68 * TextLayoutCacheKey is the Cache key 69 */ 70class TextLayoutCacheKey { 71public: 72 TextLayoutCacheKey(); 73 74 TextLayoutCacheKey(const SkPaint* paint, const UChar* text, size_t start, size_t count, 75 size_t contextCount, int dirFlags); 76 77 TextLayoutCacheKey(const TextLayoutCacheKey& other); 78 79 /** 80 * We need to copy the text when we insert the key into the cache itself. 81 * We don't need to copy the text when we are only comparing keys. 82 */ 83 void internalTextCopy(); 84 85 /** 86 * Get the size of the Cache key. 87 */ 88 size_t getSize() const; 89 90 static int compare(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs); 91 92private: 93 const UChar* text; // if text is NULL, use textCopy 94 String16 textCopy; 95 size_t start; 96 size_t count; 97 size_t contextCount; 98 int dirFlags; 99 SkTypeface* typeface; 100 SkScalar textSize; 101 SkScalar textSkewX; 102 SkScalar textScaleX; 103 uint32_t flags; 104 SkPaint::Hinting hinting; 105 SkPaint::FontVariant variant; 106 SkLanguage language; 107 108 inline const UChar* getText() const { return text ? text : textCopy.string(); } 109 110}; // TextLayoutCacheKey 111 112inline int strictly_order_type(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs) { 113 return TextLayoutCacheKey::compare(lhs, rhs) < 0; 114} 115 116inline int compare_type(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs) { 117 return TextLayoutCacheKey::compare(lhs, rhs); 118} 119 120/* 121 * TextLayoutValue is the Cache value 122 */ 123class TextLayoutValue : public RefBase { 124public: 125 TextLayoutValue(size_t contextCount); 126 127 void setElapsedTime(uint32_t time); 128 uint32_t getElapsedTime(); 129 130 inline const jfloat* getAdvances() const { return mAdvances.array(); } 131 inline size_t getAdvancesCount() const { return mAdvances.size(); } 132 inline jfloat getTotalAdvance() const { return mTotalAdvance; } 133 inline const jchar* getGlyphs() const { return mGlyphs.array(); } 134 inline size_t getGlyphsCount() const { return mGlyphs.size(); } 135 inline const jfloat* getPos() const { return mPos.array(); } 136 inline size_t getPosCount() const { return mPos.size(); } 137 138 /** 139 * Advances vector 140 */ 141 Vector<jfloat> mAdvances; 142 143 /** 144 * Total number of advances 145 */ 146 jfloat mTotalAdvance; 147 148 /** 149 * Glyphs vector 150 */ 151 Vector<jchar> mGlyphs; 152 153 /** 154 * Pos vector (2 * i is x pos, 2 * i + 1 is y pos, same as drawPosText) 155 */ 156 Vector<jfloat> mPos; 157 158 /** 159 * Get the size of the Cache entry 160 */ 161 size_t getSize() const; 162 163private: 164 /** 165 * Time for computing the values (in milliseconds) 166 */ 167 uint32_t mElapsedTime; 168 169}; // TextLayoutCacheValue 170 171/** 172 * The TextLayoutShaper is responsible for shaping (with the Harfbuzz library) 173 */ 174class TextLayoutShaper { 175public: 176 TextLayoutShaper(); 177 virtual ~TextLayoutShaper(); 178 179 void computeValues(TextLayoutValue* value, const SkPaint* paint, const UChar* chars, 180 size_t start, size_t count, size_t contextCount, int dirFlags); 181 182 void purgeCaches(); 183 184private: 185 /** 186 * Harfbuzz shaper item 187 */ 188 HB_ShaperItem mShaperItem; 189 190 /** 191 * Harfbuzz font 192 */ 193 HB_FontRec mFontRec; 194 195 /** 196 * Skia Paint used for shaping 197 */ 198 SkPaint mShapingPaint; 199 200 /** 201 * Skia default typeface to be returned if we cannot resolve script 202 */ 203 SkTypeface* mDefaultTypeface; 204 205 /** 206 * Cache of Harfbuzz faces 207 */ 208 KeyedVector<SkFontID, HB_Face> mCachedHBFaces; 209 210 /** 211 * Cache of glyph array size 212 */ 213 size_t mShaperItemGlyphArraySize; 214 215 /** 216 * Buffer for containing the ICU normalized form of a run 217 */ 218 UnicodeString mNormalizedString; 219 220 /** 221 * Buffer for normalizing a piece of a run with ICU 222 */ 223 UnicodeString mBuffer; 224 225 void init(); 226 void unrefTypefaces(); 227 228 SkTypeface* typefaceForScript(const SkPaint* paint, SkTypeface* typeface, 229 HB_Script script); 230 231 size_t shapeFontRun(const SkPaint* paint, bool isRTL); 232 233 void computeValues(const SkPaint* paint, const UChar* chars, 234 size_t start, size_t count, size_t contextCount, int dirFlags, 235 Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, 236 Vector<jchar>* const outGlyphs, Vector<jfloat>* const outPos); 237 238 void computeRunValues(const SkPaint* paint, const UChar* chars, 239 size_t count, bool isRTL, 240 Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, 241 Vector<jchar>* const outGlyphs, Vector<jfloat>* const outPos); 242 243 SkTypeface* getCachedTypeface(SkTypeface** typeface, HB_Script script, SkTypeface::Style style); 244 HB_Face getCachedHBFace(SkTypeface* typeface); 245 246 bool doShaping(size_t size); 247 void createShaperItemGlyphArrays(size_t size); 248 void deleteShaperItemGlyphArrays(); 249 bool isComplexScript(HB_Script script); 250 251}; // TextLayoutShaper 252 253/** 254 * Cache of text layout information. 255 */ 256class TextLayoutCache : private OnEntryRemoved<TextLayoutCacheKey, sp<TextLayoutValue> > 257{ 258public: 259 TextLayoutCache(TextLayoutShaper* shaper); 260 261 ~TextLayoutCache(); 262 263 bool isInitialized() { 264 return mInitialized; 265 } 266 267 /** 268 * Used as a callback when an entry is removed from the cache 269 * Do not invoke directly 270 */ 271 void operator()(TextLayoutCacheKey& text, sp<TextLayoutValue>& desc); 272 273 sp<TextLayoutValue> getValue(const SkPaint* paint, const jchar* text, jint start, 274 jint count, jint contextCount, jint dirFlags); 275 276 /** 277 * Clear the cache 278 */ 279 void purgeCaches(); 280 281private: 282 TextLayoutShaper* mShaper; 283 Mutex mLock; 284 bool mInitialized; 285 286 GenerationCache<TextLayoutCacheKey, sp<TextLayoutValue> > mCache; 287 288 uint32_t mSize; 289 uint32_t mMaxSize; 290 291 uint32_t mCacheHitCount; 292 uint64_t mNanosecondsSaved; 293 294 uint64_t mCacheStartTime; 295 296 RtlDebugLevel mDebugLevel; 297 bool mDebugEnabled; 298 299 /* 300 * Class initialization 301 */ 302 void init(); 303 304 /** 305 * Dump Cache statistics 306 */ 307 void dumpCacheStats(); 308 309}; // TextLayoutCache 310 311/** 312 * The TextLayoutEngine is reponsible for computing TextLayoutValues 313 */ 314class TextLayoutEngine : public Singleton<TextLayoutEngine> { 315public: 316 TextLayoutEngine(); 317 virtual ~TextLayoutEngine(); 318 319 sp<TextLayoutValue> getValue(const SkPaint* paint, const jchar* text, jint start, 320 jint count, jint contextCount, jint dirFlags); 321 322 void purgeCaches(); 323 324private: 325 TextLayoutCache* mTextLayoutCache; 326 TextLayoutShaper* mShaper; 327}; // TextLayoutEngine 328 329} // namespace android 330#endif /* ANDROID_TEXT_LAYOUT_CACHE_H */ 331 332