added showclipshapes option
[swftools.git] / lib / devices / swf.c
index e7a03ac..24b090a 100644 (file)
@@ -79,12 +79,14 @@ typedef struct _swfoutput_internal
     int config_insertstoptag;
     int config_flashversion;
     int config_reordertags;
+    int config_showclipshapes;
     int config_splinemaxerror;
     int config_fontsplinemaxerror;
     int config_filloverlap;
     int config_protect;
     int config_bboxvars;
     int config_disable_polygon_conversion;
+    int config_normalize_polygon_positions;
     RGBA config_linkcolor;
     float config_minlinewidth;
     double config_caplinewidth;
@@ -177,7 +179,7 @@ static void swf_fillbitmap(gfxdevice_t*dev, gfxline_t*line, gfximage_t*img, gfxm
 static void swf_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*matrix);
 static void swf_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyph, gfxcolor_t*color, gfxmatrix_t*matrix);
 static void swf_addfont(gfxdevice_t*dev, gfxfont_t*font);
-static void swf_drawlink(gfxdevice_t*dev, gfxline_t*line, char*action);
+static void swf_drawlink(gfxdevice_t*dev, gfxline_t*line, const char*action);
 static void swf_startframe(gfxdevice_t*dev, int width, int height);
 static void swf_endframe(gfxdevice_t*dev);
 static gfxresult_t* swf_finish(gfxdevice_t*driver);
@@ -234,6 +236,7 @@ static swfoutput_internal* init_internal_struct()
     i->config_filloverlap=0;
     i->config_protect=0;
     i->config_bboxvars=0;
+    i->config_showclipshapes=0;
     i->config_minlinewidth=0.05;
     i->config_caplinewidth=1;
     i->config_linktarget=0;
@@ -1249,11 +1252,11 @@ void swfoutput_finalize(gfxdevice_t*dev)
        i->swf->compressed = 1;
     }
 
-    if(i->config_reordertags)
-       swf_Optimize(i->swf);
+//    if(i->config_reordertags)
+//     swf_Optimize(i->swf);
 }
 
-int swfresult_save(gfxresult_t*gfx, char*filename)
+int swfresult_save(gfxresult_t*gfx, const char*filename)
 {
     SWF*swf = (SWF*)gfx->internal;
     int fi;
@@ -1279,7 +1282,7 @@ int swfresult_save(gfxresult_t*gfx, char*filename)
      close(fi);
     return 0;
 }
-void* swfresult_get(gfxresult_t*gfx, char*name)
+void* swfresult_get(gfxresult_t*gfx, const char*name)
 {
     SWF*swf = (SWF*)gfx->internal;
     if(!strcmp(name, "swf")) {
@@ -1408,15 +1411,15 @@ static void swfoutput_setlinewidth(gfxdevice_t*dev, double _linewidth)
 static void drawlink(gfxdevice_t*dev, ActionTAG*,ActionTAG*, gfxline_t*points, char mouseover);
 static void swfoutput_namedlink(gfxdevice_t*dev, char*name, gfxline_t*points);
 static void swfoutput_linktopage(gfxdevice_t*dev, int page, gfxline_t*points);
-static void swfoutput_linktourl(gfxdevice_t*dev, char*url, gfxline_t*points);
+static void swfoutput_linktourl(gfxdevice_t*dev, const char*url, gfxline_t*points);
 
-void swfoutput_drawlink(gfxdevice_t*dev, char*url, gfxline_t*points)
+/*void swfoutput_drawlink(gfxdevice_t*dev, char*url, gfxline_t*points)
 {
     swfoutput_internal*i = (swfoutput_internal*)dev->internal;
     dev->drawlink(dev, points, url);
-}
+}*/
 
-void swf_drawlink(gfxdevice_t*dev, gfxline_t*points, char*url)
+void swf_drawlink(gfxdevice_t*dev, gfxline_t*points, const char*url)
 {
     swfoutput_internal*i = (swfoutput_internal*)dev->internal;
 
@@ -1442,7 +1445,7 @@ void swf_drawlink(gfxdevice_t*dev, gfxline_t*points, char*url)
        swfoutput_linktourl(dev, url, points);
     }
 }
-void swfoutput_linktourl(gfxdevice_t*dev, char*url, gfxline_t*points)
+void swfoutput_linktourl(gfxdevice_t*dev, const char*url, gfxline_t*points)
 {
     ActionTAG* actions = 0;
     swfoutput_internal*i = (swfoutput_internal*)dev->internal;
@@ -1774,14 +1777,21 @@ 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, "showclipshapes")) {
+       i->config_showclipshapes = 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")) {
        i->config_externallinkfunction = strdup(value);
+    } else if(!strcmp(name, "linkfunction")) { //sets both internallinkfunction and externallinkfunction
+       i->config_internallinkfunction = strdup(value);
+       i->config_externallinkfunction = strdup(value);
     } else if(!strcmp(name, "disable_polygon_conversion")) {
        i->config_disable_polygon_conversion = atoi(value);
+    } else if(!strcmp(name, "normalize_polygon_positions")) {
+       i->config_normalize_polygon_positions = atoi(value);
     } else if(!strcmp(name, "insertstop")) {
        i->config_insertstoptag = atoi(value);
     } else if(!strcmp(name, "protect")) {
@@ -1816,7 +1826,7 @@ int swf_setparameter(gfxdevice_t*dev, const char*name, const char*value)
     } else if(!strcmp(name, "jpegquality")) {
        int val = atoi(value);
        if(val<0) val=0;
-       if(val>100) val=100;
+       if(val>101) val=101;
        i->config_jpegquality = val;
     } else if(!strcmp(name, "splinequality")) {
        int v = atoi(value);
@@ -2039,6 +2049,34 @@ static void swf_fillbitmap(gfxdevice_t*dev, gfxline_t*line, gfximage_t*img, gfxm
     swf_ObjectPlace(i->tag,myshapeid,getNewDepth(dev),&i->page_matrix,&cxform2,NULL);
 }
 
+static RGBA col_black = {255,0,0,0};
+
+static void drawoutline(gfxdevice_t*dev, gfxline_t*line)
+{
+    swfoutput_internal*i = (swfoutput_internal*)dev->internal;
+
+    int myshapeid = getNewID(dev);
+    i->tag = swf_InsertTag(i->tag,ST_DEFINESHAPE3);
+
+    SHAPE*shape;
+    swf_ShapeNew(&shape);
+    int lsid = swf_ShapeAddLineStyle(shape,1,&col_black);
+
+    swf_SetU16(i->tag,myshapeid);
+    SRECT r = gfxline_getSWFbbox(line);
+    swf_SetRect(i->tag,&r);
+    swf_SetShapeStyles(i->tag,shape);
+    swf_ShapeCountBits(shape,NULL,NULL);
+    swf_SetShapeBits(i->tag,shape);
+    swf_ShapeSetAll(i->tag,shape,UNDEFINED_COORD,UNDEFINED_COORD,lsid,0,0);
+    drawgfxline(dev, line);
+    swf_ShapeSetEnd(i->tag);
+    swf_ShapeFree(shape);
+       
+    i->tag = swf_InsertTag(i->tag,ST_PLACEOBJECT2);
+    swf_ObjectPlace(i->tag, myshapeid, getNewDepth(dev), 0,0,0);
+}
+
 static void swf_startclip(gfxdevice_t*dev, gfxline_t*line)
 {
     swfoutput_internal*i = (swfoutput_internal*)dev->internal;
@@ -2052,6 +2090,9 @@ static void swf_startclip(gfxdevice_t*dev, gfxline_t*line)
         i->clippos --;
     } 
 
+    if(i->config_showclipshapes)
+       drawoutline(dev, line);
+
     int myshapeid = getNewID(dev);
     i->tag = swf_InsertTag(i->tag,ST_DEFINESHAPE3);
     RGBA col;
@@ -2072,7 +2113,16 @@ static void swf_startclip(gfxdevice_t*dev, gfxline_t*line)
     swf_SetShapeBits(i->tag,shape);
     swf_ShapeSetAll(i->tag,shape,UNDEFINED_COORD,UNDEFINED_COORD,0,fsid,0);
     i->swflastx = i->swflasty = UNDEFINED_COORD;
+    i->shapeisempty = 1;
     drawgfxline(dev, line);
+    if(i->shapeisempty) {
+       /* an empty clip shape is equivalent to a shape with no area */
+       int x = line?line->x:0;
+       int y = line?line->y:0;
+       moveto(dev, i->tag, x,y);
+       lineto(dev, i->tag, x,y);
+       lineto(dev, i->tag, x,y);
+    }
     swf_ShapeSetEnd(i->tag);
     swf_ShapeFree(shape);
 
@@ -2259,17 +2309,17 @@ static void swf_stroke(gfxdevice_t*dev, gfxline_t*line, gfxcoord_t width, gfxcol
     msg("<trace> draw as stroke, type=%d dots=%d", type, has_dots);
     endtext(dev);
 
-#ifdef NORMALIZE_POLYGON_POSITIONS
-    endshape(dev);
-    double startx = 0, starty = 0;
-    if(line && line->type == gfx_moveTo) {
-       startx = line->x;
-       starty = line->y;
-    }
-    line = gfxline_move(line, -startx, -starty);
-    i->shapeposx = (int)(startx*20);
-    i->shapeposy = (int)(starty*20);
-#endif
+    if(i->config_normalize_polygon_positions) {
+       endshape(dev);
+       double startx = 0, starty = 0;
+       if(line && line->type == gfx_moveTo) {
+           startx = line->x;
+           starty = line->y;
+       }
+       line = gfxline_move(line, -startx, -starty);
+       i->shapeposx = (int)(startx*20);
+       i->shapeposy = (int)(starty*20);
+    }
 
     swfoutput_setstrokecolor(dev, color->r, color->g, color->b, color->a);
     swfoutput_setlinewidth(dev, width);
@@ -2277,9 +2327,9 @@ static void swf_stroke(gfxdevice_t*dev, gfxline_t*line, gfxcoord_t width, gfxcol
     stopFill(dev);
     drawgfxline(dev, line);
 
-#ifdef NORMALIZE_POLYGON_POSITIONS
-    free(line); //account for _move
-#endif
+    if(i->config_normalize_polygon_positions) {
+       free(line); //account for _move
+    }
 
 }
 static void swf_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color)
@@ -2296,17 +2346,17 @@ static void swf_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color)
     if(!i->config_ignoredraworder)
        endshape(dev);
 
-#ifdef NORMALIZE_POLYGON_POSITIONS
-    endshape(dev);
-    double startx = 0, starty = 0;
-    if(line && line->type == gfx_moveTo) {
-       startx = line->x;
-       starty = line->y;
-    }
-    line = gfxline_move(line, -startx, -starty);
-    i->shapeposx = (int)(startx*20);
-    i->shapeposy = (int)(starty*20);
-#endif
+    if(i->config_normalize_polygon_positions) {
+       endshape(dev);
+       double startx = 0, starty = 0;
+       if(line && line->type == gfx_moveTo) {
+           startx = line->x;
+           starty = line->y;
+       }
+       line = gfxline_move(line, -startx, -starty);
+       i->shapeposx = (int)(startx*20);
+       i->shapeposy = (int)(starty*20);
+    }
 
     swfoutput_setfillcolor(dev, color->r, color->g, color->b, color->a);
     startshape(dev);
@@ -2315,9 +2365,9 @@ static void swf_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color)
     drawgfxline(dev, line);
     msg("<trace> end of swf_fill (shapeid=%d)", i->shapeid);
 
-#ifdef NORMALIZE_POLYGON_POSITIONS
-    free(line); //account for _move
-#endif
+    if(i->config_normalize_polygon_positions) {
+       free(line); //account for _move
+    }
 }
 static void swf_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*matrix)
 {
@@ -2326,7 +2376,7 @@ static void swf_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*grad
     msg("<error> Gradient filling not implemented yet");
 }
 
-static SWFFONT* gfxfont_to_swffont(gfxfont_t*font, char* id)
+static SWFFONT* gfxfont_to_swffont(gfxfont_t*font, const char* id)
 {
     SWFFONT*swffont = (SWFFONT*)rfx_calloc(sizeof(SWFFONT));
     int t;
@@ -2467,7 +2517,7 @@ static void swf_addfont(gfxdevice_t*dev, gfxfont_t*font)
     }
 }
 
-static void swf_switchfont(gfxdevice_t*dev, char*fontid)
+static void swf_switchfont(gfxdevice_t*dev, const char*fontid)
 {
     swfoutput_internal*i = (swfoutput_internal*)dev->internal;
 
@@ -2501,7 +2551,7 @@ static void swf_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyph, gfxcolor_t*
        swf_switchfont(dev, font->id); // set the current font
     }
     setfontscale(dev, matrix->m00, matrix->m01, matrix->m10, matrix->m11);
-   
+
 /*    printf("%f %f\n", m.m31,  m.m32);
     {
     static int xpos = 40;