font ids now contain the pdf reference id
[swftools.git] / pdf2swf / SWFOutputDev.cc
index bf17212..40d8847 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,8 +253,9 @@ public:
   private:
   void drawGeneralImage(GfxState *state, Object *ref, Stream *str,
                                   int width, int height, GfxImageColorMap*colorMap, GBool invert,
-                                  GBool inlineImg, int mask, int *maskColors);
-  int SWFOutputDev::setGfxFont(char*id, char*filename, double quality);
+                                  GBool inlineImg, int mask, int *maskColors,
+                                  Stream *maskStr, int maskWidth, int maskHeight, GBool maskInvert, GfxImageColorMap*maskColorMap);
+  int SWFOutputDev::setGfxFont(char*id, char*name, char*filename, double quality);
   void strokeGfxline(GfxState *state, gfxline_t*line);
   void clipToGfxLine(GfxState *state, gfxline_t*line);
   void fillGfxLine(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)
@@ -517,20 +526,31 @@ void SWFOutputDev::setClip(int x1,int y1,int x2,int y2)
 
 static char*getFontID(GfxFont*font)
 {
+    Ref*ref = font->getID();
     GString*gstr = font->getName();
-    char* fontname = gstr==0?0:gstr->getCString();
-    if(fontname==0) {
-       char buf[32];
-       Ref*r=font->getID();
-       sprintf(buf, "UFONT%d", r->num);
-       return strdup(buf);
+    char* fname = gstr==0?0:gstr->getCString();
+    char buf[128];
+    if(fname==0) {
+       sprintf(buf, "font-%d-%d", ref->num, ref->gen);
+    } else {
+       sprintf(buf, "%s-%d-%d", fname, ref->num, ref->gen);
     }
-    return strdup(fontname);
+    return strdup(buf);
 }
 
 static char*getFontName(GfxFont*font)
 {
-    char*fontid = getFontID(font);
+    char*fontid;
+    GString*gstr = font->getName();
+    char* fname = gstr==0?0:gstr->getCString();
+    if(fname==0) {
+       char buf[32];
+       Ref*r=font->getID();
+       sprintf(buf, "UFONT%d", r->num);
+       fontid = strdup(buf);
+    }
+    fontid = strdup(fname);
+
     char*fontname= 0;
     char* plus = strchr(fontid, '+');
     if(plus && plus < &fontid[strlen(fontid)-1]) {
@@ -849,9 +869,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 +914,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 +931,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;
 }
@@ -1109,8 +1130,22 @@ char* makeStringPrintable(char*str)
 
 int getGfxCharID(gfxfont_t*font, int charnr, char *charname, int u)
 {
-    int t;
+    char*uniname = 0;
+    if(u>0) {
+       int t;
+       /* find out char name from unicode index 
+          TODO: should be precomputed
+        */
+       for(t=0;t<sizeof(nameToUnicodeTab)/sizeof(nameToUnicodeTab[0]);t++) {
+           if(nameToUnicodeTab[t].u == u) {
+               uniname = nameToUnicodeTab[t].name;
+               break;
+           }
+       }
+    }
+
     if(charname) {
+       int t;
        for(t=0;t<font->num_glyphs;t++) {
            if(font->glyphs[t].name && !strcmp(font->glyphs[t].name,charname)) {
                msg("<debug> Char [%d,>%s<,%d] maps to %d\n", charnr, charname, u, t);
@@ -1127,17 +1162,30 @@ int getGfxCharID(gfxfont_t*font, int charnr, char *charname, int u)
        }
     }
 
+    if(uniname) {
+       int t;
+       for(t=0;t<font->num_glyphs;t++) {
+           if(font->glyphs[t].name && !strcmp(font->glyphs[t].name,uniname)) {
+               msg("<debug> Char [%d,%s,>%d(%s)<] maps to %d\n", charnr, charname, u, uniname, t);
+               return t;
+           }
+       }
+       /* if we didn't find the character, maybe
+          we can find the capitalized version */
+       for(t=0;t<font->num_glyphs;t++) {
+           if(font->glyphs[t].name && !strcasecmp(font->glyphs[t].name,uniname)) {
+               msg("<debug> Char [%d,%s,>>%d(%s)<<] maps to %d\n", charnr, charname, u, uniname, t);
+               return t;
+           }
+       }
+    }
+
     /* try to use the unicode id */
     if(u>=0 && u<font->max_unicode && font->unicode2glyph[u]>=0) {
        msg("<debug> Char [%d,%s,>%d<] maps to %d\n", charnr, charname, u, font->unicode2glyph[u]);
        return font->unicode2glyph[u];
     }
 
-    /* we don't need to "draw" space characters, so don't overdo the search
-       for a matching glyph */
-    if(charname && !strcasecmp(charname, "space"))
-       return -1;
-
     if(charnr>=0 && charnr<font->num_glyphs) {
        msg("<debug> Char [>%d<,%s,%d] maps to %d\n", charnr, charname, u, charnr);
        return charnr;
@@ -1178,7 +1226,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
@@ -1204,22 +1252,6 @@ void SWFOutputDev::drawChar(GfxState *state, double x, double y,
     Unicode u=0;
     char*name=0;
 
-    if(_u && uLen) {
-       u = *_u;
-       if (u) {
-           int t;
-           /* find out char name from unicode index 
-              TODO: should be precomputed
-            */
-           for(t=0;t<sizeof(nameToUnicodeTab)/sizeof(nameToUnicodeTab[0]);t++) {
-               if(nameToUnicodeTab[t].u == u) {
-                   name = nameToUnicodeTab[t].name;
-                   break;
-               }
-           }
-       }
-    }
-
     if(font->isCIDFont()) {
        GfxCIDFont*cfont = (GfxCIDFont*)font;
 
@@ -1229,9 +1261,7 @@ void SWFOutputDev::drawChar(GfxState *state, double x, double y,
        Gfx8BitFont*font8;
        font8 = (Gfx8BitFont*)font;
        char**enc=font8->getEncoding();
-       if(enc && enc[c] && strcasecmp(enc[c], "space")) {
-          name = enc[c];
-       }
+       name = enc[c];
     }
     if (CIDToGIDMap) {
        msg("<debug> drawChar(%f, %f, c='%c' (%d), GID=%d, u=%d <%d>) CID=%d name=\"%s\" render=%d\n", x, y, (c&127)>=32?c:'?', c, CIDToGIDMap[c], u, uLen, font->isCIDFont(), FIXNULL(name), render);
@@ -1245,7 +1275,8 @@ void SWFOutputDev::drawChar(GfxState *state, double x, double y,
     if(uLen<=1) {
        charid = getGfxCharID(current_gfxfont, c, name, u);
     } else {
-       charid = getGfxCharID(current_gfxfont, c, 0, -1);
+       charid = getGfxCharID(current_gfxfont, c, name, -1);
+
        if(charid < 0) {
            /* multiple unicodes- should usually map to a ligature.
               if the ligature doesn't exist, we need to draw
@@ -1253,17 +1284,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) {
-       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);
-       }
+       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);
        return;
     }
 
@@ -1435,18 +1463,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 +1606,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 +1757,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 +1771,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 {
@@ -1983,7 +1991,7 @@ void SWFOutputDev::setXRef(PDFDoc*doc, XRef *xref)
     this->xref = xref;
 }
 
-int SWFOutputDev::setGfxFont(char*id, char*filename, double maxSize)
+int SWFOutputDev::setGfxFont(char*id, char*name, char*filename, double maxSize)
 {
     gfxfont_t*font = 0;
     fontlist_t*last=0,*l = this->fontlist;
@@ -2035,7 +2043,10 @@ void SWFOutputDev::updateFont(GfxState *state)
     if (!gfxFont) {
        return;
     }  
+    
     char * fontid = getFontID(gfxFont);
+    char * fontname = getFontName(gfxFont);
+
     double maxSize = 1.0;
 
     if(this->info) {
@@ -2056,8 +2067,9 @@ void SWFOutputDev::updateFont(GfxState *state)
 
     /* second, see if this is a font which was used before-
        if so, we are done */
-    if(setGfxFont(fontid, 0, 0)) {
+    if(setGfxFont(fontid, fontname, 0, 0)) {
        free(fontid);
+       free(fontname);
        return;
     }
 /*    if(swfoutput_queryfont(&output, fontid))
@@ -2074,6 +2086,7 @@ void SWFOutputDev::updateFont(GfxState *state)
            showFontError(gfxFont, 2);
        }
        free(fontid);
+       free(fontname);
        return;
     }
 
@@ -2096,10 +2109,8 @@ void SWFOutputDev::updateFont(GfxState *state)
       if(!fileName) showFontError(gfxFont,0);
       else del = 1;
     } else {
-      char * fontname = getFontName(gfxFont);
       fileName = searchFont(fontname);
       if(!fileName) showFontError(gfxFont,0);
-      free(fontname);
     }
     if(!fileName) {
        char * fontname = getFontName(gfxFont);
@@ -2118,6 +2129,7 @@ void SWFOutputDev::updateFont(GfxState *state)
     if(!fileName) {
        msg("<error> Couldn't set font %s\n", fontid);
        free(fontid);
+       free(fontname);
        return;
     }
        
@@ -2126,15 +2138,17 @@ void SWFOutputDev::updateFont(GfxState *state)
 
     //swfoutput_setfont(&output, fontid, fileName);
     
-    if(!setGfxFont(fontid, 0, 0)) {
-       setGfxFont(fontid, fileName, maxSize);
+    if(!setGfxFont(fontid, fontname, 0, 0)) {
+       setGfxFont(fontid, fontname, fileName, maxSize);
     }
    
     if(fileName && del)
        unlinkfont(fileName);
+
     if(fileName)
         free(fileName);
     free(fontid);
+    free(fontname);
 
     msg("<verbose> |");
 }
@@ -2258,22 +2272,59 @@ void drawimagelossless(gfxdevice_t*dev, gfxcolor_t*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();
 
@@ -2287,13 +2338,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) {
@@ -2318,11 +2371,11 @@ void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
       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));
@@ -2357,16 +2410,13 @@ 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 = (unsigned char)(255*rgb.r);
-             pal[t].g = (unsigned char)(255*rgb.g);
-             pal[t].b = (unsigned char)(255*rgb.b);
+             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);
          }
       }
@@ -2381,8 +2431,9 @@ void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
       free(pic2);
       free(pic);
       delete imgStr;
+      if(maskbitmap) free(maskbitmap);
       return;
-  } 
+  }
 
   int x,y;
 
@@ -2392,10 +2443,13 @@ void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
        for (x = 0; x < width; ++x) {
          imgStr->getPixel(pixBuf);
          colorMap->getRGB(pixBuf, &rgb);
-         pic[width*y+x].r = (unsigned char)(rgb.r * 255 + 0.5);
-         pic[width*y+x].g = (unsigned char)(rgb.g * 255 + 0.5);
-         pic[width*y+x].b = (unsigned char)(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)
@@ -2404,15 +2458,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 {
       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;
@@ -2432,10 +2489,10 @@ void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
                    pal[t].b = 0;
                    pal[t].a = 0;
              }
-         } else*/ {
-             pal[t].r = (unsigned char)(rgb.r * 255 + 0.5);
-             pal[t].g = (unsigned char)(rgb.g * 255 + 0.5);
-             pal[t].b = (unsigned char)(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);
          }
       }
@@ -2443,12 +2500,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;
   }
 }
@@ -2460,7 +2521,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,
@@ -2470,14 +2531,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; 
@@ -2566,9 +2664,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);
@@ -2750,11 +2848,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;
 
@@ -2902,11 +2996,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)
@@ -2941,11 +3031,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;