Home | History | Annotate | Download | only in graphics
      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 
    103     inline const UChar* getText() const { return text ? text : textCopy.string(); }
    104 
    105 }; // TextLayoutCacheKey
    106 
    107 inline int strictly_order_type(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs) {
    108     return TextLayoutCacheKey::compare(lhs, rhs) < 0;
    109 }
    110 
    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 
    128     inline const jfloat* getAdvances() const { return mAdvances.array(); }
    129     inline size_t getAdvancesCount() const { return mAdvances.size(); }
    130     inline jfloat getTotalAdvance() const { return mTotalAdvance; }
    131     inline const jchar* getGlyphs() const { return mGlyphs.array(); }
    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 
    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