View Javadoc

1   // Copyright 2001-2006, FreeHEP.
2   package org.freehep.graphicsio.swf;
3   
4   import java.awt.Color;
5   import java.awt.Dimension;
6   import java.awt.geom.AffineTransform;
7   import java.awt.geom.Rectangle2D;
8   import java.io.IOException;
9   import java.io.OutputStream;
10  
11  import org.freehep.util.io.ActionHeader;
12  import org.freehep.util.io.TagHeader;
13  import org.freehep.util.io.TaggedOutputStream;
14  
15  /**
16   * This class extends the TaggedOutputStream with several methods to write SWF
17   * primitives to the stream and to write TagHeaders.
18   * 
19   * @author Mark Donszelmann
20   * @author Charles Loomis
21   * @version $Id: SWFOutputStream.java 9976 2006-11-27 18:25:46Z duns $
22   */
23  public class SWFOutputStream extends TaggedOutputStream implements SWFConstants {
24  
25      private Dimension size;
26  
27      private float frameRate;
28  
29      private int frameCount = 0;
30  
31      private boolean compress;
32  
33      private final static AffineTransform identityMatrix = new AffineTransform();
34  
35      public SWFOutputStream(OutputStream os, Dimension size, float frameRate,
36              boolean compress) throws IOException {
37  
38          this(os, DEFAULT_VERSION, size, frameRate, compress);
39      }
40  
41      public SWFOutputStream(OutputStream os, int version, Dimension size,
42              float frameRate, boolean compress) throws IOException {
43  
44          this(os, new SWFTagSet(version), new SWFActionSet(version), size,
45                  frameRate, compress);
46      }
47  
48      public SWFOutputStream(OutputStream os, SWFTagSet tagSet,
49              SWFActionSet actionSet, Dimension size, float frameRate,
50              boolean compress) throws IOException {
51  
52          // SWF is little-endian
53          super(os, tagSet, actionSet, true);
54          this.size = size;
55          this.frameRate = frameRate;
56          this.compress = compress;
57  
58          // will be popped by close()
59          pushBuffer();
60          
61          // add FileAttributes
62          writeTag(new FileAttributes());
63      }
64  
65      public void close() throws IOException {
66          long len = popBuffer() + SWFHeader.size();
67          SWFHeader header = new SWFHeader(getVersion(), len, size, frameRate,
68                  frameCount, compress);
69          writeHeader(header);
70          append();
71  
72          super.close();
73      }
74  
75      public void writeTag(ShowFrame tag) throws IOException {
76  
77          frameCount++;
78          super.writeTag(tag);
79      }
80  
81      public void writeFixed(double d) throws IOException {
82  
83          byteAlign();
84          long whole = (long) d;
85          long frac = (long) ((d - whole) * 0x10000);
86  
87          long fixed = ((whole & 0xFFFF) << 16) | (frac & 0xFFFF);
88          writeUnsignedInt(fixed);
89      }
90  
91      public void writeFixed8(double d) throws IOException {
92  
93          byteAlign();
94          int whole = (int) d;
95          int frac = (int) ((d - whole) * 0x100);
96  
97          int fixed = ((whole & 0xFF) << 8) | (frac & 0xFF);
98          writeUnsignedShort(fixed);
99      }
100 
101     public void writeRect(Rectangle2D rect) throws IOException {
102 
103         int nbits = 0;
104         nbits = Math.max(nbits, minBits((int) (rect.getMinX() * TWIPS), true));
105         nbits = Math.max(nbits, minBits((int) (rect.getMaxX() * TWIPS), true));
106         nbits = Math.max(nbits, minBits((int) (rect.getMinY() * TWIPS), true));
107         nbits = Math.max(nbits, minBits((int) (rect.getMaxY() * TWIPS), true));
108         writeRect(rect, nbits);
109     }
110 
111     public void writeRect(Rectangle2D rect, int nbits) throws IOException {
112 
113         byteAlign();
114         writeUBits(nbits, 5);
115         writeSBits((int) (rect.getMinX() * TWIPS), nbits);
116         writeSBits((int) (rect.getMaxX() * TWIPS), nbits);
117         writeSBits((int) (rect.getMinY() * TWIPS), nbits);
118         writeSBits((int) (rect.getMaxY() * TWIPS), nbits);
119     }
120 
121     public void writeColor(Color color, boolean alpha) throws IOException {
122 
123         byteAlign();
124         writeUnsignedByte(color.getRed());
125         writeUnsignedByte(color.getGreen());
126         writeUnsignedByte(color.getBlue());
127         if (alpha)
128             writeUnsignedByte(color.getAlpha());
129     }
130 
131     public void writeMatrix(AffineTransform matrix) throws IOException {
132 
133         if (matrix == null)
134             matrix = identityMatrix;
135 
136         byteAlign();
137 
138         // Get the scale bits.
139         if ((matrix.getScaleX() != 1.f) || (matrix.getScaleY() != 1.f)) {
140             writeBitFlag(true);
141             int nbits = 0;
142             nbits = Math.max(nbits, minBits((float) matrix.getScaleX()));
143             nbits = Math.max(nbits, minBits((float) matrix.getScaleY()));
144             writeUBits(nbits, 5);
145             writeFBits((float) matrix.getScaleX(), nbits);
146             writeFBits((float) matrix.getScaleY(), nbits);
147         } else {
148             writeBitFlag(false);
149         }
150 
151         // Rotate or skew values.
152         if ((matrix.getShearX() != 0.f) || (matrix.getShearY() != 0.f)) {
153             writeBitFlag(true);
154             int nbits = 0;
155             nbits = Math.max(nbits, minBits((float) matrix.getShearY()));
156             nbits = Math.max(nbits, minBits((float) matrix.getShearX()));
157             writeUBits(nbits, 5);
158             writeFBits((float) matrix.getShearY(), nbits);
159             writeFBits((float) matrix.getShearX(), nbits);
160         } else {
161             writeBitFlag(false);
162         }
163 
164         // Translation values.
165         int nbits = 0;
166         nbits = Math.max(nbits, minBits((int) (matrix.getTranslateX() * TWIPS),
167                 true));
168         nbits = Math.max(nbits, minBits((int) (matrix.getTranslateY() * TWIPS),
169                 true));
170         writeUBits(nbits, 5);
171         writeSBits((int) (matrix.getTranslateX() * TWIPS), nbits);
172         writeSBits((int) (matrix.getTranslateY() * TWIPS), nbits);
173     }
174 
175     public void writeString(String s) throws IOException {
176         if (getVersion() >= 6) {
177             writeUTF(s);
178             writeByte(0);
179         } else {
180             writeAsciiZString(s);
181         }
182     }
183 
184     public void writeLanguageCode(int code) throws IOException {
185         writeUnsignedByte(code);
186     }
187 
188     protected void writeTagHeader(TagHeader tagHeader) throws IOException {
189         byteAlign();
190         int th = (tagHeader.getTag() << 6);
191         if (tagHeader.getLength() >= 0x3f) {
192             th |= 0x3f;
193             writeUnsignedShort(th);
194             writeUnsignedInt(tagHeader.getLength());
195         } else {
196             th |= tagHeader.getLength();
197             writeUnsignedShort(th);
198         }
199     }
200 
201     protected void writeActionHeader(ActionHeader header) throws IOException {
202 
203         int actionCode = header.getAction();
204         long length = header.getLength();
205         writeUnsignedByte(actionCode);
206 
207         if ((actionCode & 0x80) > 0) {
208             writeUnsignedShort((int) length);
209         }
210     }
211 
212     public void writeHeader(SWFHeader header) throws IOException {
213         header.write(this);
214     }
215 
216     public int getVersion() {
217         return ((SWFTagSet) tagSet).getVersion();
218     }
219 }