/*
 * 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.ide.common.rendering.api.LayoutLog;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;

import android.annotation.NonNull;
import android.graphics.Path.Direction;
import android.graphics.Path.FillType;

import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Path2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.util.ArrayList;

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

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

    private static final float EPSILON = 1e-4f;

    // ---- delegate data ----
    private FillType mFillType = FillType.WINDING;
    private Path2D mPath = new Path2D.Double();

    private float mLastX = 0;
    private float mLastY = 0;

    // true if the path contains does not contain a curve or line.
    private boolean mCachedIsEmpty = true;

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

    public static Path_Delegate getDelegate(long nPath) {
        return sManager.getDelegate(nPath);
    }

    public Path2D getJavaShape() {
        return mPath;
    }

    public void setJavaShape(Shape shape) {
        reset();
        mPath.append(shape, false /*connect*/);
    }

    public void reset() {
        mPath.reset();
    }

    public void setPathIterator(PathIterator iterator) {
        reset();
        mPath.append(iterator, false /*connect*/);
    }

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

    @LayoutlibDelegate
    /*package*/ static long init1() {
        // create the delegate
        Path_Delegate newDelegate = new Path_Delegate();

        return sManager.addNewDelegate(newDelegate);
    }

    @LayoutlibDelegate
    /*package*/ static long init2(long nPath) {
        // create the delegate
        Path_Delegate newDelegate = new Path_Delegate();

        // get the delegate to copy, which could be null if nPath is 0
        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate != null) {
            newDelegate.set(pathDelegate);
        }

        return sManager.addNewDelegate(newDelegate);
    }

    @LayoutlibDelegate
    /*package*/ static void native_reset(long nPath) {
        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate == null) {
            return;
        }

        pathDelegate.mPath.reset();
    }

    @LayoutlibDelegate
    /*package*/ static void native_rewind(long nPath) {
        // call out to reset since there's nothing to optimize in
        // terms of data structs.
        native_reset(nPath);
    }

    @LayoutlibDelegate
    /*package*/ static void native_set(long native_dst, long native_src) {
        Path_Delegate pathDstDelegate = sManager.getDelegate(native_dst);
        if (pathDstDelegate == null) {
            return;
        }

        Path_Delegate pathSrcDelegate = sManager.getDelegate(native_src);
        if (pathSrcDelegate == null) {
            return;
        }

        pathDstDelegate.set(pathSrcDelegate);
    }

    @LayoutlibDelegate
    /*package*/ static boolean native_isConvex(long nPath) {
        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
                "Path.isConvex is not supported.", null, null);
        return true;
    }

    @LayoutlibDelegate
    /*package*/ static int native_getFillType(long nPath) {
        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate == null) {
            return 0;
        }

        return pathDelegate.mFillType.nativeInt;
    }

    @LayoutlibDelegate
    public static void native_setFillType(long nPath, int ft) {
        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate == null) {
            return;
        }

        pathDelegate.setFillType(Path.sFillTypeArray[ft]);
    }

    @LayoutlibDelegate
    /*package*/ static boolean native_isEmpty(long nPath) {
        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        return pathDelegate == null || pathDelegate.isEmpty();

    }

    @LayoutlibDelegate
    /*package*/ static boolean native_isRect(long nPath, RectF rect) {
        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate == null) {
            return false;
        }

        // create an Area that can test if the path is a rect
        Area area = new Area(pathDelegate.mPath);
        if (area.isRectangular()) {
            if (rect != null) {
                pathDelegate.fillBounds(rect);
            }

            return true;
        }

        return false;
    }

    @LayoutlibDelegate
    /*package*/ static void native_computeBounds(long nPath, RectF bounds) {
        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate == null) {
            return;
        }

        pathDelegate.fillBounds(bounds);
    }

    @LayoutlibDelegate
    /*package*/ static void native_incReserve(long nPath, int extraPtCount) {
        // since we use a java2D path, there's no way to pre-allocate new points,
        // so we do nothing.
    }

    @LayoutlibDelegate
    /*package*/ static void native_moveTo(long nPath, float x, float y) {
        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate == null) {
            return;
        }

        pathDelegate.moveTo(x, y);
    }

    @LayoutlibDelegate
    /*package*/ static void native_rMoveTo(long nPath, float dx, float dy) {
        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate == null) {
            return;
        }

        pathDelegate.rMoveTo(dx, dy);
    }

    @LayoutlibDelegate
    /*package*/ static void native_lineTo(long nPath, float x, float y) {
        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate == null) {
            return;
        }

        pathDelegate.lineTo(x, y);
    }

    @LayoutlibDelegate
    /*package*/ static void native_rLineTo(long nPath, float dx, float dy) {
        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate == null) {
            return;
        }

        pathDelegate.rLineTo(dx, dy);
    }

    @LayoutlibDelegate
    /*package*/ static void native_quadTo(long nPath, float x1, float y1, float x2, float y2) {
        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate == null) {
            return;
        }

        pathDelegate.quadTo(x1, y1, x2, y2);
    }

    @LayoutlibDelegate
    /*package*/ static void native_rQuadTo(long nPath, float dx1, float dy1, float dx2, float dy2) {
        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate == null) {
            return;
        }

        pathDelegate.rQuadTo(dx1, dy1, dx2, dy2);
    }

    @LayoutlibDelegate
    /*package*/ static void native_cubicTo(long nPath, float x1, float y1,
            float x2, float y2, float x3, float y3) {
        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate == null) {
            return;
        }

        pathDelegate.cubicTo(x1, y1, x2, y2, x3, y3);
    }

    @LayoutlibDelegate
    /*package*/ static void native_rCubicTo(long nPath, float x1, float y1,
            float x2, float y2, float x3, float y3) {
        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate == null) {
            return;
        }

        pathDelegate.rCubicTo(x1, y1, x2, y2, x3, y3);
    }

    @LayoutlibDelegate
    /*package*/ static void native_arcTo(long nPath, float left, float top, float right,
            float bottom,
                    float startAngle, float sweepAngle, boolean forceMoveTo) {
        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate == null) {
            return;
        }

        pathDelegate.arcTo(left, top, right, bottom, startAngle, sweepAngle, forceMoveTo);
    }

    @LayoutlibDelegate
    /*package*/ static void native_close(long nPath) {
        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate == null) {
            return;
        }

        pathDelegate.close();
    }

    @LayoutlibDelegate
    /*package*/ static void native_addRect(long nPath,
            float left, float top, float right, float bottom, int dir) {
        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate == null) {
            return;
        }

        pathDelegate.addRect(left, top, right, bottom, dir);
    }

    @LayoutlibDelegate
    /*package*/ static void native_addOval(long nPath, float left, float top, float right,
            float bottom, int dir) {
        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate == null) {
            return;
        }

        pathDelegate.mPath.append(new Ellipse2D.Float(
                left, top, right - left, bottom - top), false);
    }

    @LayoutlibDelegate
    /*package*/ static void native_addCircle(long nPath, float x, float y, float radius, int dir) {
        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate == null) {
            return;
        }

        // because x/y is the center of the circle, need to offset this by the radius
        pathDelegate.mPath.append(new Ellipse2D.Float(
                x - radius, y - radius, radius * 2, radius * 2), false);
    }

    @LayoutlibDelegate
    /*package*/ static void native_addArc(long nPath, float left, float top, float right,
            float bottom, float startAngle, float sweepAngle) {
        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate == null) {
            return;
        }

        // because x/y is the center of the circle, need to offset this by the radius
        pathDelegate.mPath.append(new Arc2D.Float(
                left, top, right - left, bottom - top,
                -startAngle, -sweepAngle, Arc2D.OPEN), false);
    }

    @LayoutlibDelegate
    /*package*/ static void native_addRoundRect(long nPath, float left, float top, float right,
            float bottom, float rx, float ry, int dir) {

        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate == null) {
            return;
        }

        pathDelegate.mPath.append(new RoundRectangle2D.Float(
                left, top, right - left, bottom - top, rx * 2, ry * 2), false);
    }

    @LayoutlibDelegate
    /*package*/ static void native_addRoundRect(long nPath, float left, float top, float right,
            float bottom, float[] radii, int dir) {

        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate == null) {
            return;
        }

        float[] cornerDimensions = new float[radii.length];
        for (int i = 0; i < radii.length; i++) {
            cornerDimensions[i] = 2 * radii[i];
        }
        pathDelegate.mPath.append(new RoundRectangle(left, top, right - left, bottom - top,
                cornerDimensions), false);
    }

    @LayoutlibDelegate
    /*package*/ static void native_addPath(long nPath, long src, float dx, float dy) {
        addPath(nPath, src, AffineTransform.getTranslateInstance(dx, dy));
    }

    @LayoutlibDelegate
    /*package*/ static void native_addPath(long nPath, long src) {
        addPath(nPath, src, null /*transform*/);
    }

    @LayoutlibDelegate
    /*package*/ static void native_addPath(long nPath, long src, long matrix) {
        Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(matrix);
        if (matrixDelegate == null) {
            return;
        }

        addPath(nPath, src, matrixDelegate.getAffineTransform());
    }

    @LayoutlibDelegate
    /*package*/ static void native_offset(long nPath, float dx, float dy, long dst_path) {
        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate == null) {
            return;
        }

        // could be null if the int is 0;
        Path_Delegate dstDelegate = sManager.getDelegate(dst_path);

        pathDelegate.offset(dx, dy, dstDelegate);
    }

    @LayoutlibDelegate
    /*package*/ static void native_offset(long nPath, float dx, float dy) {
        native_offset(nPath, dx, dy, 0);
    }

    @LayoutlibDelegate
    /*package*/ static void native_setLastPoint(long nPath, float dx, float dy) {
        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate == null) {
            return;
        }

        pathDelegate.mLastX = dx;
        pathDelegate.mLastY = dy;
    }

    @LayoutlibDelegate
    /*package*/ static void native_transform(long nPath, long matrix,
                                                long dst_path) {
        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate == null) {
            return;
        }

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

        // this can be null if dst_path is 0
        Path_Delegate dstDelegate = sManager.getDelegate(dst_path);

        pathDelegate.transform(matrixDelegate, dstDelegate);
    }

    @LayoutlibDelegate
    /*package*/ static void native_transform(long nPath, long matrix) {
        native_transform(nPath, matrix, 0);
    }

    @LayoutlibDelegate
    /*package*/ static boolean native_op(long nPath1, long nPath2, int op, long result) {
        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, "Path.op() not supported", null);
        return false;
    }

    @LayoutlibDelegate
    /*package*/ static void finalizer(long nPath) {
        sManager.removeJavaReferenceFor(nPath);
    }

    @LayoutlibDelegate
    /*package*/ static float[] native_approximate(long nPath, float error) {
        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
        if (pathDelegate == null) {
            return null;
        }
        // Get a FlatteningIterator
        PathIterator iterator = pathDelegate.getJavaShape().getPathIterator(null, error);

        float segment[] = new float[6];
        float totalLength = 0;
        ArrayList<Point2D.Float> points = new ArrayList<Point2D.Float>();
        Point2D.Float previousPoint = null;
        while (!iterator.isDone()) {
            int type = iterator.currentSegment(segment);
            Point2D.Float currentPoint = new Point2D.Float(segment[0], segment[1]);
            // MoveTo shouldn't affect the length
            if (previousPoint != null && type != PathIterator.SEG_MOVETO) {
                totalLength += currentPoint.distance(previousPoint);
            }
            previousPoint = currentPoint;
            points.add(currentPoint);
            iterator.next();
        }

        int nPoints = points.size();
        float[] result = new float[nPoints * 3];
        previousPoint = null;
        for (int i = 0; i < nPoints; i++) {
            Point2D.Float point = points.get(i);
            float distance = previousPoint != null ? (float) previousPoint.distance(point) : .0f;
            result[i * 3] = distance / totalLength;
            result[i * 3 + 1] = point.x;
            result[i * 3 + 2] = point.y;

            totalLength += distance;
            previousPoint = point;
        }

        return result;
    }

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

    private void set(Path_Delegate delegate) {
        mPath.reset();
        setFillType(delegate.mFillType);
        mPath.append(delegate.mPath, false /*connect*/);
    }

    private void setFillType(FillType fillType) {
        mFillType = fillType;
        mPath.setWindingRule(getWindingRule(fillType));
    }

    /**
     * Returns the Java2D winding rules matching a given Android {@link FillType}.
     * @param type the android fill type
     * @return the matching java2d winding rule.
     */
    private static int getWindingRule(FillType type) {
        switch (type) {
            case WINDING:
            case INVERSE_WINDING:
                return GeneralPath.WIND_NON_ZERO;
            case EVEN_ODD:
            case INVERSE_EVEN_ODD:
                return GeneralPath.WIND_EVEN_ODD;
        }

        assert false;
        throw new IllegalArgumentException();
    }

    @NonNull
    private static Direction getDirection(int direction) {
        for (Direction d : Direction.values()) {
            if (direction == d.nativeInt) {
                return d;
            }
        }

        assert false;
        return null;
    }

    public static void addPath(long destPath, long srcPath, AffineTransform transform) {
        Path_Delegate destPathDelegate = sManager.getDelegate(destPath);
        if (destPathDelegate == null) {
            return;
        }

        Path_Delegate srcPathDelegate = sManager.getDelegate(srcPath);
        if (srcPathDelegate == null) {
            return;
        }

        if (transform != null) {
            destPathDelegate.mPath.append(
                    srcPathDelegate.mPath.getPathIterator(transform), false);
        } else {
            destPathDelegate.mPath.append(srcPathDelegate.mPath, false);
        }
    }


    /**
     * Returns whether the path already contains any points.
     * Note that this is different to
     * {@link #isEmpty} because if all elements are {@link PathIterator#SEG_MOVETO},
     * {@link #isEmpty} will return true while hasPoints will return false.
     */
    public boolean hasPoints() {
        return !mPath.getPathIterator(null).isDone();
    }

    /**
     * Returns whether the path is empty (contains no lines or curves).
     * @see Path#isEmpty
     */
    public boolean isEmpty() {
        if (!mCachedIsEmpty) {
            return false;
        }

        float[] coords = new float[6];
        mCachedIsEmpty = Boolean.TRUE;
        for (PathIterator it = mPath.getPathIterator(null); !it.isDone(); it.next()) {
            int type = it.currentSegment(coords);
            if (type != PathIterator.SEG_MOVETO) {
                // Once we know that the path is not empty, we do not need to check again unless
                // Path#reset is called.
                mCachedIsEmpty = false;
                return false;
            }
        }

        return true;
    }

    /**
     * Fills the given {@link RectF} with the path bounds.
     * @param bounds the RectF to be filled.
     */
    public void fillBounds(RectF bounds) {
        Rectangle2D rect = mPath.getBounds2D();
        bounds.left = (float)rect.getMinX();
        bounds.right = (float)rect.getMaxX();
        bounds.top = (float)rect.getMinY();
        bounds.bottom = (float)rect.getMaxY();
    }

    /**
     * Set the beginning of the next contour to the point (x,y).
     *
     * @param x The x-coordinate of the start of a new contour
     * @param y The y-coordinate of the start of a new contour
     */
    public void moveTo(float x, float y) {
        mPath.moveTo(mLastX = x, mLastY = y);
    }

    /**
     * Set the beginning of the next contour relative to the last point on the
     * previous contour. If there is no previous contour, this is treated the
     * same as moveTo().
     *
     * @param dx The amount to add to the x-coordinate of the end of the
     *           previous contour, to specify the start of a new contour
     * @param dy The amount to add to the y-coordinate of the end of the
     *           previous contour, to specify the start of a new contour
     */
    public void rMoveTo(float dx, float dy) {
        dx += mLastX;
        dy += mLastY;
        mPath.moveTo(mLastX = dx, mLastY = dy);
    }

    /**
     * Add a line from the last point to the specified point (x,y).
     * If no moveTo() call has been made for this contour, the first point is
     * automatically set to (0,0).
     *
     * @param x The x-coordinate of the end of a line
     * @param y The y-coordinate of the end of a line
     */
    public void lineTo(float x, float y) {
        if (!hasPoints()) {
            mPath.moveTo(mLastX = 0, mLastY = 0);
        }
        mPath.lineTo(mLastX = x, mLastY = y);
    }

    /**
     * Same as lineTo, but the coordinates are considered relative to the last
     * point on this contour. If there is no previous point, then a moveTo(0,0)
     * is inserted automatically.
     *
     * @param dx The amount to add to the x-coordinate of the previous point on
     *           this contour, to specify a line
     * @param dy The amount to add to the y-coordinate of the previous point on
     *           this contour, to specify a line
     */
    public void rLineTo(float dx, float dy) {
        if (!hasPoints()) {
            mPath.moveTo(mLastX = 0, mLastY = 0);
        }

        if (Math.abs(dx) < EPSILON && Math.abs(dy) < EPSILON) {
            // The delta is so small that this shouldn't generate a line
            return;
        }

        dx += mLastX;
        dy += mLastY;
        mPath.lineTo(mLastX = dx, mLastY = dy);
    }

    /**
     * Add a quadratic bezier from the last point, approaching control point
     * (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for
     * this contour, the first point is automatically set to (0,0).
     *
     * @param x1 The x-coordinate of the control point on a quadratic curve
     * @param y1 The y-coordinate of the control point on a quadratic curve
     * @param x2 The x-coordinate of the end point on a quadratic curve
     * @param y2 The y-coordinate of the end point on a quadratic curve
     */
    public void quadTo(float x1, float y1, float x2, float y2) {
        mPath.quadTo(x1, y1, mLastX = x2, mLastY = y2);
    }

    /**
     * Same as quadTo, but the coordinates are considered relative to the last
     * point on this contour. If there is no previous point, then a moveTo(0,0)
     * is inserted automatically.
     *
     * @param dx1 The amount to add to the x-coordinate of the last point on
     *            this contour, for the control point of a quadratic curve
     * @param dy1 The amount to add to the y-coordinate of the last point on
     *            this contour, for the control point of a quadratic curve
     * @param dx2 The amount to add to the x-coordinate of the last point on
     *            this contour, for the end point of a quadratic curve
     * @param dy2 The amount to add to the y-coordinate of the last point on
     *            this contour, for the end point of a quadratic curve
     */
    public void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
        if (!hasPoints()) {
            mPath.moveTo(mLastX = 0, mLastY = 0);
        }
        dx1 += mLastX;
        dy1 += mLastY;
        dx2 += mLastX;
        dy2 += mLastY;
        mPath.quadTo(dx1, dy1, mLastX = dx2, mLastY = dy2);
    }

    /**
     * Add a cubic bezier from the last point, approaching control points
     * (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been
     * made for this contour, the first point is automatically set to (0,0).
     *
     * @param x1 The x-coordinate of the 1st control point on a cubic curve
     * @param y1 The y-coordinate of the 1st control point on a cubic curve
     * @param x2 The x-coordinate of the 2nd control point on a cubic curve
     * @param y2 The y-coordinate of the 2nd control point on a cubic curve
     * @param x3 The x-coordinate of the end point on a cubic curve
     * @param y3 The y-coordinate of the end point on a cubic curve
     */
    public void cubicTo(float x1, float y1, float x2, float y2,
                        float x3, float y3) {
        if (!hasPoints()) {
            mPath.moveTo(0, 0);
        }
        mPath.curveTo(x1, y1, x2, y2, mLastX = x3, mLastY = y3);
    }

    /**
     * Same as cubicTo, but the coordinates are considered relative to the
     * current point on this contour. If there is no previous point, then a
     * moveTo(0,0) is inserted automatically.
     */
    public void rCubicTo(float dx1, float dy1, float dx2, float dy2,
                         float dx3, float dy3) {
        if (!hasPoints()) {
            mPath.moveTo(mLastX = 0, mLastY = 0);
        }
        dx1 += mLastX;
        dy1 += mLastY;
        dx2 += mLastX;
        dy2 += mLastY;
        dx3 += mLastX;
        dy3 += mLastY;
        mPath.curveTo(dx1, dy1, dx2, dy2, mLastX = dx3, mLastY = dy3);
    }

    /**
     * Append the specified arc to the path as a new contour. If the start of
     * the path is different from the path's current last point, then an
     * automatic lineTo() is added to connect the current contour to the
     * start of the arc. However, if the path is empty, then we call moveTo()
     * with the first point of the arc. The sweep angle is tread mod 360.
     *
     * @param left        The left of oval defining shape and size of the arc
     * @param top         The top of oval defining shape and size of the arc
     * @param right       The right of oval defining shape and size of the arc
     * @param bottom      The bottom of oval defining shape and size of the arc
     * @param startAngle  Starting angle (in degrees) where the arc begins
     * @param sweepAngle  Sweep angle (in degrees) measured clockwise, treated
     *                    mod 360.
     * @param forceMoveTo If true, always begin a new contour with the arc
     */
    public void arcTo(float left, float top, float right, float bottom, float startAngle,
            float sweepAngle,
            boolean forceMoveTo) {
        Arc2D arc = new Arc2D.Float(left, top, right - left, bottom - top, -startAngle,
                -sweepAngle, Arc2D.OPEN);
        mPath.append(arc, true /*connect*/);

        resetLastPointFromPath();
    }

    /**
     * Close the current contour. If the current point is not equal to the
     * first point of the contour, a line segment is automatically added.
     */
    public void close() {
        mPath.closePath();
    }

    private void resetLastPointFromPath() {
        Point2D last = mPath.getCurrentPoint();
        mLastX = (float) last.getX();
        mLastY = (float) last.getY();
    }

    /**
     * Add a closed rectangle contour to the path
     *
     * @param left   The left side of a rectangle to add to the path
     * @param top    The top of a rectangle to add to the path
     * @param right  The right side of a rectangle to add to the path
     * @param bottom The bottom of a rectangle to add to the path
     * @param dir    The direction to wind the rectangle's contour
     */
    public void addRect(float left, float top, float right, float bottom,
                        int dir) {
        moveTo(left, top);

        Direction direction = getDirection(dir);

        switch (direction) {
            case CW:
                lineTo(right, top);
                lineTo(right, bottom);
                lineTo(left, bottom);
                break;
            case CCW:
                lineTo(left, bottom);
                lineTo(right, bottom);
                lineTo(right, top);
                break;
        }

        close();

        resetLastPointFromPath();
    }

    /**
     * Offset the path by (dx,dy), returning true on success
     *
     * @param dx  The amount in the X direction to offset the entire path
     * @param dy  The amount in the Y direction to offset the entire path
     * @param dst The translated path is written here. If this is null, then
     *            the original path is modified.
     */
    public void offset(float dx, float dy, Path_Delegate dst) {
        GeneralPath newPath = new GeneralPath();

        PathIterator iterator = mPath.getPathIterator(new AffineTransform(0, 0, dx, 0, 0, dy));

        newPath.append(iterator, false /*connect*/);

        if (dst != null) {
            dst.mPath = newPath;
        } else {
            mPath = newPath;
        }
    }

    /**
     * Transform the points in this path by matrix, and write the answer
     * into dst. If dst is null, then the the original path is modified.
     *
     * @param matrix The matrix to apply to the path
     * @param dst    The transformed path is written here. If dst is null,
     *               then the the original path is modified
     */
    public void transform(Matrix_Delegate matrix, Path_Delegate dst) {
        if (matrix.hasPerspective()) {
            assert false;
            Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_AFFINE,
                    "android.graphics.Path#transform() only " +
                    "supports affine transformations.", null, null /*data*/);
        }

        GeneralPath newPath = new GeneralPath();

        PathIterator iterator = mPath.getPathIterator(matrix.getAffineTransform());

        newPath.append(iterator, false /*connect*/);

        if (dst != null) {
            dst.mPath = newPath;
        } else {
            mPath = newPath;
        }
    }
}
