package pt.tumba.parser.swf;
import com.anotherbigidea.flash.SWFConstants;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* A Shape Symbol
*
*@author unknown
*@created 15 de Setembro de 2002
*/
public class Shape extends Symbol {
/**
* Description of the Class
*
*@author unknown
*@created 15 de Setembro de 2002
*/
public abstract static class Element {
}
/**
* Description of the Class
*
*@author unknown
*@created 15 de Setembro de 2002
*/
public abstract static class Style extends Shape.Element {
}
/**
* Description of the Class
*
*@author unknown
*@created 15 de Setembro de 2002
*/
public abstract static class FillStyle extends Shape.Style {
}
/**
* Description of the Class
*
*@author unknown
*@created 15 de Setembro de 2002
*/
public static class ColorFill extends Shape.FillStyle {
/**
* Description of the Field
*/
protected Color color;
/**
*@return may be Color or AlphaColor
*/
public Color getColor() {
return color;
}
/**
* Sets the color attribute of the ColorFill object
*
*@param color The new color value
*/
public void setColor(Color color) {
this.color = color;
}
/**
* Constructor for the ColorFill object
*
*@param color Description of the Parameter
*/
public ColorFill(Color color) {
this.color = color;
}
}
/**
* Description of the Class
*
*@author unknown
*@created 15 de Setembro de 2002
*/
public static class ImageFill extends Shape.FillStyle {
/**
* Description of the Field
*/
protected Symbol image;
/**
* Description of the Field
*/
protected Transform matrix;
/**
* Description of the Field
*/
protected boolean clipped;
/**
* Gets the image attribute of the ImageFill object
*
*@return The image value
*/
public Symbol getImage() {
return image;
}
/**
* Gets the transform attribute of the ImageFill object
*
*@return The transform value
*/
public Transform getTransform() {
return matrix;
}
/**
* Gets the clipped attribute of the ImageFill object
*
*@return The clipped value
*/
public boolean isClipped() {
return clipped;
}
/**
* Sets the image attribute of the ImageFill object
*
*@param image The new image value
*/
public void setImage(Symbol image) {
this.image = image;
}
/**
* Sets the transform attribute of the ImageFill object
*
*@param matrix The new transform value
*/
public void setTransform(Transform matrix) {
this.matrix = matrix;
}
/**
* Sets the clipped attribute of the ImageFill object
*
*@param isClipped The new clipped value
*/
public void setClipped(boolean isClipped) {
clipped = isClipped;
}
/**
* Constructor for the ImageFill object
*
*@param image Description of the Parameter
*@param matrix Description of the Parameter
*@param isClipped Description of the Parameter
*/
public ImageFill(Symbol image, Transform matrix, boolean isClipped) {
this.image = image;
this.matrix = matrix;
this.clipped = isClipped;
}
}
/**
* Description of the Class
*
*@author unknown
*@created 15 de Setembro de 2002
*/
public static class GradientFill extends Shape.FillStyle {
/**
* Description of the Field
*/
protected Color[] colors;
/**
* Description of the Field
*/
protected int[] ratios;
/**
* Description of the Field
*/
protected Transform matrix;
/**
* Description of the Field
*/
protected boolean radial;
/**
* Gets the colors attribute of the GradientFill object
*
*@return The colors value
*/
public Color[] getColors() {
return colors;
}
/**
* Gets the transform attribute of the GradientFill object
*
*@return The transform value
*/
public Transform getTransform() {
return matrix;
}
/**
* Gets the ratios attribute of the GradientFill object
*
*@return The ratios value
*/
public int[] getRatios() {
return ratios;
}
/**
* Gets the radial attribute of the GradientFill object
*
*@return The radial value
*/
public boolean isRadial() {
return radial;
}
/**
* Sets the colors attribute of the GradientFill object
*
*@param colors The new colors value
*/
public void setColors(Color[] colors) {
this.colors = colors;
}
/**
* Sets the ratios attribute of the GradientFill object
*
*@param ratios The new ratios value
*/
public void setRatios(int[] ratios) {
this.ratios = ratios;
}
/**
* Sets the transform attribute of the GradientFill object
*
*@param matrix The new transform value
*/
public void setTransform(Transform matrix) {
this.matrix = matrix;
}
/**
* Sets the radial attribute of the GradientFill object
*
*@param isRadial The new radial value
*/
public void setRadial(boolean isRadial) {
this.radial = isRadial;
}
/**
* Constructor for the GradientFill object
*
*@param colors Description of the Parameter
*@param ratios Description of the Parameter
*@param matrix Description of the Parameter
*@param isRadial Description of the Parameter
*/
public GradientFill(Color[] colors, int[] ratios,
Transform matrix, boolean isRadial) {
this.colors = colors;
this.matrix = matrix;
this.radial = isRadial;
this.ratios = ratios;
}
}
/**
* Description of the Class
*
*@author unknown
*@created 15 de Setembro de 2002
*/
public static class LineStyle extends Shape.Style {
/**
* Description of the Field
*/
protected double width;
/**
* Description of the Field
*/
protected Color color;
/**
* Gets the width attribute of the LineStyle object
*
*@return The width value
*/
public double getWidth() {
return width;
}
/**
* Gets the color attribute of the LineStyle object
*
*@return The color value
*/
public Color getColor() {
return color;
}
/**
* Sets the width attribute of the LineStyle object
*
*@param width The new width value
*/
public void setWidth(double width) {
this.width = width;
}
/**
* Sets the color attribute of the LineStyle object
*
*@param color The new color value
*/
public void setColor(Color color) {
this.color = color;
}
/**
* Constructor for the LineStyle object
*
*@param width Description of the Parameter
*@param color Description of the Parameter
*/
public LineStyle(double width, Color color) {
this.width = width;
this.color = color;
}
}
/**
* Description of the Class
*
*@author unknown
*@created 15 de Setembro de 2002
*/
public abstract static class SetStyle extends Shape.Element {
/**
* Description of the Field
*/
protected int index;
/**
* Gets the styleIndex attribute of the SetStyle object
*
*@return The styleIndex value
*/
public int getStyleIndex() {
return index;
}
/**
* Sets the styleIndex attribute of the SetStyle object
*
*@param index The new styleIndex value
*/
public void setStyleIndex(int index) {
this.index = index;
}
/**
* Constructor for the SetStyle object
*
*@param index Description of the Parameter
*/
protected SetStyle(int index) {
this.index = index;
}
}
/**
* Description of the Class
*
*@author unknown
*@created 15 de Setembro de 2002
*/
public abstract static class SetFillStyle extends Shape.SetStyle {
/**
* Constructor for the SetFillStyle object
*
*@param index Description of the Parameter
*/
protected SetFillStyle(int index) {
super(index);
}
}
/**
* Description of the Class
*
*@author unknown
*@created 15 de Setembro de 2002
*/
public static class SetLeftFillStyle extends Shape.SetFillStyle {
/**
* Constructor for the SetLeftFillStyle object
*
*@param index Description of the Parameter
*/
public SetLeftFillStyle(int index) {
super(index);
}
}
/**
* Description of the Class
*
*@author unknown
*@created 15 de Setembro de 2002
*/
public static class SetRightFillStyle extends Shape.SetFillStyle {
/**
* Constructor for the SetRightFillStyle object
*
*@param index Description of the Parameter
*/
public SetRightFillStyle(int index) {
super(index);
}
}
/**
* Description of the Class
*
*@author unknown
*@created 15 de Setembro de 2002
*/
public static class SetLineStyle extends Shape.SetStyle {
/**
* Constructor for the SetLineStyle object
*
*@param index Description of the Parameter
*/
public SetLineStyle(int index) {
super(index);
}
}
/**
* Description of the Class
*
*@author unknown
*@created 15 de Setembro de 2002
*/
public abstract static class Vector extends Shape.Element {
/**
* Description of the Field
*/
protected double x, y;
/**
* Gets the x attribute of the Vector object
*
*@return The x value
*/
public double getX() {
return x;
}
/**
* Gets the y attribute of the Vector object
*
*@return The y value
*/
public double getY() {
return y;
}
/**
* Sets the x attribute of the Vector object
*
*@param x The new x value
*/
public void setX(double x) {
this.x = x;
}
/**
* Sets the y attribute of the Vector object
*
*@param y The new y value
*/
public void setY(double y) {
this.y = y;
}
/**
* Constructor for the Vector object
*
*@param x Description of the Parameter
*@param y Description of the Parameter
*/
protected Vector(double x, double y) {
this.x = x;
this.y = y;
}
}
/**
* Description of the Class
*
*@author unknown
*@created 15 de Setembro de 2002
*/
public static class Move extends Shape.Vector {
/**
* Constructor for the Move object
*
*@param x Description of the Parameter
*@param y Description of the Parameter
*/
public Move(double x, double y) {
super(x, y);
}
}
/**
* Description of the Class
*
*@author unknown
*@created 15 de Setembro de 2002
*/
public static class Line extends Shape.Vector {
/**
* Constructor for the Line object
*
*@param x Description of the Parameter
*@param y Description of the Parameter
*/
public Line(double x, double y) {
super(x, y);
}
}
/**
* Description of the Class
*
*@author unknown
*@created 15 de Setembro de 2002
*/
public static class Curve extends Shape.Vector {
/**
* Description of the Field
*/
protected double cx, cy;
/**
* Gets the controlX attribute of the Curve object
*
*@return The controlX value
*/
public double getControlX() {
return cx;
}
/**
* Gets the controlY attribute of the Curve object
*
*@return The controlY value
*/
public double getControlY() {
return cy;
}
/**
* Sets the controlX attribute of the Curve object
*
*@param cx The new controlX value
*/
public void setControlX(double cx) {
this.cx = cx;
}
/**
* Sets the controlY attribute of the Curve object
*
*@param cy The new controlY value
*/
public void setControlY(double cy) {
this.cy = cy;
}
/**
* Constructor for the Curve object
*
*@param x Description of the Parameter
*@param y Description of the Parameter
*@param controlX Description of the Parameter
*@param controlY Description of the Parameter
*/
public Curve(double x, double y, double controlX, double controlY) {
super(x, y);
this.cx = controlX;
this.cy = controlY;
}
}
/**
* Description of the Field
*/
protected List elements = new ArrayList();
/**
* Description of the Field
*/
protected double minX, maxX, minY, maxY;
//bounding rectangle
/**
* Description of the Field
*/
protected boolean hasAlpha = false;
/**
* Description of the Field
*/
protected double maxLineWidth;
/**
* Description of the Field
*/
protected double currx, curry;
/**
* Constructor for the Shape object
*/
public Shape() { }
/**
* Get the bounding rectangle as a double[4] - (min-X,min-Y,max-X,max-Y)
*
*@return The boundingRectangle value
*/
public double[] getBoundingRectangle() {
return new double[]{minX, minY, maxX, maxY};
}
/**
* Set the bounding rectangle. This will be automatically calculated as the
* geometry vectors are defined and this rectangle will be enlarged if it
* does not contain all the vectors.
*
*@param minx The new boundingRectangle value
*@param minY The new boundingRectangle value
*@param maxX The new boundingRectangle value
*@param maxY The new boundingRectangle value
*/
public void setBoundingRectangle(double minX, double minY,
double maxX, double maxY) {
this.minX = minX;
this.minY = minY;
this.maxX = maxX;
this.maxY = maxY;
}
/**
* Access the list of shape elements Each object is a subclass of
* Shape.Element
*
*@return The shapeElements value
*/
public List getShapeElements() {
return elements;
}
/**
* Define a line style
*
*@param color if null then black is assumed
*@param width Description of the Parameter
*/
public void defineLineStyle(double width, Color color2) {
Color color = color2;
if (color == null) {
color = new Color(0, 0, 0);
}
LineStyle style = new LineStyle(width, color);
if (maxLineWidth < width) {
maxLineWidth = width;
}
if (color instanceof AlphaColor) {
hasAlpha = true;
}
elements.add(style);
}
/**
* Define a color fill
*
*@param color if null then white is assumed
*/
public void defineFillStyle(Color color2) {
Color color = color2;
if (color == null) {
color = new Color(255, 255, 255);
}
ColorFill fill = new ColorFill(color);
if (color instanceof AlphaColor) {
hasAlpha = true;
}
elements.add(fill);
}
/**
* Define an image fill
*
*@param image Description of the Parameter
*@param matrix Description of the Parameter
*@param clipped Description of the Parameter
*/
public void defineFillStyle(Symbol image, Transform matrix, boolean clipped) {
ImageFill fill = new ImageFill(image, matrix, clipped);
elements.add(fill);
}
/**
* Define a gradient fill
*
*@param colors Description of the Parameter
*@param ratios Description of the Parameter
*@param matrix Description of the Parameter
*@param radial Description of the Parameter
*/
public void defineFillStyle(Color[] colors, int[] ratios,
Transform matrix, boolean radial) {
GradientFill fill = new GradientFill(colors, ratios, matrix, radial);
elements.add(fill);
for (int i = 0; i < colors.length; i++) {
if (colors[i] == null) {
continue;
}
if (colors[i] instanceof AlphaColor) {
hasAlpha = true;
}
}
}
/**
* Set the left fill style
*
*@param index The new leftFillStyle value
*/
public void setLeftFillStyle(int index) {
SetLeftFillStyle fill = new SetLeftFillStyle(index);
elements.add(fill);
}
/**
* Set the right fill style
*
*@param index The new rightFillStyle value
*/
public void setRightFillStyle(int index) {
SetRightFillStyle fill = new SetRightFillStyle(index);
elements.add(fill);
}
/**
* Set the line style
*
*@param index The new lineStyle value
*/
public void setLineStyle(int index) {
SetLineStyle style = new SetLineStyle(index);
elements.add(style);
}
/**
* Move the pen without drawing any line
*
*@param x Description of the Parameter
*@param y Description of the Parameter
*/
public void move(double x, double y) {
Move move = new Move(x, y);
if (x < minX) {
minX = x;
}
if (y < minY) {
minY = y;
}
if (x > maxX) {
maxX = x;
}
if (y > maxY) {
maxY = y;
}
elements.add(move);
}
/**
* Draw a line in the current line style (if any)
*
*@param x Description of the Parameter
*@param y Description of the Parameter
*/
public void line(double x, double y) {
Line line = new Line(x, y);
if (x < minX) {
minX = x;
}
if (y < minY) {
minY = y;
}
if (x > maxX) {
maxX = x;
}
if (y > maxY) {
maxY = y;
}
elements.add(line);
}
/**
* Draw a curve in the current line style (if any)
*
*@param x Description of the Parameter
*@param y Description of the Parameter
*@param controlX Description of the Parameter
*@param controlY Description of the Parameter
*/
public void curve(double x, double y, double controlX, double controlY) {
Curve curve = new Curve(x, y, controlX, controlY);
if (x < minX) {
minX = x;
}
if (y < minY) {
minY = y;
}
if (x > maxX) {
maxX = x;
}
if (y > maxY) {
maxY = y;
}
if (controlX < minX) {
minX = controlX;
}
if (controlY < minY) {
minY = controlY;
}
if (controlX > maxX) {
maxX = controlX;
}
if (controlY > maxY) {
maxY = controlY;
}
elements.add(curve);
}
/**
* Description of the Method
*
*@param movie Description of the Parameter
*@param timelineWriter Description of the Parameter
*@param definitionWriter Description of the Parameter
*@return Description of the Return Value
*@exception IOException Description of the Exception
*/
protected int defineSymbol(Movie movie,
SWFTagTypes timelineWriter,
SWFTagTypes definitionWriter)
throws IOException {
currx = 0.0;
curry = 0.0;
predefineImageFills(movie, timelineWriter, definitionWriter);
int id = getNextId(movie);
Rect outline = getRect();
SWFShape shape = hasAlpha ?
definitionWriter.tagDefineShape3(id, outline) :
definitionWriter.tagDefineShape2(id, outline);
writeShape(shape);
return id;
}
/**
* Gets the rect attribute of the Shape object
*
*@return The rect value
*/
protected Rect getRect() {
double adjust = maxLineWidth / 2.0;
Rect outline = new Rect((int) (minX * SWFConstants.TWIPS - adjust * SWFConstants.TWIPS),
(int) (minY * SWFConstants.TWIPS - adjust * SWFConstants.TWIPS),
(int) (maxX * SWFConstants.TWIPS + adjust * SWFConstants.TWIPS),
(int) (maxY * SWFConstants.TWIPS + adjust * SWFConstants.TWIPS));
return outline;
}
/**
* Description of the Method
*
*@param movie Description of the Parameter
*@param timelineWriter Description of the Parameter
*@param definitionWriter Description of the Parameter
*@exception IOException Description of the Exception
*/
protected void predefineImageFills(Movie movie,
SWFTagTypes timelineWriter,
SWFTagTypes definitionWriter)
throws IOException {
//--Make sure any image fills are defined prior to the shape
for (Iterator it = elements.iterator(); it.hasNext(); ) {
Object el = it.next();
if (el instanceof Shape.ImageFill) {
Symbol image = ((Shape.ImageFill) el).getImage();
if (image != null) {
image.define(movie,
timelineWriter,
definitionWriter);
}
}
}
}
/**
* Description of the Method
*
*@param shape Description of the Parameter
*@exception IOException Description of the Exception
*/
protected void writeShape(SWFShape shape) throws IOException {
for (Iterator it = elements.iterator(); it.hasNext(); ) {
Object el = it.next();
if (el instanceof Shape.ColorFill) {
Shape.ColorFill fill = (Shape.ColorFill) el;
shape.defineFillStyle(fill.getColor());
} else if (el instanceof Shape.ImageFill) {
Shape.ImageFill fill = (Shape.ImageFill) el;
Symbol image = fill.getImage();
int imgId = (image != null) ? image.getId() : 65535;
shape.defineFillStyle(imgId, fill.getTransform(), fill.isClipped());
} else if (el instanceof Shape.GradientFill) {
Shape.GradientFill fill = (Shape.GradientFill) el;
shape.defineFillStyle(fill.getTransform(),
fill.getRatios(),
fill.getColors(),
fill.isRadial());
} else if (el instanceof Shape.LineStyle) {
Shape.LineStyle style = (Shape.LineStyle) el;
shape.defineLineStyle((int) (style.getWidth() * SWFConstants.TWIPS),
style.getColor());
} else if (el instanceof Shape.SetLeftFillStyle) {
Shape.SetLeftFillStyle style = (Shape.SetLeftFillStyle) el;
shape.setFillStyle0(style.getStyleIndex());
} else if (el instanceof Shape.SetRightFillStyle) {
Shape.SetRightFillStyle style = (Shape.SetRightFillStyle) el;
shape.setFillStyle1(style.getStyleIndex());
} else if (el instanceof Shape.SetLineStyle) {
Shape.SetLineStyle style = (Shape.SetLineStyle) el;
shape.setLineStyle(style.getStyleIndex());
} else {
writeVector(shape, el);
}
}
shape.done();
}
/**
* Description of the Method
*
*@param vecs Description of the Parameter
*@param el Description of the Parameter
*@exception IOException Description of the Exception
*/
protected void writeVector(SWFVectors vecs, Object el) throws IOException {
if (el instanceof Shape.Move) {
Shape.Move move = (Shape.Move) el;
currx = move.getX() * SWFConstants.TWIPS;
curry = move.getY() * SWFConstants.TWIPS;
int x = (int) currx;
int y = (int) curry;
vecs.move(x, y);
//System.out.println( "M: " + x + " " + y );
} else if (el instanceof Shape.Line) {
Shape.Line line = (Shape.Line) el;
double xx = line.getX() * SWFConstants.TWIPS;
double yy = line.getY() * SWFConstants.TWIPS;
int dx = (int) (xx - currx);
int dy = (int) (yy - curry);
vecs.line(dx, dy);
//System.out.println( "currx=" + currx + " curry=" + curry + " xx=" + xx + " yy=" + yy + " (xx - currx)=" + (xx - currx) + " (yy - curry)=" + (yy - curry) );
//System.out.println( "L: " + dx + " " + dy );
currx = xx;
curry = yy;
} else if (el instanceof Shape.Curve) {
Shape.Curve curve = (Shape.Curve) el;
double xx = curve.getX() * SWFConstants.TWIPS;
double yy = curve.getY() * SWFConstants.TWIPS;
double cxx = curve.getControlX() * SWFConstants.TWIPS;
double cyy = curve.getControlY() * SWFConstants.TWIPS;
int dx = (int) (xx - cxx);
int dy = (int) (yy - cyy);
int cx = (int) (cxx - currx);
int cy = (int) (cyy - curry);
vecs.curve(cx, cy, dx, dy);
currx = xx;
curry = yy;
//System.out.println( "C: " + cx + " " + cy + " " + dx + " " + dy );
}
}
/**
* Description of the Method
*
*@param vecs Description of the Parameter
*@exception IOException Description of the Exception
*/
protected void writeGlyph(SWFVectors vecs) throws IOException {
currx = 0.0;
curry = 0.0;
for (Iterator it = elements.iterator(); it.hasNext(); ) {
writeVector(vecs, it.next());
}
vecs.done();
}
}