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

Commit 996e57c8 authored by Raph Levien's avatar Raph Levien
Browse files

Hardware implementation of glyph positioning (bug 5443796)

This implementation adds a drawGeneralText() method to the OpenGL
Renderer, which supports both a global x, y position, an array of
individual glyph positions, and also a length parameter (which enables
drawing of underline and strikethrough. It also adds the method to the
display list (with marshalling and unmarshalling).

With this change, the existing drawText() method is removed entirely, as
it's subsumed by the new method. It's easy enough to revert to the old
functionality if needed by passing in a NULL positions array.

Change-Id: I8c9e6ce4309fd51cc5511db85df99f6de8f4f6f5
parent 219dfa4d
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -528,8 +528,11 @@ static void renderText(OpenGLRenderer* renderer, const jchar* text, int count,
    }
    const jchar* glyphs = value->getGlyphs();
    size_t glyphsCount = value->getGlyphsCount();
    jfloat totalAdvance = value->getTotalAdvance();
    const float* positions = value->getPos();
    int bytesCount = glyphsCount * sizeof(jchar);
    renderer->drawText((const char*) glyphs, bytesCount, glyphsCount, x, y, paint);
    renderer->drawGeneralText((const char*) glyphs, bytesCount, glyphsCount, x, y,
            positions, paint, totalAdvance);
}

static void renderTextOnPath(OpenGLRenderer* renderer, const jchar* text, int count,
@@ -556,8 +559,11 @@ static void renderTextRun(OpenGLRenderer* renderer, const jchar* text,
    }
    const jchar* glyphs = value->getGlyphs();
    size_t glyphsCount = value->getGlyphsCount();
    jfloat totalAdvance = value->getTotalAdvance();
    const float* positions = value->getPos();
    int bytesCount = glyphsCount * sizeof(jchar);
    renderer->drawText((const char*) glyphs, bytesCount, glyphsCount, x, y, paint);
    renderer->drawGeneralText((const char*) glyphs, bytesCount, glyphsCount, x, y,
            positions, paint, totalAdvance);
}

static void android_view_GLES20Canvas_drawTextArray(JNIEnv* env, jobject clazz,
+59 −55
Original line number Diff line number Diff line
@@ -61,9 +61,9 @@ const char* DisplayList::OP_NAMES[] = {
    "DrawPath",
    "DrawLines",
    "DrawPoints",
    "DrawText",
    "DrawTextOnPath",
    "DrawPosText",
    "DrawGeneralText",
    "ResetShader",
    "SetupShader",
    "ResetColorFilter",
@@ -572,17 +572,6 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
                ALOGD("%s%s", (char*) indent, OP_NAMES[op]);
            }
            break;
            case DrawText: {
                getText(&text);
                int32_t count = getInt();
                float x = getFloat();
                float y = getFloat();
                SkPaint* paint = getPaint(renderer);
                float length = getFloat();
                ALOGD("%s%s %s, %d, %d, %.2f, %.2f, %p, %.2f", (char*) indent, OP_NAMES[op],
                        text.text(), text.length(), count, x, y, paint, length);
            }
            break;
            case DrawTextOnPath: {
                getText(&text);
                int32_t count = getInt();
@@ -603,6 +592,17 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
                ALOGD("%s%s %s, %d, %d, %p", (char*) indent, OP_NAMES[op],
                        text.text(), text.length(), count, paint);
            }
            break;
            case DrawGeneralText: {
                getText(&text);
                int count = getInt();
                int positionsCount = 0;
                float* positions = getFloats(positionsCount);
                SkPaint* paint = getPaint(renderer);
                ALOGD("%s%s %s, %d, %d, %p", (char*) indent, OP_NAMES[op],
                        text.text(), text.length(), count, paint);
            }
            break;
            case ResetShader: {
                ALOGD("%s%s", (char*) indent, OP_NAMES[op]);
            }
@@ -1196,19 +1196,6 @@ status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flag
                drawGlStatus |= renderer.drawPoints(points, count, paint);
            }
            break;
            case DrawText: {
                getText(&text);
                int32_t count = getInt();
                float x = getFloat();
                float y = getFloat();
                SkPaint* paint = getPaint(renderer);
                float length = getFloat();
                DISPLAY_LIST_LOGD("%s%s %s, %d, %d, %.2f, %.2f, %p, %.2f", (char*) indent,
                        OP_NAMES[op], text.text(), text.length(), count, x, y, paint, length);
                drawGlStatus |= renderer.drawText(text.text(), text.length(), count, x, y,
                        paint, length);
            }
            break;
            case DrawTextOnPath: {
                getText(&text);
                int32_t count = getInt();
@@ -1234,6 +1221,21 @@ status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flag
                        positions, paint);
            }
            break;
            case DrawGeneralText: {
                getText(&text);
                int32_t count = getInt();
                float x = getFloat();
                float y = getFloat();
                int32_t positionsCount = 0;
                float* positions = getFloats(positionsCount);
                SkPaint* paint = getPaint(renderer);
                float length = getFloat();
                DISPLAY_LIST_LOGD("%s%s %s, %d, %d, %.2f, %.2f, %p, %.2f", (char*) indent,
                        OP_NAMES[op], text.text(), text.length(), count, x, y, paint, length);
                drawGlStatus |= renderer.drawGeneralText(text.text(), text.length(), count,
                        x, y, positions, paint, length);
            }
            break;
            case ResetShader: {
                DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
                renderer.resetShader();
@@ -1684,8 +1686,34 @@ status_t DisplayListRenderer::drawPoints(float* points, int count, SkPaint* pain
    return DrawGlInfo::kStatusDone;
}

status_t DisplayListRenderer::drawText(const char* text, int bytesCount, int count,
        float x, float y, SkPaint* paint, float length) {
status_t DisplayListRenderer::drawTextOnPath(const char* text, int bytesCount, int count,
        SkPath* path, float hOffset, float vOffset, SkPaint* paint) {
    if (!text || count <= 0) return DrawGlInfo::kStatusDone;
    addOp(DisplayList::DrawTextOnPath);
    addText(text, bytesCount);
    addInt(count);
    addPath(path);
    addFloat(hOffset);
    addFloat(vOffset);
    paint->setAntiAlias(true);
    addPaint(paint);
    return DrawGlInfo::kStatusDone;
}

status_t DisplayListRenderer::drawPosText(const char* text, int bytesCount, int count,
        const float* positions, SkPaint* paint) {
    if (!text || count <= 0) return DrawGlInfo::kStatusDone;
    addOp(DisplayList::DrawPosText);
    addText(text, bytesCount);
    addInt(count);
    addFloats(positions, count * 2);
    paint->setAntiAlias(true);
    addPaint(paint);
    return DrawGlInfo::kStatusDone;
}

status_t DisplayListRenderer::drawGeneralText(const char* text, int bytesCount, int count,
        float x, float y, const float* positions, SkPaint* paint, float length) {
    if (!text || count <= 0) return DrawGlInfo::kStatusDone;

    // TODO: We should probably make a copy of the paint instead of modifying
@@ -1705,42 +1733,18 @@ status_t DisplayListRenderer::drawText(const char* text, int bytesCount, int cou
        reject = quickReject(x, y + metrics.fTop, x + length, y + metrics.fBottom);
    }

    uint32_t* location = addOp(DisplayList::DrawText, reject);
    uint32_t* location = addOp(DisplayList::DrawGeneralText, reject);
    addText(text, bytesCount);
    addInt(count);
    addPoint(x, y);
    addFloat(x);
    addFloat(y);
    addFloats(positions, count * 2);
    addPaint(paint);
    addFloat(length);
    addSkip(location);
    return DrawGlInfo::kStatusDone;
}

status_t DisplayListRenderer::drawTextOnPath(const char* text, int bytesCount, int count,
        SkPath* path, float hOffset, float vOffset, SkPaint* paint) {
    if (!text || count <= 0) return DrawGlInfo::kStatusDone;
    addOp(DisplayList::DrawTextOnPath);
    addText(text, bytesCount);
    addInt(count);
    addPath(path);
    addFloat(hOffset);
    addFloat(vOffset);
    paint->setAntiAlias(true);
    addPaint(paint);
    return DrawGlInfo::kStatusDone;
}

status_t DisplayListRenderer::drawPosText(const char* text, int bytesCount, int count,
        const float* positions, SkPaint* paint) {
    if (!text || count <= 0) return DrawGlInfo::kStatusDone;
    addOp(DisplayList::DrawPosText);
    addText(text, bytesCount);
    addInt(count);
    addFloats(positions, count * 2);
    paint->setAntiAlias(true);
    addPaint(paint);
    return DrawGlInfo::kStatusDone;
}

void DisplayListRenderer::resetShader() {
    addOp(DisplayList::ResetShader);
}
+3 −3
Original line number Diff line number Diff line
@@ -103,9 +103,9 @@ public:
        DrawPath,
        DrawLines,
        DrawPoints,
        DrawText,
        DrawTextOnPath,
        DrawPosText,
        DrawGeneralText,
        ResetShader,
        SetupShader,
        ResetColorFilter,
@@ -599,12 +599,12 @@ public:
    virtual status_t drawPath(SkPath* path, SkPaint* paint);
    virtual status_t drawLines(float* points, int count, SkPaint* paint);
    virtual status_t drawPoints(float* points, int count, SkPaint* paint);
    virtual status_t drawText(const char* text, int bytesCount, int count, float x, float y,
            SkPaint* paint, float length = -1.0f);
    virtual status_t drawTextOnPath(const char* text, int bytesCount, int count, SkPath* path,
            float hOffset, float vOffset, SkPaint* paint);
    virtual status_t drawPosText(const char* text, int bytesCount, int count,
            const float* positions, SkPaint* paint);
    virtual status_t drawGeneralText(const char* text, int bytesCount, int count,
            float x, float y, const float* positions, SkPaint* paint, float length);

    virtual void resetShader();
    virtual void setupShader(SkiaShader* shader);
+16 −6
Original line number Diff line number Diff line
@@ -2421,8 +2421,8 @@ status_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count
    return DrawGlInfo::kStatusDrew;
}

status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
        float x, float y, SkPaint* paint, float length) {
status_t OpenGLRenderer::drawGeneralText(const char* text, int bytesCount, int count,
        float x, float y, const float* positions, SkPaint* paint, float length) {
    if (text == NULL || count == 0 || mSnapshot->isIgnored() ||
            (paint->getAlpha() * mSnapshot->alpha == 0 && paint->getXfermode() == NULL)) {
        return DrawGlInfo::kStatusDone;
@@ -2455,7 +2455,8 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
    }

#if DEBUG_GLYPHS
    ALOGD("OpenGLRenderer drawText() with FontID=%d", SkTypeface::UniqueID(paint->getTypeface()));
    ALOGD("OpenGLRenderer drawGeneralText() with FontID=%d",
            SkTypeface::UniqueID(paint->getTypeface()));
#endif

    FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
@@ -2467,7 +2468,8 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
    getAlphaAndMode(paint, &alpha, &mode);

    if (CC_UNLIKELY(mHasShadow)) {
        drawTextShadow(paint, text, bytesCount, count, NULL, fontRenderer, alpha, mode, oldX, oldY);
        drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer, alpha, mode,
                oldX, oldY);
    }

    // Pick the appropriate texture filtering
@@ -2505,8 +2507,16 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
    const bool hasActiveLayer = false;
#endif

    if (fontRenderer.renderText(paint, clip, text, 0, bytesCount, count, x, y,
            hasActiveLayer ? &bounds : NULL)) {
    bool status;
    if (positions != NULL) {
        status = fontRenderer.renderPosText(paint, clip, text, 0, bytesCount, count, x, y,
            positions, hasActiveLayer ? &bounds : NULL);
    } else {
        // TODO: would it be okay to call renderPosText with null positions?
        status = fontRenderer.renderText(paint, clip, text, 0, bytesCount, count, x, y,
            hasActiveLayer ? &bounds : NULL);
    }
    if (status) {
#if RENDER_LAYERS_AS_REGIONS
        if (hasActiveLayer) {
            if (!pureTranslate) {
+2 −2
Original line number Diff line number Diff line
@@ -138,12 +138,12 @@ public:
    virtual status_t drawPath(SkPath* path, SkPaint* paint);
    virtual status_t drawLines(float* points, int count, SkPaint* paint);
    virtual status_t drawPoints(float* points, int count, SkPaint* paint);
    virtual status_t drawText(const char* text, int bytesCount, int count, float x, float y,
            SkPaint* paint, float length = -1.0f);
    virtual status_t drawTextOnPath(const char* text, int bytesCount, int count, SkPath* path,
            float hOffset, float vOffset, SkPaint* paint);
    virtual status_t drawPosText(const char* text, int bytesCount, int count,
            const float* positions, SkPaint* paint);
    virtual status_t drawGeneralText(const char* text, int bytesCount, int count, float x, float y,
            const float* positions, SkPaint* paint, float length = -1.0f);

    virtual void resetShader();
    virtual void setupShader(SkiaShader* shader);