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 64 namespace android { 65 66 /** 67 * TextLayoutCacheKey is the Cache key 68 */ 69 class TextLayoutCacheKey { 70 public: 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 91 private: 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 109 inline int strictly_order_type(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs) { 110 return TextLayoutCacheKey::compare(lhs, rhs) < 0; 111 } 112 113 inline 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 */ 120 class TextLayoutValue : public RefBase { 121 public: 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 153 private: 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 */ 164 class TextLayoutShaper { 165 public: 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 172 void purgeCaches(); 173 174 private: 175 /** 176 * Harfbuzz shaper item 177 */ 178 HB_ShaperItem mShaperItem; 179 180 /** 181 * Harfbuzz font 182 */ 183 HB_FontRec mFontRec; 184 185 /** 186 * Skia Paint used for shaping 187 */ 188 SkPaint mShapingPaint; 189 190 /** 191 * Skia typefaces cached for shaping 192 */ 193 SkTypeface* mDefaultTypeface; 194 SkTypeface* mArabicTypeface; 195 SkTypeface* mHebrewRegularTypeface; 196 SkTypeface* mHebrewBoldTypeface; 197 SkTypeface* mBengaliTypeface; 198 SkTypeface* mThaiTypeface; 199 SkTypeface* mDevanagariRegularTypeface; 200 SkTypeface* mTamilRegularTypeface; 201 SkTypeface* mTamilBoldTypeface; 202 203 /** 204 * Cache of Harfbuzz faces 205 */ 206 KeyedVector<SkFontID, HB_Face> mCachedHBFaces; 207 208 /** 209 * Cache of glyph array size 210 */ 211 size_t mShaperItemGlyphArraySize; 212 213 /** 214 * Buffer for containing the ICU normalized form of a run 215 */ 216 UnicodeString mNormalizedString; 217 218 /** 219 * Buffer for normalizing a piece of a run with ICU 220 */ 221 UnicodeString mBuffer; 222 223 void init(); 224 void unrefTypefaces(); 225 226 SkTypeface* typefaceForUnichar(const SkPaint* paint, SkTypeface* typeface, 227 SkUnichar unichar, HB_Script script); 228 229 size_t shapeFontRun(const SkPaint* paint, bool isRTL); 230 231 void computeValues(const SkPaint* paint, const UChar* chars, 232 size_t start, size_t count, size_t contextCount, int dirFlags, 233 Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, 234 Vector<jchar>* const outGlyphs); 235 236 void computeRunValues(const SkPaint* paint, const UChar* chars, 237 size_t count, bool isRTL, 238 Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, 239 Vector<jchar>* const outGlyphs); 240 241 SkTypeface* getCachedTypeface(SkTypeface** typeface, const char path[]); 242 HB_Face getCachedHBFace(SkTypeface* typeface); 243 244 void ensureShaperItemGlyphArrays(size_t size); 245 void createShaperItemGlyphArrays(size_t size); 246 void deleteShaperItemGlyphArrays(); 247 248 }; // TextLayoutShaper 249 250 /** 251 * Cache of text layout information. 252 */ 253 class TextLayoutCache : private OnEntryRemoved<TextLayoutCacheKey, sp<TextLayoutValue> > 254 { 255 public: 256 TextLayoutCache(TextLayoutShaper* shaper); 257 258 ~TextLayoutCache(); 259 260 bool isInitialized() { 261 return mInitialized; 262 } 263 264 /** 265 * Used as a callback when an entry is removed from the cache 266 * Do not invoke directly 267 */ 268 void operator()(TextLayoutCacheKey& text, sp<TextLayoutValue>& desc); 269 270 sp<TextLayoutValue> getValue(const SkPaint* paint, const jchar* text, jint start, 271 jint count, jint contextCount, jint dirFlags); 272 273 /** 274 * Clear the cache 275 */ 276 void clear(); 277 278 private: 279 TextLayoutShaper* mShaper; 280 Mutex mLock; 281 bool mInitialized; 282 283 GenerationCache<TextLayoutCacheKey, sp<TextLayoutValue> > mCache; 284 285 uint32_t mSize; 286 uint32_t mMaxSize; 287 288 uint32_t mCacheHitCount; 289 uint64_t mNanosecondsSaved; 290 291 uint64_t mCacheStartTime; 292 293 RtlDebugLevel mDebugLevel; 294 bool mDebugEnabled; 295 296 /* 297 * Class initialization 298 */ 299 void init(); 300 301 /** 302 * Dump Cache statistics 303 */ 304 void dumpCacheStats(); 305 306 }; // TextLayoutCache 307 308 /** 309 * The TextLayoutEngine is reponsible for computing TextLayoutValues 310 */ 311 class TextLayoutEngine : public Singleton<TextLayoutEngine> { 312 public: 313 TextLayoutEngine(); 314 virtual ~TextLayoutEngine(); 315 316 sp<TextLayoutValue> getValue(const SkPaint* paint, const jchar* text, jint start, 317 jint count, jint contextCount, jint dirFlags); 318 319 void purgeCaches(); 320 321 private: 322 TextLayoutCache* mTextLayoutCache; 323 TextLayoutShaper* mShaper; 324 }; // TextLayoutEngine 325 326 } // namespace android 327 #endif /* ANDROID_TEXT_LAYOUT_CACHE_H */ 328 329