+
+
+typedef struct _sound_t
+{
+ U16 id;
+ TAG*tag;
+} sound_t;
+
+void s_sound(char*name, char*filename)
+{
+ struct WAV wav, wav2;
+ sound_t* sound;
+ U16*samples;
+ int numsamples;
+ int t;
+
+ if(!readWAV(filename, &wav)) {
+ warning("Couldn't read wav file \"%s\"", filename);
+ samples = 0;
+ numsamples = 0;
+ } else {
+ convertWAV2mono(&wav, &wav2, 44100);
+ samples = (U16*)wav2.data;
+ numsamples = wav2.size/2;
+ free(wav.data);
+#ifdef WORDS_BIGENDIAN
+ /* swap bytes */
+ for(t=0;t<numsamples;t++) {
+ samples[t] = (samples[t]>>8)&0xff | (samples[t]<<8)&0xff00;
+ }
+#endif
+ }
+
+ tag = swf_InsertTag(tag, ST_DEFINESOUND);
+ swf_SetU16(tag, id); //id
+ swf_SetSoundDefine(tag, samples, numsamples);
+
+ sound = (sound_t*)malloc(sizeof(sound_t)); /* mem leak */
+ sound->tag = tag;
+ sound->id = id;
+
+ if(dictionary_lookup(&sounds, name))
+ syntaxerror("sound %s defined twice", name);
+ dictionary_put2(&sounds, name, sound);
+
+ incrementid();
+
+ if(samples)
+ free(samples);
+}
+
+static char* gradient_getToken(const char**p)
+{
+ const char*start;
+ char*result;
+ while(**p && strchr(" \t\n\r", **p)) {
+ (*p)++;
+ }
+ start = *p;
+ while(**p && !strchr(" \t\n\r", **p)) {
+ (*p)++;
+ }
+ result = malloc((*p)-start+1);
+ memcpy(result,start,(*p)-start+1);
+ result[(*p)-start] = 0;
+ return result;
+}
+
+float parsePercent(char*str);
+RGBA parseColor(char*str);
+
+GRADIENT parseGradient(const char*str)
+{
+ GRADIENT gradient;
+ const char* p = str;
+ memset(&gradient, 0, sizeof(GRADIENT));
+ while(*p) {
+ char*posstr,*colorstr;
+ float pos;
+ RGBA color;
+ posstr = gradient_getToken(&p);
+ if(!*posstr)
+ break;
+ pos = parsePercent(posstr);
+ if(!*p) syntaxerror("Error in shape data: Color expected after %s", posstr);
+ colorstr = gradient_getToken(&p);
+ color = parseColor(colorstr);
+ if(gradient.num == sizeof(gradient.ratios)/sizeof(gradient.ratios[0])) {
+ warning("gradient record too big- max size is 8, rest ignored");
+ break;
+ }
+ gradient.ratios[gradient.num] = (int)(pos*255.0);
+ gradient.rgba[gradient.num] = color;
+ gradient.num++;
+ free(posstr);
+ free(colorstr);
+ }
+ return gradient;
+}
+
+void s_gradient(char*name, const char*text, int radial, int rotate)
+{
+ gradient_t* gradient;
+ gradient = malloc(sizeof(gradient_t));
+ memset(gradient, 0, sizeof(gradient_t));
+ gradient->gradient = parseGradient(text);
+ gradient->radial = radial;
+ gradient->rotate = rotate;
+
+ if(dictionary_lookup(&gradients, name))
+ syntaxerror("gradient %s defined twice", name);
+ dictionary_put2(&gradients, name, gradient);
+}
+
+void s_action(const char*text)
+{
+ ActionTAG* a = 0;
+ a = swf_ActionCompile(text, stack[0].swf->fileVersion);
+ if(!a) {
+ syntaxerror("Couldn't compile ActionScript");
+ }
+
+ tag = swf_InsertTag(tag, ST_DOACTION);
+
+ swf_ActionSet(tag, a);
+
+ swf_ActionFree(a);
+}
+
+int s_swf3action(char*name, char*action)
+{
+ ActionTAG* a = 0;
+ instance_t* object = 0;
+ if(name)
+ dictionary_lookup(&instances, name);
+ if(!object && name && *name) {
+ /* we have a name, but couldn't find it. Abort. */
+ return 0;
+ }
+ a = action_SetTarget(0, name);
+ if(!strcmp(action, "nextframe")) a = action_NextFrame(a);
+ else if(!strcmp(action, "previousframe")) a = action_PreviousFrame(a);
+ else if(!strcmp(action, "stop")) a = action_Stop(a);
+ else if(!strcmp(action, "play")) a = action_Play(a);
+ a = action_SetTarget(a, "");
+ a = action_End(a);
+
+ tag = swf_InsertTag(tag, ST_DOACTION);
+ swf_ActionSet(tag, a);
+ swf_ActionFree(a);
+ return 1;
+}
+
+void s_outline(char*name, char*format, char*source)
+{
+ outline_t* outline;
+
+ drawer_t draw;
+ SHAPE* shape;
+ SHAPE2* shape2;
+ SRECT bounds;
+
+ swf_Shape11DrawerInit(&draw, 0);
+ draw_string(&draw, source);
+ draw.finish(&draw);
+ shape = swf_ShapeDrawerToShape(&draw);
+ bounds = swf_ShapeDrawerGetBBox(&draw);
+ draw.dealloc(&draw);
+
+ outline = (outline_t*)rfx_calloc(sizeof(outline_t));
+ outline->shape = shape;
+ outline->bbox = bounds;
+
+ if(dictionary_lookup(&outlines, name))
+ syntaxerror("outline %s defined twice", name);
+ dictionary_put2(&outlines, name, outline);
+}
+
+int s_playsound(char*name, int loops, int nomultiple, int stop)
+{
+ sound_t* sound;
+ if(!name)
+ return 0;
+ sound = dictionary_lookup(&sounds, name);
+ SOUNDINFO info;
+ if(!sound)
+ return 0;
+
+ tag = swf_InsertTag(tag, ST_STARTSOUND);
+ swf_SetU16(tag, sound->id); //id
+ memset(&info, 0, sizeof(info));
+ info.stop = stop;
+ info.loops = loops;
+ info.nomultiple = nomultiple;
+ swf_SetSoundInfo(tag, &info);
+ return 1;
+}
+
+void s_includeswf(char*name, char*filename)