TextLayoutCache.h revision d686d76814f18061e06995df0d5de9feb9f70a7e
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 <SkScalerContext.h> 34#include <SkAutoKern.h> 35 36#include <unicode/ubidi.h> 37#include <unicode/ushape.h> 38#include "HarfbuzzSkia.h" 39#include "harfbuzz-shaper.h" 40 41#include <android_runtime/AndroidRuntime.h> 42 43#define UNICODE_NOT_A_CHAR 0xffff 44#define UNICODE_ZWSP 0x200b 45#define UNICODE_FIRST_LOW_SURROGATE 0xdc00 46#define UNICODE_FIRST_HIGH_SURROGATE 0xd800 47#define UNICODE_FIRST_PRIVATE_USE 0xe000 48#define UNICODE_FIRST_RTL_CHAR 0x0590 49 50// Temporary buffer size 51#define CHAR_BUFFER_SIZE 80 52 53// Converts a number of mega-bytes into bytes 54#define MB(s) s * 1024 * 1024 55 56// Define the default cache size in Mb 57#define DEFAULT_TEXT_LAYOUT_CACHE_SIZE_IN_MB 0.250f 58 59// Define the interval in number of cache hits between two statistics dump 60#define DEFAULT_DUMP_STATS_CACHE_HIT_INTERVAL 100 61 62namespace android { 63 64/** 65 * TextLayoutCacheKey is the Cache key 66 */ 67class TextLayoutCacheKey { 68public: 69 TextLayoutCacheKey(); 70 71 TextLayoutCacheKey(const SkPaint* paint, 72 const UChar* text, size_t contextCount, int dirFlags); 73 74 TextLayoutCacheKey(const TextLayoutCacheKey& other); 75 76 bool operator<(const TextLayoutCacheKey& rhs) const; 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(); 88 89private: 90 const UChar* text; // if text is NULL, use textCopy 91 String16 textCopy; 92 size_t contextCount; 93 int dirFlags; 94 SkTypeface* typeface; 95 SkScalar textSize; 96 SkScalar textSkewX; 97 SkScalar textScaleX; 98 uint32_t flags; 99 SkPaint::Hinting hinting; 100 101 inline const UChar* getText() const { 102 return text ? text : textCopy.string(); 103 } 104}; // TextLayoutCacheKey 105 106/* 107 * TextLayoutCacheValue is the Cache value 108 */ 109class TextLayoutCacheValue : public RefBase { 110protected: 111 ~TextLayoutCacheValue(); 112 113public: 114 TextLayoutCacheValue(); 115 116 void setElapsedTime(uint32_t time); 117 uint32_t getElapsedTime(); 118 119 void computeValues(SkPaint* paint, const UChar* chars, size_t contextCount, int dirFlags); 120 121 void getAdvances(size_t start, size_t count, jfloat* outAdvances); 122 123 jfloat getTotalAdvance(size_t start, size_t count); 124 125 void getGlyphsIndexAndCount(size_t start, size_t count, size_t* outStartIndex, 126 size_t* outGlyphsCount); 127 128 void getGlyphs(size_t startIndex, size_t count, jchar* outGlyphs); 129 130 /** 131 * Get the size of the Cache entry 132 */ 133 size_t getSize(); 134 135 static void setupShaperItem(HB_ShaperItem* shaperItem, HB_FontRec* font, FontData* fontData, 136 SkPaint* paint, const UChar* chars, size_t contextCount, bool isRTL); 137 138 static void shapeWithHarfbuzz(HB_ShaperItem* shaperItem, HB_FontRec* font, FontData* fontData, 139 SkPaint* paint, const UChar* chars, size_t contextCount, bool isRTL); 140 141 static void computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, 142 size_t contextCount, int dirFlags, 143 jfloat* outAdvances, jfloat* outTotalAdvance, 144 jchar** outGlyphs, size_t* outGlyphsCount, unsigned short** outLogClusters); 145 146 static void computeAdvancesWithICU(SkPaint* paint, const UChar* chars, size_t start, 147 size_t count, size_t contextCount, int dirFlags, 148 jfloat* outAdvances, jfloat* outTotalAdvance); 149 150private: 151 /** 152 * Advances array 153 */ 154 jfloat* mAdvances; 155 156 /** 157 * Total number of advances 158 */ 159 jfloat mTotalAdvance; 160 161 /** 162 * Allocated size for advances array 163 */ 164 size_t mAdvancesCount; 165 166 /** 167 * Glyphs array 168 */ 169 jchar* mGlyphs; 170 171 /** 172 * Total number of glyphs 173 */ 174 size_t mGlyphsCount; 175 176 /** 177 * Harfbuzz Log Clusters 178 */ 179 unsigned short* mLogClusters; 180 181 /** 182 * Time for computing the values (in milliseconds) 183 */ 184 uint32_t mElapsedTime; 185 186 static void deleteGlyphArrays(HB_ShaperItem* shaperItem); 187 static void createGlyphArrays(HB_ShaperItem* shaperItem, int size); 188 static void resetGlyphArrays(HB_ShaperItem* shaperItem); 189 190 static void computeRunValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, 191 size_t contextCount, bool isRTL, 192 jfloat* outAdvances, jfloat* outTotalAdvance, 193 jchar** outGlyphs, size_t* outGlyphsCount, unsigned short** outLogClusters); 194}; // TextLayoutCacheValue 195 196/** 197 * Cache of text layout information. 198 */ 199class TextLayoutCache : public OnEntryRemoved<TextLayoutCacheKey, sp<TextLayoutCacheValue> >, 200 public Singleton<TextLayoutCache> 201{ 202public: 203 TextLayoutCache(); 204 205 virtual ~TextLayoutCache(); 206 207 bool isInitialized() { 208 return mInitialized; 209 } 210 211 /** 212 * Used as a callback when an entry is removed from the cache 213 * Do not invoke directly 214 */ 215 void operator()(TextLayoutCacheKey& text, sp<TextLayoutCacheValue>& desc); 216 217 sp<TextLayoutCacheValue> getValue(SkPaint* paint, const jchar* text, jint contextCount, 218 jint dirFlags); 219 220 /** 221 * Clear the cache 222 */ 223 void clear(); 224 225 /** 226 * Sets the maximum size of the cache in bytes 227 */ 228 void setMaxSize(uint32_t maxSize); 229 230 /** 231 * Returns the maximum size of the cache in bytes 232 */ 233 uint32_t getMaxSize(); 234 235 /** 236 * Returns the current size of the cache in bytes 237 */ 238 uint32_t getSize(); 239 240private: 241 Mutex mLock; 242 bool mInitialized; 243 244 GenerationCache<TextLayoutCacheKey, sp<TextLayoutCacheValue> > mCache; 245 246 uint32_t mSize; 247 uint32_t mMaxSize; 248 249 uint32_t mCacheHitCount; 250 uint64_t mNanosecondsSaved; 251 252 uint64_t mCacheStartTime; 253 254 RtlDebugLevel mDebugLevel; 255 bool mDebugEnabled; 256 257 /* 258 * Class initialization 259 */ 260 void init(); 261 262 /** 263 * Remove oldest entries until we are having enough space 264 */ 265 void removeOldests(); 266 267 /** 268 * Dump Cache statistics 269 */ 270 void dumpCacheStats(); 271}; // TextLayoutCache 272 273} // namespace android 274#endif /* ANDROID_TEXT_LAYOUT_CACHE_H */ 275 276