#include <stdlib.h>
#include <unistd.h>
+#include <memory.h>
#include <fcntl.h>
-#include <zlib.h>
-#include "./bitio.h"
+#include "../config.h"
+
+#ifdef HAVE_ZLIB
+#include <zlib.h>
#define ZLIB_BUFFER_SIZE 16384
+#endif
+#include "./bitio.h"
struct memread_t
{
struct zlibinflate_t
{
+#ifdef HAVE_ZLIB
z_stream zs;
struct reader_t*input;
unsigned char readbuffer[ZLIB_BUFFER_SIZE];
+#endif
};
struct zlibdeflate_t
{
+#ifdef HAVE_ZLIB
z_stream zs;
struct writer_t*output;
unsigned char writebuffer[ZLIB_BUFFER_SIZE];
+#endif
};
void reader_resetbits(struct reader_t*r)
static int reader_zlibinflate(struct reader_t*reader, void* data, int len);
static int reader_fileread(struct reader_t*reader, void* data, int len);
static int reader_memread(struct reader_t*reader, void* data, int len);
+#ifdef HAVE_ZLIB
static void zlib_error(int ret, char* msg, z_stream*zs);
+#endif
void reader_init_filereader(struct reader_t*r, int handle)
{
void reader_init_zlibinflate(struct reader_t*r, struct reader_t*input)
{
+#ifdef HAVE_ZLIB
struct zlibinflate_t*z;
int ret;
memset(r, 0, sizeof(struct reader_t));
ret = inflateInit(&z->zs);
if (ret != Z_OK) zlib_error(ret, "bitio:inflate_init", &z->zs);
reader_resetbits(r);
+#else
+ fprintf(stderr, "Error: swftools was compiled without zlib support");
+#endif
}
+#ifdef HAVE_ZLIB
static void zlib_error(int ret, char* msg, z_stream*zs)
{
fprintf(stderr, "%s: zlib error (%d): last zlib error: %s\n",
perror("errno:");
exit(1);
}
+#endif
static int reader_fileread(struct reader_t*reader, void* data, int len)
{
static int reader_zlibinflate(struct reader_t*reader, void* data, int len)
{
+#ifdef HAVE_ZLIB
struct zlibinflate_t*z = (struct zlibinflate_t*)reader->internal;
int ret;
if(!z)
}
reader->pos += len;
return len;
+#else
+ fprintf(stderr, "Error: swftools was compiled without zlib support");
+ exit(1);
+#endif
}
unsigned int reader_readbit(struct reader_t*r)
{
void writer_init_zlibdeflate(struct writer_t*w, struct writer_t*output)
{
+#ifdef HAVE_ZLIB
struct zlibdeflate_t*z;
int ret;
memset(w, 0, sizeof(struct writer_t));
w->mybyte = 0;
z->zs.next_out = z->writebuffer;
z->zs.avail_out = ZLIB_BUFFER_SIZE;
+#else
+ fprintf(stderr, "Error: swftools was compiled without zlib support");
+ exit(1);
+#endif
}
static int writer_zlibdeflate_write(struct writer_t*writer, void* data, int len)
{
+#ifdef HAVE_ZLIB
struct zlibdeflate_t*z = (struct zlibdeflate_t*)writer->internal;
int ret;
if(!z)
}
writer->pos += len;
return len;
+#else
+ fprintf(stderr, "Error: swftools was compiled without zlib support");
+ exit(1);
+#endif
}
static void writer_zlibdeflate_finish(struct writer_t*writer)
{
+#ifdef HAVE_ZLIB
struct zlibdeflate_t*z = (struct zlibdeflate_t*)writer->internal;
struct writer_t*output;
int ret;
free(writer->internal);
writer->internal = 0;
output->finish(output);
+#else
+ fprintf(stderr, "Error: swftools was compiled without zlib support");
+ exit(1);
+#endif
}
void writer_writebit(struct writer_t*w, int bit)
// write movie to file
- f = open("shape1.swf",O_WRONLY|O_CREAT, 0644);
+ f = open("shape1.swf",O_WRONLY|O_CREAT|O_TRUNC, 0644);
if FAILED(swf_WriteSWF(f,&swf)) fprintf(stderr,"WriteSWF() failed.\n");
close(f);
// Lossless compression texture based on zlib
-#ifdef _ZLIB_INCLUDED_
+#ifdef HAVE_ZLIB
int RFXSWF_deflate_wraper(TAG * t,z_stream * zs,U8 * data,boolean finish)
{ while (1)
}
-#endif // _ZLIB_INCLUDED_
+#endif // HAVE_ZLIB
#undef OUTBUFFER_SIZE
if (flags&PF_MATRIX) swf_SetMatrix(t,m);
if (flags&PF_CXFORM) swf_SetCXForm(t,cx,1);
if (flags&PF_RATIO) swf_SetU16(t,0);
- if (flags&PF_NAME) swf_SetString(t,name);
+
+ /* ??? The spec states that name comes first? */
if (flags&PF_CLIPACTION) swf_SetU16(t, clipaction);
+ if (flags&PF_NAME) swf_SetString(t,name);
return 0;
}
if (flags&PF_MATRIX) swf_SetMatrix(t,&obj->matrix);
if (flags&PF_CXFORM) swf_SetCXForm(t,&obj->cxform,1);
if (flags&PF_RATIO) swf_SetU16(t,obj->ratio);
- if (flags&PF_NAME) swf_SetString(t,obj->name);
+
+ /* ??? The spec states that name comes first? */
if (flags&PF_CLIPACTION) swf_SetU16(t,obj->clipdepth);
+ if (flags&PF_NAME) swf_SetString(t,obj->name);
if (flags&PF_ACTIONEVENT) {
// ...
}
void swf_GetPlaceObject(TAG * tag,SWFPLACEOBJECT* obj)
{
- U8 flags = swf_GetU8(tag);
+ U8 flags;
+ if(!tag) {
+ memset(obj, 0, sizeof(SWFPLACEOBJECT));
+ swf_GetMatrix(0, &obj->matrix);
+ swf_GetCXForm(0, &obj->cxform, 1);
+ return;
+ }
+
+ flags = swf_GetU8(tag);
memset(obj,0,sizeof(SWFPLACEOBJECT));
swf_GetMatrix(0,&obj->matrix);
if(flags&4) swf_GetMatrix(tag, &obj->matrix);
if(flags&8) swf_GetCXForm(tag, &obj->cxform,1);
if(flags&16) obj->ratio = swf_GetU16(tag);
+ if(flags&64)
+ obj->clipdepth = swf_GetU16(tag); //clip
if(flags&32) {
int l,t;
U8*data;
obj->name = data;
while((data[t++] = swf_GetU8(tag)));
}
- if(flags&64)
- obj->clipdepth = swf_GetU16(tag); //clip
/* Actionscript ignored (for now) */
obj->actions = 0;
return id;
}
- if (l)
- { if (f->name) free(f->name);
- f->name = (U8*)malloc(l+1);
- if (f->name)
- { swf_GetBlock(t,f->name,l);
- f->name[l] = 0;
- }
- else
- { swf_RestoreTagPos(t);
- return -1;
- }
- }
+ if (f->name) free(f->name);
+
+ f->name = (U8*)malloc(l+1);
+ swf_GetBlock(t,f->name,l);
+ f->name[l] = 0;
+
flags = swf_GetU8(t);
if(flags & 2)
f->style |= FONT_STYLE_BOLD;
if ((!swf)||(!font)) return -1;
- f = (SWFFONT *)malloc(sizeof(SWFFONT)); font[0] = f;
- if (!f) return -1;
-
+ f = (SWFFONT *)malloc(sizeof(SWFFONT));
memset(f,0x00,sizeof(SWFFONT));
t = swf->firstTag;
if (nid>0) id = nid;
t = swf_NextTag(t);
}
+ if(f->id != id) {
+ free(f);
+ f=0;
+ }
+ font[0] = f;
return 0;
}
}
for (i=0;i<j;i++) swf_SetU16(t,ofs[i]+j*2);
+ if(!j) {
+ fprintf(stderr, "rfxswf: warning: Font is empty\n");
+ swf_SetU16(t, 0);
+ }
for (i=0;i<f->numchars;i++)
if (f->glyph[i].shape)
if ((!t)||(!f)) return -1;
swf_ResetWriteBits(t);
swf_SetU16(t,f->id);
- l = strlen(f->name); if (l>255) l = 255;
+ l = f->name?strlen(f->name):0; if (l>255) l = 255;
swf_SetU8(t,l);
- swf_SetBlock(t,f->name,l);
+ if(l)
+ swf_SetBlock(t,f->name,l);
if(f->numchars>=256)
wide=1;
swf_SetString(tag,text);
}
-void swf_SetDefineText(TAG*tag, SWFFONT*font, RGBA*rgb, char*text, int scale)
+SRECT swf_SetDefineText(TAG*tag, SWFFONT*font, RGBA*rgb, char*text, int scale)
{
SRECT r;
U8 gbits, abits;
-
- r.xmin = r.ymin = 0; /*FIXME*/
- r.xmax = r.ymax = 1024*20;
+ U8*c = (U8*)text;
+ int pos = 0;
+ swf_GetRect(0, &r);
+ if(font->layout) {
+ while(*c) {
+ if(*c < font->maxascii) {
+ int g = font->ascii2glyph[*c];
+ SRECT rn = font->layout->bounds[g];
+ rn.xmin = (rn.xmin * scale)/2000 + pos;
+ rn.xmax = (rn.xmax * scale)/2000 + pos;
+ rn.ymin = (rn.ymin * scale)/2000;
+ rn.ymax = (rn.ymax * scale)/2000;
+ swf_ExpandRect2(&r, &rn);
+ pos += (font->glyph[g].advance*scale)/100;
+ }
+ c++;
+ }
+ } else {
+ /* Hm, without layout information, we can't compute a bounding
+ box. We could call swf_FontCreateLayout to create a layout,
+ but the caller probably doesn't want us to mess up his font
+ structure.
+ */
+ r.xmin = r.ymin = 0;
+ r.xmax = r.ymax = 1024*20;
+ }
swf_SetRect(tag,&r);
swf_SetMatrix(tag,NULL);
swf_TextCountBits(font,text,scale,&gbits,&abits);
swf_SetU8(tag,gbits);
swf_SetU8(tag,abits);
- swf_TextSetInfoRecord(tag,font,scale,rgb,0,scale);
+ swf_TextSetInfoRecord(tag,font,scale/2 /*?? why /2? */,rgb,0,0); //scale
swf_TextSetCharRecord(tag,font,text,scale,gbits,abits);
swf_SetU8(tag,0);
+ return r;
}
+void swf_FontCreateLayout(SWFFONT*f)
+{
+ S16 leading = 0;
+ int t;
+ if(f->layout)
+ return;
+ if(!f->numchars)
+ return;
+
+ f->layout = (SWFLAYOUT*)malloc(sizeof(SWFLAYOUT));
+ memset(f->layout, 0, sizeof(SWFLAYOUT));
+ f->layout->bounds = (SRECT*)malloc(f->numchars*sizeof(SRECT));
+ f->layout->ascent = -32767;
+ f->layout->descent = -32767;
+
+ for(t=0;t<f->numchars;t++) {
+ SHAPE2*shape2;
+ SRECT bbox;
+ int width;
+ shape2 = swf_ShapeToShape2(f->glyph[t].shape);
+ if(!shape2) {
+ fprintf(stderr, "Shape parse error\n");exit(1);
+ }
+ bbox = swf_GetShapeBoundingBox(shape2->lines);
+ swf_Shape2Free(shape2);
+ f->layout->bounds[t] = bbox;
+ /* FIXME */
+ //width = (bbox.xmax - bbox.xmin)/20;
+ width = (bbox.xmax)/20;
+
+ /* The following is a heuristic- it may be that extractfont_DefineText
+ has already found out some widths for individual characters (from the way
+ they are used)- we now have to guess whether that width might be possible,
+ which is the case if it isn't either much too big or much too small */
+ if(width > f->glyph[t].advance*3/2 ||
+ width*2 < f->glyph[t].advance)
+ f->glyph[t].advance = width;
+
+ if(-bbox.ymin > f->layout->ascent)
+ f->layout->ascent = bbox.ymin;
+ if(bbox.ymax > f->layout->descent)
+ f->layout->descent = bbox.ymax;
+ }
+}
+
+
return id;
}
+SRECT swf_GetDefineBBox(TAG * t)
+{
+ U32 oldTagPos;
+ U16 id = 0;
+ SRECT b1,b2;
+
+ oldTagPos = swf_GetTagPos(t);
+ swf_SetTagPos(t,0);
+
+ swf_GetRect(0, &b1);
+
+ switch (swf_GetTagID(t))
+ { case ST_DEFINESHAPE:
+ case ST_DEFINESHAPE2:
+ case ST_DEFINESHAPE3:
+ case ST_DEFINEEDITTEXT:
+ case ST_DEFINEBUTTON:
+ case ST_DEFINEBUTTON2:
+ case ST_DEFINETEXT:
+ case ST_DEFINETEXT2:
+ case ST_DEFINEVIDEOSTREAM:
+ id = swf_GetU16(t);
+ swf_GetRect(t, &b1);
+ break;
+ case ST_DEFINEMORPHSHAPE:
+ id = swf_GetU16(t);
+ swf_GetRect(t, &b1);
+ swf_GetRect(t, &b2);
+ swf_ExpandRect2(&b1, &b2);
+ break;
+ case ST_DEFINEBITSLOSSLESS:
+ case ST_DEFINEBITSLOSSLESS2:
+ case ST_DEFINEBITS:
+ case ST_DEFINEBITSJPEG2:
+ case ST_DEFINEBITSJPEG3:
+ // FIXME
+ break;
+ }
+
+ swf_SetTagPos(t,oldTagPos);
+
+ return b1;
+}
+
U16 swf_GetPlaceID(TAG * t)
// up to SWF 4.0
{ U32 oldTagPos;
swf_GetCXForm(t, &c, 1);
if(flags&PF_RATIO)
swf_GetU16(t);
+ if(flags&PF_CLIPACTION)
+ swf_GetU16(t);
if(flags&PF_NAME) {
swf_ResetReadBits(t);
name = &t->data[swf_GetTagPos(t)];
#endif // HAVE_JPEGLIB_H
#endif // HAVE_LIBJPEG
-#ifdef HAVE_LIBZ
-#ifdef HAVE_ZLIB_H
+#ifdef HAVE_ZLIB
#include <zlib.h>
-#define _ZLIB_INCLUDED_
-#endif // HAVE_ZLIB_H
-#endif // HAVE_LIBZ
+#endif // HAVE_ZLIB
#define LAME
#include "lame/lame.h"
#endif
}
+char* swf_GetString(TAG*t)
+{
+ char* str = ((char*)(&(t)->data[(t)->pos]));
+ while(swf_GetU8(t));
+ return str;
+}
+
U8 swf_GetU8(TAG * t)
{ swf_ResetReadBits(t);
#ifdef DEBUG_RFXSWF
int swf_GetRect(TAG * t,SRECT * r)
{ int nbits;
SRECT dummy;
- if(!t) {r->xmin=r->xmax=r->ymin=r->ymax;return 0;}
+ if(!t) {r->xmin=r->xmax=r->ymin=r->ymax=0;return 0;}
if (!r) r = &dummy;
nbits = (int) swf_GetBits(t,5);
r->xmin = swf_GetSBits(t,nbits);
}
void swf_ExpandRect2(SRECT*src, SRECT*add)
{
+ if((add->xmin | add->ymin | add->xmax | add->ymax)==0)
+ return;
if(add->xmin < src->xmin)
src->xmin = add->xmin;
if(add->ymin < src->ymin)
SPOINT swf_TurnPoint(SPOINT p, MATRIX* m)
{
SPOINT r;
- r.x = (int)(m->sx*(1/65536.0)*p.x + m->r0*(1/65536.0)*p.y + 0.5) + m->tx;
- r.y = (int)(m->r1*(1/65536.0)*p.x + m->sy*(1/65536.0)*p.y + 0.5) + m->ty;
+ r.x = (int)(m->sx*(1/65536.0)*p.x + m->r1*(1/65536.0)*p.y + 0.5) + m->tx;
+ r.y = (int)(m->r0*(1/65536.0)*p.x + m->sy*(1/65536.0)*p.y + 0.5) + m->ty;
return r;
}
SRECT swf_TurnRect(SRECT r, MATRIX* m)
return t;
}
+void swf_ClearTag(TAG * t)
+{
+ if (t->data) free(t->data);
+ t->data = 0;
+ t->pos = 0;
+ t->len = 0;
+ t->readBit = 0;
+ t->writeBit = 0;
+ t->memsize = 0;
+}
+
int swf_DeleteTag(TAG * t)
{ if (!t) return -1;
#ifndef __RFX_SWF_INCLUDED__
#define __RFX_SWF_INCLUDED__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* little/big endian stuff */
-//#define SWAP16(s) ((U16) ((U8*)&s)[0] | ((U16) ((U8*)&s)[1] << 8))
-//#define SWAP32(s) ((U32) ((U8*)&s)[0] | ((U32) ((U8*)&s)[1] << 8) | ((U32) ((U8*)&s)[2] << 16) | ((U32) ((U8*)&s)[3] << 24))
-
#define PUT16(ptr,x) {((U8*)(ptr))[0]=(U8)(x);((U8*)(ptr))[1]=(U8)((x)>>8);}
#define PUT32(ptr,x) {((U8*)(ptr))[0]=(U8)(x);((U8*)(ptr))[1]=(U8)((x)>>8);((U8*)(ptr))[2]=(U8)((x)>>16);((U8*)(ptr))[3]=(U8)((x)>>24);}
#define GET16(ptr) (((U16)(((U8*)(ptr))[0]))+(((U16)(((U8*)(ptr))[1]))<<8))
TAG * swf_InsertTag(TAG * after,U16 id); // updates frames, if necessary
int swf_DeleteTag(TAG * t);
+void swf_ClearTag(TAG * t); //frees tag data
+
void swf_SetTagPos(TAG * t,U32 pos); // resets Bitcount
U32 swf_GetTagPos(TAG * t);
void swf_GetRGB(TAG * t, RGBA * col);
void swf_GetRGBA(TAG * t, RGBA * col);
void swf_GetGradient(TAG * t, GRADIENT * gradient, char alpha);
-
+char* swf_GetString(TAG*t);
int swf_SetU8(TAG * t,U8 v); // resets Bitcount
int swf_SetU16(TAG * t,U16 v);
int swf_SetU32(TAG * t,U32 v);
#define swf_GetS32(tag) ((S32)swf_GetU32(tag))
#define swf_GetCoord(tag) ((SCOORD)swf_GetU32(tag))
#define swf_GetFixed(tag) ((SFIXED)swf_GetU32(tag))
-#define swf_GetString(t) ((char*)(&(t)->data[(t)->pos]))
#define swf_SetS8(tag,v) swf_SetU8(tag,(U8)v)
#define swf_SetS16(tag,v) swf_SetU16(tag,(U16)v)
#define swf_SetFixed(tag,v) swf_SetU32(tag,(U32)v)
#define swf_SetString(t,s) swf_SetBlock(t,s,strlen(s)+1)
+#ifndef FAILED
#define FAILED(b) ((b)<0)
-#define SUCCEDED(b) ((b)>=0)
+#endif
+#ifndef SUCCEEDED
+#define SUCCEEDED(b) ((b)>=0)
+#endif
// Tag IDs (adopted from J. C. Kessels' Form2Flash)
int swf_FontSetDefine2(TAG * t,SWFFONT * f);
int swf_FontSetInfo(TAG * t,SWFFONT * f);
+void swf_FontCreateLayout(SWFFONT*f);
void swf_FontAddLayout(SWFFONT * f, int ascent, int descent, int leading);
int swf_FontExtract_DefineTextCallback(int id,SWFFONT * f,TAG * t,int jobs,
void swf_SetEditText(TAG*tag, U16 flags, SRECT r, char*text, RGBA*color,
int maxlength, U16 font, U16 height, EditTextLayout*layout, char*variable);
-void swf_SetDefineText(TAG*tag, SWFFONT*font, RGBA*rgb, char*text, int scale);
+SRECT swf_SetDefineText(TAG*tag, SWFFONT*font, RGBA*rgb, char*text, int scale);
// swfdump.c
U8 swf_isPseudoDefiningTag(TAG * t);
U8 swf_isAllowedSpriteTag(TAG * t);
U16 swf_GetDefineID(TAG * t);
+SRECT swf_GetDefineBBox(TAG * t);
void swf_SetDefineID(TAG * t, U16 newid);
U16 swf_GetPlaceID(TAG * t); //PLACEOBJECT, PLACEOBJECT2 (sometimes), REMOVEOBJECT
U16 swf_GetDepth(TAG * t); //PLACEOBJECT,PLACEOBJECT2,REMOVEOBJECT,REMOVEOBJECT2
void swf_GetPlaceObject(TAG * t,SWFPLACEOBJECT* obj);
void swf_PlaceObjectFree(SWFPLACEOBJECT* obj);
+#ifdef __cplusplus
+}
+#endif
+
#endif