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

Commit 674b595f authored by Chet Haase's avatar Chet Haase Committed by Android (Google) Code Review
Browse files

Merge "Antialiasing for rectangles"

parents 1f5e3a1a 858aa93d
Loading
Loading
Loading
Loading
+78 −1
Original line number Diff line number Diff line
@@ -1457,6 +1457,79 @@ void OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int
    }
}

/**
 * This function uses a similar approach to that of AA lines in the drawLines() function.
 * We expand the rectangle by a half pixel in screen space on all sides, and use a fragment
 * shader to compute the translucency of the color, determined by whether a given pixel is
 * within that boundary region and how far into the region it is.
 */
void OpenGLRenderer::drawAARect(float left, float top, float right, float bottom,
        int color, SkXfermode::Mode mode)
{
    float inverseScaleX = 1.0f;
    float inverseScaleY = 1.0f;
    // The quad that we use needs to account for scaling.
    if (!mSnapshot->transform->isPureTranslate()) {
        Matrix4 *mat = mSnapshot->transform;
        float m00 = mat->data[Matrix4::kScaleX];
        float m01 = mat->data[Matrix4::kSkewY];
        float m02 = mat->data[2];
        float m10 = mat->data[Matrix4::kSkewX];
        float m11 = mat->data[Matrix4::kScaleX];
        float m12 = mat->data[6];
        float scaleX = sqrt(m00 * m00 + m01 * m01);
        float scaleY = sqrt(m10 * m10 + m11 * m11);
        inverseScaleX = (scaleX != 0) ? (inverseScaleX / scaleX) : 0;
        inverseScaleY = (scaleY != 0) ? (inverseScaleY / scaleY) : 0;
    }

    setupDraw();
    setupDrawAALine();
    setupDrawColor(color);
    setupDrawColorFilter();
    setupDrawShader();
    setupDrawBlending(true, mode);
    setupDrawProgram();
    setupDrawModelViewIdentity(true);
    setupDrawColorUniforms();
    setupDrawColorFilterUniforms();
    setupDrawShaderIdentityUniforms();

    AAVertex rects[4];
    AAVertex* aaVertices = &rects[0];
    void* widthCoords = ((GLbyte*) aaVertices) + gVertexAAWidthOffset;
    void* lengthCoords = ((GLbyte*) aaVertices) + gVertexAALengthOffset;

    float boundarySizeX = .5 * inverseScaleX;
    float boundarySizeY = .5 * inverseScaleY;

    // Adjust the rect by the AA boundary padding
    left -= boundarySizeX;
    right += boundarySizeX;
    top -= boundarySizeY;
    bottom += boundarySizeY;

    float width = right - left;
    float height = bottom - top;

    float boundaryWidthProportion = (width != 0) ? (2 * boundarySizeX) / width : 0;
    float boundaryHeightProportion = (height != 0) ? (2 * boundarySizeY) / height : 0;
    setupDrawAALine((void*) aaVertices, widthCoords, lengthCoords, boundaryWidthProportion);
    int boundaryLengthSlot = mCaches.currentProgram->getUniform("boundaryLength");
    int inverseBoundaryLengthSlot = mCaches.currentProgram->getUniform("inverseBoundaryLength");
    glUniform1f(boundaryLengthSlot, boundaryHeightProportion);
    glUniform1f(inverseBoundaryLengthSlot, (1 / boundaryHeightProportion));

    if (!quickReject(left, top, right, bottom)) {
        AAVertex::set(aaVertices++, left, bottom, 1, 1);
        AAVertex::set(aaVertices++, left, top, 1, 0);
        AAVertex::set(aaVertices++, right, bottom, 0, 1);
        AAVertex::set(aaVertices++, right, top, 0, 0);
        dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    }
}

/**
 * We draw lines as quads (tristrips). Using GL_LINES can be difficult because the rasterization
 * rules for those lines produces some unexpected results, and may vary between hardware devices.
@@ -1848,8 +1921,12 @@ void OpenGLRenderer::drawRect(float left, float top, float right, float bottom,
    }

    int color = p->getColor();
    if (p->isAntiAlias()) {
        drawAARect(left, top, right, bottom, color, mode);
    } else {
        drawColorRect(left, top, right, bottom, color, mode);
    }
}

void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
        float x, float y, SkPaint* paint) {
+3 −0
Original line number Diff line number Diff line
@@ -285,6 +285,9 @@ private:

    void drawAlphaBitmap(Texture* texture, float left, float top, SkPaint* paint);

    void drawAARect(float left, float top, float right, float bottom,
            int color, SkXfermode::Mode mode);

    /**
     * Draws a textured rectangle with the specified texture. The specified coordinates
     * are transformed by the current snapshot's transform matrix.
+9 −0
Original line number Diff line number Diff line
@@ -92,6 +92,15 @@
            </intent-filter>
        </activity>
        
        <activity
                android:name="ColoredRectsActivity"
                android:label="_Rects">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity
                android:name="SimplePatchActivity"
                android:label="_SimplePatch"
+124 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 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.
 */

package com.android.test.hwui;

import android.animation.ObjectAnimator;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.view.View;
import android.widget.FrameLayout;

@SuppressWarnings({"UnusedDeclaration"})
public class ColoredRectsActivity extends Activity {
    private ObjectAnimator mAnimator;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().setBackgroundDrawable(new ColorDrawable(0xff000000));
        FrameLayout frame = new FrameLayout(this);
        final RectsView gpuView = new RectsView(this, 0, Color.GREEN);
        frame.addView(gpuView);
        final RectsView swView = new RectsView(this, 400, Color.RED);
        swView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        frame.addView(swView);
        final RectsView hwBothView = new RectsView(this, 850, Color.GREEN);
        // Don't actually need to render to a hw layer, but it's a good sanity-check that
        // we're rendering to/from layers correctly
        hwBothView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
        frame.addView(hwBothView);
        final RectsView swBothView = new RectsView(this, 854, Color.RED);
        swBothView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        frame.addView(swBothView);
        setContentView(frame);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    public static class RectsView extends View {

        private float mOffset;
        private int mColor;

        public RectsView(Context c, float offset, int color) {
            super(c);
            mOffset = offset;
            mColor = color;
        }

        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            Paint p = new Paint();
            p.setColor(mColor);
            float yOffset = 10;

            for (int i = 0; i < 2; ++i) {
                canvas.save();
                canvas.translate(mOffset, yOffset);
                canvas.drawRect(0, 0, 20, 10, p);
                canvas.drawRect(35, 0, 45, 20, p);
                canvas.translate(0, -yOffset);
                canvas.scale(2, 2);
                canvas.translate(60, yOffset/2);
                canvas.drawRect(0, 0, 20, 10, p);
                canvas.translate(15, 0);
                canvas.drawRect(35, 0, 45, 20, p);
                canvas.restore();

                yOffset += 100;

                canvas.save();
                canvas.save();
                canvas.translate(mOffset + 10, yOffset);
                canvas.rotate(45);
                canvas.drawRect(0, 0, 20, 10, p);
                canvas.restore();
                canvas.save();
                canvas.translate(mOffset + 70, yOffset);
                canvas.rotate(5);
                canvas.drawRect(0, 0, 20, 10, p);
                canvas.restore();
                canvas.save();
                canvas.translate(mOffset + 140, yOffset);
                canvas.scale(2, 2);
                canvas.rotate(5);
                canvas.drawRect(0, 0, 20, 10, p);
                canvas.restore();
                canvas.save();
                canvas.translate(mOffset + 210, yOffset);
                canvas.scale(2, 2);
                canvas.rotate(45);
                canvas.drawRect(0, 0, 20, 10, p);
                canvas.restore();
                canvas.restore();

                yOffset += 100;

                p.setAntiAlias(true);
            }
        }
    }
}