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

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

Merge "Add support for drawLines(), with anti-aliasing"

parents ca6fd847 759ea80d
Loading
Loading
Loading
Loading
+10 −3
Original line number Diff line number Diff line
@@ -537,17 +537,24 @@ class GLES20Canvas extends Canvas {
        mLine[1] = startY;
        mLine[2] = stopX;
        mLine[3] = stopY;
        drawLines(mLine, 0, 1, paint);
        drawLines(mLine, 0, 4, paint);
    }

    @Override
    public void drawLines(float[] pts, int offset, int count, Paint paint) {
        // TODO: Implement
        if ((offset | count) < 0 || offset + count > pts.length) {
            throw new IllegalArgumentException("The lines array must contain 4 elements per line.");
        }
        boolean hasModifier = setupModifiers(paint);
        nDrawLines(mRenderer, pts, offset, count, paint.mNativePaint);
        if (hasModifier) nResetModifiers(mRenderer);
    }

    private native void nDrawLines(int renderer, float[] points, int offset, int count, int paint);

    @Override
    public void drawLines(float[] pts, Paint paint) {
        drawLines(pts, 0, pts.length / 4, paint);
        drawLines(pts, 0, pts.length, paint);
    }

    @Override
+10 −0
Original line number Diff line number Diff line
@@ -265,6 +265,15 @@ static void android_view_GLES20Canvas_drawPath(JNIEnv* env, jobject canvas,
    renderer->drawPath(path, paint);
}

static void android_view_GLES20Canvas_drawLines(JNIEnv* env, jobject canvas,
        OpenGLRenderer* renderer, jfloatArray points, jint offset, jint count, SkPaint* paint) {
    jfloat* storage = env->GetFloatArrayElements(points, NULL);

    renderer->drawLines(storage + offset, count, paint);

    env->ReleaseFloatArrayElements(points, storage, 0);
}

// ----------------------------------------------------------------------------
// Shaders and color filters
// ----------------------------------------------------------------------------
@@ -421,6 +430,7 @@ static JNINativeMethod gMethods[] = {
    { "nDrawRect",          "(IFFFFI)V",       (void*) android_view_GLES20Canvas_drawRect },
    { "nDrawRects",         "(III)V",          (void*) android_view_GLES20Canvas_drawRects },
    { "nDrawPath",          "(III)V",          (void*) android_view_GLES20Canvas_drawPath },
    { "nDrawLines",         "(I[FIII)V",       (void*) android_view_GLES20Canvas_drawLines },

    { "nResetModifiers",    "(I)V",            (void*) android_view_GLES20Canvas_resetModifiers },
    { "nSetupShader",       "(II)V",           (void*) android_view_GLES20Canvas_setupShader },

libs/hwui/Line.h

0 → 100644
+126 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_UI_LINE_H
#define ANDROID_UI_LINE_H

#include <GLES2/gl2.h>

#include <cmath>

#include <sys/types.h>

#include "Patch.h"

namespace android {
namespace uirenderer {

///////////////////////////////////////////////////////////////////////////////
// Globals
///////////////////////////////////////////////////////////////////////////////

// Alpha8 texture used to perform texture anti-aliasing
static const uint8_t gLineTexture[] = {
        0,   0,   0,   0, 0,
        0, 255, 255, 255, 0,
        0, 255, 255, 255, 0,
        0, 255, 255, 255, 0,
        0,   0,   0,   0, 0
};
static const GLsizei gLineTextureWidth = 5;
static const GLsizei gLineTextureHeight = 5;
static const float gLineAABias = 1.0f;

///////////////////////////////////////////////////////////////////////////////
// Line
///////////////////////////////////////////////////////////////////////////////

class Line {
public:
    Line(): mXDivsCount(2), mYDivsCount(2) {
        mPatch = new Patch(mXDivsCount, mYDivsCount);
        mXDivs = new int32_t[mXDivsCount];
        mYDivs = new int32_t[mYDivsCount];

        mXDivs[0] = mYDivs[0] = 2;
        mXDivs[1] = mYDivs[1] = 3;

        glGenTextures(1, &mTexture);
        glBindTexture(GL_TEXTURE_2D, mTexture);

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, gLineTextureWidth, gLineTextureHeight, 0,
                GL_ALPHA, GL_UNSIGNED_BYTE, gLineTexture);
    }

    ~Line() {
        delete mPatch;
        delete mXDivs;
        delete mYDivs;

        glDeleteTextures(1, &mTexture);
    }

    void update(float x1, float y1, float x2, float y2, float lineWidth, float& tx, float& ty) {
        const float length = sqrtf((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
        const float half = lineWidth * 0.5f;

        mPatch->updateVertices(gLineTextureWidth, gLineTextureHeight,
                -gLineAABias, -half - gLineAABias, length + gLineAABias, half + gLineAABias,
                mXDivs, mYDivs, mXDivsCount, mYDivsCount);

        tx = -gLineAABias;
        ty = -half - gLineAABias;
    }

    inline GLvoid* getVertices() const {
        return &mPatch->vertices[0].position[0];
    }

    inline GLvoid* getTexCoords() const {
        return &mPatch->vertices[0].texture[0];
    }

    inline GLsizei getElementsCount() const {
        return mPatch->verticesCount;
    }

    inline GLuint getTexture() const {
        return mTexture;
    }

private:
    uint32_t mXDivsCount;
    uint32_t mYDivsCount;

    int32_t* mXDivs;
    int32_t* mYDivs;

    Patch* mPatch;

    GLuint mTexture;
}; // class Line

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

#endif // ANDROID_UI_LINE_H
+61 −4
Original line number Diff line number Diff line
@@ -39,6 +39,9 @@ namespace uirenderer {
// Generates simple and textured vertices
#define FV(x, y, u, v) { { x, y }, { u, v } }

#define RAD_TO_DEG (180.0f / 3.14159265f)
#define MIN_ANGLE 0.001f

///////////////////////////////////////////////////////////////////////////////
// Globals
///////////////////////////////////////////////////////////////////////////////
@@ -588,7 +591,7 @@ void OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,
    getAlphaAndMode(paint, &alpha, &mode);

    Patch* mesh = mCaches.patchCache.get(patch);
    mesh->updateVertices(bitmap, left, top, right, bottom,
    mesh->updateVertices(bitmap->width(), bitmap->height(),left, top, right, bottom,
            &patch->xDivs[0], &patch->yDivs[0], patch->numXDivs, patch->numYDivs);

    // Specify right and bottom as +1.0f from left/top to prevent scaling since the
@@ -598,6 +601,50 @@ void OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,
            &mesh->vertices[0].texture[0], GL_TRIANGLES, mesh->verticesCount);
}

void OpenGLRenderer::drawLines(float* points, int count, const SkPaint* paint) {
    int alpha;
    SkXfermode::Mode mode;
    getAlphaAndMode(paint, &alpha, &mode);

    uint32_t color = paint->getColor();
    const GLfloat a = alpha / 255.0f;
    const GLfloat r = a * ((color >> 16) & 0xFF) / 255.0f;
    const GLfloat g = a * ((color >>  8) & 0xFF) / 255.0f;
    const GLfloat b = a * ((color      ) & 0xFF) / 255.0f;

    GLuint textureUnit = 0;
    setupTextureAlpha8(mLine.getTexture(), 0, 0, textureUnit, 0.0f, 0.0f, r, g, b, a,
            mode, false, true, mLine.getVertices(), mLine.getTexCoords());

    for (int i = 0; i < count; i += 4) {
        float tx = 0.0f;
        float ty = 0.0f;

        mLine.update(points[i], points[i + 1], points[i + 2], points[i + 3],
                paint->getStrokeWidth(), tx, ty);

        const float dx = points[i + 2] - points[i];
        const float dy = points[i + 3] - points[i + 1];
        const float mag = sqrtf(dx * dx + dy * dy);
        const float angle = acos(dx / mag);

        mModelView.loadTranslate(points[i], points[i + 1], 0.0f);
        if (angle > MIN_ANGLE || angle < -MIN_ANGLE) {
            mModelView.rotate(angle * RAD_TO_DEG, 0.0f, 0.0f, 1.0f);
        }
        mModelView.translate(tx, ty, 0.0f);
        mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform);

        if (mShader) {
            mShader->updateTransforms(mCaches.currentProgram, mModelView, *mSnapshot);
        }

        glDrawArrays(GL_TRIANGLES, 0, mLine.getElementsCount());
    }

    glDisableVertexAttribArray(mCaches.currentProgram->getAttrib("texCoords"));
}

void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
    const Rect& clip = *mSnapshot->clipRect;
    drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode, true);
@@ -793,12 +840,22 @@ void OpenGLRenderer::setupTextureAlpha8(const Texture* texture, GLuint& textureU
        float x, float y, float r, float g, float b, float a, SkXfermode::Mode mode,
        bool transforms, bool applyFilters) {
    setupTextureAlpha8(texture->id, texture->width, texture->height, textureUnit,
            x, y, r, g, b, a, mode, transforms, applyFilters);
            x, y, r, g, b, a, mode, transforms, applyFilters,
            &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0]);
}

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) {
    setupTextureAlpha8(texture, width, height, textureUnit,
            x, y, r, g, b, a, mode, transforms, applyFilters,
            &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0]);
}

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) {
     // Describe the required shaders
     ProgramDescription description;
     description.hasTexture = true;
@@ -827,9 +884,9 @@ void OpenGLRenderer::setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t

     // Setup attributes
     glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
             gMeshStride, &mMeshVertices[0].position[0]);
             gMeshStride, vertices);
     glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE,
             gMeshStride, &mMeshVertices[0].texture[0]);
             gMeshStride, texCoords);

     // Setup uniforms
     if (transforms) {
+15 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
#include "SkiaShader.h"
#include "SkiaColorFilter.h"
#include "Caches.h"
#include "Line.h"

namespace android {
namespace uirenderer {
@@ -99,6 +100,7 @@ public:
    void drawColor(int color, SkXfermode::Mode mode);
    void drawRect(float left, float top, float right, float bottom, const SkPaint* paint);
    void drawPath(SkPath* path, SkPaint* paint);
    void drawLines(float* points, int count, const SkPaint* paint);

    void resetShader();
    void setupShader(SkiaShader* shader);
@@ -296,6 +298,15 @@ private:
            GLuint& textureUnit, float x, float y, float r, float g, float b, float a,
            SkXfermode::Mode mode, bool transforms, bool applyFilters);

    /**
     * Same as above setupTextureAlpha8() but specifies the mesh's vertices
     * and texCoords pointers.
     */
    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);

    /**
     * Draws text underline and strike-through if needed.
     *
@@ -403,6 +414,10 @@ private:
    // List of rectangles to clear due to calls to saveLayer()
    Vector<Rect*> mLayers;

    // Single object used to draw lines
    Line mLine;

    // Misc
    GLint mMaxTextureSize;

}; // class OpenGLRenderer
Loading