TextLayoutCache.h revision 30ca5cd11a23f06f2f8eeaa587685450826f800f
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 36#include <unicode/ubidi.h> 37#include <unicode/ushape.h> 38#include <unicode/unistr.h> 39 40#include "HarfbuzzSkia.h" 41#include "harfbuzz-shaper.h" 42 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 59#define DEFAULT_TEXT_LAYOUT_CACHE_SIZE_IN_MB 0.250f 60 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: 71 TextLayoutCacheKey(); 72 73 TextLayoutCacheKey(const SkPaint* paint, const UChar* text, size_t start, size_t count, 74 size_t contextCount, int dirFlags); 75 76 TextLayoutCacheKey(const TextLayoutCacheKey& other); 77 78 /** 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(); 83 84 /** 85 * Get the size of the Cache key. 86 */ 87 size_t getSize() const; 88 89 static int compare(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs); 90 91private: 92 const UChar* text; // if text is NULL, use textCopy 93 String16 textCopy; 94 size_t start; 95 size_t count; 96 size_t contextCount; 97 int dirFlags; 98 SkTypeface* typeface; 99 SkScalar textSize; 100 SkScalar textSkewX; 101 SkScalar textScaleX; 102 uint32_t flags; 103 SkPaint::Hinting hinting; 104 105 inline const UChar* getText() const { return text ? text : textCopy.string(); } 106 107}; // TextLayoutCacheKey 108 109inline 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 117/* 118 * TextLayoutValue is the Cache value 119 */ 120class TextLayoutValue : public RefBase { 121public: 122 TextLayoutValue(size_t contextCount); 123 124 void setElapsedTime(uint32_t time); 125 uint32_t getElapsedTime(); 126 127 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(); } 132 133 /** 134 * Advances vector 135 */ 136 Vector<jfloat> mAdvances; 137 138 /** 139 * Total number of advances 140 */ 141 jfloat mTotalAdvance; 142 143 /** 144 * Glyphs vector 145 */ 146 Vector<jchar> mGlyphs; 147 148 /** 149 * Get the size of the Cache entry 150 */ 151 size_t getSize() const; 152 153private: 154 /** 155 * Time for computing the values (in milliseconds) 156 */ 157 uint32_t mElapsedTime; 158 159}; // TextLayoutCacheValue 160 161/** 162 * The TextLayoutShaper is responsible for shaping (with the Harfbuzz library) 163 */ 164class TextLayoutShaper { 165public: 166 TextLayoutShaper(); 167 virtual ~TextLayoutShaper(); 168 169 void computeValues(TextLayoutValue* value, const SkPaint* paint, const UChar* chars, 170 size_t start, size_t count, size_t contextCount, int dirFlags); 171 172private: 173 /** 174 * Harfbuzz shaper item 175 */ 176 HB_ShaperItem mShaperItem; 177 178 /** 179 * Harfbuzz font 180 */ 181 HB_FontRec mFontRec; 182 183 /** 184 * Skia Paint used for shaping 185 */ 186 SkPaint mShapingPaint; 187 188 /** 189 * Skia typefaces cached for shaping 190 */ 191 SkTypeface* mDefaultTypeface; 192 SkTypeface* mArabicTypeface; 193 SkTypeface* mHebrewRegularTypeface; 194 SkTypeface* mHebrewBoldTypeface; 195 SkTypeface* mBengaliTypeface; 196 SkTypeface* mThaiTypeface; 197 SkTypeface* mDevanagariTypeface; 198 SkTypeface* mTamilTypeface; 199 200 /** 201 * Cache of Harfbuzz faces 202 */ 203 KeyedVector<SkFontID, HB_Face> mCachedHBFaces; 204 205 /** 206 * Cache of glyph array size 207 */ 208 size_t mShaperItemGlyphArraySize; 209 210 /** 211 * Buffer for containing the ICU normalized form of a run 212 */ 213 UnicodeString mNormalizedString; 214 215 /** 216 * Buffer for normalizing a piece of a run with ICU 217 */ 218 UnicodeString mBuffer; 219 220 SkTypeface* typefaceForUnichar(const SkPaint* paint, SkTypeface* typeface, 221 SkUnichar unichar, HB_Script script); 222 223 size_t shapeFontRun(const SkPaint* paint, bool isRTL); 224 225 void computeValues(const SkPaint* paint, const UChar* chars, 226 size_t start, size_t count, size_t contextCount, int dirFlags, 227 Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, 228 Vector<jchar>* const outGlyphs); 229 230 void computeRunValues(const SkPaint* paint, const UChar* chars, 231 size_t count, bool isRTL, 232 Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, 233 Vector<jchar>* const outGlyphs); 234 235 SkTypeface* getCachedTypeface(SkTypeface** typeface, const char path[]); 236 HB_Face getCachedHBFace(SkTypeface* typeface); 237 238 void ensureShaperItemGlyphArrays(size_t size); 239 void createShaperItemGlyphArrays(size_t size); 240 void deleteShaperItemGlyphArrays(); 241 242}; // TextLayoutShaper 243 244/** 245 * Cache of text layout information. 246 */ 247class TextLayoutCache : private OnEntryRemoved<TextLayoutCacheKey, sp<TextLayoutValue> > 248{ 249public: 250 TextLayoutCache(TextLayoutShaper* shaper); 251 252 ~TextLayoutCache(); 253 254 bool isInitialized() { 255 return mInitialized; 256 } 257 258 /** 259 * Used as a callback when an entry is removed from the cache 260 * Do not invoke directly 261 */ 262 void operator()(TextLayoutCacheKey& text, sp<TextLayoutValue>& desc); 263 264 sp<TextLayoutValue> getValue(const SkPaint* paint, const jchar* text, jint start, 265 jint count, jint contextCount, jint dirFlags); 266 267 /** 268 * Clear the cache 269 */ 270 void clear(); 271 272private: 273 TextLayoutShaper* mShaper; 274 Mutex mLock; 275 bool mInitialized; 276 277 GenerationCache<TextLayoutCacheKey, sp<TextLayoutValue> > mCache; 278 279 uint32_t mSize; 280 uint32_t mMaxSize; 281 282 uint32_t mCacheHitCount; 283 uint64_t mNanosecondsSaved; 284 285 uint64_t mCacheStartTime; 286 287 RtlDebugLevel mDebugLevel; 288 bool mDebugEnabled; 289 290 /* 291 * Class initialization 292 */ 293 void init(); 294 295 /** 296 * Dump Cache statistics 297 */ 298 void dumpCacheStats(); 299 300}; // TextLayoutCache 301 302/** 303 * The TextLayoutEngine is reponsible for computing TextLayoutValues 304 */ 305class TextLayoutEngine : public Singleton<TextLayoutEngine> { 306public: 307 TextLayoutEngine(); 308 virtual ~TextLayoutEngine(); 309 310 sp<TextLayoutValue> getValue(const SkPaint* paint, const jchar* text, jint start, 311 jint count, jint contextCount, jint dirFlags); 312 313 void purgeCaches(); 314 315private: 316 TextLayoutCache* mTextLayoutCache; 317 TextLayoutShaper* mShaper; 318}; // TextLayoutEngine 319 320} // namespace android 321#endif /* ANDROID_TEXT_LAYOUT_CACHE_H */ 322 323