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
= lu(args
, "noinstancename");
3418 { // (?) .rotate or .arcchange
3419 pivotstr
= lu(args
, "pivot");
3420 anglestr
= lu(args
, "angle");
3424 xstr
= lu(args
, "x");
3425 ystr
= lu(args
, "y");
3429 luminance
= parseMulAdd(luminancestr
);
3433 luminance
.mul
= 256;
3438 if(scalexstr
[0]||scaleystr
[0])
3439 syntaxerror("scalex/scaley and scale cannot both be set");
3440 scalexstr
= scaleystr
= scalestr
;
3443 if(type
== PT_PUT
|| type
== PT_STARTCLIP
) {
3445 character
= lu(args
, "character");
3446 parameters_clear(&p
);
3447 } else if(type
== PT_BUTTON
) {
3448 character
= lu(args
, "name");
3449 parameters_clear(&p
);
3452 s_getParameters(instance
, &p
);
3455 /* noinstancename */
3456 p
.noinstancename
= !strcmp(noinstancenamestr
, "noinstancename");
3461 if(isRelative(xstr
))
3463 if(type
== PT_PUT
|| type
== PT_STARTCLIP
)
3464 syntaxerror("relative x values not allowed for initial put or startclip");
3465 p
.x
+= parseTwip(getOffset(xstr
))*getSign(xstr
);
3469 p
.x
= parseTwip(xstr
);
3475 if(isRelative(ystr
))
3477 if(type
== PT_PUT
|| type
== PT_STARTCLIP
)
3478 syntaxerror("relative y values not allowed for initial put or startclip");
3479 p
.y
+= parseTwip(getOffset(ystr
))*getSign(ystr
);
3483 p
.y
= parseTwip(ystr
);
3488 /* scale, scalex, scaley */
3490 oldbbox
= s_getCharBBox(character
);
3492 oldbbox
= s_getInstanceBBox(instance
);
3493 oldwidth
= oldbbox
.xmax
- oldbbox
.xmin
;
3494 oldheight
= oldbbox
.ymax
- oldbbox
.ymin
;
3501 p
.scalex
= (float)(parseNewSize(scalexstr
, oldwidth
))/oldwidth
;
3502 set
= set
| SF_SCALEX
;
3510 p
.scaley
= (float)(parseNewSize(scaleystr
, oldheight
))/oldheight
;
3511 set
= set
| SF_SCALEY
;
3517 if(isRelative(rotatestr
))
3518 p
.rotate
+= parseFloat(getOffset(rotatestr
))*getSign(rotatestr
);
3520 p
.rotate
= parseFloat(rotatestr
);
3521 set
= set
| SF_ROTATE
;
3527 if(isRelative(shearstr
))
3528 p
.shear
+= parseFloat(getOffset(shearstr
))*getSign(shearstr
);
3530 p
.shear
= parseFloat(shearstr
);
3531 set
= set
| SF_SHEAR
;
3536 if(isPoint(pivotstr
))
3537 p
.pivot
= parsePoint(pivotstr
);
3539 p
.pivot
= getPoint(oldbbox
, pivotstr
);
3540 set
= set
| SF_PIVOT
;
3546 p
.pin
= parsePoint(pinstr
);
3548 p
.pin
= getPoint(oldbbox
, pinstr
);
3552 /* color transform */
3554 if(rstr
[0] || luminancestr
[0])
3558 r
= parseMulAdd(rstr
);
3561 r
.add
= p
.cxform
.r0
;
3562 r
.mul
= p
.cxform
.r1
;
3564 r
= mergeMulAdd(r
, luminance
);
3565 p
.cxform
.r0
= r
.mul
;
3566 p
.cxform
.r1
= r
.add
;
3567 set
= set
| SF_CX_R
;
3569 if(gstr
[0] || luminancestr
[0])
3573 g
= parseMulAdd(gstr
);
3576 g
.add
= p
.cxform
.g0
;
3577 g
.mul
= p
.cxform
.g1
;
3579 g
= mergeMulAdd(g
, luminance
);
3580 p
.cxform
.g0
= g
.mul
;
3581 p
.cxform
.g1
= g
.add
;
3582 set
= set
| SF_CX_G
;
3584 if(bstr
[0] || luminancestr
[0])
3588 b
= parseMulAdd(bstr
);
3591 b
.add
= p
.cxform
.b0
;
3592 b
.mul
= p
.cxform
.b1
;
3594 b
= mergeMulAdd(b
, luminance
);
3595 p
.cxform
.b0
= b
.mul
;
3596 p
.cxform
.b1
= b
.add
;
3597 set
= set
| SF_CX_B
;
3601 MULADD a
= parseMulAdd(astr
);
3602 p
.cxform
.a0
= a
.mul
;
3603 p
.cxform
.a1
= a
.add
;
3604 set
= set
| SF_CX_A
;
3611 for(t
= 0; blendModeNames
[t
]; t
++)
3613 if(!strcmp(blendModeNames
[t
], blendmode
))
3621 syntaxerror("unknown blend mode: '%s'", blendmode
);
3623 p
.blendmode
= blend
;
3624 set
= set
| SF_BLEND
;
3629 p
.filters
= parseFilters((char*)filterstr
);
3630 set
= set
| SF_FILTER
;
3633 if(type
== PT_CHANGE
&& set
& (SF_X
| SF_Y
))
3634 warning("As of version 0.8.2 using the .change command to modify an \
3635 object's position on the stage is considered deprecated. Future \
3636 versions may consider x and y parameters for the .change command \
3637 to be illegal; please use the .move command.");
3646 s_put(instance
, character
, p
);
3650 const char* interstr
= lu(args
, "interpolation");
3651 interpolation_t
* inter
= (interpolation_t
*)dict_lookup(&interpolations
, interstr
);
3653 syntaxerror("unkown interpolation %s", interstr
);
3654 s_change(instance
, p
, inter
);
3659 const char* interstr
= lu(args
, "interpolation");
3660 interpolation_t
* inter
= (interpolation_t
*)dict_lookup(&interpolations
, interstr
);
3662 syntaxerror("unkown interpolation %s", interstr
);
3663 s_schange(instance
, p
, inter
);
3667 s_jump(instance
, p
);
3670 s_startclip(instance
, character
, p
);
3674 s_buttonput(character
, as
, p
);
3676 s_buttonput(character
, "shape", p
);
3682 static int c_put(map_t
*args
)
3684 c_placement(args
, PT_PUT
);
3687 static int c_change(map_t
*args
)
3689 if(currentframe
== 0)
3690 warning("change commands in frame 1 will be ignored, please use the put command to set object parameters");
3691 c_placement(args
, PT_CHANGE
);
3694 static int c_schange(map_t
*args
)
3696 c_placement(args
, PT_SCHANGE
);
3699 static int c_move(map_t
* args
)
3701 c_movement(args
, PT_MOVE
);
3704 static int c_smove(map_t
* args
)
3706 c_movement(args
, PT_SMOVE
);
3709 static int c_sweep(map_t
* args
)
3711 c_movement(args
, PT_SWEEP
);
3714 static int c_arcchange(map_t
*args
)
3716 c_placement(args
, 0);
3719 static int c_jump(map_t
*args
)
3721 c_placement(args
, PT_JUMP
);
3724 static int c_startclip(map_t
*args
)
3726 c_placement(args
, PT_STARTCLIP
);
3729 static int c_show(map_t
*args
)
3731 c_placement(args
, PT_BUTTON
);
3734 static int c_toggle(map_t
* args
)
3736 const char*instance
= lu(args
, "name");
3737 U16 flagsOn
= 0x0000, flagsOff
= 0xffff;
3738 const char* alignstr
= lu(args
, "fixed_alignment");
3739 if(!strcmp(alignstr
, "on"))
3740 flagsOn
+= IF_FIXED_ALIGNMENT
;
3742 if(!strcmp(alignstr
, "off"))
3743 flagsOff
-= IF_FIXED_ALIGNMENT
;
3745 syntaxerror("values for toggle must be \"on\" or \"off\". %s is not legal.", alignstr
);
3746 s_toggle(instance
, flagsOn
, flagsOff
);
3749 static int c_del(map_t
*args
)
3751 const char*instance
= lu(args
, "name");
3752 s_delinstance(instance
);
3755 static int c_end(map_t
*args
)
3760 static int c_sprite(map_t
*args
)
3762 const char* name
= lu(args
, "name");
3763 const char* scalinggrid
= lu(args
, "scalinggrid");
3764 const char* as3name
= lu(args
, "as3name");
3766 if(scalinggrid
&& *scalinggrid
) {
3767 SRECT r
= parseBox(scalinggrid
);
3768 s_sprite(name
, &r
, as3name
);
3770 s_sprite(name
, 0, as3name
);
3774 static int c_frame(map_t
*args
)
3776 const char*framestr
= lu(args
, "n");
3777 const char*cutstr
= lu(args
, "cut");
3779 const char*name
= lu(args
, "name");
3780 const char*anchor
= lu(args
, "anchor");
3783 if(!strcmp(anchor
, "anchor") && !*name
)
3788 if(strcmp(cutstr
, "no"))
3790 if(isRelative(framestr
)) {
3791 frame
= s_getframe();
3792 if(getSign(framestr
)<0)
3793 syntaxerror("relative frame expressions must be positive");
3794 frame
+= parseInt(getOffset(framestr
));
3797 frame
= parseInt(framestr
);
3798 if(s_getframe() >= frame
3799 && !(frame
==1 && s_getframe()==frame
)) // equality is o.k. for frame 0
3800 syntaxerror("frame expression must be >%d (is:%s)", s_getframe(), framestr
);
3802 s_frame(frame
, cut
, name
, !strcmp(anchor
, "anchor"));
3805 static int c_primitive(map_t
*args
)
3807 const char*name
= lu(args
, "name");
3808 const char*command
= lu(args
, "commandname");
3809 int width
=0, height
=0, r
=0;
3810 int linewidth
= parseTwip(lu(args
, "line"));
3811 const char*colorstr
= lu(args
, "color");
3812 RGBA color
= parseColor(colorstr
);
3813 const char*fillstr
= lu(args
, "fill");
3818 const char* outline
=0;
3820 if(!strcmp(command
, "circle"))
3822 else if(!strcmp(command
, "filled"))
3826 width
= parseTwip(lu(args
, "width"));
3827 height
= parseTwip(lu(args
, "height"));
3828 } else if(type
==1) {
3829 r
= parseTwip(lu(args
, "r"));
3830 } else if(type
==2) {
3831 outline
= lu(args
, "outline");
3834 if(!strcmp(fillstr
, "fill"))
3836 if(!strcmp(fillstr
, "none"))
3838 if(width
<0 || height
<0 || linewidth
<0 || r
<0)
3839 syntaxerror("values width, height, line, r must be positive");
3841 if(type
== 0) s_box(name
, width
, height
, color
, linewidth
, fillstr
);
3842 else if(type
==1) s_circle(name
, r
, color
, linewidth
, fillstr
);
3843 else if(type
==2) s_filled(name
, outline
, color
, linewidth
, fillstr
);
3847 static int c_textshape(map_t
*args
)
3849 const char*name
= lu(args
, "name");
3850 const char*text
= lu(args
, "text");
3851 const char*font
= lu(args
, "font");
3852 float size
= parsePxOrPercent(font
, lu(args
, "size"));
3854 s_textshape(name
, font
, size
, text
);
3858 static int c_swf(map_t
*args
)
3860 const char*name
= lu(args
, "name");
3861 const char*filename
= lu(args
, "filename");
3862 const char*command
= lu(args
, "commandname");
3863 const char*as3name
= lu(args
, "as3name");
3865 if(!strcmp(command
, "shape"))
3866 warning("Please use .swf instead of .shape");
3867 s_includeswf(name
, filename
, as3name
);
3871 static int c_font(map_t
*args
)
3873 const char*name
= lu(args
, "name");
3874 const char*filename
= lu(args
, "filename");
3875 s_font(name
, filename
);
3879 static int c_sound(map_t
*args
)
3881 const char*name
= lu(args
, "name");
3882 const char*filename
= lu(args
, "filename");
3883 s_sound(name
, filename
);
3887 static int c_text(map_t
*args
)
3889 const char*name
= lu(args
, "name");
3890 const char*text
= lu(args
, "text");
3891 const char*font
= lu(args
, "font");
3892 float size
= parsePxOrPercent(font
, lu(args
, "size"));
3893 RGBA color
= parseColor(lu(args
, "color"));
3894 s_text(name
, font
, text
, (int)(size
*100), color
);
3898 static int c_soundtrack(map_t
*args
)
3903 static int c_quicktime(map_t
*args
)
3905 const char*name
= lu(args
, "name");
3906 const char*url
= lu(args
, "url");
3907 s_quicktime(name
, url
);
3911 static int c_video(map_t
*args
)
3913 const char*name
= lu(args
, "name");
3914 int width
= parseInt(lu(args
, "width"));
3915 int height
= parseInt(lu(args
, "height"));
3916 s_video(name
, width
, height
);
3920 static int c_image(map_t
*args
)
3922 const char*command
= lu(args
, "commandname");
3923 const char*name
= lu(args
, "name");
3924 const char*filename
= lu(args
, "filename");
3925 if(!strcmp(command
,"jpeg")) {
3926 int quality
= (int)(parsePercent(lu(args
, "quality"))*100);
3927 s_image(name
, "jpeg", filename
, quality
);
3929 s_image(name
, "png", filename
, 0);
3934 static int c_outline(map_t
*args
)
3936 const char*name
= lu(args
, "name");
3937 const char*format
= lu(args
, "format");
3941 syntaxerror("colon (:) expected");
3943 s_outline(name
, format
, text
);
3947 int fakechar(map_t
*args
)
3949 const char*name
= lu(args
, "name");
3950 s_box(name
, 0, 0, black
, 20, 0);
3954 static int c_egon(map_t
*args
) {return fakechar(args
);}
3955 static int c_button(map_t
*args
) {
3956 const char*name
= lu(args
, "name");
3957 const char*as3name
= lu(args
, "as3name");
3958 s_button(name
, as3name
);
3961 static int current_button_flags
= 0;
3962 static int c_on_press(map_t
*args
)
3964 const char*position
= lu(args
, "position");
3965 const char*action
= "";
3966 if(!strcmp(position
, "inside")) {
3967 current_button_flags
|= BC_OVERUP_OVERDOWN
;
3968 } else if(!strcmp(position
, "outside")) {
3969 //current_button_flags |= BC_IDLE_OUTDOWN;
3970 syntaxerror("IDLE_OVERDOWN not supported by SWF");
3971 } else if(!strcmp(position
, "anywhere")) {
3972 current_button_flags
|= /*BC_IDLE_OUTDOWN|*/BC_OVERUP_OVERDOWN
|BC_IDLE_OVERDOWN
;
3975 if(type
== RAWDATA
) {
3977 s_buttonaction(current_button_flags
, action
);
3978 current_button_flags
= 0;
3984 static int c_on_release(map_t
*args
)
3986 const char*position
= lu(args
, "position");
3987 const char*action
= "";
3988 if(!strcmp(position
, "inside")) {
3989 current_button_flags
|= BC_OVERDOWN_OVERUP
;
3990 } else if(!strcmp(position
, "outside")) {
3991 current_button_flags
|= BC_OUTDOWN_IDLE
;
3992 } else if(!strcmp(position
, "anywhere")) {
3993 current_button_flags
|= BC_OVERDOWN_OVERUP
|BC_OUTDOWN_IDLE
|BC_OVERDOWN_IDLE
;
3996 if(type
== RAWDATA
) {
3998 s_buttonaction(current_button_flags
, action
);
3999 current_button_flags
= 0;
4005 static int c_on_move_in(map_t
*args
)
4007 const char*position
= lu(args
, "state");
4008 const char*action
= "";
4009 if(!strcmp(position
, "pressed")) {
4010 current_button_flags
|= BC_OUTDOWN_OVERDOWN
;
4011 } else if(!strcmp(position
, "not_pressed")) {
4012 current_button_flags
|= BC_IDLE_OVERUP
;
4013 } else if(!strcmp(position
, "any")) {
4014 current_button_flags
|= BC_OUTDOWN_OVERDOWN
|BC_IDLE_OVERUP
|BC_IDLE_OVERDOWN
;
4017 if(type
== RAWDATA
) {
4019 s_buttonaction(current_button_flags
, action
);
4020 current_button_flags
= 0;
4026 static int c_on_move_out(map_t
*args
)
4028 const char*position
= lu(args
, "state");
4029 const char*action
= "";
4030 if(!strcmp(position
, "pressed")) {
4031 current_button_flags
|= BC_OVERDOWN_OUTDOWN
;
4032 } else if(!strcmp(position
, "not_pressed")) {
4033 current_button_flags
|= BC_OVERUP_IDLE
;
4034 } else if(!strcmp(position
, "any")) {
4035 current_button_flags
|= BC_OVERDOWN_OUTDOWN
|BC_OVERUP_IDLE
|BC_OVERDOWN_IDLE
;
4038 if(type
== RAWDATA
) {
4040 s_buttonaction(current_button_flags
, action
);
4041 current_button_flags
= 0;
4047 static int c_on_key(map_t
*args
)
4049 const char*key
= lu(args
, "key");
4050 const char*action
= "";
4051 if(strlen(key
)==1) {
4054 current_button_flags
|= 0x4000 + (key
[0]*0x200);
4056 syntaxerror("invalid character: %c"+key
[0]);
4061 <ctrl-x> = 0x200*(x-'a')
4065 syntaxerror("invalid key: %s",key
);
4068 if(type
== RAWDATA
) {
4070 s_buttonaction(current_button_flags
, action
);
4071 current_button_flags
= 0;
4078 static int c_edittext(map_t
*args
)
4080 //"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"},
4081 const char*name
= lu(args
, "name");
4082 const char*font
= lu(args
, "font");
4083 int size
= (int)(1024*parsePxOrPercent(font
, lu(args
, "size")));
4084 int width
= parseTwip(lu(args
, "width"));
4085 int height
= parseTwip(lu(args
, "height"));
4086 const char*text
= lu(args
, "text");
4087 RGBA color
= parseColor(lu(args
, "color"));
4088 int maxlength
= parseInt(lu(args
, "maxlength"));
4089 const char*variable
= lu(args
, "variable");
4090 const char*passwordstr
= lu(args
, "password");
4091 const char*wordwrapstr
= lu(args
, "wordwrap");
4092 const char*multilinestr
= lu(args
, "multiline");
4093 const char*htmlstr
= lu(args
, "html");
4094 const char*noselectstr
= lu(args
, "noselect");
4095 const char*readonlystr
= lu(args
, "readonly");
4096 const char*borderstr
= lu(args
, "border");
4097 const char*autosizestr
= lu(args
, "autosize");
4098 const char*alignstr
= lu(args
, "align");
4102 if(!strcmp(passwordstr
, "password")) flags
|= ET_PASSWORD
;
4103 if(!strcmp(wordwrapstr
, "wordwrap")) flags
|= ET_WORDWRAP
;
4104 if(!strcmp(multilinestr
, "multiline")) flags
|= ET_MULTILINE
;
4105 if(!strcmp(readonlystr
, "readonly")) flags
|= ET_READONLY
;
4106 if(!strcmp(htmlstr
, "html")) flags
|= ET_HTML
;
4107 if(!strcmp(noselectstr
, "noselect")) flags
|= ET_NOSELECT
;
4108 if(!strcmp(borderstr
, "border")) flags
|= ET_BORDER
;
4109 if(!strcmp(autosizestr
, "autosize")) flags
|= ET_AUTOSIZE
;
4110 if(!strcmp(alignstr
, "left") || !*alignstr
) align
= ET_ALIGN_LEFT
;
4111 else if(!strcmp(alignstr
, "right")) align
= ET_ALIGN_RIGHT
;
4112 else if(!strcmp(alignstr
, "center")) align
= ET_ALIGN_CENTER
;
4113 else if(!strcmp(alignstr
, "justify")) align
= ET_ALIGN_JUSTIFY
;
4114 else syntaxerror("Unknown alignment: %s", alignstr
);
4116 s_edittext(name
, font
, size
, width
, height
, text
, &color
, maxlength
, variable
, flags
, align
);
4120 static int c_morphshape(map_t
*args
) {return fakechar(args
);}
4121 static int c_movie(map_t
*args
) {return fakechar(args
);}
4123 static char* readfile(char*filename
)
4125 FILE*fi
= fopen(filename
, "rb");
4129 syntaxerror("Couldn't find file %s: %s", filename
, strerror(errno
));
4130 fseek(fi
, 0, SEEK_END
);
4132 fseek(fi
, 0, SEEK_SET
);
4133 text
= rfx_alloc(l
+1);
4134 fread(text
, l
, 1, fi
);
4140 static int c_action(map_t
*args
)
4142 const char* filename
= map_lookup(args
, "filename");
4143 if(!filename
||!*filename
) {
4145 if(type
!= RAWDATA
) {
4146 syntaxerror("colon (:) expected");
4150 s_action(readfile((char*)filename
));
4156 static int c_initaction(map_t
*args
)
4158 const char* character
= lu(args
, "name");
4159 const char* filename
= map_lookup(args
, "filename");
4160 if(!filename
||!*filename
) {
4162 if(type
!= RAWDATA
) {
4163 syntaxerror("colon (:) expected");
4165 s_initaction(character
, text
);
4167 s_initaction(character
, readfile((char*)filename
));
4175 command_func_t
* func
;
4178 {{"flash", c_flash
, "bbox=autocrop background=black version=6 fps=50 name= filename= @compress=default @change-sets-all=no @export=1 @mainclass="},
4179 {"frame", c_frame
, "n=<plus>1 name= @cut=no @anchor=no"},
4180 // "import" type stuff
4181 {"swf", c_swf
, "name filename as3name="},
4182 {"shape", c_swf
, "name filename"},
4183 {"jpeg", c_image
, "name filename quality=80%"},
4184 {"png", c_image
, "name filename"},
4185 {"movie", c_movie
, "name filename"},
4186 {"sound", c_sound
, "name filename"},
4187 {"font", c_font
, "name filename glyphs= @flashtype="},
4188 {"soundtrack", c_soundtrack
, "filename"},
4189 {"quicktime", c_quicktime
, "url"},
4190 {"video", c_video
, "name width= height="},
4192 // generators of primitives
4194 {"define", c_define
, "name value=0"},
4195 {"point", c_point
, "name x=0 y=0"},
4196 {"gradient", c_gradient
, "name @radial=0 rotate=0 scale= scalex= scaley= x= y= width= height= r= shear="}, //extra parameters like .texture
4197 {"interpolation", c_interpolation
, "name function=linear speed=1.3 amplitude=0 bounces=2 growth=1.5 damping=2 slope=0"},
4198 {"outline", c_outline
, "name format=simple"},
4199 {"textshape", c_textshape
, "name font size=100% text"},
4202 {"blur", c_blur
, "name blur= blurx= blury= passes=1"},
4203 {"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"},
4204 {"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"},
4205 {"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"},
4207 // character generators
4208 {"box", c_primitive
, "name width height color=white line=1 @fill=none"},
4209 {"circle", c_primitive
, "name r color=white line=1 @fill=none"},
4210 {"filled", c_primitive
, "name outline color=white line=1 @fill=none"},
4212 {"egon", c_egon
, "name vertices color=white line=1 @fill=none"},
4213 {"text", c_text
, "name text font size=100% color=white"},
4214 {"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="},
4215 {"morphshape", c_morphshape
, "name start end"},
4216 {"button", c_button
, "name as3name="},
4217 {"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="},
4218 {"on_press", c_on_press
, "position=inside"},
4219 {"on_release", c_on_release
, "position=anywhere"},
4220 {"on_move_in", c_on_move_in
, "state=not_pressed"},
4221 {"on_move_out", c_on_move_out
, "state=not_pressed"},
4222 {"on_key", c_on_key
, "key=any"},
4225 {"play", c_play
, "name loop=0 @nomultiple=0"},
4226 {"stop", c_stop
, "name= "},
4227 {"nextframe", c_nextframe
, "name"},
4228 {"previousframe", c_previousframe
, "name"},
4230 // object placement tags
4231 {"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"},
4232 {"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"},
4233 {"move", c_move
, "name x= y= interpolation=linear"},
4234 {"smove", c_smove
, "name x= y= interpolation=linear"},
4235 {"sweep", c_sweep
, "name x= y= r= dir=counterclockwise arc=short interpolation=linear"},
4236 {"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"},
4237 //{"arcchange", c_arcchange, "name pivot= angle= red= green= blue= alpha= luminance= scale= scalex= scaley= blend= filter= pivot= pin= shear= rotate= ratio= above= below="},
4238 {"schange", c_schange
, "name red= green= blue= alpha= luminance= scale= scalex= scaley= blend= filter= pivot= pin= shear= rotate= ratio= above= below= interpolation=linear"},
4239 {"jump", c_jump
, "name x= y= red= green= blue= alpha= luminance= scale= scalex= scaley= blend= filter= pivot= pin= shear= rotate= ratio= above= below="},
4240 {"del", c_del
, "name"},
4241 // virtual object placement
4242 {"texture", c_texture
, "<i> x=0 y=0 width= height= scale= scalex= scaley= r= shear= rotate="},
4244 {"toggle", c_toggle
, "name fixed_alignment="},
4246 // commands which start a block
4247 //startclip (see above)
4248 {"sprite", c_sprite
, "name scalinggrid= as3name="},
4249 {"action", c_action
, "filename="},
4250 {"initaction", c_initaction
, "name filename="},
4256 static map_t
parseArguments(char*command
, char*pattern
)
4272 string_set(&t1
, "commandname");
4273 string_set(&t2
, command
);
4274 map_put(&result
, t1
, t2
);
4276 if(!pattern
|| !*pattern
)
4283 if(!strncmp("<i> ", x
, 3)) {
4285 if(type
== COMMAND
|| type
== RAWDATA
) {
4287 syntaxerror("character name expected");
4289 name
[pos
].str
= "instance";
4291 value
[pos
].str
= text
;
4292 value
[pos
].len
= strlen(text
);
4296 if(type
== ASSIGNMENT
)
4299 name
[pos
].str
= "character";
4301 value
[pos
].str
= text
;
4302 value
[pos
].len
= strlen(text
);
4310 isboolean
[pos
] = (x
[0] =='@');
4323 name
[pos
].len
= d
-x
;
4328 name
[pos
].len
= e
-x
;
4329 value
[pos
].str
= e
+1;
4330 value
[pos
].len
= d
-e
-1;
4338 /* for(t=0;t<len;t++) {
4339 printf("(%d) %s=%s %s\n", t, strdup_n(name[t], namelen[t]), strdup_n(value[t], valuelen[t]),
4340 isboolean[t]?"(boolean)":"");
4345 if(type
== RAWDATA
|| type
== COMMAND
) {
4350 // first, search for boolean arguments
4351 for(pos
=0;pos
<len
;pos
++)
4353 if(!set
[pos
] && isboolean
[pos
] && !strncmp(name
[pos
].str
, text
, name
[pos
].len
>textlen
?name
[pos
].len
:textlen
)) {
4355 if(type
== ASSIGNMENT
)
4357 value
[pos
].str
= text
;
4358 value
[pos
].len
= strlen(text
);
4359 /*printf("setting boolean parameter %s (to %s)\n",
4360 strdup_n(name[pos], namelen[pos]),
4361 strdup_n(value[pos], valuelen[pos]));*/
4366 // second, search for normal arguments
4368 for(pos
=0;pos
<len
;pos
++)
4370 if((type
== ASSIGNMENT
&& !strncmp(name
[pos
].str
, text
, name
[pos
].len
>textlen
?name
[pos
].len
:textlen
)) ||
4371 (type
!= ASSIGNMENT
&& !set
[pos
])) {
4373 syntaxerror("value %s set twice (old value:%s)", text
, strdup_n(value
[pos
].str
, value
[pos
].len
));
4375 if(type
== ASSIGNMENT
)
4378 value
[pos
].str
= text
;
4379 value
[pos
].len
= strlen(text
);
4381 printf("setting parameter %s (to %s)\n",
4382 strdup_n(name
[pos
].str
, name
[pos
].len
),
4383 strdup_n(value
[pos
].str
, value
[pos
].len
));
4389 syntaxerror("Illegal argument \"%s\" to .%s", text
, command
);
4393 for(t
=0;t
<len
;t
++) {
4394 printf("%s=%s\n", strdup_n(name
[t
].str
, name
[t
].len
), strdup_n(value
[t
].str
, value
[t
].len
));
4397 for(t
=0;t
<len
;t
++) {
4398 if(value
[t
].str
&& value
[t
].str
[0] == '*') {
4399 //relative default- take value from some other parameter
4401 for(s
=0;s
<len
;s
++) {
4402 if(value
[s
].len
== value
[t
].len
-1 &&
4403 !strncmp(&value
[t
].str
[1], value
[s
].str
, value
[s
].len
))
4404 value
[t
].str
= value
[s
].str
;
4407 if(value
[t
].str
== 0) {
4409 syntaxerror("value for parameter %s missing (no default)", strdup_n(name
[t
].str
, name
[t
].len
));
4413 /* ok, now construct the dictionary from the parameters */
4417 map_put(&result
, name
[t
], value
[t
]);
4421 static void parseArgumentsForCommand(char*command
)
4426 msg("<verbose> parse Command: %s (line %d)", command
, line
);
4428 for(t
=0;t
<sizeof(arguments
)/sizeof(arguments
[0]);t
++) {
4429 if(!strcmp(arguments
[t
].command
, command
)) {
4431 /* ugly hack- will be removed soon (once documentation and .sc generating
4432 utilities have been changed) */
4433 if(!strcmp(command
, "swf") && !stackpos
) {
4434 warning("Please use .flash instead of .swf- this will be mandatory soon");
4439 args
= parseArguments(command
, arguments
[t
].arguments
);
4445 syntaxerror("command %s not known", command
);
4448 // catch missing .flash directives at the beginning of a file
4449 if(strcmp(command
, "flash") && !stackpos
)
4451 syntaxerror("No movie defined- use .flash first");
4456 printf(".%s\n", command
);fflush(stdout
);
4457 map_dump(&args
, stdout
, "\t");fflush(stdout
);
4461 (*arguments
[nr
].func
)(&args
);
4463 if(!strcmp(command
, "action") || !strcmp(command
, "initaction") ||
4464 !strcmp(command
, "outline") || !strcmp(command
, "gradient")) {
4466 if(type
!= RAWDATA
) {
4467 syntaxerror("colon (:) expected");
4476 /* for now only intended to find what glyphs of each font are to be included in the swf file.
4477 * Therefore some knowledge about the command is assumed i.e. it is font/text-related
4478 * No syntax checking is done */
4479 static void analyseArgumentsForCommand(char*command
)
4484 U8
* glyphs_to_include
;
4485 msg("<verbose> analyse Command: %s (line %d)", command
, line
);
4487 for(t
=0;t
<sizeof(arguments
)/sizeof(arguments
[0]);t
++)
4489 if(!strcmp(arguments
[t
].command
, command
))
4491 args
= parseArguments(command
, arguments
[t
].arguments
);
4497 printf(".%s\n", command
);fflush(stdout
);
4498 map_dump(&args
, stdout
, "\t");fflush(stdout
);
4500 const char* name
= lu(&args
, "name");
4501 if(!strcmp(command
, "font"))
4503 const char* fontfile
= lu(&args
, "filename");
4504 const char* glyphs
= lu(&args
, "glyphs");
4505 const char* flashtype
= lu(&args
, "flashtype");
4506 s_createfont(name
, fontfile
, glyphs
, flashtype
[0]);
4508 SWFFONT
* font
= dict_lookup(&fonts
, lu(&args
, "font"));
4510 //that's ok... it might be an edittext with a system font
4511 //syntaxerror("font %s is not known in line %d", lu(&args, "font"), line);
4513 if(font
->use
&& !font
->use
->glyphs_specified
) {
4514 if(!strcmp(command
, "edittext"))
4516 swf_FontUseAll(font
);
4517 font
->use
->glyphs_specified
= 1;
4520 swf_FontUseUTF8(font
, (U8
*)lu(&args
, "text"), 0xffff);
4527 void skipParameters()
4531 while (type
!= COMMAND
);
4535 void findFontUsage()
4537 char* fontRelated
= "font;text;textshape;edittext;";
4538 while(!noMoreTokens())
4542 syntaxerror("command expected");
4543 if(strstr(fontRelated
, text
))
4544 analyseArgumentsForCommand(text
);
4546 if(strcmp(text
, "end"))
4555 dict_init(&fonts
, 16);
4556 cleanUp
= &freeFontDictionary
;
4560 int main (int argc
,char ** argv
)
4563 processargs(argc
, argv
);
4564 initLog(0,-1,0,0,-1,verbose
);
4567 args_callback_usage(argv
[0]);
4571 file
= generateTokens(filename
);
4573 fprintf(stderr
, "parser returned error.\n");
4580 while(!noMoreTokens()) {
4583 syntaxerror("command expected");
4584 parseArgumentsForCommand(text
);