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

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

Merge "Correctly render text when coordinates are not integers. Bug #3225632"

parents 97fdd7dc 6620c6d4
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -62,6 +62,11 @@ bool Matrix4::changesBounds() {
             ALMOST_EQUAL(data[10], 1.0f));
}

bool Matrix4::isPureTranslate() {
    return mSimpleMatrix &&
            ALMOST_EQUAL(data[kScaleX], 1.0f) && ALMOST_EQUAL(data[kScaleY], 1.0f);
}

void Matrix4::load(const float* v) {
    memcpy(data, v, sizeof(data));
    mSimpleMatrix = false;
+2 −0
Original line number Diff line number Diff line
@@ -103,6 +103,8 @@ public:
        multiply(u);
    }

    bool isPureTranslate();

    bool changesBounds();

    void copyTo(float* v) const;
+88 −25
Original line number Diff line number Diff line
@@ -909,9 +909,19 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap,
    SkXfermode::Mode mode;
    getAlphaAndMode(paint, &alpha, &mode);

    if (mSnapshot->transform->isPureTranslate()) {
        const float x = (int) floorf(dstLeft + mSnapshot->transform->getTranslateX() + 0.5f);
        const float y = (int) floorf(dstTop + mSnapshot->transform->getTranslateY() + 0.5f);

        drawTextureMesh(x, y, x + (dstRight - dstLeft), y + (dstBottom - dstTop),
                texture->id, alpha / 255.0f, mode, texture->blend,
                &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0],
                GL_TRIANGLE_STRIP, gMeshCount, false, true);
    } else {
        drawTextureMesh(dstLeft, dstTop, dstRight, dstBottom, texture->id, alpha / 255.0f,
                mode, texture->blend, &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0],
                GL_TRIANGLE_STRIP, gMeshCount);
    }

    resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
}
@@ -937,6 +947,7 @@ void OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int
            right - left, bottom - top, xDivs, yDivs, colors, width, height, numColors);

    if (mesh && mesh->verticesCount > 0) {
        const bool pureTranslate = mSnapshot->transform->isPureTranslate();
#if RENDER_LAYERS_AS_REGIONS
        // Mark the current layer dirty where we are going to draw the patch
        if ((mSnapshot->flags & Snapshot::kFlagFboTarget) &&
@@ -944,18 +955,35 @@ void OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int
            const size_t count = mesh->quads.size();
            for (size_t i = 0; i < count; i++) {
                Rect bounds = mesh->quads.itemAt(i);
                if (pureTranslate) {
                    const float x = (int) floorf(bounds.left + 0.5f);
                    const float y = (int) floorf(bounds.top + 0.5f);
                    dirtyLayer(x, y, x + bounds.getWidth(), y + bounds.getBottom(),
                            *mSnapshot->transform);
                } else {
                    dirtyLayer(bounds.left, bounds.top, bounds.right, bounds.bottom,
                            *mSnapshot->transform);
                }
            }
        }
#endif

        if (pureTranslate) {
            const float x = (int) floorf(left + mSnapshot->transform->getTranslateX() + 0.5f);
            const float y = (int) floorf(top + mSnapshot->transform->getTranslateY() + 0.5f);

            drawTextureMesh(x, y, x + right - left, y + bottom - top, texture->id, alpha / 255.0f,
                    mode, texture->blend, (GLvoid*) 0, (GLvoid*) gMeshTextureOffset,
                    GL_TRIANGLES, mesh->verticesCount, false, true, mesh->meshBuffer,
                    true, !mesh->hasEmptyQuads);
        } else {
            drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f,
                    mode, texture->blend, (GLvoid*) 0, (GLvoid*) gMeshTextureOffset,
                    GL_TRIANGLES, mesh->verticesCount, false, false, mesh->meshBuffer,
                    true, !mesh->hasEmptyQuads);
        }
    }
}

void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
    // TODO: Should do quickReject for each line
@@ -1087,6 +1115,13 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
            break;
    }

    // TODO: Handle paint->getTextScaleX()
    const bool pureTranslate = mSnapshot->transform->isPureTranslate();
    if (pureTranslate) {
        x = (int) floorf(x + mSnapshot->transform->getTranslateX() + 0.5f);
        y = (int) floorf(y + mSnapshot->transform->getTranslateY() + 0.5f);
    }

    int alpha;
    SkXfermode::Mode mode;
    getAlphaAndMode(paint, &alpha, &mode);
@@ -1110,7 +1145,7 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
                count, mShadowRadius);
        const AutoTexture autoCleanup(shadow);

        setupShadow(shadow, x, y, mode, a);
        setupShadow(shadow, x, y, mode, a, pureTranslate);

        // Draw the mesh
        glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
@@ -1120,14 +1155,17 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
    GLuint textureUnit = 0;
    glActiveTexture(gTextureUnits[textureUnit]);

    // Assume that the modelView matrix does not force scales, rotates, etc.
    const bool linearFilter = mSnapshot->transform->changesBounds();
    // Pick the appropriate texture filtering
    bool linearFilter = mSnapshot->transform->changesBounds();
    if (pureTranslate && !linearFilter) {
        linearFilter = fabs(y - (int) y) > 0.0f || fabs(x - (int) x) > 0.0f;
    }

    // Dimensions are set to (0,0), the layer (if any) won't be dirtied
    setupTextureAlpha8(fontRenderer.getTexture(linearFilter), 0, 0, textureUnit,
            x, y, r, g, b, a, mode, false, true, NULL, NULL);
            x, y, r, g, b, a, mode, false, true, NULL, NULL, 0, pureTranslate);

    const Rect& clip = mSnapshot->getLocalClip();
    const Rect* clip = pureTranslate ? mSnapshot->clipRect : &mSnapshot->getLocalClip();
    Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);

#if RENDER_LAYERS_AS_REGIONS
@@ -1137,11 +1175,13 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
#endif

    mCaches.unbindMeshBuffer();
    if (fontRenderer.renderText(paint, &clip, text, 0, bytesCount, count, x, y,
    if (fontRenderer.renderText(paint, clip, text, 0, bytesCount, count, x, y,
            hasLayer ? &bounds : NULL)) {
#if RENDER_LAYERS_AS_REGIONS
        if (hasLayer) {
            if (!pureTranslate) {
                mSnapshot->transform->mapRect(bounds);
            }
            bounds.intersect(*mSnapshot->clipRect);
            bounds.snapToPixelBoundaries();

@@ -1241,7 +1281,7 @@ void OpenGLRenderer::setupShadow(float radius, float dx, float dy, int color) {
///////////////////////////////////////////////////////////////////////////////

void OpenGLRenderer::setupShadow(const ShadowTexture* texture, float x, float y,
        SkXfermode::Mode mode, float alpha) {
        SkXfermode::Mode mode, float alpha, bool ignoreTransforms) {
    const float sx = x - texture->left + mShadowDx;
    const float sy = y - texture->top + mShadowDy;

@@ -1252,7 +1292,9 @@ void OpenGLRenderer::setupShadow(const ShadowTexture* texture, float x, float y,
    const GLfloat b = a * ((mShadowColor      ) & 0xFF) / 255.0f;

    GLuint textureUnit = 0;
    setupTextureAlpha8(texture, textureUnit, sx, sy, r, g, b, a, mode, true, false);
    setupTextureAlpha8(texture->id, texture->width, texture->height, textureUnit,
            sx, sy, r, g, b, a, mode, true, false,
            (GLvoid*) 0, (GLvoid*) gMeshTextureOffset, 0, ignoreTransforms);
}

void OpenGLRenderer::setupTextureAlpha8(const Texture* texture, GLuint& textureUnit,
@@ -1273,7 +1315,7 @@ void OpenGLRenderer::setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t
void OpenGLRenderer::setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t height,
        GLuint& textureUnit, float x, float y, float r, float g, float b, float a,
        SkXfermode::Mode mode, bool transforms, bool applyFilters,
        GLvoid* vertices, GLvoid* texCoords, GLuint vbo) {
        GLvoid* vertices, GLvoid* texCoords, GLuint vbo, bool ignoreTransform) {
     // Describe the required shaders
     ProgramDescription description;
     description.hasTexture = true;
@@ -1321,9 +1363,14 @@ void OpenGLRenderer::setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t
         mModelView.loadIdentity();
     }

     mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform);
     mat4 t;
     if (!ignoreTransform) {
         t.load(*mSnapshot->transform);
     }

     mCaches.currentProgram->set(mOrthoMatrix, mModelView, t);
     if (width > 0 && height > 0) {
         dirtyLayer(x, y, x + width, y + height, *mSnapshot->transform);
         dirtyLayer(x, y, x + width, y + height, t);
     }

     if (setColor) {
@@ -1334,6 +1381,9 @@ void OpenGLRenderer::setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t
     if (applyFilters) {
         // Setup attributes and uniforms required by the shaders
         if (mShader) {
             if (ignoreTransform) {
                 mModelView.loadInverse(*mSnapshot->transform);
             }
             mShader->setupProgram(mCaches.currentProgram, mModelView, *mSnapshot, &textureUnit);
         }
         if (mColorFilter) {
@@ -1473,7 +1523,11 @@ void OpenGLRenderer::setupColorRect(float left, float top, float right, float bo

    // Setup attributes and uniforms required by the shaders
    if (mShader) {
        if (ignoreMatrix) mModelView.loadIdentity();
        if (ignoreMatrix) {
            mModelView.loadIdentity();
        } else if (ignoreTransform) {
            mModelView.loadInverse(*mSnapshot->transform);
        }
        mShader->setupProgram(mCaches.currentProgram, mModelView, *mSnapshot, &textureUnit);
    }
    if (mColorFilter) {
@@ -1489,10 +1543,19 @@ void OpenGLRenderer::drawTextureRect(float left, float top, float right, float b

    setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);

    if (mSnapshot->transform->isPureTranslate()) {
        const float x = (int) floorf(left + mSnapshot->transform->getTranslateX() + 0.5f);
        const float y = (int) floorf(top + mSnapshot->transform->getTranslateY() + 0.5f);

        drawTextureMesh(x, y, x + texture->width, y + texture->height, texture->id,
                alpha / 255.0f, mode, texture->blend, (GLvoid*) NULL,
                (GLvoid*) gMeshTextureOffset, GL_TRIANGLE_STRIP, gMeshCount, false, true);
    } else {
        drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f, mode,
                texture->blend, (GLvoid*) NULL, (GLvoid*) gMeshTextureOffset,
                GL_TRIANGLE_STRIP, gMeshCount);
    }
}

void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom,
        GLuint texture, float alpha, SkXfermode::Mode mode, bool blend) {
+3 −2
Original line number Diff line number Diff line
@@ -294,9 +294,10 @@ private:
     * @param y The y coordinate of the shadow
     * @param mode The blending mode
     * @param alpha The alpha value
     * @param ignoreTransforms True if the coordinates are already in screen space
     */
    void setupShadow(const ShadowTexture* texture, float x, float y, SkXfermode::Mode mode,
            float alpha);
            float alpha, bool ignoreTransforms = false);

    /**
     * Prepares the renderer to draw the specified Alpha8 texture as a rectangle.
@@ -349,7 +350,7 @@ private:
    void setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t height,
            GLuint& textureUnit, float x, float y, float r, float g, float b, float a,
            SkXfermode::Mode mode, bool transforms, bool applyFilters,
            GLvoid* vertices, GLvoid* texCoords, GLuint vbo = 0);
            GLvoid* vertices, GLvoid* texCoords, GLuint vbo = 0, bool ignoreTransform = false);

    /**
     * Draws text underline and strike-through if needed.