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

Commit e3a9b24b authored by Romain Guy's avatar Romain Guy
Browse files

Add plumbing for better text scaling

Fonts are now described by a transform matrix. This lead to switching
from a vector to a hashmap. This change therefore adds new comparators
and hash computations to Font.

Change-Id: I2daffa7d6287c18554c606b8bfa06640d28b4530
parent 5b4628ae
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -1775,7 +1775,7 @@ status_t DisplayListRenderer::drawTextOnPath(const char* text, int bytesCount, i
    paint->setAntiAlias(true);
    SkPaint* addedPaint = addPaint(paint);
    FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(addedPaint);
    fontRenderer.precache(addedPaint, text, count);
    fontRenderer.precache(addedPaint, text, count, *mSnapshot->transform);
    return DrawGlInfo::kStatusDone;
}

@@ -1789,7 +1789,7 @@ status_t DisplayListRenderer::drawPosText(const char* text, int bytesCount, int
    paint->setAntiAlias(true);
    SkPaint* addedPaint = addPaint(paint);
    FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(addedPaint);
    fontRenderer.precache(addedPaint, text, count);
    fontRenderer.precache(addedPaint, text, count, *mSnapshot->transform);
    return DrawGlInfo::kStatusDone;
}

@@ -1823,7 +1823,7 @@ status_t DisplayListRenderer::drawText(const char* text, int bytesCount, int cou
    SkPaint* addedPaint = addPaint(paint);
    if (!reject) {
        FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(addedPaint);
        fontRenderer.precache(addedPaint, text, count);
        fontRenderer.precache(addedPaint, text, count, *mSnapshot->transform);
    }
    addFloat(length);
    addSkip(location);
+18 −60
Original line number Diff line number Diff line
@@ -36,7 +36,9 @@ namespace uirenderer {

static bool sLogFontRendererCreate = true;

FontRenderer::FontRenderer() {
FontRenderer::FontRenderer() :
        mActiveFonts(LruCache<Font::FontDescription, Font*>::kUnlimitedCapacity) {

    if (sLogFontRendererCreate) {
        INIT_LOGD("Creating FontRenderer");
    }
@@ -107,10 +109,11 @@ FontRenderer::~FontRenderer() {
        delete[] mTextMesh;
    }

    Vector<Font*> fontsToDereference = mActiveFonts;
    for (uint32_t i = 0; i < fontsToDereference.size(); i++) {
        delete fontsToDereference[i];
    LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts);
    while (it.next()) {
        delete it.value();
    }
    mActiveFonts.clear();
}

void FontRenderer::flushAllAndInvalidate() {
@@ -118,8 +121,9 @@ void FontRenderer::flushAllAndInvalidate() {
        issueDrawCommand();
    }

    for (uint32_t i = 0; i < mActiveFonts.size(); i++) {
        mActiveFonts[i]->invalidateTextureCache();
    LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts);
    while (it.next()) {
        it.value()->invalidateTextureCache();
    }

    for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
@@ -146,8 +150,9 @@ void FontRenderer::flushLargeCaches() {
        CacheTexture* cacheTexture = mCacheTextures[i];
        if (cacheTexture->getTexture()) {
            cacheTexture->init();
            for (uint32_t j = 0; j < mActiveFonts.size(); j++) {
                mActiveFonts[j]->invalidateTextureCache(cacheTexture);
            LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts);
            while (it.next()) {
                it.value()->invalidateTextureCache(cacheTexture);
            }
            cacheTexture->releaseTexture();
        }
@@ -480,22 +485,8 @@ void FontRenderer::appendRotatedMeshQuad(float x1, float y1, float u1, float v1,
    }
}

void FontRenderer::setFont(SkPaint* paint, uint32_t fontId, float fontSize) {
    int flags = 0;
    if (paint->isFakeBoldText()) {
        flags |= Font::kFakeBold;
    }

    const float skewX = paint->getTextSkewX();
    uint32_t italicStyle = *(uint32_t*) &skewX;
    const float scaleXFloat = paint->getTextScaleX();
    uint32_t scaleX = *(uint32_t*) &scaleXFloat;
    SkPaint::Style style = paint->getStyle();
    const float strokeWidthFloat = paint->getStrokeWidth();
    uint32_t strokeWidth = *(uint32_t*) &strokeWidthFloat;
    mCurrentFont = Font::create(this, fontId, fontSize, flags, italicStyle,
            scaleX, style, strokeWidth);

void FontRenderer::setFont(SkPaint* paint, const mat4& matrix) {
    mCurrentFont = Font::create(this, paint, matrix);
}

FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const char *text,
@@ -561,39 +552,11 @@ void FontRenderer::finishRender() {
    }
}

void FontRenderer::precache(SkPaint* paint, const char* text, int numGlyphs) {
    int flags = 0;
    if (paint->isFakeBoldText()) {
        flags |= Font::kFakeBold;
    }
    const float skewX = paint->getTextSkewX();
    uint32_t italicStyle = *(uint32_t*) &skewX;
    const float scaleXFloat = paint->getTextScaleX();
    uint32_t scaleX = *(uint32_t*) &scaleXFloat;
    SkPaint::Style style = paint->getStyle();
    const float strokeWidthFloat = paint->getStrokeWidth();
    uint32_t strokeWidth = *(uint32_t*) &strokeWidthFloat;
    float fontSize = paint->getTextSize();
    Font* font = Font::create(this, SkTypeface::UniqueID(paint->getTypeface()),
            fontSize, flags, italicStyle, scaleX, style, strokeWidth);

void FontRenderer::precache(SkPaint* paint, const char* text, int numGlyphs, const mat4& matrix) {
    Font* font = Font::create(this, paint, matrix);
    font->precache(paint, text, numGlyphs);
}

bool FontRenderer::renderText(SkPaint* paint, const Rect* clip, const char *text,
        uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, Rect* bounds) {
    if (!mCurrentFont) {
        ALOGE("No font set");
        return false;
    }

    initRender(clip, bounds);
    mCurrentFont->render(paint, text, startIndex, len, numGlyphs, x, y);
    finishRender();

    return mDrawn;
}

bool FontRenderer::renderPosText(SkPaint* paint, const Rect* clip, const char *text,
        uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y,
        const float* positions, Rect* bounds) {
@@ -625,12 +588,7 @@ bool FontRenderer::renderTextOnPath(SkPaint* paint, const Rect* clip, const char
}

void FontRenderer::removeFont(const Font* font) {
    for (uint32_t ct = 0; ct < mActiveFonts.size(); ct++) {
        if (mActiveFonts[ct] == font) {
            mActiveFonts.removeAt(ct);
            break;
        }
    }
    mActiveFonts.remove(font->getDescription());

    if (mCurrentFont == font) {
        mCurrentFont = NULL;
+5 −6
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#ifndef ANDROID_HWUI_FONT_RENDERER_H
#define ANDROID_HWUI_FONT_RENDERER_H

#include <utils/LruCache.h>
#include <utils/Vector.h>

#include <SkPaint.h>
@@ -27,6 +28,7 @@
#include "font/CacheTexture.h"
#include "font/CachedGlyphInfo.h"
#include "font/Font.h"
#include "Matrix.h"
#include "Properties.h"

namespace android {
@@ -47,13 +49,10 @@ public:
        mGammaTable = gammaTable;
    }

    void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
    void setFont(SkPaint* paint, const mat4& matrix);

    void precache(SkPaint* paint, const char* text, int numGlyphs);
    void precache(SkPaint* paint, const char* text, int numGlyphs, const mat4& matrix);

    // bounds is an out parameter
    bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
            uint32_t len, int numGlyphs, int x, int y, Rect* bounds);
    // bounds is an out parameter
    bool renderPosText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
            uint32_t len, int numGlyphs, int x, int y, const float* positions, Rect* bounds);
@@ -153,7 +152,7 @@ private:
    Vector<CacheTexture*> mCacheTextures;

    Font* mCurrentFont;
    Vector<Font*> mActiveFonts;
    LruCache<Font::FontDescription, Font*> mActiveFonts;

    CacheTexture* mCurrentCacheTexture;

+8 −0
Original line number Diff line number Diff line
@@ -67,6 +67,14 @@ void LayerCache::setMaxSize(uint32_t maxSize) {
// Caching
///////////////////////////////////////////////////////////////////////////////

int LayerCache::LayerEntry::compare(const LayerCache::LayerEntry& lhs,
        const LayerCache::LayerEntry& rhs) {
    int deltaInt = int(lhs.mWidth) - int(rhs.mWidth);
    if (deltaInt != 0) return deltaInt;

    return int(lhs.mHeight) - int(rhs.mHeight);
}

void LayerCache::deleteLayer(Layer* layer) {
    if (layer) {
        LAYER_LOGD("Destroying layer %dx%d, fbo %d", layer->getWidth(), layer->getHeight(),
+18 −10
Original line number Diff line number Diff line
@@ -102,9 +102,6 @@ public:
     */
    void dump();

private:
    void deleteLayer(Layer* layer);

    struct LayerEntry {
        LayerEntry():
            mLayer(NULL), mWidth(0), mHeight(0) {
@@ -119,15 +116,14 @@ private:
            mLayer(layer), mWidth(layer->getWidth()), mHeight(layer->getHeight()) {
        }

        bool operator<(const LayerEntry& rhs) const {
            if (mWidth == rhs.mWidth) {
                return mHeight < rhs.mHeight;
            }
            return mWidth < rhs.mWidth;
        static int compare(const LayerEntry& lhs, const LayerEntry& rhs);

        bool operator==(const LayerEntry& other) const {
            return compare(*this, other) == 0;
        }

        bool operator==(const LayerEntry& rhs) const {
            return mWidth == rhs.mWidth && mHeight == rhs.mHeight;
        bool operator!=(const LayerEntry& other) const {
            return compare(*this, other) != 0;
        }

        Layer* mLayer;
@@ -135,12 +131,24 @@ private:
        uint32_t mHeight;
    }; // struct LayerEntry

private:
    void deleteLayer(Layer* layer);

    SortedList<LayerEntry> mCache;

    uint32_t mSize;
    uint32_t mMaxSize;
}; // class LayerCache

inline int strictly_order_type(const LayerCache::LayerEntry& lhs,
        const LayerCache::LayerEntry& rhs) {
    return LayerCache::LayerEntry::compare(lhs, rhs) < 0;
}

inline int compare_type(const LayerCache::LayerEntry& lhs, const LayerCache::LayerEntry& rhs) {
    return LayerCache::LayerEntry::compare(lhs, rhs);
}

}; // namespace uirenderer
}; // namespace android

Loading