fixed font layout code (again)
[swftools.git] / lib / devices / swf.c
index 6027af2..087433b 100644 (file)
@@ -155,6 +155,8 @@ typedef struct _swfoutput_internal
     int bboxrectpos;
     SRECT bboxrect;
 
+    SRECT pagebbox;
+
     chardata_t chardata[CHARDATAMAX];
     int chardatapos;
     int firstpage;
@@ -703,7 +705,7 @@ static void endtext(gfxdevice_t*dev)
 
     SRECT r;
     r = getcharacterbbox(dev, i->swffont, &i->fontmatrix);
-    
+    r = swf_ClipRect(i->pagebbox, r);
     swf_SetRect(i->tag,&r);
 
     swf_SetMatrix(i->tag,&i->fontmatrix);
@@ -760,8 +762,8 @@ static void setfontscale(gfxdevice_t*dev,double m11,double m12, double m21,doubl
     double ifs = 1.0 / (i->current_font_size*GLYPH_SCALE);
 
     MATRIX m;
-    m.sx = (U32)((m11*ifs)*65536); m.r1 = (U32)((m21*ifs)*65536);
-    m.r0 = (U32)((m12*ifs)*65536); m.sy = (U32)((m22*ifs)*65536); 
+    m.sx = (S32)((m11*ifs)*65536); m.r1 = (S32)((m21*ifs)*65536);
+    m.r0 = (S32)((m12*ifs)*65536); m.sy = (S32)((m22*ifs)*65536); 
     /* this is the position of the first char to set a new fontmatrix-
        we hope that it's close enough to all other characters using the
        font, so we use its position as origin for the matrix */
@@ -791,9 +793,9 @@ static void draw_watermark(gfxdevice_t*dev, gfxbbox_t r, char drawall)
        for(y=0;y<watermark2_height;y++)
        for(x=0;x<watermark2_width;x++) {
            if(((watermark2[x]>>y)&1)) {
-               if(!drawall && lrand48()%5)
+               if(!drawall && rand()%5)
                    continue;
-               unsigned int b = lrand48();
+               unsigned int b = rand();
                moveto(dev, i->tag, x*sx+tx+((b>>1)&1)/20.0, y*sy+ty+((b>>3)&1)/20.0);
                lineto(dev, i->tag, x*sx+px+tx+((b>>2)&1)/20.0, y*sy+ty+((b>>3)&1)/20.0);
                lineto(dev, i->tag, x*sx+px+tx+((b>>2)&1)/20.0, y*sy+py+ty+((b>>4)&1)/20.0);
@@ -830,7 +832,7 @@ static void insert_watermark(gfxdevice_t*dev, char drawall)
     if(drawall) {
        swfoutput_setfillcolor(dev, 0,0,255,192);
     } else {
-       swfoutput_setfillcolor(dev, lrand48(),lrand48(),lrand48(),(lrand48()&127)+128);
+       swfoutput_setfillcolor(dev, rand(),rand(),rand(),(rand()&127)+128);
     }
     startshape(dev);
     startFill(dev);
@@ -880,17 +882,17 @@ void swf_startframe(gfxdevice_t*dev, int width, int height)
     i->max_y = height;
     i->watermarks = 0;
 
-    /* set clipping/background rectangle */
-    /* TODO: this should all be done in SWFOutputDev */
-    //setBackground(dev, x1, y1, x2, y2);
+    /* create a bbox structure with the page size. This is used
+       for clipping shape and text bounding boxes. As we don't want to
+       generate bounding boxes which extend beyond the movie size (in
+       order to not confuse Flash), we clip everything against i->pagebbox */
+    i->pagebbox.xmin = 0;
+    i->pagebbox.ymin = 0;
+    i->pagebbox.xmax = width*20;
+    i->pagebbox.ymax = height*20;
 
     /* increase SWF's bounding box */
-    SRECT r;
-    r.xmin = 0;
-    r.ymin = 0;
-    r.xmax = width*20;
-    r.ymax = height*20;
-    swf_ExpandRect2(&i->swf->movieSize, &r);
+    swf_ExpandRect2(&i->swf->movieSize, &i->pagebbox);
 
     i->lastframeno = i->frameno;
     i->firstpage = 0;
@@ -1034,11 +1036,7 @@ static void startshape(gfxdevice_t*dev)
 
     i->bboxrectpos = i->tag->len;
     /* changed later */
-    r.xmin = 0;
-    r.ymin = 0;
-    r.xmax = 20*i->max_x;
-    r.ymax = 20*i->max_y;
-    swf_SetRect(i->tag,&r);
+    swf_SetRect(i->tag,&i->pagebbox);
    
     memset(&i->bboxrect, 0, sizeof(i->bboxrect));
 
@@ -1188,7 +1186,8 @@ static void endshape(gfxdevice_t*dev)
     
     swf_ShapeSetEnd(i->tag);
 
-    changeRect(dev, i->tag, i->bboxrectpos, &i->bboxrect);
+    SRECT r = swf_ClipRect(i->pagebbox, i->bboxrect);
+    changeRect(dev, i->tag, i->bboxrectpos, &r);
 
     msg("<trace> Placing shape ID %d", i->shapeid);
 
@@ -1499,8 +1498,8 @@ void swfoutput_linktourl(gfxdevice_t*dev, const char*url, gfxline_t*points)
        actions = action_GetUrl(actions, url, i->config_linktarget);
     }
     actions = action_End(actions);
-    
-    drawlink(dev, actions, 0, points,0);
+   
+    drawlink(dev, actions, 0, points, 0);
 }
 void swfoutput_linktopage(gfxdevice_t*dev, int page, gfxline_t*points)
 {
@@ -1523,7 +1522,7 @@ void swfoutput_linktopage(gfxdevice_t*dev, int page, gfxline_t*points)
        actions = action_End(actions);
     }
 
-    drawlink(dev, actions, 0, points,0);
+    drawlink(dev, actions, 0, points, 0);
 }
 
 /* Named Links (a.k.a. Acrobatmenu) are used to implement various gadgets
@@ -1573,7 +1572,7 @@ void swfoutput_namedlink(gfxdevice_t*dev, char*name, gfxline_t*points)
        actions2 = action_End(actions2);
     }
 
-    drawlink(dev, actions1, actions2, points,mouseover);
+    drawlink(dev, actions1, actions2, points, mouseover);
 
     swf_ActionFree(actions1);
     swf_ActionFree(actions2);
@@ -1642,6 +1641,7 @@ static void drawlink(gfxdevice_t*dev, ActionTAG*actions1, ActionTAG*actions2, gf
     r.ymin = (int)(bbox.ymin*20);
     r.xmax = (int)(bbox.xmax*20);
     r.ymax = (int)(bbox.ymax*20);
+    r = swf_ClipRect(i->pagebbox, r);
     swf_SetRect(i->tag,&r);
     swf_SetShapeStyles(i->tag,i->shape);
     swf_ShapeCountBits(i->shape,NULL,NULL);
@@ -1664,6 +1664,7 @@ static void drawlink(gfxdevice_t*dev, ActionTAG*actions1, ActionTAG*actions2, gf
     r.ymin = (int)(bbox.ymin*20);
     r.xmax = (int)(bbox.xmax*20);
     r.ymax = (int)(bbox.ymax*20);
+    r = swf_ClipRect(i->pagebbox, r);
     swf_SetRect(i->tag,&r);
     swf_SetShapeStyles(i->tag,i->shape);
     swf_ShapeCountBits(i->shape,NULL,NULL);
@@ -1708,6 +1709,8 @@ static void drawlink(gfxdevice_t*dev, ActionTAG*actions1, ActionTAG*actions2, gf
             swf_ButtonPostProcess(i->tag, 1);
        }
     }
+    char name[80];
+    sprintf(name, "link%d", buttonid);
     
     msg("<trace> Placing link ID %d", buttonid);
     i->tag = swf_InsertTag(i->tag,ST_PLACEOBJECT2);
@@ -1721,9 +1724,9 @@ static void drawlink(gfxdevice_t*dev, ActionTAG*actions1, ActionTAG*actions2, gf
         m = i->page_matrix;
         m.tx = p.x;
         m.ty = p.y;
-       swf_ObjectPlace(i->tag, buttonid, getNewDepth(dev),&m,0,0);
+       swf_ObjectPlace(i->tag, buttonid, getNewDepth(dev),&m,0,name);
     } else {
-       swf_ObjectPlace(i->tag, buttonid, getNewDepth(dev),&i->page_matrix,0,0);
+       swf_ObjectPlace(i->tag, buttonid, getNewDepth(dev),&i->page_matrix,0,name);
     }
 }
 
@@ -2080,6 +2083,7 @@ static void swf_fillbitmap(gfxdevice_t*dev, gfxline_t*line, gfximage_t*img, gfxm
     int fsid = swf_ShapeAddBitmapFillStyle(shape,&m,bitid,1);
     swf_SetU16(i->tag, myshapeid);
     SRECT r = gfxline_getSWFbbox(line);
+    r = swf_ClipRect(i->pagebbox, r);
     swf_SetRect(i->tag,&r);
     swf_SetShapeStyles(i->tag,shape);
     swf_ShapeCountBits(shape,NULL,NULL);
@@ -2111,6 +2115,7 @@ static void drawoutline(gfxdevice_t*dev, gfxline_t*line)
 
     swf_SetU16(i->tag,myshapeid);
     SRECT r = gfxline_getSWFbbox(line);
+    r = swf_ClipRect(i->pagebbox, r);
     swf_SetRect(i->tag,&r);
     swf_SetShapeStyles(i->tag,shape);
     swf_ShapeCountBits(shape,NULL,NULL);
@@ -2154,6 +2159,7 @@ static void swf_startclip(gfxdevice_t*dev, gfxline_t*line)
     }
     swf_SetU16(i->tag,myshapeid);
     SRECT r = gfxline_getSWFbbox(line);
+    r = swf_ClipRect(i->pagebbox, r);
     swf_SetRect(i->tag,&r);
     swf_SetShapeStyles(i->tag,shape);
     swf_ShapeCountBits(shape,NULL,NULL);
@@ -2488,6 +2494,7 @@ static void swf_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*grad
     int fsid = swf_ShapeAddGradientFillStyle(shape,&m,swfgradient,type==gfxgradient_radial);
     swf_SetU16(i->tag, myshapeid);
     SRECT r = gfxline_getSWFbbox(line);
+    r = swf_ClipRect(i->pagebbox, r);
     swf_SetRect(i->tag,&r);
     swf_SetShapeStyles(i->tag,shape);
     swf_ShapeCountBits(shape,NULL,NULL);
@@ -2515,7 +2522,7 @@ static SWFFONT* gfxfont_to_swffont(gfxfont_t*font, const char* id)
     swffont->version = 2;
     swffont->name = (U8*)strdup(id);
     swffont->layout = (SWFLAYOUT*)rfx_calloc(sizeof(SWFLAYOUT));
-    swffont->layout->ascent = 0; /* ? */
+    swffont->layout->ascent = 0;
     swffont->layout->descent = 0;
     swffont->layout->leading = 0;
     swffont->layout->bounds = (SRECT*)rfx_calloc(sizeof(SRECT)*font->num_glyphs);
@@ -2583,17 +2590,21 @@ static SWFFONT* gfxfont_to_swffont(gfxfont_t*font, const char* id)
 
        swf_ExpandRect2(&bounds, &swffont->layout->bounds[t]);
     }
-    if(bounds.ymin < 0 && bounds.ymax > 0) {
-       swffont->layout->ascent = -bounds.ymin;
-       swffont->layout->descent = bounds.ymax;
-       swffont->layout->leading = bounds.ymax - bounds.ymin;
-    } else {
-       swffont->layout->ascent = (bounds.ymax - bounds.ymin)/2;
-       swffont->layout->descent = (bounds.ymax - bounds.ymin)/2;
-       swffont->layout->leading = bounds.ymax - bounds.ymin;
-    }
-    swffont->layout->descent= (bounds.ymax - bounds.ymin);
-    swffont->layout->ascent = 0;
+
+
+    /* Flash player will use the advance value from the char, and the ascent/descent values
+       from the layout for text selection.
+       ascent will extend the char into negative y direction, from the baseline, while descent
+       will extend in positive y direction, also from the baseline.
+       The baseline is defined as the y-position zero 
+     */
+
+    swffont->layout->ascent = -bounds.ymin;
+    if(swffont->layout->ascent < 0)
+        swffont->layout->ascent = 0;
+    swffont->layout->descent = bounds.ymax;
+    if(swffont->layout->descent < 0)
+        swffont->layout->descent = 0;
     swffont->layout->leading = bounds.ymax - bounds.ymin;
 
     return swffont;