fixed crash and offset error in transparency groups
[swftools.git] / lib / pdf / GFXOutputDev.cc
index 2c41499..43aa743 100644 (file)
 typedef struct _fontfile
 {
     const char*filename;
+    int len; // basename length
     int used;
+    struct _fontfile*next;
 } fontfile_t;
 
 // for pdfswf_addfont
-static fontfile_t fonts[2048];
+
+static fontfile_t* global_fonts = 0;
+static fontfile_t* global_fonts_next = 0;
+
 static int fontnum = 0;
 
 /* config */
@@ -151,7 +156,7 @@ typedef struct _feature
 } feature_t;
 feature_t*featurewarnings = 0;
 
-void GFXOutputDev::showfeature(const char*feature,char fully, char warn)
+void GFXOutputDev::showfeature(const char*feature, char fully, char warn)
 {
     feature_t*f = featurewarnings;
     while(f) {
@@ -327,12 +332,24 @@ DisplayFontParam *GFXGlobalParams::getDisplayFont(GString *fontName)
            return dfp;
        }
     }
-    for(t=0;t<fontnum;t++) {
-       if(strstr(fonts[t].filename, name)) {
-           DisplayFontParam *dfp = new DisplayFontParam(new GString(fontName), displayFontT1);
-           dfp->t1.fileName = new GString(fonts[t].filename);
-           return dfp;
-       }
+    
+    int bestlen = 0x7fffffff;
+    const char*bestfilename = 0;
+    
+    fontfile_t*f = 0;
+    while(f) {
+       if(strstr(f->filename, name)) {
+            if(f->len < bestlen) {
+                bestlen = f->len;
+                bestfilename = f->filename;
+            }
+        }
+        f = f->next;
+    }
+    if(bestfilename) {
+        DisplayFontParam *dfp = new DisplayFontParam(new GString(fontName), displayFontT1);
+        dfp->t1.fileName = new GString(bestfilename);
+        return dfp;
     }
     return GlobalParams::getDisplayFont(fontName);
 }
@@ -652,7 +669,7 @@ GBool GFXOutputDev::needNonText()
 }
 void GFXOutputDev::endPage() 
 {
-    msg("<verbose> endPage");
+    msg("<verbose> endPage (GfxOutputDev)");
     if(outer_clip_box) {
        device->endclip(device);
        outer_clip_box = 0;
@@ -939,7 +956,7 @@ void GFXOutputDev::drawChar(GfxState *state, double x, double y,
                        CharCode charid, int nBytes, Unicode *_u, int uLen)
 {
     if(!current_fontinfo || (unsigned)charid >= current_fontinfo->num_glyphs || !current_fontinfo->glyphs[charid]) {
-       msg("<error> Invalid charid %d for font %s", charid, current_font_id);
+       msg("<error> Invalid charid %d for font (%d characters)", charid, current_fontinfo?current_fontinfo->num_glyphs:0);
        return;
     }
   
@@ -1070,7 +1087,7 @@ GBool GFXOutputDev::beginType3Char(GfxState *state, double x, double y, double d
        m.ty += user_movey + clipmovey;
 
        if(!current_fontinfo || (unsigned)charid >= current_fontinfo->num_glyphs || !current_fontinfo->glyphs[charid]) {
-           msg("<error> Invalid charid %d for font %s", charid, current_font_id);
+           msg("<error> Invalid charid %d for font", charid);
            return gFalse;
        }
        gfxcolor_t col={0,0,0,0};
@@ -1189,6 +1206,10 @@ void GFXOutputDev::processLink(Link *link, Catalog *catalog)
            points[1].x, points[1].y,
            points[2].x, points[2].y,
            points[3].x, points[3].y); 
+    
+    if(getLogLevel() >= LOGLEVEL_TRACE)  {
+       dump_outline(points);
+    }
 
     LinkAction*action=link->getAction();
     char buf[128];
@@ -1520,7 +1541,7 @@ void GFXOutputDev::updateFont(GfxState *state)
     this->current_fontinfo = this->info->getFont(id);
     if(!this->current_fontinfo) {
        msg("<error> Internal Error: no fontinfo for font %s\n", id);
-    return;
+       return;
     }
     if(!this->current_fontinfo->seen) {
        dumpFontInfo("<verbose>", gfxFont);
@@ -1711,7 +1732,7 @@ void GFXOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
   imgStr = new ImageStream(str, width, ncomps,bits);
   imgStr->reset();
 
-  if(!width || !height || (height<=1 && width<=1))
+  if(!width || !height || (height<=1 && width<=1 && maskWidth<=1 && maskHeight<=1))
   {
       msg("<verbose> Ignoring %d by %d image", width, height);
       unsigned char buf[8];
@@ -1781,7 +1802,7 @@ void GFXOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
          pic2 = antialize(pic,width,height,realwidth,realheight,numpalette);
 
          if(!pic2) {
-           delete pic;
+           delete[] pic;
            delete imgStr;
            return;
          }
@@ -1838,7 +1859,7 @@ void GFXOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
          drawimagejpeg(device, pic, width, height, x1,y1,x2,y2,x3,y3,x4,y4);
       else
          drawimagelossless(device, pic, width, height, x1,y1,x2,y2,x3,y3,x4,y4);
-      delete pic;
+      delete[] pic;
       delete imgStr;
       if(maskbitmap) free(maskbitmap);
       return;
@@ -1882,14 +1903,39 @@ void GFXOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
        for (x = 0; x < width; ++x) {
          imgStr->getPixel(pixBuf);
          pic[width*y+x] = pal[pixBuf[0]];
-         if(maskbitmap) {
-             pic[width*y+x].a = maskbitmap[(y*maskHeight/height)*maskWidth+(x*maskWidth/width)];
-         }
        }
       }
+      if(maskbitmap) {
+         if(maskWidth < width && maskHeight < height) {
+             for(y = 0; y < height; y++) {
+                 for (x = 0; x < width; x++) {
+                     pic[width*y+x].a = maskbitmap[(y*maskHeight/height)*maskWidth+(x*maskWidth/width)];
+                 }
+             }
+         } else {
+             msg("<verbose> resampling %dx%d to mask size (%dx%d)", width, height, maskWidth, maskHeight);
+             gfxcolor_t*newpic=new gfxcolor_t[maskWidth*maskHeight];
+             double dx = width / maskWidth;
+             double dy = height / maskHeight;
+             double yy = 0;
+             for(y = 0; y < maskHeight; y++) {
+                 double xx = 0;
+                 for (x = 0; x < maskWidth; x++) {
+                     newpic[maskWidth*y+x] = pic[int(yy)*width+int(xx)];
+                     newpic[maskWidth*y+x].a = maskbitmap[maskWidth*y+x];
+                     xx += dx;
+                 }
+                 yy += dy;
+             }
+             delete[] pic;
+             pic = newpic;
+             width = maskWidth;
+             height = maskHeight;
+         }
+      }
       drawimagelossless(device, pic, width, height, x1,y1,x2,y2,x3,y3,x4,y4);
 
-      delete pic;
+      delete[] pic;
       delete imgStr;
       if(maskbitmap) free(maskbitmap);
       return;
@@ -2004,14 +2050,25 @@ static const char* dirseparator()
 
 void addGlobalFont(const char*filename)
 {
-    fontfile_t f;
-    memset(&f, 0, sizeof(fontfile_t));
-    f.filename = filename;
-    if(fontnum < sizeof(fonts)/sizeof(fonts[0])) {
-       msg("<notice> Adding font \"%s\".", filename);
-       fonts[fontnum++] = f;
+    fontfile_t* f = (fontfile_t*)malloc(sizeof(fontfile_t));
+    memset(f, 0, sizeof(fontfile_t));
+    f->filename = filename;
+    int len = strlen(filename);
+    char*r1 = strrchr(filename, '/');
+    char*r2 = strrchr(filename, '\\');
+    if(r2>r1)
+        r1 = r2;
+    if(r1) {
+        len = strlen(r1+1);
+    }
+    f->len = len;
+
+    msg("<notice> Adding font \"%s\".", filename);
+    if(global_fonts_next) {
+        global_fonts_next->next = f;
+        global_fonts_next = global_fonts_next->next;
     } else {
-       msg("<error> Too many external fonts. Not adding font file \"%s\".", filename);
+        global_fonts_next = global_fonts = f;
     }
 }
 
@@ -2193,7 +2250,8 @@ void GFXOutputDev::beginTransparencyGroup(GfxState *state, double *bbox,
     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);
     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;
+    //states[statepos].createsoftmask |= forSoftMask;
+    states[statepos].createsoftmask = forSoftMask;
     states[statepos].transparencygroup = !forSoftMask;
     states[statepos].isolated = isolated;
 
@@ -2218,10 +2276,11 @@ void GFXOutputDev::endTransparencyGroup(GfxState *state)
 
     this->device = states[statepos].olddevice;
 
+    gfxresult_t*recording = r->finish(r);
     if(states[statepos].createsoftmask) {
-       states[statepos-1].softmaskrecording = r->finish(r);
+       states[statepos-1].softmaskrecording = recording;
     } else {
-       states[statepos-1].grouprecording = r->finish(r);
+       states[statepos-1].grouprecording = recording;
     }
     
     states[statepos].createsoftmask = 0;