/*
 * 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.
 */

package android.graphics;

import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.layoutlib.bridge.impl.Stack;

import android.graphics.Paint_Delegate.FontInfo;
import android.text.TextUtils;

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;


/**
 * Delegate implementing the native methods of android.graphics.Canvas
 *
 * Through the layoutlib_create tool, the original native methods of Canvas 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 Canvas class.
 *
 * @see DelegateManager
 *
 */
public class Canvas_Delegate {

    // ---- delegate manager ----
    private static final DelegateManager<Canvas_Delegate> sManager =
            new DelegateManager<Canvas_Delegate>();

    // ---- delegate helper data ----

    // ---- delegate data ----
    private BufferedImage mBufferedImage;
    private final Stack<Graphics2D> mGraphicsStack = new Stack<Graphics2D>();

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

    /**
     * Returns the native delegate associated to a given {@link Canvas} object.
     */
    public static Canvas_Delegate getDelegate(Canvas canvas) {
        return sManager.getDelegate(canvas.mNativeCanvas);
    }

    /**
     * Returns the native delegate associated to a given an int referencing a {@link Canvas} object.
     */
    public static Canvas_Delegate getDelegate(int native_canvas) {
        return sManager.getDelegate(native_canvas);
    }

    /**
     * Returns the current {@link Graphics2D} used to draw.
     */
    public Graphics2D getGraphics2d() {
        return mGraphicsStack.peek();
    }

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

    /*package*/ static boolean isOpaque(Canvas thisCanvas) {
        // FIXME
        throw new UnsupportedOperationException();
    }

    /*package*/ static int getWidth(Canvas thisCanvas) {
        // get the delegate from the native int.
        Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
        if (canvasDelegate == null) {
            assert false;
            return 0;
        }

        return canvasDelegate.mBufferedImage.getWidth();
    }

    /*package*/ static int getHeight(Canvas thisCanvas) {
        // get the delegate from the native int.
        Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
        if (canvasDelegate == null) {
            assert false;
            return 0;
        }

        return canvasDelegate.mBufferedImage.getHeight();
    }

    /*package*/ static void translate(Canvas thisCanvas, float dx, float dy) {
        // get the delegate from the native int.
        Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
        if (canvasDelegate == null) {
            assert false;
            return;
        }

        canvasDelegate.getGraphics2d().translate(dx, dy);
    }

    /*package*/ static void rotate(Canvas thisCanvas, float degrees) {
        // get the delegate from the native int.
        Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
        if (canvasDelegate == null) {
            assert false;
            return;
        }

        canvasDelegate.getGraphics2d().rotate(Math.toRadians(degrees));
    }

    /*package*/ static void scale(Canvas thisCanvas, float sx, float sy) {
        // get the delegate from the native int.
        Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
        if (canvasDelegate == null) {
            assert false;
            return;
        }

        canvasDelegate.getGraphics2d().scale(sx, sy);
    }

    /*package*/ static void skew(Canvas thisCanvas, float kx, float ky) {
        // get the delegate from the native int.
        Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
        if (canvasDelegate == null) {
            assert false;
            return;
        }

        // get the current top graphics2D object.
        Graphics2D g = canvasDelegate.getGraphics2d();

        // get its current matrix
        AffineTransform currentTx = g.getTransform();
        // get the AffineTransform for the given skew.
        float[] mtx = Matrix_Delegate.getSkew(kx, ky);
        AffineTransform matrixTx = Matrix_Delegate.getAffineTransform(mtx);

        // 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);
    }

    /*package*/ static boolean clipRect(Canvas thisCanvas, RectF rect) {
        return clipRect(thisCanvas, rect.left, rect.top, rect.right, rect.bottom);
    }

    /*package*/ static boolean clipRect(Canvas thisCanvas, Rect rect) {
        return clipRect(thisCanvas, rect.left, rect.top, rect.right, rect.bottom);
    }

    /*package*/ static boolean clipRect(Canvas thisCanvas, float left, float top, float right,
            float bottom) {
        // get the delegate from the native int.
        Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
        if (canvasDelegate == null) {
            assert false;
            return false;
        }

        canvasDelegate.getGraphics2d().clipRect((int)left, (int)top, (int)(right-left),
                (int)(bottom-top));
        return true;
    }

    /*package*/ static boolean clipRect(Canvas thisCanvas, int left, int top, int right,
            int bottom) {
        // get the delegate from the native int.
        Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
        if (canvasDelegate == null) {
            assert false;
            return false;
        }

        canvasDelegate.getGraphics2d().clipRect(left, top, right - left, bottom - top);
        return true;
    }

    /*package*/ static int save(Canvas thisCanvas) {
        // get the delegate from the native int.
        Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
        if (canvasDelegate == null) {
            assert false;
            return 0;
        }

        // get the current save count
        int count = canvasDelegate.mGraphicsStack.size();

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

        // return the old save count
        return count;

    }

    /*package*/ static int save(Canvas thisCanvas, int saveFlags) {
        // FIXME implement save(flags)
        return save(thisCanvas);
    }

    /*package*/ static void restore(Canvas thisCanvas) {
        // get the delegate from the native int.
        Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
        if (canvasDelegate == null) {
            assert false;
            return;
        }

        canvasDelegate.mGraphicsStack.pop();
    }

    /*package*/ static int getSaveCount(Canvas thisCanvas) {
        // get the delegate from the native int.
        Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
        if (canvasDelegate == null) {
            assert false;
            return 0;
        }

        return canvasDelegate.mGraphicsStack.size();
    }

    /*package*/ static void restoreToCount(Canvas thisCanvas, int saveCount) {
        // get the delegate from the native int.
        Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
        if (canvasDelegate == null) {
            assert false;
            return;
        }

        while (canvasDelegate.mGraphicsStack.size() > saveCount) {
            canvasDelegate.mGraphicsStack.pop();
        }
    }

    /*package*/ static void drawPoints(Canvas thisCanvas, float[] pts, int offset, int count,
            Paint paint) {
        // FIXME
        throw new UnsupportedOperationException();
    }

    /*package*/ static void drawPoint(Canvas thisCanvas, float x, float y, Paint paint) {
        // FIXME
        throw new UnsupportedOperationException();
    }

    /*package*/ static void drawLines(Canvas thisCanvas, float[] pts, int offset, int count,
            Paint paint) {
        // FIXME
        throw new UnsupportedOperationException();
    }

    /*package*/ static void freeCaches() {
        // FIXME
        throw new UnsupportedOperationException();
    }

    /*package*/ static int initRaster(int nativeBitmapOrZero) {
        if (nativeBitmapOrZero > 0) {
            // get the Bitmap from the int
            Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nativeBitmapOrZero);

            // create a new Canvas_Delegate with the given bitmap and return its new native int.
            Canvas_Delegate newDelegate = new Canvas_Delegate(bitmapDelegate.getImage());

            return sManager.addDelegate(newDelegate);
        } else {
            // create a new Canvas_Delegate and return its new native int.
            Canvas_Delegate newDelegate = new Canvas_Delegate();

            return sManager.addDelegate(newDelegate);
        }
    }

    /*package*/ static void native_setBitmap(int nativeCanvas, int bitmap) {
        // 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.
        Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
        if (bitmapDelegate == null) {
            assert false;
            return;
        }

        canvasDelegate.setBitmap(bitmapDelegate.getImage());
    }

    /*package*/ static int native_saveLayer(int nativeCanvas, RectF bounds,
                                               int paint, int layerFlags) {
        // FIXME
        throw new UnsupportedOperationException();
    }

    /*package*/ static int native_saveLayer(int nativeCanvas, float l,
                                               float t, float r, float b,
                                               int paint, int layerFlags) {
        // FIXME
        throw new UnsupportedOperationException();
    }

    /*package*/ static int native_saveLayerAlpha(int nativeCanvas,
                                                    RectF bounds, int alpha,
                                                    int layerFlags) {
        // FIXME
        throw new UnsupportedOperationException();
    }

    /*package*/ static int native_saveLayerAlpha(int nativeCanvas, float l,
                                                    float t, float r, float b,
                                                    int alpha, int layerFlags) {
        // FIXME
        throw new UnsupportedOperationException();
    }


    /*package*/ static void native_concat(int nCanvas, int nMatrix) {
        // get the delegate from the native int.
        Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
        if (canvasDelegate == null) {
            assert false;
            return;
        }

        Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix);
        if (matrixDelegate == null) {
            assert false;
            return;
        }

        // get the current top graphics2D object.
        Graphics2D g = canvasDelegate.getGraphics2d();

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

        // 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);
    }

    /*package*/ static void native_setMatrix(int nCanvas, int nMatrix) {
        // get the delegate from the native int.
        Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
        if (canvasDelegate == null) {
            assert false;
        }

        Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix);
        if (matrixDelegate == null) {
            assert false;
        }

        // get the current top graphics2D object.
        Graphics2D g = canvasDelegate.getGraphics2d();

        // get the AffineTransform of the given matrix
        AffineTransform matrixTx = matrixDelegate.getAffineTransform();

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

        if (matrixDelegate.hasPerspective()) {
            Bridge.getLog().warning(null,
                    "android.graphics.Canvas#setMatrix(android.graphics.Matrix) only " +
                    "supports affine transformations in the Layout Preview.");
        }
    }

    /*package*/ static boolean native_clipRect(int nCanvas,
                                                  float left, float top,
                                                  float right, float bottom,
                                                  int regionOp) {
        // FIXME
        throw new UnsupportedOperationException();
    }

    /*package*/ static boolean native_clipPath(int nativeCanvas,
                                                  int nativePath,
                                                  int regionOp) {
        // FIXME
        throw new UnsupportedOperationException();
    }

    /*package*/ static boolean native_clipRegion(int nativeCanvas,
                                                    int nativeRegion,
                                                    int regionOp) {
        // FIXME
        throw new UnsupportedOperationException();
    }

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

    /*package*/ static boolean native_getClipBounds(int nativeCanvas,
                                                       Rect bounds) {
        // get the delegate from the native int.
        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
        if (canvasDelegate == null) {
            assert false;
            return false;
        }

        Rectangle rect = canvasDelegate.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;
    }

    /*package*/ static void native_getCTM(int canvas, int matrix) {
        // FIXME
        throw new UnsupportedOperationException();
    }

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

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

    /*package*/ static boolean native_quickReject(int nativeCanvas,
                                                     float left, float top,
                                                     float right, float bottom,
                                                     int native_edgeType) {
        // FIXME properly implement quickReject
        return false;
    }

    /*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_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) {
            assert false;
            return;
        }

        // get a new graphics context.
        Graphics2D graphics = (Graphics2D)canvasDelegate.getGraphics2d().create();
        try {
            // reset its transform just in case
            graphics.setTransform(new AffineTransform());

            // set the color
            graphics.setColor(new Color(color, true /*alpha*/));

            setModeInGraphics(graphics, mode);

            graphics.fillRect(0, 0, canvasDelegate.mBufferedImage.getWidth(),
                    canvasDelegate.mBufferedImage.getHeight());
        } finally {
            // dispose Graphics2D object
            graphics.dispose();
        }
    }

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

    /*package*/ static void native_drawLine(int nativeCanvas, float startX,
                                               float startY, float stopX,
                                               float stopY, int paint) {
        // 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) {
        native_drawRect(nativeCanvas, rect.left, rect.top, rect.right, rect.bottom, paint);
    }

    /*package*/ static void native_drawRect(int nativeCanvas, float left,
                                               float top, float right,
                                               float bottom, int paint) {
        // 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 (right > left && bottom > 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.fillRect((int)left, (int)top, (int)(right-left), (int)(bottom-top));
            }

            if (style == Paint.Style.STROKE.nativeInt ||
                    style == Paint.Style.FILL_AND_STROKE.nativeInt) {
                g.drawRect((int)left, (int)top, (int)(right-left), (int)(bottom-top));
            }

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

    /*package*/ static void native_drawOval(int nativeCanvas, RectF oval,
                                               int paint) {
        // 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) {
        native_drawOval(nativeCanvas,
                new RectF(cx - radius, cy - radius, radius*2, radius*2),
                paint);
    }

    /*package*/ static void native_drawArc(int nativeCanvas, RectF oval,
                                              float startAngle, float sweep,
                                              boolean useCenter, int paint) {
        // FIXME
        throw new UnsupportedOperationException();
    }

    /*package*/ static void native_drawRoundRect(int nativeCanvas,
                                                    RectF rect, float rx,
                                                    float ry, int paint) {
        // 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,
                                               int paint) {
        // FIXME
        throw new UnsupportedOperationException();
    }

    /*package*/ static void native_drawBitmap(Canvas thisCanvas, int nativeCanvas, int bitmap,
                                                 float left, float top,
                                                 int nativePaintOrZero,
                                                 int canvasDensity,
                                                 int screenDensity,
                                                 int bitmapDensity) {
        // FIXME
        throw new UnsupportedOperationException();
    }

    /*package*/ static void native_drawBitmap(Canvas thisCanvas, int nativeCanvas, int bitmap,
                                                 Rect src, RectF dst,
                                                 int nativePaintOrZero,
                                                 int screenDensity,
                                                 int bitmapDensity) {
        // get the delegate from the native int.
        Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
        if (bitmapDelegate == null) {
            assert false;
            return;
        }

        BufferedImage image = bitmapDelegate.getImage();

        if (src == null) {
            drawBitmap(nativeCanvas, image, nativePaintOrZero,
                    0, 0, image.getWidth(), image.getHeight(),
                    (int)dst.left, (int)dst.top, (int)dst.right, (int)dst.bottom);
        } else {
            drawBitmap(nativeCanvas, image, nativePaintOrZero,
                    src.left, src.top, src.width(), src.height(),
                    (int)dst.left, (int)dst.top, (int)dst.right, (int)dst.bottom);
        }
    }

    /*package*/ static void native_drawBitmap(int nativeCanvas, int bitmap,
                                                 Rect src, Rect dst,
                                                 int nativePaintOrZero,
                                                 int screenDensity,
                                                 int bitmapDensity) {
        // get the delegate from the native int.
        Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
        if (bitmapDelegate == null) {
            assert false;
            return;
        }

        BufferedImage image = bitmapDelegate.getImage();

        if (src == null) {
            drawBitmap(nativeCanvas, image, nativePaintOrZero,
                    0, 0, image.getWidth(), image.getHeight(),
                    dst.left, dst.top, dst.right, dst.bottom);
        } else {
            drawBitmap(nativeCanvas, image, nativePaintOrZero,
                    src.left, src.top, src.width(), src.height(),
                    dst.left, dst.top, dst.right, dst.bottom);
        }
    }

    /*package*/ static void native_drawBitmap(int nativeCanvas, int[] colors,
                                                int offset, int stride, float x,
                                                 float y, int width, int height,
                                                 boolean hasAlpha,
                                                 int nativePaintOrZero) {
        // FIXME
        throw new UnsupportedOperationException();
    }

    /*package*/ static void nativeDrawBitmapMatrix(int nCanvas, int nBitmap,
                                                      int nMatrix, int nPaint) {
        // FIXME
        throw new UnsupportedOperationException();
    }

    /*package*/ static void nativeDrawBitmapMesh(int nCanvas, int nBitmap,
                                                    int meshWidth, int meshHeight,
                                                    float[] verts, int vertOffset,
                                                    int[] colors, int colorOffset, int nPaint) {
        // FIXME
        throw new UnsupportedOperationException();
    }

    /*package*/ static void nativeDrawVertices(int nCanvas, int mode, int n,
                   float[] verts, int vertOffset, float[] texs, int texOffset,
                   int[] colors, int colorOffset, short[] indices,
                   int indexOffset, int indexCount, int nPaint) {
        // FIXME
        throw new UnsupportedOperationException();
    }

    /*package*/ static void native_drawText(int nativeCanvas, char[] text,
                                               int index, int count, float x,
                                               float y, int flags, int paint) {
        // WARNING: the logic in this method is similar to Paint.measureText.
        // Any change to this method should be reflected in Paint.measureText

        // 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;
        }

        Graphics2D g = (Graphics2D) canvasDelegate.getCustomGraphics(paintDelegate);
        try {
            // 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) {
                float m = paintDelegate.measureText(text, index, count);
                if (paintDelegate.getTextAlign() == Paint.Align.CENTER.nativeInt) {
                    x -= m / 2;
                } else if (paintDelegate.getTextAlign() == Paint.Align.RIGHT.nativeInt) {
                    x -= m;
                }
            }

            List<FontInfo> fonts = paintDelegate.getFonts();

            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();
        }
    }

    /*package*/ static void native_drawText(int nativeCanvas, String text,
                                               int start, int end, float x,
                                               float y, int flags, int paint) {
        int count = end - start;
        char[] buffer = TemporaryBuffer.obtain(count);
        TextUtils.getChars(text, start, end, buffer, 0);

        native_drawText(nativeCanvas, buffer, 0, count, x, y, flags, paint);
    }

    /*package*/ static void native_drawTextRun(int nativeCanvas, String text,
            int start, int end, int contextStart, int contextEnd,
            float x, float y, int flags, int paint) {
        int count = end - start;
        char[] buffer = TemporaryBuffer.obtain(count);
        TextUtils.getChars(text, start, end, buffer, 0);

        native_drawText(nativeCanvas, buffer, start, end, x, y, flags, paint);
    }

    /*package*/ static void native_drawTextRun(int nativeCanvas, char[] text,
            int start, int count, int contextStart, int contextCount,
            float x, float y, int flags, int paint) {
        native_drawText(nativeCanvas, text, 0, count, x, y, flags, paint);
    }

    /*package*/ static void native_drawPosText(int nativeCanvas,
                                                  char[] text, int index,
                                                  int count, float[] pos,
                                                  int paint) {
        // FIXME
        throw new UnsupportedOperationException();
    }

    /*package*/ static void native_drawPosText(int nativeCanvas,
                                                  String text, float[] pos,
                                                  int paint) {
        // FIXME
        throw new UnsupportedOperationException();
    }

    /*package*/ static void native_drawTextOnPath(int nativeCanvas,
                                                     char[] text, int index,
                                                     int count, int path,
                                                     float hOffset,
                                                     float vOffset, int bidiFlags,
                                                     int paint) {
        // FIXME
        throw new UnsupportedOperationException();
    }

    /*package*/ static void native_drawTextOnPath(int nativeCanvas,
                                                     String text, int path,
                                                     float hOffset,
                                                     float vOffset,
                                                     int flags, int paint) {
        // FIXME
        throw new UnsupportedOperationException();
    }

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

    /*package*/ static void finalizer(int nativeCanvas) {
        // get the delegate from the native int so that it can be disposed.
        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
        if (canvasDelegate == null) {
            assert false;
            return;
        }

        canvasDelegate.dispose();

        // remove it from the manager.
        sManager.removeDelegate(nativeCanvas);
    }

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

    private Canvas_Delegate(BufferedImage image) {
        setBitmap(image);
    }

    private Canvas_Delegate() {
    }

    /**
     * Disposes of the {@link Graphics2D} stack.
     */
    private void dispose() {
        while (mGraphicsStack.size() > 0) {
            mGraphicsStack.pop().dispose();
        }
    }

    private void setBitmap(BufferedImage image) {
        mBufferedImage = image;
        mGraphicsStack.push(mBufferedImage.createGraphics());
    }

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

        // configure it

        if (paint.isAntiAliased()) {
            g.setRenderingHint(
                    RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g.setRenderingHint(
                    RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        }

        boolean useColorPaint = true;

        // get the shader first, as it'll replace the color if it can be used it.
        Shader_Delegate shaderDelegate = Shader_Delegate.getDelegate(paint.getShader());
        if (shaderDelegate != null) {
            java.awt.Paint shaderPaint = shaderDelegate.getJavaPaint();
            if (shaderPaint != null) {
                g.setPaint(shaderPaint);
                useColorPaint = false;
            } else {
                Bridge.getLog().warning(null,
                        String.format(
                            "Shader '%1$s' is not supported in the Layout Preview.",
                            shaderDelegate.getClass().getCanonicalName()));
            }
        }

        if (useColorPaint) {
            g.setColor(new Color(paint.getColor(), true /*hasAlpha*/));
        }

        int style = paint.getStyle();
        if (style == Paint.Style.STROKE.nativeInt ||
                style == Paint.Style.FILL_AND_STROKE.nativeInt) {

            PathEffect_Delegate effectDelegate = PathEffect_Delegate.getDelegate(
                    paint.getPathEffect());

            if (effectDelegate instanceof DashPathEffect_Delegate) {
                DashPathEffect_Delegate dpe = (DashPathEffect_Delegate)effectDelegate;
                g.setStroke(new BasicStroke(
                        paint.getStrokeWidth(),
                        paint.getJavaCap(),
                        paint.getJavaJoin(),
                        paint.getStrokeMiter(),
                        dpe.getIntervals(),
                        dpe.getPhase()));
            } else {
                g.setStroke(new BasicStroke(
                        paint.getStrokeWidth(),
                        paint.getJavaCap(),
                        paint.getJavaJoin(),
                        paint.getStrokeMiter()));
            }
        }

        Xfermode_Delegate xfermodeDelegate = Xfermode_Delegate.getDelegate(paint.getXfermode());
        if (xfermodeDelegate instanceof PorterDuffXfermode_Delegate) {
            int mode = ((PorterDuffXfermode_Delegate)xfermodeDelegate).getMode();

            setModeInGraphics(g, mode);
        } else {
            // default mode is src_over
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));

            // if xfermode wasn't null, then it's something we don't support. log it.
            if (xfermodeDelegate != null) {
                Bridge.getLog().warning(null,
                        String.format(
                            "Xfermode '%1$s' is not supported in the Layout Preview.",
                            xfermodeDelegate.getClass().getCanonicalName()));
            }
        }

        return g;
    }

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

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


    private static void drawBitmap(
            int nativeCanvas,
            BufferedImage image,
            int nativePaintOrZero,
            int sleft, int stop, int sright, int sbottom,
            int dleft, int dtop, int dright, int dbottom) {
        // 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 = null;
        if (nativePaintOrZero > 0) {
            paintDelegate = Paint_Delegate.getDelegate(nativePaintOrZero);
            if (paintDelegate == null) {
                assert false;
                return;
            }
        }

        drawBitmap(canvasDelegate, image, paintDelegate,
                sleft, stop, sright, sbottom,
                dleft, dtop, dright, dbottom);
    }

    private static void drawBitmap(
            Canvas_Delegate canvasDelegate,
            BufferedImage image,
            Paint_Delegate paintDelegate,
            int sleft, int stop, int sright, int sbottom,
            int dleft, int dtop, int dright, int dbottom) {

        Graphics2D g = canvasDelegate.getGraphics2d();

        Composite c = null;

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

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

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

}

