Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 39d18f53 authored by Fabrice Di Meglio's avatar Fabrice Di Meglio Committed by Android (Google) Code Review
Browse files

Merge "Code cleaning: centralize use of #if USE_TEXT_LAYOUT_CACHE"

parents 11001c34 a731b082
Loading
Loading
Loading
Loading
+3 −12
Original line number Diff line number Diff line
@@ -757,20 +757,11 @@ public:
            int start, int count, int contextCount,
            jfloat x, jfloat y, int flags, SkPaint* paint) {

        sp<TextLayoutCacheValue> value;
#if USE_TEXT_LAYOUT_CACHE
        value = TextLayoutCache::getInstance().getValue(paint, textArray, start, count,
                contextCount, flags);
        sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
                textArray, start, count, contextCount, flags);
        if (value == NULL) {
            ALOGE("Cannot get TextLayoutCache value for text = '%s'",
                    String8(textArray + start, count).string());
            return;
        }
#else
        value = new TextLayoutCacheValue(contextCount);
        TextLayoutEngine::getInstance().computeValues(value.get(), paint,
                reinterpret_cast<const UChar*>(textArray), start, count, contextCount, flags);
#endif
        doDrawGlyphs(canvas, value->getGlyphs(), 0, value->getGlyphsCount(), x, y, flags, paint);
    }

+10 −28
Original line number Diff line number Diff line
@@ -465,11 +465,10 @@ public:

        jchar* glyphsArray = env->GetCharArrayElements(glyphs, NULL);

        TextLayoutCacheValue value(contextCount);
        TextLayoutEngine::getInstance().computeValues(&value, paint, text, start, count,
                contextCount, flags);
        const jchar* shapedGlyphs = value.getGlyphs();
        size_t glyphsCount = value.getGlyphsCount();
        sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
                text, start, count, contextCount, flags);
        const jchar* shapedGlyphs = value->getGlyphs();
        size_t glyphsCount = value->getGlyphsCount();
        memcpy(glyphsArray, shapedGlyphs, sizeof(jchar) * glyphsCount);

        env->ReleaseCharArrayElements(glyphs, glyphsArray, JNI_ABORT);
@@ -677,20 +676,11 @@ public:
    static int breakText(JNIEnv* env, SkPaint& paint, const jchar text[],
                         int count, float maxWidth, jfloatArray jmeasured,
                         SkPaint::TextBufferDirection tbd) {
        sp<TextLayoutCacheValue> value;
#if USE_TEXT_LAYOUT_CACHE
        value = TextLayoutCache::getInstance().getValue(&paint, text, 0, count,
                count, paint.getFlags());
        sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(&paint,
                text, 0, count, count, paint.getFlags());
        if (value == NULL) {
            ALOGE("Cannot get TextLayoutCache value for text = '%s'",
                    String8(text, count).string());
            return 0;
        }
#else
        value = new TextLayoutCacheValue(count);
        TextLayoutEngine::getInstance().computeValues(value.get(), &paint,
                reinterpret_cast<const UChar*>(text), 0, count, count, paint.getFlags());
#endif

        SkScalar     measured;
        size_t       bytes = paint.breakText(value->getGlyphs(), value->getGlyphsCount() << 1,
                                   SkFloatToScalar(maxWidth), &measured, tbd);
@@ -756,19 +746,11 @@ public:
        SkRect  r;
        SkIRect ir;

        sp<TextLayoutCacheValue> value;
#if USE_TEXT_LAYOUT_CACHE
        value = TextLayoutCache::getInstance().getValue(&paint, text, 0, count,
                count, paint.getFlags());
        sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(&paint,
                text, 0, count, count, paint.getFlags());
        if (value == NULL) {
            ALOGE("Cannot get TextLayoutCache value for text = '%s'",
                    String8(text, count).string());
        }
#else
        value = new TextLayoutCacheValue(count);
        TextLayoutEngine::getInstance().computeValues(value.get(), &paint,
                reinterpret_cast<const UChar*>(text), 0, count, count, paint.getFlags());
#endif
            return;
        }
        paint.measureText(value->getGlyphs(), value->getGlyphsCount() << 1, &r);
        r.roundOut(&ir);
        GraphicsJNI::irect_to_jrect(ir, env, bounds);
+8 −36
Original line number Diff line number Diff line
@@ -53,19 +53,9 @@ bool TextLayout::needsLayout(const jchar* text, jint len, jint bidiFlags) {
// a path representing the text that would have been drawn.
void TextLayout::handleText(SkPaint *paint, const jchar* text, jsize len,
                            jint bidiFlags, jfloat x, jfloat y, SkPath *path) {
    sp<TextLayoutCacheValue> value;
#if USE_TEXT_LAYOUT_CACHE
    // Return advances from the cache. Compute them if needed
    value = TextLayoutCache::getInstance().getValue(paint, text, 0, len,
            len, bidiFlags);
#else
    value = new TextLayoutCacheValue(len);
    TextLayoutEngine::getInstance().computeValues(value.get(), paint,
            reinterpret_cast<const UChar*>(text), 0, len, len, bidiFlags);
#endif
    sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
            text, 0, len, len, bidiFlags);
    if (value == NULL) {
        ALOGE("Cannot get TextLayoutCache value for text = '%s'",
                String8(text, len).string());
        return ;
    }
    SkScalar x_ = SkFloatToScalar(x);
@@ -77,19 +67,9 @@ void TextLayout::handleText(SkPaint *paint, const jchar* text, jsize len,
void TextLayout::getTextRunAdvances(SkPaint* paint, const jchar* chars, jint start,
                                    jint count, jint contextCount, jint dirFlags,
                                    jfloat* resultAdvances, jfloat* resultTotalAdvance) {
    sp<TextLayoutCacheValue> value;
#if USE_TEXT_LAYOUT_CACHE
    // Return advances from the cache. Compute them if needed
    value = TextLayoutCache::getInstance().getValue(paint, chars, start, count,
            contextCount, dirFlags);
#else
    value = new TextLayoutCacheValue(contextCount);
    TextLayoutEngine::getInstance().computeValues(value.get(), paint,
            reinterpret_cast<const UChar*>(chars), start, count, contextCount, dirFlags);
#endif
    sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
            chars, start, count, contextCount, dirFlags);
    if (value == NULL) {
        ALOGE("Cannot get TextLayoutCache value for text = '%s'",
                String8(chars + start, count).string());
        return ;
    }
    if (resultAdvances) {
@@ -126,20 +106,12 @@ void TextLayout::drawTextOnPath(SkPaint* paint, const jchar* text, int count,
        return;
    }

    sp<TextLayoutCacheValue> value;
#if USE_TEXT_LAYOUT_CACHE
    value = TextLayoutCache::getInstance().getValue(paint, text, 0, count,
            count, bidiFlags);
#else
    value = new TextLayoutCacheValue(count);
    TextLayoutEngine::getInstance().computeValues(value.get(), paint,
            reinterpret_cast<const UChar*>(text), 0, count, count, bidiFlags);
#endif
    sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
            text, 0, count, count, bidiFlags);
    if (value == NULL) {
        ALOGE("Cannot get TextLayoutCache value for text = '%s'",
                String8(text, count).string());
        return;
    }

    // Beware: this needs Glyph encoding (already done on the Paint constructor)
    canvas->drawTextOnPathHV(value->getGlyphs(), value->getGlyphsCount() * 2, *path, h_, v_, *paint);
}
+66 −32
Original line number Diff line number Diff line
@@ -35,18 +35,13 @@ namespace android {
#define TYPEFACE_BENGALI "/system/fonts/Lohit-Bengali.ttf"
#define TYPEFACE_THAI "/system/fonts/DroidSansThai.ttf"

#if USE_TEXT_LAYOUT_CACHE

    ANDROID_SINGLETON_STATIC_INSTANCE(TextLayoutCache);

#endif

ANDROID_SINGLETON_STATIC_INSTANCE(TextLayoutEngine);

//--------------------------------------------------------------------------------------------------

TextLayoutCache::TextLayoutCache() :
        mCache(GenerationCache<TextLayoutCacheKey, sp<TextLayoutCacheValue> >::kUnlimitedCapacity),
TextLayoutCache::TextLayoutCache(TextLayoutShaper* shaper) :
        mShaper(shaper),
        mCache(GenerationCache<TextLayoutCacheKey, sp<TextLayoutValue> >::kUnlimitedCapacity),
        mSize(0), mMaxSize(MB(DEFAULT_TEXT_LAYOUT_CACHE_SIZE_IN_MB)),
        mCacheHitCount(0), mNanosecondsSaved(0) {
    init();
@@ -75,7 +70,7 @@ void TextLayoutCache::init() {
/**
 *  Callbacks
 */
void TextLayoutCache::operator()(TextLayoutCacheKey& text, sp<TextLayoutCacheValue>& desc) {
void TextLayoutCache::operator()(TextLayoutCacheKey& text, sp<TextLayoutValue>& desc) {
    size_t totalSizeToDelete = text.getSize() + desc->getSize();
    mSize -= totalSizeToDelete;
    if (mDebugEnabled) {
@@ -93,7 +88,7 @@ void TextLayoutCache::clear() {
/*
 * Caching
 */
sp<TextLayoutCacheValue> TextLayoutCache::getValue(const SkPaint* paint,
sp<TextLayoutValue> TextLayoutCache::getValue(const SkPaint* paint,
            const jchar* text, jint start, jint count, jint contextCount, jint dirFlags) {
    AutoMutex _l(mLock);
    nsecs_t startTime = 0;
@@ -105,7 +100,7 @@ sp<TextLayoutCacheValue> TextLayoutCache::getValue(const SkPaint* paint,
    TextLayoutCacheKey key(paint, text, start, count, contextCount, dirFlags);

    // Get value from cache if possible
    sp<TextLayoutCacheValue> value = mCache.get(key);
    sp<TextLayoutValue> value = mCache.get(key);

    // Value not found for the key, we need to add a new value in the cache
    if (value == NULL) {
@@ -113,10 +108,10 @@ sp<TextLayoutCacheValue> TextLayoutCache::getValue(const SkPaint* paint,
            startTime = systemTime(SYSTEM_TIME_MONOTONIC);
        }

        value = new TextLayoutCacheValue(contextCount);
        value = new TextLayoutValue(contextCount);

        // Compute advances and store them
        TextLayoutEngine::getInstance().computeValues(value.get(), paint,
        mShaper->computeValues(value.get(), paint,
                reinterpret_cast<const UChar*>(text), start, count,
                size_t(contextCount), int(dirFlags));

@@ -312,31 +307,33 @@ size_t TextLayoutCacheKey::getSize() const {
/**
 * TextLayoutCacheValue
 */
TextLayoutCacheValue::TextLayoutCacheValue(size_t contextCount) :
TextLayoutValue::TextLayoutValue(size_t contextCount) :
        mTotalAdvance(0), mElapsedTime(0) {
    // Give a hint for advances and glyphs vectors size
    mAdvances.setCapacity(contextCount);
    mGlyphs.setCapacity(contextCount);
}

size_t TextLayoutCacheValue::getSize() const {
    return sizeof(TextLayoutCacheValue) + sizeof(jfloat) * mAdvances.capacity() +
size_t TextLayoutValue::getSize() const {
    return sizeof(TextLayoutValue) + sizeof(jfloat) * mAdvances.capacity() +
            sizeof(jchar) * mGlyphs.capacity();
}

void TextLayoutCacheValue::setElapsedTime(uint32_t time) {
void TextLayoutValue::setElapsedTime(uint32_t time) {
    mElapsedTime = time;
}

uint32_t TextLayoutCacheValue::getElapsedTime() {
uint32_t TextLayoutValue::getElapsedTime() {
    return mElapsedTime;
}

TextLayoutEngine::TextLayoutEngine() : mShaperItemGlyphArraySize(0) {
TextLayoutShaper::TextLayoutShaper() : mShaperItemGlyphArraySize(0) {
    mDefaultTypeface = SkFontHost::CreateTypeface(NULL, NULL, NULL, 0, SkTypeface::kNormal);
    mArabicTypeface = NULL;
    mHebrewRegularTypeface = NULL;
    mHebrewBoldTypeface = NULL;
    mBengaliTypeface = NULL;
    mThaiTypeface = NULL;

    mFontRec.klass = &harfbuzzSkiaClass;
    mFontRec.userData = 0;
@@ -355,12 +352,17 @@ TextLayoutEngine::TextLayoutEngine() : mShaperItemGlyphArraySize(0) {
    mShaperItem.font->userData = &mShapingPaint;
}

TextLayoutEngine::~TextLayoutEngine() {
    // FIXME should free fonts and caches but since this class is a singleton,
    // we don't bother at the moment
TextLayoutShaper::~TextLayoutShaper() {
    SkSafeUnref(mDefaultTypeface);
    SkSafeUnref(mArabicTypeface);
    SkSafeUnref(mHebrewRegularTypeface);
    SkSafeUnref(mHebrewBoldTypeface);
    SkSafeUnref(mBengaliTypeface);
    SkSafeUnref(mThaiTypeface);
    deleteShaperItemGlyphArrays();
}

void TextLayoutEngine::computeValues(TextLayoutCacheValue* value, const SkPaint* paint, const UChar* chars,
void TextLayoutShaper::computeValues(TextLayoutValue* value, const SkPaint* paint, const UChar* chars,
        size_t start, size_t count, size_t contextCount, int dirFlags) {

    computeValues(paint, chars, start, count, contextCount, dirFlags,
@@ -371,7 +373,7 @@ void TextLayoutEngine::computeValues(TextLayoutCacheValue* value, const SkPaint*
#endif
}

void TextLayoutEngine::computeValues(const SkPaint* paint, const UChar* chars,
void TextLayoutShaper::computeValues(const SkPaint* paint, const UChar* chars,
        size_t start, size_t count, size_t contextCount, int dirFlags,
        Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
        Vector<jchar>* const outGlyphs) {
@@ -513,7 +515,7 @@ static void logGlyphs(HB_ShaperItem shaperItem) {
    }
}

void TextLayoutEngine::computeRunValues(const SkPaint* paint, const UChar* chars,
void TextLayoutShaper::computeRunValues(const SkPaint* paint, const UChar* chars,
        size_t count, bool isRTL,
        Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
        Vector<jchar>* const outGlyphs) {
@@ -719,7 +721,7 @@ void TextLayoutEngine::computeRunValues(const SkPaint* paint, const UChar* chars
}


size_t TextLayoutEngine::shapeFontRun(const SkPaint* paint, bool isRTL) {
size_t TextLayoutShaper::shapeFontRun(const SkPaint* paint, bool isRTL) {
    // Reset kerning
    mShaperItem.kerning_applied = false;

@@ -833,14 +835,14 @@ size_t TextLayoutEngine::shapeFontRun(const SkPaint* paint, bool isRTL) {
    return baseGlyphCount;
}

void TextLayoutEngine::ensureShaperItemGlyphArrays(size_t size) {
void TextLayoutShaper::ensureShaperItemGlyphArrays(size_t size) {
    if (size > mShaperItemGlyphArraySize) {
        deleteShaperItemGlyphArrays();
        createShaperItemGlyphArrays(size);
    }
}

void TextLayoutEngine::createShaperItemGlyphArrays(size_t size) {
void TextLayoutShaper::createShaperItemGlyphArrays(size_t size) {
#if DEBUG_GLYPHS
    ALOGD("Creating Glyph Arrays with size = %d", size);
#endif
@@ -858,7 +860,7 @@ void TextLayoutEngine::createShaperItemGlyphArrays(size_t size) {
    mShaperItem.log_clusters = new unsigned short[size];
}

void TextLayoutEngine::deleteShaperItemGlyphArrays() {
void TextLayoutShaper::deleteShaperItemGlyphArrays() {
    delete[] mShaperItem.glyphs;
    delete[] mShaperItem.attributes;
    delete[] mShaperItem.advances;
@@ -866,7 +868,7 @@ void TextLayoutEngine::deleteShaperItemGlyphArrays() {
    delete[] mShaperItem.log_clusters;
}

SkTypeface* TextLayoutEngine::getCachedTypeface(SkTypeface** typeface, const char path[]) {
SkTypeface* TextLayoutShaper::getCachedTypeface(SkTypeface** typeface, const char path[]) {
    if (!*typeface) {
        *typeface = SkTypeface::CreateFromFile(path);
        // CreateFromFile(path) can return NULL if the path is non existing
@@ -884,7 +886,7 @@ SkTypeface* TextLayoutEngine::getCachedTypeface(SkTypeface** typeface, const cha
    return *typeface;
}

HB_Face TextLayoutEngine::getCachedHBFace(SkTypeface* typeface) {
HB_Face TextLayoutShaper::getCachedHBFace(SkTypeface* typeface) {
    SkFontID fontId = typeface->uniqueID();
    ssize_t index = mCachedHBFaces.indexOfKey(fontId);
    if (index >= 0) {
@@ -900,4 +902,36 @@ HB_Face TextLayoutEngine::getCachedHBFace(SkTypeface* typeface) {
    return face;
}

TextLayoutEngine::TextLayoutEngine() {
    mShaper = new TextLayoutShaper();
#if USE_TEXT_LAYOUT_CACHE
    mTextLayoutCache = new TextLayoutCache(mShaper);
#else
    mTextLayoutCache = NULL;
#endif
}

TextLayoutEngine::~TextLayoutEngine() {
    delete mTextLayoutCache;
    delete mShaper;
}

sp<TextLayoutValue> TextLayoutEngine::getValue(const SkPaint* paint, const jchar* text,
        jint start, jint count, jint contextCount, jint dirFlags) {
    sp<TextLayoutValue> value;
#if USE_TEXT_LAYOUT_CACHE
    value = mTextLayoutCache->getValue(paint, text, start, count,
            contextCount, dirFlags);
    if (value == NULL) {
        ALOGE("Cannot get TextLayoutCache value for text = '%s'",
                String8(text + start, count).string());
    }
#else
    value = new TextLayoutValue(count);
    mShaper->computeValues(value.get(), paint,
            reinterpret_cast<const UChar*>(text), start, count, contextCount, dirFlags);
#endif
    return value;
}

} // namespace android
+81 −67
Original line number Diff line number Diff line
@@ -115,11 +115,11 @@ inline int compare_type(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey&
}

/*
 * TextLayoutCacheValue is the Cache value
 * TextLayoutValue is the Cache value
 */
class TextLayoutCacheValue : public RefBase {
class TextLayoutValue : public RefBase {
public:
    TextLayoutCacheValue(size_t contextCount);
    TextLayoutValue(size_t contextCount);

    void setElapsedTime(uint32_t time);
    uint32_t getElapsedTime();
@@ -159,72 +159,14 @@ private:
}; // TextLayoutCacheValue

/**
 * Cache of text layout information.
 * The TextLayoutShaper is responsible for shaping (with the Harfbuzz library)
 */
class TextLayoutCache : public OnEntryRemoved<TextLayoutCacheKey, sp<TextLayoutCacheValue> >,
        public Singleton<TextLayoutCache>
{
class TextLayoutShaper {
public:
    TextLayoutCache();

    virtual ~TextLayoutCache();

    bool isInitialized() {
        return mInitialized;
    }

    /**
     * Used as a callback when an entry is removed from the cache
     * Do not invoke directly
     */
    void operator()(TextLayoutCacheKey& text, sp<TextLayoutCacheValue>& desc);

    sp<TextLayoutCacheValue> getValue(const SkPaint* paint, const jchar* text, jint start, jint count,
            jint contextCount, jint dirFlags);

    /**
     * Clear the cache
     */
    void clear();

private:
    Mutex mLock;
    bool mInitialized;

    GenerationCache<TextLayoutCacheKey, sp<TextLayoutCacheValue> > mCache;

    uint32_t mSize;
    uint32_t mMaxSize;

    uint32_t mCacheHitCount;
    uint64_t mNanosecondsSaved;
    TextLayoutShaper();
    virtual ~TextLayoutShaper();

    uint64_t mCacheStartTime;

    RtlDebugLevel mDebugLevel;
    bool mDebugEnabled;

    /*
     * Class initialization
     */
    void init();

    /**
     * Dump Cache statistics
     */
    void dumpCacheStats();

}; // TextLayoutCache

/**
 * The TextLayoutEngine is responsible for shaping with Harfbuzz library
 */
class TextLayoutEngine : public Singleton<TextLayoutEngine> {
public:
    TextLayoutEngine();
    virtual ~TextLayoutEngine();

    void computeValues(TextLayoutCacheValue* value, const SkPaint* paint, const UChar* chars,
    void computeValues(TextLayoutValue* value, const SkPaint* paint, const UChar* chars,
            size_t start, size_t count, size_t contextCount, int dirFlags);

private:
@@ -292,8 +234,80 @@ private:
    void createShaperItemGlyphArrays(size_t size);
    void deleteShaperItemGlyphArrays();

}; // TextLayoutEngine
}; // TextLayoutShaper

/**
 * Cache of text layout information.
 */
class TextLayoutCache : private OnEntryRemoved<TextLayoutCacheKey, sp<TextLayoutValue> >
{
public:
    TextLayoutCache(TextLayoutShaper* shaper);

    ~TextLayoutCache();

    bool isInitialized() {
        return mInitialized;
    }

    /**
     * Used as a callback when an entry is removed from the cache
     * Do not invoke directly
     */
    void operator()(TextLayoutCacheKey& text, sp<TextLayoutValue>& desc);

    sp<TextLayoutValue> getValue(const SkPaint* paint, const jchar* text, jint start,
            jint count, jint contextCount, jint dirFlags);

    /**
     * Clear the cache
     */
    void clear();

private:
    TextLayoutShaper* mShaper;
    Mutex mLock;
    bool mInitialized;

    GenerationCache<TextLayoutCacheKey, sp<TextLayoutValue> > mCache;

    uint32_t mSize;
    uint32_t mMaxSize;

    uint32_t mCacheHitCount;
    uint64_t mNanosecondsSaved;

    uint64_t mCacheStartTime;

    RtlDebugLevel mDebugLevel;
    bool mDebugEnabled;

    /*
     * Class initialization
     */
    void init();

    /**
     * Dump Cache statistics
     */
    void dumpCacheStats();

}; // TextLayoutCache

/**
 * The TextLayoutEngine is reponsible for computing TextLayoutValues
 */
class TextLayoutEngine : public Singleton<TextLayoutEngine> {
public:
    TextLayoutEngine();
    virtual ~TextLayoutEngine();

    sp<TextLayoutValue> getValue(const SkPaint* paint, const jchar* text, jint start,
            jint count, jint contextCount, jint dirFlags);
private:
    TextLayoutCache* mTextLayoutCache;
    TextLayoutShaper* mShaper;
}; // TextLayoutEngine

} // namespace android
#endif /* ANDROID_TEXT_LAYOUT_CACHE_H */
Loading