small bugfix in drawchar(), removed rfxswf.h references
[swftools.git] / pdf2swf / SWFOutputDev.cc
index 9fce9e7..bf17212 100644 (file)
@@ -63,7 +63,7 @@
 #include "SWFOutputDev.h"
 
 //swftools header files
-#include "swfoutput.h"
+#include "../lib/devices/swf.h"
 #include "../lib/log.h"
 #include "../lib/gfxdevice.h"
 #include "../lib/gfxtools.h"
@@ -101,6 +101,8 @@ static int forceType0Fonts = 1;
 static void printInfoString(Dict *infoDict, char *key, char *fmt);
 static void printInfoDate(Dict *infoDict, char *key, char *fmt);
 
+static char* lastfontdir = 0;
+
 struct mapping {
     char*pdffont;
     char*filename;
@@ -163,7 +165,7 @@ public:
   virtual void startPage(int pageNum, GfxState *state, double x1, double y1, double x2, double y2) ;
 
   void endframe();
-  void* getSWF();
+  void* get(char*name);
 
   //----- get info about output device
 
@@ -304,6 +306,51 @@ public:
   friend void swf_output_preparepage(swf_output_t*swf, int pdfpage, int outputpage);
 };
 
+typedef struct _drawnchar
+{
+    gfxcoord_t x,y;
+    int charid;
+    gfxcolor_t color;
+} drawnchar_t;
+
+class CharBuffer
+{
+    drawnchar_t * chars;
+    int buf_size;
+    int num_chars;
+
+public:
+
+    CharBuffer()
+    {
+       buf_size = 32;
+       chars = (drawnchar_t*)malloc(sizeof(drawnchar_t)*buf_size);
+       memset(chars, 0, sizeof(drawnchar_t)*buf_size);
+       num_chars = 0;
+    }
+    ~CharBuffer()
+    {
+       free(chars);chars = 0;
+    }
+
+    void grow(int size)
+    {
+       if(size>=buf_size) {
+           buf_size += 32;
+           chars = (drawnchar_t*)realloc(chars, sizeof(drawnchar_t)*buf_size);
+       }
+    }
+
+    void addChar(int charid, gfxcoord_t x, gfxcoord_t y, gfxcolor_t color)
+    {
+       grow(num_chars);
+       chars[num_chars].x = x;
+       chars[num_chars].y = y;
+       chars[num_chars].color = color;
+       chars[num_chars].charid = charid;
+    }
+};
+
 static char*getFontID(GfxFont*font);
 
 struct FontInfo
@@ -975,10 +1022,10 @@ int SWFOutputDev::save(char*filename)
     finish();
     return result->save(result, filename);
 }
-void* SWFOutputDev::getSWF()
+void* SWFOutputDev::get(char*name)
 {
     finish();
-    return result->get(result, "swf");
+    return result->get(result, name);
 }
 
 SWFOutputDev::~SWFOutputDev() 
@@ -1135,8 +1182,10 @@ void SWFOutputDev::drawChar(GfxState *state, double x, double y,
 {
     int render = state->getRender();
     // check for invisible text -- this is used by Acrobat Capture
-    if (render == 3)
+    if (render == 3) {
+       msg("<debug> Ignoring invisible text: char %d at %f,%f", c, x, y);
        return;
+    }
 
     if(states[statepos].textRender != render)
        msg("<error> Internal error: drawChar.render!=beginString.render");
@@ -1180,8 +1229,9 @@ void SWFOutputDev::drawChar(GfxState *state, double x, double y,
        Gfx8BitFont*font8;
        font8 = (Gfx8BitFont*)font;
        char**enc=font8->getEncoding();
-       if(enc && enc[c])
+       if(enc && enc[c] && strcasecmp(enc[c], "space")) {
           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);
@@ -1190,9 +1240,27 @@ void SWFOutputDev::drawChar(GfxState *state, double x, double y,
        msg("<debug> drawChar(%f,%f,c='%c' (%d), u=%d <%d>) CID=%d name=\"%s\" render=%d\n",x,y,(c&127)>=32?c:'?',c,u, uLen, font->isCIDFont(), FIXNULL(name), render);
     }
 
-    int charid = getGfxCharID(current_gfxfont, c, name, u);
+    int charid = -1;
+   
+    if(uLen<=1) {
+       charid = getGfxCharID(current_gfxfont, c, name, u);
+    } else {
+       charid = getGfxCharID(current_gfxfont, c, 0, -1);
+       if(charid < 0) {
+           /* multiple unicodes- should usually map to a ligature.
+              if the ligature doesn't exist, we need to draw
+              the characters one-by-one. */
+           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);
+           }
+           return;
+       }
+    }
+
     if(charid<0) {
-       if(strcasecmp(name, "space")) {
+       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);
        }
@@ -1513,7 +1581,6 @@ void SWFOutputDev::drawLink(Link *link, Catalog *catalog)
         int t;
        int lpage = -1;
         for(t=1;t<=pagepos;t++) {
-           printf("%d) %d (%d?)\n", t, pages[t], page);
             if(pages[t]==page) {
                lpage = t;
                 break;
@@ -1857,7 +1924,7 @@ char* searchForSuitableFont(GfxFont*gfxFont)
 char* SWFOutputDev::substituteFont(GfxFont*gfxFont, char* oldname)
 {
     char*fontname = 0, *filename = 0;
-    msg("<notice> subsituteFont(%s)", oldname);
+    msg("<notice> substituteFont(%s)", oldname);
 
     if(!(fontname = searchForSuitableFont(gfxFont))) {
        fontname = "Times-Roman";
@@ -1940,8 +2007,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);
@@ -2034,7 +2104,12 @@ void SWFOutputDev::updateFont(GfxState *state)
     if(!fileName) {
        char * fontname = getFontName(gfxFont);
        msg("<warning> Font %s %scould not be loaded.", fontname, embedded?"":"(not embedded) ");
-       msg("<warning> Try putting a TTF version of that font (named \"%s.ttf\") into /swftools/fonts", fontname);
+       
+       if(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");
+
        fileName = substituteFont(gfxFont, fontid);
        if(fontid) { free(fontid);fontid = strdup(substitutetarget[substitutepos-1]); /*ugly hack*/};
        msg("<notice> Font is now %s (%s)", fontid, fileName);
@@ -2060,6 +2135,8 @@ void SWFOutputDev::updateFont(GfxState *state)
     if(fileName)
         free(fileName);
     free(fontid);
+
+    msg("<verbose> |");
 }
 
 #define SQR(x) ((x)*(x))
@@ -2115,13 +2192,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));
@@ -2166,13 +2243,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);
@@ -2236,7 +2313,7 @@ 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);
 
@@ -2287,14 +2364,14 @@ void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
          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 = (unsigned char)(255*rgb.r);
+             pal[t].g = (unsigned char)(255*rgb.g);
+             pal[t].b = (unsigned char)(255*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]];
@@ -2310,14 +2387,14 @@ 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];
+      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)(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].a = 255;//(U8)(rgb.a * 255 + 0.5);
        }
       }
@@ -2329,8 +2406,8 @@ void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
       delete imgStr;
       return;
   } else {
-      RGBA*pic=new RGBA[width*height];
-      RGBA pal[256];
+      gfxcolor_t*pic=new gfxcolor_t[width*height];
+      gfxcolor_t pal[256];
       int t;
       for(t=0;t<256;t++) {
          pixBuf[0] = t;
@@ -2356,9 +2433,9 @@ void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
                    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].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);
              pal[t].a = 255;//(U8)(rgb.b * 255 + 0.5);
          }
       }
@@ -2547,6 +2624,7 @@ void pdfswf_addfontdir(char*dirname)
 {
 #ifdef HAVE_DIRENT_H
     msg("<notice> Adding %s to font directories", dirname);
+    lastfontdir = strdup(dirname);
     DIR*dir = opendir(dirname);
     if(!dir) {
        msg("<warning> Couldn't open directory %s\n", dirname);
@@ -2793,10 +2871,10 @@ int swf_output_save(swf_output_t*swf, char*filename)
     return ret;
 }
 
-void* swf_output_get(swf_output_t*swf)
+void* swf_output_get(swf_output_t*swf,char*name)
 {
     swf_output_internal_t*i= (swf_output_internal_t*)swf->internal;
-    void* ret = i->outputDev->getSWF();
+    void* ret = i->outputDev->get(name);
     return ret;
 }