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

Commit 6b6fa162 authored by Xavier Ducrohet's avatar Xavier Ducrohet Committed by Android (Google) Code Review
Browse files

Merge "Layoutlib native delegate: primitive shapes and shaders"

parents 1272b462 251d2e99
Loading
Loading
Loading
Loading
+0 −48
Original line number Diff line number Diff line
/*
 * Copyright (C) 2008 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 android.graphics;

import java.awt.Paint;

public class BitmapShader extends Shader {

    // we hold on just for the GC, since our native counterpart is using it
    private final Bitmap mBitmap;

    /**
     * Call this to create a new shader that will draw with a bitmap.
     *
     * @param bitmap            The bitmap to use inside the shader
     * @param tileX             The tiling mode for x to draw the bitmap in.
     * @param tileY             The tiling mode for y to draw the bitmap in.
     */
    public BitmapShader(Bitmap bitmap, TileMode tileX, TileMode tileY) {
        mBitmap = bitmap;
    }

    //---------- Custom methods

    public Bitmap getBitmap() {
        return mBitmap;
    }

    @Override
    Paint getJavaPaint() {
        return null;
    }
}
+140 −53
Original line number Diff line number Diff line
@@ -431,14 +431,14 @@ public class Canvas_Delegate {
    /*package*/ static boolean native_quickReject(int nativeCanvas,
                                                     RectF rect,
                                                     int native_edgeType) {
        // FIXME
        // FIXME properly implement quickReject
        return false;
    }

    /*package*/ static boolean native_quickReject(int nativeCanvas,
                                                     int path,
                                                     int native_edgeType) {
        // FIXME
        // FIXME properly implement quickReject
        return false;
    }

@@ -446,18 +446,26 @@ public class Canvas_Delegate {
                                                     float left, float top,
                                                     float right, float bottom,
                                                     int native_edgeType) {
        // FIXME
        // FIXME properly implement quickReject
        return false;
    }

    /*package*/ static void native_drawRGB(int nativeCanvas, int r, int g,
                                              int b) {
        // FIXME
        throw new UnsupportedOperationException();
    /*package*/ static void native_drawRGB(int nativeCanvas, int r, int g, int b) {
        native_drawColor(nativeCanvas, 0xFF000000 | r << 16 | (g&0xFF) << 8 | (b&0xFF),
                PorterDuff.Mode.SRC_OVER.nativeInt);

    }

    /*package*/ static void native_drawARGB(int nativeCanvas, int a, int r, int g, int b) {
        native_drawColor(nativeCanvas, a << 24 | (r&0xFF) << 16 | (g&0xFF) << 8 | (b&0xFF),
                PorterDuff.Mode.SRC_OVER.nativeInt);
    }

    /*package*/ static void native_drawARGB(int nativeCanvas, int a, int r,
                                               int g, int b) {
    /*package*/ static void native_drawColor(int nativeCanvas, int color) {
        native_drawColor(nativeCanvas, color, PorterDuff.Mode.SRC_OVER.nativeInt);
    }

    /*package*/ static void native_drawColor(int nativeCanvas, int color, int mode) {
        // get the delegate from the native int.
        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
        if (canvasDelegate == null) {
@@ -472,7 +480,13 @@ public class Canvas_Delegate {
            graphics.setTransform(new AffineTransform());

            // set the color
            graphics.setColor(new Color(r, g, b, a));
            graphics.setColor(new Color(color));

            // set the mode and alpha.
            int alpha = color >>> 24;
            float falpha = alpha / 255.f;

            setModeInGraphics(graphics, mode, falpha);

            graphics.fillRect(0, 0, canvasDelegate.mBufferedImage.getWidth(),
                    canvasDelegate.mBufferedImage.getHeight());
@@ -482,17 +496,6 @@ public class Canvas_Delegate {
        }
    }

    /*package*/ static void native_drawColor(int nativeCanvas, int color) {
        // FIXME
        throw new UnsupportedOperationException();
    }

    /*package*/ static void native_drawColor(int nativeCanvas, int color,
                                                int mode) {
        // FIXME
        throw new UnsupportedOperationException();
    }

    /*package*/ static void native_drawPaint(int nativeCanvas, int paint) {
        // FIXME
        throw new UnsupportedOperationException();
@@ -501,14 +504,32 @@ public class Canvas_Delegate {
    /*package*/ static void native_drawLine(int nativeCanvas, float startX,
                                               float startY, float stopX,
                                               float stopY, int paint) {
        // FIXME
        throw new UnsupportedOperationException();
        // get the delegate from the native int.
        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
        if (canvasDelegate == null) {
            assert false;
            return;
        }

        // get the delegate from the native int.
        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(paint);
        if (paintDelegate == null) {
            assert false;
            return;
        }

        // get a Graphics2D object configured with the drawing parameters.
        Graphics2D g = canvasDelegate.getCustomGraphics(paintDelegate);

        g.drawLine((int)startX, (int)startY, (int)stopX, (int)stopY);

        // dispose Graphics2D object
        g.dispose();
    }

    /*package*/ static void native_drawRect(int nativeCanvas, RectF rect,
                                               int paint) {
        // FIXME
        throw new UnsupportedOperationException();
        native_drawRect(nativeCanvas, rect.left, rect.top, rect.right, rect.bottom, paint);
    }

    /*package*/ static void native_drawRect(int nativeCanvas, float left,
@@ -548,20 +569,52 @@ public class Canvas_Delegate {
            // dispose Graphics2D object
            g.dispose();
        }

    }

    /*package*/ static void native_drawOval(int nativeCanvas, RectF oval,
                                               int paint) {
        // FIXME
        throw new UnsupportedOperationException();
        // get the delegate from the native int.
        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
        if (canvasDelegate == null) {
            assert false;
            return;
        }

        // get the delegate from the native int.
        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(paint);
        if (paintDelegate == null) {
            assert false;
            return;
        }

        if (oval.right > oval.left && oval.bottom > oval.top) {
            // get a Graphics2D object configured with the drawing parameters.
            Graphics2D g = canvasDelegate.getCustomGraphics(paintDelegate);

            int style = paintDelegate.getStyle();

            // draw
            if (style == Paint.Style.FILL.nativeInt ||
                    style == Paint.Style.FILL_AND_STROKE.nativeInt) {
                g.fillOval((int)oval.left, (int)oval.top, (int)oval.width(), (int)oval.height());
            }

            if (style == Paint.Style.STROKE.nativeInt ||
                    style == Paint.Style.FILL_AND_STROKE.nativeInt) {
                g.drawOval((int)oval.left, (int)oval.top, (int)oval.width(), (int)oval.height());
            }

            // dispose Graphics2D object
            g.dispose();
        }
    }

    /*package*/ static void native_drawCircle(int nativeCanvas, float cx,
                                                 float cy, float radius,
                                                 int paint) {
        // FIXME
        throw new UnsupportedOperationException();
        native_drawOval(nativeCanvas,
                new RectF(cx - radius, cy - radius, radius*2, radius*2),
                paint);
    }

    /*package*/ static void native_drawArc(int nativeCanvas, RectF oval,
@@ -574,8 +627,44 @@ public class Canvas_Delegate {
    /*package*/ static void native_drawRoundRect(int nativeCanvas,
                                                    RectF rect, float rx,
                                                    float ry, int paint) {
        // FIXME
        throw new UnsupportedOperationException();
        // get the delegate from the native int.
        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
        if (canvasDelegate == null) {
            assert false;
            return;
        }

        // get the delegate from the native int.
        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(paint);
        if (paintDelegate == null) {
            assert false;
            return;
        }

        if (rect.right > rect.left && rect.bottom > rect.top) {
            // get a Graphics2D object configured with the drawing parameters.
            Graphics2D g = canvasDelegate.getCustomGraphics(paintDelegate);

            int style = paintDelegate.getStyle();

            // draw
            if (style == Paint.Style.FILL.nativeInt ||
                    style == Paint.Style.FILL_AND_STROKE.nativeInt) {
                g.fillRoundRect(
                        (int)rect.left, (int)rect.top, (int)rect.width(), (int)rect.height(),
                        (int)rx, (int)ry);
            }

            if (style == Paint.Style.STROKE.nativeInt ||
                    style == Paint.Style.FILL_AND_STROKE.nativeInt) {
                g.drawRoundRect(
                        (int)rect.left, (int)rect.top, (int)rect.width(), (int)rect.height(),
                        (int)rx, (int)ry);
            }

            // dispose Graphics2D object
            g.dispose();
        }
    }

    /*package*/ static void native_drawPath(int nativeCanvas, int path,
@@ -675,7 +764,6 @@ public class Canvas_Delegate {
        throw new UnsupportedOperationException();
    }


    /*package*/ static void native_drawText(int nativeCanvas, char[] text,
                                               int index, int count, float x,
                                               float y, int flags, int paint) {
@@ -696,21 +784,8 @@ public class Canvas_Delegate {
            return;
        }

        Graphics2D g = (Graphics2D) canvasDelegate.getGraphics2d().create();
        Graphics2D g = (Graphics2D) canvasDelegate.getCustomGraphics(paintDelegate);
        try {
            if (paintDelegate.isAntiAliased()) {
                g.setRenderingHint(
                        RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            }

            // set the color. because this only handles RGB, the alpha channel is handled
            // as a composite.
            g.setColor(new Color(paintDelegate.getColor()));
            int alpha = paintDelegate.getAlpha();
            float falpha = alpha / 255.f;

            setModeInGraphics(g, PorterDuff.Mode.SRC_OVER, falpha);

            // Paint.TextAlign indicates how the text is positioned relative to X.
            // LEFT is the default and there's nothing to do.
            if (paintDelegate.getTextAlign() != Paint.Align.LEFT.nativeInt) {
@@ -898,6 +973,8 @@ public class Canvas_Delegate {
        if (paint.isAntiAliased()) {
            g.setRenderingHint(
                    RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g.setRenderingHint(
                    RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        }

        // configure it
@@ -941,24 +1018,34 @@ public class Canvas_Delegate {
            }
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha));
        }

        Shader shader = paint.getShader();
        if (shader != null) {
            java.awt.Paint shaderPaint = shader.getJavaPaint();
*/
        int nativeShader = paint.getShader();
        Shader_Delegate shaderDelegate = Shader_Delegate.getDelegate(nativeShader);
        if (shaderDelegate != null) {
            java.awt.Paint shaderPaint = shaderDelegate.getJavaPaint();
            if (shaderPaint != null) {
                g.setPaint(shaderPaint);
            } else {
                if (mLogger != null) {
                    mLogger.warning(String.format(
                            "Shader '%1$s' is not supported in the Layout Editor.",
                            shader.getClass().getCanonicalName()));
                            shaderDelegate.getClass().getCanonicalName()));
                }
            }
        }
*/

        return g;
    }

    private static void setModeInGraphics(Graphics2D g, int mode, float falpha) {
        for (PorterDuff.Mode m : PorterDuff.Mode.values()) {
            if (m.nativeInt == mode) {
                setModeInGraphics(g, m, falpha);
                return;
            }
        }
    }

    private static void setModeInGraphics(Graphics2D g, PorterDuff.Mode mode, float falpha) {
        switch (mode) {
            case CLEAR:
+0 −53
Original line number Diff line number Diff line
/*
 * Copyright (C) 2008 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 android.graphics;

import java.awt.Paint;

/** A subclass of shader that returns the composition of two other shaders, combined by
    an {@link android.graphics.Xfermode} subclass.
*/
public class ComposeShader extends Shader {
    /** Create a new compose shader, given shaders A, B, and a combining mode.
        When the mode is applied, it will be given the result from shader A as its
        "dst", and the result of from shader B as its "src".
        @param shaderA  The colors from this shader are seen as the "dst" by the mode
        @param shaderB  The colors from this shader are seen as the "src" by the mode
        @param mode     The mode that combines the colors from the two shaders. If mode
                        is null, then SRC_OVER is assumed.
    */
    public ComposeShader(Shader shaderA, Shader shaderB, Xfermode mode) {
        // FIXME Implement shader
    }

    /** Create a new compose shader, given shaders A, B, and a combining PorterDuff mode.
        When the mode is applied, it will be given the result from shader A as its
        "dst", and the result of from shader B as its "src".
        @param shaderA  The colors from this shader are seen as the "dst" by the mode
        @param shaderB  The colors from this shader are seen as the "src" by the mode
        @param mode     The PorterDuff mode that combines the colors from the two shaders.
    */
    public ComposeShader(Shader shaderA, Shader shaderB, PorterDuff.Mode mode) {
        // FIXME Implement shader
    }

    @Override
    Paint getJavaPaint() {
        return null;
    }
}
+4 −13
Original line number Diff line number Diff line
@@ -16,19 +16,12 @@

package android.graphics;

import android.graphics.Shader.TileMode;

/**
 * Base class for Gradient shader. This is not a standard android class and is just used
 * as a base class for the re-implemented gradient classes.
 *
 * It also provides a base class to handle common code between the different shaders'
 * implementations of {@link java.awt.Paint}.
 *
 * @see LinearGradient
 * @see RadialGradient
 * @see SweepGradient
 * Base class for true Gradient shader delegate.
 */
public abstract class GradientShader extends Shader {
public abstract class Gradient_Delegate extends Shader_Delegate {

    protected final int[] mColors;
    protected final float[] mPositions;
@@ -41,7 +34,7 @@ public abstract class GradientShader extends Shader {
     *            corresponding color in the colors array. If this is null, the
     *            the colors are distributed evenly along the gradient line.
     */
    protected GradientShader(int colors[], float positions[]) {
    protected Gradient_Delegate(int colors[], float positions[]) {
        if (colors.length < 2) {
            throw new IllegalArgumentException("needs >= 2 number of colors");
        }
@@ -199,7 +192,5 @@ public abstract class GradientShader extends Shader {
        private int computeChannel(int c1, int c2, float percent) {
            return c1 + (int)((percent * (c2-c1)) + .5);
        }


    }
}
+76 −28
Original line number Diff line number Diff line
/*
 * Copyright (C) 2008 The Android Open Source Project
 * 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.
@@ -16,10 +16,80 @@

package android.graphics;

public class LinearGradient extends GradientShader {
import com.android.layoutlib.bridge.DelegateManager;

import android.graphics.Shader.TileMode;

import java.awt.Paint;

/**
 * Delegate implementing the native methods of android.graphics.LinearGradient
 *
 * Through the layoutlib_create tool, the original native methods of LinearGradient have been
 * replaced by calls to methods of the same name in this delegate class.
 *
 * This class behaves like the original native implementation, but in Java, keeping previously
 * native data into its own objects and mapping them to int that are sent back and forth between
 * it and the original LinearGradient class.
 *
 * Because this extends {@link Shader_Delegate}, there's no need to use a {@link DelegateManager},
 * as all the Shader classes will be added to the manager owned by {@link Shader_Delegate}.
 *
 * @see Shader_Delegate
 *
 */
public class LinearGradient_Delegate extends Gradient_Delegate {

    // ---- delegate data ----
    private java.awt.Paint mJavaPaint;

    // ---- Public Helper methods ----

    @Override
    public Paint getJavaPaint() {
        return mJavaPaint;
    }

    // ---- native methods ----

    /*package*/ static int nativeCreate1(LinearGradient thisGradient,
            float x0, float y0, float x1, float y1,
            int colors[], float positions[], int tileMode) {
        // figure out the tile
        TileMode tile = null;
        for (TileMode tm : TileMode.values()) {
            if (tm.nativeInt == tileMode) {
                tile = tm;
                break;
            }
        }

        LinearGradient_Delegate newDelegate = new LinearGradient_Delegate(x0, y0, x1, y1,
                colors, positions, tile);
        return sManager.addDelegate(newDelegate);
    }
    /*package*/ static int nativeCreate2(LinearGradient thisGradient,
            float x0, float y0, float x1, float y1,
            int color0, int color1, int tileMode) {
        return nativeCreate1(thisGradient,
                x0, y0, x1, y1, new int[] { color0, color1}, null /*positions*/,
                tileMode);
    }
    /*package*/ static int nativePostCreate1(LinearGradient thisGradient,
            int native_shader, float x0, float y0, float x1, float y1,
            int colors[], float positions[], int tileMode) {
        // nothing to be done here.
        return 0;
    }
    /*package*/ static int nativePostCreate2(LinearGradient thisGradient,
            int native_shader, float x0, float y0, float x1, float y1,
            int color0, int color1, int tileMode) {
        // nothing to be done here.
        return 0;
    }

    // ---- Private delegate/helper methods ----

    /**
     * Create a shader that draws a linear gradient along a line.
     *
@@ -33,35 +103,13 @@ public class LinearGradient extends GradientShader {
     *            the colors are distributed evenly along the gradient line.
     * @param tile The Shader tiling mode
     */
    public LinearGradient(float x0, float y0, float x1, float y1, int colors[], float positions[],
            TileMode tile) {
    private LinearGradient_Delegate(float x0, float y0, float x1, float y1,
            int colors[], float positions[], TileMode tile) {
        super(colors, positions);
        mJavaPaint = new LinearGradientPaint(x0, y0, x1, y1, mColors, mPositions, tile);
    }

    /**
     * Create a shader that draws a linear gradient along a line.
     *
     * @param x0 The x-coordinate for the start of the gradient line
     * @param y0 The y-coordinate for the start of the gradient line
     * @param x1 The x-coordinate for the end of the gradient line
     * @param y1 The y-coordinate for the end of the gradient line
     * @param color0 The color at the start of the gradient line.
     * @param color1 The color at the end of the gradient line.
     * @param tile The Shader tiling mode
     */
    public LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1,
            TileMode tile) {
        this(x0, y0, x1, y1, new int[] { color0, color1}, null /*positions*/, tile);
    }

    // ---------- Custom Methods

    @Override
    java.awt.Paint getJavaPaint() {
        return mJavaPaint;
    }

    // ---- Custom Java Paint ----
    /**
     * Linear Gradient (Java) Paint able to handle more than 2 points, as
     * {@link java.awt.GradientPaint} only supports 2 points and does not support Android's tile
@@ -101,7 +149,7 @@ public class LinearGradient extends GradientShader {

            public LinearGradientPaintContext(java.awt.image.ColorModel colorModel) {
                mColorModel = colorModel;
                // FIXME: so far all this is always the same rect gotten in getRaster with an indentity matrix?
                // FIXME: so far all this is always the same rect gotten in getRaster with an identity matrix?
            }

            public void dispose() {
Loading