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

Commit cb0975b3 authored by Romain Guy's avatar Romain Guy Committed by Android (Google) Code Review
Browse files

Merge "Add support to OpenGLRendere to draw BiDi text. Bug #4350336"

parents 0523c55e 726aeba8
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@
#include <SkiaColorFilter.h>
#include <Rect.h>

#include "TextLayout.h"
#include <TextLayout.h>

namespace android {

@@ -419,7 +419,7 @@ static void android_view_GLES20Canvas_setupShadow(JNIEnv* env, jobject clazz,

static void renderText(OpenGLRenderer* renderer, const jchar* text, int count,
        jfloat x, jfloat y, int flags, SkPaint* paint) {
#if 0 // TODO: replace "0" by "RTL_USE_HARFBUZZ" when renderer->drawGlyphs() is implemented
#if RTL_USE_HARFBUZZ
    sp<TextLayoutCacheValue> value = gTextLayoutCache.getValue(
            paint, text, 0, count, count, flags);
    if (value == NULL) {
@@ -431,7 +431,8 @@ static void renderText(OpenGLRenderer* renderer, const jchar* text, int count,
#endif
    const jchar* glyphArray = value->getGlyphs();
    int glyphCount = value->getGlyphsCount();
    renderer->drawGlyphs((const char*) glyphArray, 0, glyphCount << 1, x, y, paint);
    int bytesCount = glyphCount * sizeof(jchar);
    renderer->drawText((const char*) glyphArray, bytesCount, glyphCount, x, y, paint);
#else
    const jchar *workText;
    jchar* buffer = NULL;
@@ -446,7 +447,7 @@ static void renderText(OpenGLRenderer* renderer, const jchar* text, int count,
static void renderTextRun(OpenGLRenderer* renderer, const jchar* text,
        jint start, jint count, jint contextCount, jfloat x, jfloat y,
        int flags, SkPaint* paint) {
#if 0 // TODO: replace "0" by "RTL_USE_HARFBUZZ" when renderer->drawGlyphs() is implemented
#if RTL_USE_HARFBUZZ
    sp<TextLayoutCacheValue> value = gTextLayoutCache.getValue(
            paint, text, start, count, contextCount, flags);
    if (value == NULL) {
@@ -458,7 +459,8 @@ static void renderTextRun(OpenGLRenderer* renderer, const jchar* text,
#endif
    const jchar* glyphArray = value->getGlyphs();
    int glyphCount = value->getGlyphsCount();
    renderer->drawGlyphs((const char*) glyphArray, 0, glyphCount << 1, x, y, paint);
    int bytesCount = glyphCount * sizeof(jchar);
    renderer->drawText((const char*) glyphArray, bytesCount, glyphCount, x, y, paint);
#else
    uint8_t rtl = flags & 0x1;
    if (rtl) {
+1 −0
Original line number Diff line number Diff line
@@ -1151,6 +1151,7 @@ void DisplayListRenderer::drawPoints(float* points, int count, SkPaint* paint) {

void DisplayListRenderer::drawText(const char* text, int bytesCount, int count,
        float x, float y, SkPaint* paint) {
    if (count <= 0) return;
    addOp(DisplayList::DrawText);
    addText(text, bytesCount);
    addInt(count);
+22 −21
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ namespace uirenderer {
#define DEFAULT_TEXT_CACHE_WIDTH 1024
#define DEFAULT_TEXT_CACHE_HEIGHT 256

// We should query these values from the GL context
#define MAX_TEXT_CACHE_WIDTH 2048
#define MAX_TEXT_CACHE_HEIGHT 2048

@@ -58,8 +59,7 @@ Font::~Font() {
    }

    for (uint32_t i = 0; i < mCachedGlyphs.size(); i++) {
        CachedGlyphInfo* glyph = mCachedGlyphs.valueAt(i);
        delete glyph;
        delete mCachedGlyphs.valueAt(i);
    }
}

@@ -134,48 +134,49 @@ void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y,

}

Font::CachedGlyphInfo* Font::getCachedUTFChar(SkPaint* paint, int32_t utfChar) {
Font::CachedGlyphInfo* Font::getCachedGlyph(SkPaint* paint, glyph_t textUnit) {
    CachedGlyphInfo* cachedGlyph = NULL;
    ssize_t index = mCachedGlyphs.indexOfKey(utfChar);
    ssize_t index = mCachedGlyphs.indexOfKey(textUnit);
    if (index >= 0) {
        cachedGlyph = mCachedGlyphs.valueAt(index);
    } else {
        cachedGlyph = cacheGlyph(paint, utfChar);
        cachedGlyph = cacheGlyph(paint, textUnit);
    }

    // Is the glyph still in texture cache?
    if (!cachedGlyph->mIsValid) {
        const SkGlyph& skiaGlyph = paint->getUnicharMetrics(utfChar);
        const SkGlyph& skiaGlyph = GET_METRICS(paint, textUnit);
        updateGlyphCache(paint, skiaGlyph, cachedGlyph);
    }

    return cachedGlyph;
}

void Font::renderUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
        int numGlyphs, int x, int y, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) {
    if (bitmap != NULL && bitmapW > 0 && bitmapH > 0) {
        renderUTF(paint, text, start, len, numGlyphs, x, y, BITMAP, bitmap,
        render(paint, text, start, len, numGlyphs, x, y, BITMAP, bitmap,
                bitmapW, bitmapH, NULL);
    } else {
        renderUTF(paint, text, start, len, numGlyphs, x, y, FRAMEBUFFER, NULL, 0, 0, NULL);
        render(paint, text, start, len, numGlyphs, x, y, FRAMEBUFFER, NULL,
                0, 0, NULL);
    }

}

void Font::measureUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
void Font::measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
        int numGlyphs, Rect *bounds) {
    if (bounds == NULL) {
        LOGE("No return rectangle provided to measure text");
        return;
    }
    bounds->set(1e6, -1e6, -1e6, 1e6);
    renderUTF(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds);
    render(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds);
}

#define SkAutoKern_AdjustF(prev, next) (((next) - (prev) + 32) >> 6 << 16)

void Font::renderUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
        int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
        uint32_t bitmapW, uint32_t bitmapH,Rect *bounds) {
    if (numGlyphs == 0 || text == NULL || len == 0) {
@@ -195,14 +196,14 @@ void Font::renderUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t
    text += start;

    while (glyphsLeft > 0) {
        int32_t utfChar = SkUTF16_NextUnichar((const uint16_t**) &text);
        glyph_t glyph = GET_GLYPH(text);

        // Reached the end of the string
        if (utfChar < 0) {
        if (IS_END_OF_STRING(glyph)) {
            break;
        }

        CachedGlyphInfo* cachedGlyph = getCachedUTFChar(paint, utfChar);
        CachedGlyphInfo* cachedGlyph = getCachedGlyph(paint, glyph);
        penX += SkAutoKern_AdjustF(prevRsbDelta, cachedGlyph->mLsbDelta);
        prevRsbDelta = cachedGlyph->mRsbDelta;

@@ -268,11 +269,11 @@ void Font::updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyp
    mState->mUploadTexture = true;
}

Font::CachedGlyphInfo* Font::cacheGlyph(SkPaint* paint, int32_t glyph) {
Font::CachedGlyphInfo* Font::cacheGlyph(SkPaint* paint, glyph_t glyph) {
    CachedGlyphInfo* newGlyph = new CachedGlyphInfo();
    mCachedGlyphs.add(glyph, newGlyph);

    const SkGlyph& skiaGlyph = paint->getUnicharMetrics(glyph);
    const SkGlyph& skiaGlyph = GET_METRICS(paint, glyph);
    newGlyph->mGlyphIndex = skiaGlyph.fID;
    newGlyph->mIsValid = false;

@@ -672,7 +673,7 @@ void FontRenderer::precacheLatin(SkPaint* paint) {
    uint32_t remainingCapacity = getRemainingCacheCapacity();
    uint32_t precacheIdx = 0;
    while (remainingCapacity > 25 && precacheIdx < mLatinPrecache.size()) {
        mCurrentFont->getCachedUTFChar(paint, (int32_t) mLatinPrecache[precacheIdx]);
        mCurrentFont->getCachedGlyph(paint, (int32_t) mLatinPrecache[precacheIdx]);
        remainingCapacity = getRemainingCacheCapacity();
        precacheIdx ++;
    }
@@ -714,7 +715,7 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch
    }

    Rect bounds;
    mCurrentFont->measureUTF(paint, text, startIndex, len, numGlyphs, &bounds);
    mCurrentFont->measure(paint, text, startIndex, len, numGlyphs, &bounds);
    uint32_t paddedWidth = (uint32_t) (bounds.right - bounds.left) + 2 * radius;
    uint32_t paddedHeight = (uint32_t) (bounds.top - bounds.bottom) + 2 * radius;
    uint8_t* dataBuffer = new uint8_t[paddedWidth * paddedHeight];
@@ -725,7 +726,7 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch
    int penX = radius - bounds.left;
    int penY = radius - bounds.bottom;

    mCurrentFont->renderUTF(paint, text, startIndex, len, numGlyphs, penX, penY,
    mCurrentFont->render(paint, text, startIndex, len, numGlyphs, penX, penY,
            dataBuffer, paddedWidth, paddedHeight);
    blurImage(dataBuffer, paddedWidth, paddedHeight, radius);

@@ -755,7 +756,7 @@ bool FontRenderer::renderText(SkPaint* paint, const Rect* clip, const char *text
    mDrawn = false;
    mBounds = bounds;
    mClip = clip;
    mCurrentFont->renderUTF(paint, text, startIndex, len, numGlyphs, x, y);
    mCurrentFont->render(paint, text, startIndex, len, numGlyphs, x, y);
    mBounds = NULL;

    if (mCurrentQuadIndex != 0) {
+48 −13
Original line number Diff line number Diff line
@@ -33,8 +33,32 @@
namespace android {
namespace uirenderer {

///////////////////////////////////////////////////////////////////////////////
// Defines
///////////////////////////////////////////////////////////////////////////////

#if RENDER_TEXT_AS_GLYPHS
    typedef uint16_t glyph_t;
    #define GET_METRICS(paint, glyph) paint->getGlyphMetrics(glyph)
    #define GET_GLYPH(text) nextGlyph((const uint16_t**) &text)
    #define IS_END_OF_STRING(glyph) false
#else
    typedef SkUnichar glyph_t;
    #define GET_METRICS(paint, glyph) paint->getUnicharMetrics(glyph)
    #define GET_GLYPH(text) SkUTF16_NextUnichar((const uint16_t**) &text)
    #define IS_END_OF_STRING(glyph) glyph < 0
#endif

///////////////////////////////////////////////////////////////////////////////
// Declarations
///////////////////////////////////////////////////////////////////////////////

class FontRenderer;

///////////////////////////////////////////////////////////////////////////////
// Font
///////////////////////////////////////////////////////////////////////////////

/**
 * Represents a font, defined by a Skia font id and a font size. A font is used
 * to generate glyphs and cache them in the FontState.
@@ -51,9 +75,9 @@ public:
     * Renders the specified string of text.
     * If bitmap is specified, it will be used as the render target
     */
    void renderUTF(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
                     int numGlyphs, int x, int y,
                     uint8_t *bitmap = NULL, uint32_t bitmapW = 0, uint32_t bitmapH = 0);
    void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
            int numGlyphs, int x, int y, uint8_t *bitmap = NULL,
            uint32_t bitmapW = 0, uint32_t bitmapH = 0);
    /**
     * Creates a new font associated with the specified font state.
     */
@@ -69,12 +93,11 @@ protected:
        MEASURE,
    };

    void renderUTF(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
                     int numGlyphs, int x, int y, RenderMode mode,
                     uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
                     Rect *bounds);
    void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
            int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
            uint32_t bitmapW, uint32_t bitmapH, Rect *bounds);

    void measureUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
    void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
            int numGlyphs, Rect *bounds);

    struct CachedGlyphInfo {
@@ -107,18 +130,26 @@ protected:
    Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle,
            uint32_t scaleX);

    DefaultKeyedVector<int32_t, CachedGlyphInfo*> mCachedGlyphs;
    // Cache of glyphs
    DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;

    void invalidateTextureCache();

    CachedGlyphInfo* cacheGlyph(SkPaint* paint, int32_t glyph);
    CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph);
    void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo *glyph);
    void measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, Rect *bounds);
    void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y);
    void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y,
            uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH);

    CachedGlyphInfo* getCachedUTFChar(SkPaint* paint, int32_t utfChar);
    CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit);

    static glyph_t nextGlyph(const uint16_t** srcPtr) {
        const uint16_t* src = *srcPtr;
        glyph_t g = *src++;
        *srcPtr = src;
        return g;
    }

    FontRenderer* mState;
    uint32_t mFontId;
@@ -128,6 +159,10 @@ protected:
    uint32_t mScaleX;
};

///////////////////////////////////////////////////////////////////////////////
// Renderer
///////////////////////////////////////////////////////////////////////////////

class FontRenderer {
public:
    FontRenderer();
+10 −12
Original line number Diff line number Diff line
@@ -2073,11 +2073,6 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
    drawTextDecorations(text, bytesCount, length, oldX, oldY, paint);
}

void OpenGLRenderer::drawGlyphs(const char* glyphs, int index, int count, float x, float y,
        SkPaint* paint) {
    // TODO
}

void OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) {
    if (mSnapshot->isIgnored()) return;

@@ -2230,14 +2225,19 @@ void OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float
    // Handle underline and strike-through
    uint32_t flags = paint->getFlags();
    if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
        SkPaint paintCopy(*paint);
#if RENDER_TEXT_AS_GLYPHS
        paintCopy.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
#endif

        float underlineWidth = length;
        // If length is > 0.0f, we already measured the text for the text alignment
        if (length <= 0.0f) {
            underlineWidth = paint->measureText(text, bytesCount);
            underlineWidth = paintCopy.measureText(text, bytesCount);
        }

        float offsetX = 0;
        switch (paint->getTextAlign()) {
        switch (paintCopy.getTextAlign()) {
            case SkPaint::kCenter_Align:
                offsetX = underlineWidth * 0.5f;
                break;
@@ -2249,8 +2249,7 @@ void OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float
        }

        if (underlineWidth > 0.0f) {
            const float textSize = paint->getTextSize();
            // TODO: Support stroke width < 1.0f when we have AA lines
            const float textSize = paintCopy.getTextSize();
            const float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);

            const float left = x - offsetX;
@@ -2280,10 +2279,9 @@ void OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float
                points[currentPoint++] = top;
            }

            SkPaint linesPaint(*paint);
            linesPaint.setStrokeWidth(strokeWidth);
            paintCopy.setStrokeWidth(strokeWidth);

            drawLines(&points[0], pointsCount, &linesPaint);
            drawLines(&points[0], pointsCount, &paintCopy);
        }
    }
}
Loading