KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openlaszlo > iv > flash > api > shape > ShapeRecords


1 /*
2  * $Id: ShapeRecords.java,v 1.2 2002/02/15 23:44:28 skavish Exp $
3  *
4  * ==========================================================================
5  *
6  * The JGenerator Software License, Version 1.0
7  *
8  * Copyright (c) 2000 Dmitry Skavish (skavish@usa.net). All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution, if
22  * any, must include the following acknowlegement:
23  * "This product includes software developed by Dmitry Skavish
24  * (skavish@usa.net, http://www.flashgap.com/)."
25  * Alternately, this acknowlegement may appear in the software itself,
26  * if and wherever such third-party acknowlegements normally appear.
27  *
28  * 4. The name "The JGenerator" must not be used to endorse or promote
29  * products derived from this software without prior written permission.
30  * For written permission, please contact skavish@usa.net.
31  *
32  * 5. Products derived from this software may not be called "The JGenerator"
33  * nor may "The JGenerator" appear in their names without prior written
34  * permission of Dmitry Skavish.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL DMITRY SKAVISH OR THE OTHER
40  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  *
49  */

50
51 package org.openlaszlo.iv.flash.api.shape;
52
53 import java.io.PrintStream JavaDoc;
54 import java.awt.geom.*;
55 import java.util.*;
56
57 import org.openlaszlo.iv.flash.util.*;
58 import org.openlaszlo.iv.flash.api.*;
59 import org.openlaszlo.iv.flash.parser.*;
60
61 /**
62  * Shape records.
63  * <P>
64  * Provides basic functionality for drawing geometric primitives.
65  *
66  * @author Dmitry Skavish
67  */

68 public class ShapeRecords extends FlashItem {
69
70     private IVVector shape_records;
71
72     // last drawing positions, used to keep track of drawing pen
73
private int last_x = Integer.MAX_VALUE;
74     private int last_y = Integer.MAX_VALUE;
75
76     public ShapeRecords() {
77         this( new IVVector() );
78     }
79
80     public ShapeRecords( IVVector shape_records ) {
81         this.shape_records = shape_records;
82     }
83
84     /**
85      * Returns vector of shape records.
86      *
87      * @return vector of shape records
88      */

89     public IVVector getShapeRecords() {
90         return shape_records;
91     }
92
93     /**
94      * Draws curve record.<p>
95      * All coordinates are in twixels.
96      *
97      * @param cx X control point
98      * @param cy Y control point
99      * @param ax X anchor point
100      * @param ay Y anchor point
101      */

102     public void drawCurveTo( int cx, int cy, int ax, int ay ) {
103         shape_records.addElement( new CurvedEdgeRecord(cx-last_x, cy-last_y, ax-cx, ay-cy) );
104         last_x = ax;
105         last_y = ay;
106     }
107
108     /**
109      * Draws curve record.<p>
110      * All coordinates are in twixels.
111      *
112      * @param ax1 X anchor point 1
113      * @param ay1 Y anchor point 1
114      * @param cx X control point
115      * @param cy Y control point
116      * @param ax2 X anchor point 2
117      * @param ay2 Y anchor point 2
118      */

119     public void drawCurve( int ax1, int ay1, int cx, int cy, int ax2, int ay2 ) {
120         movePenTo(ax1, ay1);
121         drawCurveTo(cx, cy, ax2, ay2);
122     }
123
124     /**
125      * Draws curve record.<p>
126      * All coordinates are in twixels.
127      *
128      * @param anchor0 first anchor point
129      * @param control control point
130      * @param anchor1 second anchor point
131      */

132     public void drawCurve( Point2D anchor1, Point2D control, Point2D anchor2 ) {
133         drawCurve( (int) anchor1.getX(), (int) anchor1.getY(),
134                    (int) control.getX(), (int) control.getY(),
135                    (int) anchor2.getX(), (int) anchor2.getY() );
136     }
137
138     /**
139      * Draws a straight line from current position to the specified one.<p>
140      * All coordinates are in twixels.
141      *
142      * @param x X of end of line
143      * @param y Y of end of line
144      */

145     public void drawLineTo( int x, int y ) {
146         int deltaX = x-last_x;
147         int deltaY = y-last_y;
148         if( deltaX == 0 ) {
149             if( deltaY == 0 ) return;
150             shape_records.addElement( StrightEdgeRecord.newVLine(deltaY) );
151         } else if( deltaY == 0 ) {
152             shape_records.addElement( StrightEdgeRecord.newHLine(deltaX) );
153         } else {
154             shape_records.addElement( StrightEdgeRecord.newLine(deltaX,deltaY) );
155         }
156         last_x = x;
157         last_y = y;
158     }
159
160     /**
161      * Draws a straight line from current position to the specified one.<p>
162      * All coordinates are in twixels.
163      *
164      * @param p1 end of line
165      */

166     public void drawLineTo( Point2D p1 ) {
167         drawLineTo( (int) p1.getX(), (int) p1.getY() );
168     }
169
170     /**
171      * Draws a straight line specified by two points.
172      * <P>
173      * All coordinates are in twixels.
174      *
175      * @param x1 X of the beginning of the line
176      * @param y1 Y of the beginning of the line
177      * @param x2 X of the end of the line
178      * @param y2 Y of the end of the line
179      */

180     public void drawLine( int x1, int y1, int x2, int y2 ) {
181         movePenTo( x1, y1 );
182         drawLineTo( x2, y2 );
183     }
184
185     /**
186      * Draws a straight line specified by two points.
187      * <P>
188      * All coordinates are in twixels.
189      *
190      * @param p0 first point
191      * @param p1 second point
192      */

193     public void drawLine( Point2D p0, Point2D p1 ) {
194         drawLine( (int) p0.getX(), (int) p0.getY(), (int) p1.getX(), (int) p1.getY() );
195     }
196
197     /**
198      * Draws a rectangle specified by its top-left corner and width and height
199      * <p>
200      * All coordinates are in twixels.
201      *
202      * @param x x coordinates of top-left corner of the rectangle
203      * @param y y coordinates of top-left corner of the rectangle
204      * @param width width of the rectangle
205      * @param height height of the rectangle
206      */

207     public void drawRectangle( int x, int y, int width, int height ) {
208         movePenTo( x, y );
209         drawLineTo( x+width, y );
210         drawLineTo( x+width, y+height );
211         drawLineTo( x, y+height );
212         drawLineTo( x, y );
213     }
214
215     /**
216      * Draws a rectangle specified by {@link java.awt.geom.Rectangle2D}
217      * <p>
218      * All coordinates are in twixels.
219      *
220      * @param r specified rectangle
221      */

222     public void drawRectangle( Rectangle2D r ) {
223         drawRectangle( (int) r.getX(), (int) r.getY(), (int) r.getWidth(), (int) r.getHeight() );
224     }
225
226     /**
227      * Moves pen to the specified position.<p>
228      * All coordinates are ABSOLUTE and are in twixels.
229      *
230      * @param x new current X
231      * @param y new current Y
232      */

233     public void movePenTo( int x, int y ) {
234         if( last_x != x || last_y != y ) {
235             StyleChangeRecord sc = getStyleChange();
236             sc.addFlags( StyleChangeRecord.MOVETO );
237             sc.setDeltaX(x);
238             sc.setDeltaY(y);
239             last_x = x;
240             last_y = y;
241         }
242     }
243
244     /**
245      * Moves pen to the specified point.<p>
246      * All coordinates are ABSOLUTE and are in twixels!
247      *
248      * @param p new pen position
249      */

250     public void movePenTo( Point2D p ) {
251         movePenTo( (int) p.getX(), (int) p.getY() );
252     }
253
254     /**
255      * Returns current pen position
256      *
257      * @return current pen position
258      */

259     public Point2D getCurrentPos() {
260         return new Point2D.Double(last_x, last_y);
261     }
262
263     /**
264      * Returns first pen position (first moveTo)
265      *
266      * @return first pen position
267      */

268     public Point2D getFirstPos() {
269         for( int i=0; i<shape_records.size(); i++ ) {
270             FlashItem item = (FlashItem) shape_records.elementAt(i);
271             if( item instanceof StyleChangeRecord ) {
272                 StyleChangeRecord sr = (StyleChangeRecord) item;
273                 if( (sr.getFlags()&StyleChangeRecord.MOVETO) == 0 ) continue;
274                 return new Point2D.Double(sr.getDeltaX(), sr.getDeltaY());
275             }
276
277         }
278         return new Point2D.Double(0,0);
279     }
280
281     /**
282      * Draw AWT Shape
283      * <P>
284      * All shape coordinates are in twixels!
285      *
286      * @param shape AWT shape
287      */

288     public void drawAWTShape( java.awt.Shape JavaDoc shape ) {
289         PathIterator pi = shape.getPathIterator(null);
290         drawAWTPathIterator(pi);
291     }
292
293     /**
294      * Draw AWT Shape
295      * <P>
296      * All shape coordinates are in twixels!
297      *
298      * @param shape AWT shape
299      */

300     public void drawAWTShape( java.awt.Shape JavaDoc shape, AffineTransform matrix ) {
301         PathIterator pi = shape.getPathIterator(matrix);
302         drawAWTPathIterator(pi);
303     }
304
305     /**
306      * Draw AWT PathIterator
307      * <P>
308      * All coordinates are in twixels!
309      *
310      * @param pi AWT PathIterator
311      */

312     public void drawAWTPathIterator( java.awt.geom.PathIterator JavaDoc pi ) {
313         double[] coords = new double[6];
314
315         int last_move_x = 0;
316         int last_move_y = 0;
317
318         while( !pi.isDone() ) {
319             int type = pi.currentSegment( coords );
320             switch( type ) {
321                 case PathIterator.SEG_MOVETO: {
322                     last_move_x = (int) coords[0];
323                     last_move_y = (int) coords[1];
324                     movePenTo( last_move_x, last_move_y );
325                     break;
326                 }
327                 case PathIterator.SEG_CLOSE: {
328                     drawLineTo( last_move_x, last_move_y );
329                     break;
330                 }
331                 case PathIterator.SEG_LINETO: {
332                     int x = (int) coords[0];
333                     int y = (int) coords[1];
334                     drawLineTo( x, y );
335                     break;
336                 }
337                 case PathIterator.SEG_QUADTO: {
338                     int cx = (int) coords[0];
339                     int cy = (int) coords[1];
340                     int ax = (int) coords[2];
341                     int ay = (int) coords[3];
342                     drawCurveTo( cx, cy, ax, ay );
343                     break;
344                 }
345                 case PathIterator.SEG_CUBICTO: {
346                     double c1x = coords[0];
347                     double c1y = coords[1];
348                     double c2x = coords[2];
349                     double c2y = coords[3];
350                     double ax = coords[4];
351                     double ay = coords[5];
352
353                     // construct coefficients of qubic curve
354
Point2D p0 = new Point2D.Double(last_x, last_y);
355                     Point2D p1 = new Point2D.Double(c1x, c1y);
356                     Point2D p2 = new Point2D.Double(c2x, c2y);
357                     Point2D p3 = new Point2D.Double(ax, ay);
358
359                     // break cubic curve into qudratic ones
360
Point2D[] quad_curves = GeomHelper.CubicToQudratricBezier(p0, p1, p2, p3);
361
362                     // draw resulting quadratic curves
363
for( int i=0; i<quad_curves.length; i+=3 ) {
364                         Point2D anchor1 = quad_curves[i];
365                         Point2D control = quad_curves[i+1];
366                         Point2D anchor2 = quad_curves[i+2];
367                         drawCurve(anchor1, control, anchor2);
368                     }
369                     break;
370                 }
371             }
372             pi.next();
373         }
374     }
375
376     /**
377      * Add style change record
378      *
379      * @param scr add this record
380      */

381     public StyleChangeRecord addStyleChangeRecord( StyleChangeRecord scr ) {
382         shape_records.addElement(scr);
383         return scr;
384     }
385
386     /**
387      * Add style change record
388      */

389     public StyleChangeRecord addStyleChangeRecord() {
390         StyleChangeRecord scr = new StyleChangeRecord();
391         shape_records.addElement(scr);
392         return scr;
393     }
394
395     protected StyleChangeRecord getStyleChange() {
396         if( shape_records.size() > 0 ) {
397             FlashItem item = (FlashItem) shape_records.elementAt( shape_records.size()-1 );
398             if( item instanceof StyleChangeRecord ) return (StyleChangeRecord) item;
399         }
400         return addStyleChangeRecord();
401     }
402
403     public static ShapeRecords parse( Parser p ) {
404         return new ShapeRecords(parseShapeRecords(p));
405     }
406
407     public static IVVector parseShapeRecords( Parser p ) {
408         IVVector shape_records = new IVVector();
409
410         // parse shape records
411
int nBits = p.getUByte();
412         int nFillBits = (nBits&0xf0)>>4;
413         int nLineBits = nBits&0x0f;
414         p.initBits();
415         for(;;) {
416             if( p.getBool() ) { // edge record
417
if( p.getBool() ) { // stright edge
418
int nb = p.getBits(4)+2;
419                     if( p.getBool() ) { // general line
420
int deltaX = p.getSBits(nb);
421                         int deltaY = p.getSBits(nb);
422                         shape_records.addElement( StrightEdgeRecord.newLine(deltaX, deltaY) );
423                     } else if( p.getBool() ) { // vertical line
424
int deltaY = p.getSBits(nb);
425                         shape_records.addElement( StrightEdgeRecord.newVLine(deltaY) );
426                     } else { // horizontal line
427
int deltaX = p.getSBits(nb);
428                         shape_records.addElement( StrightEdgeRecord.newHLine(deltaX) );
429                     }
430                 } else { // curved edge
431
int nb = p.getBits(4)+2;
432                     int cx = p.getSBits(nb);
433                     int cy = p.getSBits(nb);
434                     int ax = p.getSBits(nb);
435                     int ay = p.getSBits(nb);
436                     shape_records.addElement( new CurvedEdgeRecord(cx, cy, ax, ay) );
437                 }
438             } else { // style-change record (non-edge)
439
int flags = p.getBits(5);
440                 if( flags == 0 ) break; // end record
441
StyleChangeRecord scr = new StyleChangeRecord();
442                 scr.setFlags( flags );
443
444                 if( (flags & StyleChangeRecord.MOVETO) != 0 ) {
445                     int nMoveBits = p.getBits(5);
446                     scr.setDeltaX( p.getSBits(nMoveBits) );
447                     scr.setDeltaY( p.getSBits(nMoveBits) );
448                 }
449
450                 if( (flags & StyleChangeRecord.FILLSTYLE0) != 0 ) {
451                     scr.setFillStyle0( p.getBits(nFillBits) );
452                 }
453
454                 if( (flags & StyleChangeRecord.FILLSTYLE1) != 0 ) {
455                     scr.setFillStyle1( p.getBits(nFillBits) );
456                 }
457
458                 if( (flags & StyleChangeRecord.LINESTYLE) != 0 ) {
459                     scr.setLineStyle( p.getBits(nLineBits) );
460                 }
461
462                 shape_records.addElement( scr );
463
464                 if( (flags&0x80) != 0 ) {
465                     break;
466                 }
467             }
468         }
469
470         return shape_records;
471     }
472
473     /**
474      * Writes this shape records into specified buffer, writes end of records and flush the bits.
475      * Number of fill and line style bits is considered to be 0 (zero).
476      *
477      * @param fob buffer
478      */

479     public void write( FlashOutput fob ) {
480         fob.initBits();
481         shape_records.write(fob);
482         fob.writeBits(0, 6);
483         fob.flushBits();
484     }
485
486     /**
487      * Writes this shape records into specified buffer but does not flush last bits and
488      * does not write end of record, it has to be done separatedly.
489      *
490      * @param fob specified buffer
491      * @param nFillBits number of fill bits
492      * @param nLineBits number of line bits
493      */

494     public void write( FlashOutput fob, int nFillBits, int nLineBits ) {
495         fob.initBits();
496         for( int i=0; i<shape_records.size(); i++ ) {
497             FlashItem item = (FlashItem) shape_records.elementAt(i);
498             if( item instanceof StyleChangeRecord ) {
499                 StyleChangeRecord scr = (StyleChangeRecord) item;
500                 scr.write(fob, nFillBits, nLineBits);
501             } else {
502                 item.write(fob);
503             }
504         }
505     }
506
507     public void printContent( PrintStream JavaDoc out, String JavaDoc indent ) {
508         out.println( indent+"ShapeRecords:" );
509         shape_records.printContent(out, indent+" ");
510     }
511
512     protected FlashItem copyInto( FlashItem item, ScriptCopier copier ) {
513         super.copyInto( item, copier );
514         ((ShapeRecords)item).shape_records = shape_records.getCopy(copier);
515         return item;
516     }
517
518     public FlashItem getCopy( ScriptCopier copier ) {
519         return copyInto( new ShapeRecords(null), copier );
520     }
521 }
522
523
Popular Tags