alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Android example source code file (Canvas.java)

This example Android source code file (Canvas.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Android by Example" TM.

Java - Android tags/keywords

affinetransform, android, awt, bufferedimage, canvas, drawing, edgetype, forbidden, graphics, graphics2d, layout, override, paint, parent, rect, style, to, ui, unsupportedoperationexception, util

The Canvas.java Android example source code

/*
 * 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 com.android.layoutlib.api.ILayoutLog;

import android.graphics.DrawFilter;
import android.graphics.Picture;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.Xfermode;
import android.graphics.Paint.Align;
import android.graphics.Paint.FontInfo;
import android.graphics.Paint.Style;
import android.graphics.Region.Op;

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.util.List;
import java.util.Stack;

import javax.microedition.khronos.opengles.GL;

/**
 * Re-implementation of the Canvas, 100% in java on top of a BufferedImage.
 */
public class Canvas extends _Original_Canvas {

    private BufferedImage mBufferedImage;
    private final Stack<Graphics2D> mGraphicsStack = new Stack();
    private final ILayoutLog mLogger;

    public Canvas() {
        mLogger = null;
        // the mBufferedImage will be taken from a bitmap in #setBitmap()
    }

    public Canvas(Bitmap bitmap) {
        mLogger = null;
        mBufferedImage = bitmap.getImage();
        mGraphicsStack.push(mBufferedImage.createGraphics());
    }

    public Canvas(int nativeCanvas) {
        mLogger = null;
        throw new UnsupportedOperationException("Can't create Canvas(int)");
    }

    public Canvas(javax.microedition.khronos.opengles.GL gl) {
        mLogger = null;
        throw new UnsupportedOperationException("Can't create Canvas(javax.microedition.khronos.opengles.GL)");
    }

    // custom constructors for our use.
    public Canvas(int width, int height, ILayoutLog logger) {
        mLogger = logger;
        mBufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        mGraphicsStack.push(mBufferedImage.createGraphics());
    }

    public Canvas(int width, int height) {
        this(width, height, null /* logger*/);
    }

    // custom mehtods
    public BufferedImage getImage() {
        return mBufferedImage;
    }

    public Graphics2D getGraphics2d() {
        return mGraphicsStack.peek();
    }

    public void dispose() {
        while (mGraphicsStack.size() > 0) {
            mGraphicsStack.pop().dispose();
        }
    }

    /**
     * Creates a new {@link Graphics2D} based on the {@link Paint} parameters.
     * <p/>The object must be disposed ({@link Graphics2D#dispose()}) after being used.
     */
    private Graphics2D getCustomGraphics(Paint paint) {
        // make new one
        Graphics2D g = getGraphics2d();
        g = (Graphics2D)g.create();

        // configure it
        g.setColor(new Color(paint.getColor()));
        int alpha = paint.getAlpha();
        float falpha = alpha / 255.f;

        Style style = paint.getStyle();
        if (style == Style.STROKE || style == Style.FILL_AND_STROKE) {
            PathEffect e = paint.getPathEffect();
            if (e instanceof DashPathEffect) {
                DashPathEffect dpe = (DashPathEffect)e;
                g.setStroke(new BasicStroke(
                        paint.getStrokeWidth(),
                        paint.getStrokeCap().getJavaCap(),
                        paint.getStrokeJoin().getJavaJoin(),
                        paint.getStrokeMiter(),
                        dpe.getIntervals(),
                        dpe.getPhase()));
            } else {
                g.setStroke(new BasicStroke(
                        paint.getStrokeWidth(),
                        paint.getStrokeCap().getJavaCap(),
                        paint.getStrokeJoin().getJavaJoin(),
                        paint.getStrokeMiter()));
            }
        }

        Xfermode xfermode = paint.getXfermode();
        if (xfermode instanceof PorterDuffXfermode) {
            PorterDuff.Mode mode = ((PorterDuffXfermode)xfermode).getMode();

            setModeInGraphics(mode, g, falpha);
        } else {
            if (mLogger != null && xfermode != null) {
                mLogger.warning(String.format(
                        "Xfermode '%1$s' is not supported in the Layout Editor.",
                        xfermode.getClass().getCanonicalName()));
            }
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha));
        }

        Shader shader = paint.getShader();
        if (shader != null) {
            java.awt.Paint shaderPaint = shader.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()));
                }
            }
        }

        return g;
    }

    private void setModeInGraphics(PorterDuff.Mode mode, Graphics2D g, float falpha) {
        switch (mode) {
            case CLEAR:
                g.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, falpha));
                break;
            case DARKEN:
                break;
            case DST:
                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST, falpha));
                break;
            case DST_ATOP:
                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_ATOP, falpha));
                break;
            case DST_IN:
                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_IN, falpha));
                break;
            case DST_OUT:
                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OUT, falpha));
                break;
            case DST_OVER:
                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OVER, falpha));
                break;
            case LIGHTEN:
                break;
            case MULTIPLY:
                break;
            case SCREEN:
                break;
            case SRC:
                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, falpha));
                break;
            case SRC_ATOP:
                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, falpha));
                break;
            case SRC_IN:
                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, falpha));
                break;
            case SRC_OUT:
                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OUT, falpha));
                break;
            case SRC_OVER:
                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha));
                break;
            case XOR:
                g.setComposite(AlphaComposite.getInstance(AlphaComposite.XOR, falpha));
                break;
        }
    }


    // --------------------
    // OVERRIDEN ENUMS
    // This is needed since we rename Canvas into _Original_Canvas
    // --------------------

    public enum EdgeType {
        BW(0),  //!< treat edges by just rounding to nearest pixel boundary
        AA(1);  //!< treat edges by rounding-out, since they may be antialiased

        EdgeType(int nativeInt) {
            this.nativeInt = nativeInt;
        }
        final int nativeInt;
    }


    // --------------------
    // OVERRIDEN METHODS
    // --------------------

    /* (non-Javadoc)
     * @see android.graphics.Canvas#setBitmap(android.graphics.Bitmap)
     */
    @Override
    public void setBitmap(Bitmap bitmap) {
        mBufferedImage = bitmap.getImage();
        mGraphicsStack.push(mBufferedImage.createGraphics());
    }


    /* (non-Javadoc)
     * @see android.graphics.Canvas#translate(float, float)
     */
    @Override
    public void translate(float dx, float dy) {
        getGraphics2d().translate(dx, dy);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#save()
     */
    @Override
    public int save() {
        // get the current save count
        int count = mGraphicsStack.size();

        // create a new graphics and add it to the stack
        Graphics2D g = (Graphics2D)getGraphics2d().create();
        mGraphicsStack.push(g);

        // return the old save count
        return count;
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#save(int)
     */
    @Override
    public int save(int saveFlags) {
        // For now we ignore saveFlags
        return save();
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#restore()
     */
    @Override
    public void restore() {
        mGraphicsStack.pop();
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#restoreToCount(int)
     */
    @Override
    public void restoreToCount(int saveCount) {
        while (mGraphicsStack.size() > saveCount) {
            mGraphicsStack.pop();
        }
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#getSaveCount()
     */
    @Override
    public int getSaveCount() {
        return mGraphicsStack.size();
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#clipRect(float, float, float, float, android.graphics.Region.Op)
     */
    @Override
    public boolean clipRect(float left, float top, float right, float bottom, Op op) {
        return clipRect(left, top, right, bottom);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#clipRect(float, float, float, float)
     */
    @Override
    public boolean clipRect(float left, float top, float right, float bottom) {
        getGraphics2d().clipRect((int)left, (int)top, (int)(right-left), (int)(bottom-top));
        return true;
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#clipRect(int, int, int, int)
     */
    @Override
    public boolean clipRect(int left, int top, int right, int bottom) {
        getGraphics2d().clipRect(left, top, right-left, bottom-top);
        return true;
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#clipRect(android.graphics.Rect, android.graphics.Region.Op)
     */
    @Override
    public boolean clipRect(Rect rect, Op op) {
        return clipRect(rect.left, rect.top, rect.right, rect.bottom);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#clipRect(android.graphics.Rect)
     */
    @Override
    public boolean clipRect(Rect rect) {
        return clipRect(rect.left, rect.top, rect.right, rect.bottom);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#clipRect(android.graphics.RectF, android.graphics.Region.Op)
     */
    @Override
    public boolean clipRect(RectF rect, Op op) {
        return clipRect(rect.left, rect.top, rect.right, rect.bottom);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#clipRect(android.graphics.RectF)
     */
    @Override
    public boolean clipRect(RectF rect) {
        return clipRect(rect.left, rect.top, rect.right, rect.bottom);
    }

    public boolean quickReject(RectF rect, EdgeType type) {
        return false;
    }

    @Override
    public boolean quickReject(RectF rect, _Original_Canvas.EdgeType type) {
        throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN");
    }

    public boolean quickReject(Path path, EdgeType type) {
        return false;
    }

    @Override
    public boolean quickReject(Path path, _Original_Canvas.EdgeType type) {
        throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN");
    }

    public boolean quickReject(float left, float top, float right, float bottom,
                               EdgeType type) {
        return false;
    }

    @Override
    public boolean quickReject(float left, float top, float right, float bottom,
                               _Original_Canvas.EdgeType type) {
        throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN");
    }

    /**
     * Retrieve the clip bounds, returning true if they are non-empty.
     *
     * @param bounds Return the clip bounds here. If it is null, ignore it but
     *               still return true if the current clip is non-empty.
     * @return true if the current clip is non-empty.
     */
    @Override
    public boolean getClipBounds(Rect bounds) {
        Rectangle rect = getGraphics2d().getClipBounds();
        if (rect != null) {
            bounds.left = rect.x;
            bounds.top = rect.y;
            bounds.right = rect.x + rect.width;
            bounds.bottom = rect.y + rect.height;
            return true;
        }
        return false;
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawColor(int, android.graphics.PorterDuff.Mode)
     */
    @Override
    public void drawColor(int color, PorterDuff.Mode mode) {
        Graphics2D g = getGraphics2d();

        // save old color
        Color c = g.getColor();

        Composite composite = g.getComposite();

        // get the alpha from the color
        int alpha = color >>> 24;
        float falpha = alpha / 255.f;

        setModeInGraphics(mode, g, falpha);

        g.setColor(new Color(color));

        g.fillRect(0, 0, getWidth(), getHeight());

        g.setComposite(composite);

        // restore color
        g.setColor(c);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawColor(int)
     */
    @Override
    public void drawColor(int color) {
        drawColor(color, PorterDuff.Mode.SRC_OVER);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawARGB(int, int, int, int)
     */
    @Override
    public void drawARGB(int a, int r, int g, int b) {
        drawColor(a << 24 | r << 16 | g << 8 | b, PorterDuff.Mode.SRC_OVER);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawRGB(int, int, int)
     */
    @Override
    public void drawRGB(int r, int g, int b) {
        drawColor(0xFF << 24 | r << 16 | g << 8 | b, PorterDuff.Mode.SRC_OVER);
    }


    /* (non-Javadoc)
     * @see android.graphics.Canvas#getWidth()
     */
    @Override
    public int getWidth() {
        return mBufferedImage.getWidth();
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#getHeight()
     */
    @Override
    public int getHeight() {
        return mBufferedImage.getHeight();
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawPaint(android.graphics.Paint)
     */
    @Override
    public void drawPaint(Paint paint) {
        drawColor(paint.getColor());
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawBitmap(android.graphics.Bitmap, float, float, android.graphics.Paint)
     */
    @Override
    public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
        drawBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(),
                (int)left, (int)top,
                (int)left+bitmap.getWidth(), (int)top+bitmap.getHeight(), paint);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawBitmap(android.graphics.Bitmap, android.graphics.Matrix, android.graphics.Paint)
     */
    @Override
    public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
        boolean needsRestore = false;
        if (matrix.isIdentity() == false) {
            // create a new graphics and apply the matrix to it
            save(); // this creates a new Graphics2D, and stores it for children call to use
            needsRestore = true;
            Graphics2D g = getGraphics2d(); // get the newly create Graphics2D

            // get the Graphics2D current matrix
            AffineTransform currentTx = g.getTransform();
            // get the AffineTransform from the matrix
            AffineTransform matrixTx = matrix.getTransform();

            // combine them so that the matrix is applied after.
            currentTx.preConcatenate(matrixTx);

            // give it to the graphics as a new matrix replacing all previous transform
            g.setTransform(currentTx);
        }

        // draw the bitmap
        drawBitmap(bitmap, 0, 0, paint);

        if (needsRestore) {
            // remove the new graphics
            restore();
        }
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.Rect, android.graphics.Paint)
     */
    @Override
    public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
        if (src == null) {
            drawBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(),
                    dst.left, dst.top, dst.right, dst.bottom, paint);
        } else {
            drawBitmap(bitmap, src.left, src.top, src.width(), src.height(),
                    dst.left, dst.top, dst.right, dst.bottom, paint);
        }
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.RectF, android.graphics.Paint)
     */
    @Override
    public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
        if (src == null) {
            drawBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(),
                    (int)dst.left, (int)dst.top, (int)dst.right, (int)dst.bottom, paint);
        } else {
            drawBitmap(bitmap, src.left, src.top, src.width(), src.height(),
                    (int)dst.left, (int)dst.top, (int)dst.right, (int)dst.bottom, paint);
        }
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawBitmap(int[], int, int, int, int, int, int, boolean, android.graphics.Paint)
     */
    @Override
    public void drawBitmap(int[] colors, int offset, int stride, int x, int y, int width,
            int height, boolean hasAlpha, Paint paint) {
        throw new UnsupportedOperationException();
    }

    private void drawBitmap(Bitmap bitmap, int sleft, int stop, int sright, int sbottom, int dleft,
            int dtop, int dright, int dbottom, Paint paint) {
        BufferedImage image = bitmap.getImage();

        Graphics2D g = getGraphics2d();

        Composite c = null;

        if (paint != null) {
            if (paint.isFilterBitmap()) {
                g = (Graphics2D)g.create();
                g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                        RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            }

            if (paint.getAlpha() != 0xFF) {
                c = g.getComposite();
                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
                        paint.getAlpha()/255.f));
            }
        }

        g.drawImage(image, dleft, dtop, dright, dbottom,
                sleft, stop, sright, sbottom, null);

        if (paint != null) {
            if (paint.isFilterBitmap()) {
                g.dispose();
            }
            if (c != null) {
                g.setComposite(c);
            }
        }
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#rotate(float, float, float)
     */
    @Override
    public void rotate(float degrees, float px, float py) {
        if (degrees != 0) {
            Graphics2D g = getGraphics2d();
            g.translate(px, py);
            g.rotate(Math.toRadians(degrees));
            g.translate(-px, -py);
        }
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#rotate(float)
     */
    @Override
    public void rotate(float degrees) {
        getGraphics2d().rotate(Math.toRadians(degrees));
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#scale(float, float, float, float)
     */
    @Override
    public void scale(float sx, float sy, float px, float py) {
        Graphics2D g = getGraphics2d();
        g.translate(px, py);
        g.scale(sx, sy);
        g.translate(-px, -py);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#scale(float, float)
     */
    @Override
    public void scale(float sx, float sy) {
        getGraphics2d().scale(sx, sy);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawText(char[], int, int, float, float, android.graphics.Paint)
     */
    @Override
    public void drawText(char[] text, int index, int count, float x, float y, Paint paint) {
        // WARNING: the logic in this method is similar to Paint.measureText.
        // Any change to this method should be reflected in Paint.measureText
        Graphics2D g = getGraphics2d();

        g = (Graphics2D)g.create();
        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(paint.getColor()));
        int alpha = paint.getAlpha();
        float falpha = alpha / 255.f;
        g.setComposite(AlphaComposite.getInstance(AlphaComposite.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 (paint.getTextAlign() != Align.LEFT) {
            float m = paint.measureText(text, index, count);
            if (paint.getTextAlign() == Align.CENTER) {
                x -= m / 2;
            } else if (paint.getTextAlign() == Align.RIGHT) {
                x -= m;
            }
        }

        List<FontInfo> fonts = paint.getFonts();
        try {
            if (fonts.size() > 0) {
                FontInfo mainFont = fonts.get(0);
                int i = index;
                int lastIndex = index + count;
                while (i < lastIndex) {
                    // always start with the main font.
                    int upTo = mainFont.mFont.canDisplayUpTo(text, i, lastIndex);
                    if (upTo == -1) {
                        // draw all the rest and exit.
                        g.setFont(mainFont.mFont);
                        g.drawChars(text, i, lastIndex - i, (int)x, (int)y);
                        return;
                    } else if (upTo > 0) {
                        // draw what's possible
                        g.setFont(mainFont.mFont);
                        g.drawChars(text, i, upTo - i, (int)x, (int)y);

                        // compute the width that was drawn to increase x
                        x += mainFont.mMetrics.charsWidth(text, i, upTo - i);

                        // move index to the first non displayed char.
                        i = upTo;

                        // don't call continue at this point. Since it is certain the main font
                        // cannot display the font a index upTo (now ==i), we move on to the
                        // fallback fonts directly.
                    }

                    // no char supported, attempt to read the next char(s) with the
                    // fallback font. In this case we only test the first character
                    // and then go back to test with the main font.
                    // Special test for 2-char characters.
                    boolean foundFont = false;
                    for (int f = 1 ; f < fonts.size() ; f++) {
                        FontInfo fontInfo = fonts.get(f);

                        // need to check that the font can display the character. We test
                        // differently if the char is a high surrogate.
                        int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1;
                        upTo = fontInfo.mFont.canDisplayUpTo(text, i, i + charCount);
                        if (upTo == -1) {
                            // draw that char
                            g.setFont(fontInfo.mFont);
                            g.drawChars(text, i, charCount, (int)x, (int)y);

                            // update x
                            x += fontInfo.mMetrics.charsWidth(text, i, charCount);

                            // update the index in the text, and move on
                            i += charCount;
                            foundFont = true;
                            break;

                        }
                    }

                    // in case no font can display the char, display it with the main font.
                    // (it'll put a square probably)
                    if (foundFont == false) {
                        int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1;

                        g.setFont(mainFont.mFont);
                        g.drawChars(text, i, charCount, (int)x, (int)y);

                        // measure it to advance x
                        x += mainFont.mMetrics.charsWidth(text, i, charCount);

                        // and move to the next chars.
                        i += charCount;
                    }
                }
            }
        } finally {
            g.dispose();
        }
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawText(java.lang.CharSequence, int, int, float, float, android.graphics.Paint)
     */
    @Override
    public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) {
        drawText(text.toString().toCharArray(), start, end - start, x, y, paint);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawText(java.lang.String, float, float, android.graphics.Paint)
     */
    @Override
    public void drawText(String text, float x, float y, Paint paint) {
        drawText(text.toCharArray(), 0, text.length(), x, y, paint);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawText(java.lang.String, int, int, float, float, android.graphics.Paint)
     */
    @Override
    public void drawText(String text, int start, int end, float x, float y, Paint paint) {
        drawText(text.toCharArray(), start, end - start, x, y, paint);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawRect(android.graphics.RectF, android.graphics.Paint)
     */
    @Override
    public void drawRect(RectF rect, Paint paint) {
        doDrawRect((int)rect.left, (int)rect.top, (int)rect.width(), (int)rect.height(), paint);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawRect(float, float, float, float, android.graphics.Paint)
     */
    @Override
    public void drawRect(float left, float top, float right, float bottom, Paint paint) {
        doDrawRect((int)left, (int)top, (int)(right-left), (int)(bottom-top), paint);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawRect(android.graphics.Rect, android.graphics.Paint)
     */
    @Override
    public void drawRect(Rect r, Paint paint) {
        doDrawRect(r.left, r.top, r.width(), r.height(), paint);
    }

    private final void doDrawRect(int left, int top, int width, int height, Paint paint) {
        if (width > 0 && height > 0) {
            // get a Graphics2D object configured with the drawing parameters.
            Graphics2D g = getCustomGraphics(paint);

            Style style = paint.getStyle();

            // draw
            if (style == Style.FILL || style == Style.FILL_AND_STROKE) {
                g.fillRect(left, top, width, height);
            }

            if (style == Style.STROKE || style == Style.FILL_AND_STROKE) {
                g.drawRect(left, top, width, height);
            }

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

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawRoundRect(android.graphics.RectF, float, float, android.graphics.Paint)
     */
    @Override
    public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) {
        if (rect.width() > 0 && rect.height() > 0) {
            // get a Graphics2D object configured with the drawing parameters.
            Graphics2D g = getCustomGraphics(paint);

            Style style = paint.getStyle();

            // draw

            int arcWidth = (int)(rx * 2);
            int arcHeight = (int)(ry * 2);

            if (style == Style.FILL || style == Style.FILL_AND_STROKE) {
                g.fillRoundRect((int)rect.left, (int)rect.top, (int)rect.width(), (int)rect.height(),
                        arcWidth, arcHeight);
            }

            if (style == Style.STROKE || style == Style.FILL_AND_STROKE) {
                g.drawRoundRect((int)rect.left, (int)rect.top, (int)rect.width(), (int)rect.height(),
                        arcWidth, arcHeight);
            }

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


    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawLine(float, float, float, float, android.graphics.Paint)
     */
    @Override
    public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) {
        // get a Graphics2D object configured with the drawing parameters.
        Graphics2D g = getCustomGraphics(paint);

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

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

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawLines(float[], int, int, android.graphics.Paint)
     */
    @Override
    public void drawLines(float[] pts, int offset, int count, Paint paint) {
        // get a Graphics2D object configured with the drawing parameters.
        Graphics2D g = getCustomGraphics(paint);

        for (int i = 0 ; i < count ; i += 4) {
            g.drawLine((int)pts[i + offset], (int)pts[i + offset + 1],
                    (int)pts[i + offset + 2], (int)pts[i + offset + 3]);
        }

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

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawLines(float[], android.graphics.Paint)
     */
    @Override
    public void drawLines(float[] pts, Paint paint) {
        drawLines(pts, 0, pts.length, paint);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawCircle(float, float, float, android.graphics.Paint)
     */
    @Override
    public void drawCircle(float cx, float cy, float radius, Paint paint) {
        // get a Graphics2D object configured with the drawing parameters.
        Graphics2D g = getCustomGraphics(paint);

        Style style = paint.getStyle();

        int size = (int)(radius * 2);

        // draw
        if (style == Style.FILL || style == Style.FILL_AND_STROKE) {
            g.fillOval((int)(cx - radius), (int)(cy - radius), size, size);
        }

        if (style == Style.STROKE || style == Style.FILL_AND_STROKE) {
            g.drawOval((int)(cx - radius), (int)(cy - radius), size, size);
        }

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

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawOval(android.graphics.RectF, android.graphics.Paint)
     */
    @Override
    public void drawOval(RectF oval, Paint paint) {
        // get a Graphics2D object configured with the drawing parameters.
        Graphics2D g = getCustomGraphics(paint);

        Style style = paint.getStyle();

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

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

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

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawPath(android.graphics.Path, android.graphics.Paint)
     */
    @Override
    public void drawPath(Path path, Paint paint) {
        // get a Graphics2D object configured with the drawing parameters.
        Graphics2D g = getCustomGraphics(paint);

        Style style = paint.getStyle();

        // draw
        if (style == Style.FILL || style == Style.FILL_AND_STROKE) {
            g.fill(path.getAwtShape());
        }

        if (style == Style.STROKE || style == Style.FILL_AND_STROKE) {
            g.draw(path.getAwtShape());
        }

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

    /* (non-Javadoc)
     * @see android.graphics.Canvas#setMatrix(android.graphics.Matrix)
     */
    @Override
    public void setMatrix(Matrix matrix) {
        // get the new current graphics
        Graphics2D g = getGraphics2d();

        // and apply the matrix
        g.setTransform(matrix.getTransform());

        if (mLogger != null && matrix.hasPerspective()) {
            mLogger.warning("android.graphics.Canvas#setMatrix(android.graphics.Matrix) only supports affine transformations in the Layout Editor.");
        }
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#concat(android.graphics.Matrix)
     */
    @Override
    public void concat(Matrix matrix) {
        // get the current top graphics2D object.
        Graphics2D g = getGraphics2d();

        // get its current matrix
        AffineTransform currentTx = g.getTransform();
        // get the AffineTransform of the given matrix
        AffineTransform matrixTx = matrix.getTransform();

        // combine them so that the given matrix is applied after.
        currentTx.preConcatenate(matrixTx);

        // give it to the graphics2D as a new matrix replacing all previous transform
        g.setTransform(currentTx);
    }


    // --------------------

    /* (non-Javadoc)
     * @see android.graphics.Canvas#clipPath(android.graphics.Path, android.graphics.Region.Op)
     */
    @Override
    public boolean clipPath(Path path, Op op) {
        // TODO Auto-generated method stub
        return super.clipPath(path, op);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#clipPath(android.graphics.Path)
     */
    @Override
    public boolean clipPath(Path path) {
        // TODO Auto-generated method stub
        return super.clipPath(path);
    }


    /* (non-Javadoc)
     * @see android.graphics.Canvas#clipRegion(android.graphics.Region, android.graphics.Region.Op)
     */
    @Override
    public boolean clipRegion(Region region, Op op) {
        // TODO Auto-generated method stub
        return super.clipRegion(region, op);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#clipRegion(android.graphics.Region)
     */
    @Override
    public boolean clipRegion(Region region) {
        // TODO Auto-generated method stub
        return super.clipRegion(region);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawArc(android.graphics.RectF, float, float, boolean, android.graphics.Paint)
     */
    @Override
    public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,
            Paint paint) {
        // TODO Auto-generated method stub
        super.drawArc(oval, startAngle, sweepAngle, useCenter, paint);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawBitmapMesh(android.graphics.Bitmap, int, int, float[], int, int[], int, android.graphics.Paint)
     */
    @Override
    public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts,
            int vertOffset, int[] colors, int colorOffset, Paint paint) {
        // TODO Auto-generated method stub
        super.drawBitmapMesh(bitmap, meshWidth, meshHeight, verts, vertOffset, colors, colorOffset, paint);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawPicture(android.graphics.Picture, android.graphics.Rect)
     */
    @Override
    public void drawPicture(Picture picture, Rect dst) {
        // TODO Auto-generated method stub
        super.drawPicture(picture, dst);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawPicture(android.graphics.Picture, android.graphics.RectF)
     */
    @Override
    public void drawPicture(Picture picture, RectF dst) {
        // TODO Auto-generated method stub
        super.drawPicture(picture, dst);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawPicture(android.graphics.Picture)
     */
    @Override
    public void drawPicture(Picture picture) {
        // TODO Auto-generated method stub
        super.drawPicture(picture);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawPoint(float, float, android.graphics.Paint)
     */
    @Override
    public void drawPoint(float x, float y, Paint paint) {
        // TODO Auto-generated method stub
        super.drawPoint(x, y, paint);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawPoints(float[], int, int, android.graphics.Paint)
     */
    @Override
    public void drawPoints(float[] pts, int offset, int count, Paint paint) {
        // TODO Auto-generated method stub
        super.drawPoints(pts, offset, count, paint);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawPoints(float[], android.graphics.Paint)
     */
    @Override
    public void drawPoints(float[] pts, Paint paint) {
        // TODO Auto-generated method stub
        super.drawPoints(pts, paint);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawPosText(char[], int, int, float[], android.graphics.Paint)
     */
    @Override
    public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint) {
        // TODO Auto-generated method stub
        super.drawPosText(text, index, count, pos, paint);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawPosText(java.lang.String, float[], android.graphics.Paint)
     */
    @Override
    public void drawPosText(String text, float[] pos, Paint paint) {
        // TODO Auto-generated method stub
        super.drawPosText(text, pos, paint);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawTextOnPath(char[], int, int, android.graphics.Path, float, float, android.graphics.Paint)
     */
    @Override
    public void drawTextOnPath(char[] text, int index, int count, Path path, float offset,
            float offset2, Paint paint) {
        // TODO Auto-generated method stub
        super.drawTextOnPath(text, index, count, path, offset, offset2, paint);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawTextOnPath(java.lang.String, android.graphics.Path, float, float, android.graphics.Paint)
     */
    @Override
    public void drawTextOnPath(String text, Path path, float offset, float offset2, Paint paint) {
        // TODO Auto-generated method stub
        super.drawTextOnPath(text, path, offset, offset2, paint);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#drawVertices(android.graphics.Canvas.VertexMode, int, float[], int, float[], int, int[], int, short[], int, int, android.graphics.Paint)
     */
    @Override
    public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset,
            float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices,
            int indexOffset, int indexCount, Paint paint) {
        // TODO Auto-generated method stub
        super.drawVertices(mode, vertexCount, verts, vertOffset, texs, texOffset, colors, colorOffset,
                indices, indexOffset, indexCount, paint);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#getDrawFilter()
     */
    @Override
    public DrawFilter getDrawFilter() {
        // TODO Auto-generated method stub
        return super.getDrawFilter();
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#getGL()
     */
    @Override
    public GL getGL() {
        // TODO Auto-generated method stub
        return super.getGL();
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#getMatrix()
     */
    @Override
    public Matrix getMatrix() {
        // TODO Auto-generated method stub
        return super.getMatrix();
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#getMatrix(android.graphics.Matrix)
     */
    @Override
    public void getMatrix(Matrix ctm) {
        // TODO Auto-generated method stub
        super.getMatrix(ctm);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#isOpaque()
     */
    @Override
    public boolean isOpaque() {
        // TODO Auto-generated method stub
        return super.isOpaque();
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#saveLayer(float, float, float, float, android.graphics.Paint, int)
     */
    @Override
    public int saveLayer(float left, float top, float right, float bottom, Paint paint,
            int saveFlags) {
        // TODO Auto-generated method stub
        return super.saveLayer(left, top, right, bottom, paint, saveFlags);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#saveLayer(android.graphics.RectF, android.graphics.Paint, int)
     */
    @Override
    public int saveLayer(RectF bounds, Paint paint, int saveFlags) {
        // TODO Auto-generated method stub
        return super.saveLayer(bounds, paint, saveFlags);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#saveLayerAlpha(float, float, float, float, int, int)
     */
    @Override
    public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
            int saveFlags) {
        // TODO Auto-generated method stub
        return super.saveLayerAlpha(left, top, right, bottom, alpha, saveFlags);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#saveLayerAlpha(android.graphics.RectF, int, int)
     */
    @Override
    public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) {
        // TODO Auto-generated method stub
        return super.saveLayerAlpha(bounds, alpha, saveFlags);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#setDrawFilter(android.graphics.DrawFilter)
     */
    @Override
    public void setDrawFilter(DrawFilter filter) {
        // TODO Auto-generated method stub
        super.setDrawFilter(filter);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#setViewport(int, int)
     */
    @Override
    public void setViewport(int width, int height) {
        // TODO Auto-generated method stub
        super.setViewport(width, height);
    }

    /* (non-Javadoc)
     * @see android.graphics.Canvas#skew(float, float)
     */
    @Override
    public void skew(float sx, float sy) {
        // TODO Auto-generated method stub
        super.skew(sx, sy);
    }



}

Other Android examples (source code examples)

Here is a short list of links related to this Android Canvas.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.