/*
 * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.java2d.pipe;

import java.awt.Font;
import java.awt.Shape;
import java.awt.BasicStroke;
import java.awt.Polygon;
import java.awt.geom.AffineTransform;
import java.awt.geom.PathIterator;
import java.awt.geom.RoundRectangle2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Arc2D;
import java.awt.geom.IllegalPathStateException;
import java.awt.geom.Path2D;
import java.awt.font.GlyphVector;
import sun.java2d.SunGraphics2D;
import sun.java2d.SurfaceData;
import sun.java2d.loops.FontInfo;
import sun.java2d.loops.DrawPolygons;
import sun.awt.SunHints;

public class LoopPipe
    implements PixelDrawPipe,
               PixelFillPipe,
               ShapeDrawPipe,
               LoopBasedPipe
{
    final static RenderingEngine RenderEngine = RenderingEngine.getInstance();

    public void drawLine(SunGraphics2D sg2d,
                         int x1, int y1, int x2, int y2)
    {
        int tX = sg2d.transX;
        int tY = sg2d.transY;
        sg2d.loops.drawLineLoop.DrawLine(sg2d, sg2d.getSurfaceData(),
                                         x1 + tX, y1 + tY,
                                         x2 + tX, y2 + tY);
    }

    public void drawRect(SunGraphics2D sg2d,
                         int x, int y, int width, int height)
    {
        sg2d.loops.drawRectLoop.DrawRect(sg2d, sg2d.getSurfaceData(),
                                         x + sg2d.transX,
                                         y + sg2d.transY,
                                         width, height);
    }

    public void drawRoundRect(SunGraphics2D sg2d,
                              int x, int y, int width, int height,
                              int arcWidth, int arcHeight)
    {
        sg2d.shapepipe.draw(sg2d,
                            new RoundRectangle2D.Float(x, y, width, height,
                                                       arcWidth, arcHeight));
    }

    public void drawOval(SunGraphics2D sg2d,
                         int x, int y, int width, int height)
    {
        sg2d.shapepipe.draw(sg2d, new Ellipse2D.Float(x, y, width, height));
    }

    public void drawArc(SunGraphics2D sg2d,
                        int x, int y, int width, int height,
                        int startAngle, int arcAngle)
    {
        sg2d.shapepipe.draw(sg2d, new Arc2D.Float(x, y, width, height,
                                                  startAngle, arcAngle,
                                                  Arc2D.OPEN));
    }

    public void drawPolyline(SunGraphics2D sg2d,
                             int xPoints[], int yPoints[],
                             int nPoints)
    {
        int nPointsArray[] = { nPoints };
        sg2d.loops.drawPolygonsLoop.DrawPolygons(sg2d, sg2d.getSurfaceData(),
                                                 xPoints, yPoints,
                                                 nPointsArray, 1,
                                                 sg2d.transX, sg2d.transY,
                                                 false);
    }

    public void drawPolygon(SunGraphics2D sg2d,
                            int xPoints[], int yPoints[],
                            int nPoints)
    {
        int nPointsArray[] = { nPoints };
        sg2d.loops.drawPolygonsLoop.DrawPolygons(sg2d, sg2d.getSurfaceData(),
                                                 xPoints, yPoints,
                                                 nPointsArray, 1,
                                                 sg2d.transX, sg2d.transY,
                                                 true);
    }

    public void fillRect(SunGraphics2D sg2d,
                         int x, int y, int width, int height)
    {
        sg2d.loops.fillRectLoop.FillRect(sg2d, sg2d.getSurfaceData(),
                                         x + sg2d.transX,
                                         y + sg2d.transY,
                                         width, height);
    }

    public void fillRoundRect(SunGraphics2D sg2d,
                              int x, int y, int width, int height,
                              int arcWidth, int arcHeight)
    {
        sg2d.shapepipe.fill(sg2d,
                            new RoundRectangle2D.Float(x, y, width, height,
                                                       arcWidth, arcHeight));
    }

    public void fillOval(SunGraphics2D sg2d,
                         int x, int y, int width, int height)
    {
        sg2d.shapepipe.fill(sg2d, new Ellipse2D.Float(x, y, width, height));
    }

    public void fillArc(SunGraphics2D sg2d,
                        int x, int y, int width, int height,
                        int startAngle, int arcAngle)
    {
        sg2d.shapepipe.fill(sg2d, new Arc2D.Float(x, y, width, height,
                                                  startAngle, arcAngle,
                                                  Arc2D.PIE));
    }

    public void fillPolygon(SunGraphics2D sg2d,
                            int xPoints[], int yPoints[],
                            int nPoints)
    {
        ShapeSpanIterator sr = getFillSSI(sg2d);

        try {
            sr.setOutputArea(sg2d.getCompClip());
            sr.appendPoly(xPoints, yPoints, nPoints, sg2d.transX, sg2d.transY);
            fillSpans(sg2d, sr);
        } finally {
            sr.dispose();
        }
    }


    public void draw(SunGraphics2D sg2d, Shape s) {
        if (sg2d.strokeState == sg2d.STROKE_THIN) {
            Path2D.Float p2df;
            int transX;
            int transY;
            if (sg2d.transformState <= sg2d.TRANSFORM_INT_TRANSLATE) {
                if (s instanceof Path2D.Float) {
                    p2df = (Path2D.Float)s;
                } else {
                    p2df = new Path2D.Float(s);
                }
                transX = sg2d.transX;
                transY = sg2d.transY;
            } else {
                p2df = new Path2D.Float(s, sg2d.transform);
                transX = 0;
                transY = 0;
            }
            sg2d.loops.drawPathLoop.DrawPath(sg2d, sg2d.getSurfaceData(),
                                             transX, transY, p2df);
            return;
        }

        if (sg2d.strokeState == sg2d.STROKE_CUSTOM) {
            fill(sg2d, sg2d.stroke.createStrokedShape(s));
            return;
        }

        ShapeSpanIterator sr = getStrokeSpans(sg2d, s);

        try {
            fillSpans(sg2d, sr);
        } finally {
            sr.dispose();
        }
    }

    /**
     * Return a ShapeSpanIterator instance that normalizes as
     * appropriate for a fill operation as per the settings in
     * the specified SunGraphics2D object.
     *
     * The ShapeSpanIterator will be newly constructed and ready
     * to start taking in geometry.
     *
     * Note that the caller is responsible for calling dispose()
     * on the returned ShapeSpanIterator inside a try/finally block:
     * <pre>
     *     ShapeSpanIterator ssi = LoopPipe.getFillSSI(sg2d);
     *     try {
     *         ssi.setOutputArea(clip);
     *         ssi.appendPath(...); // or appendPoly
     *         // iterate the spans from ssi and operate on them
     *     } finally {
     *         ssi.dispose();
     *     }
     * </pre>
     */
    public static ShapeSpanIterator getFillSSI(SunGraphics2D sg2d) {
        boolean adjust = ((sg2d.stroke instanceof BasicStroke) &&
                          sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE);
        return new ShapeSpanIterator(adjust);
    }

    /*
     * Return a ShapeSpanIterator ready to iterate the spans of the wide
     * outline of Shape s using the attributes of the SunGraphics2D
     * object.
     *
     * The ShapeSpanIterator returned will be fully constructed
     * and filled with the geometry from the Shape widened by the
     * appropriate BasicStroke and normalization parameters taken
     * from the SunGraphics2D object and be ready to start returning
     * spans.
     *
     * Note that the caller is responsible for calling dispose()
     * on the returned ShapeSpanIterator inside a try/finally block.
     * <pre>
     *     ShapeSpanIterator ssi = LoopPipe.getStrokeSpans(sg2d, s);
     *     try {
     *         // iterate the spans from ssi and operate on them
     *     } finally {
     *         ssi.dispose();
     *     }
     * </pre>
     *
     * REMIND: This should return a SpanIterator interface object
     * but the caller needs to dispose() the object and that method
     * is only on ShapeSpanIterator.
     * TODO: Add a dispose() method to the SpanIterator interface.
     */
    public static ShapeSpanIterator getStrokeSpans(SunGraphics2D sg2d,
                                                   Shape s)
    {
        ShapeSpanIterator sr = new ShapeSpanIterator(false);

        try {
            sr.setOutputArea(sg2d.getCompClip());
            sr.setRule(PathIterator.WIND_NON_ZERO);

            BasicStroke bs = (BasicStroke) sg2d.stroke;
            boolean thin = (sg2d.strokeState <= sg2d.STROKE_THINDASHED);
            boolean normalize =
                (sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE);

            RenderEngine.strokeTo(s,
                                  sg2d.transform, bs,
                                  thin, normalize, false, sr);
        } catch (Throwable t) {
            sr.dispose();
            sr = null;
            t.printStackTrace();
            throw new InternalError("Unable to Stroke shape ("+
                                    t.getMessage()+")");
        }
        return sr;
    }

    public void fill(SunGraphics2D sg2d, Shape s) {
        if (sg2d.strokeState == sg2d.STROKE_THIN) {
            Path2D.Float p2df;
            int transX;
            int transY;
            if (sg2d.transformState <= sg2d.TRANSFORM_INT_TRANSLATE) {
                if (s instanceof Path2D.Float) {
                    p2df = (Path2D.Float)s;
                } else {
                    p2df = new Path2D.Float(s);
                }
                transX = sg2d.transX;
                transY = sg2d.transY;
            } else {
                p2df = new Path2D.Float(s, sg2d.transform);
                transX = 0;
                transY = 0;
            }
            sg2d.loops.fillPathLoop.FillPath(sg2d, sg2d.getSurfaceData(),
                                             transX, transY, p2df);
            return;
        }

        ShapeSpanIterator sr = getFillSSI(sg2d);
        try {
            sr.setOutputArea(sg2d.getCompClip());
            AffineTransform at =
                ((sg2d.transformState == sg2d.TRANSFORM_ISIDENT)
                 ? null
                 : sg2d.transform);
            sr.appendPath(s.getPathIterator(at));
            fillSpans(sg2d, sr);
        } finally {
            sr.dispose();
        }
    }

    private static void fillSpans(SunGraphics2D sg2d, SpanIterator si) {
        // REMIND: Eventually, the plan is that it will not be possible for
        // fs to be null since the FillSpans loop will be the fundamental
        // loop implemented for any destination type...
        if (sg2d.clipState == sg2d.CLIP_SHAPE) {
            si = sg2d.clipRegion.filter(si);
            // REMIND: Region.filter produces a Java-only iterator
            // with no native counterpart...
        } else {
            sun.java2d.loops.FillSpans fs = sg2d.loops.fillSpansLoop;
            if (fs != null) {
                fs.FillSpans(sg2d, sg2d.getSurfaceData(), si);
                return;
            }
        }
        int spanbox[] = new int[4];
        SurfaceData sd = sg2d.getSurfaceData();
        while (si.nextSpan(spanbox)) {
            int x = spanbox[0];
            int y = spanbox[1];
            int w = spanbox[2] - x;
            int h = spanbox[3] - y;
            sg2d.loops.fillRectLoop.FillRect(sg2d, sd, x, y, w, h);
        }
    }
}
