fixed type 3 stroke/fill color problem.
[swftools.git] / pdf2swf / SWFOutputDev.cc
index 001c137..ad47eac 100644 (file)
@@ -206,14 +206,16 @@ public:
                         int width, int height, GfxImageColorMap *colorMap,
                         int *maskColors, GBool inlineImg);
   
-  virtual GBool beginType3Char(GfxState *state,
-                              CharCode code, Unicode *u, int uLen);
+  virtual GBool beginType3Char(GfxState *state, double x, double y, double dx, double dy, CharCode code, Unicode *u, int uLen);
   virtual void endType3Char(GfxState *state);
 
+  virtual void type3D0(GfxState *state, double wx, double wy);
+  virtual void type3D1(GfxState *state, double wx, double wy, double llx, double lly, double urx, double ury);
+
   private:
   void drawGeneralImage(GfxState *state, Object *ref, Stream *str,
                                   int width, int height, GfxImageColorMap*colorMap, GBool invert,
-                                  GBool inlineImg, int mask);
+                                  GBool inlineImg, int mask, int *maskColors);
   int clipping[64];
   int clippos;
 
@@ -575,6 +577,21 @@ static void dumpFontInfo(char*loglevel, GfxFont*font)
 //void SWFOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, GBool inlineImg) {printf("void SWFOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, GBool inlineImg) \n");}
 //void SWFOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, GBool inlineImg) {printf("void SWFOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, GBool inlineImg) \n");}
 
+
+void dump_outline(gfxline_t*line)
+{
+    while(line) {
+       if(line->type == gfx_moveTo) {
+           msg("<debug> |     moveTo %.2f %.2f", line->x,line->y);
+       } else if(line->type == gfx_lineTo) {
+           msg("<debug> |     lineTo %.2f %.2f", line->x,line->y);
+       } else if(line->type == gfx_splineTo) {
+           msg("<debug> |     splineTo (%.2f %.2f) %.2f %.2f", line->sx,line->sy, line->x, line->y);
+       }
+       line = line->next;
+    }
+}
+
 gfxline_t* gfxPath_to_gfxline(GfxState*state, GfxPath*path, int closed)
 {
     int num = path->getNumSubpaths();
@@ -631,7 +648,8 @@ gfxline_t* gfxPath_to_gfxline(GfxState*state, GfxPath*path, int closed)
     if(closed && needsfix && (fabs(posx-lastx)+fabs(posy-lasty))>0.001) {
        draw.lineTo(&draw, lastx, lasty);
     }
-    return (gfxline_t*)draw.result(&draw);
+    gfxline_t*result = (gfxline_t*)draw.result(&draw);
+    return result;
 }
 
 /*----------------------------------------------------------------------------
@@ -648,13 +666,16 @@ void SWFOutputDev::stroke(GfxState *state)
 
     GfxRGB rgb;
     double opaq = state->getStrokeOpacity();
-    state->getStrokeRGB(&rgb);
+    if(type3active)
+       state->getFillRGB(&rgb);
+    else
+       state->getStrokeRGB(&rgb);
     gfxcolor_t col;
     col.r = (unsigned char)(rgb.r*255);
     col.g = (unsigned char)(rgb.g*255);
     col.b = (unsigned char)(rgb.b*255);
     col.a = (unsigned char)(opaq*255);
-    
+   
     gfx_capType capType = gfx_capRound;
     if(lineCap == 0) capType = gfx_capButt;
     else if(lineCap == 1) capType = gfx_capRound;
@@ -668,31 +689,44 @@ void SWFOutputDev::stroke(GfxState *state)
     gfxline_t*line= gfxPath_to_gfxline(state, path, 0);
     
     int dashnum = 0;
-    double dashstart = 0;
+    double dashphase = 0;
     double * ldash = 0;
-    state->getLineDash(&ldash, &dashnum, &dashstart);
+    state->getLineDash(&ldash, &dashnum, &dashphase);
+
     if(dashnum && ldash) {
-       float * dash = (float*)malloc(sizeof(float)*(dashnum+2));
-       dash[0] = dashstart;
+       float * dash = (float*)malloc(sizeof(float)*(dashnum+1));
        int t;
+       double cut = 0;
+       int fixzero = 0;
+       msg("<trace> %d dashes", dashnum);
+       msg("<trace> |  phase: %f", dashphase);
        for(t=0;t<dashnum;t++) {
-           dash[t+1] = ldash[t];
+           dash[t] = ldash[t];
+           msg("<trace> |  d%-3d: %f", t, ldash[t]);
+       }
+       dash[dashnum] = -1;
+       if(getLogLevel() >= LOGLEVEL_TRACE) {
+           dump_outline(line);
        }
-       dash[dashnum+1] = 0;
 
-       gfxline_t*line2 = gfxtool_dash_line(line, dash);
+       gfxline_t*line2 = gfxtool_dash_line(line, dash, dashphase);
        gfxline_free(line);
        line = line2;
+       msg("<trace> After dashing:");
     }
     
     if(getLogLevel() >= LOGLEVEL_TRACE)  {
-        msg("<trace> stroke width=%f join=%s cap=%s dashes=%d\n",
+       double gray;
+       state->getStrokeGray(&gray);
+        msg("<trace> stroke width=%f join=%s cap=%s dashes=%d color=%02x%02x%02x%02x gray=%f\n",
                width,
                lineJoin==0?"miter": (lineJoin==1?"round":"bevel"),
                lineCap==0?"butt": (lineJoin==1?"round":"square"),
-               dashnum
+               dashnum,
+               col.r,col.g,col.b,col.a,
+               gray
                );
-        //gfxline_show(line, stdout);
+        dump_outline(line);
     }
    
     swfoutput_drawgfxline(&output, line, width, &col, capType, joinType, miterLimit);
@@ -713,8 +747,8 @@ void SWFOutputDev::fill(GfxState *state)
     gfxline_t*line= gfxPath_to_gfxline(state, path, 1);
 
     if(getLogLevel() >= LOGLEVEL_TRACE)  {
-        msg("<trace> fill\n");
-        //dump_outline(line);
+        msg("<trace> fill %02x%02x%02x%02x\n", col.r, col.g, col.b, col.a);
+        dump_outline(line);
     }
 
     swfoutput_fillgfxline(&output, line, &col);
@@ -736,7 +770,7 @@ void SWFOutputDev::eoFill(GfxState *state)
 
     if(getLogLevel() >= LOGLEVEL_TRACE)  {
         msg("<trace> eofill\n");
-        //dump_outline(line);
+        dump_outline(line);
     }
 
     swfoutput_fillgfxline(&output, line, &col);
@@ -749,7 +783,7 @@ void SWFOutputDev::clip(GfxState *state)
 
     if(getLogLevel() >= LOGLEVEL_TRACE)  {
         msg("<trace> clip\n");
-        //dump_outline(line);
+        dump_outline(line);
     }
 
     swfoutput_startclip(&output, line);
@@ -763,7 +797,7 @@ void SWFOutputDev::eoClip(GfxState *state)
 
     if(getLogLevel() >= LOGLEVEL_TRACE)  {
         msg("<trace> eoclip\n");
-        //dump_outline(line);
+        dump_outline(line);
     }
 
     swfoutput_startclip(&output, line);
@@ -893,17 +927,33 @@ void SWFOutputDev::drawChar(GfxState *state, double x, double y,
 void SWFOutputDev::endString(GfxState *state) { 
 }    
 
-GBool SWFOutputDev::beginType3Char(GfxState *state,
-                              CharCode code, Unicode *u, int uLen)
+/* the logic seems to be as following:
+   first, beginType3Char is called, with the charcode and the coordinates.
+   if this function returns true, it already knew about the char and has now drawn it.
+   if the function returns false, it's a new char, and type3D1 is called with some parameters-
+   the all draw operations until endType3Char are part of the char (which in this moment is
+   at the position first passed to beginType3Char). the char ends with endType3Char.
+
+   The drawing operations between beginType3Char and endType3Char are somewhat different to
+   the normal ones. For example, the fillcolor equals the stroke color.
+*/
+
+GBool SWFOutputDev::beginType3Char(GfxState *state, double x, double y, double dx, double dy, CharCode code, Unicode *u, int uLen)
 {
     msg("<debug> beginType3Char %d, %08x, %d", code, *u, uLen);
     type3active = 1;
-    /* the character itself is going to be passed using
-       drawImageMask() */
+    /* the character itself is going to be passed using the draw functions */
     return gFalse; /* gTrue= is_in_cache? */
 }
 
+void SWFOutputDev::type3D0(GfxState *state, double wx, double wy) {
+    msg("<debug> type3D0 width=%f height=%f", wx, wy);
+}
+void SWFOutputDev::type3D1(GfxState *state, double wx, double wy, double llx, double lly, double urx, double ury) {
+    msg("<debug> type3D1 width=%f height=%f bbox=(%f,%f,%f,%f)", wx, wy,
+           llx,lly,urx,ury);
+}
+
 void SWFOutputDev::endType3Char(GfxState *state)
 {
     type3active = 0;
@@ -1188,7 +1238,6 @@ void SWFOutputDev::updateStrokeColor(GfxState *state)
     GfxRGB rgb;
     double opaq = state->getStrokeOpacity();
     state->getStrokeRGB(&rgb);
-
     //swfoutput_setstrokecolor(&output, (char)(rgb.r*255), (char)(rgb.g*255), (char)(rgb.b*255), (char)(opaq*255));
 }
 
@@ -1622,7 +1671,7 @@ unsigned char* antialize(unsigned char*data, int width, int height, int newwidth
 
 void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
                                   int width, int height, GfxImageColorMap*colorMap, GBool invert,
-                                  GBool inlineImg, int mask)
+                                  GBool inlineImg, int mask, int*maskColors)
 {
   FILE *fi;
   int c;
@@ -1749,7 +1798,7 @@ void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
   } 
 
   int x,y;
-  
+
   if(colorMap->getNumPixelComps()!=1 || str->getKind()==strDCT) {
       RGBA*pic=new RGBA[width*height];
       for (y = 0; y < height; ++y) {
@@ -1776,10 +1825,32 @@ void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
       for(t=0;t<256;t++) {
          pixBuf[0] = t;
          colorMap->getRGB(pixBuf, &rgb);
-         pal[t].r = (U8)(rgb.r * 255 + 0.5);
-         pal[t].g = (U8)(rgb.g * 255 + 0.5);
-         pal[t].b = (U8)(rgb.b * 255 + 0.5);
-         pal[t].a = 255;//(U8)(rgb.b * 255 + 0.5);
+         /*if(maskColors && *maskColors==t) {
+             msg("<notice> Color %d is transparent", t);
+             if (imgData->maskColors) {
+               *alpha = 0;
+               for (i = 0; i < imgData->colorMap->getNumPixelComps(); ++i) {
+                 if (pix[i] < imgData->maskColors[2*i] ||
+                     pix[i] > imgData->maskColors[2*i+1]) {
+                   *alpha = 1;
+                   break;
+                 }
+               }
+             } else {
+               *alpha = 1;
+             }
+             if(!*alpha) {
+                   pal[t].r = 0;
+                   pal[t].g = 0;
+                   pal[t].b = 0;
+                   pal[t].a = 0;
+             }
+         } else*/ {
+             pal[t].r = (U8)(rgb.r * 255 + 0.5);
+             pal[t].g = (U8)(rgb.g * 255 + 0.5);
+             pal[t].b = (U8)(rgb.b * 255 + 0.5);
+             pal[t].a = 255;//(U8)(rgb.b * 255 + 0.5);
+         }
       }
       for (y = 0; y < height; ++y) {
        for (x = 0; x < width; ++x) {
@@ -1800,7 +1871,7 @@ void SWFOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
                                   GBool inlineImg) 
 {
   msg("<verbose> drawImageMask %dx%d, invert=%d inline=%d", width, height, invert, inlineImg);
-  drawGeneralImage(state,ref,str,width,height,0,invert,inlineImg,1);
+  drawGeneralImage(state,ref,str,width,height,0,invert,inlineImg,1, 0);
 }
 
 void SWFOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
@@ -1814,7 +1885,7 @@ void SWFOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
   if(colorMap)
       msg("<verbose> colorMap pixcomps:%d bits:%d mode:%d\n", colorMap->getNumPixelComps(),
              colorMap->getBits(),colorMap->getColorSpace()->getMode());
-  drawGeneralImage(state,ref,str,width,height,colorMap,0,inlineImg,0);
+  drawGeneralImage(state,ref,str,width,height,colorMap,0,inlineImg,0,maskColors);
 }
 
 SWFOutputDev*output = 0;