Part of the swftools package.
Copyright (c) 2001 Matthias Kramm <kramm@quiss.org>
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
static int optimize = 0;
static int override_outputname = 0;
static int do_cgi = 0;
+static int change_sets_all = 0;
static struct options_t options[] = {
{"h", "help"},
{"o", "output"},
{0,0}
};
-
+
int args_callback_option(char*name,char*val)
{
if(!strcmp(name, "V")) {
/* for swf (0): */
SWF*swf;
- char*filename;
+ char*filename;
/* for sprites (1): */
TAG*tag;
static dictionary_t fontUsage;
typedef struct _parameters {
- int x,y;
- float scalex, scaley;
+ int x,y;
+ float scalex, scaley;
CXFORM cxform;
float rotate;
float shear;
SPOINT pivot;
SPOINT pin;
U8 blendmode; //not interpolated
- FILTER*filter;
+ FILTERLIST* filters;
U16 set; // bits indicating wether a parameter was set in the c_placement function
} parameters_t;
character_t*character;
U16 depth;
parameters_t parameters;
- TAG* lastTag; //last tag which set the object
- U16 lastFrame; //frame lastTag is in
+ U16 deathFrame;
history_t* history;
} instance_t;
"bounceIn", "bounceOut", "bounceInOut", \
"fastBounceIn", "fastBounceOut", "fastBounceInOut"};
-typedef struct _fontData {
- char *glyphs;
- int notUsed, needsAll;
-} fontData;
-
-void addFontData(char *name)
-{
- fontData* newFont;
- newFont = (fontData *)malloc(sizeof(fontData));
- memset(newFont, 0, sizeof(fontData));
- newFont->notUsed = 1;
- dictionary_put2(&fontUsage, name, newFont);
-}
-
-void freeFontData(fontData* font)
-{
- free(font->glyphs);
- free(font);
-}
-
-fontData *getFontData(char *name)
-{
- return (fontData *)dictionary_lookup(&fontUsage, name);
-}
-
static void character_init(character_t*c)
{
memset(c, 0, sizeof(character_t));
swf_FontFree((SWFFONT*)f);
}
-static void free_fontData(void* fd)
-{
- freeFontData((fontData*)fd);
-}
-
static void gradient_free(GRADIENT* grad)
{
free(grad->ratios);
dictionary_free_all(&filters, free);
dictionary_free_all(&fonts, free_font);
dictionary_free_all(&sounds, free);
- dictionary_free_all(&fontUsage, free_fontData);
dictionary_free_all(&interpolations, free);
}
+static void freeFontDictionary()
+{
+ dictionary_free_all(&fonts, free_font);
+}
+
static void incrementid()
{
while(idmap[++id]) {
if(dictionary_lookup(&characters, name))
syntaxerror("character %s defined twice", name);
character_t* c = character_new();
-
+
c->definingTag = ctag;
c->id = id;
c->size = r;
{
if(dictionary_lookup(&images, name))
syntaxerror("image %s defined twice", name);
-
+
character_t* c = character_new();
c->definingTag = ctag;
c->id = id;
static void parameters_clear(parameters_t*p)
{
- p->x = 0; p->y = 0;
+ p->x = 0; p->y = 0;
p->scalex = 1.0; p->scaley = 1.0;
p->pin.x = 0; //1??
p->pin.y = 0;
p->pivot.x = 0; p->pivot.y = 0;
- p->rotate = 0;
- p->shear = 0;
+ p->rotate = 0;
+ p->shear = 0;
p->blendmode = 0;
- p->filter = 0;
+ p->filters = 0;
swf_GetCXForm(0, &p->cxform, 1);
}
SPOINT h;
float sx,r1,r0,sy;
- /* /sx r1\ /x\
+ /* /sx r1\ /x\
* \r0 sy/ \y/
*/
- sx = p->scalex*cos(p->rotate/360*2*PI);
- r1 = -p->scalex*sin(p->rotate/360*2*PI)+sx*p->shear;
- r0 = p->scaley*sin(p->rotate/360*2*PI);
- sy = p->scaley*cos(p->rotate/360*2*PI)+r0*p->shear;
+ sx = p->scalex*cos(p->rotate/360*2*M_PI);
+ r1 = -p->scalex*sin(p->rotate/360*2*M_PI)+sx*p->shear;
+ r0 = p->scaley*sin(p->rotate/360*2*M_PI);
+ sy = p->scaley*cos(p->rotate/360*2*M_PI)+r0*p->shear;
m->sx = (int)(sx*65536+0.5);
m->r1 = (int)(r1*65536+0.5);
m->sy = (int)(sy*65536+0.5);
m->tx = m->ty = 0;
-
+
h = swf_TurnPoint(p->pin, m);
m->tx = p->x - h.x;
m->ty = p->y - h.y;
SRECT r;
makeMatrix(&m, p);
r = swf_TurnRect(rect, &m);
- if(currentrect.xmin == 0 && currentrect.ymin == 0 &&
+ if(currentrect.xmin == 0 && currentrect.ymin == 0 &&
currentrect.xmax == 0 && currentrect.ymax == 0)
currentrect = r;
else
return m;
}
-void builtInInterpolations()
+void initBuiltIns()
{
interpolation_t* new;
new = (interpolation_t*)malloc(sizeof(interpolation_t));
new = (interpolation_t*)malloc(sizeof(interpolation_t));
new->function = IF_SINE_IN_OUT;
dictionary_put2(&interpolations, "sineInOut", new);
+
+ RGBA c;
+ memset(&c, 0, sizeof(RGBA));
+ gradient_t* noGradient = (gradient_t*)malloc(sizeof(gradient_t));
+ noGradient->gradient.ratios = (U8*)malloc(16 * sizeof(U8));
+ noGradient->gradient.rgba = (RGBA*)malloc(16 * sizeof(RGBA));
+ noGradient->gradient.num = 2;
+ noGradient->gradient.rgba[0] = c;
+ noGradient->gradient.ratios[0] = 0;
+ noGradient->gradient.rgba[1] = c;
+ noGradient->gradient.ratios[1] = 255;
+ noGradient->radial = 0;
+ noGradient->rotate = 0;
+ dictionary_put2(&gradients, "no_gradient", noGradient);
+
+ noFilters = 0;
+// put a no_filters entry in the filters dictionary to provoce a message when a user tries
+// to define a no_filters filter. The real filter=no_filters case is handled in parseFilters.
+ char* dummy = (char*)malloc(2);
+ dictionary_put2(&filters, "no_filters", dummy);
+ noBlur = (FILTER_BLUR*) swf_NewFilter(FILTERTYPE_BLUR);
+ noBlur->passes = 1;
+ dictionary_put2(&filters, "no_blur", noBlur);
+ noBevel = (FILTER_BEVEL*) swf_NewFilter(FILTERTYPE_BEVEL);
+ noBevel->passes = 1;
+ noBevel->composite = 1;
+ dictionary_put2(&filters, "no_bevel", noBevel);
+ noDropshadow = (FILTER_DROPSHADOW*) swf_NewFilter(FILTERTYPE_DROPSHADOW);
+ noDropshadow->passes = 1;
+ noDropshadow->composite = 1;
+ dictionary_put2(&filters, "no_dropshadow", noDropshadow);
+ noGradientGlow = (FILTER_GRADIENTGLOW*) swf_NewFilter(FILTERTYPE_GRADIENTGLOW);
+ noGradientGlow->passes = 1;
+ noGradientGlow->composite = 1;
+ noGradientGlow->gradient = &noGradient->gradient;
+ dictionary_put2(&filters, "no_gradientglow", noGradientGlow);
}
void s_swf(char*name, SRECT r, int version, int fps, int compress, RGBA background)
syntaxerror(".swf blocks can't be nested");
if(stackpos==sizeof(stack)/sizeof(stack[0]))
syntaxerror("too many levels of recursion");
-
+
SWF*swf = (SWF*)malloc(sizeof(SWF));
memset(swf, 0, sizeof(swf));
swf->firstTag = tag = swf_InsertTag(0, ST_SETBACKGROUNDCOLOR);
swf->compressed = compress;
swf_SetRGB(tag,&background);
-
+
dictionary_init(&characters);
dictionary_init(&images);
dictionary_init(&textures);
dictionary_init(&gradients);
dictionary_init(&filters);
dictionary_init(&instances);
- dictionary_init(&fonts);
dictionary_init(&sounds);
dictionary_init(&interpolations);
- builtInInterpolations();
+ initBuiltIns();
cleanUp = &freeDictionaries;
memset(&stack[stackpos], 0, sizeof(stack[0]));
stack[stackpos].swf = swf;
stack[stackpos].oldframe = -1;
stackpos++;
- id = 0;
currentframe = 0;
memset(¤trect, 0, sizeof(currentrect));
currentdepth = 1;
-
+
memset(idmap, 0, sizeof(idmap));
incrementid();
}
stack[stackpos].tag = tag;
stack[stackpos].id = id;
stack[stackpos].name = strdup(name);
-
+
/* FIXME: those four fields should be bundled together */
dictionary_init(&instances);
currentframe = 0;
if(mybutton.endofshapes) {
syntaxerror("a .do may not precede a .show", character, character);
}
-
+
m = s_instancepos(c->size, &p);
r.id = c->id;
int flags[] = {BS_UP,BS_OVER,BS_DOWN,BS_HIT};
if(!mybutton.endofshapes) {
int t;
-
+
if(!mybutton.records[3].set) {
memcpy(&mybutton.records[3], &mybutton.records[0], sizeof(buttonrecord_t));
}
return;
}
setbuttonrecords(stack[stackpos-1].tag);
-
+
a = swf_ActionCompile(text, stack[0].swf->fileVersion);
if(!a) {
syntaxerror("Couldn't compile ActionScript");
setbuttonrecords(stack[stackpos-1].tag);
setactionend(stack[stackpos-1].tag);
stackpos--;
-
+
swf_ButtonPostProcess(stack[stackpos].tag, mybutton.nr_actions);
r = currentrect;
return save;
}
+static int parametersChange(history_t* history, int frame)
+{
+ int willChange = 0;
+
+ willChange = willChange || history_change(history, frame, "x");
+ willChange = willChange || history_change(history, frame, "y");
+ willChange = willChange || history_change(history, frame, "scalex");
+ willChange = willChange || history_change(history, frame, "scaley");
+ willChange = willChange || history_change(history, frame, "cxform.r0");
+ willChange = willChange || history_change(history, frame, "cxform.g0");
+ willChange = willChange || history_change(history, frame, "cxform.b0");
+ willChange = willChange || history_change(history, frame, "cxform.a0");
+ willChange = willChange || history_change(history, frame, "cxform.r1");
+ willChange = willChange || history_change(history, frame, "cxform.g1");
+ willChange = willChange || history_change(history, frame, "cxform.b1");
+ willChange = willChange || history_change(history, frame, "cxform.a1");
+ willChange = willChange || history_change(history, frame, "rotate");
+ willChange = willChange || history_change(history, frame, "shear");
+ willChange = willChange || history_change(history, frame, "pivot.x");
+ willChange = willChange || history_change(history, frame, "pivot.y");
+ willChange = willChange || history_change(history, frame, "pin.x");
+ willChange = willChange || history_change(history, frame, "pin.y");
+ willChange = willChange || history_change(history, frame, "blendmode");
+ willChange = willChange || history_changeFilter(history, frame);
+
+ return willChange;
+}
+
+static void free_filterlist(FILTERLIST* f_list)
+{
+ int i;
+ for (i = 0; i < f_list->num; i++)
+ {
+ if (f_list->filter[i]->type == FILTERTYPE_GRADIENTGLOW)
+ gradient_free(((FILTER_GRADIENTGLOW*)f_list->filter[i])->gradient);
+ free(f_list->filter[i]);
+ }
+ free(f_list);
+}
+
static void readParameters(history_t* history, parameters_t* p, int frame)
{
p->x = history_value(history, frame, "x");
p->pin.x = history_value(history, frame, "pin.x");
p->pin.y = history_value(history, frame, "pin.y");
p->blendmode = history_value(history, frame, "blendmode");
- p->filter = history_valueFilter(history, frame);
+ p->filters = history_valueFilter(history, frame);
}
void setPlacement(TAG*tag, U16 id, U16 depth, MATRIX m, char*name, parameters_t*p, char move)
if(p->blendmode) {
po.blendmode = p->blendmode;
}
- if(p->filter) {
- flist.num = 1;
- flist.filter[0] = p->filter;
- po.filters = &flist;
- }
+ if (p->filters)
+ po.filters = p->filters;
swf_SetPlaceObject(tag, &po);
}
while (frame < currentframe)
{
frame++;
- readParameters(i->history, &p, frame);
while (tag->id != ST_SHOWFRAME)
tag = tag->next;
+ if (i->deathFrame == frame)
+ {
+ tag = swf_InsertTag(tag, ST_REMOVEOBJECT2);
+ swf_SetU16(tag, i->depth);
+ break;
+ }
+ if (parametersChange(i->history, frame))
+ {
+ readParameters(i->history, &p, frame);
m = s_instancepos(i->character->size, &p);
- if(p.blendmode || p.filter)
+ if(p.blendmode || p.filters)
tag = swf_InsertTag(tag, ST_PLACEOBJECT3);
else
tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
setPlacement(tag, 0, i->depth, m, 0, &p, 1);
- if (p.filter)
- free(p.filter);
+ if (p.filters)
+ free_filterlist(p.filters);
+}
+ else
+ tag = tag->next;
}
}
static void s_endSprite()
{
SRECT r = currentrect;
-
+
if(stack[stackpos].cut)
tag = removeFromTo(stack[stackpos].cut, tag);
num++;
name = stringarray_at(index, num);
}
-
+ while (tag->next)
+ tag = tag->next;
+
tag = swf_InsertTag(tag, ST_SHOWFRAME);
tag = swf_InsertTag(tag, ST_END);
int fi;
SWF* swf;
char*filename;
-
+
instance_t *i;
- stringarray_t* index =dictionary_index(&instances);
+ stringarray_t* index = dictionary_index(&instances);
int num = 0;
char* name = stringarray_at(index, num);
while (name)
tag = removeFromTo(stack[stackpos].cut, tag);
stackpos--;
-
+
swf = stack[stackpos].swf;
filename = stack[stackpos].filename;
-
+
//if(tag->prev && tag->prev->id != ST_SHOWFRAME)
// tag = swf_InsertTag(tag, ST_SHOWFRAME);
tag = swf_InsertTag(tag, ST_SHOWFRAME);
tag = swf_InsertTag(tag, ST_END);
swf_OptimizeTagOrder(swf);
-
+
if(optimize) {
swf_Optimize(swf);
}
-
+
if(!(swf->movieSize.xmax-swf->movieSize.xmin) || !(swf->movieSize.ymax-swf->movieSize.ymin)) {
swf->movieSize = currentrect; /* "autocrop" */
}
-
+
if(!(swf->movieSize.xmax-swf->movieSize.xmin) || !(swf->movieSize.ymax-swf->movieSize.ymin)) {
swf->movieSize.xmax += 20; /* 1 by 1 pixels */
swf->movieSize.ymax += 20;
warning("Empty bounding box for movie");
}
-
+
if(do_cgi || !strcmp(filename, "-"))
fi = fileno(stdout);
else
}
if(do_cgi)
{if(swf_WriteCGI(swf)<0) syntaxerror("WriteCGI() failed.\n");}
- else if(swf->compressed)
+ else if(swf->compressed)
{if(swf_WriteSWC(fi, swf)<0) syntaxerror("WriteSWC() failed.\n");}
else
{if(swf_WriteSWF(fi, swf)<0) syntaxerror("WriteSWF() failed.\n");}
int t;
TAG*now = tag;
- if(nr<1)
+ if(nr<1)
syntaxerror("Illegal frame number");
nr--; // internally, frame 1 is frame 0
MATRIX rot,m;
double ccos,csin;
swf_GetMatrix(0, &rot);
- ccos = cos(-gradient->rotate*2*PI/360);
- csin = sin(-gradient->rotate*2*PI/360);
+ ccos = cos(-gradient->rotate*2*M_PI/360);
+ csin = sin(-gradient->rotate*2*M_PI/360);
rot.sx = ccos*65536;
rot.r1 = -csin*65536;
rot.r0 = csin*65536;
return 0;
}
}
-
+
RGBA black={r:0,g:0,b:0,a:0};
void s_box(char*name, int width, int height, RGBA color, int linewidth, char*texture)
{
swf_ShapeSetLine(tag,s,0,-height);
swf_ShapeSetEnd(tag);
swf_ShapeFree(s);
-
+
s_addcharacter(name, id, tag, r);
incrementid();
}
}
if(texture)
fs1 = addFillStyle(s, &r2, texture);
-
+
swf_SetU16(tag,id);
rect.xmin = r2.xmin-linewidth/2;
rect.ymin = r2.ymin-linewidth/2;
swf_SetRect(tag,&rect);
swf_SetShapeStyles(tag, s);
swf_ShapeCountBits(s,0,0);
- swf_RecodeShapeData(outline->shape->data, outline->shape->bitlen, outline->shape->bits.fill, outline->shape->bits.line,
+ swf_RecodeShapeData(outline->shape->data, outline->shape->bitlen, outline->shape->bits.fill, outline->shape->bits.line,
&s->data, &s->bitlen, s->bits.fill, s->bits.line);
swf_SetShapeBits(tag, s);
swf_SetBlock(tag, s->data, (s->bitlen+7)/8);
swf_ShapeSetCircle(tag, s, r,r,r,r);
swf_ShapeSetEnd(tag);
swf_ShapeFree(s);
-
+
s_addcharacter(name, id, tag, rect);
incrementid();
}
font = dictionary_lookup(&fonts, fontname);
if(!font)
syntaxerror("font \"%s\" not known!", fontname);
-
+
if(text[0] >= font->maxascii || font->ascii2glyph[text[0]]<0) {
warning("no character 0x%02x (%c) in font \"%s\"", text[0], text[0], fontname);
s_box(name, 0, 0, black, 20, 0);
memset(outline, 0, sizeof(outline_t));
outline->shape = font->glyph[g].shape;
outline->bbox = font->layout->bounds[g];
-
+
{
drawer_t draw;
swf_Shape11DrawerInit(&draw, 0);
font = dictionary_lookup(&fonts, fontname);
if(!font)
syntaxerror("font \"%s\" not known!", fontname);
-
+
tag = swf_InsertTag(tag, ST_DEFINETEXT2);
swf_SetU16(tag, id);
if(!font->numchars) {
swf_SetU32(tag, 0);//sharpness
swf_SetU8(tag, 0);//reserved
}
-
+
s_addcharacter(name, id, tag, r);
incrementid();
}
MATRIX _m,*m=0;
memset(&r, 0, sizeof(r));
-
+
tag = swf_InsertTag(tag, ST_DEFINEMOVIE);
swf_SetU16(tag, id);
swf_SetString(tag, url);
-
+
s_addcharacter(name, id, tag, r);
incrementid();
}
r.ymin = 0;
r.xmax = width;
r.ymax = height;
-
+
swf_SetEditText(tag, flags, r, text, color, maxlength, font?font->id:0, size, &layout, variable);
s_addcharacter(name, id, tag, r);
{
/* an image is actually two folded: 1st bitmap, 2nd character.
Both of them can be used separately */
-
+
/* step 1: the bitmap */
SRECT r;
int imageID = id;
void s_font(char*name, char*filename)
{
- if(dictionary_lookup(&fonts, name))
- syntaxerror("font %s defined twice", name);
-
SWFFONT* font;
- font = swf_LoadFont(filename);
-
- if(font == 0) {
- warning("Couldn't open font file \"%s\"", filename);
- font = (SWFFONT*)malloc(sizeof(SWFFONT));
- memset(font, 0, sizeof(SWFFONT));
- dictionary_put2(&fonts, name, font);
- return;
- }
-
+ font = dictionary_lookup(&fonts, name);
if(0)
{
/* fix the layout. Only needed for old fonts */
font->layout = 0;
swf_FontCreateLayout(font);
}
- /* just in case this thing is used in .edittext later on */
- swf_FontPrepareForEditText(font);
-
font->id = id;
+ swf_FontReduce_swfc(font);
tag = swf_InsertTag(tag, ST_DEFINEFONT2);
swf_FontSetDefine2(tag, font);
tag = swf_InsertTag(tag, ST_EXPORTASSETS);
swf_SetU16(tag, 1);
swf_SetU16(tag, id);
swf_SetString(tag, name);
- incrementid();
- dictionary_put2(&fonts, name, font);
+ incrementid();
}
if(dictionary_lookup(&sounds, name))
syntaxerror("sound %s defined twice", name);
-
+
if(wav_read(&wav, filename))
{
int t;
samples = 0;
numsamples = 0;
}
-
+
if(numsamples%blocksize != 0)
{
// apply padding, so that block is a multiple of blocksize
}
else
swf_SetSoundDefine(tag, samples, numsamples);
-
+
tag = swf_InsertTag(tag, ST_NAMECHARACTER);
swf_SetU16(tag, id);
swf_SetString(tag, name);
sound->id = id;
dictionary_put2(&sounds, name, sound);
-
+
incrementid();
if (samples)
char*result;
while(**p && strchr(" \t\n\r", **p)) {
(*p)++;
- }
+ }
start = *p;
while(**p && !strchr(" \t\n\r", **p)) {
(*p)++;
memset(&gradient, 0, sizeof(GRADIENT));
gradient.ratios = rfx_calloc(16*sizeof(U8));
gradient.rgba = rfx_calloc(16*sizeof(RGBA));
-
+
while(*p)
{
char*posstr,*colorstr;
return gradient;
}
+FILTERLIST* parseFilters(char* list)
+{
+ if (!strcmp(list, "no_filters"))
+ return noFilters;
+ FILTER* f;
+ FILTERLIST* f_list = (FILTERLIST*)malloc(sizeof(FILTERLIST));
+ f_list->num = 0;
+ char* f_start = list;
+ char* f_end;
+ while (f_start)
+ {
+ f_end = strchr(f_start, ',');
+ if (f_end)
+ *f_end = '\0';
+ f = dictionary_lookup(&filters, f_start);
+ if (!f)
+ {
+ free(f_list);
+ syntaxerror("unknown filter %s", f_start);
+ }
+ if (f_list->num == 8)
+ {
+ warning("too many filters in filterlist, no more than 8 please, rest ignored");
+ break;
+ }
+ f_list->filter[f_list->num] = f;
+ f_list->num++;
+ if (f_end)
+ {
+ *f_end = ',';
+ f_start = f_end + 1;
+ }
+ else
+ f_start = 0;
+ }
+ return f_list;
+}
+
void s_gradient(char*name, const char*text, int radial, int rotate)
{
gradient_t* gradient;
dictionary_put2(&gradients, name, gradient);
}
-
-void s_gradientglow(char*name, char*gradient, float blurx, float blury,
- float angle, float distance, float strength, char innershadow,
+
+void s_gradientglow(char*name, char*gradient, float blurx, float blury,
+ float angle, float distance, float strength, char innershadow,
char knockout, char composite, char ontop, int passes)
{
if(dictionary_lookup(&filters, name))
syntaxerror("filter %s defined twice", name);
-
+
gradient_t* g = dictionary_lookup(&gradients, gradient);
+ if(!g)
+ syntaxerror("unknown gradient %s", gradient);
composite = 1;
- if(!g)
- syntaxerror("unknown gradient %s", gradient);
FILTER_GRADIENTGLOW* filter = rfx_calloc(sizeof(FILTER_GRADIENTGLOW));
filter->type = FILTERTYPE_GRADIENTGLOW;
filter->gradient = &g->gradient;
ActionTAG* a = 0;
character_t*c = 0;
a = swf_ActionCompile(text, stack[0].swf->fileVersion);
- if(!a)
+ if(!a)
{
swf_ActionFree(a);
syntaxerror("Couldn't compile ActionScript");
{
ActionTAG* a = 0;
instance_t* object = 0;
- if(name)
+ if(name)
object = (instance_t*)dictionary_lookup(&instances, name);
if(!object && name && *name) {
/* we have a name, but couldn't find it. Abort. */
{
if(dictionary_lookup(&outlines, name))
syntaxerror("outline %s defined twice", name);
-
+
outline_t* outline;
drawer_t draw;
SHAPE* shape;
SHAPE2* shape2;
SRECT bounds;
-
+
//swf_Shape10DrawerInit(&draw, 0);
swf_Shape11DrawerInit(&draw, 0);
shape = swf_ShapeDrawerToShape(&draw);
bounds = swf_ShapeDrawerGetBBox(&draw);
draw.dealloc(&draw);
-
+
outline = (outline_t*)rfx_calloc(sizeof(outline_t));
outline->shape = shape;
outline->bbox = bounds;
-
+
dictionary_put2(&outlines, name, outline);
}
int level = 0;
U16 cutout[] = {ST_SETBACKGROUNDCOLOR, ST_PROTECT, ST_FREEALL, ST_REFLEX};
f = open(filename,O_RDONLY|O_BINARY);
- if (f<0) {
+ if (f<0) {
warning("Couldn't open file \"%s\": %s", filename, strerror(errno));
s_box(name, 0, 0, black, 20, 0);
return;
}
- if (swf_ReadSWF(f,&swf)<0) {
+ if (swf_ReadSWF(f,&swf)<0) {
warning("Only SWF files supported in .shape for now. File \"%s\" wasn't SWF.", filename);
s_box(name, 0, 0, black, 20, 0);
return;
}
close(f);
- /* FIXME: The following sets the bounding Box for the character.
+ /* FIXME: The following sets the bounding Box for the character.
It is wrong for two reasons:
a) It may be too small (in case objects in the movie clip at the borders)
b) it may be too big (because the poor movie never got autocropped)
*/
r = swf.movieSize;
-
+
s = tag = swf_InsertTag(tag, ST_DEFINESPRITE);
swf_SetU16(tag, id);
swf_SetU16(tag, swf.frameCount);
if(ftag->id != ST_SETBACKGROUNDCOLOR) {
/* We simply dump all tags right after the sprite
header, relying on the fact that swf_OptimizeTagOrder() will
- sort things out for us later.
+ sort things out for us later.
We also rely on the fact that the imported SWF is well-formed.
*/
tag = swf_InsertTag(tag, ftag->id);
if(!c) syntaxerror("internal error(5)");
return c->size;
}
-parameters_t s_getParameters(char*name)
+void s_getParameters(char*name, parameters_t* p)
{
instance_t * i = dictionary_lookup(&instances, name);
- if(!i) syntaxerror("instance '%s' unknown(10)", name);
- return i->parameters;
+ if(!i)
+ syntaxerror("instance '%s' unknown(10)", name);
+ if (change_sets_all)
+ readParameters(i->history, p, currentframe);
+ else
+ *p = i->parameters;
}
void s_startclip(char*instance, char*character, parameters_t p)
{
i = s_addinstance(instance, c, currentdepth);
i->parameters = p;
m = s_instancepos(i->character->size, &p);
-
+
tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
/* TODO: should be ObjectPlaceClip, with clipdepth backpatched */
swf_ObjectPlace(tag, c->id, currentdepth, &m, &p.cxform, instance);
- i->lastTag = tag;
- i->lastFrame= currentframe;
stack[stackpos].tag = tag;
stack[stackpos].type = 2;
history_begin(i->history, "pin.x", currentframe, tag, p->pin.x);
history_begin(i->history, "pin.y", currentframe, tag, p->pin.y);
history_begin(i->history, "blendmode", currentframe, tag, p->blendmode);
- history_beginFilter(i->history, currentframe, tag, p->filter);
+ history_beginFilter(i->history, currentframe, tag, p->filters);
}
void s_put(char*instance, char*character, parameters_t p)
character_t* c = dictionary_lookup(&characters, character);
instance_t* i;
MATRIX m;
- if(!c)
+ if(!c)
syntaxerror("character %s not known (in .put %s=%s)", character, instance, character);
-
+
i = s_addinstance(instance, c, currentdepth);
i->parameters = p;
m = s_instancepos(i->character->size, &p);
-
- if(p.blendmode || p.filter)
+
+ if(p.blendmode || p.filters)
{
- if(stack[0].swf->fileVersion < 8)
+ if(stack[0].swf->fileVersion < 8)
{
if(p.blendmode)
warning("blendmodes only supported for flash version>=8");
tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
setPlacement(tag, c->id, currentdepth, m, instance, &p, 0);
setStartparameters(i, &p, tag);
- i->lastTag = tag;
- i->lastFrame = currentframe;
currentdepth++;
}
if (p.set & SF_BLEND)
history_remember(history, "blendmode", currentframe, changeFunction, p.blendmode, inter);
if (p.set & SF_FILTER)
- history_rememberFilter(history, currentframe, changeFunction, p.filter, inter);
+ history_rememberFilter(history, currentframe, changeFunction, p.filters, inter);
}
void s_jump(char* instance, parameters_t p)
instance_t* i = dictionary_lookup(&instances, instance);
if(!i)
syntaxerror("instance %s not known", instance);
+
recordChanges(i->history, p2, CF_CHANGE, inter);
}
instance_t* i = dictionary_lookup(&instances, instance);
if(!i)
syntaxerror("instance %s not known", instance);
- tag = swf_InsertTag(tag, ST_REMOVEOBJECT2);
- swf_SetU16(tag, i->depth);
- dictionary_del(&instances, instance);
+ i->deathFrame = currentframe;
}
void s_qchange(char*instance, parameters_t p)
return value;
}
-static int c_flash(map_t*args)
+static int c_flash(map_t*args)
{
char* filename = map_lookup(args, "filename");
char* compressstr = lu(args, "compress");
+ char* change_modestr = lu(args, "change-sets-all");
SRECT bbox = parseBox(lu(args, "bbox"));
int version = parseInt(lu(args, "version"));
int fps = (int)(parseFloat(lu(args, "fps"))*256);
- int compress = 0;
RGBA color = parseColor(lu(args, "background"));
+ int compress = 0;
if(!filename || !*filename) {
/* for compatibility */
if(!filename || override_outputname)
filename = outputname;
-
+
if(!strcmp(compressstr, "default"))
compress = version>=6;
else if(!strcmp(compressstr, "yes") || !strcmp(compressstr, "compress"))
compress = 0;
else syntaxerror("value \"%s\" not supported for the compress argument", compressstr);
+ if(!strcmp(change_modestr, "yes"))
+ change_sets_all = 1;
+ else
+ if(strcmp(change_modestr, "no"))
+ syntaxerror("value \"%s\" not supported for the change-sets-all argument", change_modestr);
+
s_swf(filename, bbox, version, fps, compress, color);
return 0;
}
char* name = lu(args, "name");
if (dictionary_lookup(&interpolations, name))
syntaxerror("interpolation %s defined twice", name);
-
+
interpolation_t* inter = (interpolation_t*)malloc(sizeof(interpolation_t));
char* functionstr = lu(args, "function");
inter->function = 0;
inter->growth = parseFloat(lu(args, "growth"));
inter->bounces = parseInt(lu(args, "bounces"));
inter->damping = parseInt(lu(args, "damping"));
-
+
dictionary_put2(&interpolations, name, inter);
return 0;
}
return *(SPOINT*)&mpoints.buffer[l];
}
-static int texture2(char*name, char*object, map_t*args, int errors)
+static int texture2(char*name, char*object, map_t*args, int errors)
{
SPOINT pos,size;
char*xstr = map_lookup(args, "x");
return 0;
}
-static int c_texture(map_t*args)
+static int c_texture(map_t*args)
{
char*name = lu(args, "instance");
char*object = lu(args, "character");
return texture2(name, object, args, 1);
}
-static int c_gradient(map_t*args)
+static int c_gradient(map_t*args)
{
char*name = lu(args, "name");
int radial= strcmp(lu(args, "radial"), "radial")?0:1;
return 0;
}
-static int c_blur(map_t*args)
+static char* checkFiltername(map_t* args)
{
char*name = lu(args, "name");
+ if (strchr(name, ','))
+ syntaxerror("the comma (,) is used to separate filters in filterlists. Please do not use in filternames.");
+ return name;
+}
+
+static int c_blur(map_t*args)
+{
+ char*name = checkFiltername(args);
char*blurstr = lu(args, "blur");
char*blurxstr = lu(args, "blurx");
char*blurystr = lu(args, "blury");
if(blurstr[0]) {
blurx = parseFloat(blurstr);
blury = parseFloat(blurstr);
- }
+ }
if(blurxstr[0])
blurx = parseFloat(blurxstr);
if(blurystr[0])
return 0;
}
-static int c_gradientglow(map_t*args)
+static int c_gradientglow(map_t*args)
{
- char*name = lu(args, "name");
+ char*name = checkFiltername(args);
char*gradient = lu(args, "gradient");
char*blurstr = lu(args, "blur");
char*blurxstr = lu(args, "blurx");
if(blurstr[0]) {
blurx = parseFloat(blurstr);
blury = parseFloat(blurstr);
- }
+ }
if(blurxstr[0])
blurx = parseFloat(blurxstr);
if(blurystr[0])
return 0;
}
-static int c_dropshadow(map_t*args)
+static int c_dropshadow(map_t*args)
{
- char*name = lu(args, "name");
+ char*name = checkFiltername(args);
RGBA color = parseColor(lu(args, "color"));
char*blurstr = lu(args, "blur");
char*blurxstr = lu(args, "blurx");
if(blurstr[0]) {
blurx = parseFloat(blurstr);
blury = parseFloat(blurstr);
- }
+ }
if(blurxstr[0])
blurx = parseFloat(blurxstr);
if(blurystr[0])
return 0;
}
-static int c_bevel(map_t*args)
+static int c_bevel(map_t*args)
{
- char*name = lu(args, "name");
+ char*name = checkFiltername(args);
RGBA shadow = parseColor(lu(args, "shadow"));
RGBA highlight = parseColor(lu(args, "highlight"));
char*blurstr = lu(args, "blur");
if(blurstr[0]) {
blurx = parseFloat(blurstr);
blury = parseFloat(blurstr);
- }
+ }
if(blurxstr[0])
blurx = parseFloat(blurxstr);
if(blurystr[0])
return 0;
}
-static int c_point(map_t*args)
+static int c_point(map_t*args)
{
char*name = lu(args, "name");
int pos;
dictionary_put(&points, s1, (void*)pos);
return 0;
}
-static int c_play(map_t*args)
+static int c_play(map_t*args)
{
char*name = lu(args, "name");
char*loop = lu(args, "loop");
return 0;
}
-static int c_stop(map_t*args)
+static int c_stop(map_t*args)
{
char*name = map_lookup(args, "name");
return 0;
}
-static int c_nextframe(map_t*args)
+static int c_nextframe(map_t*args)
{
char*name = lu(args, "name");
return 0;
}
-static int c_previousframe(map_t*args)
+static int c_previousframe(map_t*args)
{
char*name = lu(args, "name");
SRECT oldbbox;
MULADD luminance;
parameters_t p;
- U32 set = 0x00000000;
+ U16 set = 0x0000;
if(type==9)
{ // (?) .rotate or .arcchange
xstr = lu(args, "x");
ystr = lu(args, "y");
}
-
+
if(luminancestr[0])
luminance = parseMulAdd(luminancestr);
else
syntaxerror("scalex/scaley and scale cannot both be set");
scalexstr = scaleystr = scalestr;
}
-
+
if(type == 0 || type == 4) {
// put or startclip
character = lu(args, "character");
parameters_clear(&p);
// button's show
} else {
- p = s_getParameters(instance);
+ s_getParameters(instance, &p);
}
/* x,y position */
- if(xstr[0])
+ if(xstr[0])
{
if(isRelative(xstr))
{
p.scaley = (float)(parseNewSize(scaleystr, oldheight))/oldheight;
set = set | SF_SCALEY;
}
-
+
/* rotation */
if(rotatestr[0])
{
{
if(isPoint(pivotstr))
p.pivot = parsePoint(pivotstr);
- else
+ else
p.pivot = getPoint(oldbbox, pivotstr);
set = set | SF_PIVOT;
}
-
+
if(pinstr[0])
{
if(isPoint(pinstr))
p.pin = getPoint(oldbbox, pinstr);
set = set | SF_PIN;
}
-
+
/* color transform */
if(rstr[0] || luminancestr[0])
p.blendmode = blend;
set = set | SF_BLEND;
}
-
+
if(filterstr[0])
{
- FILTER*f = dictionary_lookup(&filters, filterstr);
- if(!f)
- syntaxerror("Unknown filter %s", filterstr);
- p.filter = f;
+ p.filters = parseFilters(filterstr);
set = set | SF_FILTER;
}
+ if (change_sets_all)
+ set = SF_ALL;
p.set = set;
switch (type)
else
s_buttonput(character, "shape", p);
break;
-// default:
+// default:
}
return 0;
}
-static int c_put(map_t*args)
+static int c_put(map_t*args)
{
c_placement(args, 0);
return 0;
}
-static int c_change(map_t*args)
+static int c_change(map_t*args)
{
if (currentframe == 0)
warning("change commands in frame 1 will be ignored, please use the put command to set object parameters");
c_placement(args, 1);
return 0;
}
-static int c_qchange(map_t*args)
+static int c_qchange(map_t*args)
{
c_placement(args, 2);
return 0;
}
-static int c_arcchange(map_t*args)
+static int c_arcchange(map_t*args)
{
c_placement(args, 2);
return 0;
}
-static int c_jump(map_t*args)
+static int c_jump(map_t*args)
{
c_placement(args, 3);
return 0;
}
-static int c_startclip(map_t*args)
+static int c_startclip(map_t*args)
{
c_placement(args, 4);
return 0;
}
-static int c_show(map_t*args)
+static int c_show(map_t*args)
{
c_placement(args, 5);
return 0;
}
-static int c_del(map_t*args)
+static int c_del(map_t*args)
{
char*instance = lu(args, "name");
s_delinstance(instance);
return 0;
}
-static int c_end(map_t*args)
+static int c_end(map_t*args)
{
s_end();
return 0;
}
-static int c_sprite(map_t*args)
+static int c_sprite(map_t*args)
{
char* name = lu(args, "name");
s_sprite(name);
return 0;
}
-static int c_frame(map_t*args)
+static int c_frame(map_t*args)
{
char*framestr = lu(args, "n");
char*cutstr = lu(args, "cut");
-
+
char*name = lu(args, "name");
char*anchor = lu(args, "anchor");
char buf[40];
s_frame(frame, cut, name, !strcmp(anchor, "anchor"));
return 0;
}
-static int c_primitive(map_t*args)
+static int c_primitive(map_t*args)
{
char*name = lu(args, "name");
char*command = lu(args, "commandname");
type = 1;
else if(!strcmp(command, "filled"))
type = 2;
-
+
if(type==0) {
width = parseTwip(lu(args, "width"));
height = parseTwip(lu(args, "height"));
fillstr = 0;
if(width<0 || height<0 || linewidth<0 || r<0)
syntaxerror("values width, height, line, r must be positive");
-
+
if(type == 0) s_box(name, width, height, color, linewidth, fillstr);
else if(type==1) s_circle(name, r, color, linewidth, fillstr);
else if(type==2) s_filled(name, outline, color, linewidth, fillstr);
return 0;
}
-static int c_textshape(map_t*args)
+static int c_textshape(map_t*args)
{
char*name = lu(args, "name");
char*text = lu(args, "text");
return 0;
}
-static int c_swf(map_t*args)
+static int c_swf(map_t*args)
{
char*name = lu(args, "name");
char*filename = lu(args, "filename");
return 0;
}
-static int c_font(map_t*args)
+static int c_font(map_t*args)
{
char*name = lu(args, "name");
char*filename = lu(args, "filename");
return 0;
}
-static int c_sound(map_t*args)
+static int c_sound(map_t*args)
{
char*name = lu(args, "name");
char*filename = lu(args, "filename");
return 0;
}
-static int c_text(map_t*args)
+static int c_text(map_t*args)
{
char*name = lu(args, "name");
char*text = lu(args, "text");
return 0;
}
-static int c_soundtrack(map_t*args)
+static int c_soundtrack(map_t*args)
{
return 0;
}
-static int c_quicktime(map_t*args)
+static int c_quicktime(map_t*args)
{
char*name = lu(args, "name");
char*url = lu(args, "url");
return 0;
}
-static int c_image(map_t*args)
+static int c_image(map_t*args)
{
char*command = lu(args, "commandname");
char*name = lu(args, "name");
return 0;
}
-static int c_outline(map_t*args)
+static int c_outline(map_t*args)
{
char*name = lu(args, "name");
char*format = lu(args, "format");
return 1;
}
} else {
- /* TODO:
+ /* TODO:
<ctrl-x> = 0x200*(x-'a')
esc = = 0x3600
space = = 0x4000;
return 0;
}
-static int c_edittext(map_t*args)
+static int c_edittext(map_t*args)
{
//"name font size width height text="" color=black maxlength=0 variable="" @password=0 @wordwrap=0 @multiline=0 @html=0 @noselect=0 @readonly=0 @autosize=0"},
char*name = lu(args, "name");
FILE*fi = fopen(filename, "rb");
int l;
char*text;
- if(!fi)
+ if(!fi)
syntaxerror("Couldn't find file %s: %s", filename, strerror(errno));
fseek(fi, 0, SEEK_END);
l = ftell(fi);
return text;
}
-static int c_action(map_t*args)
+static int c_action(map_t*args)
{
char* filename = map_lookup(args, "filename");
if(!filename ||!*filename) {
} else {
s_action(readfile(filename));
}
-
+
return 0;
}
-static int c_initaction(map_t*args)
+static int c_initaction(map_t*args)
{
char* character = lu(args, "name");
char* filename = map_lookup(args, "filename");
} else {
s_initaction(character, readfile(filename));
}
-
+
return 0;
}
command_func_t* func;
char*arguments;
} arguments[] =
-{{"flash", c_flash, "bbox=autocrop background=black version=6 fps=50 name= filename= @compress=default"},
+{{"flash", c_flash, "bbox=autocrop background=black version=6 fps=50 name= filename= @compress=default @change-sets-all=no"},
{"frame", c_frame, "n=<plus>1 name= @cut=no @anchor=no"},
// "import" type stuff
{"swf", c_swf, "name filename"},
{"font", c_font, "name filename"},
{"soundtrack", c_soundtrack, "filename"},
{"quicktime", c_quicktime, "url"},
-
+
// generators of primitives
{"point", c_point, "name x=0 y=0"},
{"on_move_in", c_on_move_in, "state=not_pressed"},
{"on_move_out", c_on_move_out, "state=not_pressed"},
{"on_key", c_on_key, "key=any"},
-
+
// control tags
{"play", c_play, "name loop=0 @nomultiple=0"},
{"stop", c_stop, "name= "},
{
char*x;
char*d,*e;
-
+
string_t name[64];
string_t value[64];
int set[64];
d=&x[strlen(x)];
set[pos] = 0;
- if(!e || d<e) {
+ if(!e || d<e) {
// no default
name[pos].str = x;
name[pos].len = d-x;
/* ok, now construct the dictionary from the parameters */
- for(t=0;t<len;t++)
+ for(t=0;t<len;t++)
{
map_put(&result, name[t], value[t]);
}
/* ugly hack- will be removed soon (once documentation and .sc generating
utilities have been changed) */
if(!strcmp(command, "swf") && !stackpos) {
- warning("Please use .flash instead of .swf- this will be mandatory soon");
+ warning("Please use .flash instead of .swf- this will be mandatory soon");
command = "flash";
t = 0;
}
}
if(nr<0)
syntaxerror("command %s not known", command);
-
+
// catch missing .flash directives at the beginning of a file
if(strcmp(command, "flash") && !stackpos)
{
return;
}
+
+/* for now only intended to find what glyphs of each font are to be included in the swf file.
+ * Therefore some knowledge about the command is assumed i.e. it is font/text-related
+ * No syntax checking is done */
+static void analyseArgumentsForCommand(char*command)
+{
+ int t;
+ map_t args;
+ char* fontfile;
+ int nr = -1;
+ msg("<verbose> analyse Command: %s (line %d)", command, line);
+
+ for(t=0;t<sizeof(arguments)/sizeof(arguments[0]);t++)
+ {
+ if(!strcmp(arguments[t].command, command))
+ {
+ args = parseArguments(command, arguments[t].arguments);
+ nr = t;
+ break;
+ }
+ }
+#ifdef DEBUG
+ printf(".%s\n", command);fflush(stdout);
+ map_dump(&args, stdout, "\t");fflush(stdout);
+#endif
+ char* name = lu(&args, "name");
+ if (!strcmp(command, "font"))
+ {
+ if(dictionary_lookup(&fonts, name))
+ syntaxerror("font %s defined twice", name);
+
+ SWFFONT* font;
+ fontfile = lu(&args, "filename");
+ font = swf_LoadFont(fontfile);
+ if(font == 0) {
+ warning("Couldn't open font file \"%s\"", fontfile);
+ font = (SWFFONT*)malloc(sizeof(SWFFONT));
+ memset(font, 0, sizeof(SWFFONT));
+ }
+ swf_FontPrepareForEditText(font);
+ dictionary_put2(&fonts, name, font);
+ }
+ else
+ {
+ SWFFONT* font = dictionary_lookup(&fonts, lu(&args, "font"));
+ if (!font)
+ syntaxerror("font %s is not known in line %d", lu(&args, "font"), line);
+ else
+ if (!strcmp(command, "edittext"))
+ swf_FontUseAll(font);
+ else
+ swf_FontUseUTF8(font, lu(&args, "text"));
+ }
+ map_clear(&args);
+ return;
+}
+
+void skipParameters()
+{
+ do
+ readToken();
+ while (type != COMMAND);
+ pushBack();
+}
+
+void findFontUsage()
+{
+ char* fontRelated = "font;text;textshape;edittext;";
+ while(!noMoreTokens())
+ {
+ readToken();
+ if(type != COMMAND)
+ syntaxerror("command expected");
+ if (strstr(fontRelated, text))
+ analyseArgumentsForCommand(text);
+ else
+ if(strcmp(text, "end"))
+ skipParameters();
+ }
+}
+
+void firstPass()
+{
+ pos = 0;
+ id = 0;
+ dictionary_init(&fonts);
+ cleanUp = &freeFontDictionary;
+ findFontUsage();
+}
+
int main (int argc,char ** argv)
-{
+{
int t;
processargs(argc, argv);
initLog(0,-1,0,0,-1,verbose);
args_callback_usage(argv[0]);
exit(1);
}
-
+
file = generateTokens(filename);
if(!file) {
fprintf(stderr, "parser returned error.\n");
return 1;
}
+ firstPass();
pos=0;
t=0;