/* ScanlineConverter.java -- Rasterizes Shapes
   Copyright (C) 2006, 2007 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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 for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package gnu.java.awt.java2d;

import gnu.java.math.Fixed;

import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.PathIterator;

/**
 * Rasterizes {@link Shape} objects on an AbstractGraphics2D.
 */
public final class ScanlineConverter
{

  /**
   * The number of digits to use for fixed point arithmetics.
   */
  private static int FIXED_DIGITS = 6;

  /**
   * The fixed point constant for the number one.
   */
  private static int ONE = Fixed.fixedValue(FIXED_DIGITS, 1);

  /**
   * The actual number of scanlines.
   */
  private int numScanlines;

  /**
   * The number of scanlines. This can contain more elements than we have
   * scanlines. The real number of scanlines is stored in
   * {@link #numScanlines}. This can also contain null values for empty
   * scanlines.
   */
  private Scanline[] scanlines;

  /**
   * The upper bounds which correspond to the index 0 in the scanline array.
   *
   * This is a fixed point value.
   */
  private int upperBounds;

  /**
   * The resolution of the scanline converter.
   *
   * This is a fixed point value.
   */
  private int resolution;

  /**
   * The number of significant bits for the 'Y' resolution.
   */
  private int yResolution;

  /**
   * One half step according to the resolution. This is stored to avoid
   * unnecessary operations during rendering.
   */
  private int halfStep;

  /**
   * This is used in {@link #addShape(PathIterator, boolean)} to
   * receive the coordinates of the path.
   */
  private float[] coords;

  /**
   * The active edges.
   */
  private ActiveEdges activeEdges;

  private PolyEdge edgePool;
  private PolyEdge edgePoolLast;

  private int minY;
  private int maxY;
  private int minX;
  private int maxX;

  /**
   * Holds and manages information about the pixel coverage.
   */
  private ScanlineCoverage scanlineCoverage;

  /**
   * Create a new ScanlineConverter.
   */
  ScanlineConverter()
  {
    scanlines = new Scanline[10];
    coords = new float[6];
    activeEdges = new ActiveEdges();
    edgePool = new PolyEdge();
    edgePoolLast = edgePool;
    scanlineCoverage = new ScanlineCoverage();
  }

  /**
   * Renders the specified shape using the specified clip and transform.
   *
   * @param p the pixelizer that receives the coverage information
   * @param shape the shape to render
   * @param clip the clip
   * @param trans the transform
   */
  public void renderShape(Pixelizer p, Shape shape, Shape clip,
                          AffineTransform trans, int res, int yRes,
                          RenderingHints hints)
  {
    // TODO: Do something useful with the rendering hints. Like, adjusting
    // the resolution.

    // Prepare resolution and upper bounds.
    clear();
    setResolution(res, yRes);

    boolean haveClip = clip != null;

    // Add shapes.
    float flatness = Fixed.floatValue(FIXED_DIGITS, resolution / 2);
    PathIterator path = shape.getPathIterator(trans, flatness);
    addShape(path, false);
    if (haveClip)
      {
        path= clip.getPathIterator(trans, flatness);
        addShape(path, true);
      }

    setUpperBounds(minY);

    PolyEdge edge = edgePool;
    while (edge != edgePoolLast)
      {
        addEdge(edge);
        edge = edge.poolNext;
      }

    int y = upperBounds;
    int index;
    activeEdges.clear();
    // The render loop...
    Scanline scanline = null;
    int lastRealY = Fixed.intValue(FIXED_DIGITS, y);
    while (y <= maxY)
      {
        // First we put together our list of active edges.
        index = scanlineIndex(y);
        // If we go outside the scanline array we still need to render the
        // remaining edges until they end.
        scanline = index < scanlines.length ? scanlines[index] : null;
        if (scanline != null)
          {
            edge = scanline.getEdges();
            while (edge != null)
              {
                activeEdges.add(edge);
                edge = edge.scanlineNext;
              }
          }

        // Then we intersect all active edges with the current scanline
        // and sort them according to their intersection points.
        activeEdges.intersectSortAndPack(FIXED_DIGITS, y + halfStep);

        // Ok, now we can perform the actual scanlining.
        int realY = Fixed.intValue(FIXED_DIGITS, y + resolution);
        boolean push = lastRealY != realY;
        
        doScanline(p, y, push, haveClip);

        // Remove obsolete active edges.
        //activeEdges.remove(y + halfStep);
        // Go on with the next line...
        y += resolution;
        lastRealY = realY;

      }
  }

  /**
   * Clears all scanlines.
   */
  private void clear()
  {
    // Reset edge pool.
    edgePoolLast = edgePool;

    // Reset scanlines.
    for (int i = scanlines.length - 1; i >= 0 ; i--)
      {
        Scanline sl = scanlines[i];
        if (sl != null)
          sl.clear();
      }

    // Reset scanline coverage.
    scanlineCoverage.clear();

    // Reset bounds.
    minY = Integer.MAX_VALUE;
    maxY = Integer.MIN_VALUE;
    minX = Integer.MAX_VALUE;
    maxX = Integer.MIN_VALUE;
  }

  /**
   * Performs the scanlining on the current set of active edges.
   *
   * @param p the pixelizer to receive the pixel coverage data
   * @param y the Y coordinate
   * @param push true when the scanline is ready to be pushed to the
   *        pixelizer
   * @param haveClip true when there's a clip, false otherwise
   */
  private void doScanline(Pixelizer p, int y, boolean push,
                          boolean haveClip)
  {
    // First, rewind the scanline coverage.
    scanlineCoverage.rewind();

    // We begin outside the clip and outside the shape. We only draw when
    // we are inside the clip AND inside the shape.
    boolean inClip = ! haveClip;
    boolean inShape = false;
    PolyEdge lastEdge = null;
    int numEdges = activeEdges.getNumActiveEdges();
    for (int i = 0; i < numEdges; i++)
      {
        PolyEdge edge = activeEdges.getActiveEdge(i);
        if (inClip && inShape)
          {
            assert lastEdge != null;
            int x0 = lastEdge.xIntersection;
            int x1 = edge.xIntersection;
            assert x0 <= x1;

            int pix0 = Fixed.intValue(FIXED_DIGITS, x0);
            int pix1 = Fixed.intValue(FIXED_DIGITS, x1);
            int frac0 = ONE - Fixed.trunc(FIXED_DIGITS, x0);
            int frac1 = ONE - Fixed.trunc(FIXED_DIGITS, x1);
            // Only keep the first 4 digits after the point.
            frac0 = frac0 >> (FIXED_DIGITS - yResolution);
            frac1 = frac1 >> (FIXED_DIGITS - yResolution);
            scanlineCoverage.add(pix0, 1 * (1 << yResolution), frac0);
            scanlineCoverage.add(pix1, -1 * (1 << yResolution), -frac1);
          }
        if (edge.isClip)
          inClip = ! inClip;
        else
          inShape = ! inShape;

        lastEdge = edge;
      }

    // Push out the whole scanline to the pixelizer.
    if (push && ! scanlineCoverage.isEmpty())
      {
        p.renderScanline(Fixed.intValue(FIXED_DIGITS, y), scanlineCoverage);
        scanlineCoverage.clear();
      }
  } 


  /**
   * Sets the resolution. A value of 0 rasterizes the shape normally without
   * anti-aliasing. Greater values renders with a resolution of 2 ^ res.
   *
   * @param res the resolution
   */
  private void setResolution(int res, int yRes)
  {
    int scanlinesPerPixel = 1 << res;
    int one = Fixed.fixedValue(FIXED_DIGITS, 1);
    resolution = one / (scanlinesPerPixel);
    halfStep = resolution / 2;

    scanlineCoverage.setMaxCoverage(scanlinesPerPixel << yResolution);

    yResolution = yRes;
  }

  /**
   * Sets the vertical bounds of that shape that is beeing rendered.
   *
   * @param y0 the upper bounds
   */
  private void setUpperBounds(int y0)
  {
    upperBounds = fit(y0);
  }

  /**
   * Add a shape to the scanline converter.
   *
   * @param path
   * @param clip
   */
  private void addShape(PathIterator path, boolean clip)
  {
    int startX = 0;
    int startY = 0;
    int lastX = 0;
    int lastY = 0;
    while (! path.isDone())
      {
        int type = path.currentSegment(coords);
        switch (type)
          {
            case PathIterator.SEG_MOVETO:
              startX = lastX = Fixed.fixedValue(FIXED_DIGITS, coords[0]);
              startY = lastY = Fixed.fixedValue(FIXED_DIGITS, coords[1]);
              minY = Math.min(startY, minY);
              maxY = Math.max(startY, maxY);
              minX = Math.min(startX, minX);
              maxX = Math.max(startX, maxX);
              break;
            case PathIterator.SEG_LINETO:
              int x = Fixed.fixedValue(FIXED_DIGITS, coords[0]);
              int y = Fixed.fixedValue(FIXED_DIGITS, coords[1]);
              edgePoolAdd(lastX, lastY, x, y, clip);
              lastX = x;
              lastY = y;
              minY = Math.min(lastY, minY);
              maxY = Math.max(lastY, maxY);
              minX = Math.min(lastX, minX);
              maxX = Math.max(lastX, maxX);
              break;
            case PathIterator.SEG_CLOSE:
              edgePoolAdd(lastX, lastY, startX, startY, clip);
              lastX = startX;
              lastY = startY;
              break;
            case PathIterator.SEG_CUBICTO:
            case PathIterator.SEG_QUADTO:
            default:
              assert false;
          }
        path.next();
      }
  }

  /**
   * Adds an edge into the scanline array.
   */
  private void addEdge(PolyEdge edge)
  {
    // Determine index.
    int upper = Math.min(edge.y0, edge.y1);
    // Fit to raster.
    int index = scanlineIndex(upper);
    // Grow array when necessary.
    if (index >= scanlines.length)
      {
        int oldSize = scanlines.length;
        int newSize = Math.max(oldSize + oldSize / 2 + 1, index + 10);
        Scanline[] newScanlines = new Scanline[newSize];
        System.arraycopy(scanlines, 0, newScanlines, 0, oldSize);
        scanlines = newScanlines;
      }

    // Add edge.
    if (scanlines[index] == null)
      {
        scanlines[index] = new Scanline();
      }
    scanlines[index].addEdge(edge);
  }

  /**
   * Fits an Y coordinate to the grid.
   *
   * @param y the Y coordinate to fit
   *
   * @return the fitted Y coordinate
   */
  private int fit(int y)
  {
    int val1 = Fixed.div(FIXED_DIGITS, y, resolution);
    int rounded = Fixed.round(FIXED_DIGITS, val1);
    return Fixed.mul(FIXED_DIGITS, rounded, resolution);
  }

  /**
   * Calculates the scanline index for the specified y coordinate.
   *
   * @param y the y coordinate as fixed point value
   *
   * @return the scanline index
   */
  private int scanlineIndex(int y)
  {
    int fitted = fit(y);
    // Cleverly skip the fixed point conversions here.
    return (fitted - upperBounds)/ resolution;
  }

  private void edgePoolAdd(int x0, int y0, int x1, int y1, boolean clip)
  {
    // Don't need no horizontal edges.
    if (y0 != y1)
      {
        edgePoolLast.init(FIXED_DIGITS, x0, y0, x1, y1, clip);
        if (edgePoolLast.poolNext == null)
          {
            edgePoolLast.poolNext = new PolyEdge();
          }
        edgePoolLast = edgePoolLast.poolNext;
      }
  }
}
