TextLayoutCache.h revision bd901dee317d10c6a921922c3d7d788b90306c82
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 * TextLayoutCacheValue is the Cache value 119 */ 120class TextLayoutCacheValue : public RefBase { 121public: 122 TextLayoutCacheValue(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 * Cache of text layout information. 163 */ 164class TextLayoutCache : public OnEntryRemoved<TextLayoutCacheKey, sp<TextLayoutCacheValue> >, 165 public Singleton<TextLayoutCache> 166{ 167public: 168 TextLayoutCache(); 169 170 virtual ~TextLayoutCache(); 171 172 bool isInitialized() { 173 return mInitialized; 174 } 175 176 /** 177 * Used as a callback when an entry is removed from the cache 178 * Do not invoke directly 179 */ 180 void operator()(TextLayoutCacheKey& text, sp<TextLayoutCacheValue>& desc); 181 182 sp<TextLayoutCacheValue> getValue(const SkPaint* paint, const jchar* text, jint start, jint count, 183 jint contextCount, jint dirFlags); 184 185 /** 186 * Clear the cache 187 */ 188 void clear(); 189 190private: 191 Mutex mLock; 192 bool mInitialized; 193 194 GenerationCache<TextLayoutCacheKey, sp<TextLayoutCacheValue> > mCache; 195 196 uint32_t mSize; 197 uint32_t mMaxSize; 198 199 uint32_t mCacheHitCount; 200 uint64_t mNanosecondsSaved; 201 202 uint64_t mCacheStartTime; 203 204 RtlDebugLevel mDebugLevel; 205 bool mDebugEnabled; 206 207 /* 208 * Class initialization 209 */ 210 void init(); 211 212 /** 213 * Dump Cache statistics 214 */ 215 void dumpCacheStats(); 216 217}; // TextLayoutCache 218 219/** 220 * The TextLayoutEngine is responsible for shaping with Harfbuzz library 221 */ 222class TextLayoutEngine : public Singleton<TextLayoutEngine> { 223public: 224 TextLayoutEngine(); 225 virtual ~TextLayoutEngine(); 226 227 void computeValues(TextLayoutCacheValue* value, const SkPaint* paint, const UChar* chars, 228 size_t start, size_t count, size_t contextCount, int dirFlags); 229 230private: 231 /** 232 * Harfbuzz shaper item 233 */ 234 HB_ShaperItem mShaperItem; 235 236 /** 237 * Harfbuzz font 238 */ 239 HB_FontRec mFontRec; 240 241 /** 242 * Skia Paint used for shaping 243 */ 244 SkPaint mShapingPaint; 245 246 /** 247 * Skia typefaces cached for shaping 248 */ 249 SkTypeface* mDefaultTypeface; 250 SkTypeface* mArabicTypeface; 251 SkTypeface* mHebrewRegularTypeface; 252 SkTypeface* mHebrewBoldTypeface; 253 SkTypeface* mBengaliTypeface; 254 SkTypeface* mThaiTypeface; 255 256 /** 257 * Cache of Harfbuzz faces 258 */ 259 KeyedVector<SkFontID, HB_Face> mCachedHBFaces; 260 261 /** 262 * Cache of glyph array size 263 */ 264 size_t mShaperItemGlyphArraySize; 265 266 /** 267 * Buffer for containing the ICU normalized form of a run 268 */ 269 UnicodeString mNormalizedString; 270 271 /** 272 * Buffer for normalizing a piece of a run with ICU 273 */ 274 UnicodeString mBuffer; 275 276 size_t shapeFontRun(const SkPaint* paint, bool isRTL); 277 278 void computeValues(const SkPaint* paint, const UChar* chars, 279 size_t start, size_t count, size_t contextCount, int dirFlags, 280 Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, 281 Vector<jchar>* const outGlyphs); 282 283 void computeRunValues(const SkPaint* paint, const UChar* chars, 284 size_t count, bool isRTL, 285 Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, 286 Vector<jchar>* const outGlyphs); 287 288 SkTypeface* getCachedTypeface(SkTypeface** typeface, const char path[]); 289 HB_Face getCachedHBFace(SkTypeface* typeface); 290 291 void ensureShaperItemGlyphArrays(size_t size); 292 void createShaperItemGlyphArrays(size_t size); 293 void deleteShaperItemGlyphArrays(); 294 295}; // TextLayoutEngine 296 297 298} // namespace android 299#endif /* ANDROID_TEXT_LAYOUT_CACHE_H */ 300 301