/*
 * Copyright (C) 2016 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.ide.common.rendering.api.LayoutLog;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.layoutlib.bridge.impl.GcSnapshot;
import com.android.layoutlib.bridge.impl.PorterDuffUtility;
import com.android.ninepatch.NinePatchChunk;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;

import android.annotation.Nullable;
import android.text.TextUtils;
import android.util.imagepool.ImagePool;
import android.util.imagepool.ImagePoolProvider;

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Area;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;

public class BaseCanvas_Delegate {
    // ---- delegate manager ----
    protected static DelegateManager<BaseCanvas_Delegate> sManager =
            new DelegateManager<>(BaseCanvas_Delegate.class);

    // ---- delegate helper data ----
    private final static boolean[] sBoolOut = new boolean[1];


    // ---- delegate data ----
    protected Bitmap_Delegate mBitmap;
    protected GcSnapshot mSnapshot;

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

    protected BaseCanvas_Delegate(Bitmap_Delegate bitmap) {
        mSnapshot = GcSnapshot.createDefaultSnapshot(mBitmap = bitmap);
    }

    protected BaseCanvas_Delegate() {
        mSnapshot = GcSnapshot.createDefaultSnapshot(null /*image*/);
    }

    /**
     * Disposes of the {@link Graphics2D} stack.
     */
    protected void dispose() {
        mSnapshot.dispose();
    }

    /**
     * Returns the current {@link Graphics2D} used to draw.
     */
    public GcSnapshot getSnapshot() {
        return mSnapshot;
    }

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

    @LayoutlibDelegate
    /*package*/ static void nDrawBitmap(long nativeCanvas, long bitmapHandle, float left, float top,
            long nativePaintOrZero, int canvasDensity, int screenDensity, int bitmapDensity) {
        // get the delegate from the native int.
        Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmapHandle);
        if (bitmapDelegate == null) {
            return;
        }

        BufferedImage image = bitmapDelegate.getImage();
        float right = left + image.getWidth();
        float bottom = top + image.getHeight();

        drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero,
                0, 0, image.getWidth(), image.getHeight(),
                (int)left, (int)top, (int)right, (int)bottom);
    }

    @LayoutlibDelegate
    /*package*/ static void nDrawBitmap(long nativeCanvas, long bitmapHandle, float srcLeft,
            float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop,
            float dstRight, float dstBottom, long nativePaintOrZero, int screenDensity,
            int bitmapDensity) {
        // get the delegate from the native int.
        Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmapHandle);
        if (bitmapDelegate == null) {
            return;
        }

        drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero, (int) srcLeft, (int) srcTop,
                (int) srcRight, (int) srcBottom, (int) dstLeft, (int) dstTop, (int) dstRight,
                (int) dstBottom);
    }

    @LayoutlibDelegate
    /*package*/ static void nDrawBitmap(long nativeCanvas, int[] colors, int offset, int stride,
            final float x, final float y, int width, int height, boolean hasAlpha,
            long nativePaintOrZero) {
        // create a temp BufferedImage containing the content.
        final ImagePool.Image image = ImagePoolProvider.get().acquire(width, height,
                hasAlpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
        image.setRGB(0, 0, width, height, colors, offset, stride);

        draw(nativeCanvas, nativePaintOrZero, true /*compositeOnly*/, false /*forceSrcMode*/,
                (graphics, paint) -> {
                    if (paint != null && paint.isFilterBitmap()) {
                        graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                    }

                    image.drawImage(graphics, (int) x, (int) y, null);
                });
    }

    @LayoutlibDelegate
    /*package*/ static void nDrawColor(long nativeCanvas, final int color, final int mode) {
        // get the delegate from the native int.
        BaseCanvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
        if (canvasDelegate == null) {
            return;
        }

        final int w = canvasDelegate.mBitmap.getImage().getWidth();
        final int h = canvasDelegate.mBitmap.getImage().getHeight();
        draw(nativeCanvas, (graphics, paint) -> {
            // reset its transform just in case
            graphics.setTransform(new AffineTransform());

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

            Composite composite = PorterDuffUtility.getComposite(
                    PorterDuffUtility.getPorterDuffMode(mode), 0xFF);
            if (composite != null) {
                graphics.setComposite(composite);
            }

            graphics.fillRect(0, 0, w, h);
        });
    }

    @LayoutlibDelegate
    /*package*/ static void nDrawColor(long nativeCanvas, long nativeColorSpace, long color,
            int mode) {
        nDrawColor(nativeCanvas, Color.toArgb(color), mode);
    }

    @LayoutlibDelegate
    /*package*/ static void nDrawPaint(long nativeCanvas, long paint) {
        // FIXME
        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
                "Canvas.drawPaint is not supported.", null,null, null /*data*/);
    }

    @LayoutlibDelegate
    /*package*/ static void nDrawPoint(long nativeCanvas, float x, float y,
            long nativePaint) {
        // TODO: need to support the attribute (e.g. stroke width) of paint
        draw(nativeCanvas, nativePaint, false /*compositeOnly*/, false /*forceSrcMode*/,
                (graphics, paintDelegate) -> graphics.fillRect((int)x, (int)y, 1, 1));
    }

    @LayoutlibDelegate
    /*package*/ static void nDrawPoints(long nativeCanvas, float[] pts, int offset, int count,
            long nativePaint) {
        if (offset < 0 || count < 0 || offset + count > pts.length) {
            throw new IllegalArgumentException("Invalid argument set");
        }
        // ignore the last point if the count is odd (It means it is not paired).
        count = (count >> 1) << 1;
        for (int i = offset; i < offset + count; i += 2) {
            nDrawPoint(nativeCanvas, pts[i], pts[i + 1], nativePaint);
        }
    }

    @LayoutlibDelegate
    /*package*/ static void nDrawLine(long nativeCanvas,
            final float startX, final float startY, final float stopX, final float stopY,
            long paint) {
        draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
                (graphics, paintDelegate) -> graphics.drawLine((int)startX, (int)startY, (int)stopX, (int)stopY));
    }

    @LayoutlibDelegate
    /*package*/ static void nDrawLines(long nativeCanvas,
            final float[] pts, final int offset, final int count,
            long nativePaint) {
        draw(nativeCanvas, nativePaint, false /*compositeOnly*/,
                false /*forceSrcMode*/, (graphics, paintDelegate) -> {
                    for (int i = 0; i < count; i += 4) {
                        graphics.drawLine((int) pts[i + offset], (int) pts[i + offset + 1],
                                (int) pts[i + offset + 2], (int) pts[i + offset + 3]);
                    }
                });
    }

    @LayoutlibDelegate
    /*package*/ static void nDrawRect(long nativeCanvas,
            final float left, final float top, final float right, final float bottom, long paint) {

        draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
                (graphics, paintDelegate) -> {
                    int style = paintDelegate.getStyle();

                    // draw
                    if (style == Paint.Style.FILL.nativeInt ||
                            style == Paint.Style.FILL_AND_STROKE.nativeInt) {
                        graphics.fillRect((int)left, (int)top,
                                (int)(right-left), (int)(bottom-top));
                    }

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

    @LayoutlibDelegate
    /*package*/ static void nDrawOval(long nativeCanvas, final float left,
            final float top, final float right, final float bottom, long paint) {
        if (right > left && bottom > top) {
            draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
                    (graphics, paintDelegate) -> {
                        int style = paintDelegate.getStyle();

                        // draw
                        if (style == Paint.Style.FILL.nativeInt ||
                                style == Paint.Style.FILL_AND_STROKE.nativeInt) {
                            graphics.fillOval((int)left, (int)top,
                                    (int)(right - left), (int)(bottom - top));
                        }

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

    @LayoutlibDelegate
    /*package*/ static void nDrawCircle(long nativeCanvas,
            float cx, float cy, float radius, long paint) {
        nDrawOval(nativeCanvas,
                cx - radius, cy - radius, cx + radius, cy + radius,
                paint);
    }

    @LayoutlibDelegate
    /*package*/ static void nDrawArc(long nativeCanvas,
            final float left, final float top, final float right, final float bottom,
            final float startAngle, final float sweep,
            final boolean useCenter, long paint) {
        if (right > left && bottom > top) {
            draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
                    (graphics, paintDelegate) -> {
                        int style = paintDelegate.getStyle();

                        Arc2D.Float arc = new Arc2D.Float(
                                left, top, right - left, bottom - top,
                                -startAngle, -sweep,
                                useCenter ? Arc2D.PIE : Arc2D.OPEN);

                        // draw
                        if (style == Paint.Style.FILL.nativeInt ||
                                style == Paint.Style.FILL_AND_STROKE.nativeInt) {
                            graphics.fill(arc);
                        }

                        if (style == Paint.Style.STROKE.nativeInt ||
                                style == Paint.Style.FILL_AND_STROKE.nativeInt) {
                            graphics.draw(arc);
                        }
                    });
        }
    }

    @LayoutlibDelegate
    /*package*/ static void nDrawRoundRect(long nativeCanvas,
            final float left, final float top, final float right, final float bottom,
            final float rx, final float ry, long paint) {
        draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
                (graphics, paintDelegate) -> {
                    int style = paintDelegate.getStyle();

                    // draw
                    if (style == Paint.Style.FILL.nativeInt ||
                            style == Paint.Style.FILL_AND_STROKE.nativeInt) {
                        graphics.fillRoundRect(
                                (int)left, (int)top,
                                (int)(right - left), (int)(bottom - top),
                                2 * (int)rx, 2 * (int)ry);
                    }

                    if (style == Paint.Style.STROKE.nativeInt ||
                            style == Paint.Style.FILL_AND_STROKE.nativeInt) {
                        graphics.drawRoundRect(
                                (int)left, (int)top,
                                (int)(right - left), (int)(bottom - top),
                                2 * (int)rx, 2 * (int)ry);
                    }
                });
    }

    @LayoutlibDelegate
    /*package*/ static void nDrawDoubleRoundRect(long nativeCanvas, float outerLeft,
            float outerTop, float outerRight, float outerBottom, float outerRx, float outerRy,
            float innerLeft, float innerTop, float innerRight, float innerBottom, float innerRx,
            float innerRy, long nativePaint) {
        nDrawDoubleRoundRect(nativeCanvas, outerLeft, outerTop, outerRight, outerBottom,
                new float[]{outerRx, outerRy, outerRx, outerRy, outerRx, outerRy, outerRx, outerRy},
                innerLeft, innerTop, innerRight, innerBottom,
                new float[]{innerRx, innerRy, innerRx, innerRy, innerRx, innerRy, innerRx, innerRy},
                nativePaint);
    }

    @LayoutlibDelegate
    /*package*/ static void nDrawDoubleRoundRect(long nativeCanvas, float outerLeft,
            float outerTop, float outerRight, float outerBottom, float[] outerRadii,
            float innerLeft, float innerTop, float innerRight, float innerBottom,
            float[] innerRadii, long nativePaint) {
        draw(nativeCanvas, nativePaint, false /*compositeOnly*/, false /*forceSrcMode*/,
                (graphics, paintDelegate) -> {
                    RoundRectangle innerRect = new RoundRectangle(innerLeft, innerTop,
                            innerRight - innerLeft, innerBottom - innerTop, innerRadii);
                    RoundRectangle outerRect = new RoundRectangle(outerLeft, outerTop,
                            outerRight - outerLeft, outerBottom - outerTop, outerRadii);

                    int style = paintDelegate.getStyle();

                    // draw
                    if (style == Paint.Style.STROKE.nativeInt ||
                            style == Paint.Style.FILL_AND_STROKE.nativeInt) {
                        graphics.draw(innerRect);
                        graphics.draw(outerRect);
                    }

                    if (style == Paint.Style.FILL.nativeInt ||
                            style == Paint.Style.FILL_AND_STROKE.nativeInt) {
                        Area outerArea = new Area(outerRect);
                        Area innerArea = new Area(innerRect);
                        outerArea.subtract(innerArea);
                        graphics.fill(outerArea);
                    }
                });
    }

    @LayoutlibDelegate
    public static void nDrawPath(long nativeCanvas, long path, long paint) {
        final Path_Delegate pathDelegate = Path_Delegate.getDelegate(path);
        if (pathDelegate == null) {
            return;
        }

        draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
                (graphics, paintDelegate) -> {
                    Shape shape = pathDelegate.getJavaShape();
                    Rectangle2D bounds = shape.getBounds2D();
                    if (bounds.isEmpty()) {
                        // Apple JRE 1.6 doesn't like drawing empty shapes.
                        // http://b.android.com/178278

                        if (pathDelegate.isEmpty()) {
                            // This means that the path doesn't have any lines or curves so
                            // nothing to draw.
                            return;
                        }

                        // The stroke width is not consider for the size of the bounds so,
                        // for example, a horizontal line, would be considered as an empty
                        // rectangle.
                        // If the strokeWidth is not 0, we use it to consider the size of the
                        // path as well.
                        float strokeWidth = paintDelegate.getStrokeWidth();
                        if (strokeWidth <= 0.0f) {
                            return;
                        }
                        bounds.setRect(bounds.getX(), bounds.getY(),
                                Math.max(strokeWidth, bounds.getWidth()),
                                Math.max(strokeWidth, bounds.getHeight()));
                    }

                    int style = paintDelegate.getStyle();

                    if (style == Paint.Style.FILL.nativeInt ||
                            style == Paint.Style.FILL_AND_STROKE.nativeInt) {
                        graphics.fill(shape);
                    }

                    if (style == Paint.Style.STROKE.nativeInt ||
                            style == Paint.Style.FILL_AND_STROKE.nativeInt) {
                        graphics.draw(shape);
                    }
                });
    }

    @LayoutlibDelegate
    /*package*/ static void nDrawRegion(long nativeCanvas, long nativeRegion,
            long nativePaint) {
        // FIXME
        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
                "Some canvas paths may not be drawn", null, null, null);
    }

    @LayoutlibDelegate
    /*package*/ static void nDrawNinePatch(long nativeCanvas, long nativeBitmap, long ninePatch,
            final float dstLeft, final float dstTop, final float dstRight, final float dstBottom,
            long nativePaintOrZero, final int screenDensity, final int bitmapDensity) {

        // get the delegate from the native int.
        final Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nativeBitmap);
        if (bitmapDelegate == null) {
            return;
        }

        byte[] c = NinePatch_Delegate.getChunk(ninePatch);
        if (c == null) {
            // not a 9-patch?
            BufferedImage image = bitmapDelegate.getImage();
            drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero, 0, 0, image.getWidth(),
                    image.getHeight(), (int) dstLeft, (int) dstTop, (int) dstRight,
                    (int) dstBottom);
            return;
        }

        final NinePatchChunk chunkObject = NinePatch_Delegate.getChunk(c);
        if (chunkObject == null) {
            return;
        }

        Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
        if (canvasDelegate == null) {
            return;
        }

        // this one can be null
        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nativePaintOrZero);

        canvasDelegate.getSnapshot().draw(new GcSnapshot.Drawable() {
            @Override
            public void draw(Graphics2D graphics, Paint_Delegate paint) {
                chunkObject.draw(bitmapDelegate.getImage(), graphics, (int) dstLeft, (int) dstTop,
                        (int) (dstRight - dstLeft), (int) (dstBottom - dstTop), screenDensity,
                        bitmapDensity);
            }
        }, paintDelegate, true, false);

    }

    @LayoutlibDelegate
    /*package*/ static void nDrawBitmapMatrix(long nCanvas, long bitmapHandle,
            long nMatrix, long nPaint) {
        // get the delegate from the native int.
        BaseCanvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
        if (canvasDelegate == null) {
            return;
        }

        // get the delegate from the native int, which can be null
        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nPaint);

        // get the delegate from the native int.
        Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmapHandle);
        if (bitmapDelegate == null) {
            return;
        }

        final BufferedImage image = getImageToDraw(bitmapDelegate, paintDelegate, sBoolOut);

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

        final AffineTransform mtx = matrixDelegate.getAffineTransform();

        canvasDelegate.getSnapshot().draw((graphics, paint) -> {
            if (paint != null && paint.isFilterBitmap()) {
                graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                        RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            }

            //FIXME add support for canvas, screen and bitmap densities.
            graphics.drawImage(image, mtx, null);
        }, paintDelegate, true /*compositeOnly*/, false /*forceSrcMode*/);
    }

    @LayoutlibDelegate
    /*package*/ static void nDrawBitmapMesh(long nCanvas, long bitmapHandle,
            int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors,
            int colorOffset, long nPaint) {
        // FIXME
        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
                "Canvas.drawBitmapMesh is not supported.", null, null, null /*data*/);
    }

    @LayoutlibDelegate
    /*package*/ static void nDrawVertices(long nCanvas, int mode, int n,
            float[] verts, int vertOffset,
            float[] texs, int texOffset,
            int[] colors, int colorOffset,
            short[] indices, int indexOffset,
            int indexCount, long nPaint) {
        // FIXME
        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
                "Canvas.drawVertices is not supported.", null, null, null /*data*/);
    }

    @LayoutlibDelegate
    /*package*/ static void nDrawText(long nativeCanvas, char[] text, int index, int count,
            float startX, float startY, int flags, long paint) {
        drawText(nativeCanvas, text, index, count, startX, startY, flags,
                paint);
    }

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

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

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

        drawText(nativeCanvas, buffer, 0, count, x, y, isRtl ? Paint.BIDI_RTL : Paint.BIDI_LTR,
                paint);
    }

    @LayoutlibDelegate
    /*package*/ static void nDrawTextRun(long nativeCanvas, char[] text,
            int start, int count, int contextStart, int contextCount,
            float x, float y, boolean isRtl, long paint,
            long nativeMeasuredText) {
        drawText(nativeCanvas, text, start, count, x, y, isRtl ? Paint.BIDI_RTL : Paint.BIDI_LTR, paint);
    }

    @LayoutlibDelegate
    /*package*/ static void nDrawTextOnPath(long nativeCanvas,
            char[] text, int index,
            int count, long path,
            float hOffset,
            float vOffset, int bidiFlags,
            long paint) {
        // FIXME
        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
                "Canvas.drawTextOnPath is not supported.", null, null, null /*data*/);
    }

    @LayoutlibDelegate
    /*package*/ static void nDrawTextOnPath(long nativeCanvas,
            String text, long path,
            float hOffset,
            float vOffset,
            int bidiFlags, long paint) {
        // FIXME
        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
                "Canvas.drawTextOnPath is not supported.", null, null, null /*data*/);
    }

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

    /**
     * Executes a {@link GcSnapshot.Drawable} with a given canvas and paint.
     * <p>Note that the drawable may actually be executed several times if there are
     * layers involved (see {@link #saveLayer(RectF, Paint_Delegate, int)}.
     */
    private static void draw(long nCanvas, long nPaint, boolean compositeOnly, boolean forceSrcMode,
            GcSnapshot.Drawable drawable) {
        // get the delegate from the native int.
        BaseCanvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
        if (canvasDelegate == null) {
            return;
        }

        // get the paint which can be null if nPaint is 0;
        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nPaint);

        canvasDelegate.getSnapshot().draw(drawable, paintDelegate, compositeOnly, forceSrcMode);
    }

    /**
     * Executes a {@link GcSnapshot.Drawable} with a given canvas. No paint object will be provided
     * to {@link GcSnapshot.Drawable#draw(Graphics2D, Paint_Delegate)}.
     * <p>Note that the drawable may actually be executed several times if there are
     * layers involved (see {@link #saveLayer(RectF, Paint_Delegate, int)}.
     */
    private static void draw(long nCanvas, GcSnapshot.Drawable drawable) {
        // get the delegate from the native int.
        BaseCanvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
        if (canvasDelegate == null) {
            return;
        }

        canvasDelegate.mSnapshot.draw(drawable);
    }

    private static void drawText(long nativeCanvas, final char[] text, final int index,
            final int count, final float startX, final float startY, final int bidiFlags,
            long paint) {

        draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
                (graphics, paintDelegate) -> {
                    // WARNING: the logic in this method is similar to Paint_Delegate.measureText.
                    // Any change to this method should be reflected in Paint.measureText

                    // Paint.TextAlign indicates how the text is positioned relative to X.
                    // LEFT is the default and there's nothing to do.
                    float x = startX;
                    int limit = index + count;
                    if (paintDelegate.getTextAlign() != Paint.Align.LEFT.nativeInt) {
                        RectF bounds =
                                paintDelegate.measureText(text, index, count, null, 0, bidiFlags);
                        float m = bounds.right - bounds.left;
                        if (paintDelegate.getTextAlign() == Paint.Align.CENTER.nativeInt) {
                            x -= m / 2;
                        } else if (paintDelegate.getTextAlign() == Paint.Align.RIGHT.nativeInt) {
                            x -= m;
                        }
                    }

                    new BidiRenderer(graphics, paintDelegate, text).setRenderLocation(x,
                            startY).renderText(index, limit, bidiFlags, null, 0, true);
                });
    }

    private static void drawBitmap(long nativeCanvas, Bitmap_Delegate bitmap,
            long nativePaintOrZero, final int sleft, final int stop, final int sright,
            final int sbottom, final int dleft, final int dtop, final int dright,
            final int dbottom) {
        // get the delegate from the native int.
        BaseCanvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
        if (canvasDelegate == null) {
            return;
        }

        // get the paint, which could be null if the int is 0
        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nativePaintOrZero);

        final BufferedImage image = getImageToDraw(bitmap, paintDelegate, sBoolOut);

        draw(nativeCanvas, nativePaintOrZero, true /*compositeOnly*/, sBoolOut[0],
                (graphics, paint) -> {
                    if (paint != null && paint.isFilterBitmap()) {
                        graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                    }

                    //FIXME add support for canvas, screen and bitmap densities.
                    graphics.drawImage(image, dleft, dtop, dright, dbottom, sleft, stop, sright,
                            sbottom, null);
                });
    }

    /**
     * Returns a BufferedImage ready for drawing, based on the bitmap and paint delegate.
     * The image returns, through a 1-size boolean array, whether the drawing code should
     * use a SRC composite no matter what the paint says.
     *
     * @param bitmap the bitmap
     * @param paint the paint that will be used to draw
     * @param forceSrcMode whether the composite will have to be SRC
     * @return the image to draw
     */
    private static BufferedImage getImageToDraw(Bitmap_Delegate bitmap, Paint_Delegate paint,
            boolean[] forceSrcMode) {
        BufferedImage image = bitmap.getImage();
        forceSrcMode[0] = false;

        // if the bitmap config is alpha_8, then we erase all color value from it
        // before drawing it or apply the texture from the shader if present.
        if (bitmap.getConfig() == Bitmap.Config.ALPHA_8) {
            Shader_Delegate shader = paint.getShader();
            java.awt.Paint javaPaint = null;
            if (shader instanceof BitmapShader_Delegate) {
                javaPaint = shader.getJavaPaint();
            }

            fixAlpha8Bitmap(image, javaPaint);
        } else if (!bitmap.hasAlpha()) {
            // hasAlpha is merely a rendering hint. There can in fact be alpha values
            // in the bitmap but it should be ignored at drawing time.
            // There is two ways to do this:
            // - override the composite to be SRC. This can only be used if the composite
            //   was going to be SRC or SRC_OVER in the first place
            // - Create a different bitmap to draw in which all the alpha channel values is set
            //   to 0xFF.
            if (paint != null) {
                PorterDuff.Mode mode = PorterDuff.intToMode(paint.getPorterDuffMode());

                forceSrcMode[0] = mode == PorterDuff.Mode.SRC_OVER || mode == PorterDuff.Mode.SRC;
            }

            // if we can't force SRC mode, then create a temp bitmap of TYPE_RGB
            if (!forceSrcMode[0]) {
                image = Bitmap_Delegate.createCopy(image, BufferedImage.TYPE_INT_RGB, 0xFF);
            }
        }

        return image;
    }

    /**
     * This method will apply the correct color to the passed "only alpha" image. Colors on the
     * passed image will be destroyed.
     * If the passed javaPaint is null, the color will be set to 0. If a paint is passed, it will
     * be used to obtain the color that will be applied.
     * <p/>
     * This will destroy the passed image color channel.
     */
    private static void fixAlpha8Bitmap(final BufferedImage image,
            @Nullable java.awt.Paint javaPaint) {
        int w = image.getWidth();
        int h = image.getHeight();

        DataBuffer texture = null;
        if (javaPaint != null) {
            PaintContext context = javaPaint.createContext(ColorModel.getRGBdefault(), null, null,
                    new AffineTransform(), null);
            texture = context.getRaster(0, 0, w, h).getDataBuffer();
        }

        int[] argb = new int[w * h];
        image.getRGB(0, 0, image.getWidth(), image.getHeight(), argb, 0, image.getWidth());

        final int length = argb.length;
        for (int i = 0; i < length; i++) {
            argb[i] &= 0xFF000000;
            if (texture != null) {
                argb[i] |= texture.getElem(i) & 0x00FFFFFF;
            }
        }

        image.setRGB(0, 0, w, h, argb, 0, w);
    }

    protected int save(int saveFlags) {
        // get the current save count
        int count = mSnapshot.size();

        mSnapshot = mSnapshot.save(saveFlags);

        // return the old save count
        return count;
    }

    protected int saveLayerAlpha(RectF rect, int alpha, int saveFlags) {
        Paint_Delegate paint = new Paint_Delegate();
        paint.setAlpha(alpha);
        return saveLayer(rect, paint, saveFlags);
    }

    protected int saveLayer(RectF rect, Paint_Delegate paint, int saveFlags) {
        // get the current save count
        int count = mSnapshot.size();

        mSnapshot = mSnapshot.saveLayer(rect, paint, saveFlags);

        // return the old save count
        return count;
    }

    /**
     * Restores the {@link GcSnapshot} to <var>saveCount</var>
     * @param saveCount the saveCount
     */
    protected void restoreTo(int saveCount) {
        mSnapshot = mSnapshot.restoreTo(saveCount);
    }

    /**
     * Restores the top {@link GcSnapshot}
     */
    protected void restore() {
        mSnapshot = mSnapshot.restore();
    }

    protected boolean clipRect(float left, float top, float right, float bottom, int regionOp) {
        return mSnapshot.clipRect(left, top, right, bottom, regionOp);
    }
}
