KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openlaszlo > iv > flash > util > FlashBuffer


1 /*
2  * $Id: FlashBuffer.java,v 1.4 2002/07/15 02:15:03 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.util;
52
53 import java.awt.geom.AffineTransform JavaDoc;
54 import java.awt.geom.Rectangle2D JavaDoc;
55 import java.io.*;
56 import org.openlaszlo.iv.flash.api.*;
57
58 /**
59  * Wrapper of array of bytes.
60  * <p>
61  * Provides reading and writing of flash related data types.
62  *
63  * @author Dmitry Skavish
64  * @see FlashOutput
65  */

66 public class FlashBuffer {
67
68     // bit buffer and position
69
private int bitBuf;
70     private int bitPos;
71
72     // byte array
73
private byte buf[];
74
75     // current position in the buffer for reading and writing
76
public int pos;
77
78     // size of the buffer
79
private int size;
80
81     public FlashBuffer() {
82     }
83
84     /**
85      * Allocates buffer of given capacity.<p>
86      * Sets current position and size to zero.
87      *
88      * @param capacity capacity of allocated buffer in bytes
89      */

90     public FlashBuffer( int capacity ) {
91         this( new byte[capacity], 0, 0 );
92     }
93
94     /**
95      * Creates buffer from given one.<p>
96      * Sets current position to zero and size to the size of the buffer.
97      *
98      * @param buf buffer to init from
99      */

100     public FlashBuffer( byte[] buf ) {
101         this( buf, 0, buf.length );
102     }
103
104     /**
105      * Creates buffer from given one of specified size.<p>
106      * Sets current position to zero and size to given value.
107      *
108      * @param buf buffer to init from
109      * @param size size of buffer
110      */

111     public FlashBuffer( byte[] buf, int size ) {
112         this( buf, 0, size );
113     }
114
115     /**
116      * Creates buffer from given one of specified size and position.
117      *
118      * @param buf buffer to init from
119      * @param pos current position
120      * @param size size of filled buffer (writer pos)
121      */

122     public FlashBuffer( byte[] buf, int pos, int size ) {
123         init( buf, pos, size );
124     }
125
126     /**
127      * Creates FlashBuffer from input stream.<p>
128      * Reads InputStream into the buffer, sets current position
129      * to zero and size to the size of data read.
130      *
131      * @author Andrew Wason
132      * @author Dmitry Skavish
133      * @param is InputStream to read from
134      * @exception IOException
135      */

136     public FlashBuffer( InputStream is ) throws IOException {
137         size = 0;
138         try {
139             int count = is.available();
140             if( count <= 0 ) count = 4096;
141             buf = new byte[count+8]; // make it a little bit bigger to avoid reallocation
142
for(;;) {
143                 count = is.read(buf, size, buf.length - size);
144                 if( count == -1 ) break;
145                 size += count;
146                 if( size == buf.length )
147                     ensureCapacity(buf.length + 4096 * 4);
148             }
149         } finally {
150             is.close();
151         }
152         pos = 0;
153         bitBuf = 0;
154         bitPos = 0;
155     }
156
157     public void init( byte[] buf, int pos, int size ) {
158         this.buf = buf;
159         this.pos = pos;
160         this.size = size;
161         this.bitBuf = 0;
162         this.bitPos = 0;
163     }
164
165     /**
166      * Ensures that the buffer is as big as specified number of bytes
167      *
168      * @param cap required size of buffer
169      */

170     public final void ensureCapacity( int cap ) {
171         if( cap > buf.length ) {
172             int max = buf.length*2;
173             if( cap > max ) max = cap+16;
174             if( max < 4096 ) max = 4096;
175             byte[] newBuf = new byte[max];
176             System.arraycopy(buf, 0, newBuf, 0, buf.length);
177             buf = newBuf;
178         }
179     }
180
181     /**
182      * Creates copy of the buffer.
183      *
184      * @return copy of the buffer
185      */

186     public FlashBuffer getCopy() {
187         byte[] myBuf = new byte[buf.length];
188         System.arraycopy(buf, 0, myBuf, 0, buf.length);
189         return new FlashBuffer( myBuf, pos, size );
190     }
191
192     /**
193      * Current read/write position.
194      *
195      * @return current read/write position
196      */

197     public final int getPos() {
198         return pos;
199     }
200
201     /**
202      * Returns size of the buffer.
203      *
204      * @return size of the buffer
205      */

206     public final int getSize() {
207         return size;
208     }
209
210     /**
211      * Sets current read/write position.<P>
212      * Does not increase the buffer if new position is larger
213      * than current capacity.
214      *
215      * @param pos new position
216      * @see #ensureCapacity
217      */

218     public final void setPos( int pos ) {
219         this.pos = pos;
220         if( pos > size ) size = pos;
221     }
222
223     /**
224      * Increment current position.<p>
225      * Does not increase the buffer if new position is larger
226      * than current capacity.
227      *
228      * @see #ensureCapacity
229      * @see #setPos
230      */

231     public final void incPos() {
232         if( ++pos > size ) size = pos;
233     }
234
235     /**
236      * Sets new size of the buffer.<p>
237      * Does not increase the buffer if new position is larger
238      * than current capacity.
239      *
240      * @param size new size of the buffer
241      */

242     public final void setSize( int size ) {
243         this.size = size;
244     }
245
246     /**
247      * Skips bytes (changes current position).<P>
248      * Does not increase the buffer if new position is larger
249      * than current capacity.
250      *
251      * @param inc advance value
252      */

253     public final void skip( int inc ) {
254         setPos( pos + inc );
255     }
256
257     /**
258      * Returns the whole buffer.
259      *
260      * @return buffer
261      */

262     public final byte[] getBuf() {
263         return buf;
264     }
265
266     /*-----------------------------------------------------------------------
267      * W R I T E R
268      *-----------------------------------------------------------------------*/

269
270     /**
271      * Writes byte at specified position.<p>
272      * Does not change current position.
273      *
274      * @param b byte to write
275      * @param pos position to write
276      */

277     public final void writeByteAt( int b, int pos ) {
278         buf[pos] = (byte) b;
279     }
280
281     /**
282      * Writes word at specified position.<p>
283      * Does not change current position.
284      *
285      * @param b word to write
286      * @param pos position to write
287      */

288     public final void writeWordAt( int b, int pos ) {
289         buf[pos] = (byte) b;
290         buf[pos+1] = (byte) (b>>8);
291     }
292
293     /**
294      * Writes dword at specified position.<p>
295      * Does not change current position.
296      *
297      * @param b dword to write
298      * @param pos position to write
299      */

300     public final void writeDWordAt( int b, int pos ) {
301         buf[pos] = (byte) b;
302         buf[pos+1] = (byte) (b>>8);
303         buf[pos+2] = (byte) (b>>16);
304         buf[pos+3] = (byte) (b>>24);
305     }
306
307     /**
308      * Writes byte and advance current position.
309      *
310      * @param b byte to write
311      */

312     public final void writeByte( int b ) {
313         ensureCapacity( pos+1 );
314         buf[pos] = (byte) b;
315         incPos();
316     }
317
318     /**
319      * Writes word and advance current position.
320      *
321      * @param b word to write
322      */

323     public final void writeWord( int b ) {
324         ensureCapacity( pos+2 );
325         buf[pos] = (byte) b;
326         buf[pos+1] = (byte) (b>>8);
327         setPos( pos+2 );
328     }
329
330     /**
331      * Writes dword and advance current position.
332      *
333      * @param b dword to write
334      */

335     public final void writeDWord( int b ) {
336         ensureCapacity( pos+4 );
337         buf[pos] = (byte) b;
338         buf[pos+1] = (byte) (b>>8);
339         buf[pos+2] = (byte) (b>>16);
340         buf[pos+3] = (byte) (b>>24);
341         setPos( pos+4 );
342     }
343
344
345     /****************************************************************
346      * Fast operations do not call ensureCapacity
347      */

348
349     /**
350      * Writes byte and advance current position.
351      *
352      * @param b byte to write
353      */

354     public final void _writeByte( int b ) {
355         buf[pos++] = (byte) b;
356     }
357
358     /**
359      * Writes word and advance current position.
360      *
361      * @param b word to write
362      */

363     public final void _writeWord( int b ) {
364         buf[pos++] = (byte) b;
365         buf[pos++] = (byte) (b>>8);
366     }
367
368     /**
369      * Writes dword and advance current position.
370      *
371      * @param b dword to write
372      */

373     public final void _writeDWord( int b ) {
374         buf[pos++] = (byte) b;
375         buf[pos++] = (byte) (b>>8);
376         buf[pos++] = (byte) (b>>16);
377         buf[pos++] = (byte) (b>>24);
378     }
379
380
381     /**
382      * Writes zero-ending string into the buffer and advance current position.
383      * (Flash5 back compatibility, uses Cp1252 encoding)
384      * @param s string to write
385      */

386     public final byte[] _writeStringZ( String JavaDoc s ) {
387         return _writeStringZ(s, "Cp1252");
388     }
389
390
391     /**
392      * Writes zero-ending string into the buffer and advance current position.
393      *
394      * @param s string to write
395      * @return the string converted to a byte array in Flash's favorite encoding
396      */

397     public final byte[] _writeStringZ( String JavaDoc s, String JavaDoc encoding ) {
398         byte chars[];
399         try {
400             chars = s.getBytes(encoding);
401         } catch (UnsupportedEncodingException e) {
402             throw new RuntimeException JavaDoc("could not convert string to "+encoding);
403         }
404         System.arraycopy(chars, 0, buf, pos, chars.length);
405         setPos( pos+chars.length );
406         buf[pos++] = 0; // null-terminate the string
407
return chars;
408     }
409
410
411
412     /**
413      * Writes array into this one and advance current position.
414      *
415      * @param b intput buffer
416      * @param off offset in the input buffer
417      * @param len number of bytes in input buffer
418      */

419     public final void _writeArray( byte b[], int off, int len ) {
420         System.arraycopy(b, off, buf, pos, len);
421         setPos( pos+len );
422     }
423
424
425     /****************************************************************/
426
427
428
429     /**
430      * Writes FlashBuffer into this one and advance current position.
431      *
432      * @param fob buffer to write
433      */

434     public final void writeFOB( FlashBuffer fob ) {
435         int len = fob.getSize();
436         ensureCapacity( pos+len );
437         System.arraycopy(fob.getBuf(), 0, buf, pos, len);
438         setPos( pos+len );
439     }
440
441     /**
442      * Writes array into this one and advance current position.
443      *
444      * @param b intput buffer
445      * @param off offset in the input buffer
446      * @param len number of bytes in input buffer
447      */

448     public final void writeArray( byte b[], int off, int len ) {
449         ensureCapacity( pos+len );
450         System.arraycopy(b, off, buf, pos, len);
451         setPos( pos+len );
452     }
453
454     /**
455      * Writes zero-ending string into the buffer and advance current position.
456      *
457      * +++ Back compatible with Jgen-1.4/Flash5
458      * Uses default encoding of JGen 1.4, "Cp1252".
459      * @param s string to write
460      *
461      */

462
463     public final byte[] writeStringZ( String JavaDoc s ) {
464         return writeStringZ(s, "Cp1252");
465     }
466
467
468     /**
469      * Writes zero-ending string into the buffer and advance current position.
470      *
471      * @param s string to write
472      * @param encoding charset encoding to use
473      *
474      */

475
476     public final byte[] writeStringZ( String JavaDoc s, String JavaDoc encoding ) {
477         byte chars[];
478         try {
479             // encode utf-8 for flash 6
480
chars = s.getBytes(encoding);
481         } catch (UnsupportedEncodingException e) {
482             throw new RuntimeException JavaDoc("could not convert string to "+encoding);
483         }
484         ensureCapacity( pos+chars.length+1 );
485         for( int i=0; i<chars.length; i++ ) {
486             buf[pos++] = chars[i];
487         }
488         buf[pos] = 0;
489         incPos();
490         return chars;
491     }
492
493     /**
494      * Writes length-prefixed string into the buffer and advance current position.
495      *
496      * @param s string to write
497      */

498     public final void writeStringL( String JavaDoc s ) {
499         writeStringL(s, "Cp1252");
500     }
501
502     /**
503      * Writes length-prefixed string into the buffer and advance current position.
504      *
505      * @param s string to write
506      * @param encoding charset encoding to use
507      */

508     public final void writeStringL( String JavaDoc s, String JavaDoc encoding ) {
509
510         byte chars[];
511         try {
512             chars = s.getBytes(encoding);
513         } catch (UnsupportedEncodingException e) {
514             throw new RuntimeException JavaDoc("could not convert string to "+encoding);
515         }
516         ensureCapacity( pos+chars.length+1 );
517         buf[pos++] = (byte) chars.length;
518         for( int i=0; i<chars.length; i++ ) {
519             buf[pos++] = chars[i];
520         }
521         setPos( pos ); // to update size
522
}
523
524     /**
525      * Writes flash tag into the buffer and advance current position.<P>
526      * Depending on tag length writes short or long tag
527      *
528      * @param tagCode tag code
529      * @param tagSize tag size
530      * @see Tag
531      * @see #writeLongTag
532      * @see #writeLongTagAt
533      * @see #writeShortTagAt
534      */

535     public final void writeTag( int tagCode, int tagSize ) {
536         if( tagSize >= 0x3f ) {
537             writeLongTag( tagCode, tagSize );
538         } else {
539             writeWord( (tagCode<<6) | tagSize );
540         }
541     }
542
543     /**
544      * Writes long flash tag into the buffer and advance current position.<P>
545      *
546      * @param tagCode tag code
547      * @param tagSize tag size
548      * @see Tag
549      * @see #writeTag
550      * @see #writeLongTagAt
551      * @see #writeShortTagAt
552      */

553     public final void writeLongTag( int tagCode, int tagSize ) {
554         writeWord( (tagCode<<6) | 0x3f );
555         writeDWord( tagSize );
556     }
557
558     /**
559      * Writes short flash tag into the buffer at specified position.<P>
560      * Does not advance position
561      *
562      * @param tagCode tag code
563      * @param tagSize tag size
564      * @see Tag
565      * @see #writeLongTag
566      * @see #writeLongTagAt
567      * @see #writeTag
568      */

569     public final void writeShortTagAt( int tagCode, int tagSize, int pos ) {
570         writeWordAt( (tagCode<<6) | tagSize, pos );
571     }
572
573     /**
574      * Writes long flash tag into the buffer at specified position.<P>
575      * Does not advance position
576      *
577      * @param tagCode tag code
578      * @param tagSize tag size
579      * @see Tag
580      * @see #writeLongTag
581      * @see #writeShortTagAt
582      * @see #writeTag
583      */

584     public final void writeLongTagAt( int tagCode, int tagSize, int pos ) {
585         writeWordAt( (tagCode<<6) | 0x3f, pos );
586         writeDWordAt( tagSize, pos+2 );
587     }
588
589     /**
590      * Writes lower bit to bit buffer.
591      *
592      * @param b bit to write
593      * @see #initBits
594      * @see #flushBits
595      * @see #writeBits
596      */

597     public final void writeBit( int b ) {
598         writeBits( b, 1 );
599     }
600
601     /**
602      * Writes boolean as a bit to bit buffer.
603      *
604      * @param b boolean to write
605      * @see #initBits
606      * @see #flushBits
607      */

608     public final void writeBool( boolean b ) {
609         writeBits( b?1:0, 1 );
610     }
611
612     /**
613      * Writes bits into the buffer.<P>
614      * Before starting writing bits you have to init or flush bits
615      * buffer using methods {@link #initBits} or {@link #flushBits}
616      *
617      * @param v bits to write packed in integer
618      * @param len number of bits to write
619      * @see #initBits
620      * @see #flushBits
621      */

622     public final void writeBits( int v, int len ) {
623         ensureCapacity( pos+4 );
624         for(;;) {
625             v = v & ((1<<len)-1);
626             int l = 8-bitPos;
627             int s = l-len;
628             if( s >= 0 ) {
629                 bitBuf = (bitBuf<<len) | v;
630                 bitPos += len;
631                 return;
632             } else {
633                 s = -s;
634                 int bb = (bitBuf<<l) | (v>>>s);
635                 buf[pos] = (byte)bb;
636                 incPos();
637                 len = s;
638                 bitBuf = 0;
639                 bitPos = 0;
640             }
641         }
642     }
643
644     /**
645      * Flushes bits buffer into flash buffer.<P>
646      * Has to be called after you finished writing series of bits
647      *
648      * @see #writeBits
649      * @see #initBits
650      */

651     public final void flushBits() {
652         if( bitPos != 0 ) {
653             int bb = bitBuf << (8-bitPos);
654             writeByte( bb );
655         }
656         bitBuf = 0;
657         bitPos = 0;
658     }
659
660     /**
661      * Inits bits buffer.<P>
662      * Has to be called before writing series of bits or
663      * before reading bits
664      *
665      * @see #writeBits
666      * @see #flushBits
667      * @see #skipBits
668      * @see #getBits
669      */

670     public final void initBits() {
671         bitBuf = 0;
672         bitPos = 0;
673     }
674
675     /**
676      * Writes specified inputstream to this buffer
677      *
678      * @param is input stream
679      */

680     public final void write( InputStream is ) throws IOException {
681         try {
682             int count = is.available();
683             if( count <= 0 ) count = 4096;
684             ensureCapacity(pos+count+8);
685             for(;;) {
686                 count = is.read(buf, pos, buf.length - pos);
687                 if( count == -1 ) break;
688                 pos += count;
689                 if( pos == buf.length )
690                     ensureCapacity(buf.length + 4096 * 4);
691             }
692             setPos(pos);
693         } finally {
694             is.close();
695         }
696     }
697
698     /*-----------------------------------------------------------------------
699      * R E A D E R
700      *-----------------------------------------------------------------------*/

701
702     /**
703      * Skips bits.
704      *
705      * @param n number of bits to skip
706      * @see #initBits
707      */

708     public final void skipBits( int n ) {
709         for (;;) {
710             int s = n - bitPos;
711             if( s > 0 ) {
712                 n -= bitPos;
713                 // get the next buffer
714
bitBuf = getUByte();
715                 bitPos = 8;
716             } else {
717                 // Consume a portion of the buffer
718
s = -s;
719                 bitPos = s;
720                 bitBuf &= (1<<s)-1; // mask off the consumed bits
721
break;
722             }
723         }
724     }
725
726     /**
727      * Reads <b>unsigned</b> bits from the buffer.<P>
728      *
729      * According to profiler this is probably the most
730      * time consuming operation. Below there is a new version,
731      * but I did not test it much, it's about 30% percent faster.
732      *
733      * @param n number of bits to read
734      * @return read bits
735      * @see #initBits
736      * @see #getSBits
737      */

738     public final int getBits( int n ) {
739         // get n bits from the stream.
740
int v = 0;
741
742         for (;;) {
743             int s = n - bitPos;
744             if( s > 0 ) {
745                 // Consume the entire buffer
746
v |= bitBuf << s;
747                 n -= bitPos;
748
749                 // get the next buffer
750
bitBuf = getUByte();
751                 bitPos = 8;
752             } else {
753                 // Consume a portion of the buffer
754
s = -s;
755                 v |= bitBuf >> s;
756                 bitPos = s;
757                 bitBuf &= (1<<s)-1; // mask off the consumed bits
758
return v;
759             }
760         }
761     }
762
763     // new version of getBits
764
public final int new_getBits( int n ) {
765         // get n bits from the stream.
766

767         int s = n-bitPos;
768         if( s > 0 ) {
769             // Consume the entire buffer
770
int v = bitBuf << s;
771             n -= bitPos;
772
773             // get the next buffer
774
if( n <= 8 ) {
775                 bitBuf = getUByte();
776                 bitPos = 8;
777             } else if( n <= 16 ) {
778                 bitBuf = (getUByte()<<8) | getUByte();
779                 bitPos = 16;
780             } else if( n <= 24 ) {
781                 bitBuf = (getUByte()<<16) | (getUByte()<<8) | getUByte();
782                 bitPos = 24;
783             } else {
784                 bitBuf = (getUByte()<<24) | (getUByte()<<16) | (getUByte()<<8) | getUByte();
785                 bitPos = 32;
786             }
787             bitPos -= n;
788             v |= bitBuf >> bitPos;
789             bitBuf &= (1<<bitPos)-1;
790             return v;
791         }
792
793         // Consume a portion of the buffer
794
s = -s;
795         int v = bitBuf >> s;
796         bitPos = s;
797         bitBuf &= (1<<s)-1; // mask off the consumed bits
798
return v;
799     }
800
801     /**
802      * Reads <b>signed</b> bits from the buffer.<P>
803      *
804      * @param n number of bits to read
805      * @return read bits extended with sign
806      * @see #initBits
807      * @see #getBits
808      */

809     public final int getSBits( int n ) {
810         // get n bits from the string with sign extension.
811
// get the number as an unsigned value.
812
int v = getBits(n);
813
814         // Is the number negative?
815
if( (v & (1<<(n-1))) != 0 ) {
816             // Yes. Extend the sign.
817
v |= -1 << n;
818         }
819
820         return v;
821     }
822
823     /**
824      * Reads one bit and returns it as boolean
825      *
826      * @return true - if bit is 1, false - if bit is 0
827      */

828     public boolean getBool() {
829         return getBits(1) == 1;
830     }
831
832     /**
833      * Reads bytes into given FlashBuffer.
834      *
835      * @param fob flash buffer where to read bytes
836      * @param length number of bytes to read
837      */

838     public final void getTo( FlashBuffer fob, int length ) {
839         fob.writeArray(buf, pos, length);
840         pos += length;
841     }
842
843     /**
844      * Reads zero-ending string.
845      *
846      * @return read string
847      */

848     public final String JavaDoc getString() {
849         int sp = pos;
850         while( buf[pos++] != 0 );
851         return new String JavaDoc( buf, sp, pos-sp-1 );
852     }
853
854     /**
855      * Read string by its length.
856      *
857      * @param length string length
858      * @return read string
859      */

860     public final String JavaDoc getString( int length ) {
861         int sp = pos;
862         pos += length;
863         return new String JavaDoc(buf, sp, length);
864     }
865
866     /**
867      * Reads bytes into array of bytes.
868      *
869      * @param length number of bytes to read
870      * @return created array of bytes with data
871      */

872     public final byte[] getBytes( int length ) {
873         byte[] ba = new byte[length];
874         System.arraycopy(buf, pos, ba, 0, length);
875         pos += length;
876         return ba;
877     }
878
879     /**
880      * Reads one signed byte.
881      *
882      * @return signed byte
883      */

884     public final int getByte() {
885         return buf[pos++];
886     }
887
888     /**
889      * Reads one unsigned byte.
890      *
891      * @return unsigned byte
892      */

893     public final int getUByte() {
894         return buf[pos++] & 0xff;
895     }
896
897     public final int getByteAt( int p ) {
898         return buf[p];
899     }
900
901     public final int getUByteAt( int p ) {
902         return buf[p] & 0xff;
903     }
904
905     /**
906      * Reads one signed word.
907      *
908      * @return signed word
909      */

910     public final int getWord() {
911         int r = Util.getWord(buf[pos], buf[pos+1]);
912         pos += 2;
913         return r;
914     }
915
916     public final int getWordAt( int p ) {
917         return Util.getWord(buf[p], buf[p+1]);
918     }
919
920     /**
921      * Reads one unsigned word.
922      *
923      * @return unsigned word
924      */

925     public final int getUWord() {
926         int r = Util.getUWord(buf[pos], buf[pos+1]);
927         pos += 2;
928         return r;
929     }
930
931     public final int getUWordAt( int p ) {
932         return Util.getUWord(buf[p], buf[p+1]);
933     }
934
935     /**
936      * Reads one signed dword.
937      *
938      * @return signed dword
939      */

940     public int getDWord() {
941         int r = Util.getDWord(buf[pos], buf[pos+1], buf[pos+2], buf[pos+3]);
942         pos += 4;
943         return r;
944     }
945
946     public int getDWordAt( int p ) {
947         return Util.getDWord(buf[p], buf[p+1], buf[p+2], buf[p+3]);
948     }
949
950     /**
951      * Reads one unsigned dword.
952      *
953      * @return unsigned dword
954      */

955     public int getUDWord() {
956         int r = Util.getUDWord(buf[pos], buf[pos+1], buf[pos+2], buf[pos+3]);
957         pos += 4;
958         return r;
959     }
960
961     public int getUDWordAt( int p ) {
962         return Util.getUDWord(buf[p], buf[p+1], buf[p+2], buf[p+3]);
963     }
964
965     /*-----------------------------------------------------------------------
966      * InputStream
967      *-----------------------------------------------------------------------*/

968
969     /**
970      * Creates input stream which can be used to read data from this buffer.
971      *
972      * @return input stream
973      * @see #getOutputStream
974      */

975     public InputStream getInputStream() {
976         return new FlashBufferInputStream();
977     }
978
979     /**
980      * Creates input stream which can be used to read data from this buffer.
981      *
982      * @param pos first input position, position to start reading from
983      * @return input stream
984      * @see #getOutputStream
985      */

986     public InputStream getInputStream( int pos ) {
987         return new FlashBufferInputStream(pos);
988     }
989
990     public class FlashBufferInputStream extends InputStream {
991
992         private int curPos = 0;
993
994         public FlashBufferInputStream() {
995         }
996
997         public FlashBufferInputStream( int curPos ) {
998             this.curPos = curPos;
999         }
1000
1001        public int read() throws IOException {
1002            if( curPos >= size ) return -1;
1003            return buf[curPos++] & 0xff;
1004        }
1005
1006        public int read( byte b[], int off, int len ) throws IOException {
1007            if( len == 0 ) return 0;
1008            int sz = Math.min(len, size-curPos);
1009            if( sz <= 0 ) return -1;
1010            System.arraycopy(buf, curPos, b, off, sz);
1011            curPos += sz;
1012            return sz;
1013        }
1014
1015        public int available() throws IOException {
1016            return size-curPos;
1017        }
1018    }
1019
1020    /*-----------------------------------------------------------------------
1021     * OutputStream
1022     *-----------------------------------------------------------------------*/

1023
1024    /**
1025     * Creates output stream which can be used to write data to this buffer.
1026     *
1027     * @return output stream
1028     * @see #getInputStream
1029     */

1030    public OutputStream getOutputStream() {
1031        return new FlashBufferOutputStream();
1032    }
1033
1034    public class FlashBufferOutputStream extends OutputStream {
1035
1036        public FlashBufferOutputStream() {
1037        }
1038
1039        public void write(int b) {
1040            writeByte(b);
1041        }
1042
1043        public void write(byte b[], int off, int len) {
1044            writeArray(b,off,len);
1045        }
1046    }
1047
1048    /*-----------------------------------------------------------------------
1049     * AffineTransform
1050     *-----------------------------------------------------------------------*/

1051
1052    public AffineTransform JavaDoc getMatrix() {
1053        initBits();
1054
1055        double m00; // scale x
1056
double m10; // skew0 (y shear)
1057
double m01; // skew1 (x shear)
1058
double m11; // scale y
1059
double m02; // translate x
1060
double m12; // trasnlate y
1061

1062        // Scale terms
1063
if( getBool() ) {
1064            int nBits = getBits(5);
1065            m00 = Util.fixed2double(getSBits(nBits));
1066            m11 = Util.fixed2double(getSBits(nBits));
1067        } else {
1068            m00 = 1.0;
1069            m11 = 1.0;
1070        }
1071
1072        // Rotate/skew terms
1073
if( getBool() ) {
1074            int nBits = getBits(5);
1075            m10 = Util.fixed2double(getSBits(nBits));
1076            m01 = Util.fixed2double(getSBits(nBits));
1077        } else {
1078            m10 = 0.0;
1079            m01 = 0.0;
1080        }
1081
1082        // Translate terms
1083
int nBits = getBits(5);
1084        m02 = getSBits(nBits);
1085        m12 = getSBits(nBits);
1086
1087        AffineTransform JavaDoc m = new AffineTransform JavaDoc( m00, m10, m01, m11, m02, m12 );
1088        return m;
1089    }
1090
1091    /**
1092     * Skips MATRIX tag without creating Matrix object
1093     */

1094    public void skipMatrix() {
1095        initBits();
1096        // Scale terms
1097
if( getBool() ) {
1098            int nBits = getBits(5);
1099            skipBits(nBits+nBits);
1100        }
1101        // Rotate/skew terms
1102
if( getBool() ) {
1103            int nBits = getBits(5);
1104            skipBits(nBits+nBits);
1105        }
1106        // Translate terms
1107
int nBits = getBits(5);
1108        skipBits(nBits+nBits);
1109    }
1110
1111    public void write( AffineTransform JavaDoc m ) {
1112        initBits();
1113
1114        double m00 = m.getScaleX();
1115        double m10 = m.getShearY();
1116        double m01 = m.getShearX();
1117        double m11 = m.getScaleY();
1118        double m02 = m.getTranslateX();
1119        double m12 = m.getTranslateY();
1120
1121        if( m00 != 1.0 || m11 != 1.0 ) {
1122            writeBit(1);
1123            int i_scaleX = Util.double2fixed(m00);
1124            int i_scaleY = Util.double2fixed(m11);
1125            int nBits = Util.getMinBitsS( Util.getMax(i_scaleX,i_scaleY) );
1126            writeBits(nBits, 5);
1127            writeBits(i_scaleX, nBits);
1128            writeBits(i_scaleY, nBits);
1129        } else {
1130            writeBit(0);
1131        }
1132
1133        if( m10 != 0.0 || m01 != 0.0 ) {
1134            writeBit(1);
1135            int i_rotateSkew0 = Util.double2fixed(m10);
1136            int i_rotateSkew1 = Util.double2fixed(m01);
1137            int nBits = Util.getMinBitsS( Util.getMax(i_rotateSkew0,i_rotateSkew1) );
1138            writeBits(nBits, 5);
1139            writeBits(i_rotateSkew0, nBits);
1140            writeBits(i_rotateSkew1, nBits);
1141        } else {
1142            writeBit(0);
1143        }
1144
1145        int i_translateX = (int) m02;
1146        int i_translateY = (int) m12;
1147        int nBits = Util.getMinBitsS( Util.getMax(i_translateX,i_translateY) );
1148        writeBits(nBits, 5);
1149        writeBits(i_translateX, nBits);
1150        writeBits(i_translateY, nBits);
1151        flushBits();
1152    }
1153
1154    /*-----------------------------------------------------------------------
1155     * Rectangle2D
1156     *-----------------------------------------------------------------------*/

1157
1158    public Rectangle2D JavaDoc getRect() {
1159        initBits();
1160        int nBits = getBits(5);
1161        int xmin = getSBits(nBits);
1162        int xmax = getSBits(nBits);
1163        int ymin = getSBits(nBits);
1164        int ymax = getSBits(nBits);
1165
1166        Rectangle2D JavaDoc r = GeomHelper.newRectangle( xmin, ymin, xmax-xmin, ymax-ymin );
1167        return r;
1168    }
1169
1170    /**
1171     * Skips rectangle
1172     */

1173    public void skipRect() {
1174        initBits();
1175        int nBits = getBits(5);
1176        skip( ((5+(nBits*4))+7)/8 - 1 );
1177    }
1178
1179    public void write( Rectangle2D JavaDoc r ) {
1180        initBits();
1181
1182        int xmin = (int) r.getMinX();
1183        int xmax = (int) r.getMaxX();
1184        int ymin = (int) r.getMinY();
1185        int ymax = (int) r.getMaxY();
1186
1187        int nBits = Util.getMinBitsS( Util.getMax(xmin,xmax,ymin,ymax) );
1188        writeBits( nBits, 5 );
1189        writeBits( xmin, nBits );
1190        writeBits( xmax, nBits );
1191        writeBits( ymin, nBits );
1192        writeBits( ymax, nBits );
1193        flushBits();
1194    }
1195
1196    public String JavaDoc toString() {
1197        return new String JavaDoc(buf, 0, pos);
1198    }
1199
1200    public String JavaDoc toString( String JavaDoc encoding ) throws java.io.UnsupportedEncodingException JavaDoc {
1201        return new String JavaDoc(buf, 0, pos, encoding);
1202    }
1203}
1204
Popular Tags