package pt.tumba.parser.swf;
import com.anotherbigidea.flash.SWFConstants;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* A Flash Movie
*
*@author unknown
*@created 15 de Setembro de 2002
*/
public class Movie implements TimeLine {
protected int width;
protected int height;
protected int frameRate;
protected Color backColor;
protected int version;
protected boolean isProtected;
protected Map<String, List> importLibraries;
protected List<ExportedSymbol> exportedSymbols;
protected SortedMap<Integer, Frame> frames = new TreeMap();
protected int frameCount = 0;
//--Table of characters defined so far in the movie - while writing out
protected Map definedSymbols = new HashMap();
protected int depth = 1; //the next available depth
protected int maxId = 1;
//the next available symbol id
/**
* Create a movie with the default values - (550x400), 12 frames/sec, white
* backcolor, Flash version 5.
*/
public Movie() {
width = 550;
height = 400;
frameRate = 12;
version = 5;
}
/**
* Create a movie with the given properties
*
*@param width Description of the Parameter
*@param height Description of the Parameter
*@param frameRate Description of the Parameter
*@param version Description of the Parameter
*@param backColor Description of the Parameter
*/
public Movie(int width, int height, int frameRate, int version, Color backColor) {
this.width = width;
this.height = height;
this.frameRate = frameRate;
this.version = version;
this.backColor = backColor;
}
/**
* Gets the width attribute of the Movie object
*
*@return The width value
*/
public int getWidth() {
return width;
}
/**
* Gets the height attribute of the Movie object
*
*@return The height value
*/
public int getHeight() {
return height;
}
/**
* Gets the frameRate attribute of the Movie object
*
*@return The frameRate value
*/
public int getFrameRate() {
return frameRate;
}
/**
* Gets the version attribute of the Movie object
*
*@return The version value
*/
public int getVersion() {
return version;
}
/**
* Gets the backColor attribute of the Movie object
*
*@return The backColor value
*/
public Color getBackColor() {
return backColor;
}
/**
* Sets the width attribute of the Movie object
*
*@param width The new width value
*/
public void setWidth(int width) {
this.width = width;
}
/**
* Sets the height attribute of the Movie object
*
*@param height The new height value
*/
public void setHeight(int height) {
this.height = height;
}
/**
* Sets the frameRate attribute of the Movie object
*
*@param rate The new frameRate value
*/
public void setFrameRate(int rate) {
this.frameRate = rate;
}
/**
* Sets the version attribute of the Movie object
*
*@param version The new version value
*/
public void setVersion(int version) {
this.version = version;
}
/**
* Sets the backColor attribute of the Movie object
*
*@param color The new backColor value
*/
public void setBackColor(Color color) {
this.backColor = color;
}
/**
* Return the protection flag. If true then the movie cannot be imported
* into the Flash Author. The existence of tools such as JavaSWF makes this
* kind of protection almost worthless.
*
*@return The protected value
*/
public boolean isProtected() {
return isProtected;
}
/**
* Description of the Method
*
*@param isProtected Description of the Parameter
*/
public void protect(boolean isProtected) {
this.isProtected = isProtected;
}
/**
* Get the current number of frames in the timeline.
*
*@return The frameCount value
*/
public int getFrameCount() {
return frameCount;
}
/**
* Get the Frame object for the given frame number - or create one if none
* exists. If the frame number is larger than the current frame count then
* the frame count is increased.
*
*@param frameNumber must be 1 or larger
*@return The frame value
*/
public Frame getFrame(int frameNumber) {
if (frameNumber < 1) {
return null;
}
Integer num = new Integer(frameNumber);
Frame frame = (Frame) frames.get(num);
if (frame == null) {
frame = new Frame(frameNumber, this);
frames.put(num, frame);
if (frameNumber > frameCount) {
frameCount = frameNumber;
}
}
return frame;
}
/**
* Append a frame to the end of the timeline
*
*@return Description of the Return Value
*/
public Frame appendFrame() {
frameCount++;
Frame frame = new Frame(frameCount, this);
frames.put(new Integer(frameCount), frame);
return frame;
}
/**
* Get the next available depth in the timeline
*
*@return The availableDepth value
*/
public int getAvailableDepth() {
return depth;
}
/**
* Set the next available depth in the timeline
*
*@param depth must be >= 1
*/
public void setAvailableDepth(int depth) {
if (depth < 1) {
return;
}
this.depth = depth;
}
/**
* Import symbols from another movie (Flash 5 only)
*
*@param libraryName Description of the Parameter
*@param symbolNames Description of the Parameter
*@return Symbols representing the imports
*/
public ImportedSymbol[] importSymbols(String libraryName, String[] symbolNames) {
if (importLibraries == null) {
importLibraries = new HashMap();
}
ArrayList imports = (ArrayList) importLibraries.get(libraryName);
if (imports == null) {
imports = new ArrayList();
importLibraries.put(libraryName, imports);
}
ImportedSymbol[] symbols = new ImportedSymbol[symbolNames.length];
for (int i = 0; i < symbolNames.length; i++) {
ImportedSymbol imp = new ImportedSymbol(0, symbolNames[i], libraryName);
symbols[i] = imp;
imports.add(imp);
}
return symbols;
}
/**
* Clear all the defined library imports
*/
public void clearImports() {
if (importLibraries != null) {
importLibraries.clear();
}
}
/**
* Access the imported symbols.
*
*@return an empty array if there are no imports
*/
public ImportedSymbol[] getImportedSymbols() {
if (importLibraries == null) {
return new ImportedSymbol[0];
}
List imports = new ArrayList();
for (List list : importLibraries.values()) {
for (Iterator i2 = list.iterator(); i2.hasNext(); ) {
imports.add(i2.next());
}
}
ImportedSymbol[] imps = new ImportedSymbol[imports.size()];
return (ImportedSymbol[])imports.toArray(imps);
}
/**
* Export a number of symbols with the given names so that other movies can
* import and use them. Flash version 5 only.
*
*@param exportNames Description of the Parameter
*@param symbols Description of the Parameter
*/
public void exportSymbols(String[] exportNames, Symbol[] symbols) {
if (exportedSymbols == null) {
exportedSymbols = new ArrayList();
}
for (int i = 0; i < exportNames.length && i < symbols.length; i++) {
exportedSymbols.add(new ExportedSymbol(symbols[i], exportNames[i]));
}
}
/**
* Get the symbols exported from the movie
*
*@return an empty array if there are no exports
*/
public ExportedSymbol[] getExportedSymbols() {
if (exportedSymbols == null) {
return new ExportedSymbol[0];
}
ExportedSymbol[] exports = new ExportedSymbol[exportedSymbols.size()];
exportedSymbols.toArray(exports);
return exports;
}
/**
* Clear all the symbol exports
*/
public void clearExports() {
if (exportedSymbols != null) {
exportedSymbols.clear();
}
}
/**
* Write the movie in SWF format.
*
*@param tagwriter Description of the Parameter
*@exception IOException Description of the Exception
*/
public void write(SWFTagTypes tagwriter) throws IOException {
//--Reset state
definedSymbols.clear();
maxId = 1;
tagwriter.header(version,
-1,
//force length calculation
width * SWFConstants.TWIPS,
height * SWFConstants.TWIPS,
frameRate,
-1);
//force frame calculation
//default backColor is white
if (backColor == null) {
backColor = new Color(255, 255, 255);
}
tagwriter.tagSetBackgroundColor(backColor);
if (isProtected) {
tagwriter.tagProtect(null);
}
//--Process Imports
if (importLibraries != null && !importLibraries.isEmpty()) {
for (Iterator keys = importLibraries.keySet().iterator(); keys.hasNext(); ) {
String libName = (String) keys.next();
List imports = (List) importLibraries.get(libName);
String[] names = new String[imports.size()];
int[] ids = new int[imports.size()];
int i = 0;
for (Iterator it = imports.iterator(); it.hasNext(); ) {
ImportedSymbol imp = (ImportedSymbol) it.next();
names[i] = imp.getName();
ids[i] = imp.define(this, tagwriter, tagwriter);
i++;
}
tagwriter.tagImport(libName, names, ids);
}
}
//--Process Exports
if (exportedSymbols != null && !exportedSymbols.isEmpty()) {
String[] names = new String[exportedSymbols.size()];
int[] ids = new int[exportedSymbols.size()];
int i = 0;
for (Iterator it = exportedSymbols.iterator(); it.hasNext(); ) {
ExportedSymbol exp = (ExportedSymbol) it.next();
names[i] = exp.getExportName();
ids[i] = exp.getSymbol().define(this, tagwriter, tagwriter);
i++;
}
tagwriter.tagExport(names, ids);
}
int lastFrame = 0;
for (Iterator iter = frames.values().iterator(); iter.hasNext(); ) {
Frame frame = (Frame) iter.next();
int number = frame.getFrameNumber();
//write any intermediate empty frames
while (number > lastFrame + 1) {
tagwriter.tagShowFrame();
lastFrame++;
}
frame.write(this, tagwriter, tagwriter);
lastFrame = number;
}
//end of time line
tagwriter.tagEnd();
}
/**
* Write the movie in SWF format to the given file.
*
*@param filename Description of the Parameter
*@exception IOException Description of the Exception
*/
public void write(String filename) throws IOException {
SWFWriter swfwriter = new SWFWriter(filename);
TagWriter tagwriter = new TagWriter(swfwriter);
write(tagwriter);
}
/**
* Write the movie in SWF format to the given output stream.
*
*@param out Description of the Parameter
*@exception IOException Description of the Exception
*/
public void write(OutputStream out) throws IOException {
SWFWriter swfwriter = new SWFWriter(out);
TagWriter tagwriter = new TagWriter(swfwriter);
write(tagwriter);
}
}