TextLayoutCache.h revision e187a2f55fe8684c853a0701cbc4a71392f437e0
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/Compare.h> 27#include <utils/RefBase.h> 28#include <utils/Singleton.h> 29 30#include <SkPaint.h> 31#include <SkTemplates.h> 32#include <SkUtils.h> 33#include <SkAutoKern.h> 34 35#include <unicode/ubidi.h> 36#include <unicode/ushape.h> 37#include "HarfbuzzSkia.h" 38#include "harfbuzz-shaper.h" 39 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 56#define DEFAULT_TEXT_LAYOUT_CACHE_SIZE_IN_MB 0.250f 57 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: 68 TextLayoutCacheKey(); 69 70 TextLayoutCacheKey(const SkPaint* paint, const UChar* text, size_t start, size_t count, 71 size_t contextCount, int dirFlags); 72 73 TextLayoutCacheKey(const TextLayoutCacheKey& other); 74 75 /** 76 * We need to copy the text when we insert the key into the cache itself. 77 * We don't need to copy the text when we are only comparing keys. 78 */ 79 void internalTextCopy(); 80 81 /** 82 * Get the size of the Cache key. 83 */ 84 size_t getSize(); 85 86 static int compare(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs); 87 88private: 89 const UChar* text; // if text is NULL, use textCopy 90 String16 textCopy; 91 size_t start; 92 size_t count; 93 size_t contextCount; 94 int dirFlags; 95 SkTypeface* typeface; 96 SkScalar textSize; 97 SkScalar textSkewX; 98 SkScalar textScaleX; 99 uint32_t flags; 100 SkPaint::Hinting hinting; 101 102 inline const UChar* getText() const { return text ? text : textCopy.string(); } 103 104}; // TextLayoutCacheKey 105 106inline int strictly_order_type(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs) { 107 return TextLayoutCacheKey::compare(lhs, rhs) < 0; 108} 109 110inline int compare_type(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs) { 111 return TextLayoutCacheKey::compare(lhs, rhs); 112} 113 114/* 115 * TextLayoutCacheValue is the Cache value 116 */ 117class TextLayoutCacheValue : public RefBase { 118public: 119 TextLayoutCacheValue(); 120 121 void setElapsedTime(uint32_t time); 122 uint32_t getElapsedTime(); 123 124 void computeValues(SkPaint* paint, const UChar* chars, size_t start, size_t count, 125 size_t contextCount, int dirFlags); 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 * Get the size of the Cache entry 135 */ 136 size_t getSize(); 137 138private: 139 /** 140 * Advances vector 141 */ 142 Vector<jfloat> mAdvances; 143 144 /** 145 * Total number of advances 146 */ 147 jfloat mTotalAdvance; 148 149 /** 150 * Glyphs vector 151 */ 152 Vector<jchar> mGlyphs; 153 154 /** 155 * Time for computing the values (in milliseconds) 156 */ 157 uint32_t mElapsedTime; 158 159 static void computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, 160 size_t start, size_t count, size_t contextCount, int dirFlags, 161 Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, 162 Vector<jchar>* const outGlyphs); 163 164 static void computeRunValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, 165 size_t count, bool isRTL, 166 Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, 167 Vector<jchar>* const outGlyphs); 168 169 static void initShaperItem(HB_ShaperItem& shaperItem, HB_FontRec* font, FontData* fontData, 170 SkPaint* paint, const UChar* chars, size_t count); 171 172 static void freeShaperItem(HB_ShaperItem& shaperItem); 173 174 static unsigned shapeFontRun(HB_ShaperItem& shaperItem, SkPaint* paint, 175 size_t count, bool isRTL); 176 177 static void deleteGlyphArrays(HB_ShaperItem& shaperItem); 178 179 static void createGlyphArrays(HB_ShaperItem& shaperItem, int size); 180 181}; // TextLayoutCacheValue 182 183/** 184 * Cache of text layout information. 185 */ 186class TextLayoutCache : public OnEntryRemoved<TextLayoutCacheKey, sp<TextLayoutCacheValue> >, 187 public Singleton<TextLayoutCache> 188{ 189public: 190 TextLayoutCache(); 191 192 virtual ~TextLayoutCache(); 193 194 bool isInitialized() { 195 return mInitialized; 196 } 197 198 /** 199 * Used as a callback when an entry is removed from the cache 200 * Do not invoke directly 201 */ 202 void operator()(TextLayoutCacheKey& text, sp<TextLayoutCacheValue>& desc); 203 204 sp<TextLayoutCacheValue> getValue(SkPaint* paint, const jchar* text, jint start, jint count, 205 jint contextCount, jint dirFlags); 206 207 /** 208 * Clear the cache 209 */ 210 void clear(); 211 212 /** 213 * Sets the maximum size of the cache in bytes 214 */ 215 void setMaxSize(uint32_t maxSize); 216 217 /** 218 * Returns the maximum size of the cache in bytes 219 */ 220 uint32_t getMaxSize(); 221 222 /** 223 * Returns the current size of the cache in bytes 224 */ 225 uint32_t getSize(); 226 227private: 228 Mutex mLock; 229 bool mInitialized; 230 231 GenerationCache<TextLayoutCacheKey, sp<TextLayoutCacheValue> > mCache; 232 233 uint32_t mSize; 234 uint32_t mMaxSize; 235 236 uint32_t mCacheHitCount; 237 uint64_t mNanosecondsSaved; 238 239 uint64_t mCacheStartTime; 240 241 RtlDebugLevel mDebugLevel; 242 bool mDebugEnabled; 243 244 /* 245 * Class initialization 246 */ 247 void init(); 248 249 /** 250 * Remove oldest entries until we are having enough space 251 */ 252 void removeOldests(); 253 254 /** 255 * Dump Cache statistics 256 */ 257 void dumpCacheStats(); 258 259}; // TextLayoutCache 260 261} // namespace android 262#endif /* ANDROID_TEXT_LAYOUT_CACHE_H */ 263 264