X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=src%2Fswfbbox.c;h=138ad1ef3513ebcee1d7dd45f9317ffe73730736;hb=7d65cab745499277588a5ab47c336d218c7a7a31;hp=b3b8a7776341b020e7fee1b11968d80745439eb1;hpb=cd3c96f5d5aee5c64e7aaad2360d38e97cdc962f;p=swftools.git diff --git a/src/swfbbox.c b/src/swfbbox.c index b3b8a77..138ad1e 100644 --- a/src/swfbbox.c +++ b/src/swfbbox.c @@ -36,7 +36,8 @@ static int swifty = 0; static int verbose = 0; static int showbbox = 0; static int showorigbbox = 1; -static int expand = 1; +static int expand = 0; +static int clip = 0; static struct options_t options[] = { {"h", "help"}, @@ -45,6 +46,7 @@ static struct options_t options[] = { {"e", "expand"}, {"O", "optimize"}, {"S", "swifty"}, +{"c", "clip"}, {"o", "output"}, {"v", "verbose"}, {"V", "version"}, @@ -58,7 +60,7 @@ int args_callback_option(char*name,char*val) exit(0); } else if(!strcmp(name, "b")) { - showorigbbox = 1; + showorigbbox = 2; if(showbbox == 1) showbbox = 0; return 0; } @@ -68,12 +70,18 @@ int args_callback_option(char*name,char*val) } else if(!strcmp(name, "O")) { optimize = 1; - if(showbbox == 1) showbbox = 0; + if(showorigbbox == 1) showorigbbox = 0; return 0; } else if(!strcmp(name, "S")) { swifty = 1; - if(showbbox == 1) showbbox = 0; + if(showorigbbox == 1) showorigbbox = 0; + return 0; + } + else if(!strcmp(name, "c")) { + if(showorigbbox == 1) showorigbbox = 0; + optimize = 1; + clip = 1; return 0; } else if(!strcmp(name, "v")) { @@ -81,7 +89,8 @@ int args_callback_option(char*name,char*val) return 0; } else if(!strcmp(name, "q")) { - verbose --; + if(verbose) + verbose --; return 0; } else if(!strcmp(name, "e")) { @@ -114,6 +123,7 @@ void args_callback_usage(char *name) printf("-e , --expand Write out a new file using the recalculated bounding box\n"); printf("-O , --optimize Recalculate bounding boxes\n"); printf("-S , --swifty Print out transformed bounding boxes\n"); + printf("-c , --clip Clip bounding boxes to movie size\n"); printf("-o , --output Set output filename to (for -O)\n"); printf("-v , --verbose Be more verbose\n"); printf("-V , --version Print program version and exit\n"); @@ -152,6 +162,8 @@ int hasid(TAG*tag) return 1; if(tag->id == ST_PLACEOBJECT2 && (tag->data[0] & 2)) return 1; + if(tag->id == ST_PLACEOBJECT3 && (tag->data[0] & 2)) + return 1; return 0; } @@ -161,6 +173,8 @@ int hasname(TAG*tag) return 0; if(tag->id == ST_PLACEOBJECT2 && (tag->data[0] & 0x20)) return 1; + if(tag->id == ST_PLACEOBJECT3 && (tag->data[0] & 0x20)) + return 1; return 0; } @@ -174,6 +188,12 @@ char* getname(TAG*tag) swf_GetPlaceObject(tag, &o); return o.name; } + if(tag->id == ST_PLACEOBJECT3 && (tag->data[0] & 0x20)) { + SWFPLACEOBJECT o; + tag->pos = 0;tag->readBit = 0; + swf_GetPlaceObject(tag, &o); + return o.name; + } return 0; } @@ -209,6 +229,121 @@ typedef struct _textbounds MATRIX m; // character transform matrix } textbounds_t; +typedef struct _placement +{ + SWFPLACEOBJECT* po; + int num; +} placement_t; + +static placement_t* placements; + +static placement_t* readPlacements(SWF*swf) +{ + placement_t* p = (placement_t*)rfx_calloc(sizeof(placement_t)*65536); + TAG*tag = swf->firstTag; + while(tag) { + if(swf_isPlaceTag(tag)) { + SWFPLACEOBJECT*po = rfx_alloc(sizeof(SWFPLACEOBJECT)); + int id; + swf_GetPlaceObject(tag, po); + id = po->id; + if(po->move) { + fprintf(stderr, "MOVE tags not supported with -c"); + } + p[id].po = po; + p[id].num++; + } + tag = tag->next; + } + + return p; +} + +static void freePlacements(placement_t*p) +{ + int t; + for(t=0;t<65536;t++) { + if(p[t].po) { + swf_PlaceObjectFree(p[t].po); p[t].po = 0; + } + } + rfx_free(p); +} + +SRECT swf_ClipRect(SRECT border, SRECT r) +{ + if(r.xmax > border.xmax) r.xmax = border.xmax; + if(r.ymax > border.ymax) r.ymax = border.ymax; + if(r.xmax < border.xmin) r.xmax = border.xmin; + if(r.ymax < border.ymin) r.ymax = border.ymin; + + if(r.xmin > border.xmax) r.xmin = border.xmax; + if(r.ymin > border.ymax) r.ymin = border.ymax; + if(r.xmin < border.xmin) r.xmin = border.xmin; + if(r.ymin < border.ymin) r.ymin = border.ymin; + return r; +} + +static SRECT clipBBox(TAG*tag, SRECT mbbox, SRECT r) +{ + int id = swf_GetDefineID(tag); + MATRIX m; + if(!placements[id].po) { + if(verbose) + printf("Id %d is never set\n", id); + return r; + } + if(placements[id].num>1) { + if(verbose) + printf("Id %d is set more than once\n", id); + return r; + } + m = placements[id].po->matrix; + if(m.r0 || m.r1) { + fprintf(stderr, "Rotating PLACEOBJECTS are not supported with -c\n"); + return r; + } + + if(verbose) { + printf("ID %d\n", id); + swf_DumpMatrix(stdout, &m); + } + mbbox.xmin -= m.tx; + mbbox.ymin -= m.ty; + mbbox.xmax -= m.tx; + mbbox.ymax -= m.ty; + mbbox.xmin *= 65536.0/m.sx; + mbbox.xmax *= 65536.0/m.sx; + mbbox.ymin *= 65536.0/m.sy; + mbbox.ymax *= 65536.0/m.sy; + + if(verbose) { + printf("border: %f/%f/%f/%f - rect: %f/%f/%f/%f\n", + mbbox.xmin /20.0, + mbbox.ymin /20.0, + mbbox.xmax /20.0, + mbbox.ymax /20.0, + r.xmin /20.0, + r.ymin /20.0, + r.xmax /20.0, + r.ymax /20.0); + } + + + r = swf_ClipRect(mbbox, r); + + if(verbose) { + printf("new rect: %f/%f/%f/%f\n", + r.xmin /20.0, + r.ymin /20.0, + r.xmax /20.0, + r.ymax /20.0); + } + + return r; +} + + static void textcallback(void*self, int*chars, int*xpos, int nr, int fontid, int fontsize, int xstart, int ystart, RGBA* color) { @@ -238,7 +373,7 @@ static void textcallback(void*self, int*chars, int*xpos, int nr, int fontid, int /* not tested yet- the matrix/fontsize calculation is probably all wrong */ int x = xstart + xpos[t]; int y = ystart; - int ch; + int ch = 0; SRECT newglyphbbox, glyphbbox = font->layout->bounds[chars[t]]; MATRIX m = bounds->m; SPOINT p; @@ -280,13 +415,21 @@ static void swf_OptimizeBoundingBoxes(SWF*swf) while (tag) { if (tag->id == ST_DEFINESHAPE || tag->id == ST_DEFINESHAPE2 || - tag->id == ST_DEFINESHAPE3) { + tag->id == ST_DEFINESHAPE3 || + tag->id == ST_DEFINESHAPE4) { SHAPE2 s; if(verbose) printf("%s\n", swf_TagGetName(tag)); swf_ParseDefineShape(tag, &s); swf_Shape2Optimize(&s); tag->len = 2; tag->pos = 0; + if(!s.bbox) { + fprintf(stderr, "Internal error (5)\n"); + exit(1); + } + if(clip) { + *s.bbox = clipBBox(tag, swf->movieSize, *s.bbox); + } swf_SetShape2(tag, &s); } if (tag->id == ST_DEFINETEXT || tag->id == ST_DEFINETEXT2) { @@ -322,6 +465,9 @@ static void swf_OptimizeBoundingBoxes(SWF*swf) printf("old: %d %d %d %d\n", oldbox.xmin, oldbox.ymin, oldbox.xmax, oldbox.ymax); printf("new: %d %d %d %d\n", bounds.r.xmin, bounds.r.ymin, bounds.r.xmax, bounds.r.ymax); } + if(clip) { + bounds.r = clipBBox(tag, swf->movieSize, bounds.r); + } /* now comes the tricky part: we have to fiddle the data back in @@ -352,7 +498,7 @@ static void showSwiftyOutput(SWF*swf) if (tag->id == ST_SHOWFRAME) { printf("}\n{\n\t{frame %d}\n", frame++); } - if (tag->id == ST_PLACEOBJECT || tag->id == ST_PLACEOBJECT2) { + if (swf_isPlaceTag(tag)) { if(hasid(tag)) { depth2id[swf_GetDepth(tag)] = swf_GetPlaceID(tag); } @@ -360,7 +506,7 @@ static void showSwiftyOutput(SWF*swf) depth2name[swf_GetDepth(tag)] = getname(tag); } } - if (tag->id == ST_PLACEOBJECT || tag->id == ST_PLACEOBJECT2) { + if (swf_isPlaceTag(tag)) { MATRIX m = getmatrix(tag); U16 id = depth2id[swf_GetDepth(tag)]; char*name = depth2name[swf_GetDepth(tag)]; @@ -398,12 +544,12 @@ static SRECT getMovieClipBBox(TAG*tag) memset(&movieSize,0,sizeof(SRECT)); while (tag->id != ST_END) { - if (tag->id == ST_PLACEOBJECT || tag->id == ST_PLACEOBJECT2) { + if (swf_isPlaceTag(tag)) { if(hasid(tag)) { depth2id[swf_GetDepth(tag)] = swf_GetPlaceID(tag); } } - if (tag->id == ST_PLACEOBJECT || tag->id == ST_PLACEOBJECT2) { + if (swf_isPlaceTag(tag)) { MATRIX m = getmatrix(tag); U16 id = depth2id[swf_GetDepth(tag)]; SRECT bbox = bboxes[id]; @@ -457,6 +603,11 @@ int main (int argc,char ** argv) close(fi); swf_OptimizeTagOrder(&swf); + + if(clip) { + placements = readPlacements(&swf); + } + swf_FoldAll(&swf); /* Optimize bounding boxes in case -O flag was set */ @@ -529,5 +680,9 @@ int main (int argc,char ** argv) } swf_FreeTags(&swf); + + if(placements) { + freePlacements(placements); + } return 0; }