📄 fsshapeconstructor.java
字号:
/*
* FSShapeConstructor.java
* Transform Utilities
*
* Copyright (c) 2001-2006 Flagstone Software Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Flagstone Software Ltd. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.flagstone.transform.util;
import com.flagstone.transform.*;
import java.util.*;
/**
* The FSShapeConstructor class is used to create shape definitions. Arbitrary paths can be
* created using a series of move, line or curve segments. Drawing operations using both
* absolute coordinates and coordinates relative to the current point (updated after every
* operation) are supported.
*
* For curves both cubic and quadratic curves are supported. Flash only supports quadratic
* curves so cubic curves are approximated by a series of line segments using (converting cubic
* to quadratic curves is mathematically difficult). The smoothness of cubic curves is
* controlled by the flatness attribute which can be used to limit the number of line segments
* that are drawn.
*
* While drawing the start of the first segment to be drawn is recorded so the path can
* easily be closed by drawing a line from the current point to the start of the first
* segment drawn. To account for the rounded mitering supported by Flash the path is closed
* by re-adding the first segment drawn so the line ends overlap.
*
* As a path is drawn the maximum and minimum x and y coordinates are recorded so that the
* bounding rectangle that completely encloses the shape can be defined. This is used when
* creating shape definitions using the FSDefineShape, FSDefineShape2 or FSDefineShape3 classes.
*
* The FSShapeConstructor class also supports a number of method to create closed paths that
* represent different geometric shapes. Basic rectangles, ellipses and circles are supported.
* More complex shapes can be drawn using the polygon() method which uses pairs of points to
* specified the vertices of an arbitrary shapes.
*
* When drawing paths whether coordinates are specified in twips or pixels is controlled by
* the attributes COORDINATES_ARE_PIXELS. This is independent of the flag of the same name
* supported in the Transform SWF frameworks. When true coordinates are specified in pixels,
* while coordinates are specified in twips when false. 1 pixel == 20 twips. Internally all
* coordinates are converted to twips to perform the actual drawing.
*
* The styles used to draw the path and fill the area enclosed is specified using the ordinal
* position of the style object in the arrays of styles maintained by the shape definition
* object (FSDefineShape, SDefineShape2 or FSDefineShape3) used to construct the final shape.
*
* <b>Examples</b>
*
* The following code samples illustrate how to use the FSShapeConstructor class create shapes.
*
* 1. Defining a rectangle using move and line drawing operations.\n
*
*<pre>
* FSShapeConstructor path = new FSShapeConstructor();
*
* path.COORDINATES_ARE_PIXELS = true;
*
* int width = 200;
* int height = 100;
*
* // Setting the line style before any drawing commands is important
* // so the thickness of the line can be taken into account when
* // calculating the bounding rectangle which must completely enclose
* // the shape so it will be drawn correctly.
*
* path.add(new FSSolidLine(1, FSColorTable.black()));
* path.add(new FSSolidFill(FSColorTable.red()));
*
* newPath(); // start a new path
* selectStyle(1, 1); // select the first line and fill style objects
* move(-width/2, -height/2); // Move to the top left corner
* rline(width, 0); // Draw the sides of the rectangle
* rline(0, height);
* rline(-width, 0);
* rline(0, -height);
* closePath(); // close the path to correctly seal the line ends.
*
* // Now define the shape.
*
* FSDefineShape3 rect = path.defineShape(movie.newIdentifier());
*
*</pre>
*
* 2. Defining a rectangle using the path creation method.\n
*
*<pre>
* FSShapeConstructor path = new FSShapeConstructor();
*
* path.COORDINATES_ARE_PIXELS = true;
*
* // Define the origin for the shape so the bottom left corner of the
* // rectangle will appear at the coordinates the shape is place at
* // using the FSPlaceObject or FSPlaceObject2 class.
*
* int xorigin = 100;
* int yorigin = -50;
*
* int width = 200;
* int height = 100;
* int cornerRadius = 10
*
* path.add(new FSSolidLine(1, FSColorTable.black()));
* path.add(new FSSolidFill(FSColorTable.red()));
*
* // Create a rectangle with rounded corners.
*
* path.rect(xorign, yorigin, width, height, cornerRadius);
*
* // Now define the shape.
*
* FSDefineShape3 rect = path.defineShape(movie.newIdentifier());
*
*</pre>
*
*/
public class FSShapeConstructor
{
private double flattenLimit = 0.25;
/**
* The COORDINATES_ARE_PIXELS flag controls whether the coordinates passed to methods when creating
* a path of predefined shape are expressed in pixels (true) or twips (false).
*
* Flash coordinates are specified in twips (1 twip equals 1/1440th of an inch or 1/20th of a point).
* Allowing coordinates to be specified in pixels simplifies the drawing process avoiding the conversion
* to twips by multiplying each value by 20.
*
* IMPORTANT: The value of this flag is independent of the COORDINATES_ARE_PIXELS flag specified in
* the Transform class of the Transform SWF framework.
*/
public boolean COORDINATES_ARE_PIXELS = false;
private double[] Px = new double[4];
private double[] Py = new double[4];
private boolean pathInProgress = false;
private int initialX = 0;
private int initialY = 0;
private int currentX = 0;
private int currentY = 0;
private int controlX = 0;
private int controlY = 0;
private int minX = 0;
private int minY = 0;
private int maxX = 0;
private int maxY = 0;
private int lineWidth = 0;
ArrayList objects = new ArrayList();
ArrayList lineStyles = new ArrayList();
ArrayList fillStyles = new ArrayList();
/**
* Creates an FSShapeConstructor object with no path defined.
*/
public FSShapeConstructor()
{
}
/** Sets the line style at the index in the array of line styles.
@param index the position in the array of line styles.
@param aLineStyle and FSSolidLine object.
@throws ArrayIndexOutOfBounds if the index < 0 or index > array size.
*/
public void set(int index, FSLineStyle aLineStyle)
{
lineStyles.set(index, aLineStyle);
}
/** Add a FSSolidLine object to the array of line styles.
@param aLineStyle and FSSolidLine object.
*/
public void add(FSLineStyle aLineStyle)
{
lineStyles.add(aLineStyle);
}
/** Sets the fill style at the index in the array of fill styles.
@param index the position in the array of fill styles.
@param aFillStyle an FSFillStyle object.
@throws ArrayIndexOutOfBounds if the index < 0 or index > array size.
*/
public void set(int index, FSFillStyle aFillStyle)
{
fillStyles.set(index, aFillStyle);
}
/** Add the fill style object to the array of fill styles.
@param aFillStyle and FSFillStyle object.
*/
public void add(FSFillStyle aFillStyle)
{
fillStyles.add(aFillStyle);
}
/** Gets the array line styles.
@return the line styles used in the shape.
*/
public ArrayList getLineStyles()
{
return lineStyles;
}
/** Sets the line styles.
@param anArray set the line styles for the shape.
*/
public void setLineStyles(ArrayList anArray)
{
lineStyles = anArray;
}
/** Gets the array fill styles.
@return the fill styles used in the shape.
*/
public ArrayList getFillStyles()
{
return fillStyles;
}
/** Sets the fill styles.
@param anArray set the fill styles for the shape.
*/
public void setFillStyles(ArrayList anArray)
{
fillStyles = anArray;
}
/**
* Selects the style used to draw the outline of the shape from the array of
* line styles.
*
* @param index the position of the style used to draw the shape.
*/
public void selectLineStyle(int index)
{
lineWidth = ((FSSolidLine)lineStyles.get(index)).getWidth();
objects.add(new FSShapeStyle(index+1, Transform.VALUE_NOT_SET, Transform.VALUE_NOT_SET));
}
/**
* Selects the style used to fill the contents of the shape from the array of
* fill styles.
*
* @param index the position of the style used to fill the shape.
*/
public void selectFillStyle(int index)
{
objects.add(new FSShapeStyle(Transform.VALUE_NOT_SET, index+1, Transform.VALUE_NOT_SET));
}
/**
* Selects the style used to fill overlapping areas of the shape from the
* array of fill styles.
*
* @param index the position of the style used to fill overlapping areas.
*/
public void selectAltStyle(int index)
{
objects.add(new FSShapeStyle(Transform.VALUE_NOT_SET, Transform.VALUE_NOT_SET, index+1));
}
/**
* Selects the styles used to draw the outline and fill the contents of the
* shape from the array of line and fill styles.
*
* @param lineIndex the position of the style used to draw the outline of the shape.
* @param fillIndex the position of the style used to fill the shape.
*/
public void selectStyle(int lineIndex, int fillIndex)
{
lineWidth = ((FSSolidLine)lineStyles.get(lineIndex)).getWidth();
objects.add(new FSShapeStyle(lineIndex+1, fillIndex+1, Transform.VALUE_NOT_SET));
}
/**
* Selects the styles used to draw the outline and fill the contents of the
* shape, including overlapping area, from the array of line and fill styles.
*
* @param lineIndex the position of the style used to draw the outline of the shape.
* @param fillIndex the position of the style used to fill the shape.
* @param altIndex the position of the style used to fill overlapping areas of the shape.
*/
public void selectStyle(int lineIndex, int fillIndex, int altIndex)
{
lineWidth = ((FSSolidLine)lineStyles.get(lineIndex)).getWidth();
objects.add(new FSShapeStyle(lineIndex+1, fillIndex+1, altIndex+1));
}
/**
* Generates the bounding box that encloses the current path.
*
* @return an FSBounds object representing the bounding box that encloses the path.
*/
public FSBounds bounds()
{
return new FSBounds(minX, minY, maxX, maxY);
}
/**
* Generates an FSShape object containing the objects used to draw the current path.
*
* @return an FSShape object contain the FSLine, FSCurve and FSShapeStyle objects used to
* construct the current path.
*/
public FSShape shape()
{
return new FSShape((ArrayList)objects.clone());
}
/**
* Generates a shape containing the current path and styles.
*
* The shape is constructed with copies of the style arrays and the shape representing the
* path drawn. This allows the number of styles to be changed without affecting previously
* created shapes.
*
* @param identifier an unique identifier for the shape.
*/
public FSDefineShape2 defineShape(int identifier)
{
return new FSDefineShape2(identifier, bounds(), (ArrayList)fillStyles.clone(), (ArrayList)lineStyles.clone(), new FSShape((ArrayList)objects.clone()));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -