• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
62 namespace android {
63 
64 /**
65  * TextLayoutCacheKey is the Cache key
66  */
67 class TextLayoutCacheKey {
68 public:
69     TextLayoutCacheKey();
70 
71     TextLayoutCacheKey(const SkPaint* paint, const UChar* text, size_t start, size_t count,
72             size_t contextCount, int dirFlags);
73 
74     TextLayoutCacheKey(const TextLayoutCacheKey& other);
75 
76     /**
77      * We need to copy the text when we insert the key into the cache itself.
78      * We don't need to copy the text when we are only comparing keys.
79      */
80     void internalTextCopy();
81 
82     /**
83      * Get the size of the Cache key.
84      */
85     size_t getSize();
86 
87     static int compare(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs);
88 
89 private:
90     const UChar* text; // if text is NULL, use textCopy
91     String16 textCopy;
92     size_t start;
93     size_t count;
94     size_t contextCount;
95     int dirFlags;
96     SkTypeface* typeface;
97     SkScalar textSize;
98     SkScalar textSkewX;
99     SkScalar textScaleX;
100     uint32_t flags;
101     SkPaint::Hinting hinting;
102 
getText()103     inline const UChar* getText() const { return text ? text : textCopy.string(); }
104 
105 }; // TextLayoutCacheKey
106 
strictly_order_type(const TextLayoutCacheKey & lhs,const TextLayoutCacheKey & rhs)107 inline int strictly_order_type(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs) {
108     return TextLayoutCacheKey::compare(lhs, rhs) < 0;
109 }
110 
compare_type(const TextLayoutCacheKey & lhs,const TextLayoutCacheKey & rhs)111 inline int compare_type(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs) {
112     return TextLayoutCacheKey::compare(lhs, rhs);
113 }
114 
115 /*
116  * TextLayoutCacheValue is the Cache value
117  */
118 class TextLayoutCacheValue : public RefBase {
119 public:
120     TextLayoutCacheValue();
121 
122     void setElapsedTime(uint32_t time);
123     uint32_t getElapsedTime();
124 
125     void computeValues(SkPaint* paint, const UChar* chars, size_t start, size_t count,
126             size_t contextCount, int dirFlags);
127 
getAdvances()128     inline const jfloat* getAdvances() const { return mAdvances.array(); }
getAdvancesCount()129     inline size_t getAdvancesCount() const { return mAdvances.size(); }
getTotalAdvance()130     inline jfloat getTotalAdvance() const { return mTotalAdvance; }
getGlyphs()131     inline const jchar* getGlyphs() const { return mGlyphs.array(); }
getGlyphsCount()132     inline size_t getGlyphsCount() const { return mGlyphs.size(); }
133 
134     /**
135      * Get the size of the Cache entry
136      */
137     size_t getSize();
138 
139 private:
140     /**
141      * Advances vector
142      */
143     Vector<jfloat> mAdvances;
144 
145     /**
146      * Total number of advances
147      */
148     jfloat mTotalAdvance;
149 
150     /**
151      * Glyphs vector
152      */
153     Vector<jchar> mGlyphs;
154 
155     /**
156      * Time for computing the values (in milliseconds)
157      */
158     uint32_t mElapsedTime;
159 
160     static void computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars,
161             size_t start, size_t count, size_t contextCount, int dirFlags,
162             Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
163             Vector<jchar>* const outGlyphs);
164 
165     static void computeRunValuesWithHarfbuzz(HB_ShaperItem& shaperItem, SkPaint* paint,
166             size_t start, size_t count, bool isRTL,
167             Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
168             Vector<jchar>* const outGlyphs);
169 
170     static void initShaperItem(HB_ShaperItem& shaperItem, HB_FontRec* font, FontData* fontData,
171             SkPaint* paint, const UChar* chars, size_t contextCount);
172 
173     static void freeShaperItem(HB_ShaperItem& shaperItem);
174 
175     static void shapeRun(HB_ShaperItem& shaperItem, size_t start, 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  */
186 class TextLayoutCache : public OnEntryRemoved<TextLayoutCacheKey, sp<TextLayoutCacheValue> >,
187         public Singleton<TextLayoutCache>
188 {
189 public:
190     TextLayoutCache();
191 
192     virtual ~TextLayoutCache();
193 
isInitialized()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 
227 private:
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