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