added masking and soft masking
[swftools.git] / pdf2swf / SWFOutputDev.cc
index ab19a5a..b54f1e6 100644 (file)
 #include "Page.h"
 #include "PDFDoc.h"
 #include "Error.h"
+#include "Link.h"
 #include "OutputDev.h"
 #include "GfxState.h"
 #include "GfxFont.h"
 #include "CharCodeToUnicode.h"
 #include "NameToUnicodeTable.h"
 #include "GlobalParams.h"
-//#define XPDF_101
-#ifdef XPDF_101
-#include "FontFile.h"
-#else
 #include "FoFiType1C.h"
 #include "FoFiTrueType.h"
 #include "GHash.h"
-#endif
 #include "SWFOutputDev.h"
 
 //swftools header files
@@ -227,7 +223,7 @@ public:
   virtual void drawChar(GfxState *state, double x, double y,
                        double dx, double dy,
                        double originX, double originY,
-                       CharCode code, Unicode *u, int uLen);
+                       CharCode code, int nBytes, Unicode *u, int uLen);
 
   //----- image drawing
   virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
@@ -236,6 +232,17 @@ public:
   virtual void drawImage(GfxState *state, Object *ref, Stream *str,
                         int width, int height, GfxImageColorMap *colorMap,
                         int *maskColors, GBool inlineImg);
+  virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str,
+                              int width, int height,
+                              GfxImageColorMap *colorMap,
+                              Stream *maskStr, int maskWidth, int maskHeight,
+                              GBool maskInvert);
+  virtual void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str,
+                                  int width, int height,
+                                  GfxImageColorMap *colorMap,
+                                  Stream *maskStr,
+                                  int maskWidth, int maskHeight,
+                                  GfxImageColorMap *maskColorMap);
   
   virtual GBool beginType3Char(GfxState *state, double x, double y, double dx, double dy, CharCode code, Unicode *u, int uLen);
   virtual void endType3Char(GfxState *state);
@@ -246,7 +253,8 @@ public:
   private:
   void drawGeneralImage(GfxState *state, Object *ref, Stream *str,
                                   int width, int height, GfxImageColorMap*colorMap, GBool invert,
-                                  GBool inlineImg, int mask, int *maskColors);
+                                  GBool inlineImg, int mask, int *maskColors,
+                                  Stream *maskStr, int maskWidth, int maskHeight, GBool maskInvert, GfxImageColorMap*maskColorMap);
   int SWFOutputDev::setGfxFont(char*id, char*filename, double quality);
   void strokeGfxline(GfxState *state, gfxline_t*line);
   void clipToGfxLine(GfxState *state, gfxline_t*line);
@@ -429,10 +437,11 @@ class InfoOutputDev:  public OutputDev
       }
       currentfont = info;
   }
+  
   virtual void drawChar(GfxState *state, double x, double y,
                        double dx, double dy,
                        double originX, double originY,
-                       CharCode code, Unicode *u, int uLen)
+                       CharCode code, int nBytes, Unicode *u, int uLen)
   {
       int render = state->getRender();
       if (render == 3)
@@ -849,9 +858,9 @@ void SWFOutputDev::strokeGfxline(GfxState *state, gfxline_t*line)
     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.r = colToByte(rgb.r);
+    col.g = colToByte(rgb.g);
+    col.b = colToByte(rgb.b);
     col.a = (unsigned char)(opaq*255);
    
     gfx_capType capType = gfx_capRound;
@@ -894,15 +903,12 @@ void SWFOutputDev::strokeGfxline(GfxState *state, gfxline_t*line)
     }
     
     if(getLogLevel() >= LOGLEVEL_TRACE)  {
-       double gray;
-       state->getStrokeGray(&gray);
-        msg("<trace> stroke width=%f join=%s cap=%s dashes=%d color=%02x%02x%02x%02x gray=%f\n",
+        msg("<trace> stroke width=%f join=%s cap=%s dashes=%d color=%02x%02x%02x%02x\n",
                width,
                lineJoin==0?"miter": (lineJoin==1?"round":"bevel"),
                lineCap==0?"butt": (lineJoin==1?"round":"square"),
                dashnum,
-               col.r,col.g,col.b,col.a,
-               gray
+               col.r,col.g,col.b,col.a
                );
         dump_outline(line);
     }
@@ -914,15 +920,19 @@ void SWFOutputDev::strokeGfxline(GfxState *state, gfxline_t*line)
        gfxline_free(line2);
 }
 
+void convertRGB()
+{
+}
+
 gfxcolor_t getFillColor(GfxState * state)
 {
     GfxRGB rgb;
     double opaq = state->getFillOpacity();
     state->getFillRGB(&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.r = colToByte(rgb.r);
+    col.g = colToByte(rgb.g);
+    col.b = colToByte(rgb.b);
     col.a = (unsigned char)(opaq*255);
     return col;
 }
@@ -1178,7 +1188,7 @@ void SWFOutputDev::beginString(GfxState *state, GString *s)
 void SWFOutputDev::drawChar(GfxState *state, double x, double y,
                        double dx, double dy,
                        double originX, double originY,
-                       CharCode c, Unicode *_u, int uLen)
+                       CharCode c, int nBytes, Unicode *_u, int uLen)
 {
     int render = state->getRender();
     // check for invisible text -- this is used by Acrobat Capture
@@ -1253,14 +1263,14 @@ void SWFOutputDev::drawChar(GfxState *state, double x, double y,
            int t;
            msg("<warning> ligature %d missing in font %s\n", c, current_font_id);
            for(t=0;t<uLen;t++) {
-               drawChar(state, x, y, dx, dy, originX, originY, c, _u+t, 1);
+               drawChar(state, x, y, dx, dy, originX, originY, c, nBytes, _u+t, 1);
            }
            return;
        }
     }
 
-    if(charid<0 && name) {
-       if(strcasecmp(name, "space")) {
+    if(charid<0) {
+       if(!name || strcasecmp(name, "space")) {
            msg("<warning> Didn't find character '%s' (c=%d,u=%d) in current charset (%s, %d characters)", 
                    FIXNULL(name),c, u, FIXNULL((char*)current_font_id), current_gfxfont->num_glyphs);
        }
@@ -1435,18 +1445,10 @@ void SWFOutputDev::drawLink(Link *link, Catalog *catalog)
 {
     msg("<debug> drawlink\n");
     double x1, y1, x2, y2, w;
-    GfxRGB rgb;
     gfxline_t points[5];
     int x, y;
 
-#ifdef XPDF_101
-    link->getBorder(&x1, &y1, &x2, &y2, &w);
-#else
     link->getRect(&x1, &y1, &x2, &y2);
-#endif
-    rgb.r = 0;
-    rgb.g = 0;
-    rgb.b = 1;
     cvtUserToDev(x1, y1, &x, &y);
     points[0].type = gfx_moveTo;
     points[0].x = points[4].x = x + user_movex;
@@ -1586,13 +1588,12 @@ void SWFOutputDev::drawLink(Link *link, Catalog *catalog)
                 break;
            }
        }
-        if(lpage>=0) {
-           char buf[80];
-           sprintf(buf, "page%d", t);
-            output->drawlink(output, points, buf);
-       } else {
-           msg("<warning> Invalid link to page %d", page);
+        if(lpage<0) {
+           lpage = page;
        }
+       char buf[80];
+       sprintf(buf, "page%d", lpage);
+       output->drawlink(output, points, buf);
     }
     else if(url)
     {
@@ -1738,15 +1739,9 @@ char*SWFOutputDev::writeEmbeddedFontToFile(XRef*ref, GfxFont*font)
        msg("<error> Couldn't read embedded font file");
        return 0;
       }
-#ifdef XPDF_101
-      Type1CFontFile *cvt = new Type1CFontFile(fontBuf, fontLen);
-      if(!cvt) return 0;
-      cvt->convertToType1(f);
-#else
       FoFiType1C *cvt = FoFiType1C::make(fontBuf, fontLen);
       if(!cvt) return 0;
       cvt->convertToType1(NULL, gTrue, FoFiWrite, f);
-#endif
       //cvt->convertToCIDType0("test", f);
       //cvt->convertToType0("test", f);
       delete cvt;
@@ -1758,13 +1753,8 @@ char*SWFOutputDev::writeEmbeddedFontToFile(XRef*ref, GfxFont*font)
        msg("<error> Couldn't read embedded font file");
        return 0;
       }
-#ifdef XPDF_101
-      TrueTypeFontFile *cvt = new TrueTypeFontFile(fontBuf, fontLen);
-      cvt->writeTTF(f);
-#else
       FoFiTrueType *cvt = FoFiTrueType::make(fontBuf, fontLen);
       cvt->writeTTF(FoFiWrite, f);
-#endif
       delete cvt;
       gfree(fontBuf);
     } else {
@@ -2007,8 +1997,11 @@ int SWFOutputDev::setGfxFont(char*id, char*filename, double maxSize)
        we have to divide 0.05 by (fontsize/1024)
      */
     double quality = (1024 * 0.05) / maxSize;
-    
+   
+    msg("<verbose> Loading %s...", filename);
     font = gfxfont_load(filename, quality);
+    msg("<verbose> Font %s loaded successfully", filename);
+
     l = new fontlist_t;
     l->font = font;
     l->filename = strdup(filename);
@@ -2103,7 +2096,7 @@ void SWFOutputDev::updateFont(GfxState *state)
        msg("<warning> Font %s %scould not be loaded.", fontname, embedded?"":"(not embedded) ");
        
        if(lastfontdir)
-           msg("<warning> Try putting a TTF version of that font (named \"%s.ttf\") into %s/swftools/fonts", fontname, lastfontdir);
+           msg("<warning> Try putting a TTF version of that font (named \"%s.ttf\") into %s", fontname, lastfontdir);
        else
            msg("<warning> Try specifying one or more font directories");
 
@@ -2132,6 +2125,8 @@ void SWFOutputDev::updateFont(GfxState *state)
     if(fileName)
         free(fileName);
     free(fontid);
+
+    msg("<verbose> |");
 }
 
 #define SQR(x) ((x)*(x))
@@ -2187,13 +2182,13 @@ unsigned char* antialize(unsigned char*data, int width, int height, int newwidth
 #define IMAGE_TYPE_JPEG 0
 #define IMAGE_TYPE_LOSSLESS 1
 
-static void drawimage(gfxdevice_t*dev, RGBA* data, int sizex,int sizey, 
+static void drawimage(gfxdevice_t*dev, gfxcolor_t* data, int sizex,int sizey, 
         double x1,double y1,
         double x2,double y2,
         double x3,double y3,
         double x4,double y4, int type)
 {
-    RGBA*newpic=0;
+    gfxcolor_t*newpic=0;
     
     double l1 = sqrt((x4-x1)*(x4-x1) + (y4-y1)*(y4-y1));
     double l2 = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
@@ -2238,13 +2233,13 @@ static void drawimage(gfxdevice_t*dev, RGBA* data, int sizex,int sizey,
     dev->fillbitmap(dev, &p1, &img, &m, 0);
 }
 
-void drawimagejpeg(gfxdevice_t*dev, RGBA*mem, int sizex,int sizey, 
+void drawimagejpeg(gfxdevice_t*dev, gfxcolor_t*mem, int sizex,int sizey, 
         double x1,double y1, double x2,double y2, double x3,double y3, double x4,double y4)
 {
     drawimage(dev,mem,sizex,sizey,x1,y1,x2,y2,x3,y3,x4,y4, IMAGE_TYPE_JPEG);
 }
 
-void drawimagelossless(gfxdevice_t*dev, RGBA*mem, int sizex,int sizey, 
+void drawimagelossless(gfxdevice_t*dev, gfxcolor_t*mem, int sizex,int sizey, 
         double x1,double y1, double x2,double y2, double x3,double y3, double x4,double y4)
 {
     drawimage(dev,mem,sizex,sizey,x1,y1,x2,y2,x3,y3,x4,y4, IMAGE_TYPE_LOSSLESS);
@@ -2253,22 +2248,59 @@ void drawimagelossless(gfxdevice_t*dev, RGBA*mem, int sizex,int sizey,
 
 void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
                                   int width, int height, GfxImageColorMap*colorMap, GBool invert,
-                                  GBool inlineImg, int mask, int*maskColors)
+                                  GBool inlineImg, int mask, int*maskColors,
+                                  Stream *maskStr, int maskWidth, int maskHeight, GBool maskInvert, GfxImageColorMap*maskColorMap)
 {
-  FILE *fi;
-  int c;
-  char fileName[128];
   double x1,y1,x2,y2,x3,y3,x4,y4;
   ImageStream *imgStr;
   Guchar pixBuf[4];
   GfxRGB rgb;
   int ncomps = 1;
   int bits = 1;
+  unsigned char* maskbitmap = 0;
                                 
   if(colorMap) {
     ncomps = colorMap->getNumPixelComps();
     bits = colorMap->getBits();
   }
+  
+  if(maskStr) {
+      int x,y;
+      unsigned char buf[8];
+      maskbitmap = (unsigned char*)malloc(maskHeight*maskWidth);
+      if(maskColorMap) {
+         ImageStream*imgMaskStr = new ImageStream(maskStr, maskWidth, maskColorMap->getNumPixelComps(), maskColorMap->getBits());
+         imgMaskStr->reset();
+         unsigned char pal[256];
+         int n = 1 << colorMap->getBits();
+         int t;
+         for(t=0;t<n;t++) {
+             GfxGray gray;
+             pixBuf[0] = t;
+             maskColorMap->getGray(pixBuf, &gray);
+             pal[t] = colToByte(gray);
+         }
+         for (y = 0; y < maskHeight; y++) {
+             for (x = 0; x < maskWidth; x++) {
+                 imgMaskStr->getPixel(buf);
+                 maskbitmap[y*maskWidth+x] = pal[buf[0]];
+             }
+         }
+         delete imgMaskStr;
+      } else {
+         ImageStream*imgMaskStr = new ImageStream(maskStr, maskWidth, 1, 1);
+         imgMaskStr->reset();
+         for (y = 0; y < maskHeight; y++) {
+             for (x = 0; x < maskWidth; x++) {
+                 imgMaskStr->getPixel(buf);
+                 buf[0]^=maskInvert;
+                 maskbitmap[y*maskWidth+x] = (buf[0]^1)*255;
+             }
+         }
+         delete imgMaskStr;
+      }
+  }
+      
   imgStr = new ImageStream(str, width, ncomps,bits);
   imgStr->reset();
 
@@ -2282,13 +2314,15 @@ void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
          imgStr->getPixel(buf);
       }
       delete imgStr;
+      if(maskbitmap)
+         free(maskbitmap);
       return;
   }
-  
-  state->transform(0, 1, &x1, &y1); x1 += user_movex; y1+= user_movey;
-  state->transform(0, 0, &x2, &y2); x2 += user_movex; y2+= user_movey;
-  state->transform(1, 0, &x3, &y3); x3 += user_movex; y3+= user_movey;
-  state->transform(1, 1, &x4, &y4); x4 += user_movex; y4+= user_movey;
+
+  state->transform(0, 1, &x1, &y1); x1 += user_movex; y1 += user_movey;
+  state->transform(0, 0, &x2, &y2); x2 += user_movex; y2 += user_movey;
+  state->transform(1, 0, &x3, &y3); x3 += user_movex; y3 += user_movey;
+  state->transform(1, 1, &x4, &y4); x4 += user_movex; y4 += user_movey;
 
   if(!pbminfo && !(str->getKind()==strDCT)) {
       if(!type3active) {
@@ -2308,16 +2342,16 @@ void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
       unsigned char buf[8];
       int x,y;
       unsigned char*pic = new unsigned char[width*height];
-      RGBA pal[256];
+      gfxcolor_t pal[256];
       GfxRGB rgb;
       state->getFillRGB(&rgb);
 
       memset(pal,255,sizeof(pal));
-      pal[0].r = (int)(rgb.r*255); pal[1].r = 0;
-      pal[0].g = (int)(rgb.g*255); pal[1].g = 0;
-      pal[0].b = (int)(rgb.b*255); pal[1].b = 0;
+      pal[0].r = (int)(colToByte(rgb.r)); pal[1].r = 0;
+      pal[0].g = (int)(colToByte(rgb.g)); pal[1].g = 0;
+      pal[0].b = (int)(colToByte(rgb.b)); pal[1].b = 0;
       pal[0].a = 255;              pal[1].a = 0;
-
+    
       int numpalette = 2;
       int realwidth = (int)sqrt(SQR(x2-x3) + SQR(y2-y3));
       int realheight = (int)sqrt(SQR(x1-x2) + SQR(y1-y2));
@@ -2352,21 +2386,18 @@ void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
          pic = pic2;
          
          /* make a black/white palette */
-         GfxRGB rgb2;
-         rgb2.r = 1 - rgb.r;
-         rgb2.g = 1 - rgb.g;
-         rgb2.b = 1 - rgb.b;
+
          float r = 255/(numpalette-1);
          int t;
          for(t=0;t<numpalette;t++) {
-             pal[t].r = (U8)(255*rgb.r);
-             pal[t].g = (U8)(255*rgb.g);
-             pal[t].b = (U8)(255*rgb.b);
-             pal[t].a = (U8)(t*r);
+             pal[t].r = colToByte(rgb.r);
+             pal[t].g = colToByte(rgb.g);
+             pal[t].b = colToByte(rgb.b);
+             pal[t].a = (unsigned char)(t*r);
          }
       }
 
-      RGBA*pic2 = new RGBA[width*height];
+      gfxcolor_t*pic2 = new gfxcolor_t[width*height];
       for (y = 0; y < height; ++y) {
        for (x = 0; x < width; ++x) {
          pic2[width*y+x] = pal[pic[y*width+x]];
@@ -2376,21 +2407,25 @@ void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
       free(pic2);
       free(pic);
       delete imgStr;
+      if(maskbitmap) free(maskbitmap);
       return;
-  } 
+  }
 
   int x,y;
 
   if(colorMap->getNumPixelComps()!=1 || str->getKind()==strDCT) {
-      RGBA*pic=new RGBA[width*height];
+      gfxcolor_t*pic=new gfxcolor_t[width*height];
       for (y = 0; y < height; ++y) {
        for (x = 0; x < width; ++x) {
          imgStr->getPixel(pixBuf);
          colorMap->getRGB(pixBuf, &rgb);
-         pic[width*y+x].r = (U8)(rgb.r * 255 + 0.5);
-         pic[width*y+x].g = (U8)(rgb.g * 255 + 0.5);
-         pic[width*y+x].b = (U8)(rgb.b * 255 + 0.5);
+         pic[width*y+x].r = (unsigned char)(colToByte(rgb.r));
+         pic[width*y+x].g = (unsigned char)(colToByte(rgb.g));
+         pic[width*y+x].b = (unsigned char)(colToByte(rgb.b));
          pic[width*y+x].a = 255;//(U8)(rgb.a * 255 + 0.5);
+         if(maskbitmap) {
+             pic[width*y+x].a = maskbitmap[(y*maskHeight/height)*maskWidth+(x*maskWidth/width)];
+         }
        }
       }
       if(str->getKind()==strDCT)
@@ -2399,15 +2434,18 @@ void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
          drawimagelossless(output, pic, width, height, x1,y1,x2,y2,x3,y3,x4,y4);
       delete pic;
       delete imgStr;
+      if(maskbitmap) free(maskbitmap);
       return;
   } else {
-      RGBA*pic=new RGBA[width*height];
-      RGBA pal[256];
+      gfxcolor_t*pic=new gfxcolor_t[width*height];
+      gfxcolor_t pal[256];
+      int n = 1 << colorMap->getBits();
       int t;
       for(t=0;t<256;t++) {
          pixBuf[0] = t;
          colorMap->getRGB(pixBuf, &rgb);
-         /*if(maskColors && *maskColors==t) {
+
+         {/*if(maskColors && *maskColors==t) {
              msg("<notice> Color %d is transparent", t);
              if (imgData->maskColors) {
                *alpha = 0;
@@ -2427,10 +2465,10 @@ void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
                    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);
+         } else {*/
+             pal[t].r = (unsigned char)(colToByte(rgb.r));
+             pal[t].g = (unsigned char)(colToByte(rgb.g));
+             pal[t].b = (unsigned char)(colToByte(rgb.b));
              pal[t].a = 255;//(U8)(rgb.b * 255 + 0.5);
          }
       }
@@ -2438,12 +2476,16 @@ void SWFOutputDev::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)];
+         }
        }
       }
       drawimagelossless(output, pic, width, height, x1,y1,x2,y2,x3,y3,x4,y4);
 
       delete pic;
       delete imgStr;
+      if(maskbitmap) free(maskbitmap);
       return;
   }
 }
@@ -2455,7 +2497,7 @@ void SWFOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
   if(states[statepos].textRender & 4) //clipped
       return;
   msg("<verbose> drawImageMask %dx%d, invert=%d inline=%d", width, height, invert, inlineImg);
-  drawGeneralImage(state,ref,str,width,height,0,invert,inlineImg,1, 0);
+  drawGeneralImage(state,ref,str,width,height,0,invert,inlineImg,1, 0, 0,0,0,0, 0);
 }
 
 void SWFOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
@@ -2465,14 +2507,51 @@ void SWFOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
   if(states[statepos].textRender & 4) //clipped
       return;
 
-  msg("<verbose> drawImage %dx%d, %s %s, inline=%d", width, height, 
+  msg("<verbose> drawImage %dx%d, %s, %s, inline=%d", width, height, 
          colorMap?"colorMap":"no colorMap", 
          maskColors?"maskColors":"no maskColors",
          inlineImg);
   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,maskColors);
+  drawGeneralImage(state,ref,str,width,height,colorMap,0,inlineImg,0,maskColors, 0,0,0,0, 0);
+}
+  
+void SWFOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str,
+                              int width, int height,
+                              GfxImageColorMap *colorMap,
+                              Stream *maskStr, int maskWidth, int maskHeight,
+                              GBool maskInvert)
+{
+  if(states[statepos].textRender & 4) //clipped
+      return;
+
+  msg("<verbose> drawMaskedImage %dx%d, %s, %dx%d mask", width, height, 
+         colorMap?"colorMap":"no colorMap", 
+         maskWidth, maskHeight);
+  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,0,0,0, maskStr, maskWidth, maskHeight, maskInvert, 0);
+}
+
+void SWFOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str,
+                                  int width, int height,
+                                  GfxImageColorMap *colorMap,
+                                  Stream *maskStr,
+                                  int maskWidth, int maskHeight,
+                                  GfxImageColorMap *maskColorMap)
+{
+  if(states[statepos].textRender & 4) //clipped
+      return;
+
+  msg("<verbose> drawSoftMaskedImage %dx%d, %s, %dx%d mask", width, height, 
+         colorMap?"colorMap":"no colorMap", 
+         maskWidth, maskHeight);
+  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,0,0,0, maskStr, maskWidth, maskHeight, 0, maskColorMap);
 }
 
 //SWFOutputDev*output = 0; 
@@ -2561,9 +2640,9 @@ void pdfswf_setparameter(char*name, char*value)
        storeDeviceParameter("ppmsubpixels", buf);
     } else if(!strcmp(name, "forceType0Fonts")) {
        forceType0Fonts = atoi(value);
-    } else if(!strcmp(name, "fontdir")) {
+    } else if(!strncmp(name, "fontdir", strlen("fontdir"))) {
         pdfswf_addfontdir(value);
-    } else if(!strcmp(name, "languagedir")) {
+    } else if(!strncmp(name, "languagedir", strlen("languagedir"))) {
         pdfswf_addlanguagedir(value);
     } else if(!strcmp(name, "fontconfig")) {
         config_use_fontconfig = atoi(value);
@@ -2745,11 +2824,7 @@ pdf_doc_t* pdf_init(char*filename, char*userPassword)
     InfoOutputDev*io = new InfoOutputDev();
     int t;
     for(t=1;t<=pdf_doc->num_pages;t++) {
-#ifdef XPDF_101
-       i->doc->displayPage((OutputDev*)io, t, /*zoom*/zoom, /*rotate*/0, /*doLinks*/(int)1);
-#else
-       i->doc->displayPage((OutputDev*)io, t, zoom, zoom, /*rotate*/0, true, /*doLinks*/(int)1);
-#endif
+       i->doc->displayPage((OutputDev*)io, t, zoom, zoom, /*rotate*/0, /*usemediabox*/true, /*crop*/true, /*doLinks*/(int)1);
     }
     i->info = io;
 
@@ -2897,11 +2972,7 @@ void pdf_page_render2(pdf_page_t*page, swf_output_t*swf)
     }
     si->outputDev->setInfo(pi->info);
     si->outputDev->setXRef(pi->doc, pi->doc->getXRef());
-#ifdef XPDF_101
-    pi->doc->displayPage((OutputDev*)si->outputDev, page->nr, /*zoom*/zoom, /*rotate*/0, /*doLinks*/(int)1);
-#else
-    pi->doc->displayPage((OutputDev*)si->outputDev, page->nr, zoom, zoom, /*rotate*/0, true, /*doLinks*/(int)1);
-#endif
+    pi->doc->displayPage((OutputDev*)si->outputDev, page->nr, zoom, zoom, /*rotate*/0, true, true, /*doLinks*/(int)1);
 }
 
 void pdf_page_rendersection(pdf_page_t*page, swf_output_t*output, int x, int y, int x1, int y1, int x2, int y2)
@@ -2936,11 +3007,7 @@ pdf_page_info_t* pdf_page_getinfo(pdf_page_t*page)
 
     InfoOutputDev*output = new InfoOutputDev;
     
-#ifdef XPDF_101
-    pi->doc->displayPage((OutputDev*)output, page->nr, /*zoom*/zoom, /*rotate*/0, /*doLinks*/(int)1);
-#else
-    pi->doc->displayPage((OutputDev*)output, page->nr, zoom, zoom, /*rotate*/0, true, /*doLinks*/(int)1);
-#endif
+    pi->doc->displayPage((OutputDev*)output, page->nr, zoom, zoom, /*rotate*/0, true, true, /*doLinks*/(int)1);
 
     info->xMin = output->x1;
     info->yMin = output->y1;