new config option "animate"
[swftools.git] / lib / devices / swf.c
index 86b2e2c..83a5e67 100644 (file)
@@ -78,6 +78,7 @@ typedef struct _swfoutput_internal
     int config_enablezlib;
     int config_insertstoptag;
     int config_flashversion;
+    int config_reordertags;
     int config_splinemaxerror;
     int config_fontsplinemaxerror;
     int config_filloverlap;
@@ -90,6 +91,7 @@ typedef struct _swfoutput_internal
     char* config_linktarget;
     char*config_internallinkfunction;
     char*config_externallinkfunction;
+    char config_animate;
 
     SWF* swf;
 
@@ -234,6 +236,7 @@ static swfoutput_internal* init_internal_struct()
     i->config_linktarget=0;
     i->config_internallinkfunction=0;
     i->config_externallinkfunction=0;
+    i->config_reordertags=1;
 
     i->config_linkcolor.r = i->config_linkcolor.g = i->config_linkcolor.b = 255;
     i->config_linkcolor.a = 0x40;
@@ -247,8 +250,10 @@ static U16 getNewID(gfxdevice_t* dev)
 {
     swfoutput_internal*i = (swfoutput_internal*)dev->internal;
     if(i->currentswfid == 65535) {
-       if(!id_error)
+       if(!id_error) {
            msg("<error> ID Table overflow");
+           msg("<error> This file is too complex to render- SWF only supports 65536 shapes at once");
+       }
        id_error=1;
        i->overflow = 1;
        exit(1);
@@ -259,8 +264,10 @@ static U16 getNewDepth(gfxdevice_t* dev)
 {
     swfoutput_internal*i = (swfoutput_internal*)dev->internal;
     if(i->depth == 65535) {
-       if(!id_error)
+       if(!id_error) {
            msg("<error> Depth Table overflow");
+           msg("<error> This file is too complex to render- SWF only supports 65536 shapes at once");
+       }
        id_error=1;
        i->overflow = 1;
        exit(1);
@@ -734,8 +741,20 @@ static void endtext(gfxdevice_t*dev)
 
     putcharacters(dev, i->tag);
     swf_SetU8(i->tag,0);
-    i->tag = swf_InsertTag(i->tag,ST_PLACEOBJECT2);
 
+    if(i->swf->fileVersion >= 8) {
+       i->tag = swf_InsertTag(i->tag, ST_CSMTEXTSETTINGS);
+       swf_SetU16(i->tag, i->textid);
+       //swf_SetU8(i->tag, /*subpixel grid*/(2<<3)|/*flashtype*/0x40);
+       //swf_SetU8(i->tag, /*grid*/(1<<3)|/*flashtype*/0x40);
+       //swf_SetU8(i->tag, /*grid*/(0<<3)|/*flashtype*/0x40);
+       swf_SetU8(i->tag, /*grid*/(1<<3)|/*no flashtype*/0x00);
+       swf_SetU32(i->tag, 0);//thickness
+       swf_SetU32(i->tag, 0);//sharpness
+       swf_SetU8(i->tag, 0);//reserved
+    }
+    i->tag = swf_InsertTag(i->tag,ST_PLACEOBJECT2);
+    
     swf_ObjectPlace(i->tag,i->textid,getNewDepth(dev),&i->page_matrix,NULL,NULL);
     i->textid = -1;
 }
@@ -873,6 +892,9 @@ static void setBackground(gfxdevice_t*dev, int x1, int y1, int x2, int y2)
 void gfxdevice_swf_init(gfxdevice_t* dev)
 {
     memset(dev, 0, sizeof(gfxdevice_t));
+    
+    dev->name = "swf";
+
     dev->internal = init_internal_struct();
 
     dev->startpage = swf_startframe;
@@ -1102,7 +1124,7 @@ static void endshape(gfxdevice_t*dev)
 
     changeRect(dev, i->tag, i->bboxrectpos, &i->bboxrect);
 
-    msg("<trace> Placing shape id %d", i->shapeid);
+    msg("<trace> Placing shape ID %d", i->shapeid);
 
     i->tag = swf_InsertTag(i->tag,ST_PLACEOBJECT2);
     MATRIX m = i->page_matrix;
@@ -1110,6 +1132,10 @@ static void endshape(gfxdevice_t*dev)
     m.ty += i->shapeposy;
     swf_ObjectPlace(i->tag,i->shapeid,getNewDepth(dev),&m,NULL,NULL);
 
+    if(i->config_animate) {
+       i->tag = swf_InsertTag(i->tag,ST_SHOWFRAME);
+    }
+
     swf_ShapeFree(i->shape);
     i->shape = 0;
     i->shapeid = -1;
@@ -1211,6 +1237,9 @@ void swfoutput_finalize(gfxdevice_t*dev)
     if(i->config_enablezlib || i->config_flashversion>=6) {
        i->swf->compressed = 1;
     }
+
+    if(i->config_reordertags)
+       swf_Optimize(i->swf);
 }
 
 int swfresult_save(gfxresult_t*gfx, char*filename)
@@ -1511,24 +1540,23 @@ static void drawgfxline(gfxdevice_t*dev, gfxline_t*line)
     swfoutput_internal*i = (swfoutput_internal*)dev->internal;
     gfxcoord_t lastx=0,lasty=0,px=0,py=0;
     char lastwasmoveto;
+    int lines= 0, splines=0;
     while(1) {
        if(!line)
            break;
        /* check whether the next segment is zero */
        if(line->type == gfx_moveTo) {
-           msg("<trace> ======== moveTo %.2f %.2f", line->x, line->y);
            moveto(dev, i->tag, line->x, line->y);
            px = lastx = line->x;
            py = lasty = line->y;
            lastwasmoveto = 1;
        } if(line->type == gfx_lineTo) {
-           msg("<trace> ======== lineTo %.2f %.2f", line->x, line->y);
            lineto(dev, i->tag, line->x, line->y);
            px = line->x;
            py = line->y;
            lastwasmoveto = 0;
+           lines++;
        } else if(line->type == gfx_splineTo) {
-           msg("<trace> ======== splineTo  %.2f %.2f", line->x, line->y);
            plotxy_t s,p;
            s.x = line->sx;p.x = line->x;
            s.y = line->sy;p.y = line->y;
@@ -1536,9 +1564,11 @@ static void drawgfxline(gfxdevice_t*dev, gfxline_t*line)
            px = line->x;
            py = line->y;
            lastwasmoveto = 0;
+           splines++;
        }
        line = line->next;
     }
+    msg("<trace> drawgfxline, %d lines, %d splines", lines, splines);
 }
 
 
@@ -1636,6 +1666,7 @@ static void drawlink(gfxdevice_t*dev, ActionTAG*actions1, ActionTAG*actions2, gf
        }
     }
     
+    msg("<trace> Placing link ID %d", buttonid);
     i->tag = swf_InsertTag(i->tag,ST_PLACEOBJECT2);
 
     if(posx!=0 || posy!=0) {
@@ -1732,6 +1763,8 @@ int swf_setparameter(gfxdevice_t*dev, const char*name, const char*value)
        i->config_enablezlib = atoi(value);
     } else if(!strcmp(name, "bboxvars")) {
        i->config_bboxvars = atoi(value);
+    } else if(!strcmp(name, "reordertags")) {
+       i->config_reordertags = atoi(value);
     } else if(!strcmp(name, "internallinkfunction")) {
        i->config_internallinkfunction = strdup(value);
     } else if(!strcmp(name, "externallinkfunction")) {
@@ -1760,6 +1793,8 @@ int swf_setparameter(gfxdevice_t*dev, const char*name, const char*value)
        i->config_linktarget = strdup(value);
     } else if(!strcmp(name, "dumpfonts")) {
        i->config_dumpfonts = atoi(value);
+    } else if(!strcmp(name, "animate")) {
+       i->config_animate = atoi(value);
     } else if(!strcmp(name, "next_bitmap_is_jpeg")) {
        i->jpeg = 1;
     } else if(!strcmp(name, "jpegquality")) {
@@ -1794,7 +1829,6 @@ int swf_setparameter(gfxdevice_t*dev, const char*name, const char*value)
            i->config_linkcolor.a);
 
     } else {
-       fprintf(stderr, "unknown parameter: %s (=%s)\n", name, value);
        return 0;
     }
     return 1;
@@ -1818,10 +1852,10 @@ static CXFORM gfxcxform_to_cxform(gfxcxform_t* c)
     cx.r0 = (S16)(c->rr*256);
     cx.g0 = (S16)(c->gg*256);
     cx.b0 = (S16)(c->bb*256);
-    cx.a1 = c->t.a;
-    cx.r1 = c->t.r;
-    cx.g1 = c->t.g;
-    cx.b1 = c->t.b;
+    cx.a1 = c->ta;
+    cx.r1 = c->tr;
+    cx.g1 = c->tg;
+    cx.b1 = c->tb;
     return cx;
 }
 
@@ -1849,16 +1883,20 @@ static int add_image(swfoutput_internal*i, gfximage_t*img, int targetwidth, int
 
     /// {
     if(is_jpeg && i->config_jpegsubpixels) {
-       newsizex = (int)(targetwidth*i->config_jpegsubpixels+0.5);
-       newsizey = (int)(targetheight*i->config_jpegsubpixels+0.5);
+       newsizex = (int)(targetwidth*i->config_jpegsubpixels + 0.5);
+       newsizey = (int)(targetheight*i->config_jpegsubpixels + 0.5);
     } else if(!is_jpeg && i->config_ppmsubpixels) {
-       newsizex = (int)(targetwidth*i->config_ppmsubpixels+0.5);
-       newsizey = (int)(targetheight*i->config_ppmsubpixels+0.5);
+       newsizex = (int)(targetwidth*i->config_ppmsubpixels + 0.5);
+       newsizey = (int)(targetheight*i->config_ppmsubpixels + 0.5);
     }
     /// }
 
-    if(sizex<=0 || sizey<=0 || newsizex<=0 || newsizey<=0)
+    if(sizex<=0 || sizey<=0)
        return -1;
+    if(newsizex<=0)
+       newsizex = 1;
+    if(newsizey<=0)
+       newsizey = 1;
 
     /* TODO: cache images */
     
@@ -1876,10 +1914,10 @@ static int add_image(swfoutput_internal*i, gfximage_t*img, int targetwidth, int
     int num_colors = swf_ImageGetNumberOfPaletteEntries(mem,sizex,sizey,0);
     int has_alpha = swf_ImageHasAlpha(mem,sizex,sizey);
     
-    msg("<verbose> Drawing %dx%d %s%simage at size %dx%d (%dx%d), %s%d colors",
+    msg("<verbose> Drawing %dx%d %s%simage (id %d) at size %dx%d (%dx%d), %s%d colors",
            sizex, sizey, 
            has_alpha?(has_alpha==2?"semi-transparent ":"transparent "):"", 
-           is_jpeg?"jpeg-":"",
+           is_jpeg?"jpeg-":"", i->currentswfid+1,
            newsizex, newsizey,
            targetwidth, targetheight,
            /*newsizex, newsizey,*/
@@ -1979,6 +2017,7 @@ static void swf_fillbitmap(gfxdevice_t*dev, gfxline_t*line, gfximage_t*img, gfxm
     swf_ShapeSetEnd(i->tag);
     swf_ShapeFree(shape);
 
+    msg("<trace> Placing bitmap ID %d", myshapeid);
     i->tag = swf_InsertTag(i->tag,ST_PLACEOBJECT2);
     CXFORM cxform2 = gfxcxform_to_cxform(cxform);
     swf_ObjectPlace(i->tag,myshapeid,getNewDepth(dev),&i->page_matrix,&cxform2,NULL);
@@ -2001,6 +2040,7 @@ static void swf_startclip(gfxdevice_t*dev, gfxline_t*line)
     i->tag = swf_InsertTag(i->tag,ST_DEFINESHAPE3);
     RGBA col;
     memset(&col, 0, sizeof(RGBA));
+    col.a = 255;
     SHAPE*shape;
     swf_ShapeNew(&shape);
     int fsid = swf_ShapeAddSolidFillStyle(shape,&col);
@@ -2022,6 +2062,7 @@ static void swf_startclip(gfxdevice_t*dev, gfxline_t*line)
 
     /* TODO: remember the bbox, and check all shapes against it */
     
+    msg("<trace> Placing clip ID %d", myshapeid);
     i->tag = swf_InsertTag(i->tag,ST_PLACEOBJECT2);
     i->cliptags[i->clippos] = i->tag;
     i->clipshapes[i->clippos] = myshapeid;
@@ -2230,6 +2271,8 @@ static void swf_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color)
     swfoutput_internal*i = (swfoutput_internal*)dev->internal;
     if(line_is_empty(line))
        return;
+    if(!color->a)
+       return;
     gfxbbox_t r = gfxline_getbbox(line);
     int is_outside_page = !is_inside_page(dev, r.xmin, r.ymin) || !is_inside_page(dev, r.xmax, r.ymax);