removed parameter_t
[swftools.git] / lib / pdf / GFXOutputDev.cc
index 88fa728..288de6e 100644 (file)
 #include "../devices/polyops.h"
 #include "../devices/render.h"
 
-#include "../art/libart.h"
-
 #include "../png.h"
 #include "fonts.h"
 
 #include <math.h>
 
+#define SQRT2 1.41421356237309504880
+
 typedef struct _fontfile
 {
     const char*filename;
@@ -564,7 +564,7 @@ GFXOutputDev::GFXOutputDev(InfoOutputDev*info, PDFDoc*doc)
     this->pages = 0;
     this->pagebuflen = 0;
     this->pagepos = 0;
-    this->config_convertgradients=0;
+    this->config_convertgradients=1;
     this->config_break_on_warning=0;
     this->config_remapunicode=0;
     this->config_transparent=0;
@@ -596,13 +596,6 @@ void GFXOutputDev::setParameter(const char*key, const char*value)
         this->config_fontquality = atof(value);
        if(this->config_fontquality<=1)
            this->config_fontquality=1;
-    } else if(!strcmp(key,"help")) {
-       printf("\nPDF layer options:\n");
-       printf("breakonwarning=0/1  Abort conversion if graphic objects are found which\n");
-       printf("                    are not 100%% supported\n");
-       printf("transparent=0/1     Make PDF transparent (alpha background)\n");
-       printf("extrafontdata=0/1   Store Type3 characters and capture characters\n");
-       printf("fontquality=1..100  Curve approximation quality of the fonts\n");
     }
     
 }
@@ -1026,14 +1019,13 @@ void GFXOutputDev::endPage()
        device->endclip(device);
        outer_clip_box = 0;
     }
-    if(this->dashPattern) {
-        free(this->dashPattern);
-        this->dashPattern = 0;
-    }
+    this->dashPattern = 0;
     /* notice: we're not fully done yet with this page- there might still be 
        a few calls to drawLink() yet to come */
 }
 
+static inline double sqr(double x) {return x*x;}
+
 #define STROKE_FILL 1
 #define STROKE_CLIP 2
 void GFXOutputDev::strokeGfxline(GfxState *state, gfxline_t*line, int flags)
@@ -1067,13 +1059,27 @@ void GFXOutputDev::strokeGfxline(GfxState *state, gfxline_t*line, int flags)
 
     gfxline_t*line2 = 0;
 
-    if(0 && this->dashLength && this->dashPattern) {
+    if(this->dashLength && this->dashPattern) {
        float * dash = (float*)malloc(sizeof(float)*(this->dashLength+1));
        int t;
+
+        /* try to find out how much the transformation matrix would
+           stretch the dashes, and factor that into the dash lengths.
+           This is not the entirely correct approach- it would be 
+           better to first convert the path to an unscaled version,
+           then apply dashing, and then transform the path using
+           the current transformation matrix. However there are few
+           PDFs which actually stretch a dashed path in a non-orthonormal
+           way */
+        double tx1, ty1, tx2, ty2;
+       this->transformXY(state, 0, 0, &tx1, &ty1);
+       this->transformXY(state, 1, 1, &tx2, &ty2);
+        double f = sqrt(sqr(tx2-tx1)+sqr(ty2-ty1)) / SQRT2;
+
        msg("<trace> %d dashes", this->dashLength);
        msg("<trace> |  phase: %f", this->dashStart);
        for(t=0;t<this->dashLength;t++) {
-           dash[t] = (float)this->dashPattern[t];
+           dash[t] = (float)this->dashPattern[t] * f;
            msg("<trace> |  d%-3d: %f", t, this->dashPattern[t]);
        }
        dash[this->dashLength] = -1;
@@ -1081,7 +1087,7 @@ void GFXOutputDev::strokeGfxline(GfxState *state, gfxline_t*line, int flags)
            dump_outline(line);
        }
 
-       line2 = gfxtool_dash_line(line, dash, (float)this->dashStart);
+       line2 = gfxtool_dash_line(line, dash, (float)(this->dashStart*f));
        line = line2;
        free(dash);
        msg("<trace> After dashing:");
@@ -1113,7 +1119,7 @@ void GFXOutputDev::strokeGfxline(GfxState *state, gfxline_t*line, int flags)
         } else {
             device->fill(device, gfxline, &col);
         }
-        free(gfxline);
+        gfxline_free(gfxline);
        gfxpoly_free(poly);
     } else {
         if(flags&STROKE_CLIP) 
@@ -1188,7 +1194,8 @@ void GFXOutputDev::clipToStrokePath(GfxState *state)
     gfxline_t*line= gfxPath_to_gfxline(state, path, 0, user_movex + clipmovex, user_movey + clipmovey);
 
     if(getLogLevel() >= LOGLEVEL_TRACE)  {
-        msg("<trace> cliptostrokepath");
+        double width = state->getTransformedLineWidth();
+        msg("<trace> cliptostrokepath width=%f", width);
         dump_outline(line);
     }
 
@@ -1724,7 +1731,7 @@ void GFXOutputDev::processLink(Link *link, Catalog *catalog)
 }
 
 void GFXOutputDev::saveState(GfxState *state) {
-    dbg("saveState");dbgindent+=2;
+    dbg("saveState"); dbgindent+=2;
 
     msg("<trace> saveState");
     updateAll(state);
@@ -1949,8 +1956,8 @@ unsigned char* antialize(unsigned char*data, int width, int height, int newwidth
     unsigned char*newdata;
     int x,y;
     newdata= (unsigned char*)malloc(newwidth*newheight);
-    double fx = (double)(width)/newwidth;
-    double fy = (double)(height)/newheight;
+    double fx = ((double)width)/newwidth;
+    double fy = ((double)height)/newheight;
     double px = 0;
     int blocksize = (int)(8192/(fx*fy));
     int r = 8192*256/palettesize;
@@ -1958,17 +1965,21 @@ unsigned char* antialize(unsigned char*data, int width, int height, int newwidth
        double ex = px + fx;
        int fromx = (int)px;
        int tox = (int)ex;
-       int xweight1 = (int)(((fromx+1)-px)*256);
+       int xweight1 = (int)((1-(px-fromx))*256);
        int xweight2 = (int)((ex-tox)*256);
        double py =0;
        for(y=0;y<newheight;y++) {
            double ey = py + fy;
            int fromy = (int)py;
            int toy = (int)ey;
-           int yweight1 = (int)(((fromy+1)-py)*256);
+           int yweight1 = (int)((1-(py-fromy))*256);
            int yweight2 = (int)((ey-toy)*256);
            int a = 0;
            int xx,yy;
+            if(tox>=width) 
+                tox = width-1;
+            if(toy>=height) 
+                toy = height-1;
            for(xx=fromx;xx<=tox;xx++)
            for(yy=fromy;yy<=toy;yy++) {
                int b = 1-data[width*yy+xx];
@@ -2036,6 +2047,7 @@ static void drawimage(gfxdevice_t*dev, gfxcolor_t* data, int sizex,int sizey,
        /* TODO: pass image_dpi to device instead */
        dev->setparameter(dev, "next_bitmap_is_jpeg", "1");
 
+    dump_outline(&p1);
     dev->fillbitmap(dev, &p1, &img, &m, 0);
 }
 
@@ -2131,6 +2143,16 @@ void GFXOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
   this->transformXY(state, 1, 0, &x3, &y3);
   this->transformXY(state, 1, 1, &x4, &y4);
 
+  if(type3active) {
+      /* as type 3 bitmaps are antialized, we need to place them
+        at integer coordinates, otherwise flash player's antializing
+        will kick in and make everything blurry */
+      x1 = (int)(x1);y1 = (int)(y1);
+      x2 = (int)(x2);y2 = (int)(y2);
+      x3 = (int)(x3);y3 = (int)(y3);
+      x4 = (int)(x4);y4 = (int)(y4);
+  }
+
   if(!pbminfo && !(str->getKind()==strDCT)) {
       if(!type3active) {
          msg("<notice> File contains pbm pictures %s",mask?"(masked)":"");
@@ -2185,7 +2207,7 @@ void GFXOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
            delete imgStr;
            return;
          }
-
+          
          width = realwidth;
          height = realheight;
          delete[] pic;
@@ -2201,6 +2223,7 @@ void GFXOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
              pal[t].b = colToByte(rgb.b);
              pal[t].a = (unsigned char)(t*r);
          }
+          
       }
 
       gfxcolor_t*pic2 = new gfxcolor_t[width*height];
@@ -2546,11 +2569,11 @@ void GFXOutputDev::beginTransparencyGroup(GfxState *state, double *bbox,
                                      GBool forSoftMask)
 {
     const char*colormodename = "";
-
+  
     if(blendingColorSpace) {
        colormodename = GfxColorSpace::getColorSpaceModeName(blendingColorSpace->getMode());
     }
-    dbg("beginTransparencyGroup %.1f/%.1f/%.1f/%.1f %s isolated=%d knockout=%d forsoftmask=%d", bbox[0],bbox[1],bbox[2],bbox[3], colormodename, isolated, knockout, forSoftMask);
+    dbg("beginTransparencyGroup device=%08x %.1f/%.1f/%.1f/%.1f %s isolated=%d knockout=%d forsoftmask=%d", device, bbox[0],bbox[1],bbox[2],bbox[3], colormodename, isolated, knockout, forSoftMask);
     msg("<verbose> beginTransparencyGroup %.1f/%.1f/%.1f/%.1f %s isolated=%d knockout=%d forsoftmask=%d", bbox[0],bbox[1],bbox[2],bbox[3], colormodename, isolated, knockout, forSoftMask);
     
     //states[statepos].createsoftmask |= forSoftMask;
@@ -2628,8 +2651,14 @@ void GFXOutputDev::paintTransparencyGroup(GfxState *state, double *bbox)
 
 void GFXOutputDev::setSoftMask(GfxState *state, double *bbox, GBool alpha, Function *transferFunc, GfxColor *rgb)
 {
+    if(states[statepos].softmask) {
+       /* shouldn't happen, but *does* happen */
+       clearSoftMask(state);
+    }
+
     /* alpha = 1: retrieve mask values from alpha layer
        alpha = 0: retrieve mask values from luminance */
+
     dbg("setSoftMask %.1f/%.1f/%.1f/%.1f alpha=%d backdrop=%02x%02x%02x",
            bbox[0], bbox[1], bbox[2], bbox[3], alpha, colToByte(rgb->c[0]), colToByte(rgb->c[1]), colToByte(rgb->c[2]));
     msg("<verbose> setSoftMask %.1f/%.1f/%.1f/%.1f alpha=%d backdrop=%02x%02x%02x",
@@ -2643,7 +2672,7 @@ void GFXOutputDev::setSoftMask(GfxState *state, double *bbox, GBool alpha, Funct
     this->device = (gfxdevice_t*)rfx_calloc(sizeof(gfxdevice_t));
     gfxdevice_record_init(this->device);
 
-    dbg("softmaskrecording is %08x at statepos %d\n", states[statepos].softmaskrecording, statepos);
+    dbg("softmaskrecording is %08x (dev=%08x) at statepos %d\n", states[statepos].softmaskrecording, this->device, statepos);
     
     states[statepos].softmask = 1;
     states[statepos].softmask_alpha = alpha;
@@ -2666,7 +2695,7 @@ void GFXOutputDev::clearSoftMask(GfxState *state)
        return;
     states[statepos].softmask = 0;
     dbg("clearSoftMask statepos=%d", statepos);
-    msg("<verbose> clearSoftMask");
+    msg("<verbose> clearSoftMask statepos=%d", statepos);
     
     if(!states[statepos].softmaskrecording || strcmp(this->device->name, "record")) {
        msg("<error> Error in softmask/tgroup ordering");