1 /*
2 Ming, an SWF output library
3 Copyright (C) 2002 Opaque Industries - http://www.opaque.net/
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 /* $Id$ */
21
22 #ifndef __C2MAN__
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #endif
27
28 #include "output.h"
29 #include "error.h"
30
31 #include "libming.h"
32
33 struct SWFOutput_s
34 {
35 SWFOutput next;
36
37 byte *buffer;
38 byte *pos;
39 int buffersize;
40 int free;
41 int bitpos;
42 };
43
44
45 SWFOutput
newSWFOutput()46 newSWFOutput()
47 {
48 SWFOutput out = (SWFOutput) malloc(sizeof(struct SWFOutput_s));
49
50 /* If malloc failed, return NULL to signify this */
51 if (NULL == out)
52 return NULL;
53
54 out->next = NULL;
55 out->buffer = (byte*) malloc(OUTPUT_BUFFER_INCREMENT);
56
57 /* If malloc failed, return NULL to signify this */
58 if (NULL == out->buffer)
59 {
60 free(out);
61 return NULL;
62 }
63
64 out->pos = out->buffer;
65 *(out->pos) = 0;
66 out->buffersize = out->free = OUTPUT_BUFFER_INCREMENT;
67 out->bitpos = 0;
68
69 return out;
70 }
71
72
73 /* same as above but with specified buffer size,
74 use if you have an upper limit to how big this'll get */
75
76 SWFOutput
newSizedSWFOutput(int size)77 newSizedSWFOutput(int size)
78 {
79 SWFOutput out = (SWFOutput)malloc(sizeof(struct SWFOutput_s));
80
81 /* If malloc failed, return NULL to signify this */
82 if (NULL == out)
83 return NULL;
84
85 out->next = NULL;
86 out->buffer = (byte*) malloc(size+1);
87
88 /* If malloc failed, return NULL to signify this */
89 if (NULL == out->buffer)
90 {
91 free(out);
92 return NULL;
93 }
94
95 out->pos = out->buffer;
96 *(out->pos) = 0;
97 out->buffersize = out->free = size+1;
98 out->bitpos = 0;
99
100 return out;
101 }
102
103
104 void
SWFOutput_writeToMethod(SWFOutput out,SWFByteOutputMethod method,void * data)105 SWFOutput_writeToMethod(SWFOutput out, SWFByteOutputMethod method, void *data)
106 {
107 int i, l;
108 SWFOutput o = out;
109 byte *buffer;
110
111 SWFOutput_byteAlign(out);
112
113 while ( o != NULL )
114 {
115 buffer = o->buffer;
116 l = o->pos - buffer;
117
118 for(i=0; i<l; ++i)
119 method(buffer[i], data);
120
121 o = o->next;
122 }
123 }
124
125
126 void
destroySWFOutput(SWFOutput out)127 destroySWFOutput(SWFOutput out)
128 {
129 SWFOutput o = out, next;
130
131 while(o != NULL)
132 {
133 next = o->next;
134 free(o->buffer);
135 free(o);
136 o = next;
137 }
138 }
139
140
141 void
SWFOutput_grow(SWFOutput out)142 SWFOutput_grow(SWFOutput out)
143 {
144 int num = out->pos - out->buffer; /* in case buffer gets displaced.. */
145
146 unsigned char* newbuf =
147 (unsigned char*)realloc(out->buffer, out->buffersize + OUTPUT_BUFFER_INCREMENT);
148
149 if ( newbuf != out->buffer )
150 out->pos = newbuf+num;
151
152 out->buffer = newbuf;
153 out->buffersize += OUTPUT_BUFFER_INCREMENT;
154 out->free += OUTPUT_BUFFER_INCREMENT;
155 }
156
157
158 int
SWFOutput_getLength(SWFOutput out)159 SWFOutput_getLength(SWFOutput out)
160 {
161 int size = 0;
162
163 while ( out!=NULL )
164 {
165 size += (out->pos) - (out->buffer) + (out->bitpos>0 ? 1 : 0);
166 out = out->next;
167 }
168
169 return size;
170 }
171
172
173 /* make sure there's enough space for bytes bytes */
174 void
SWFOutput_checkSize(SWFOutput out,int bytes)175 SWFOutput_checkSize(SWFOutput out, int bytes)
176 {
177 if ( bytes >= out->free )
178 {
179 int New = OUTPUT_BUFFER_INCREMENT *
180 ((bytes-out->free-1)/OUTPUT_BUFFER_INCREMENT + 1);
181
182 int num = out->pos - out->buffer; /* in case buffer gets displaced.. */
183
184 unsigned char *newbuf = (unsigned char*)realloc(out->buffer, out->buffersize+New);
185
186 if ( newbuf != out->buffer )
187 out->pos = newbuf + num;
188
189 out->buffer = newbuf;
190 out->buffersize += New;
191 out->free += New;
192 }
193 }
194
195
196 void
SWFOutput_byteAlign(SWFOutput out)197 SWFOutput_byteAlign(SWFOutput out)
198 {
199 if ( out->bitpos > 0 )
200 {
201 SWFOutput_checkSize(out, 1);
202 ++out->pos;
203 --out->free;
204 out->bitpos = 0;
205 }
206 }
207
208
209 void
SWFOutput_setNext(SWFOutput out,SWFOutput next)210 SWFOutput_setNext(SWFOutput out, SWFOutput next)
211 {
212 out->next = next;
213 }
214
215
216 SWFOutput
SWFOutput_getNext(SWFOutput out)217 SWFOutput_getNext(SWFOutput out)
218 {
219 return out->next;
220 }
221
222
223 byte*
SWFOutput_getBuffer(SWFOutput out)224 SWFOutput_getBuffer(SWFOutput out)
225 {
226 return out->buffer;
227 }
228
229
230 byte*
SWFOutput_getCurPos(SWFOutput out)231 SWFOutput_getCurPos(SWFOutput out)
232 {
233 return out->pos;
234 }
235
236
237 void
SWFOutput_writeBits(SWFOutput out,int data,int bits)238 SWFOutput_writeBits(SWFOutput out, int data, int bits)
239 {
240 int bitpos = out->bitpos;
241
242 if ( bitpos == 0 )
243 *(out->pos) = 0;
244
245 SWFOutput_checkSize(out, (bits+bitpos+7)/8);
246
247 while ( bits > 0 )
248 {
249 if ( bits + bitpos >= 8 )
250 {
251 *(out->pos) += (data >> (bits+bitpos-8)) & 0xff;
252 bits -= 8-bitpos;
253 ++out->pos;
254 *(out->pos) = 0;
255 --out->free;
256 bitpos = 0;
257 }
258 else
259 {
260 *(out->pos) += (data << (8-bits-bitpos)) & 0xff;
261 bitpos += bits;
262 bits = 0;
263 }
264 }
265
266 out->bitpos = bitpos;
267 }
268
269
270 void
SWFOutput_writeSBits(SWFOutput out,int data,int bits)271 SWFOutput_writeSBits(SWFOutput out, int data, int bits)
272 {
273 if ( data < 0 )
274 data = (1<<bits)+data;
275
276 SWFOutput_writeBits(out, data, bits);
277 }
278
279
280 void
SWFOutput_writeUInt8(SWFOutput out,int data)281 SWFOutput_writeUInt8(SWFOutput out, int data)
282 {
283 /* think we have to byte align when we write whole bytes */
284 SWFOutput_byteAlign(out);
285
286 SWFOutput_checkSize(out, 1);
287 *(out->pos) = data;
288 ++out->pos;
289 --out->free;
290 }
291
292 void
SWFOutput_truncate(SWFOutput out,int size)293 SWFOutput_truncate(SWFOutput out, int size)
294 { SWF_assert(size < out->buffersize);
295 out->pos = out->buffer + size;
296 out->free = out->buffersize - size;
297 }
298
299 void
SWFOutput_writeSInt8(SWFOutput out,int data)300 SWFOutput_writeSInt8(SWFOutput out, int data)
301 {
302 if ( data < 0 )
303 data = (1<<8)+data;
304
305 SWFOutput_writeUInt8(out, data);
306 }
307
308
309 void
SWFOutput_writeUInt16(SWFOutput out,int data)310 SWFOutput_writeUInt16(SWFOutput out, int data)
311 {
312 SWFOutput_writeUInt8(out, data&0xff);
313 data >>= 8;
314 SWFOutput_writeUInt8(out, data&0xff);
315 }
316
317
318 void
SWFOutput_writeSInt16(SWFOutput out,int data)319 SWFOutput_writeSInt16(SWFOutput out, int data)
320 {
321 if ( data < 0 )
322 data = (1<<16)+data;
323
324 SWFOutput_writeUInt8(out, data%256);
325 data >>= 8;
326 SWFOutput_writeUInt8(out, data%256);
327 }
328
329
330 void
SWFOutput_writeUInt32(SWFOutput out,long data)331 SWFOutput_writeUInt32(SWFOutput out, long data)
332 {
333 SWFOutput_writeUInt8(out, data&0xff);
334 data >>= 8;
335 SWFOutput_writeUInt8(out, data&0xff);
336 data >>= 8;
337 SWFOutput_writeUInt8(out, data&0xff);
338 data >>= 8;
339 SWFOutput_writeUInt8(out, data&0xff);
340 }
341
342
343 void
SWFOutput_writeSInt32(SWFOutput out,long data)344 SWFOutput_writeSInt32(SWFOutput out, long data)
345 {
346 if ( data < 0 )
347 data = (0xffffffff + data) + 1;
348
349 SWFOutput_writeUInt8(out, data&0xff);
350 data >>= 8;
351 SWFOutput_writeUInt8(out, data&0xff);
352 data >>= 8;
353 SWFOutput_writeUInt8(out, data&0xff);
354 data >>= 8;
355 SWFOutput_writeUInt8(out, data&0xff);
356 }
357
358
359 void
SWFOutput_writeBuffer(SWFOutput out,unsigned char * buffer,int bytes)360 SWFOutput_writeBuffer(SWFOutput out, unsigned char *buffer, int bytes)
361 {
362 SWFOutput_checkSize(out, bytes);
363 memcpy(out->pos, buffer, bytes);
364 out->pos += bytes;
365 out->free -= bytes;
366 }
367
368
369 int
SWFOutput_numBits(int num)370 SWFOutput_numBits(int num)
371 {
372 int i=0;
373
374 while ( num > 0 )
375 {
376 num >>= 1;
377 ++i;
378 }
379
380 return i;
381 }
382
383
384 int
SWFOutput_numSBits(int num)385 SWFOutput_numSBits(int num)
386 {
387 if ( num < 0 )
388 // XXX - one more than necessary if num = -2^n:
389 return SWFOutput_numBits(-num)+1;
390 else
391 return SWFOutput_numBits(num)+1;
392 }
393
394
395 void
SWFOutput_writeString(SWFOutput out,const unsigned char * string)396 SWFOutput_writeString(SWFOutput out, const unsigned char *string)
397 {
398 char c;
399
400 SWFOutput_byteAlign(out);
401
402 if ( string )
403 {
404 while ( (c = *(string++)) != 0 )
405 SWFOutput_writeUInt8(out, c);
406 }
407
408 SWFOutput_writeUInt8(out, 0);
409 }
410
411 void
SWFOutput_writeFixed(SWFOutput out,double val)412 SWFOutput_writeFixed(SWFOutput out, double val)
413 {
414 unsigned int fixed;
415
416 fixed = val * (1<<16);
417 SWFOutput_writeUInt32(out, fixed);
418 }
419
420 void
SWFOutput_writeFixed8(SWFOutput out,double val)421 SWFOutput_writeFixed8(SWFOutput out, double val)
422 {
423 unsigned int fixed;
424
425 fixed = 0xffff & (int)(val * (1<<8));
426 SWFOutput_writeUInt16(out, fixed);
427 }
428
429
430
431 void
SWFOutput_writeFloat(SWFOutput out,float f)432 SWFOutput_writeFloat(SWFOutput out, float f)
433 {
434 unsigned char *p = (unsigned char *)&f;
435 #if SWF_LITTLE_ENDIAN
436 SWFOutput_writeUInt8(out, p[0]);
437 SWFOutput_writeUInt8(out, p[1]);
438 SWFOutput_writeUInt8(out, p[2]);
439 SWFOutput_writeUInt8(out, p[3]);
440 #else
441 SWFOutput_writeUInt8(out, p[3]);
442 SWFOutput_writeUInt8(out, p[2]);
443 SWFOutput_writeUInt8(out, p[1]);
444 SWFOutput_writeUInt8(out, p[0]);
445 #endif
446 }
447
448 void
SWFOutput_writeDouble(SWFOutput out,double d)449 SWFOutput_writeDouble(SWFOutput out, double d)
450 {
451 unsigned char *p = (unsigned char *)&d;
452
453 #if SWF_LITTLE_ENDIAN
454 SWFOutput_writeUInt8(out, p[4]);
455 SWFOutput_writeUInt8(out, p[5]);
456 SWFOutput_writeUInt8(out, p[6]);
457 SWFOutput_writeUInt8(out, p[7]);
458 SWFOutput_writeUInt8(out, p[0]);
459 SWFOutput_writeUInt8(out, p[1]);
460 SWFOutput_writeUInt8(out, p[2]);
461 SWFOutput_writeUInt8(out, p[3]);
462 #else
463 SWFOutput_writeUInt8(out, p[3]);
464 SWFOutput_writeUInt8(out, p[2]);
465 SWFOutput_writeUInt8(out, p[1]);
466 SWFOutput_writeUInt8(out, p[0]);
467 SWFOutput_writeUInt8(out, p[7]);
468 SWFOutput_writeUInt8(out, p[6]);
469 SWFOutput_writeUInt8(out, p[5]);
470 SWFOutput_writeUInt8(out, p[4]);
471 #endif
472 }
473
474 #define FLOAT_SIGN_MASK 0x80000000
475 #define FLOAT_SIGN_SHIFT 31
476 #define FLOAT_EXP_MASK 0x7f800000
477 #define FLOAT_EXP_SHIFT 23
478 #define FLOAT_MAT_MASK 0x7fff
479 #define FLOAT_BIAS 127;
480
481 /*
482 * FLOAT16 - half precision
483 * 1 - bit sign
484 * 5 - bit exp / bias = 16
485 * 10 - bit mantissa
486 */
487
488 #define FLOAT16_SIGN_SHIFT 15
489 #define FLOAT16_EXP_SHIFT 11
490 #define FLOAT16_BIAS 16
491
492 void
SWFOutput_writeFloat16(SWFOutput out,float f)493 SWFOutput_writeFloat16(SWFOutput out, float f)
494 {
495 unsigned char buf[4];
496 float *pf = (float *)buf;
497 int sig, exp, mat;
498 unsigned int i;
499
500 *pf = f;
501 i = (unsigned int)*buf;
502
503 sig = (FLOAT_SIGN_MASK & i) >> FLOAT_SIGN_SHIFT;
504
505 exp = (FLOAT_EXP_MASK & i) >> FLOAT_EXP_SHIFT;
506 exp -= FLOAT_BIAS;
507
508 mat = (FLOAT_MAT_MASK &i);
509
510 exp += FLOAT16_BIAS;
511 exp &= 0x1f;
512
513 // reduce mantissa to 11-bit
514 mat >>= 12;
515
516 i = sig << FLOAT16_SIGN_SHIFT | exp << FLOAT16_EXP_SHIFT | (mat & 0x7ff);
517 SWFOutput_writeUInt16(out, i);
518 }
519
520 #define ENC_HIGH_BIT 0x80
521 #define ENC_BYTE_MASK 0x7f
522
523 void
SWFOutput_writeEncUInt32(SWFOutput out,unsigned int i)524 SWFOutput_writeEncUInt32(SWFOutput out, unsigned int i)
525 {
526 if(i == 0) // special case
527 {
528 SWFOutput_writeUInt8(out, 0);
529 return;
530 }
531 while(i > 0)
532 {
533 unsigned char temp = i & ENC_BYTE_MASK;
534 i = i >> 7;
535 if(i > 0)
536 temp |= ENC_HIGH_BIT;
537 SWFOutput_writeUInt8(out, temp);
538 }
539 }
540
541 /*
542 * Local variables:
543 * tab-width: 2
544 * c-basic-offset: 2
545 * End:
546 */
547