package com.flagstone.cookbook;
/*
* BasicShapes.java
* Cookbook
*
* Copyright (c) 2001-2010 Flagstone Software Ltd. All rights reserved.
*
* This code is distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, AND Flagstone HEREBY DISCLAIMS ALL SUCH
* WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
*/
import java.io.File;
import com.flagstone.transform.Background;
import com.flagstone.transform.Movie;
import com.flagstone.transform.MovieHeader;
import com.flagstone.transform.Place2;
import com.flagstone.transform.ShowFrame;
import com.flagstone.transform.datatype.Bounds;
import com.flagstone.transform.datatype.WebPalette;
import com.flagstone.transform.fillstyle.SolidFill;
import com.flagstone.transform.linestyle.LineStyle1;
import com.flagstone.transform.util.shape.Canvas;
/*
* This example shows how the drawing commands available in the ShapeConstructor
* can be used to draw simple geometric shapes and arbitrary paths. The example
* draws a series of simple geometric shapes and discusses how the line and fill
* styles are specified to render the paths drawn.
*
* To run this example, type the following on a command line:
*
* java -cp ... com.flagstone.cookbook.BasicShapes file-out
*
* where:
*
* file-out is the path where the file will be written. If no output file
* is specified then a file named after the example will be written to the
* current directory.
*/
public class BasicShapes {
public static void main(String[] args) {
try {
String out = args.length == 0 ? "BasicShapes.swf" : args[0];
BasicShapes example = new BasicShapes();
Movie movie = new Movie();
example.createMovie(movie);
movie.encodeToFile(new File(out));
} catch (Exception e) {
e.printStackTrace();
}
}
public void createMovie(Movie movie) {
/*
* Canvas allows coordinates to be specified either in twips or pixels.
* Pixels makes life a little easier.
*/
Canvas path = new Canvas();
path.setPixels(true);
int uid = 1;
int width = 150;
int height = 100;
int cornerRadius = 10;
int identifier = 0;
MovieHeader header = new MovieHeader();
header.setFrameRate(1.0f);
header.setFrameSize(new Bounds(-4000, -4000, 4000, 4000));
movie.add(header);
movie.add(new Background(WebPalette.LIGHT_BLUE.color()));
/*
* Draw a rectangle with the origin at the centre of the shape.
*/
identifier = uid++;
rect(path, width / 2, -height / 2, width, height);
movie.add(path.defineShape(identifier));
movie.add(Place2.show(identifier, 1, 0, 0));
movie.add(ShowFrame.getInstance());
/*
* Draw a rectangle with rounded corners.
*/
identifier = uid++;
rect(path, width / 2, height / 2, width, height, cornerRadius);
movie.add(path.defineShape(identifier));
movie.add(Place2.replace(identifier, 1));
movie.add(ShowFrame.getInstance());
/*
* Draw a circle.
*/
identifier = uid++;
circle(path, -width / 2, height / 2, height / 2);
movie.add(path.defineShape(identifier));
movie.add(Place2.replace(identifier, 1));
movie.add(ShowFrame.getInstance());
/*
* Draw an ellipse.
*/
identifier = uid++;
ellipse(path, -width / 2, -height / 2, width / 2, height / 2);
movie.add(path.defineShape(identifier));
movie.add(Place2.replace(identifier, 1));
movie.add(ShowFrame.getInstance());
/*
* Draw a polyline. The first point of a polyline is a move relative to
* the current drawing point - which for a new path is (0,0). While the
* geometric shapes drawn previous were all closed the polygon method
* can be used to draw part of a shape so the newPath() and styles must
* be explicitly specified to draw the shape.
*/
identifier = uid++;
int[] points = new int[] { 0, -100, 10, 0, 0, 90, 90, 0, 0, 20, -90, 0,
0, 90, -20, 0, 0, -90, -90, 0, 0, -20, 90, 0, 0, -90, 10, 0 };
path.clear();
path.setLineStyle(new LineStyle1(20, WebPalette.BLACK.color()));
path.setFillStyle(new SolidFill(WebPalette.RED.color()));
path.rpolygon(points);
path.close();
movie.add(path.defineShape(identifier));
movie.add(Place2.replace(identifier, 1));
movie.add(ShowFrame.getInstance());
/*
* Draw a cubic bezier curve.
*
* This simple curve is included to show how cubic Bezier curves are
* drawn. Flash only directly supports quadratic Bezier curves.
* Converting from cubic to quadratic is mathematically difficult so
* the cubic curve is flattened and drawn as a series of straight lines.
* The results are visually appealing and the slight increase in the
* size of the Flash file is compensated for by the increase in drawing
* performance. Note that the path is closed before the shape is
* generated. The Canvas tracks the initial and current drawing points.
* When a call to close() is made it draws a straight line (if required)
* between the current point and the initial point to ensure that the
* shape is closed and will be rendered correctly.
*/
identifier = uid++;
path.clear();
path.setLineStyle(new LineStyle1(20, WebPalette.BLACK.color()));
path.setFillStyle(new SolidFill(WebPalette.RED.color()));
path.curve(0, -100, 150, -100, 150, 0);
path.close();
movie.add(path.defineShape(identifier));
movie.add(Place2.replace(identifier, 1));
movie.add(ShowFrame.getInstance());
}
private void rect(Canvas path, int x, int y, int width, int height) {
path.clear();
path.setLineStyle(new LineStyle1(20, WebPalette.BLACK.color()));
path.setFillStyle(new SolidFill(WebPalette.RED.color()));
path.move(x - width / 2, y - height / 2);
path.rline(width, 0);
path.rline(0, height);
path.rline(-width, 0);
path.rline(0, -height);
path.close();
}
private void rect(Canvas path, int x, int y, int width, int height,
int radius) {
int shortestSide = (height < width) ? height : width;
if (radius > shortestSide / 2)
radius = shortestSide / 2;
path.clear();
path.setLineStyle(new LineStyle1(20, WebPalette.BLACK.color()));
path.setFillStyle(new SolidFill(WebPalette.RED.color()));
path.move(x, y - height / 2);
path.rline(width / 2 - radius, 0);
path.rcurve(radius, 0, 0, radius);
path.rline(0, height - 2 * radius);
path.rcurve(0, radius, -radius, 0);
path.rline(-(width - 2 * radius), 0);
path.rcurve(-radius, 0, 0, -radius);
path.rline(0, -(height - 2 * radius));
path.rcurve(0, -radius, radius, 0);
path.close();
}
private void ellipse(Canvas path, int x, int y, int rx, int ry) {
boolean wasInPixels = path.isPixels();
if (wasInPixels) {
path.setPixels(false);
x *= 20;
y *= 20;
rx *= 20;
ry *= 20;
}
int startX = (int) (0.707 * rx) + x;
int startY = (int) (0.707 * ry) + y;
int ax = (int) (0.293 * rx);
int ay = (int) (0.293 * ry);
int cx = (int) (0.414 * rx);
int cy = (int) (0.414 * ry);
path.clear();
path.setLineStyle(new LineStyle1(20, WebPalette.BLACK.color()));
path.setFillStyle(new SolidFill(WebPalette.RED.color()));
path.move(startX, startY);
path.rcurve(-ax, ay, -cx, 0);
path.rcurve(-cx, 0, -ax, -ay);
path.rcurve(-ax, -ay, 0, -cy);
path.rcurve(0, -cy, ax, -ay);
path.rcurve(ax, -ay, cx, 0);
path.rcurve(cx, 0, ax, ay);
path.rcurve(ax, ay, 0, cy);
path.rcurve(0, cy, -ax, ay);
path.close();
path.setPixels(wasInPixels);
}
private void circle(final Canvas path, int x, int y, int r) {
ellipse(path, x, y, r, r);
}
}