2 Compiles swf code (.sc) files into .swf files.
4 Part of the swftools package.
6 Copyright (c) 2001 Matthias Kramm <kramm@quiss.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
29 #include "../config.h"
30 #include "../lib/rfxswf.h"
31 #include "../lib/drawer.h"
32 #include "../lib/log.h"
33 #include "../lib/args.h"
35 #include "../lib/mp3.h"
36 #include "../lib/wav.h"
38 #include "../lib/png.h"
39 #include "swfc-feedback.h"
40 #include "swfc-interpolation.h"
41 #include "swfc-history.h"
44 static char * outputname
= "output.swf";
45 static int verbose
= 2;
46 static int optimize
= 0;
47 static int override_outputname
= 0;
48 static int do_cgi
= 0;
49 static int change_sets_all
= 0;
50 static int do_exports
= 0;
51 static char * mainclass
= "";
53 static struct options_t options
[] = {
62 int args_callback_option(char*name
,char*val
)
64 if(!strcmp(name
, "V")) {
65 printf("swfc - part of %s %s\n", PACKAGE
, VERSION
);
68 else if(!strcmp(name
, "o")) {
70 override_outputname
= 1;
73 else if(!strcmp(name
, "O")) {
77 else if(!strcmp(name
, "C")) {
81 else if(!strcmp(name
, "v")) {
86 printf("Unknown option: -%s\n", name
);
91 int args_callback_longoption(char*name
,char*val
)
93 return args_long2shortoption(options
, name
, val
);
95 void args_callback_usage(char *name
)
98 printf("Usage: %s [-o file.swf] file.sc\n", name
);
100 printf("-h , --help Print short help message and exit\n");
101 printf("-V , --version Print version info and exit\n");
102 printf("-C , --cgi Output to stdout (for use in CGI environments)\n");
103 printf("-v , --verbose Increase verbosity. \n");
104 printf("-o , --output <filename> Set output file to <filename>.\n");
107 int args_callback_command(char*name
,char*val
)
110 fprintf(stderr
, "Only one file allowed. You supplied at least two. (%s and %s)\n",
117 static struct token_t
* file
;
124 static void readToken()
126 type
= file
[pos
].type
;
128 syntaxerror("unexpected end of file");
130 text
= file
[pos
].text
;
131 textlen
= strlen(text
);
132 line
= file
[pos
].line
;
133 column
= file
[pos
].column
;
135 //printf("---> %d(%s) %s\n", type, type_names[type], text);
138 static void pushBack()
141 if(!pos
) syntaxerror("internal error 3");
146 textlen
= strlen(text
);
149 column
= file
[p
].column
;
152 static int noMoreTokens()
154 if(file
[pos
].type
== END
)
172 // ------------------------------ swf routines ----------------------------
176 int type
; //0=swf, 1=sprite, 2=clip, 3=button
183 /* for sprites (1): */
197 static int stackpos
= 0;
199 static dict_t characters
;
200 static dict_t images
;
201 static dict_t textures
;
202 static dict_t outlines
;
203 static dict_t gradients
;
204 static dict_t filters
;
205 static dict_t interpolations
;
206 static char idmap
[65536];
207 static TAG
*tag
= 0; //current tag
209 static int id
; //current character id
210 static int currentframe
; //current frame in current level
211 static SRECT currentrect
; //current bounding box in current level
212 static U16 currentdepth
;
213 static dict_t instances
;
215 static dict_t sounds
;
216 static dict_t fontUsage
;
218 typedef struct _parameters
{
220 float scalex
, scaley
;
226 U8 blendmode
; //not interpolated
228 U16 set
; // bits indicating wether a parameter was set in the c_placement function
229 U16 flags
; // bits to toggle anything you may care to implement as a toggle
233 typedef struct _character
{
239 typedef struct _instance
{
240 character_t
*character
;
242 parameters_t parameters
;
246 typedef struct _outline
{
251 typedef struct _gradient
{
257 typedef struct _filter
{
261 typedef struct _texture
{
265 char* interpolationFunctions
[] = {"linear", \
266 "quadIn", "quadOut", "quadInOut", \
267 "cubicIn", "cubicOut", "cubicInOut", \
268 "quartIn", "quartOut", "quartInOut", \
269 "quintIn", "quintOut", "quintInOut", \
270 "circleIn", "circleOut", "circleInOut", \
271 "exponentialIn", "exponentialOut", "exponentialInOut", \
272 "sineIn", "sineOut", "sineInOut", \
273 "elasticIn", "elasticOut", "elasticInOut", \
274 "backIn", "backOut", "backInOut", \
275 "bounceIn", "bounceOut", "bounceInOut", \
276 "fastBounceIn", "fastBounceOut", "fastBounceInOut"};
278 static void character_init(character_t
*c
)
280 memset(c
, 0, sizeof(character_t
));
283 static character_t
* character_new()
286 c
= (character_t
*)malloc(sizeof(character_t
));
291 static void instance_init(instance_t
*i
)
293 memset(i
, 0, sizeof(instance_t
));
294 i
->history
= history_new();
297 static void instance_free(instance_t
* i
)
299 history_free(i
->history
);
303 static instance_t
* instance_new()
306 c
= (instance_t
*)malloc(sizeof(instance_t
));
311 static void free_instance(void* i
)
313 instance_free((instance_t
*)i
);
316 static void free_font(void* f
)
318 swf_FontFree((SWFFONT
*)f
);
321 static void gradient_free(GRADIENT
* grad
)
328 static void free_gradient(void* grad
)
330 gradient_free((GRADIENT
*) grad
);
333 static void outline_free(outline_t
* o
)
335 free(o
->shape
->data
);
340 static void free_outline(void* o
)
342 outline_free((outline_t
*)o
);
345 static void freeDictionaries()
347 dict_free_all(&instances
, 1, free_instance
);
348 dict_free_all(&characters
, 1, free
);
349 dict_free_all(&images
, 1, free
);
350 dict_free_all(&textures
, 1, free
);
351 dict_free_all(&outlines
, 1, free_outline
);
352 dict_free_all(&gradients
, 1, free_gradient
);
353 dict_free_all(&filters
, 1, free
);
354 dict_free_all(&fonts
, 1, free_font
);
355 dict_free_all(&sounds
, 1, free
);
356 dict_free_all(&interpolations
, 1, free
);
360 static void freeFontDictionary()
362 dict_free_all(&fonts
, 1, free_font
);
365 static void incrementid()
367 while(id
<65536 && idmap
[id
]) {
371 syntaxerror("Out of character ids.");
375 static void s_addcharacter(const char*name
, U16 id
, TAG
*ctag
, SRECT r
)
377 if(dict_lookup(&characters
, name
))
378 syntaxerror("character %s defined twice", name
);
379 character_t
* c
= character_new();
381 c
->definingTag
= ctag
;
384 dict_put(&characters
, name
, c
);
387 tag
= swf_InsertTag(tag
, ST_NAMECHARACTER
);
389 swf_SetString(tag
, name
);
390 tag
= swf_InsertTag(tag
, ST_EXPORTASSETS
);
393 swf_SetString(tag
, name
);
396 static void s_addimage(const char*name
, U16 id
, TAG
*ctag
, SRECT r
)
398 if(dict_lookup(&images
, name
))
399 syntaxerror("image %s defined twice", name
);
401 character_t
* c
= character_new();
402 c
->definingTag
= ctag
;
405 dict_put(&images
, name
, c
);
407 static instance_t
* s_addinstance(const char*name
, character_t
*c
, U16 depth
)
409 if(dict_lookup(&instances
, name
))
410 syntaxerror("object %s defined twice", name
);
411 instance_t
* i
= instance_new();
414 //swf_GetMatrix(0, &i->matrix);
415 dict_put(&instances
, name
, i
);
419 static void parameters_clear(parameters_t
*p
)
422 p
->scalex
= 1.0; p
->scaley
= 1.0;
425 p
->pivot
.x
= 0; p
->pivot
.y
= 0;
430 p
->noinstancename
= 0;
431 swf_GetCXForm(0, &p
->cxform
, 1);
434 static void makeMatrix(MATRIX
*m
, parameters_t
*p
)
443 sx
= p
->scalex
*cos(p
->rotate
/360*2*M_PI
);
444 r1
= -p
->scalex
*sin(p
->rotate
/360*2*M_PI
)+sx
*p
->shear
;
445 r0
= p
->scaley
*sin(p
->rotate
/360*2*M_PI
);
446 sy
= p
->scaley
*cos(p
->rotate
/360*2*M_PI
)+r0
*p
->shear
;
448 m
->sx
= (int)(sx
*65536+0.5);
449 m
->r1
= (int)(r1
*65536+0.5);
450 m
->r0
= (int)(r0
*65536+0.5);
451 m
->sy
= (int)(sy
*65536+0.5);
455 h
= swf_TurnPoint(p
->pin
, m
);
460 static MATRIX
s_instancepos(SRECT rect
, parameters_t
*p
)
465 r
= swf_TurnRect(rect
, &m
);
466 if(currentrect
.xmin
== 0 && currentrect
.ymin
== 0 &&
467 currentrect
.xmax
== 0 && currentrect
.ymax
== 0)
470 swf_ExpandRect2(¤trect
, &r
);
476 interpolation_t
* new;
477 new = (interpolation_t
*)malloc(sizeof(interpolation_t
));
478 new->function
= IF_LINEAR
;
479 dict_put(&interpolations
, "linear", new);
481 new = (interpolation_t
*)malloc(sizeof(interpolation_t
));
482 new->function
= IF_QUAD_IN
;
484 dict_put(&interpolations
, "quadIn", new);
485 new = (interpolation_t
*)malloc(sizeof(interpolation_t
));
486 new->function
= IF_QUAD_OUT
;
488 dict_put(&interpolations
, "quadOut", new);
489 new = (interpolation_t
*)malloc(sizeof(interpolation_t
));
490 new->function
= IF_QUAD_IN_OUT
;
492 dict_put(&interpolations
, "quadInOut", new);
494 new = (interpolation_t
*)malloc(sizeof(interpolation_t
));
495 new->function
= IF_CUBIC_IN
;
497 dict_put(&interpolations
, "cubicIn", new);
498 new = (interpolation_t
*)malloc(sizeof(interpolation_t
));
499 new->function
= IF_CUBIC_OUT
;
501 dict_put(&interpolations
, "cubicOut", new);
502 new = (interpolation_t
*)malloc(sizeof(interpolation_t
));
503 new->function
= IF_CUBIC_IN_OUT
;
505 dict_put(&interpolations
, "cubicInOut", new);
507 new = (interpolation_t
*)malloc(sizeof(interpolation_t
));
508 new->function
= IF_QUART_IN
;
510 dict_put(&interpolations
, "quartIn", new);
511 new = (interpolation_t
*)malloc(sizeof(interpolation_t
));
512 new->function
= IF_QUART_OUT
;
514 dict_put(&interpolations
, "quartOut", new);
515 new = (interpolation_t
*)malloc(sizeof(interpolation_t
));
516 new->function
= IF_QUART_IN_OUT
;
518 dict_put(&interpolations
, "quartInOut", new);
520 new = (interpolation_t
*)malloc(sizeof(interpolation_t
));
521 new->function
= IF_QUINT_IN
;
523 dict_put(&interpolations
, "quintIn", new);
524 new = (interpolation_t
*)malloc(sizeof(interpolation_t
));
525 new->function
= IF_QUINT_OUT
;
527 dict_put(&interpolations
, "quintOut", new);
528 new = (interpolation_t
*)malloc(sizeof(interpolation_t
));
529 new->function
= IF_QUINT_IN_OUT
;
531 dict_put(&interpolations
, "quintInOut", new);
533 new = (interpolation_t
*)malloc(sizeof(interpolation_t
));
534 new->function
= IF_CIRCLE_IN
;
535 dict_put(&interpolations
, "circleIn", new);
536 new = (interpolation_t
*)malloc(sizeof(interpolation_t
));
537 new->function
= IF_CIRCLE_OUT
;
538 dict_put(&interpolations
, "circleOut", new);
539 new = (interpolation_t
*)malloc(sizeof(interpolation_t
));
540 new->function
= IF_CIRCLE_IN_OUT
;
541 dict_put(&interpolations
, "circleInOut", new);
543 new = (interpolation_t
*)malloc(sizeof(interpolation_t
));
544 new->function
= IF_EXPONENTIAL_IN
;
545 dict_put(&interpolations
, "exponentialIn", new);
546 new = (interpolation_t
*)malloc(sizeof(interpolation_t
));
547 new->function
= IF_EXPONENTIAL_OUT
;
548 dict_put(&interpolations
, "exponentialOut", new);
549 new = (interpolation_t
*)malloc(sizeof(interpolation_t
));
550 new->function
= IF_EXPONENTIAL_IN_OUT
;
551 dict_put(&interpolations
, "exponentialInOut", new);
553 new = (interpolation_t
*)malloc(sizeof(interpolation_t
));
554 new->function
= IF_SINE_IN
;
555 dict_put(&interpolations
, "sineIn", new);
556 new = (interpolation_t
*)malloc(sizeof(interpolation_t
));
557 new->function
= IF_SINE_OUT
;
558 dict_put(&interpolations
, "sineOut", new);
559 new = (interpolation_t
*)malloc(sizeof(interpolation_t
));
560 new->function
= IF_SINE_IN_OUT
;
561 dict_put(&interpolations
, "sineInOut", new);
564 memset(&c
, 0, sizeof(RGBA
));
565 gradient_t
* noGradient
= (gradient_t
*)malloc(sizeof(gradient_t
));
566 noGradient
->gradient
.ratios
= (U8
*)malloc(16 * sizeof(U8
));
567 noGradient
->gradient
.rgba
= (RGBA
*)malloc(16 * sizeof(RGBA
));
568 noGradient
->gradient
.num
= 2;
569 noGradient
->gradient
.rgba
[0] = c
;
570 noGradient
->gradient
.ratios
[0] = 0;
571 noGradient
->gradient
.rgba
[1] = c
;
572 noGradient
->gradient
.ratios
[1] = 255;
573 noGradient
->radial
= 0;
574 noGradient
->rotate
= 0;
575 dict_put(&gradients
, "no_gradient", noGradient
);
578 // put a no_filters entry in the filters dictionary to provoce a message when a user tries
579 // to define a no_filters filter. The real filter=no_filters case is handled in parseFilters.
580 FILTER
* dummy
= (FILTER
*)malloc(sizeof(FILTER
));
581 dict_put(&filters
, "no_filters", dummy
);
582 noBlur
= (FILTER_BLUR
*) swf_NewFilter(FILTERTYPE_BLUR
);
584 dict_put(&filters
, "no_blur", noBlur
);
585 noBevel
= (FILTER_BEVEL
*) swf_NewFilter(FILTERTYPE_BEVEL
);
587 noBevel
->composite
= 1;
588 dict_put(&filters
, "no_bevel", noBevel
);
589 noDropshadow
= (FILTER_DROPSHADOW
*) swf_NewFilter(FILTERTYPE_DROPSHADOW
);
590 noDropshadow
->passes
= 1;
591 noDropshadow
->composite
= 1;
592 dict_put(&filters
, "no_dropshadow", noDropshadow
);
593 noGradientGlow
= (FILTER_GRADIENTGLOW
*) swf_NewFilter(FILTERTYPE_GRADIENTGLOW
);
594 noGradientGlow
->passes
= 1;
595 noGradientGlow
->composite
= 1;
596 noGradientGlow
->gradient
= &noGradient
->gradient
;
597 dict_put(&filters
, "no_gradientglow", noGradientGlow
);
600 void s_swf(const char*name
, SRECT r
, int version
, int fps
, int compress
, RGBA background
)
603 syntaxerror(".swf blocks can't be nested");
604 if(stackpos
==sizeof(stack
)/sizeof(stack
[0]))
605 syntaxerror("too many levels of recursion");
607 SWF
*swf
= (SWF
*)malloc(sizeof(SWF
));
609 memset(swf
, 0, sizeof(swf
));
610 swf
->fileVersion
= version
;
612 swf
->frameRate
= fps
;
613 swf
->firstTag
= tag
= swf_InsertTag(0, ST_SETBACKGROUNDCOLOR
);
614 swf
->compressed
= compress
;
615 swf_SetRGB(tag
,&background
);
617 dict_init(&characters
, 16);
618 dict_init(&images
, 16);
619 dict_init(&textures
, 16);
620 dict_init(&outlines
, 16);
621 dict_init(&gradients
, 16);
622 dict_init(&filters
, 16);
623 dict_init(&instances
, 16);
624 dict_init(&sounds
, 16);
625 dict_init(&interpolations
, 16);
627 cleanUp
= &freeDictionaries
;
629 memset(&stack
[stackpos
], 0, sizeof(stack
[0]));
630 stack
[stackpos
].type
= 0;
631 stack
[stackpos
].filename
= strdup(name
);
632 stack
[stackpos
].swf
= swf
;
633 stack
[stackpos
].oldframe
= -1;
637 memset(¤trect
, 0, sizeof(currentrect
));
640 memset(idmap
, 0, sizeof(idmap
));
641 idmap
[0]=1; //main movie has ID 0
646 void s_sprite(const char*name
, SRECT
*scalegrid
, const char*as3name
)
648 tag
= swf_InsertTag(tag
, ST_DEFINESPRITE
);
649 swf_SetU16(tag
, id
); //id
650 swf_SetU16(tag
, 0); //frames
652 memset(&stack
[stackpos
], 0, sizeof(stack
[0]));
653 stack
[stackpos
].type
= 1;
654 stack
[stackpos
].oldframe
= currentframe
;
655 stack
[stackpos
].olddepth
= currentdepth
;
656 stack
[stackpos
].oldrect
= currentrect
;
657 stack
[stackpos
].oldinstances
= instances
;
658 stack
[stackpos
].tag
= tag
;
659 stack
[stackpos
].id
= id
;
660 stack
[stackpos
].name
= strdup(name
);
661 stack
[stackpos
].as3name
= strdup(as3name
);
663 stack
[stackpos
].scalegrid
= *scalegrid
;
665 memset(&stack
[stackpos
].scalegrid
, 0, sizeof(SRECT
));
668 /* FIXME: those four fields should be bundled together */
669 dict_init(&instances
, 16);
672 memset(¤trect
, 0, sizeof(currentrect
));
678 typedef struct _buttonrecord
686 typedef struct _button
690 buttonrecord_t records
[4];
693 static button_t mybutton
;
695 void s_button(const char*name
, const char*as3name
)
697 tag
= swf_InsertTag(tag
, ST_DEFINEBUTTON2
);
698 swf_SetU16(tag
, id
); //id
699 swf_ButtonSetFlags(tag
, 0); //menu=no
701 memset(&mybutton
, 0, sizeof(mybutton
));
703 memset(&stack
[stackpos
], 0, sizeof(stack
[0]));
704 stack
[stackpos
].type
= 3;
705 stack
[stackpos
].tag
= tag
;
706 stack
[stackpos
].id
= id
;
707 stack
[stackpos
].name
= strdup(name
);
708 stack
[stackpos
].as3name
= strdup(as3name
);
709 stack
[stackpos
].oldrect
= currentrect
;
710 memset(¤trect
, 0, sizeof(currentrect
));
715 void s_buttonput(const char*character
, const char*as
, parameters_t p
)
717 character_t
* c
= dict_lookup(&characters
, character
);
720 const char*o
= as
,*s
= as
;
722 if(!stackpos
|| (stack
[stackpos
-1].type
!= 3)) {
723 syntaxerror(".show may only appear in .button");
726 syntaxerror("character %s not known (in .shape %s)", character
, character
);
728 if(mybutton
.endofshapes
) {
729 syntaxerror("a .do may not precede a .show", character
, character
);
732 m
= s_instancepos(c
->size
, &p
);
740 if(*s
==',' || *s
==0) {
741 if(!strncmp(o
,"idle",s
-o
)) {mybutton
.records
[0]=r
;o
=s
+1;}
742 else if(!strncmp(o
,"shape",s
-o
)) {mybutton
.records
[0]=r
;o
=s
+1;}
743 else if(!strncmp(o
,"hover",s
-o
)) {mybutton
.records
[1]=r
;o
=s
+1;}
744 else if(!strncmp(o
,"pressed",s
-o
)) {mybutton
.records
[2]=r
;o
=s
+1;}
745 else if(!strncmp(o
,"area",s
-o
)) {mybutton
.records
[3]=r
;o
=s
+1;}
746 else syntaxerror("unknown \"as\" argument: \"%s\"", strdup_n(o
,s
-o
));
753 static void setbuttonrecords(TAG
*tag
)
755 int flags
[] = {BS_UP
,BS_OVER
,BS_DOWN
,BS_HIT
};
756 if(!mybutton
.endofshapes
) {
759 if(!mybutton
.records
[3].set
) {
760 memcpy(&mybutton
.records
[3], &mybutton
.records
[0], sizeof(buttonrecord_t
));
764 if(mybutton
.records
[t
].set
) {
765 swf_ButtonSetRecord(tag
,flags
[t
],mybutton
.records
[t
].id
,1,&mybutton
.records
[t
].matrix
,&mybutton
.records
[t
].cxform
);
768 swf_SetU8(tag
,0); // end of button records
769 mybutton
.endofshapes
= 1;
773 void s_buttonaction(int flags
, const char*action
)
779 if(!stackpos
|| !stack
[stackpos
-1].tag
||
780 stack
[stackpos
-1].tag
->id
!= ST_DEFINEBUTTON2
) {
781 syntaxerror("Need to be inside a button for .on_* commands");
783 setbuttonrecords(stack
[stackpos
-1].tag
);
785 a
= swf_ActionCompile(text
, stack
[0].swf
->fileVersion
);
787 syntaxerror("Couldn't compile ActionScript");
790 swf_ButtonSetCondition(stack
[stackpos
-1].tag
, flags
);
791 swf_ActionSet(stack
[stackpos
-1].tag
, a
);
792 mybutton
.nr_actions
++;
797 static void setactionend(TAG
*tag
)
799 if(!mybutton
.nr_actions
) {
800 /* no actions means we didn't have an actionoffset,
801 which means we can't signal the end of the
802 buttonaction records, so, *sigh*, we have
803 to insert a dummy record */
804 swf_SetU16(tag
, 0); //offset
805 swf_SetU16(tag
, 0); //condition
806 swf_SetU8(tag
, 0); //action
810 static void s_endButton()
813 setbuttonrecords(stack
[stackpos
-1].tag
);
814 setactionend(stack
[stackpos
-1].tag
);
817 swf_ButtonPostProcess(stack
[stackpos
].tag
, mybutton
.nr_actions
);
821 tag
= stack
[stackpos
].tag
;
822 currentrect
= stack
[stackpos
].oldrect
;
824 s_addcharacter(stack
[stackpos
].name
, stack
[stackpos
].id
, stack
[stackpos
].tag
, r
);
826 if(*stack
[stackpos
].as3name
) {
827 tag
= swf_InsertTag(tag
, ST_SYMBOLCLASS
);
829 swf_SetU16(tag
, stack
[stackpos
].id
);
830 swf_SetString(tag
, stack
[stackpos
].as3name
);
833 free(stack
[stackpos
].name
);
836 TAG
* removeFromTo(TAG
*from
, TAG
*to
)
838 TAG
*save
= from
->prev
;
840 TAG
*next
= from
->next
;
841 if(swf_isAllowedSpriteTag(from
))
842 swf_DeleteTag(0, from
);
849 static int parametersChange(history_t
* history
, int frame
)
853 willChange
= willChange
|| history_change(history
, frame
, "x");
854 willChange
= willChange
|| history_change(history
, frame
, "y");
855 willChange
= willChange
|| history_change(history
, frame
, "scalex");
856 willChange
= willChange
|| history_change(history
, frame
, "scaley");
857 willChange
= willChange
|| history_change(history
, frame
, "cxform.r0");
858 willChange
= willChange
|| history_change(history
, frame
, "cxform.g0");
859 willChange
= willChange
|| history_change(history
, frame
, "cxform.b0");
860 willChange
= willChange
|| history_change(history
, frame
, "cxform.a0");
861 willChange
= willChange
|| history_change(history
, frame
, "cxform.r1");
862 willChange
= willChange
|| history_change(history
, frame
, "cxform.g1");
863 willChange
= willChange
|| history_change(history
, frame
, "cxform.b1");
864 willChange
= willChange
|| history_change(history
, frame
, "cxform.a1");
865 willChange
= willChange
|| history_change(history
, frame
, "rotate");
866 willChange
= willChange
|| history_change(history
, frame
, "shear");
867 willChange
= willChange
|| history_change(history
, frame
, "pivot.x");
868 willChange
= willChange
|| history_change(history
, frame
, "pivot.y");
869 willChange
= willChange
|| history_change(history
, frame
, "pin.x");
870 willChange
= willChange
|| history_change(history
, frame
, "pin.y");
871 willChange
= willChange
|| history_change(history
, frame
, "blendmode");
872 willChange
= willChange
|| history_changeFilter(history
, frame
);
877 static void free_filterlist(FILTERLIST
* f_list
)
880 for (i
= 0; i
< f_list
->num
; i
++)
882 if(f_list
->filter
[i
]->type
== FILTERTYPE_GRADIENTGLOW
)
883 gradient_free(((FILTER_GRADIENTGLOW
*)f_list
->filter
[i
])->gradient
);
884 free(f_list
->filter
[i
]);
889 static void readParameters(history_t
* history
, parameters_t
* p
, int frame
)
891 p
->x
= history_value(history
, frame
, "x");
892 p
->y
= history_value(history
, frame
, "y");
893 p
->scalex
= history_value(history
, frame
, "scalex");
894 p
->scaley
= history_value(history
, frame
, "scaley");
895 p
->cxform
.r0
= history_value(history
, frame
, "cxform.r0");
896 p
->cxform
.g0
= history_value(history
, frame
, "cxform.g0");
897 p
->cxform
.b0
= history_value(history
, frame
, "cxform.b0");
898 p
->cxform
.a0
= history_value(history
, frame
, "cxform.a0");
899 p
->cxform
.r1
= history_value(history
, frame
, "cxform.r1");
900 p
->cxform
.g1
= history_value(history
, frame
, "cxform.g1");
901 p
->cxform
.b1
= history_value(history
, frame
, "cxform.b1");
902 p
->cxform
.a1
= history_value(history
, frame
, "cxform.a1");
903 p
->rotate
= history_rotateValue(history
, frame
);
904 p
->shear
= history_value(history
, frame
, "shear");
905 p
->pivot
.x
= history_value(history
, frame
, "pivot.x");
906 p
->pivot
.y
= history_value(history
, frame
, "pivot.y");
907 p
->pin
.x
= history_value(history
, frame
, "pin.x");
908 p
->pin
.y
= history_value(history
, frame
, "pin.y");
909 p
->blendmode
= history_value(history
, frame
, "blendmode");
910 p
->filters
= history_filterValue(history
, frame
);
913 void setPlacement(TAG
*tag
, U16 id
, U16 depth
, MATRIX m
, const char*name
, parameters_t
*p
, char move
)
917 swf_GetPlaceObject(NULL
, &po
);
921 po
.cxform
= p
->cxform
;
922 po
.name
= (char*)name
;
927 po
.blendmode
= p
->blendmode
;
930 po
.filters
= p
->filters
;
931 swf_SetPlaceObject(tag
, &po
);
934 static void writeInstance(void* _i
)
936 instance_t
*i
= (instance_t
*)_i
;
939 int frame
= i
->history
->firstFrame
;
940 TAG
* tag
= i
->history
->firstTag
;
941 history_processFlags(i
->history
);
942 while (tag
&& frame
< currentframe
)
945 while (tag
&& tag
->id
!= ST_SHOWFRAME
)
947 if(parametersChange(i
->history
, frame
))
949 readParameters(i
->history
, &p
, frame
);
950 m
= s_instancepos(i
->character
->size
, &p
);
952 if(p
.blendmode
|| p
.filters
)
953 tag
= swf_InsertTag(tag
, ST_PLACEOBJECT3
);
955 tag
= swf_InsertTag(tag
, ST_PLACEOBJECT2
);
956 setPlacement(tag
, 0, i
->depth
, m
, 0, &p
, 1);
958 free_filterlist(p
.filters
);
965 void dumpSWF(SWF
*swf
)
967 TAG
* tag
= swf
->firstTag
;
968 printf("vvvvvvvvvvvvvvvvvvvvv\n");
970 printf("%8d %s\n", tag
->len
, swf_TagGetName(tag
));
973 printf("^^^^^^^^^^^^^^^^^^^^^\n");
976 static void s_endSprite()
978 SRECT r
= currentrect
;
983 dict_foreach_value(&instances
, writeInstance
);
985 if(stack
[stackpos
].cut
)
986 tag
= removeFromTo(stack
[stackpos
].cut
, tag
);
988 // the writeInstance loop above may have inserted tags after what used to be the current tag,
989 // so let's make sure 'tag' point to the current tag again.
993 tag
= swf_InsertTag(tag
, ST_SHOWFRAME
);
994 tag
= swf_InsertTag(tag
, ST_END
);
996 tag
= stack
[stackpos
].tag
;
999 if(stack
[stackpos
].scalegrid
.xmin
| stack
[stackpos
].scalegrid
.ymin
|
1000 stack
[stackpos
].scalegrid
.xmax
| stack
[stackpos
].scalegrid
.ymax
)
1002 tag
= swf_InsertTag(tag
, ST_DEFINESCALINGGRID
);
1003 swf_SetU16(tag
, stack
[stackpos
].id
);
1004 swf_SetRect(tag
, &stack
[stackpos
].scalegrid
);
1008 syntaxerror("internal error(7)");
1009 /* TODO: before clearing, prepend "<spritename>." to names and
1010 copy into old instances dict */
1011 dict_free_all(&instances
, 1, free_instance
);
1013 currentframe
= stack
[stackpos
].oldframe
;
1014 currentrect
= stack
[stackpos
].oldrect
;
1015 currentdepth
= stack
[stackpos
].olddepth
;
1016 instances
= stack
[stackpos
].oldinstances
;
1018 s_addcharacter(stack
[stackpos
].name
, stack
[stackpos
].id
, stack
[stackpos
].tag
, r
);
1020 if(*stack
[stackpos
].as3name
) {
1021 tag
= swf_InsertTag(tag
, ST_SYMBOLCLASS
);
1023 swf_SetU16(tag
, stack
[stackpos
].id
);
1024 swf_SetString(tag
, stack
[stackpos
].as3name
);
1028 free(stack
[stackpos
].name
);
1031 static void s_endSWF()
1038 dict_foreach_value(&instances
, writeInstance
);
1040 if(stack
[stackpos
].cut
)
1041 tag
= removeFromTo(stack
[stackpos
].cut
, tag
);
1045 swf
= stack
[stackpos
].swf
;
1046 filename
= stack
[stackpos
].filename
;
1048 // the writeInstance loop above may have inserted tags after what used yo be the current tag,
1049 // so let's make sure 'tag' point to the current tag again.
1053 //if(tag->prev && tag->prev->id != ST_SHOWFRAME)
1054 // tag = swf_InsertTag(tag, ST_SHOWFRAME);
1055 tag
= swf_InsertTag(tag
, ST_SHOWFRAME
);
1058 TAG
*tag
= swf
->firstTag
;
1059 tag
= swf_InsertTag(tag
, ST_DOABC
);
1060 void*code
= as3_getcode();
1061 swf_WriteABC(tag
, code
);
1064 else if(as3_getglobalclass())
1065 mc
= as3_getglobalclass();
1067 tag
= swf_InsertTag(tag
, ST_SYMBOLCLASS
);
1070 swf_SetString(tag
, mc
);
1072 warning("no global public MovieClip subclass");
1077 tag
= swf_InsertTag(tag
, ST_END
);
1079 swf_OptimizeTagOrder(swf
);
1085 if(!(swf
->movieSize
.xmax
-swf
->movieSize
.xmin
) || !(swf
->movieSize
.ymax
-swf
->movieSize
.ymin
)) {
1086 swf
->movieSize
= currentrect
; /* "autocrop" */
1089 if(!(swf
->movieSize
.xmax
-swf
->movieSize
.xmin
) || !(swf
->movieSize
.ymax
-swf
->movieSize
.ymin
)) {
1090 swf
->movieSize
.xmax
+= 20; /* 1 by 1 pixels */
1091 swf
->movieSize
.ymax
+= 20;
1092 warning("Empty bounding box for movie");
1095 if(do_cgi
|| !strcmp(filename
, "-"))
1096 fi
= fileno(stdout
);
1098 fi
= open(filename
, O_WRONLY
|O_CREAT
|O_TRUNC
|O_BINARY
, 0644);
1100 syntaxerror("couldn't create output file %s", filename
);
1103 {if(swf_WriteCGI(swf
)<0) syntaxerror("WriteCGI() failed.\n");}
1105 {if(swf_WriteSWF(fi
, swf
)<0) syntaxerror("WriteSWF() failed.\n");}
1119 if(stack
[stackpos
-1].type
== 0)
1120 syntaxerror("End of file encountered in .flash block");
1121 if(stack
[stackpos
-1].type
== 1)
1122 syntaxerror("End of file encountered in .sprite block");
1123 if(stack
[stackpos
-1].type
== 2)
1124 syntaxerror("End of file encountered in .clip block");
1130 return currentframe
+1;
1133 void s_frame(int nr
, int cut
, const char*name
, char anchor
)
1139 syntaxerror("Illegal frame number");
1140 nr
--; // internally, frame 1 is frame 0
1142 for(t
=currentframe
;t
<nr
;t
++) {
1143 tag
= swf_InsertTag(tag
, ST_SHOWFRAME
);
1144 if(t
==nr
-1 && name
&& *name
) {
1145 tag
= swf_InsertTag(tag
, ST_FRAMELABEL
);
1146 swf_SetString(tag
, name
);
1148 swf_SetU8(tag
, 1); //make this an anchor
1151 if(nr
== 0 && currentframe
== 0 && name
&& *name
) {
1152 tag
= swf_InsertTag(tag
, ST_FRAMELABEL
);
1153 swf_SetString(tag
, name
);
1155 swf_SetU8(tag
, 1); //make this an anchor
1160 syntaxerror("Can't cut, frame empty");
1162 stack
[stackpos
].cut
= tag
;
1168 int parseColor2(const char*str
, RGBA
*color
);
1170 int addFillStyle(SHAPE
*s
, SRECT
*r
, const char*name
)
1174 gradient_t
*gradient
;
1176 if(name
[0] == '#') {
1177 parseColor2(name
, &color
);
1178 return swf_ShapeAddSolidFillStyle(s
, &color
);
1179 } else if((texture
= dict_lookup(&textures
, name
))) {
1180 return swf_ShapeAddFillStyle2(s
, &texture
->fs
);
1181 } else if((image
= dict_lookup(&images
, name
))) {
1183 swf_GetMatrix(0, &m
);
1184 m
.sx
= 65536.0*20.0*(r
->xmax
- r
->xmin
)/image
->size
.xmax
;
1185 m
.sy
= 65536.0*20.0*(r
->ymax
- r
->ymin
)/image
->size
.ymax
;
1188 return swf_ShapeAddBitmapFillStyle(s
, &m
, image
->id
, 0);
1189 } else if((gradient
= dict_lookup(&gradients
, name
))) {
1193 swf_GetMatrix(0, &rot
);
1194 ccos
= cos(-gradient
->rotate
*2*M_PI
/360);
1195 csin
= sin(-gradient
->rotate
*2*M_PI
/360);
1196 rot
.sx
= ccos
*65536;
1197 rot
.r1
= -csin
*65536;
1198 rot
.r0
= csin
*65536;
1199 rot
.sy
= ccos
*65536;
1200 r2
= swf_TurnRect(*r
, &rot
);
1201 swf_GetMatrix(0, &m
);
1202 m
.sx
= (r2
.xmax
- r2
.xmin
)*2*ccos
;
1203 m
.r1
= -(r2
.xmax
- r2
.xmin
)*2*csin
;
1204 m
.r0
= (r2
.ymax
- r2
.ymin
)*2*csin
;
1205 m
.sy
= (r2
.ymax
- r2
.ymin
)*2*ccos
;
1206 m
.tx
= r
->xmin
+ (r
->xmax
- r
->xmin
)/2;
1207 m
.ty
= r
->ymin
+ (r
->ymax
- r
->ymin
)/2;
1208 return swf_ShapeAddGradientFillStyle(s
, &m
, &gradient
->gradient
, gradient
->radial
);
1209 } else if(parseColor2(name
, &color
)) {
1210 return swf_ShapeAddSolidFillStyle(s
, &color
);
1212 syntaxerror("not a color/fillstyle: %s", name
);
1217 RGBA black
={r
:0,g
:0,b
:0,a
:0};
1218 void s_box(const char*name
, int width
, int height
, RGBA color
, int linewidth
, const char*texture
)
1227 tag
= swf_InsertTag(tag
, ST_DEFINESHAPE3
);
1230 linewidth
= linewidth
>=20?linewidth
-20:0;
1231 ls1
= swf_ShapeAddLineStyle(s
,linewidth
,&color
);
1234 fs1
= addFillStyle(s
, &r2
, texture
);
1237 r
.xmin
= r2
.xmin
-linewidth
/2;
1238 r
.ymin
= r2
.ymin
-linewidth
/2;
1239 r
.xmax
= r2
.xmax
+linewidth
/2;
1240 r
.ymax
= r2
.ymax
+linewidth
/2;
1241 swf_SetRect(tag
,&r
);
1242 swf_SetShapeHeader(tag
,s
);
1243 swf_ShapeSetAll(tag
,s
,0,0,ls1
,fs1
,0);
1244 swf_ShapeSetLine(tag
,s
,width
,0);
1245 swf_ShapeSetLine(tag
,s
,0,height
);
1246 swf_ShapeSetLine(tag
,s
,-width
,0);
1247 swf_ShapeSetLine(tag
,s
,0,-height
);
1248 swf_ShapeSetEnd(tag
);
1251 s_addcharacter(name
, id
, tag
, r
);
1255 void s_filled(const char*name
, const char*outlinename
, RGBA color
, int linewidth
, const char*texture
)
1261 outline
= dict_lookup(&outlines
, outlinename
);
1263 syntaxerror("outline %s not defined", outlinename
);
1267 tag
= swf_InsertTag(tag
, ST_DEFINESHAPE3
);
1270 linewidth
= linewidth
>=20?linewidth
-20:0;
1271 ls1
= swf_ShapeAddLineStyle(s
,linewidth
,&color
);
1274 fs1
= addFillStyle(s
, &r2
, texture
);
1277 rect
.xmin
= r2
.xmin
-linewidth
/2;
1278 rect
.ymin
= r2
.ymin
-linewidth
/2;
1279 rect
.xmax
= r2
.xmax
+linewidth
/2;
1280 rect
.ymax
= r2
.ymax
+linewidth
/2;
1282 swf_SetRect(tag
,&rect
);
1283 swf_SetShapeStyles(tag
, s
);
1284 swf_ShapeCountBits(s
,0,0);
1285 swf_RecodeShapeData(outline
->shape
->data
, outline
->shape
->bitlen
, outline
->shape
->bits
.fill
, outline
->shape
->bits
.line
,
1286 &s
->data
, &s
->bitlen
, s
->bits
.fill
, s
->bits
.line
);
1287 swf_SetShapeBits(tag
, s
);
1288 swf_SetBlock(tag
, s
->data
, (s
->bitlen
+7)/8);
1291 s_addcharacter(name
, id
, tag
, rect
);
1295 void s_circle(const char*name
, int r
, RGBA color
, int linewidth
, const char*texture
)
1300 r2
.xmin
= r2
.ymin
= 0;
1304 tag
= swf_InsertTag(tag
, ST_DEFINESHAPE3
);
1307 linewidth
= linewidth
>=20?linewidth
-20:0;
1308 ls1
= swf_ShapeAddLineStyle(s
,linewidth
,&color
);
1311 fs1
= addFillStyle(s
, &r2
, texture
);
1313 rect
.xmin
= r2
.xmin
-linewidth
/2;
1314 rect
.ymin
= r2
.ymin
-linewidth
/2;
1315 rect
.xmax
= r2
.xmax
+linewidth
/2;
1316 rect
.ymax
= r2
.ymax
+linewidth
/2;
1318 swf_SetRect(tag
,&rect
);
1319 swf_SetShapeHeader(tag
,s
);
1320 swf_ShapeSetAll(tag
,s
,0,0,ls1
,fs1
,0);
1321 swf_ShapeSetCircle(tag
, s
, r
,r
,r
,r
);
1322 swf_ShapeSetEnd(tag
);
1325 s_addcharacter(name
, id
, tag
, rect
);
1329 void s_textshape(const char*name
, const char*fontname
, float size
, const char*_text
)
1332 U8
*text
= (U8
*)_text
;
1336 font
= dict_lookup(&fonts
, fontname
);
1338 syntaxerror("font \"%s\" not known!", fontname
);
1340 if(text
[0] >= font
->maxascii
|| font
->ascii2glyph
[text
[0]]<0) {
1341 warning("no character 0x%02x (%c) in font \"%s\"", text
[0], text
[0], fontname
);
1342 s_box(name
, 0, 0, black
, 20, 0);
1345 g
= font
->ascii2glyph
[text
[0]];
1347 outline
= malloc(sizeof(outline_t
));
1348 memset(outline
, 0, sizeof(outline_t
));
1349 outline
->shape
= font
->glyph
[g
].shape
;
1350 outline
->bbox
= font
->layout
->bounds
[g
];
1354 swf_Shape11DrawerInit(&draw
, 0);
1355 swf_DrawText(&draw
, font
, (int)(size
*100), (char*)_text
);
1357 outline
->shape
= swf_ShapeDrawerToShape(&draw
);
1358 outline
->bbox
= swf_ShapeDrawerGetBBox(&draw
);
1359 draw
.dealloc(&draw
);
1362 if(dict_lookup(&outlines
, name
))
1363 syntaxerror("outline %s defined twice", name
);
1364 dict_put(&outlines
, name
, outline
);
1367 void s_text(const char*name
, const char*fontname
, const char*text
, int size
, RGBA color
)
1372 font
= dict_lookup(&fonts
, fontname
);
1374 syntaxerror("font \"%s\" not known!", fontname
);
1376 tag
= swf_InsertTag(tag
, ST_DEFINETEXT2
);
1377 swf_SetU16(tag
, id
);
1378 if(!font
->numchars
) {
1379 s_box(name
, 0, 0, black
, 20, 0);
1382 r
= swf_SetDefineText(tag
, font
, &color
, (char*)text
, size
);
1384 if(stack
[0].swf
->fileVersion
>= 8) {
1385 tag
= swf_InsertTag(tag
, ST_CSMTEXTSETTINGS
);
1386 swf_SetU16(tag
, id
);
1387 swf_SetU8(tag
, /*grid*/(1<<3)|/*flashtype*/0x40);
1388 swf_SetU32(tag
, 0);//thickness
1389 swf_SetU32(tag
, 0);//sharpness
1390 swf_SetU8(tag
, 0);//reserved
1393 s_addcharacter(name
, id
, tag
, r
);
1397 void s_quicktime(const char*name
, const char*url
)
1402 memset(&r
, 0, sizeof(r
));
1404 tag
= swf_InsertTag(tag
, ST_DEFINEMOVIE
);
1405 swf_SetU16(tag
, id
);
1406 swf_SetString(tag
, url
);
1408 s_addcharacter(name
, id
, tag
, r
);
1412 void s_video(const char *name
, int width
, int height
)
1416 memset(&r
, 0, sizeof(r
));
1418 tag
= swf_InsertTag(tag
, ST_DEFINEVIDEOSTREAM
);
1419 swf_SetU16(tag
, id
);
1420 swf_SetU16(tag
, 0); // numframes
1421 swf_SetU16(tag
, width
);
1422 swf_SetU16(tag
, height
);
1423 swf_SetU8(tag
, 0); // videoflags
1424 swf_SetU8(tag
, 0); // codecid
1426 s_addcharacter(name
, id
, tag
, r
);
1430 void s_edittext(const char*name
, const char*fontname
, int size
, int width
, int height
, const char*text
, RGBA
*color
, int maxlength
, const char*variable
, int flags
, int align
)
1433 EditTextLayout layout
;
1436 if(fontname
&& *fontname
) {
1437 flags
|= ET_USEOUTLINES
;
1438 font
= dict_lookup(&fonts
, fontname
);
1440 syntaxerror("font \"%s\" not known!", fontname
);
1442 tag
= swf_InsertTag(tag
, ST_DEFINEEDITTEXT
);
1443 swf_SetU16(tag
, id
);
1444 layout
.align
= align
;
1445 layout
.leftmargin
= 0;
1446 layout
.rightmargin
= 0;
1454 swf_SetEditText(tag
, flags
, r
, (char*)text
, color
, maxlength
, font
?font
->id
:0, size
, &layout
, (char*)variable
);
1456 s_addcharacter(name
, id
, tag
, r
);
1460 /* type: either "jpeg" or "png"
1462 void s_image(const char*name
, const char*type
, const char*filename
, int quality
)
1464 /* an image is actually two folded: 1st bitmap, 2nd character.
1465 Both of them can be used separately */
1467 /* step 1: the bitmap */
1470 unsigned width
, height
;
1471 if(!strcmp(type
,"jpeg")) {
1472 #ifndef HAVE_JPEGLIB
1473 warning("no jpeg support compiled in");
1474 s_box(name
, 0, 0, black
, 20, 0);
1477 tag
= swf_InsertTag(tag
, ST_DEFINEBITSJPEG2
);
1478 swf_SetU16(tag
, imageID
);
1480 if(swf_SetJPEGBits(tag
, (char*)filename
, quality
) < 0) {
1481 syntaxerror("Image \"%s\" not found, or contains errors", filename
);
1484 swf_GetJPEGSize(filename
, &width
, &height
);
1491 s_addimage(name
, id
, tag
, r
);
1494 } else if(!strcmp(type
,"png")) {
1496 swf_SetU16(tag
, imageID
);
1498 png_load(filename
, &width
, &height
, (unsigned char**)&data
);
1501 syntaxerror("Image \"%s\" not found, or contains errors", filename
);
1504 /*tag = swf_AddImage(tag, imageID, data, width, height, quality)*/
1505 tag
= swf_InsertTag(tag
, ST_DEFINEBITSLOSSLESS
);
1506 swf_SetU16(tag
, imageID
);
1507 swf_SetLosslessImage(tag
, data
, width
, height
);
1514 s_addimage(name
, id
, tag
, r
);
1517 warning("image type \"%s\" not supported yet!", type
);
1518 s_box(name
, 0, 0, black
, 20, 0);
1522 /* step 2: the character */
1523 tag
= swf_InsertTag(tag
, ST_DEFINESHAPE
); // todo: should be defineshape2/3 once images can be transparent.(?)
1524 swf_SetU16(tag
, id
);
1525 swf_ShapeSetBitmapRect(tag
, imageID
, width
, height
);
1527 s_addcharacter(name
, id
, tag
, r
);
1531 void s_getBitmapSize(const char*name
, int*width
, int*height
)
1533 character_t
* image
= dict_lookup(&images
, name
);
1534 gradient_t
* gradient
= dict_lookup(&gradients
,name
);
1536 *width
= image
->size
.xmax
;
1537 *height
= image
->size
.ymax
;
1541 /* internal SWF gradient size */
1542 if(gradient
->radial
) {
1551 syntaxerror("No such bitmap/gradient: %s", name
);
1554 void s_texture(const char*name
, const char*object
, int x
, int y
, float scalex
, float scaley
, float rotate
, float shear
)
1556 if(dict_lookup(&textures
, name
))
1557 syntaxerror("texture %s defined twice", name
);
1558 gradient_t
* gradient
= dict_lookup(&gradients
, object
);
1559 character_t
* bitmap
= dict_lookup(&images
, object
);
1560 texture_t
* texture
= (texture_t
*)rfx_calloc(sizeof(texture_t
));
1562 FILLSTYLE
*fs
= &texture
->fs
;
1564 memset(&p
, 0, sizeof(parameters_t
));
1567 fs
->type
= FILL_TILED
;
1568 fs
->id_bitmap
= bitmap
->id
;
1569 } else if(gradient
) {
1570 fs
->type
= gradient
->radial
?FILL_RADIAL
:FILL_LINEAR
;
1571 fs
->gradient
= gradient
->gradient
;
1573 p
.x
= x
;p
.y
= y
;p
.scalex
= scalex
;p
.scaley
= scaley
;p
.rotate
=rotate
;p
.shear
=shear
;
1574 makeMatrix(&fs
->m
, &p
);
1575 if(gradient
&& !gradient
->radial
) {
1582 p2
= swf_TurnPoint(p1
, &m
);
1591 dict_put(&textures
, name
, texture
);
1594 void s_createfont(const char*name
, const char*filename
, const char*glyphs
, char flashtype
)
1596 if(dict_lookup(&fonts
, name
))
1597 syntaxerror("font %s defined twice", name
);
1599 SWFFONT
* font
= swf_LoadFont(filename
, flashtype
);
1601 warning("Couldn't open font file \"%s\"", filename
);
1602 font
= (SWFFONT
*)malloc(sizeof(SWFFONT
));
1603 memset(font
, 0, sizeof(SWFFONT
));
1604 dict_put(&fonts
, name
, font
);
1607 swf_FontPrepareForEditText(font
);
1609 if(!strcmp(glyphs
, "all")) {
1610 swf_FontUseAll(font
);
1611 font
->use
->glyphs_specified
= 1;
1614 swf_FontInitUsage(font
);
1616 swf_FontUseUTF8(font
, (const U8
*)glyphs
, 0xffff);
1617 font
->use
->glyphs_specified
= 1;
1620 dict_put(&fonts
, name
, font
);
1623 void s_font(const char*name
, const char*filename
)
1626 font
= dict_lookup(&fonts
, name
);
1628 swf_FontReduce_swfc(font
);
1630 if(font
->version
>=3 && stack
[0].swf
->fileVersion
< 8) {
1631 warning("flashtype not supported for flash versions 8 and below");
1634 tag
= swf_InsertTag(tag
, font
->version
==3?ST_DEFINEFONT3
:ST_DEFINEFONT2
);
1635 swf_FontSetDefine2(tag
, font
);
1638 tag
= swf_InsertTag(tag
, ST_EXPORTASSETS
);
1640 swf_SetU16(tag
, id
);
1641 swf_SetString(tag
, name
);
1649 typedef struct _sound_t
1655 void s_sound(const char*name
, const char*filename
)
1657 struct WAV wav
, wav2
;
1661 unsigned numsamples
= 1;
1662 unsigned blocksize
= 1152;
1665 if(dict_lookup(&sounds
, name
))
1666 syntaxerror("sound %s defined twice", name
);
1668 if(wav_read(&wav
, filename
))
1671 wav_convert2mono(&wav
, &wav2
, 44100);
1672 samples
= (U16
*)wav2
.data
;
1673 numsamples
= wav2
.size
/2;
1675 #ifdef WORDS_BIGENDIAN
1677 for(t
=0;t
<numsamples
;t
++)
1678 samples
[t
] = (samples
[t
]>>8)&0xff | (samples
[t
]<<8)&0xff00;
1682 if(mp3_read(&mp3
, filename
))
1684 fprintf(stderr
, "\"%s\" seems to work as a MP3 file...\n", filename
);
1690 warning("Couldn't read WAV/MP3 file \"%s\"", filename
);
1695 if(numsamples
%blocksize
!= 0)
1697 // apply padding, so that block is a multiple of blocksize
1698 int numblocks
= (numsamples
+blocksize
-1)/blocksize
;
1701 numsamples2
= numblocks
* blocksize
;
1702 samples2
= malloc(sizeof(U16
)*numsamples2
);
1703 memcpy(samples2
, samples
, numsamples
*sizeof(U16
));
1704 memset(&samples2
[numsamples
], 0, sizeof(U16
)*(numsamples2
- numsamples
));
1705 numsamples
= numsamples2
;
1710 tag
= swf_InsertTag(tag
, ST_DEFINESOUND
);
1711 swf_SetU16(tag
, id
); //id
1714 swf_SetSoundDefineMP3(
1715 tag
, mp3
.data
, mp3
.size
,
1722 swf_SetSoundDefine(tag
, samples
, numsamples
);
1725 tag
= swf_InsertTag(tag
, ST_NAMECHARACTER
);
1726 swf_SetU16(tag
, id
);
1727 swf_SetString(tag
, name
);
1728 tag
= swf_InsertTag(tag
, ST_EXPORTASSETS
);
1730 swf_SetU16(tag
, id
);
1731 swf_SetString(tag
, name
);
1734 sound
= (sound_t
*)malloc(sizeof(sound_t
)); /* mem leak */
1738 dict_put(&sounds
, name
, sound
);
1746 static char* gradient_getToken(const char**p
)
1750 while(**p
&& strchr(" \t\n\r", **p
)) {
1754 while(**p
&& !strchr(" \t\n\r", **p
)) {
1757 result
= malloc((*p
)-start
+1);
1758 memcpy(result
,start
,(*p
)-start
+1);
1759 result
[(*p
)-start
] = 0;
1763 float parsePercent(const char*str
);
1764 RGBA
parseColor(const char*str
);
1766 GRADIENT
parseGradient(const char*str
)
1770 const char* p
= str
;
1771 memset(&gradient
, 0, sizeof(GRADIENT
));
1772 gradient
.ratios
= rfx_calloc(16*sizeof(U8
));
1773 gradient
.rgba
= rfx_calloc(16*sizeof(RGBA
));
1777 char*posstr
,*colorstr
;
1780 posstr
= gradient_getToken(&p
);
1786 pos
= (int)(parsePercent(posstr
)*255.0);
1791 rfx_free(gradient
.ratios
);
1792 rfx_free(gradient
.rgba
);
1794 syntaxerror("Error in shape data: Color expected after %s", posstr
);
1796 colorstr
= gradient_getToken(&p
);
1797 color
= parseColor(colorstr
);
1798 if(gradient
.num
== 16)
1800 warning("gradient record too big- max size is 16, rest ignored");
1803 gradient
.ratios
[gradient
.num
] = pos
;
1804 gradient
.rgba
[gradient
.num
] = color
;
1813 FILTERLIST
* parseFilters(char* list
)
1815 if(!strcmp(list
, "no_filters"))
1818 FILTERLIST
* f_list
= (FILTERLIST
*)malloc(sizeof(FILTERLIST
));
1820 char* f_start
= list
;
1824 f_end
= strchr(f_start
, ',');
1827 f
= dict_lookup(&filters
, f_start
);
1831 syntaxerror("unknown filter %s", f_start
);
1833 if(f_list
->num
== 8)
1835 warning("too many filters in filterlist, no more than 8 please, rest ignored");
1838 f_list
->filter
[f_list
->num
] = f
;
1843 f_start
= f_end
+ 1;
1851 void s_gradient(const char*name
, const char*text
, int radial
, int rotate
)
1853 gradient_t
* gradient
;
1854 gradient
= malloc(sizeof(gradient_t
));
1855 memset(gradient
, 0, sizeof(gradient_t
));
1856 gradient
->gradient
= parseGradient(text
);
1857 gradient
->radial
= radial
;
1858 gradient
->rotate
= rotate
;
1860 dict_put(&gradients
, name
, gradient
);
1863 void s_gradientglow(const char*name
, const char*gradient
, float blurx
, float blury
,
1864 float angle
, float distance
, float strength
, char innershadow
,
1865 char knockout
, char composite
, char ontop
, int passes
)
1867 if(dict_lookup(&filters
, name
))
1868 syntaxerror("filter %s defined twice", name
);
1870 gradient_t
* g
= dict_lookup(&gradients
, gradient
);
1872 syntaxerror("unknown gradient %s", gradient
);
1876 FILTER_GRADIENTGLOW
* filter
= rfx_calloc(sizeof(FILTER_GRADIENTGLOW
));
1877 filter
->type
= FILTERTYPE_GRADIENTGLOW
;
1878 filter
->gradient
= &g
->gradient
;
1879 filter
->blurx
= blurx
;
1880 filter
->blury
= blury
;
1881 filter
->strength
= strength
;
1882 filter
->angle
= angle
;
1883 filter
->distance
= distance
;
1884 filter
->innershadow
= innershadow
;
1885 filter
->knockout
= knockout
;
1886 filter
->composite
= composite
;
1887 filter
->ontop
= ontop
;
1888 filter
->passes
= passes
;
1890 dict_put(&filters
, name
, filter
);
1893 void s_dropshadow(const char*name
, RGBA color
, double blurx
, double blury
, double angle
, double distance
, double strength
, char innershadow
, char knockout
, char composite
, int passes
)
1895 if(dict_lookup(&filters
, name
))
1896 syntaxerror("filter %s defined twice", name
);
1899 FILTER_DROPSHADOW
* filter
= rfx_calloc(sizeof(FILTER_DROPSHADOW
));
1900 filter
->type
= FILTERTYPE_DROPSHADOW
;
1901 filter
->color
= color
;
1902 filter
->blurx
= blurx
;
1903 filter
->blury
= blury
;
1904 filter
->strength
= strength
;
1905 filter
->angle
= angle
;
1906 filter
->distance
= distance
;
1907 filter
->innershadow
= innershadow
;
1908 filter
->knockout
= knockout
;
1909 filter
->composite
= composite
;
1910 filter
->passes
= passes
;
1912 dict_put(&filters
, name
, filter
);
1915 void s_bevel(const char*name
, RGBA shadow
, RGBA highlight
, double blurx
, double blury
, double angle
, double distance
, double strength
, char innershadow
, char knockout
, char composite
, char ontop
, int passes
)
1917 if(dict_lookup(&filters
, name
))
1918 syntaxerror("filter %s defined twice", name
);
1921 FILTER_BEVEL
* filter
= rfx_calloc(sizeof(FILTER_BEVEL
));
1922 filter
->type
= FILTERTYPE_BEVEL
;
1923 filter
->shadow
= shadow
;
1924 filter
->highlight
= highlight
;
1925 filter
->blurx
= blurx
;
1926 filter
->blury
= blury
;
1927 filter
->strength
= strength
;
1928 filter
->angle
= angle
;
1929 filter
->distance
= distance
;
1930 filter
->innershadow
= innershadow
;
1931 filter
->knockout
= knockout
;
1932 filter
->composite
= composite
;
1933 filter
->ontop
= ontop
;
1934 filter
->passes
= passes
;
1936 dict_put(&filters
, name
, filter
);
1939 void s_blur(const char*name
, double blurx
, double blury
, int passes
)
1941 if(dict_lookup(&filters
, name
))
1942 syntaxerror("filter %s defined twice", name
);
1944 FILTER_BLUR
* filter
= rfx_calloc(sizeof(FILTER_BLUR
));
1945 filter
->type
= FILTERTYPE_BLUR
;
1946 filter
->blurx
= blurx
;
1947 filter
->blury
= blury
;
1948 filter
->passes
= passes
;
1950 dict_put(&filters
, name
, filter
);
1953 void s_action(const char*text
)
1955 if(stack
[0].swf
->fileVersion
< 9) {
1957 a
= swf_ActionCompile(text
, stack
[0].swf
->fileVersion
);
1960 syntaxerror("Couldn't compile ActionScript");
1962 tag
= swf_InsertTag(tag
, ST_DOACTION
);
1963 swf_ActionSet(tag
, a
);
1966 as3_parse_bytearray(stack
[0].filename
, text
, strlen(text
));
1971 void s_initaction(const char*character
, const char*text
)
1975 a
= swf_ActionCompile(text
, stack
[0].swf
->fileVersion
);
1979 syntaxerror("Couldn't compile ActionScript");
1982 c
= (character_t
*)dict_lookup(&characters
, character
);
1984 tag
= swf_InsertTag(tag
, ST_DOINITACTION
);
1985 swf_SetU16(tag
, c
->id
);
1986 swf_ActionSet(tag
, a
);
1991 int s_swf3action(const char*name
, const char*action
)
1994 instance_t
* object
= 0;
1996 object
= (instance_t
*)dict_lookup(&instances
, name
);
1997 if(!object
&& name
&& *name
) {
1998 /* we have a name, but couldn't find it. Abort. */
2001 a
= action_SetTarget(0, name
);
2002 if(!strcmp(action
, "nextframe")) a
= action_NextFrame(a
);
2003 else if(!strcmp(action
, "previousframe")) a
= action_PreviousFrame(a
);
2004 else if(!strcmp(action
, "stop")) a
= action_Stop(a
);
2005 else if(!strcmp(action
, "play")) a
= action_Play(a
);
2006 a
= action_SetTarget(a
, "");
2009 tag
= swf_InsertTag(tag
, ST_DOACTION
);
2010 swf_ActionSet(tag
, a
);
2015 void s_outline(const char*name
, const char*format
, const char*source
)
2017 if(dict_lookup(&outlines
, name
))
2018 syntaxerror("outline %s defined twice", name
);
2027 //swf_Shape10DrawerInit(&draw, 0);
2028 swf_Shape11DrawerInit(&draw
, 0);
2030 draw_string(&draw
, source
);
2032 shape
= swf_ShapeDrawerToShape(&draw
);
2033 bounds
= swf_ShapeDrawerGetBBox(&draw
);
2034 draw
.dealloc(&draw
);
2036 outline
= (outline_t
*)rfx_calloc(sizeof(outline_t
));
2037 outline
->shape
= shape
;
2038 outline
->bbox
= bounds
;
2040 dict_put(&outlines
, name
, outline
);
2043 int s_playsound(const char*name
, int loops
, int nomultiple
, int stop
)
2049 sound
= dict_lookup(&sounds
, name
);
2053 tag
= swf_InsertTag(tag
, ST_STARTSOUND
);
2054 swf_SetU16(tag
, sound
->id
); //id
2055 memset(&info
, 0, sizeof(info
));
2058 info
.nomultiple
= nomultiple
;
2059 swf_SetSoundInfo(tag
, &info
);
2063 void s_includeswf(const char*name
, const char*filename
, const char*as3name
)
2071 U16 cutout
[] = {ST_SETBACKGROUNDCOLOR
, ST_PROTECT
, ST_FREEALL
, ST_REFLEX
};
2072 f
= open(filename
,O_RDONLY
|O_BINARY
);
2074 warning("Couldn't open file \"%s\": %s", filename
, strerror(errno
));
2075 s_box(name
, 0, 0, black
, 20, 0);
2078 if(swf_ReadSWF(f
,&swf
)<0) {
2079 warning("Only SWF files supported in .shape for now. File \"%s\" wasn't SWF.", filename
);
2080 s_box(name
, 0, 0, black
, 20, 0);
2085 /* FIXME: The following sets the bounding Box for the character.
2086 It is wrong for two reasons:
2087 a) It may be too small (in case objects in the movie clip at the borders)
2088 b) it may be too big (because the poor movie never got autocropped)
2092 s
= tag
= swf_InsertTag(tag
, ST_DEFINESPRITE
);
2093 swf_SetU16(tag
, id
);
2094 swf_SetU16(tag
, swf
.frameCount
);
2096 swf_Relocate(&swf
, idmap
);
2098 ftag
= swf
.firstTag
;
2102 for(t
=0;t
<sizeof(cutout
)/sizeof(cutout
[0]);t
++)
2103 if(cutout
[t
] == ftag
->id
) {
2107 if(ftag
->id
== ST_DEFINESPRITE
&& !swf_IsFolded(ftag
))
2109 if(ftag
->id
== ST_END
)
2114 if(ftag
->id
!= ST_SETBACKGROUNDCOLOR
) {
2115 /* We simply dump all tags right after the sprite
2116 header, relying on the fact that swf_OptimizeTagOrder() will
2117 sort things out for us later.
2118 We also rely on the fact that the imported SWF is well-formed.
2120 tag
= swf_InsertTag(tag
, ftag
->id
);
2121 swf_SetBlock(tag
, ftag
->data
, ftag
->len
);
2127 syntaxerror("Included file %s contains errors", filename
);
2128 tag
= swf_InsertTag(tag
, ST_END
);
2132 s_addcharacter(name
, id
, tag
, r
);
2135 tag
= swf_InsertTag(tag
, ST_SYMBOLCLASS
);
2137 swf_SetU16(tag
, id
);
2138 swf_SetString(tag
, as3name
);
2142 SRECT
s_getCharBBox(const char*name
)
2144 character_t
* c
= dict_lookup(&characters
, name
);
2145 if(!c
) syntaxerror("character '%s' unknown(2)", name
);
2148 SRECT
s_getInstanceBBox(const char*name
)
2150 instance_t
* i
= dict_lookup(&instances
, name
);
2152 if(!i
) syntaxerror("instance '%s' unknown(4)", name
);
2154 if(!c
) syntaxerror("internal error(5)");
2157 void s_getParameters(const char*name
, parameters_t
* p
)
2159 instance_t
* i
= dict_lookup(&instances
, name
);
2161 syntaxerror("instance '%s' unknown(10)", name
);
2163 readParameters(i
->history
, p
, currentframe
);
2168 void setStartparameters(instance_t
* i
, parameters_t
* p
, TAG
* tag
)
2170 history_begin(i
->history
, "x", currentframe
, tag
, p
->x
);
2171 history_begin(i
->history
, "y", currentframe
, tag
, p
->y
);
2172 history_begin(i
->history
, "scalex", currentframe
, tag
, p
->scalex
);
2173 history_begin(i
->history
, "scaley", currentframe
, tag
, p
->scaley
);
2174 history_begin(i
->history
, "cxform.r0", currentframe
, tag
, p
->cxform
.r0
);
2175 history_begin(i
->history
, "cxform.g0", currentframe
, tag
, p
->cxform
.g0
);
2176 history_begin(i
->history
, "cxform.b0", currentframe
, tag
, p
->cxform
.b0
);
2177 history_begin(i
->history
, "cxform.a0", currentframe
, tag
, p
->cxform
.a0
);
2178 history_begin(i
->history
, "cxform.r1", currentframe
, tag
, p
->cxform
.r1
);
2179 history_begin(i
->history
, "cxform.g1", currentframe
, tag
, p
->cxform
.g1
);
2180 history_begin(i
->history
, "cxform.b1", currentframe
, tag
, p
->cxform
.b1
);
2181 history_begin(i
->history
, "cxform.a1", currentframe
, tag
, p
->cxform
.a1
);
2182 history_begin(i
->history
, "rotate", currentframe
, tag
, p
->rotate
);
2183 history_begin(i
->history
, "shear", currentframe
, tag
, p
->shear
);
2184 history_begin(i
->history
, "pivot.x", currentframe
, tag
, p
->pivot
.x
);
2185 history_begin(i
->history
, "pivot.y", currentframe
, tag
, p
->pivot
.y
);
2186 history_begin(i
->history
, "pin.x", currentframe
, tag
, p
->pin
.x
);
2187 history_begin(i
->history
, "pin.y", currentframe
, tag
, p
->pin
.y
);
2188 history_begin(i
->history
, "blendmode", currentframe
, tag
, p
->blendmode
);
2189 history_beginFilter(i
->history
, currentframe
, tag
, p
->filters
);
2190 history_begin(i
->history
, "flags", currentframe
, tag
, 0);
2193 void s_startclip(const char*instance
, const char*character
, parameters_t p
)
2195 character_t
* c
= dict_lookup(&characters
, character
);
2199 syntaxerror("character %s not known", character
);
2201 i
= s_addinstance(instance
, c
, currentdepth
);
2203 m
= s_instancepos(i
->character
->size
, &p
);
2205 tag
= swf_InsertTag(tag
, ST_PLACEOBJECT2
);
2206 /* TODO: should be ObjectPlaceClip, with clipdepth backpatched */
2207 swf_ObjectPlace(tag
, c
->id
, currentdepth
, &m
, &p
.cxform
, instance
);
2209 stack
[stackpos
].tag
= tag
;
2210 stack
[stackpos
].type
= 2;
2213 setStartparameters(i
, &p
, tag
);
2220 swf_SetTagPos(stack
[stackpos
].tag
, 0);
2221 swf_GetPlaceObject(stack
[stackpos
].tag
, &p
);
2222 p
.clipdepth
= currentdepth
;
2224 swf_ClearTag(stack
[stackpos
].tag
);
2225 swf_SetPlaceObject(stack
[stackpos
].tag
, &p
);
2229 void s_put(const char*instance
, const char*character
, parameters_t p
)
2231 character_t
* c
= dict_lookup(&characters
, character
);
2235 syntaxerror("character %s not known (in .put %s=%s)", character
, instance
, character
);
2237 i
= s_addinstance(instance
, c
, currentdepth
);
2239 m
= s_instancepos(i
->character
->size
, &p
);
2241 if(p
.blendmode
|| p
.filters
)
2243 if(stack
[0].swf
->fileVersion
< 8)
2246 warning("blendmodes only supported for flash version>=8");
2248 warning("filters only supported for flash version>=8");
2250 tag
= swf_InsertTag(tag
, ST_PLACEOBJECT3
);
2253 tag
= swf_InsertTag(tag
, ST_PLACEOBJECT2
);
2254 setPlacement(tag
, c
->id
, currentdepth
, m
, p
.noinstancename
? NULL
: instance
, &p
, 0);
2255 setStartparameters(i
, &p
, tag
);
2259 void recordChanges(history_t
* history
, parameters_t p
, int changeFunction
, interpolation_t
* inter
)
2262 history_remember(history
, "x", currentframe
, changeFunction
, p
.x
, inter
);
2264 history_remember(history
, "y", currentframe
, changeFunction
, p
.y
, inter
);
2265 if(p
.set
& SF_SCALEX
)
2266 history_remember(history
, "scalex", currentframe
, changeFunction
, p
.scalex
, inter
);
2267 if(p
.set
& SF_SCALEY
)
2268 history_remember(history
, "scaley", currentframe
, changeFunction
, p
.scaley
, inter
);
2271 history_remember(history
, "cxform.r0", currentframe
, changeFunction
, p
.cxform
.r0
, inter
);
2272 history_remember(history
, "cxform.r1", currentframe
, changeFunction
, p
.cxform
.r1
, inter
);
2276 history_remember(history
, "cxform.g0", currentframe
, changeFunction
, p
.cxform
.g0
, inter
);
2277 history_remember(history
, "cxform.g1", currentframe
, changeFunction
, p
.cxform
.g1
, inter
);
2281 history_remember(history
, "cxform.b0", currentframe
, changeFunction
, p
.cxform
.b0
, inter
);
2282 history_remember(history
, "cxform.b1", currentframe
, changeFunction
, p
.cxform
.b1
, inter
);
2286 history_remember(history
, "cxform.a0", currentframe
, changeFunction
, p
.cxform
.a0
, inter
);
2287 history_remember(history
, "cxform.a1", currentframe
, changeFunction
, p
.cxform
.a1
, inter
);
2289 if(p
.set
& SF_ROTATE
)
2290 history_remember(history
, "rotate", currentframe
, changeFunction
, p
.rotate
, inter
);
2291 if(p
.set
& SF_SHEAR
)
2292 history_remember(history
, "shear", currentframe
, changeFunction
, p
.shear
, inter
);
2293 if(p
.set
& SF_PIVOT
)
2295 history_remember(history
, "pivot.x", currentframe
, changeFunction
, p
.pivot
.x
, inter
);
2296 history_remember(history
, "pivot.y", currentframe
, changeFunction
, p
.pivot
.y
, inter
);
2300 history_remember(history
, "pin.x", currentframe
, changeFunction
, p
.pin
.x
, inter
);
2301 history_remember(history
, "pin.y", currentframe
, changeFunction
, p
.pin
.y
, inter
);
2303 if(p
.set
& SF_BLEND
)
2304 history_remember(history
, "blendmode", currentframe
, changeFunction
, p
.blendmode
, inter
);
2305 if(p
.set
& SF_FILTER
)
2306 history_rememberFilter(history
, currentframe
, changeFunction
, p
.filters
, inter
);
2309 void s_jump(const char* instance
, parameters_t p
)
2311 instance_t
* i
= dict_lookup(&instances
, instance
);
2313 syntaxerror("instance %s not known", instance
);
2314 recordChanges(i
->history
, p
, CF_JUMP
, 0);
2317 void s_change(const char*instance
, parameters_t p
, interpolation_t
* inter
)
2319 instance_t
* i
= dict_lookup(&instances
, instance
);
2321 syntaxerror("instance %s not known", instance
);
2322 recordChanges(i
->history
, p
, CF_CHANGE
, inter
);
2325 void s_sweep(const char* instance
, parameters_t p
, float radius
, int clockwise
, int short_arc
, interpolation_t
* inter
)
2327 instance_t
* i
= dict_lookup(&instances
, instance
);
2329 syntaxerror("instance %s not known", instance
);
2330 history_rememberSweep(i
->history
, currentframe
, p
.x
, p
.y
, radius
, clockwise
, short_arc
, inter
);
2333 void s_toggle(const char* instance
, U16 flagsOn
, U16 flagsOff
)
2335 instance_t
* i
= dict_lookup(&instances
, instance
);
2337 syntaxerror("instance %s not known", instance
);
2338 U16 flags
= (U16
)history_value(i
->history
, currentframe
, "flags");
2341 history_remember(i
->history
, "flags", currentframe
, CF_JUMP
, flags
, 0);
2344 void s_delinstance(const char*instance
)
2346 instance_t
* i
= dict_lookup(&instances
, instance
);
2348 syntaxerror("instance %s not known", instance
);
2350 tag
= swf_InsertTag(tag
, ST_REMOVEOBJECT2
);
2351 swf_SetU16(tag
, i
->depth
);
2352 dict_del(&instances
, instance
);
2356 void s_schange(const char*instance
, parameters_t p
, interpolation_t
* inter
)
2358 instance_t
* i
= dict_lookup(&instances
, instance
);
2360 syntaxerror("instance %s not known", instance
);
2361 recordChanges(i
->history
, p
, CF_SCHANGE
, inter
);
2367 syntaxerror(".end unexpected");
2368 switch (stack
[stackpos
-1].type
)
2383 syntaxerror("internal error 1");
2387 // ------------------------------------------------------------------------
2389 typedef int command_func_t(map_t
*args
);
2391 SRECT
parseBox(const char*str
)
2393 SRECT r
= {0,0,0,0};
2394 float xmin
, xmax
, ymin
, ymax
;
2395 char*x
= strchr(str
, 'x');
2397 if(!strcmp(str
, "autocrop")) {
2398 r
.xmin
= r
.ymin
= r
.xmax
= r
.ymax
= 0;
2402 d1
= strchr(x
+1, ':');
2404 d2
= strchr(d1
+1, ':');
2406 if(sscanf(str
, "%fx%f", &xmax
, &ymax
) < 2)
2410 else if(d1
&& !d2
) {
2411 if(sscanf(str
, "%fx%f:%f", &xmax
, &ymax
, &xmin
) < 3)
2417 if(sscanf(str
, "%fx%f:%f:%f", &xmax
, &ymax
, &xmin
, &ymin
) < 4)
2422 r
.xmin
= (SCOORD
)(xmin
*20);
2423 r
.ymin
= (SCOORD
)(ymin
*20);
2424 r
.xmax
= (SCOORD
)(xmax
*20);
2425 r
.ymax
= (SCOORD
)(ymax
*20);
2428 syntaxerror("expression %s is not a valid bound Box.\nE.g. 1024x768 or 1024x768:30:30 would have been valid bounding Boxes.", str
);
2431 float parseFloat(const char*str
)
2435 int parseInt(const char*str
)
2440 if(str
[0]=='+' || str
[0]=='-')
2444 if(str
[t
]<'0' || str
[t
]>'9')
2445 syntaxerror("Not an Integer: \"%s\"", str
);
2448 static double parseRawTwip(const char*str
)
2452 if(str
[0]=='+' || str
[0]=='-') {
2457 dot
= strchr(str
, '.');
2461 return sign
*parseInt(str
);
2463 char* old
= strdup(str
);
2464 int l
=strlen(dot
+1);
2467 for(s
=str
;s
<dot
-1;s
++) {
2468 if(*s
<'0' || *s
>'9')
2471 syntaxerror("Not a coordinate: \"%s\"", str
);
2475 if(*s
<'0' || *s
>'9')
2478 syntaxerror("Not a coordinate: \"%s\"", str
);
2481 if(l
>2 || (l
==2 && (dot
[1]!='0' && dot
[1]!='5'))) {
2482 dot
[1] = ((dot
[1]-0x30)/5)*5 + 0x30;
2485 warning("precision loss: %s converted to twip: %s.%s", old
, str
, dot
);
2489 return sign
*(atoi(str
));
2491 return sign
*(atoi(str
)+0.1*atoi(dot
));
2493 return sign
*(atoi(str
)+0.01*atoi(dot
));
2498 static dict_t defines
;
2499 static int defines_initialized
= 0;
2500 static mem_t define_values
;
2502 static double parseNameOrTwip(const char*s
)
2506 if(defines_initialized
) {
2507 l
= PTR_AS_INT(dict_lookup(&defines
, s
));
2510 return *(int*)&define_values
.buffer
[l
-1];
2512 return parseRawTwip(s
);
2516 /* automatically generated by yiyiyacc, http://www.quiss.org/yiyiyacc/ */
2517 static double parseExpression(char*s
)
2520 memset(chr2index
, -1, sizeof(chr2index
));
2527 chr2index
['\0'] = 7;
2535 int left
[10]={11,8,8,8,8,9,9,9,10,10}; //production left side
2536 int plen
[10]={1,3,2,3,1,3,3,1,1,3}; //production size
2537 int table
[18][12] = {
2538 {0, 4, 0, 0, 5, 6, 0, 0, 1, 2, 3, 0},
2539 {7, 8, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0},
2540 {-4, -4, 9, 10, 0, 0, -4, -4, 0, 0, 0, 0},
2541 {-7, -7, -7, -7, 0, 0, -7, -7, 0, 0, 0, 0},
2542 {0, 0, 0, 0, 5, 6, 0, 0, 0, 11, 3, 0},
2543 {-8, -8, -8, -8, 0, 0, -8, -8, 0, 0, 0, 0},
2544 {0, 4, 0, 0, 5, 6, 0, 0, 12, 2, 3, 0},
2545 {0, 0, 0, 0, 5, 6, 0, 0, 0, 13, 3, 0},
2546 {0, 0, 0, 0, 5, 6, 0, 0, 0, 14, 3, 0},
2547 {0, 0, 0, 0, 5, 6, 0, 0, 0, 0, 15, 0},
2548 {0, 0, 0, 0, 5, 6, 0, 0, 0, 0, 16, 0},
2549 {-2, -2, 9, 10, 0, 0, -2, -2, 0, 0, 0, 0},
2550 {7, 8, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0},
2551 {-1, -1, 9, 10, 0, 0, -1, -1, 0, 0, 0, 0},
2552 {-3, -3, 9, 10, 0, 0, -3, -3, 0, 0, 0, 0},
2553 {-5, -5, -5, -5, 0, 0, -5, -5, 0, 0, 0, 0},
2554 {-6, -6, -6, -6, 0, 0, -6, -6, 0, 0, 0, 0},
2555 {-9, -9, -9, -9, 0, 0, -9, -9, 0, 0, 0, 0}};
2563 fprintf(stderr
, "Error in expression\n");
2567 if(chr2index
[*p
]<0) {
2568 action
= table
[stack
[stackpos
-1]][4];
2570 while(chr2index
[*pnext
]<0)
2574 value
= parseNameOrTwip(p
);
2578 action
= table
[stack
[stackpos
-1]][chr2index
[*p
]];
2581 if(action
== accept
) {
2582 return values
[stack
[stackpos
-1]];
2583 } else if(action
>0) { // shift
2585 fprintf(stderr
, "Stack overflow while parsing expression\n");
2588 values
[stackpos
]=value
;
2589 stack
[stackpos
++]=action
;
2591 } else if(action
<0) { // reduce
2592 stackpos
-=plen
[-action
];
2593 stack
[stackpos
] = table
[stack
[stackpos
-1]][left
[-action
]];
2596 values
[stackpos
] = values
[stackpos
+0] + values
[stackpos
+2];
2599 values
[stackpos
] = 0 - values
[stackpos
+1];
2602 values
[stackpos
] = values
[stackpos
+0] - values
[stackpos
+2];
2605 values
[stackpos
] = values
[stackpos
+0] * values
[stackpos
+2];
2608 values
[stackpos
] = values
[stackpos
+0] / values
[stackpos
+2];
2611 values
[stackpos
] = values
[stackpos
+1];
2616 fprintf(stderr
, "Syntax error in expression\n");
2622 int parseTwip(const char*str
)
2624 char*str2
= (char*)str
;
2625 int v
= (int)(parseExpression(str2
)*20);
2629 int parseArc(const char* str
)
2631 if(!strcmp(str
, "short"))
2633 if(!strcmp(str
, "long"))
2635 syntaxerror("invalid value for the arc parameter: %s", str
);
2639 int parseDir(const char* str
)
2641 if(!strcmp(str
, "clockwise"))
2643 if(!strcmp(str
, "counterclockwise"))
2645 syntaxerror("invalid value for the dir parameter: %s", str
);
2649 int isPoint(const char*str
)
2651 if(strchr(str
, '('))
2657 SPOINT
parsePoint(const char*str
)
2661 int l
= strlen(str
);
2662 char*comma
= strchr(str
, ',');
2663 if(str
[0]!='(' || str
[l
-1]!=')' || !comma
|| l
>70)
2664 syntaxerror("\"%s\" is not a valid point of the form (x,y)", str
);
2665 strncpy(tmp
, str
+1, comma
-(str
+1));tmp
[comma
-(str
+1)]=0;
2666 p
.x
= parseTwip(tmp
);
2667 strncpy(tmp
, comma
+1, l
-1-(comma
+1-str
));tmp
[l
-1-(comma
+1-str
)]=0;
2668 p
.y
= parseTwip(tmp
);
2672 int parseColor2(const char*str
, RGBA
*color
)
2674 int l
= strlen(str
);
2678 struct {unsigned char r
,g
,b
;char*name
;} colors
[] =
2679 {{255,250,250,"snow"},{220,220,220,"gainsboro"},{250,240,230,"linen"},{255,228,196,"bisque"},
2680 {255,228,181,"moccasin"},{255,248,220,"cornsilk"},{255,255,240,"ivory"},{255,245,238,"seashell"},
2681 {240,255,240,"honeydew"},{240,255,255,"azure"},{230,230,250,"lavender"},{255,255,255,"white"},
2682 {0,0,0,"black"},{190,190,190,"gray"},{190,190,190,"grey"},{0,0,128,"navy"},{0,0,255,"blue"},
2683 {64,224,208,"turquoise"},{0,255,255,"cyan"},{127,255,212,"aquamarine"}, {0,255,0,"green"},
2684 {127,255,0,"chartreuse"},{240,230,140,"khaki"},{255,255,0,"yellow"},
2685 {255,215,0,"gold"},{218,165,32,"goldenrod"},{160,82,45,"sienna"},{205,133,63,"peru"},
2686 {222,184,135,"burlywood"},{245,245,220,"beige"},{245,222,179,"wheat"},{210,180,140,"tan"},
2687 {210,105,30,"chocolate"},{178,34,34,"firebrick"},{165,42,42,"brown"},{250,128,114,"salmon"},
2688 {255,165,0,"orange"},{255,127,80,"coral"},{255,99,71,"tomato"},{255,0,0,"red"},
2689 {255,192,203,"pink"},{176,48,96,"maroon"},{255,0,255,"magenta"},{238,130,238,"violet"},
2690 {221,160,221,"plum"},{218,112,214,"orchid"},{160,32,240,"purple"},{216,191,216,"thistle"}};
2694 if(str
[0]=='#' && (l
==7 || l
==9)) {
2695 if(l
== 7 && !(sscanf(str
, "#%02x%02x%02x", &r
, &g
, &b
)))
2697 if(l
== 9 && !(sscanf(str
, "#%02x%02x%02x%02x", &r
, &g
, &b
, &a
)))
2699 color
->r
= r
; color
->g
= g
; color
->b
= b
; color
->a
= a
;
2702 int len
=strlen(str
);
2704 if(strchr(str
, '/')) {
2705 len
= strchr(str
, '/')-str
;
2706 sscanf(str
+len
+1,"%02x", &alpha
);
2708 for(t
=0;t
<sizeof(colors
)/sizeof(colors
[0]);t
++)
2709 if(!strncmp(str
, colors
[t
].name
, len
)) {
2714 color
->r
= r
; color
->g
= g
; color
->b
= b
; color
->a
= a
;
2720 RGBA
parseColor(const char*str
)
2723 if(!parseColor2(str
, &c
))
2724 syntaxerror("Expression '%s' is not a color", str
);
2728 typedef struct _muladd
{
2733 MULADD
parseMulAdd(const char*str
)
2736 char* str2
= (char*)malloc(strlen(str
)+5);
2743 if(sscanf(str2
, "%f%f %d", &mul
, &add
, &i
)==2+1) { add
/=256.0; i
=1;}
2744 else if(sscanf(str2
, "%f%%%f %d", &mul
, &add
, &i
)==2+1) { mul
/=100.0; add
/=256.0; i
=2;}
2745 else if(sscanf(str2
, "%f%f%% %d", &mul
, &add
, &i
)==2+1) { add
/=100.0; i
=3;}
2746 else if(sscanf(str2
, "%f%%%f%% %d", &mul
, &add
, &i
)==2+1) { mul
/=100.0; add
/=100.0; i
=4;}
2747 else if(sscanf(str2
, "+%f%% %d", &add
, &i
)==1+1) { mul
=1.0;add
/=100.0; i
=5;}
2748 else if(sscanf(str2
, "+%f %d", &add
, &i
)==1+1) { mul
=1.0;add
/=256.0; i
=6;}
2749 else if(sscanf(str2
, "-%f%% %d", &add
, &i
)==1+1) { mul
=1.0;add
/=-100.0; i
=7;}
2750 else if(sscanf(str2
, "-%f %d", &add
, &i
)==1+1) { mul
=1.0;add
/=-256.0; i
=8;}
2751 else if(sscanf(str2
, "%f%% %d", &mul
, &i
)==1+1) { mul
/=100.0;add
=0; i
=9;}
2752 else if(sscanf(str2
, "%f %d", &mul
, &i
)==1+1) { add
=0; i
=10;}
2754 syntaxerror("'%s' is not a valid color transform expression", str
);
2756 m
.add
= (int)(add
*256);
2757 m
.mul
= (int)(mul
*256);
2762 MULADD
mergeMulAdd(MULADD m1
, MULADD m2
)
2764 int a
= (int)((double)m2
.add
+((double)m1
.add
*(double)m2
.mul
)/256.0);
2765 double m
= ((double)m1
.mul
*(double)m2
.mul
)/256.0;
2767 if(a
<-32768) a
=-32768;
2768 if(a
>32767) a
=32767;
2769 if(m
<-32768) m
=-32768;
2770 if(m
>32767) m
=32767;
2776 float parsePxOrPercent(const char*fontname
, const char*str
)
2778 int l
= strlen(str
);
2779 if(strchr(str
, '%'))
2780 return parsePercent(str
);
2781 if(l
>2 && str
[l
-2]=='p' && str
[l
-1]=='t') {
2782 float p
= atof(str
);
2783 return p
/64.0; /*64 = FT_SUBPIXELS- see ../lib/modules/swffont.c */
2785 syntaxerror("Expression '%s' is neither a point size (?pt) nor a percentage (?%)", str
);
2789 float parsePercent(const char*str
)
2791 int l
= strlen(str
);
2795 return atof(str
)/100.0;
2797 syntaxerror("Expression '%s' is not a percentage", str
);
2800 int isPercent(const char*str
)
2802 return str
[strlen(str
)-1]=='%';
2804 int parseNewSize(const char*str
, int size
)
2807 return parsePercent(str
)*size
;
2809 return (int)(atof(str
)*20);
2812 int isColor(char*str
)
2815 return parseColor2(str
, &c
);
2818 static const char* lu(map_t
* args
, char*name
)
2820 const char* value
= map_lookup(args
, name
);
2822 map_dump(args
, stdout
, "");
2823 syntaxerror("internal error 2: value %s should be set", name
);
2828 static int c_flash(map_t
*args
)
2830 const char* filename
= map_lookup(args
, "filename");
2831 const char* compressstr
= lu(args
, "compress");
2832 const char* change_modestr
= lu(args
, "change-sets-all");
2833 const char* exportstr
= lu(args
, "export");
2834 SRECT bbox
= parseBox(lu(args
, "bbox"));
2835 int version
= parseInt(lu(args
, "version"));
2836 int fps
= (int)(parseFloat(lu(args
, "fps"))*256);
2837 RGBA color
= parseColor(lu(args
, "background"));
2840 if(!filename
|| !*filename
) {
2841 /* for compatibility */
2842 filename
= map_lookup(args
, "name");
2843 if(!filename
|| !*filename
) {
2846 //msg("<warning> line %d: .flash name=... is deprecated, use .flash filename=...", line);
2847 msg("<notice> line %d: .flash name=... is deprecated, use .flash filename=...", line
);
2851 if(!filename
|| override_outputname
)
2852 filename
= outputname
;
2854 if(!strcmp(compressstr
, "default"))
2855 compress
= version
>=6;
2856 else if(!strcmp(compressstr
, "yes") || !strcmp(compressstr
, "compress"))
2858 else if(!strcmp(compressstr
, "no"))
2860 else syntaxerror("value \"%s\" not supported for the compress argument", compressstr
);
2862 if(!strcmp(change_modestr
, "yes"))
2863 change_sets_all
= 1;
2865 if(strcmp(change_modestr
, "no"))
2866 syntaxerror("value \"%s\" not supported for the change-sets-all argument", change_modestr
);
2868 do_exports
=atoi(exportstr
);
2869 mainclass
=strdup(lu(args
, "mainclass"));
2871 s_swf(filename
, bbox
, version
, fps
, compress
, color
);
2874 int isRelative(const char*str
)
2876 return !strncmp(str
, "<plus>", 6) ||
2877 !strncmp(str
, "<minus>", 7);
2879 const char* getOffset(const char*str
)
2881 if(!strncmp(str
, "<plus>", 6))
2883 if(!strncmp(str
, "<minus>", 7))
2885 syntaxerror("internal error (347)");
2888 int getSign(const char*str
)
2890 if(!strncmp(str
, "<plus>", 6))
2892 if(!strncmp(str
, "<minus>", 7))
2894 syntaxerror("internal error (348)");
2898 static dict_t points
;
2899 static mem_t mpoints
;
2900 static int points_initialized
= 0;
2902 static int c_interpolation(map_t
*args
)
2905 const char* name
= lu(args
, "name");
2906 if(dict_lookup(&interpolations
, name
))
2907 syntaxerror("interpolation %s defined twice", name
);
2909 interpolation_t
* inter
= (interpolation_t
*)malloc(sizeof(interpolation_t
));
2910 const char* functionstr
= lu(args
, "function");
2911 inter
->function
= 0;
2912 for (i
= 0; i
< sizeof(interpolationFunctions
) / sizeof(interpolationFunctions
[0]); i
++)
2913 if(!strcmp(functionstr
,interpolationFunctions
[i
]))
2915 inter
->function
= i
+ 1;
2918 if(!inter
->function
)
2919 syntaxerror("unkown interpolation function %s", functionstr
);
2920 inter
->speed
= parseFloat(lu(args
, "speed"));
2921 inter
->amplitude
= parseTwip(lu(args
, "amplitude"));
2922 inter
->growth
= parseFloat(lu(args
, "growth"));
2923 inter
->bounces
= parseInt(lu(args
, "bounces"));
2924 inter
->damping
= parseFloat(lu(args
, "damping"));
2925 inter
->slope
= parseFloat(lu(args
, "slope"));
2927 dict_put(&interpolations
, name
, inter
);
2931 SPOINT
getPoint(SRECT r
, const char*name
)
2934 if(!strcmp(name
, "center")) {
2936 p
.x
= (r
.xmin
+ r
.xmax
)/2;
2937 p
.y
= (r
.ymin
+ r
.ymax
)/2;
2940 if(!strcmp(name
, "bottom-center")) {
2942 p
.x
= (r
.xmin
+ r
.xmax
)/2;
2946 if(!strcmp(name
, "top-center")) {
2948 p
.x
= (r
.xmin
+ r
.xmax
)/2;
2952 if(!strcmp(name
, "top-left")) {
2958 if(!strcmp(name
, "top-right")) {
2964 if(!strcmp(name
, "bottom-right")) {
2970 if(!strcmp(name
, "bottom-left")) {
2976 if(!strcmp(name
, "left-center")) {
2979 p
.y
= (r
.ymin
+ r
.ymax
)/2;
2982 if(!strcmp(name
, "right-center")) {
2985 p
.y
= (r
.ymin
+ r
.ymax
)/2;
2990 if(points_initialized
)
2991 l
= PTR_AS_INT(dict_lookup(&points
, name
));
2993 syntaxerror("Invalid point: \"%s\".", name
);
2995 return *(SPOINT
*)&mpoints
.buffer
[l
-1];
2999 static int texture2(const char*name
, const char*object
, map_t
*args
, int errors
)
3002 const char*xstr
= map_lookup(args
, "x");
3003 const char*ystr
= map_lookup(args
, "y");
3004 const char*widthstr
= map_lookup(args
, "width");
3005 const char*heightstr
= map_lookup(args
, "height");
3006 const char*scalestr
= map_lookup(args
, "scale");
3007 const char*scalexstr
= map_lookup(args
, "scalex");
3008 const char*scaleystr
= map_lookup(args
, "scaley");
3009 const char*rotatestr
= map_lookup(args
, "rotate");
3010 const char* shearstr
= map_lookup(args
, "shear");
3011 const char* radiusstr
= map_lookup(args
, "r");
3013 float scalex
= 1.0, scaley
= 1.0;
3014 float rotate
=0, shear
=0;
3016 if(!*xstr
&& !*ystr
) {
3018 syntaxerror("x and y must be set");
3021 if(*scalestr
&& (*scalexstr
|| *scaleystr
)) {
3022 syntaxerror("scale and scalex/scaley can't both be set");
3025 if((*widthstr
|| *heightstr
) && *radiusstr
) {
3026 syntaxerror("width/height and radius can't both be set");
3029 widthstr
= radiusstr
;
3030 heightstr
= radiusstr
;
3032 if(!*xstr
) xstr
="0";
3033 if(!*ystr
) ystr
="0";
3034 if(!*rotatestr
) rotatestr
="0";
3035 if(!*shearstr
) shearstr
="0";
3038 scalex
= scaley
= parsePercent(scalestr
);
3039 } else if(*scalexstr
|| *scaleystr
) {
3040 if(scalexstr
) scalex
= parsePercent(scalexstr
);
3041 if(scaleystr
) scaley
= parsePercent(scaleystr
);
3042 } else if(*widthstr
|| *heightstr
) {
3045 s_getBitmapSize(object
, &width
, &height
);
3047 scalex
= (float)parseTwip(widthstr
)/(float)width
;
3049 scaley
= (float)parseTwip(heightstr
)/(float)height
;
3051 x
= parseTwip(xstr
);
3052 y
= parseTwip(ystr
);
3053 rotate
= parseFloat(rotatestr
);
3054 shear
= parseFloat(shearstr
);
3056 s_texture(name
, object
, x
,y
,scalex
,scaley
,rotate
, shear
);
3061 static int c_texture(map_t
*args
)
3063 const char*name
= lu(args
, "instance");
3064 const char*object
= lu(args
, "character");
3065 return texture2(name
, object
, args
, 1);
3068 static int c_gradient(map_t
*args
)
3070 const char*name
= lu(args
, "name");
3071 int radial
= strcmp(lu(args
, "radial"), "radial")?0:1;
3072 int rotate
= parseInt(lu(args
, "rotate"));
3076 syntaxerror("colon (:) expected");
3078 if(dict_lookup(&gradients
, name
))
3079 syntaxerror("gradient %s defined twice", name
);
3081 s_gradient(name
, text
, radial
, rotate
);
3083 /* check whether we also have placement information,
3084 which would make this a positioned gradient.
3085 If there is placement information, texture2() will
3086 add a texture, which has priority over the gradient.
3088 texture2(name
, name
, args
, 0);
3092 static const char* checkFiltername(map_t
* args
)
3094 const char* name
= lu(args
, "name");
3095 if(strchr(name
, ','))
3096 syntaxerror("the comma (,) is used to separate filters in filterlists. Please do not use in filternames.");
3100 static int c_blur(map_t
*args
)
3102 const char*name
= checkFiltername(args
);
3103 const char*blurstr
= lu(args
, "blur");
3104 const char*blurxstr
= lu(args
, "blurx");
3105 const char*blurystr
= lu(args
, "blury");
3106 float blurx
=1.0, blury
=1.0;
3108 blurx
= parseFloat(blurstr
);
3109 blury
= parseFloat(blurstr
);
3112 blurx
= parseFloat(blurxstr
);
3114 blury
= parseFloat(blurystr
);
3115 int passes
= parseInt(lu(args
, "passes"));
3116 s_blur(name
, blurx
, blury
, passes
);
3120 static int c_gradientglow(map_t
*args
)
3122 const char*name
= checkFiltername(args
);
3123 const char*gradient
= lu(args
, "gradient");
3124 const char*blurstr
= lu(args
, "blur");
3125 const char*blurxstr
= lu(args
, "blurx");
3126 const char*blurystr
= lu(args
, "blury");
3127 float blurx
=1.0, blury
=1.0;
3129 blurx
= parseFloat(blurstr
);
3130 blury
= parseFloat(blurstr
);
3133 blurx
= parseFloat(blurxstr
);
3135 blury
= parseFloat(blurystr
);
3137 float angle
= parseFloat(lu(args
, "angle")) / 180 * M_PI
;
3138 float distance
= parseFloat(lu(args
, "distance"));
3139 float strength
= parseFloat(lu(args
, "strength"));
3140 char innershadow
= strcmp(lu(args
, "innershadow"),"innershadow")?0:1;
3141 char knockout
= strcmp(lu(args
, "knockout"),"knockout")?0:1;
3142 char composite
= strcmp(lu(args
, "composite"),"composite")?0:1;
3143 char ontop
= strcmp(lu(args
, "ontop"),"ontop")?0:1;
3144 int passes
= parseInt(lu(args
, "passes"));
3146 s_gradientglow(name
, gradient
, blurx
, blury
, angle
, distance
, strength
, innershadow
, knockout
, composite
, ontop
, passes
);
3150 static int c_dropshadow(map_t
*args
)
3152 const char*name
= checkFiltername(args
);
3153 RGBA color
= parseColor(lu(args
, "color"));
3154 const char*blurstr
= lu(args
, "blur");
3155 const char*blurxstr
= lu(args
, "blurx");
3156 const char*blurystr
= lu(args
, "blury");
3157 float blurx
=1.0, blury
=1.0;
3159 blurx
= parseFloat(blurstr
);
3160 blury
= parseFloat(blurstr
);
3163 blurx
= parseFloat(blurxstr
);
3165 blury
= parseFloat(blurystr
);
3167 float angle
= parseFloat(lu(args
, "angle")) / 180 * M_PI
;
3168 float distance
= parseFloat(lu(args
, "distance"));
3169 float strength
= parseFloat(lu(args
, "strength"));
3170 char innershadow
= strcmp(lu(args
, "innershadow"),"innershadow")?0:1;
3171 char knockout
= strcmp(lu(args
, "knockout"),"knockout")?0:1;
3172 char composite
= strcmp(lu(args
, "composite"),"composite")?0:1;
3173 int passes
= parseInt(lu(args
, "passes"));
3175 s_dropshadow(name
, color
, blurx
, blury
, angle
, distance
, strength
, innershadow
, knockout
, composite
, passes
);
3179 static int c_bevel(map_t
*args
)
3181 const char*name
= checkFiltername(args
);
3182 RGBA shadow
= parseColor(lu(args
, "shadow"));
3183 RGBA highlight
= parseColor(lu(args
, "highlight"));
3184 const char*blurstr
= lu(args
, "blur");
3185 const char*blurxstr
= lu(args
, "blurx");
3186 const char*blurystr
= lu(args
, "blury");
3187 float blurx
=1.0, blury
=1.0;
3189 blurx
= parseFloat(blurstr
);
3190 blury
= parseFloat(blurstr
);
3193 blurx
= parseFloat(blurxstr
);
3195 blury
= parseFloat(blurystr
);
3197 float angle
= parseFloat(lu(args
, "angle")) / 180 * M_PI
;
3198 float distance
= parseFloat(lu(args
, "distance"));
3199 float strength
= parseFloat(lu(args
, "strength"));
3200 char innershadow
= strcmp(lu(args
, "innershadow"),"innershadow")?0:1;
3201 char knockout
= strcmp(lu(args
, "knockout"),"knockout")?0:1;
3202 char composite
= strcmp(lu(args
, "composite"),"composite")?0:1;
3203 char ontop
= strcmp(lu(args
, "ontop"),"ontop")?0:1;
3204 int passes
= parseInt(lu(args
, "passes"));
3206 s_bevel(name
, shadow
, highlight
, blurx
, blury
, angle
, distance
, strength
, innershadow
, knockout
, composite
, ontop
, passes
);
3210 static int c_define(map_t
*args
)
3212 const char*name
= lu(args
, "name");
3213 const char*value
= lu(args
, "value");
3215 if(!defines_initialized
) {
3216 dict_init(&defines
, 16);
3217 mem_init(&define_values
);
3218 defines_initialized
= 1;
3220 int val
= parseTwip(value
);
3221 int pos
= mem_put(&define_values
, &val
, sizeof(val
));
3222 dict_put(&defines
, name
, INT_AS_PTR(pos
+ 1));
3225 static int c_point(map_t
*args
)
3227 const char*name
= lu(args
, "name");
3230 if(!points_initialized
) {
3231 dict_init(&points
, 16);
3233 points_initialized
= 1;
3235 p
.x
= parseTwip(lu(args
, "x"));
3236 p
.y
= parseTwip(lu(args
, "y"));
3237 pos
= mem_put(&mpoints
, &p
, sizeof(p
));
3238 dict_put(&points
, name
, INT_AS_PTR(pos
+1));
3241 static int c_play(map_t
*args
)
3243 const char*name
= lu(args
, "name");
3244 const char*loop
= lu(args
, "loop");
3245 const char*nomultiple
= lu(args
, "nomultiple");
3247 if(!strcmp(nomultiple
, "nomultiple"))
3250 nm
= parseInt(nomultiple
);
3252 if(s_playsound(name
, parseInt(loop
), nm
, 0)) {
3254 } else if(s_swf3action(name
, "play")) {
3260 static int c_stop(map_t
*args
)
3262 const char*name
= map_lookup(args
, "name");
3264 if(s_playsound(name
, 0,0,1))
3266 else if(s_swf3action(name
, "stop"))
3268 syntaxerror("I don't know anything about sound/movie \"%s\"", name
);
3272 static int c_nextframe(map_t
*args
)
3274 const char*name
= lu(args
, "name");
3276 if(s_swf3action(name
, "nextframe")) {
3279 syntaxerror("I don't know anything about movie \"%s\"", name
);
3283 static int c_previousframe(map_t
*args
)
3285 const char*name
= lu(args
, "name");
3287 if(s_swf3action(name
, "previousframe")) {
3290 syntaxerror("I don't know anything about movie \"%s\"", name
);
3294 static int c_movement(map_t
*args
, int type
)
3296 const char*instance
= lu(args
, "name");
3298 const char* xstr
="";
3299 const char* ystr
="";
3304 xstr
= lu(args
, "x");
3305 ystr
= lu(args
, "y");
3307 s_getParameters(instance
, &p
);
3312 if(isRelative(xstr
))
3314 if(type
== PT_PUT
|| type
== PT_STARTCLIP
)
3315 syntaxerror("relative x values not allowed for initial put or startclip");
3316 p
.x
+= parseTwip(getOffset(xstr
))*getSign(xstr
);
3320 p
.x
= parseTwip(xstr
);
3326 if(isRelative(ystr
))
3328 if(type
== PT_PUT
|| type
== PT_STARTCLIP
)
3329 syntaxerror("relative y values not allowed for initial put or startclip");
3330 p
.y
+= parseTwip(getOffset(ystr
))*getSign(ystr
);
3334 p
.y
= parseTwip(ystr
);
3347 const char* interstr
= lu(args
, "interpolation");
3348 interpolation_t
* inter
= (interpolation_t
*)dict_lookup(&interpolations
, interstr
);
3350 syntaxerror("unkown interpolation %s", interstr
);
3351 s_change(instance
, p
, inter
);
3356 const char* interstr
= lu(args
, "interpolation");
3357 interpolation_t
* inter
= (interpolation_t
*)dict_lookup(&interpolations
, interstr
);
3359 syntaxerror("unkown interpolation %s", interstr
);
3360 s_schange(instance
, p
, inter
);
3365 const char* rstr
= lu(args
, "r");
3366 int radius
= parseTwip(rstr
);
3368 syntaxerror("sweep not possible: radius must be greater than 0.");
3369 const char* dirstr
= lu(args
, "dir");
3370 int clockwise
= parseDir(dirstr
);
3371 const char* arcstr
= lu(args
, "arc");
3372 int short_arc
= parseArc(arcstr
);
3373 const char* interstr
= lu(args
, "interpolation");
3374 interpolation_t
* inter
= (interpolation_t
*)dict_lookup(&interpolations
, interstr
);
3376 syntaxerror("unkown interpolation %s", interstr
);
3377 s_sweep(instance
, p
, radius
, clockwise
, short_arc
, inter
);
3384 static int c_placement(map_t
*args
, int type
)
3386 const char*instance
= lu(args
, (type
==PT_PUT
||type
==PT_STARTCLIP
)?"instance":"name");
3387 const char*character
= 0;
3389 const char* luminancestr
= lu(args
, "luminance");
3390 const char* scalestr
= lu(args
, "scale");
3391 const char* scalexstr
= lu(args
, "scalex");
3392 const char* scaleystr
= lu(args
, "scaley");
3393 const char* rotatestr
= lu(args
, "rotate");
3394 const char* shearstr
= lu(args
, "shear");
3395 const char* xstr
="", *pivotstr
="";
3396 const char* ystr
="", *anglestr
="";
3397 const char*above
= lu(args
, "above"); /*FIXME*/
3398 const char*below
= lu(args
, "below");
3399 const char* rstr
= lu(args
, "red");
3400 const char* gstr
= lu(args
, "green");
3401 const char* bstr
= lu(args
, "blue");
3402 const char* astr
= lu(args
, "alpha");
3403 const char* pinstr
= lu(args
, "pin");
3404 const char* as
= map_lookup(args
, "as");
3405 const char* blendmode
= lu(args
, "blend");
3406 const char* filterstr
= lu(args
, "filter");
3407 const char* noinstancenamestr
= "";
3418 noinstancenamestr
= lu(args
, "noinstancename");
3421 { // (?) .rotate or .arcchange
3422 pivotstr
= lu(args
, "pivot");
3423 anglestr
= lu(args
, "angle");
3427 xstr
= lu(args
, "x");
3428 ystr
= lu(args
, "y");
3432 luminance
= parseMulAdd(luminancestr
);
3436 luminance
.mul
= 256;
3441 if(scalexstr
[0]||scaleystr
[0])
3442 syntaxerror("scalex/scaley and scale cannot both be set");
3443 scalexstr
= scaleystr
= scalestr
;
3446 if(type
== PT_PUT
|| type
== PT_STARTCLIP
) {
3448 character
= lu(args
, "character");
3449 parameters_clear(&p
);
3450 } else if(type
== PT_BUTTON
) {
3451 character
= lu(args
, "name");
3452 parameters_clear(&p
);
3455 s_getParameters(instance
, &p
);
3458 /* noinstancename */
3459 p
.noinstancename
= !strcmp(noinstancenamestr
, "noinstancename");
3464 if(isRelative(xstr
))
3466 if(type
== PT_PUT
|| type
== PT_STARTCLIP
)
3467 syntaxerror("relative x values not allowed for initial put or startclip");
3468 p
.x
+= parseTwip(getOffset(xstr
))*getSign(xstr
);
3472 p
.x
= parseTwip(xstr
);
3478 if(isRelative(ystr
))
3480 if(type
== PT_PUT
|| type
== PT_STARTCLIP
)
3481 syntaxerror("relative y values not allowed for initial put or startclip");
3482 p
.y
+= parseTwip(getOffset(ystr
))*getSign(ystr
);
3486 p
.y
= parseTwip(ystr
);
3491 /* scale, scalex, scaley */
3493 oldbbox
= s_getCharBBox(character
);
3495 oldbbox
= s_getInstanceBBox(instance
);
3496 oldwidth
= oldbbox
.xmax
- oldbbox
.xmin
;
3497 oldheight
= oldbbox
.ymax
- oldbbox
.ymin
;
3504 p
.scalex
= (float)(parseNewSize(scalexstr
, oldwidth
))/oldwidth
;
3505 set
= set
| SF_SCALEX
;
3513 p
.scaley
= (float)(parseNewSize(scaleystr
, oldheight
))/oldheight
;
3514 set
= set
| SF_SCALEY
;
3520 if(isRelative(rotatestr
))
3521 p
.rotate
+= parseFloat(getOffset(rotatestr
))*getSign(rotatestr
);
3523 p
.rotate
= parseFloat(rotatestr
);
3524 set
= set
| SF_ROTATE
;
3530 if(isRelative(shearstr
))
3531 p
.shear
+= parseFloat(getOffset(shearstr
))*getSign(shearstr
);
3533 p
.shear
= parseFloat(shearstr
);
3534 set
= set
| SF_SHEAR
;
3539 if(isPoint(pivotstr
))
3540 p
.pivot
= parsePoint(pivotstr
);
3542 p
.pivot
= getPoint(oldbbox
, pivotstr
);
3543 set
= set
| SF_PIVOT
;
3549 p
.pin
= parsePoint(pinstr
);
3551 p
.pin
= getPoint(oldbbox
, pinstr
);
3555 /* color transform */
3557 if(rstr
[0] || luminancestr
[0])
3561 r
= parseMulAdd(rstr
);
3564 r
.add
= p
.cxform
.r0
;
3565 r
.mul
= p
.cxform
.r1
;
3567 r
= mergeMulAdd(r
, luminance
);
3568 p
.cxform
.r0
= r
.mul
;
3569 p
.cxform
.r1
= r
.add
;
3570 set
= set
| SF_CX_R
;
3572 if(gstr
[0] || luminancestr
[0])
3576 g
= parseMulAdd(gstr
);
3579 g
.add
= p
.cxform
.g0
;
3580 g
.mul
= p
.cxform
.g1
;
3582 g
= mergeMulAdd(g
, luminance
);
3583 p
.cxform
.g0
= g
.mul
;
3584 p
.cxform
.g1
= g
.add
;
3585 set
= set
| SF_CX_G
;
3587 if(bstr
[0] || luminancestr
[0])
3591 b
= parseMulAdd(bstr
);
3594 b
.add
= p
.cxform
.b0
;
3595 b
.mul
= p
.cxform
.b1
;
3597 b
= mergeMulAdd(b
, luminance
);
3598 p
.cxform
.b0
= b
.mul
;
3599 p
.cxform
.b1
= b
.add
;
3600 set
= set
| SF_CX_B
;
3604 MULADD a
= parseMulAdd(astr
);
3605 p
.cxform
.a0
= a
.mul
;
3606 p
.cxform
.a1
= a
.add
;
3607 set
= set
| SF_CX_A
;
3614 for(t
= 0; blendModeNames
[t
]; t
++)
3616 if(!strcmp(blendModeNames
[t
], blendmode
))
3624 syntaxerror("unknown blend mode: '%s'", blendmode
);
3626 p
.blendmode
= blend
;
3627 set
= set
| SF_BLEND
;
3632 p
.filters
= parseFilters((char*)filterstr
);
3633 set
= set
| SF_FILTER
;
3636 if(type
== PT_CHANGE
&& set
& (SF_X
| SF_Y
))
3637 warning("As of version 0.8.2 using the .change command to modify an \
3638 object's position on the stage is considered deprecated. Future \
3639 versions may consider x and y parameters for the .change command \
3640 to be illegal; please use the .move command.");
3649 s_put(instance
, character
, p
);
3653 const char* interstr
= lu(args
, "interpolation");
3654 interpolation_t
* inter
= (interpolation_t
*)dict_lookup(&interpolations
, interstr
);
3656 syntaxerror("unkown interpolation %s", interstr
);
3657 s_change(instance
, p
, inter
);
3662 const char* interstr
= lu(args
, "interpolation");
3663 interpolation_t
* inter
= (interpolation_t
*)dict_lookup(&interpolations
, interstr
);
3665 syntaxerror("unkown interpolation %s", interstr
);
3666 s_schange(instance
, p
, inter
);
3670 s_jump(instance
, p
);
3673 s_startclip(instance
, character
, p
);
3677 s_buttonput(character
, as
, p
);
3679 s_buttonput(character
, "shape", p
);
3685 static int c_put(map_t
*args
)
3687 c_placement(args
, PT_PUT
);
3690 static int c_change(map_t
*args
)
3692 if(currentframe
== 0)
3693 warning("change commands in frame 1 will be ignored, please use the put command to set object parameters");
3694 c_placement(args
, PT_CHANGE
);
3697 static int c_schange(map_t
*args
)
3699 c_placement(args
, PT_SCHANGE
);
3702 static int c_move(map_t
* args
)
3704 c_movement(args
, PT_MOVE
);
3707 static int c_smove(map_t
* args
)
3709 c_movement(args
, PT_SMOVE
);
3712 static int c_sweep(map_t
* args
)
3714 c_movement(args
, PT_SWEEP
);
3717 static int c_arcchange(map_t
*args
)
3719 c_placement(args
, 0);
3722 static int c_jump(map_t
*args
)
3724 c_placement(args
, PT_JUMP
);
3727 static int c_startclip(map_t
*args
)
3729 c_placement(args
, PT_STARTCLIP
);
3732 static int c_show(map_t
*args
)
3734 c_placement(args
, PT_BUTTON
);
3737 static int c_toggle(map_t
* args
)
3739 const char*instance
= lu(args
, "name");
3740 U16 flagsOn
= 0x0000, flagsOff
= 0xffff;
3741 const char* alignstr
= lu(args
, "fixed_alignment");
3742 if(!strcmp(alignstr
, "on"))
3743 flagsOn
+= IF_FIXED_ALIGNMENT
;
3745 if(!strcmp(alignstr
, "off"))
3746 flagsOff
-= IF_FIXED_ALIGNMENT
;
3748 syntaxerror("values for toggle must be \"on\" or \"off\". %s is not legal.", alignstr
);
3749 s_toggle(instance
, flagsOn
, flagsOff
);
3752 static int c_del(map_t
*args
)
3754 const char*instance
= lu(args
, "name");
3755 s_delinstance(instance
);
3758 static int c_end(map_t
*args
)
3763 static int c_sprite(map_t
*args
)
3765 const char* name
= lu(args
, "name");
3766 const char* scalinggrid
= lu(args
, "scalinggrid");
3767 const char* as3name
= lu(args
, "as3name");
3769 if(scalinggrid
&& *scalinggrid
) {
3770 SRECT r
= parseBox(scalinggrid
);
3771 s_sprite(name
, &r
, as3name
);
3773 s_sprite(name
, 0, as3name
);
3777 static int c_frame(map_t
*args
)
3779 const char*framestr
= lu(args
, "n");
3780 const char*cutstr
= lu(args
, "cut");
3782 const char*name
= lu(args
, "name");
3783 const char*anchor
= lu(args
, "anchor");
3786 if(!strcmp(anchor
, "anchor") && !*name
)
3791 if(strcmp(cutstr
, "no"))
3793 if(isRelative(framestr
)) {
3794 frame
= s_getframe();
3795 if(getSign(framestr
)<0)
3796 syntaxerror("relative frame expressions must be positive");
3797 frame
+= parseInt(getOffset(framestr
));
3800 frame
= parseInt(framestr
);
3801 if(s_getframe() >= frame
3802 && !(frame
==1 && s_getframe()==frame
)) // equality is o.k. for frame 0
3803 syntaxerror("frame expression must be >%d (is:%s)", s_getframe(), framestr
);
3805 s_frame(frame
, cut
, name
, !strcmp(anchor
, "anchor"));
3808 static int c_primitive(map_t
*args
)
3810 const char*name
= lu(args
, "name");
3811 const char*command
= lu(args
, "commandname");
3812 int width
=0, height
=0, r
=0;
3813 int linewidth
= parseTwip(lu(args
, "line"));
3814 const char*colorstr
= lu(args
, "color");
3815 RGBA color
= parseColor(colorstr
);
3816 const char*fillstr
= lu(args
, "fill");
3821 const char* outline
=0;
3823 if(!strcmp(command
, "circle"))
3825 else if(!strcmp(command
, "filled"))
3829 width
= parseTwip(lu(args
, "width"));
3830 height
= parseTwip(lu(args
, "height"));
3831 } else if(type
==1) {
3832 r
= parseTwip(lu(args
, "r"));
3833 } else if(type
==2) {
3834 outline
= lu(args
, "outline");
3837 if(!strcmp(fillstr
, "fill"))
3839 if(!strcmp(fillstr
, "none"))
3841 if(width
<0 || height
<0 || linewidth
<0 || r
<0)
3842 syntaxerror("values width, height, line, r must be positive");
3844 if(type
== 0) s_box(name
, width
, height
, color
, linewidth
, fillstr
);
3845 else if(type
==1) s_circle(name
, r
, color
, linewidth
, fillstr
);
3846 else if(type
==2) s_filled(name
, outline
, color
, linewidth
, fillstr
);
3850 static int c_textshape(map_t
*args
)
3852 const char*name
= lu(args
, "name");
3853 const char*text
= lu(args
, "text");
3854 const char*font
= lu(args
, "font");
3855 float size
= parsePxOrPercent(font
, lu(args
, "size"));
3857 s_textshape(name
, font
, size
, text
);
3861 static int c_swf(map_t
*args
)
3863 const char*name
= lu(args
, "name");
3864 const char*filename
= lu(args
, "filename");
3865 const char*command
= lu(args
, "commandname");
3866 const char*as3name
= lu(args
, "as3name");
3868 if(!strcmp(command
, "shape"))
3869 warning("Please use .swf instead of .shape");
3870 s_includeswf(name
, filename
, as3name
);
3874 static int c_font(map_t
*args
)
3876 const char*name
= lu(args
, "name");
3877 const char*filename
= lu(args
, "filename");
3878 s_font(name
, filename
);
3882 static int c_sound(map_t
*args
)
3884 const char*name
= lu(args
, "name");
3885 const char*filename
= lu(args
, "filename");
3886 s_sound(name
, filename
);
3890 static int c_text(map_t
*args
)
3892 const char*name
= lu(args
, "name");
3893 const char*text
= lu(args
, "text");
3894 const char*font
= lu(args
, "font");
3895 float size
= parsePxOrPercent(font
, lu(args
, "size"));
3896 RGBA color
= parseColor(lu(args
, "color"));
3897 s_text(name
, font
, text
, (int)(size
*100), color
);
3901 static int c_soundtrack(map_t
*args
)
3906 static int c_quicktime(map_t
*args
)
3908 const char*name
= lu(args
, "name");
3909 const char*url
= lu(args
, "url");
3910 s_quicktime(name
, url
);
3914 static int c_video(map_t
*args
)
3916 const char*name
= lu(args
, "name");
3917 int width
= parseInt(lu(args
, "width"));
3918 int height
= parseInt(lu(args
, "height"));
3919 s_video(name
, width
, height
);
3923 static int c_image(map_t
*args
)
3925 const char*command
= lu(args
, "commandname");
3926 const char*name
= lu(args
, "name");
3927 const char*filename
= lu(args
, "filename");
3928 if(!strcmp(command
,"jpeg")) {
3929 int quality
= (int)(parsePercent(lu(args
, "quality"))*100);
3930 s_image(name
, "jpeg", filename
, quality
);
3932 s_image(name
, "png", filename
, 0);
3937 static int c_outline(map_t
*args
)
3939 const char*name
= lu(args
, "name");
3940 const char*format
= lu(args
, "format");
3944 syntaxerror("colon (:) expected");
3946 s_outline(name
, format
, text
);
3950 int fakechar(map_t
*args
)
3952 const char*name
= lu(args
, "name");
3953 s_box(name
, 0, 0, black
, 20, 0);
3957 static int c_egon(map_t
*args
) {return fakechar(args
);}
3958 static int c_button(map_t
*args
) {
3959 const char*name
= lu(args
, "name");
3960 const char*as3name
= lu(args
, "as3name");
3961 s_button(name
, as3name
);
3964 static int current_button_flags
= 0;
3965 static int c_on_press(map_t
*args
)
3967 const char*position
= lu(args
, "position");
3968 const char*action
= "";
3969 if(!strcmp(position
, "inside")) {
3970 current_button_flags
|= BC_OVERUP_OVERDOWN
;
3971 } else if(!strcmp(position
, "outside")) {
3972 //current_button_flags |= BC_IDLE_OUTDOWN;
3973 syntaxerror("IDLE_OVERDOWN not supported by SWF");
3974 } else if(!strcmp(position
, "anywhere")) {
3975 current_button_flags
|= /*BC_IDLE_OUTDOWN|*/BC_OVERUP_OVERDOWN
|BC_IDLE_OVERDOWN
;
3978 if(type
== RAWDATA
) {
3980 s_buttonaction(current_button_flags
, action
);
3981 current_button_flags
= 0;
3987 static int c_on_release(map_t
*args
)
3989 const char*position
= lu(args
, "position");
3990 const char*action
= "";
3991 if(!strcmp(position
, "inside")) {
3992 current_button_flags
|= BC_OVERDOWN_OVERUP
;
3993 } else if(!strcmp(position
, "outside")) {
3994 current_button_flags
|= BC_OUTDOWN_IDLE
;
3995 } else if(!strcmp(position
, "anywhere")) {
3996 current_button_flags
|= BC_OVERDOWN_OVERUP
|BC_OUTDOWN_IDLE
|BC_OVERDOWN_IDLE
;
3999 if(type
== RAWDATA
) {
4001 s_buttonaction(current_button_flags
, action
);
4002 current_button_flags
= 0;
4008 static int c_on_move_in(map_t
*args
)
4010 const char*position
= lu(args
, "state");
4011 const char*action
= "";
4012 if(!strcmp(position
, "pressed")) {
4013 current_button_flags
|= BC_OUTDOWN_OVERDOWN
;
4014 } else if(!strcmp(position
, "not_pressed")) {
4015 current_button_flags
|= BC_IDLE_OVERUP
;
4016 } else if(!strcmp(position
, "any")) {
4017 current_button_flags
|= BC_OUTDOWN_OVERDOWN
|BC_IDLE_OVERUP
|BC_IDLE_OVERDOWN
;
4020 if(type
== RAWDATA
) {
4022 s_buttonaction(current_button_flags
, action
);
4023 current_button_flags
= 0;
4029 static int c_on_move_out(map_t
*args
)
4031 const char*position
= lu(args
, "state");
4032 const char*action
= "";
4033 if(!strcmp(position
, "pressed")) {
4034 current_button_flags
|= BC_OVERDOWN_OUTDOWN
;
4035 } else if(!strcmp(position
, "not_pressed")) {
4036 current_button_flags
|= BC_OVERUP_IDLE
;
4037 } else if(!strcmp(position
, "any")) {
4038 current_button_flags
|= BC_OVERDOWN_OUTDOWN
|BC_OVERUP_IDLE
|BC_OVERDOWN_IDLE
;
4041 if(type
== RAWDATA
) {
4043 s_buttonaction(current_button_flags
, action
);
4044 current_button_flags
= 0;
4050 static int c_on_key(map_t
*args
)
4052 const char*key
= lu(args
, "key");
4053 const char*action
= "";
4054 if(strlen(key
)==1) {
4057 current_button_flags
|= 0x4000 + (key
[0]*0x200);
4059 syntaxerror("invalid character: %c"+key
[0]);
4064 <ctrl-x> = 0x200*(x-'a')
4068 syntaxerror("invalid key: %s",key
);
4071 if(type
== RAWDATA
) {
4073 s_buttonaction(current_button_flags
, action
);
4074 current_button_flags
= 0;
4081 static int c_edittext(map_t
*args
)
4083 //"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"},
4084 const char*name
= lu(args
, "name");
4085 const char*font
= lu(args
, "font");
4086 int size
= (int)(1024*parsePxOrPercent(font
, lu(args
, "size")));
4087 int width
= parseTwip(lu(args
, "width"));
4088 int height
= parseTwip(lu(args
, "height"));
4089 const char*text
= lu(args
, "text");
4090 RGBA color
= parseColor(lu(args
, "color"));
4091 int maxlength
= parseInt(lu(args
, "maxlength"));
4092 const char*variable
= lu(args
, "variable");
4093 const char*passwordstr
= lu(args
, "password");
4094 const char*wordwrapstr
= lu(args
, "wordwrap");
4095 const char*multilinestr
= lu(args
, "multiline");
4096 const char*htmlstr
= lu(args
, "html");
4097 const char*noselectstr
= lu(args
, "noselect");
4098 const char*readonlystr
= lu(args
, "readonly");
4099 const char*borderstr
= lu(args
, "border");
4100 const char*autosizestr
= lu(args
, "autosize");
4101 const char*alignstr
= lu(args
, "align");
4105 if(!strcmp(passwordstr
, "password")) flags
|= ET_PASSWORD
;
4106 if(!strcmp(wordwrapstr
, "wordwrap")) flags
|= ET_WORDWRAP
;
4107 if(!strcmp(multilinestr
, "multiline")) flags
|= ET_MULTILINE
;
4108 if(!strcmp(readonlystr
, "readonly")) flags
|= ET_READONLY
;
4109 if(!strcmp(htmlstr
, "html")) flags
|= ET_HTML
;
4110 if(!strcmp(noselectstr
, "noselect")) flags
|= ET_NOSELECT
;
4111 if(!strcmp(borderstr
, "border")) flags
|= ET_BORDER
;
4112 if(!strcmp(autosizestr
, "autosize")) flags
|= ET_AUTOSIZE
;
4113 if(!strcmp(alignstr
, "left") || !*alignstr
) align
= ET_ALIGN_LEFT
;
4114 else if(!strcmp(alignstr
, "right")) align
= ET_ALIGN_RIGHT
;
4115 else if(!strcmp(alignstr
, "center")) align
= ET_ALIGN_CENTER
;
4116 else if(!strcmp(alignstr
, "justify")) align
= ET_ALIGN_JUSTIFY
;
4117 else syntaxerror("Unknown alignment: %s", alignstr
);
4119 s_edittext(name
, font
, size
, width
, height
, text
, &color
, maxlength
, variable
, flags
, align
);
4123 static int c_morphshape(map_t
*args
) {return fakechar(args
);}
4124 static int c_movie(map_t
*args
) {return fakechar(args
);}
4126 static char* readfile(char*filename
)
4128 FILE*fi
= fopen(filename
, "rb");
4132 syntaxerror("Couldn't find file %s: %s", filename
, strerror(errno
));
4133 fseek(fi
, 0, SEEK_END
);
4135 fseek(fi
, 0, SEEK_SET
);
4136 text
= rfx_alloc(l
+1);
4137 int r
= fread(text
, l
, 1, fi
);
4139 syntaxerror("Couldn't read file %s: %s", filename
, strerror(errno
));
4145 static int c_action(map_t
*args
)
4147 const char* filename
= map_lookup(args
, "filename");
4148 if(!filename
||!*filename
) {
4150 if(type
!= RAWDATA
) {
4151 syntaxerror("colon (:) expected");
4155 s_action(readfile((char*)filename
));
4161 static int c_initaction(map_t
*args
)
4163 const char* character
= lu(args
, "name");
4164 const char* filename
= map_lookup(args
, "filename");
4165 if(!filename
||!*filename
) {
4167 if(type
!= RAWDATA
) {
4168 syntaxerror("colon (:) expected");
4170 s_initaction(character
, text
);
4172 s_initaction(character
, readfile((char*)filename
));
4180 command_func_t
* func
;
4183 {{"flash", c_flash
, "bbox=autocrop background=black version=6 fps=50 name= filename= @compress=default @change-sets-all=no @export=1 @mainclass="},
4184 {"frame", c_frame
, "n=<plus>1 name= @cut=no @anchor=no"},
4185 // "import" type stuff
4186 {"swf", c_swf
, "name filename as3name="},
4187 {"shape", c_swf
, "name filename"},
4188 {"jpeg", c_image
, "name filename quality=80%"},
4189 {"png", c_image
, "name filename"},
4190 {"movie", c_movie
, "name filename"},
4191 {"sound", c_sound
, "name filename"},
4192 {"font", c_font
, "name filename glyphs= @flashtype="},
4193 {"soundtrack", c_soundtrack
, "filename"},
4194 {"quicktime", c_quicktime
, "url"},
4195 {"video", c_video
, "name width= height="},
4197 // generators of primitives
4199 {"define", c_define
, "name value=0"},
4200 {"point", c_point
, "name x=0 y=0"},
4201 {"gradient", c_gradient
, "name @radial=0 rotate=0 scale= scalex= scaley= x= y= width= height= r= shear="}, //extra parameters like .texture
4202 {"interpolation", c_interpolation
, "name function=linear speed=1.3 amplitude=0 bounces=2 growth=1.5 damping=2 slope=0"},
4203 {"outline", c_outline
, "name format=simple"},
4204 {"textshape", c_textshape
, "name font size=100% text"},
4207 {"blur", c_blur
, "name blur= blurx= blury= passes=1"},
4208 {"gradientglow", c_gradientglow
, "name gradient blur= blurx= blury= angle=0.0 distance=0.0 strength=1.0 @innershadow=0 @knockout=0 @composite=0 @ontop=0 passes=1"},
4209 {"dropshadow", c_dropshadow
, "name color blur= blurx= blury= angle=0.0 distance=0.0 strength=1.0 @innershadow=0 @knockout=0 @composite=0 passes=1"},
4210 {"bevel", c_bevel
, "name shadow highlight blur= blurx= blury= angle=0.0 distance=0.0 strength=1.0 @innershadow=0 @knockout=0 @composite=0 @ontop=0 passes=1"},
4212 // character generators
4213 {"box", c_primitive
, "name width height color=white line=1 @fill=none"},
4214 {"circle", c_primitive
, "name r color=white line=1 @fill=none"},
4215 {"filled", c_primitive
, "name outline color=white line=1 @fill=none"},
4217 {"egon", c_egon
, "name vertices color=white line=1 @fill=none"},
4218 {"text", c_text
, "name text font size=100% color=white"},
4219 {"edittext", c_edittext
, "name font= size=100% width height text="" color=white maxlength=0 variable="" @password=0 @wordwrap=0 @multiline=0 @html=0 @noselect=0 @readonly=0 @border=0 @autosize=0 align="},
4220 {"morphshape", c_morphshape
, "name start end"},
4221 {"button", c_button
, "name as3name="},
4222 {"show", c_show
, "name x=0 y=0 red=+0 green=+0 blue=+0 alpha=+0 luminance= scale= scalex= scaley= blend= filter= pivot= pin= shear= rotate= ratio= above= below= as="},
4223 {"on_press", c_on_press
, "position=inside"},
4224 {"on_release", c_on_release
, "position=anywhere"},
4225 {"on_move_in", c_on_move_in
, "state=not_pressed"},
4226 {"on_move_out", c_on_move_out
, "state=not_pressed"},
4227 {"on_key", c_on_key
, "key=any"},
4230 {"play", c_play
, "name loop=0 @nomultiple=0"},
4231 {"stop", c_stop
, "name= "},
4232 {"nextframe", c_nextframe
, "name"},
4233 {"previousframe", c_previousframe
, "name"},
4235 // object placement tags
4236 {"put", c_put
, "<i> x=0 y=0 red=+0 green=+0 blue=+0 alpha=+0 luminance= scale= scalex= scaley= blend= filter= pivot= pin= shear= rotate= ratio= above= below= @noinstancename=0"},
4237 {"startclip", c_startclip
, "<i> x=0 y=0 red=+0 green=+0 blue=+0 alpha=+0 luminance= scale= scalex= scaley= blend= filter= pivot= pin= shear= rotate= ratio= above= below= @noinstancename=0"},
4238 {"move", c_move
, "name x= y= interpolation=linear"},
4239 {"smove", c_smove
, "name x= y= interpolation=linear"},
4240 {"sweep", c_sweep
, "name x= y= r= dir=counterclockwise arc=short interpolation=linear"},
4241 {"change", c_change
, "name x= y= red= green= blue= alpha= luminance= scale= scalex= scaley= blend= filter= pivot= pin= shear= rotate= ratio= above= below= interpolation=linear"},
4242 //{"arcchange", c_arcchange, "name pivot= angle= red= green= blue= alpha= luminance= scale= scalex= scaley= blend= filter= pivot= pin= shear= rotate= ratio= above= below="},
4243 {"schange", c_schange
, "name red= green= blue= alpha= luminance= scale= scalex= scaley= blend= filter= pivot= pin= shear= rotate= ratio= above= below= interpolation=linear"},
4244 {"jump", c_jump
, "name x= y= red= green= blue= alpha= luminance= scale= scalex= scaley= blend= filter= pivot= pin= shear= rotate= ratio= above= below="},
4245 {"del", c_del
, "name"},
4246 // virtual object placement
4247 {"texture", c_texture
, "<i> x=0 y=0 width= height= scale= scalex= scaley= r= shear= rotate="},
4249 {"toggle", c_toggle
, "name fixed_alignment="},
4251 // commands which start a block
4252 //startclip (see above)
4253 {"sprite", c_sprite
, "name scalinggrid= as3name="},
4254 {"action", c_action
, "filename="},
4255 {"initaction", c_initaction
, "name filename="},
4261 static map_t
parseArguments(char*command
, char*pattern
)
4277 string_set(&t1
, "commandname");
4278 string_set(&t2
, command
);
4279 map_put(&result
, t1
, t2
);
4281 if(!pattern
|| !*pattern
)
4288 if(!strncmp("<i> ", x
, 3)) {
4290 if(type
== COMMAND
|| type
== RAWDATA
) {
4292 syntaxerror("character name expected");
4294 name
[pos
].str
= "instance";
4296 value
[pos
].str
= text
;
4297 value
[pos
].len
= strlen(text
);
4301 if(type
== ASSIGNMENT
)
4304 name
[pos
].str
= "character";
4306 value
[pos
].str
= text
;
4307 value
[pos
].len
= strlen(text
);
4315 isboolean
[pos
] = (x
[0] =='@');
4328 name
[pos
].len
= d
-x
;
4333 name
[pos
].len
= e
-x
;
4334 value
[pos
].str
= e
+1;
4335 value
[pos
].len
= d
-e
-1;
4343 /* for(t=0;t<len;t++) {
4344 printf("(%d) %s=%s %s\n", t, strdup_n(name[t], namelen[t]), strdup_n(value[t], valuelen[t]),
4345 isboolean[t]?"(boolean)":"");
4350 if(type
== RAWDATA
|| type
== COMMAND
) {
4355 // first, search for boolean arguments
4356 for(pos
=0;pos
<len
;pos
++)
4358 if(!set
[pos
] && isboolean
[pos
] && !strncmp(name
[pos
].str
, text
, name
[pos
].len
>textlen
?name
[pos
].len
:textlen
)) {
4360 if(type
== ASSIGNMENT
)
4362 value
[pos
].str
= text
;
4363 value
[pos
].len
= strlen(text
);
4364 /*printf("setting boolean parameter %s (to %s)\n",
4365 strdup_n(name[pos], namelen[pos]),
4366 strdup_n(value[pos], valuelen[pos]));*/
4371 // second, search for normal arguments
4373 for(pos
=0;pos
<len
;pos
++)
4375 if((type
== ASSIGNMENT
&& !strncmp(name
[pos
].str
, text
, name
[pos
].len
>textlen
?name
[pos
].len
:textlen
)) ||
4376 (type
!= ASSIGNMENT
&& !set
[pos
])) {
4378 syntaxerror("value %s set twice (old value:%s)", text
, strdup_n(value
[pos
].str
, value
[pos
].len
));
4380 if(type
== ASSIGNMENT
)
4383 value
[pos
].str
= text
;
4384 value
[pos
].len
= strlen(text
);
4386 printf("setting parameter %s (to %s)\n",
4387 strdup_n(name
[pos
].str
, name
[pos
].len
),
4388 strdup_n(value
[pos
].str
, value
[pos
].len
));
4394 syntaxerror("Illegal argument \"%s\" to .%s", text
, command
);
4398 for(t
=0;t
<len
;t
++) {
4399 printf("%s=%s\n", strdup_n(name
[t
].str
, name
[t
].len
), strdup_n(value
[t
].str
, value
[t
].len
));
4402 for(t
=0;t
<len
;t
++) {
4403 if(value
[t
].str
&& value
[t
].str
[0] == '*') {
4404 //relative default- take value from some other parameter
4406 for(s
=0;s
<len
;s
++) {
4407 if(value
[s
].len
== value
[t
].len
-1 &&
4408 !strncmp(&value
[t
].str
[1], value
[s
].str
, value
[s
].len
))
4409 value
[t
].str
= value
[s
].str
;
4412 if(value
[t
].str
== 0) {
4414 syntaxerror("value for parameter %s missing (no default)", strdup_n(name
[t
].str
, name
[t
].len
));
4418 /* ok, now construct the dictionary from the parameters */
4422 map_put(&result
, name
[t
], value
[t
]);
4426 static void parseArgumentsForCommand(char*command
)
4431 msg("<verbose> parse Command: %s (line %d)", command
, line
);
4433 for(t
=0;t
<sizeof(arguments
)/sizeof(arguments
[0]);t
++) {
4434 if(!strcmp(arguments
[t
].command
, command
)) {
4436 /* ugly hack- will be removed soon (once documentation and .sc generating
4437 utilities have been changed) */
4438 if(!strcmp(command
, "swf") && !stackpos
) {
4439 warning("Please use .flash instead of .swf- this will be mandatory soon");
4444 args
= parseArguments(command
, arguments
[t
].arguments
);
4450 syntaxerror("command %s not known", command
);
4453 // catch missing .flash directives at the beginning of a file
4454 if(strcmp(command
, "flash") && !stackpos
)
4456 syntaxerror("No movie defined- use .flash first");
4461 printf(".%s\n", command
);fflush(stdout
);
4462 map_dump(&args
, stdout
, "\t");fflush(stdout
);
4466 (*arguments
[nr
].func
)(&args
);
4468 if(!strcmp(command
, "action") || !strcmp(command
, "initaction") ||
4469 !strcmp(command
, "outline") || !strcmp(command
, "gradient")) {
4471 if(type
!= RAWDATA
) {
4472 syntaxerror("colon (:) expected");
4481 /* for now only intended to find what glyphs of each font are to be included in the swf file.
4482 * Therefore some knowledge about the command is assumed i.e. it is font/text-related
4483 * No syntax checking is done */
4484 static void analyseArgumentsForCommand(char*command
)
4489 U8
* glyphs_to_include
;
4490 msg("<verbose> analyse Command: %s (line %d)", command
, line
);
4492 for(t
=0;t
<sizeof(arguments
)/sizeof(arguments
[0]);t
++)
4494 if(!strcmp(arguments
[t
].command
, command
))
4496 args
= parseArguments(command
, arguments
[t
].arguments
);
4502 printf(".%s\n", command
);fflush(stdout
);
4503 map_dump(&args
, stdout
, "\t");fflush(stdout
);
4505 const char* name
= lu(&args
, "name");
4506 if(!strcmp(command
, "font"))
4508 const char* fontfile
= lu(&args
, "filename");
4509 const char* glyphs
= lu(&args
, "glyphs");
4510 const char* flashtype
= lu(&args
, "flashtype");
4511 s_createfont(name
, fontfile
, glyphs
, flashtype
[0]);
4513 SWFFONT
* font
= dict_lookup(&fonts
, lu(&args
, "font"));
4515 //that's ok... it might be an edittext with a system font
4516 //syntaxerror("font %s is not known in line %d", lu(&args, "font"), line);
4518 if(font
->use
&& !font
->use
->glyphs_specified
) {
4519 if(!strcmp(command
, "edittext"))
4521 swf_FontUseAll(font
);
4522 font
->use
->glyphs_specified
= 1;
4525 swf_FontUseUTF8(font
, (U8
*)lu(&args
, "text"), 0xffff);
4532 void skipParameters()
4536 while (type
!= COMMAND
);
4540 void findFontUsage()
4542 char* fontRelated
= "font;text;textshape;edittext;";
4543 while(!noMoreTokens())
4547 syntaxerror("command expected");
4548 if(strstr(fontRelated
, text
))
4549 analyseArgumentsForCommand(text
);
4551 if(strcmp(text
, "end"))
4560 dict_init(&fonts
, 16);
4561 cleanUp
= &freeFontDictionary
;
4565 int main (int argc
,char ** argv
)
4568 processargs(argc
, argv
);
4569 initLog(0,-1,0,0,-1,verbose
);
4572 args_callback_usage(argv
[0]);
4576 file
= generateTokens(filename
);
4578 fprintf(stderr
, "parser returned error.\n");
4585 while(!noMoreTokens()) {
4588 syntaxerror("command expected");
4589 parseArgumentsForCommand(text
);