Source code: com/anotherbigidea/flash/readers/SWFReader.java
1 /****************************************************************
2 * Copyright (c) 2001, David N. Main, All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or
5 * without modification, are permitted provided that the
6 * following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
16 *
17 * 3. The name of the author may not be used to endorse or
18 * promote products derived from this software without specific
19 * prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
32 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 ****************************************************************/
34 package com.anotherbigidea.flash.readers;
35
36 import java.io.*;
37 import com.anotherbigidea.io.*;
38 import com.anotherbigidea.flash.structs.Rect;
39 import com.anotherbigidea.flash.*;
40 import com.anotherbigidea.flash.interfaces.*;
41 import com.anotherbigidea.flash.writers.SWFWriter;
42
43 /**
44 * Reads a SWF input stream and drives the SWFTags interface.
45 *
46 * Automatically decompresses the file if necessary.
47 */
48 public class SWFReader
49 {
50 protected SWFTags mConsumer;
51 protected InStream mIn;
52 protected InputStream mInputstream;
53 protected boolean mCompressed;
54 protected String mFilename;
55
56 /**
57 * Read from a file.
58 * Must call readFile() in order to properly close the file.
59 *
60 * @param consumer may also implement the SWFFileSignature interface.
61 */
62 public SWFReader( SWFTags consumer, String filename ) throws IOException {
63 this( consumer, new FileInputStream( filename ) );
64 mFilename = filename;
65 }
66
67 /**
68 * @param consumer may also implement the SWFFileSignature interface.
69 */
70 public SWFReader( SWFTags consumer, InputStream inputstream )
71 {
72 mConsumer = consumer;
73 mInputstream = inputstream;
74 mIn = new InStream( inputstream );
75 }
76
77 /**
78 * @param consumer may also implement the SWFFileSignature interface.
79 */
80 public SWFReader( SWFTags consumer, InStream instream )
81 {
82 mConsumer = consumer;
83 mIn = instream;
84 }
85
86 /**
87 * Drive the consumer by reading a SWF File - including the header and all tags
88 */
89 public void readFile() throws IOException
90 {
91 readHeader();
92 readTags();
93 if( mFilename != null ) mInputstream.close();
94 }
95
96 /**
97 * Drive the consumer by reading SWF tags only. The full header must have
98 * been read prior to this.
99 */
100 public void readTags() throws IOException
101 {
102 while( readOneTag() != SWFConstants.TAG_END );
103 }
104
105 /**
106 * Drive the consumer by reading one tag
107 * @return the tag type
108 */
109 public int readOneTag() throws IOException
110 {
111 int header = mIn.readUI16();
112
113 int type = header >> 6; //only want the top 10 bits
114 int length = header & 0x3F; //only want the bottom 6 bits
115 boolean longTag = (length == 0x3F);
116
117 if( longTag )
118 {
119 length = (int)mIn.readUI32();
120 }
121
122 byte[] contents = mIn.read( length );
123
124 mConsumer.tag( type, longTag, contents );
125
126 return type;
127 }
128
129 /**
130 * Read and verify just the file signature.
131 */
132 public void readSignature() throws IOException {
133 int[] sig = { mIn.readUI8(), mIn.readUI8(), mIn.readUI8() };
134
135 //--Verify File Signature
136 if( ( sig[0] != 0x46 && sig[0] != 0x43 ) || // "F" or "C"
137 ( sig[1] != 0x57 ) || // "W"
138 ( sig[2] != 0x53 ) ) // "S"
139 {
140 throw new IOException( "Invalid SWF File Signature" );
141 }
142
143 mCompressed = sig[0] == 0x43;
144
145 if( mConsumer instanceof SWFFileSignature ) {
146 ((SWFFileSignature) mConsumer).signature(
147 mCompressed ?
148 SWFFileSignature.SIGNATURE_COMPRESSED :
149 SWFFileSignature.SIGNATURE_NORMAL );
150 }
151 }
152
153 /**
154 * Read the SWF file header - including the signature.
155 */
156 public void readHeader() throws IOException {
157 readSignature();
158 readRemainderOfHeader();
159 }
160
161 /**
162 * Read the header after the signature. The signature must have been read
163 * prior to this.
164 */
165 public void readRemainderOfHeader() throws IOException {
166
167 int version = mIn.readUI8();
168 long length = mIn.readUI32();
169
170 //may be compressed from this point onwards
171 if( mCompressed ) mIn.readCompressed();
172
173 Rect frameSize = new Rect( mIn );
174 int frameRate = mIn.readUI16() >> 8;
175 int frameCount = mIn.readUI16();
176
177 mConsumer.header( version, length,
178 frameSize.getMaxX(), frameSize.getMaxY(),
179 frameRate, frameCount );
180 }
181
182 /**
183 * Test: read from args[0] and write to args[1].
184 *
185 * If args[2] is '+' then output is forced to be compressed, if it is '-'
186 * then output is forced to be uncompressed - otherwise the output is the
187 * same as the input.
188 */
189 public static void main( String[] args ) throws IOException {
190 SWFWriter writer = new SWFWriter( args[1] );
191
192 if( args.length > 2 ) {
193 if ( args[2].equals( "+" )) writer.setCompression( true );
194 else if( args[2].equals( "-" )) writer.setCompression( false );
195 }
196
197 SWFReader reader = new SWFReader( writer, args[0] );
198 reader.readFile();
199 }
200 }