X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=src%2Fswfc.c;h=2db2d108fa3b051dc9108315a0ac088213bb23d5;hb=7528e9af6df5b0d27fc6d27158ab3cc51d6cbf64;hp=317133dec62b63440990ee5512dfb8b7697b1b46;hpb=b35b12a5ec63ed81cd050af87575d0323b6ea931;p=swftools.git diff --git a/src/swfc.c b/src/swfc.c index 317133d..2db2d10 100644 --- a/src/swfc.c +++ b/src/swfc.c @@ -47,6 +47,7 @@ static int optimize = 0; static int override_outputname = 0; static int do_cgi = 0; static int change_sets_all = 0; +static int do_exports = 0; static struct options_t options[] = { {"h", "help"}, @@ -187,6 +188,8 @@ static struct level SRECT oldrect; TAG* cut; + SRECT scalegrid; + } stack[256]; static int stackpos = 0; @@ -347,6 +350,7 @@ static void freeDictionaries() dictionary_free_all(&fonts, free_font); dictionary_free_all(&sounds, free); dictionary_free_all(&interpolations, free); + cleanUp = 0; } static void freeFontDictionary() @@ -374,13 +378,15 @@ static void s_addcharacter(char*name, U16 id, TAG*ctag, SRECT r) c->size = r; dictionary_put2(&characters, name, c); - tag = swf_InsertTag(tag, ST_NAMECHARACTER); - swf_SetU16(tag, id); - swf_SetString(tag, name); - tag = swf_InsertTag(tag, ST_EXPORTASSETS); - swf_SetU16(tag, 1); - swf_SetU16(tag, id); - swf_SetString(tag, name); + if(do_exports) { + tag = swf_InsertTag(tag, ST_NAMECHARACTER); + swf_SetU16(tag, id); + swf_SetString(tag, name); + tag = swf_InsertTag(tag, ST_EXPORTASSETS); + swf_SetU16(tag, 1); + swf_SetU16(tag, id); + swf_SetString(tag, name); + } } static void s_addimage(char*name, U16 id, TAG*ctag, SRECT r) { @@ -629,7 +635,7 @@ void s_swf(char*name, SRECT r, int version, int fps, int compress, RGBA backgrou incrementid(); } -void s_sprite(char*name) +void s_sprite(char*name, SRECT*scalegrid) { tag = swf_InsertTag(tag, ST_DEFINESPRITE); swf_SetU16(tag, id); //id @@ -644,6 +650,11 @@ void s_sprite(char*name) stack[stackpos].tag = tag; stack[stackpos].id = id; stack[stackpos].name = strdup(name); + if(scalegrid) { + stack[stackpos].scalegrid = *scalegrid; + } else { + memset(&stack[stackpos].scalegrid, 0, sizeof(SRECT)); + } /* FIXME: those four fields should be bundled together */ dictionary_init(&instances); @@ -755,6 +766,10 @@ void s_buttonaction(int flags, char*action) if(flags==0) { return; } + if(!stackpos || !stack[stackpos-1].tag || + stack[stackpos-1].tag->id != ST_DEFINEBUTTON2) { + syntaxerror("Need to be inside a button for .on_* commands"); + } setbuttonrecords(stack[stackpos-1].tag); a = swf_ActionCompile(text, stack[0].swf->fileVersion); @@ -805,7 +820,8 @@ TAG* removeFromTo(TAG*from, TAG*to) TAG*save = from->prev; while(from!=to) { TAG*next = from->next; - swf_DeleteTag(from); + if(swf_isAllowedSpriteTag(from)) + swf_DeleteTag(0, from); from = next; } save->next = 0; @@ -907,7 +923,7 @@ static void writeInstance(instance_t* i) while (frame < currentframe) { frame++; - while (tag->id != ST_SHOWFRAME) + while (tag && tag->id != ST_SHOWFRAME) tag = tag->next; if (parametersChange(i->history, frame)) { @@ -942,9 +958,6 @@ static void s_endSprite() { SRECT r = currentrect; - if(stack[stackpos].cut) - tag = removeFromTo(stack[stackpos].cut, tag); - stackpos--; instance_t *i; stringarray_t* index =dictionary_index(&instances); @@ -958,6 +971,12 @@ static void s_endSprite() writeInstance(i); } } + + if(stack[stackpos].cut) + tag = removeFromTo(stack[stackpos].cut, tag); + + // the writeInstance loop above may have inserted tags after what used yo be the current tag, + // so let's make sure 'tag' point to the current tag again. while (tag->next) tag = tag->next; @@ -966,6 +985,15 @@ static void s_endSprite() tag = stack[stackpos].tag; swf_FoldSprite(tag); + + if(stack[stackpos].scalegrid.xmin | stack[stackpos].scalegrid.ymin | + stack[stackpos].scalegrid.xmax | stack[stackpos].scalegrid.ymax) + { + tag = swf_InsertTag(tag, ST_DEFINESCALINGGRID); + swf_SetU16(tag, stack[stackpos].id); + swf_SetRect(tag, &stack[stackpos].scalegrid); + } + if(tag->next != 0) syntaxerror("internal error(7)"); /* TODO: before clearing, prepend "." to names and @@ -1008,6 +1036,11 @@ static void s_endSWF() swf = stack[stackpos].swf; filename = stack[stackpos].filename; + // the writeInstance loop above may have inserted tags after what used yo be the current tag, + // so let's make sure 'tag' point to the current tag again. + while (tag->next) + tag = tag->next; + //if(tag->prev && tag->prev->id != ST_SHOWFRAME) // tag = swf_InsertTag(tag, ST_SHOWFRAME); tag = swf_InsertTag(tag, ST_SHOWFRAME); @@ -1039,8 +1072,6 @@ static void s_endSWF() } if(do_cgi) {if(swf_WriteCGI(swf)<0) syntaxerror("WriteCGI() failed.\n");} - else if(swf->compressed) - {if(swf_WriteSWC(fi, swf)<0) syntaxerror("WriteSWC() failed.\n");} else {if(swf_WriteSWF(fi, swf)<0) syntaxerror("WriteSWF() failed.\n");} @@ -1528,13 +1559,15 @@ void s_font(char*name, char*filename) swf_FontCreateLayout(font); } font->id = id; - swf_FontReduce_swfc(font); + swf_FontReduce_swfc(font); tag = swf_InsertTag(tag, ST_DEFINEFONT2); swf_FontSetDefine2(tag, font); - tag = swf_InsertTag(tag, ST_EXPORTASSETS); - swf_SetU16(tag, 1); - swf_SetU16(tag, id); - swf_SetString(tag, name); + if(do_exports) { + tag = swf_InsertTag(tag, ST_EXPORTASSETS); + swf_SetU16(tag, 1); + swf_SetU16(tag, id); + swf_SetString(tag, name); + } incrementid(); } @@ -1616,13 +1649,15 @@ void s_sound(char*name, char*filename) else swf_SetSoundDefine(tag, samples, numsamples); - tag = swf_InsertTag(tag, ST_NAMECHARACTER); - swf_SetU16(tag, id); - swf_SetString(tag, name); - tag = swf_InsertTag(tag, ST_EXPORTASSETS); - swf_SetU16(tag, 1); - swf_SetU16(tag, id); - swf_SetString(tag, name); + if(do_exports) { + tag = swf_InsertTag(tag, ST_NAMECHARACTER); + swf_SetU16(tag, id); + swf_SetString(tag, name); + tag = swf_InsertTag(tag, ST_EXPORTASSETS); + swf_SetU16(tag, 1); + swf_SetU16(tag, id); + swf_SetString(tag, name); + } sound = (sound_t*)malloc(sizeof(sound_t)); /* mem leak */ sound->tag = tag; @@ -2049,6 +2084,32 @@ void s_getParameters(char*name, parameters_t* p) else *p = i->parameters; } + +void setStartparameters(instance_t* i, parameters_t* p, TAG* tag) +{ + history_begin(i->history, "x", currentframe, tag, p->x); + history_begin(i->history, "y", currentframe, tag, p->y); + history_begin(i->history, "scalex", currentframe, tag, p->scalex); + history_begin(i->history, "scaley", currentframe, tag, p->scaley); + history_begin(i->history, "cxform.r0", currentframe, tag, p->cxform.r0); + history_begin(i->history, "cxform.g0", currentframe, tag, p->cxform.g0); + history_begin(i->history, "cxform.b0", currentframe, tag, p->cxform.b0); + history_begin(i->history, "cxform.a0", currentframe, tag, p->cxform.a0); + history_begin(i->history, "cxform.r1", currentframe, tag, p->cxform.r1); + history_begin(i->history, "cxform.g1", currentframe, tag, p->cxform.g1); + history_begin(i->history, "cxform.b1", currentframe, tag, p->cxform.b1); + history_begin(i->history, "cxform.a1", currentframe, tag, p->cxform.a1); + history_begin(i->history, "rotate", currentframe, tag, p->rotate); + history_begin(i->history, "shear", currentframe, tag, p->shear); + history_begin(i->history, "pivot.x", currentframe, tag, p->pivot.x); + history_begin(i->history, "pivot.y", currentframe, tag, p->pivot.y); + history_begin(i->history, "pin.x", currentframe, tag, p->pin.x); + history_begin(i->history, "pin.y", currentframe, tag, p->pin.y); + history_begin(i->history, "blendmode", currentframe, tag, p->blendmode); + history_beginFilter(i->history, currentframe, tag, p->filters); + history_begin(i->history, "flags", currentframe, tag, 0); +} + void s_startclip(char*instance, char*character, parameters_t p) { character_t* c = dictionary_lookup(&characters, character); @@ -2069,6 +2130,7 @@ void s_startclip(char*instance, char*character, parameters_t p) stack[stackpos].type = 2; stackpos++; + setStartparameters(i, &p, tag); currentdepth++; } void s_endClip() @@ -2078,37 +2140,12 @@ void s_endClip() swf_SetTagPos(stack[stackpos].tag, 0); swf_GetPlaceObject(stack[stackpos].tag, &p); p.clipdepth = currentdepth; - p.name = 0; + //p.name = 0; swf_ClearTag(stack[stackpos].tag); swf_SetPlaceObject(stack[stackpos].tag, &p); currentdepth++; } -void setStartparameters(instance_t* i, parameters_t* p, TAG* tag) -{ - history_begin(i->history, "x", currentframe, tag, p->x); - history_begin(i->history, "y", currentframe, tag, p->y); - history_begin(i->history, "scalex", currentframe, tag, p->scalex); - history_begin(i->history, "scaley", currentframe, tag, p->scaley); - history_begin(i->history, "cxform.r0", currentframe, tag, p->cxform.r0); - history_begin(i->history, "cxform.g0", currentframe, tag, p->cxform.g0); - history_begin(i->history, "cxform.b0", currentframe, tag, p->cxform.b0); - history_begin(i->history, "cxform.a0", currentframe, tag, p->cxform.a0); - history_begin(i->history, "cxform.r1", currentframe, tag, p->cxform.r1); - history_begin(i->history, "cxform.g1", currentframe, tag, p->cxform.g1); - history_begin(i->history, "cxform.b1", currentframe, tag, p->cxform.b1); - history_begin(i->history, "cxform.a1", currentframe, tag, p->cxform.a1); - history_begin(i->history, "rotate", currentframe, tag, p->rotate); - history_begin(i->history, "shear", currentframe, tag, p->shear); - history_begin(i->history, "pivot.x", currentframe, tag, p->pivot.x); - history_begin(i->history, "pivot.y", currentframe, tag, p->pivot.y); - history_begin(i->history, "pin.x", currentframe, tag, p->pin.x); - history_begin(i->history, "pin.y", currentframe, tag, p->pin.y); - history_begin(i->history, "blendmode", currentframe, tag, p->blendmode); - history_beginFilter(i->history, currentframe, tag, p->filters); - history_begin(i->history, "flags", currentframe, tag, 0); -} - void s_put(char*instance, char*character, parameters_t p) { character_t* c = dictionary_lookup(&characters, character); @@ -2327,7 +2364,7 @@ int parseInt(char*str) syntaxerror("Not an Integer: \"%s\"", str); return atoi(str); } -int parseTwip(char*str) +static double parseRawTwip(char*str) { char*dot; int sign=1; @@ -2340,23 +2377,25 @@ int parseTwip(char*str) if(!dot) { int l=strlen(str); int t; - return sign*parseInt(str)*20; + return sign*parseInt(str); } else { char* old = strdup(str); int l=strlen(dot+1); char*s; *dot++ = 0; - for(s=str;s'9') - { - free(old); - syntaxerror("Not a coordinate: \"%s\"", str); + for(s=str;s'9') + { + free(old); + syntaxerror("Not a coordinate: \"%s\"", str); + } } - for(s=dot;*s;s++) - if(*s<'0' || *s>'9') - { - free(old); - syntaxerror("Not a coordinate: \"%s\"", str); + for(s=dot;*s;s++) { + if(*s<'0' || *s>'9') + { + free(old); + syntaxerror("Not a coordinate: \"%s\"", str); + } } if(l>2 || (l==2 && (dot[1]!='0' && dot[1]!='5'))) { dot[1] = ((dot[1]-0x30)/5)*5 + 0x30; @@ -2366,15 +2405,145 @@ int parseTwip(char*str) } free(old); if(l==0) - return sign*atoi(str)*20; + return sign*(atoi(str)); if(l==1) - return sign*atoi(str)*20+atoi(dot)*2; + return sign*(atoi(str)+0.1*atoi(dot)); if(l==2) - return sign*atoi(str)*20+atoi(dot)/5; + return sign*(atoi(str)+0.01*atoi(dot)); } return 0; } +static dictionary_t defines; +static int defines_initialized = 0; +static mem_t define_values; + +static double parseNameOrTwip(char*s) +{ + int l = 0; + double v; + if(defines_initialized) { + l = (int)dictionary_lookup(&defines, s); + } + if(l) { + return *(int*)&define_values.buffer[l-1]; + } else { + return parseRawTwip(s); + } +} + +/* automatically generated by yiyiyacc, http://www.quiss.org/yiyiyacc/ */ +static double parseExpression(char*s) +{ + int chr2index[256]; + memset(chr2index, -1, sizeof(chr2index)); + chr2index['+'] = 0; + chr2index['-'] = 1; + chr2index['*'] = 2; + chr2index['/'] = 3; + chr2index['('] = 5; + chr2index[')'] = 6; + chr2index['\0'] = 7; + + int stackpos = 1; + int stack[256]; + double values[256]; + stack[0]=0; + values[0]=0; + int accept = 18; + int left[10]={11,8,8,8,8,9,9,9,10,10}; //production left side + int plen[10]={1,3,2,3,1,3,3,1,1,3}; //production size + int table[18][12] = { + {0, 4, 0, 0, 5, 6, 0, 0, 1, 2, 3, 0}, + {7, 8, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0}, + {-4, -4, 9, 10, 0, 0, -4, -4, 0, 0, 0, 0}, + {-7, -7, -7, -7, 0, 0, -7, -7, 0, 0, 0, 0}, + {0, 0, 0, 0, 5, 6, 0, 0, 0, 11, 3, 0}, + {-8, -8, -8, -8, 0, 0, -8, -8, 0, 0, 0, 0}, + {0, 4, 0, 0, 5, 6, 0, 0, 12, 2, 3, 0}, + {0, 0, 0, 0, 5, 6, 0, 0, 0, 13, 3, 0}, + {0, 0, 0, 0, 5, 6, 0, 0, 0, 14, 3, 0}, + {0, 0, 0, 0, 5, 6, 0, 0, 0, 0, 15, 0}, + {0, 0, 0, 0, 5, 6, 0, 0, 0, 0, 16, 0}, + {-2, -2, 9, 10, 0, 0, -2, -2, 0, 0, 0, 0}, + {7, 8, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0}, + {-1, -1, 9, 10, 0, 0, -1, -1, 0, 0, 0, 0}, + {-3, -3, 9, 10, 0, 0, -3, -3, 0, 0, 0, 0}, + {-5, -5, -5, -5, 0, 0, -5, -5, 0, 0, 0, 0}, + {-6, -6, -6, -6, 0, 0, -6, -6, 0, 0, 0, 0}, + {-9, -9, -9, -9, 0, 0, -9, -9, 0, 0, 0, 0}}; + + char*p = s; + while(1) { + char*pnext = p+1; + int action; + double value = 0; + if(!stackpos) { + fprintf(stderr, "Error in expression\n"); + return 0.0; + } + + if(chr2index[*p]<0) { + action = table[stack[stackpos-1]][4]; + if(action>0) { + while(chr2index[*pnext]<0) + pnext++; + char save = *pnext; + *pnext = 0; + value = parseNameOrTwip(p); + *pnext = save; + } + } else { + action = table[stack[stackpos-1]][chr2index[*p]]; + } + + if(action == accept) { + return values[stack[stackpos-1]]; + } else if(action>0) { // shift + if(stackpos>254) { + fprintf(stderr, "Stack overflow while parsing expression\n"); + return 0.0; + } + values[stackpos]=value; + stack[stackpos++]=action; + p=pnext; + } else if(action<0) { // reduce + stackpos-=plen[-action]; + stack[stackpos] = table[stack[stackpos-1]][left[-action]]; + switch(-action) { + case 1: + values[stackpos] = values[stackpos+0] + values[stackpos+2]; + break; + case 2: + values[stackpos] = 0 - values[stackpos+1]; + break; + case 3: + values[stackpos] = values[stackpos+0] - values[stackpos+2]; + break; + case 5: + values[stackpos] = values[stackpos+0] * values[stackpos+2]; + break; + case 6: + values[stackpos] = values[stackpos+0] / values[stackpos+2]; + break; + case 9: + values[stackpos] = values[stackpos+1]; + break; + } + stackpos++; + } else { + fprintf(stderr, "Syntax error in expression\n"); + return 0.0; + } + } +} + +int parseTwip(char*str) +{ + int v = (int)(parseExpression(str)*20); + return v; +} + int parseArc(char* str) { if (!strcmp(str, "short")) @@ -2579,6 +2748,7 @@ static int c_flash(map_t*args) char* filename = map_lookup(args, "filename"); char* compressstr = lu(args, "compress"); char* change_modestr = lu(args, "change-sets-all"); + char* exportstr = lu(args, "export"); SRECT bbox = parseBox(lu(args, "bbox")); int version = parseInt(lu(args, "version")); int fps = (int)(parseFloat(lu(args, "fps"))*256); @@ -2613,6 +2783,8 @@ static int c_flash(map_t*args) if(strcmp(change_modestr, "no")) syntaxerror("value \"%s\" not supported for the change-sets-all argument", change_modestr); + do_exports=atoi(exportstr); + s_swf(filename, bbox, version, fps, compress, color); return 0; } @@ -2639,9 +2811,10 @@ int getSign(char*str) syntaxerror("internal error (348)"); return 0; } + static dictionary_t points; static mem_t mpoints; -int points_initialized = 0; +static int points_initialized = 0; static int c_interpolation(map_t *args) { @@ -2676,29 +2849,70 @@ SPOINT getPoint(SRECT r, char*name) { int l=0; if(!strcmp(name, "center")) { - SPOINT p; - p.x = (r.xmin + r.xmax)/2; - p.y = (r.ymin + r.ymax)/2; - return p; - } - if (!strcmp(name, "bottom-center")) - { - SPOINT p; - p.x = (r.xmin + r.xmax)/2; - p.y = r.ymax; - return p; + SPOINT p; + p.x = (r.xmin + r.xmax)/2; + p.y = (r.ymin + r.ymax)/2; + return p; + } + if (!strcmp(name, "bottom-center")) { + SPOINT p; + p.x = (r.xmin + r.xmax)/2; + p.y = r.ymax; + return p; + } + if (!strcmp(name, "top-center")) { + SPOINT p; + p.x = (r.xmin + r.xmax)/2; + p.y = r.ymin; + return p; + } + if (!strcmp(name, "top-left")) { + SPOINT p; + p.x = r.xmin; + p.y = r.ymin; + return p; + } + if (!strcmp(name, "top-right")) { + SPOINT p; + p.x = r.xmax; + p.y = r.ymin; + return p; + } + if (!strcmp(name, "bottom-right")) { + SPOINT p; + p.x = r.xmax; + p.y = r.ymax; + return p; + } + if (!strcmp(name, "bottom-left")) { + SPOINT p; + p.x = r.xmin; + p.y = r.ymax; + return p; + } + if (!strcmp(name, "left-center")) { + SPOINT p; + p.x = r.xmin; + p.y = (r.ymin + r.ymax)/2; + return p; + } + if (!strcmp(name, "right-center")) { + SPOINT p; + p.x = r.xmax; + p.y = (r.ymin + r.ymax)/2; + return p; } if(points_initialized) - l = (int)dictionary_lookup(&points, name); + l = (int)dictionary_lookup(&points, name); if(l==0) { - syntaxerror("Invalid point: \"%s\".", name); + syntaxerror("Invalid point: \"%s\".", name); } - l--; - return *(SPOINT*)&mpoints.buffer[l]; + return *(SPOINT*)&mpoints.buffer[l-1]; } + static int texture2(char*name, char*object, map_t*args, int errors) { SPOINT pos,size; @@ -2910,6 +3124,23 @@ static int c_bevel(map_t*args) return 0; } +static int c_define(map_t*args) +{ + char*name = lu(args, "name"); + char*value = lu(args, "value"); + + if(!defines_initialized) { + dictionary_init(&defines); + mem_init(&define_values); + defines_initialized = 1; + } + int val = parseTwip(value); + int pos = mem_put(&define_values, &val, sizeof(val)); + string_t s; + string_set(&s, name); + dictionary_put(&defines, s, (void*)(pos+1)); + return 0; +} static int c_point(map_t*args) { char*name = lu(args, "name"); @@ -2925,8 +3156,7 @@ static int c_point(map_t*args) p.y = parseTwip(lu(args, "y")); pos = mem_put(&mpoints, &p, sizeof(p)); string_set(&s1, name); - pos++; - dictionary_put(&points, s1, (void*)pos); + dictionary_put(&points, s1, (void*)(pos+1)); return 0; } static int c_play(map_t*args) @@ -3447,7 +3677,14 @@ static int c_end(map_t*args) static int c_sprite(map_t*args) { char* name = lu(args, "name"); - s_sprite(name); + char* scalinggrid = lu(args, "scalinggrid"); + + if(scalinggrid && *scalinggrid) { + SRECT r = parseBox(scalinggrid); + s_sprite(name, &r); + } else { + s_sprite(name, 0); + } return 0; } static int c_frame(map_t*args) @@ -3842,7 +4079,7 @@ static struct { command_func_t* func; char*arguments; } arguments[] = -{{"flash", c_flash, "bbox=autocrop background=black version=6 fps=50 name= filename= @compress=default @change-sets-all=no"}, +{{"flash", c_flash, "bbox=autocrop background=black version=6 fps=50 name= filename= @compress=default @change-sets-all=no @export=1"}, {"frame", c_frame, "n=1 name= @cut=no @anchor=no"}, // "import" type stuff {"swf", c_swf, "name filename"}, @@ -3857,6 +4094,7 @@ static struct { // generators of primitives + {"define", c_define, "name value=0"}, {"point", c_point, "name x=0 y=0"}, {"gradient", c_gradient, "name @radial=0 rotate=0 scale= scalex= scaley= x= y= width= height= r= shear="}, //extra parameters like .texture {"interpolation", c_interpolation, "name function=linear speed=1.3 amplitude=0 bounces=2 growth=1.5 damping=2 slope=0"}, @@ -3910,7 +4148,7 @@ static struct { // commands which start a block //startclip (see above) - {"sprite", c_sprite, "name"}, + {"sprite", c_sprite, "name scalinggrid="}, {"action", c_action, "filename="}, {"initaction", c_initaction, "name filename="}, @@ -4151,6 +4389,7 @@ static void analyseArgumentsForCommand(char*command) map_t args; char* fontfile; int nr = -1; + U8* glyphs_to_include; msg(" analyse Command: %s (line %d)", command, line); for(t=0;tuse->glyphs_specified = 1; + } + else + { + if (strcmp (glyphs_to_include, "")) + { + swf_FontUseUTF8(font, glyphs_to_include); + font->use->glyphs_specified = 1; + } + else + swf_FontInitUsage(font); + } + } dictionary_put2(&fonts, name, font); } else @@ -4190,10 +4447,16 @@ static void analyseArgumentsForCommand(char*command) if (!font) syntaxerror("font %s is not known in line %d", lu(&args, "font"), line); else - if (!strcmp(command, "edittext")) - swf_FontUseAll(font); - else - swf_FontUseUTF8(font, lu(&args, "text")); + if (font->use && !font->use->glyphs_specified) + { + if (!strcmp(command, "edittext")) + { + swf_FontUseAll(font); + font->use->glyphs_specified = 1; + } + else + swf_FontUseUTF8(font, lu(&args, "text")); + } } map_clear(&args); return;