1
2 package org.freehep.graphicsio.swf;
3
4 import java.io.IOException;
5 import java.util.Vector;
6
7 import org.freehep.util.io.BitOutputStream;
8
9
10
11
12
13
14
15
16 public class SWFShape {
17
18 private int numFillBits;
19
20 private int numLineBits;
21
22 protected FillStyleArray fillStyles;
23
24 protected LineStyleArray lineStyles;
25
26 private Vector records;
27
28 public SWFShape(Vector records) {
29 this.records = records;
30 }
31
32
33 public SWFShape(SWFInputStream input) throws IOException {
34 this(input, null, null, false, false, false);
35 }
36
37 public SWFShape(SWFInputStream input, FillStyleArray fillStyles,
38 LineStyleArray lineStyles, boolean isMorphStyle, boolean hasAlpha, boolean hasStyles)
39 throws IOException {
40
41 this.fillStyles = fillStyles;
42 this.lineStyles = lineStyles;
43
44 input.byteAlign();
45 numFillBits = (int) input.readUBits(4);
46 numLineBits = (int) input.readUBits(4);
47
48 records = new Vector();
49
50 boolean endOfShape = false;
51 do {
52 boolean edge = input.readBitFlag();
53 if (edge) {
54
55 records.add(new EdgeRecord(input));
56 } else {
57
58 int state = (int) input.readUBits(5);
59 if (state == 0) {
60 endOfShape = true;
61 } else {
62 records.add(new ShapeRecord(this, input, numFillBits,
63 numLineBits, isMorphStyle, hasAlpha, hasStyles, state));
64 }
65 }
66 } while (!endOfShape);
67 }
68
69
70 public void write(SWFOutputStream swf) throws IOException {
71 write(swf, false, false, false);
72 }
73
74 public void write(SWFOutputStream swf, boolean isMorphStyle, boolean hasAlpha, boolean hasStyles) throws IOException {
75 swf.byteAlign();
76 int numFillBits = 0;
77 int numLineBits = 0;
78
79 for (int i = 0; i < records.size(); i++) {
80 Record r = (Record) records.get(i);
81 if (r instanceof ShapeRecord) {
82 ShapeRecord s = (ShapeRecord) r;
83 numFillBits = Math.max(numFillBits, s.getNumFillBits());
84 numLineBits = Math.max(numLineBits, s.getNumLineBits());
85 }
86 }
87 swf.writeUBits(numFillBits, 4);
88 swf.writeUBits(numLineBits, 4);
89
90 for (int i = 0; i < records.size(); i++) {
91 Record r = (Record) records.get(i);
92 r.write(swf, numFillBits, numLineBits, isMorphStyle, hasAlpha, hasStyles);
93 }
94 swf.writeUBits(0, 6);
95 swf.byteAlign();
96 }
97
98 void setNumFillBits(int numFillBits) {
99 this.numFillBits = numFillBits;
100 }
101
102 void setNumLineBits(int numLineBits) {
103 this.numLineBits = numLineBits;
104 }
105
106 void setFillStyles(FillStyleArray fillStyles) {
107 this.fillStyles = fillStyles;
108 }
109
110 void setLineStyles(LineStyleArray lineStyles) {
111 this.lineStyles = lineStyles;
112 }
113
114 public String toString() {
115 StringBuffer s = new StringBuffer();
116 for (int i = 0; i < records.size(); i++) {
117 s.append(" ");
118 s.append(i);
119 s.append(":");
120 s.append(records.get(i));
121 s.append("\n");
122 }
123 s.append(" End of shape\n");
124 return s.toString();
125 }
126
127
128
129
130 public static abstract class Record {
131 public abstract void write(SWFOutputStream swf, int numFillBits,
132 int numLineBits, boolean isMorphStyle, boolean hasAlpha, boolean hasStyles) throws IOException;
133 }
134
135
136
137
138 public static class ShapeRecord extends Record {
139
140 private static final int MOVE = 0x01;
141
142 private static final int FILLSTYLE0 = 0x02;
143
144 private static final int FILLSTYLE1 = 0x04;
145
146 private static final int LINESTYLE = 0x08;
147
148 private static final int NEWSTYLES = 0x10;
149
150 private boolean move;
151
152 private int moveX = 0;
153
154 private int moveY = 0;
155
156 private int fillStyle0 = -1;
157
158 private int fillStyle1 = -1;
159
160 private int lineStyle = -1;
161
162 private FillStyleArray newFillStyles;
163
164 private LineStyleArray newLineStyles;
165
166 public ShapeRecord(boolean move, int moveX, int moveY, int fillStyle0,
167 int fillStyle1, int lineStyle) {
168 this.move = move;
169 this.moveX = moveX;
170 this.moveY = moveY;
171 this.fillStyle0 = fillStyle0;
172 this.fillStyle1 = fillStyle1;
173 this.lineStyle = lineStyle;
174 }
175
176 ShapeRecord(SWFShape shape, SWFInputStream input, int numFillBits,
177 int numLineBits, boolean isMorphStyle, boolean hasAlpha, boolean hasStyles,
178 int state) throws IOException {
179
180 if ((state & MOVE) > 0) {
181 move = true;
182 int numMoveBits = (int) input.readUBits(5);
183 moveX = (int) input.readSBits(numMoveBits);
184 moveY = (int) input.readSBits(numMoveBits);
185 }
186
187 if ((state & FILLSTYLE0) > 0)
188 fillStyle0 = (int) input.readUBits(numFillBits);
189 if ((state & FILLSTYLE1) > 0)
190 fillStyle1 = (int) input.readUBits(numFillBits);
191 if ((state & LINESTYLE) > 0)
192 lineStyle = (int) input.readUBits(numLineBits);
193
194 if ((state & NEWSTYLES) > 0) {
195 newFillStyles = new FillStyleArray(input, isMorphStyle,
196 hasAlpha);
197 shape.setFillStyles(newFillStyles);
198 newLineStyles = new LineStyleArray(input, isMorphStyle,
199 hasAlpha, hasStyles);
200 shape.setLineStyles(newLineStyles);
201
202 numFillBits = (int) input.readUBits(4);
203 shape.setNumFillBits(numFillBits);
204 numLineBits = (int) input.readUBits(4);
205 shape.setNumLineBits(numLineBits);
206 }
207 }
208
209 public void write(SWFOutputStream swf, int numFillBits,
210 int numLineBits, boolean isMorphStyle, boolean hasAlpha, boolean hasStyles) throws IOException {
211
212 int state = 0x00;
213 if (newFillStyles != null)
214 state |= NEWSTYLES;
215 if (lineStyle != -1)
216 state |= LINESTYLE;
217 if (fillStyle1 != -1)
218 state |= FILLSTYLE1;
219 if (fillStyle0 != -1)
220 state |= FILLSTYLE0;
221 if (move)
222 state |= MOVE;
223 swf.writeUBits(state, 6);
224
225 if (move) {
226 int numMoveBits = Math.max(BitOutputStream.minBits(moveX, true), BitOutputStream
227 .minBits(moveY, true));
228 swf.writeUBits(numMoveBits, 5);
229 swf.writeSBits(moveX, numMoveBits);
230 swf.writeSBits(moveY, numMoveBits);
231 }
232
233 if (fillStyle0 != -1)
234 swf.writeUBits(fillStyle0, numFillBits);
235 if (fillStyle1 != -1)
236 swf.writeUBits(fillStyle1, numFillBits);
237 if (lineStyle != -1)
238 swf.writeUBits(lineStyle, numLineBits);
239
240 if (newFillStyles != null) {
241 newFillStyles.write(swf, isMorphStyle, hasAlpha);
242 newLineStyles.write(swf, isMorphStyle, hasAlpha, hasStyles);
243 swf.writeUBits(numFillBits, 4);
244 swf.writeUBits(numLineBits, 4);
245 }
246 }
247
248 public int getNumFillBits() {
249 int numFillBits = 0;
250 if (fillStyle0 != -1)
251 numFillBits = Math.max(numFillBits, BitOutputStream
252 .minBits(fillStyle0));
253 if (fillStyle1 != -1)
254 numFillBits = Math.max(numFillBits, BitOutputStream
255 .minBits(fillStyle1));
256 return numFillBits;
257 }
258
259 public int getNumLineBits() {
260 return (lineStyle != -1) ? BitOutputStream.minBits(lineStyle) : 0;
261 }
262
263 public String toString() {
264 StringBuffer s = new StringBuffer();
265 if (move)
266 s.append("moveto(" + moveX + ", " + moveY + "); ");
267 if (fillStyle0 != -1)
268 s.append("fillStyle0=" + fillStyle0 + "; ");
269 if (fillStyle1 != -1)
270 s.append("fillStyle1=" + fillStyle1 + "; ");
271 if (lineStyle != -1)
272 s.append("lineStyle=" + lineStyle + "; ");
273 if ((newFillStyles != null) || (newLineStyles != null))
274 s.append("More Styles;\n");
275 if (newFillStyles != null)
276 s.append(newFillStyles.toString());
277 if (newLineStyles != null)
278 s.append(newLineStyles.toString());
279 return s.toString();
280 }
281 }
282
283
284
285
286 public static class EdgeRecord extends Record {
287
288 boolean curve;
289
290 int controlDeltaX, controlDeltaY, anchorDeltaX, anchorDeltaY;
291
292 int deltaX, deltaY;
293
294 public EdgeRecord(int controlDeltaX, int controlDeltaY,
295 int anchorDeltaX, int anchorDeltaY) {
296 curve = true;
297 this.controlDeltaX = controlDeltaX;
298 this.controlDeltaY = controlDeltaY;
299 this.anchorDeltaX = anchorDeltaX;
300 this.anchorDeltaY = anchorDeltaY;
301 }
302
303 public EdgeRecord(int deltaX, int deltaY) {
304 curve = false;
305 this.deltaX = deltaX;
306 this.deltaY = deltaY;
307 }
308
309 EdgeRecord(SWFInputStream input) throws IOException {
310 curve = !input.readBitFlag();
311 int numBits = (int) input.readUBits(4) + 2;
312 if (curve) {
313 controlDeltaX = (int) input.readSBits(numBits);
314 controlDeltaY = (int) input.readSBits(numBits);
315 anchorDeltaX = (int) input.readSBits(numBits);
316 anchorDeltaY = (int) input.readSBits(numBits);
317 } else {
318 if (input.readBitFlag()) {
319
320 deltaX = (int) input.readSBits(numBits);
321 deltaY = (int) input.readSBits(numBits);
322 } else {
323 if (input.readBitFlag()) {
324
325 deltaX = 0;
326 deltaY = (int) input.readSBits(numBits);
327 } else {
328
329 deltaX = (int) input.readSBits(numBits);
330 deltaY = 0;
331 }
332 }
333 }
334 }
335
336 public void write(SWFOutputStream swf, int numFillBits,
337 int numLineBits, boolean isMorphStyle, boolean hasAlpha, boolean hasStyles) throws IOException {
338
339 swf.writeBitFlag(true);
340 swf.writeBitFlag(!curve);
341
342 int numBits = 0;
343 if (curve) {
344 numBits = Math.max(numBits, BitOutputStream.minBits(controlDeltaX, true));
345 numBits = Math.max(numBits, BitOutputStream.minBits(controlDeltaY, true));
346 numBits = Math.max(numBits, BitOutputStream.minBits(anchorDeltaX, true));
347 numBits = Math.max(numBits, BitOutputStream.minBits(anchorDeltaY, true));
348 } else {
349 if ((deltaX != 0) && (deltaY != 0)) {
350 numBits = Math.max(numBits, BitOutputStream.minBits(deltaX, true));
351 numBits = Math.max(numBits, BitOutputStream.minBits(deltaY, true));
352 } else {
353 if (deltaX == 0) {
354
355 numBits = Math.max(numBits, BitOutputStream.minBits(deltaY, true));
356 } else {
357
358 numBits = Math.max(numBits, BitOutputStream.minBits(deltaX, true));
359 }
360 }
361 }
362 swf.writeUBits(numBits - 2, 4);
363
364 if (curve) {
365 swf.writeSBits(controlDeltaX, numBits);
366 swf.writeSBits(controlDeltaY, numBits);
367 swf.writeSBits(anchorDeltaX, numBits);
368 swf.writeSBits(anchorDeltaY, numBits);
369 } else {
370 if ((deltaX != 0) && (deltaY != 0)) {
371
372 swf.writeBitFlag(true);
373 swf.writeSBits(deltaX, numBits);
374 swf.writeSBits(deltaY, numBits);
375 } else {
376 swf.writeBitFlag(false);
377 if (deltaX == 0) {
378
379 swf.writeBitFlag(true);
380 swf.writeSBits(deltaY, numBits);
381 } else {
382
383 swf.writeBitFlag(false);
384 swf.writeSBits(deltaX, numBits);
385 }
386 }
387 }
388 }
389
390 public String toString() {
391 if (curve) {
392 return "rcurveto(" + controlDeltaX + ", " + controlDeltaY
393 + ", " + anchorDeltaX + ", " + anchorDeltaY + ")";
394 } else {
395 return "rlineto(" + deltaX + ", " + deltaY + ")";
396 }
397 }
398 }
399 }