added new output devices
[swftools.git] / lib / pdf / GFXOutputDev.cc
index 24a8f05..da5df32 100644 (file)
@@ -31,9 +31,6 @@
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
 #endif
-#ifdef HAVE_FONTCONFIG
-#include <fontconfig.h>
-#endif
 //xpdf header files
 #include "config.h"
 #include "gfile.h"
@@ -328,11 +325,22 @@ 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;
+       }
+    }
     return GlobalParams::getDisplayFont(fontName);
 }
 
-GFXOutputDev::GFXOutputDev(parameter_t*p)
+GFXOutputDev::GFXOutputDev(InfoOutputDev*info, PDFDoc*doc)
 {
+    this->info = info;
+    this->doc = doc;
+    this->xref = doc->getXRef();
+
     this->jpeginfo = 0;
     this->textmodeinfo = 0;
     this->linkinfo = 0;
@@ -356,52 +364,39 @@ GFXOutputDev::GFXOutputDev(parameter_t*p)
     this->pages = 0;
     this->pagebuflen = 0;
     this->pagepos = 0;
-    this->config_use_fontconfig=1;
     this->config_break_on_warning=0;
     this->config_remapunicode=0;
     this->config_transparent=0;
     this->config_extrafontdata = 0;
 
-    this->parameters = p;
-    
     this->gfxfontlist = gfxfontlist_create();
   
     memset(states, 0, sizeof(states));
-
-    /* configure device */
-    while(p) {
-        setParameter(p->name, p->value);
-       p = p->next;
-    }
 };
 
 void GFXOutputDev::setParameter(const char*key, const char*value)
 {
     if(!strcmp(key,"breakonwarning")) {
        this->config_break_on_warning = atoi(value);
-    } else if(!strcmp(key,"fontconfig")) {
-        this->config_use_fontconfig = atoi(value);
     } else if(!strcmp(key,"remapunicode")) {
         this->config_remapunicode = atoi(value);
     } else if(!strcmp(key,"transparent")) {
         this->config_transparent = atoi(value);
     } else if(!strcmp(key,"extrafontdata")) {
         this->config_extrafontdata = atoi(value);
+    } 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");
     }
+    
 }
   
 void GFXOutputDev::setDevice(gfxdevice_t*dev)
 {
-    parameter_t*p = this->parameters;
-
-    /* pass parameters to output device */
     this->device = dev;
-    if(this->device) {
-       while(p) {
-           this->device->setparameter(this->device, p->name, p->value);
-           p = p->next;
-       }
-    }
 }
   
 void GFXOutputDev::setMove(int x,int y)
@@ -650,6 +645,10 @@ GBool GFXOutputDev::needNonText()
 void GFXOutputDev::endPage() 
 {
     msg("<verbose> endPage");
+    if(outer_clip_box) {
+       device->endclip(device);
+       outer_clip_box = 0;
+    }
 }
 
 #define STROKE_FILL 1
@@ -819,14 +818,6 @@ void GFXOutputDev::clipToStrokePath(GfxState *state)
     gfxline_free(line);
 }
 
-void GFXOutputDev::endframe()
-{
-    if(outer_clip_box) {
-       device->endclip(device);
-       outer_clip_box = 0;
-    }
-}
-
 void GFXOutputDev::finish()
 {
     if(outer_clip_box) {
@@ -845,7 +836,7 @@ GFXOutputDev::~GFXOutputDev()
        free(this->pages); this->pages = 0;
     }
 
-    gfxfontlist_free(this->gfxfontlist);
+    gfxfontlist_free(this->gfxfontlist, 1);
 };
 GBool GFXOutputDev::upsideDown() 
 {
@@ -893,15 +884,25 @@ char* makeStringPrintable(char*str)
 #define INTERNAL_FONT_SIZE 1024.0
 void GFXOutputDev::updateFontMatrix(GfxState*state)
 {
-    double m11,m21,m12,m22;
-    state->getFontTransMat(&m11, &m12, &m21, &m22);
-    m11 *= state->getHorizScaling();
-    m21 *= state->getHorizScaling();
+    double* ctm = state->getCTM();
+    double fontSize = state->getFontSize();
+    double*textMat = state->getTextMat();
 
-    this->current_font_matrix.m00 = m11 / INTERNAL_FONT_SIZE;
-    this->current_font_matrix.m01 = m12 / INTERNAL_FONT_SIZE;
-    this->current_font_matrix.m10 = -m21 / INTERNAL_FONT_SIZE;
-    this->current_font_matrix.m11 = -m22 / INTERNAL_FONT_SIZE;
+    /*  taking the absolute value of horizScaling seems to be required for
+       some italic fonts. FIXME: SplashOutputDev doesn't need this- why? */
+    double hscale = fabs(state->getHorizScaling());
+   
+    // from xpdf-3.02/SplashOutputDev:updateFont
+    double mm11 = textMat[0] * fontSize * hscale;
+    double mm12 = textMat[1] * fontSize * hscale;
+    double mm21 = textMat[2] * fontSize;
+    double mm22 = textMat[3] * fontSize;
+
+    // multiply with ctm, like state->getFontTransMat() does
+    this->current_font_matrix.m00 = (ctm[0]*mm11 + ctm[2]*mm12) / INTERNAL_FONT_SIZE;
+    this->current_font_matrix.m01 = (ctm[1]*mm11 + ctm[3]*mm12) / INTERNAL_FONT_SIZE;
+    this->current_font_matrix.m10 = (ctm[0]*mm21 + ctm[2]*mm22) / INTERNAL_FONT_SIZE;
+    this->current_font_matrix.m11 = (ctm[1]*mm21 + ctm[3]*mm22) / INTERNAL_FONT_SIZE;
     this->current_font_matrix.tx = 0;
     this->current_font_matrix.ty = 0;
 }
@@ -914,7 +915,6 @@ void GFXOutputDev::beginString(GfxState *state, GString *s)
     }
 
     msg("<trace> beginString(%s) render=%d", makeStringPrintable(s->getCString()), render);
-    updateFontMatrix(state);
 }
 
 static gfxline_t* mkEmptyGfxShape(double x, double y)
@@ -940,7 +940,7 @@ void GFXOutputDev::drawChar(GfxState *state, double x, double y,
        msg("<error> Invalid charid %d for font %s", charid, current_font_id);
        return;
     }
-
+  
     CharCode glyphid = current_fontinfo->glyphs[charid]->glyphid;
 
     int render = state->getRender();
@@ -949,6 +949,8 @@ void GFXOutputDev::drawChar(GfxState *state, double x, double y,
     // check for invisible text -- this is used by Acrobat Capture
     if (render == RENDER_INVISIBLE) {
        col.a = 0;
+       if(!config_extrafontdata)
+           return;
     }
 
     GfxFont*font = state->getFont();
@@ -1090,18 +1092,6 @@ void GFXOutputDev::endType3Char(GfxState *state)
     msg("<debug> endType3Char");
 }
 
-void GFXOutputDev::startFrame(int width, int height) 
-{
-    if(outer_clip_box) {
-       device->endclip(device);
-       outer_clip_box = 0;
-    }
-
-    device->startpage(device, width, height);
-    this->width = width;
-    this->height = height;
-}
-
 void GFXOutputDev::startPage(int pageNum, GfxState *state, double crop_x1, double crop_y1, double crop_x2, double crop_y2) 
 {
     this->currentpage = pageNum;
@@ -1434,11 +1424,6 @@ void GFXOutputDev::updateStrokeColor(GfxState *state)
     state->getStrokeRGB(&rgb);
 }
 
-void GFXOutputDev::setXRef(PDFDoc*doc, XRef *xref) 
-{
-    this->doc = doc;
-    this->xref = xref;
-}
 
 gfxfont_t* createGfxFont(GfxFont*xpdffont, FontInfo*src)
 {
@@ -1472,7 +1457,7 @@ gfxfont_t* createGfxFont(GfxFont*xpdffont, FontInfo*src)
                Guchar f;
                double x, y;
                path->getPoint(s, &x, &y, &f);
-               if(x > xmax)
+               if(!s || x > xmax)
                    xmax = x;
                if(f&splashPathFirst) {
                    drawer.moveTo(&drawer, x*scale, y*scale);
@@ -1531,6 +1516,9 @@ 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);
+    }
     if(!this->current_fontinfo->seen) {
        dumpFontInfo("<verbose>", gfxFont);
     }
@@ -1538,7 +1526,8 @@ void GFXOutputDev::updateFont(GfxState *state)
     gfxfont_t*font = gfxfontlist_findfont(this->gfxfontlist,id);
     if(!font) {
        font = createGfxFont(gfxFont, current_fontinfo);
-       gfxfontlist_addfont(this->gfxfontlist, font);
+        font->id = strdup(id);
+       this->gfxfontlist = gfxfontlist_addfont(this->gfxfontlist, font);
        device->addfont(device, font);
     }
     current_gfxfont = font;
@@ -2021,8 +2010,7 @@ void addGlobalFont(const char*filename)
     memset(&f, 0, sizeof(fontfile_t));
     f.filename = filename;
     if(fontnum < sizeof(fonts)/sizeof(fonts[0])) {
-       msg("<verbose> Adding font \"%s\".", filename);
-       msg("<warning> External fonts are not supported with this version. Ignoring font %s", filename);
+       msg("<notice> Adding font \"%s\".", filename);
        fonts[fontnum++] = f;
     } else {
        msg("<error> Too many external fonts. Not adding font file \"%s\".", filename);
@@ -2051,8 +2039,6 @@ void addGlobalLanguageDir(const char*dir)
 
 void addGlobalFontDir(const char*dirname)
 {
-    msg("<warning> External fonts are not supported with this version. Ignoring directory %s", dirname);
-    return;
 #ifdef HAVE_DIRENT_H
     msg("<notice> Adding %s to font directories", dirname);
     lastfontdir = strdup(dirname);
@@ -2079,8 +2065,7 @@ void addGlobalFontDir(const char*dirname)
            type=3;
        if(!strncasecmp(&name[l-4], ".ttf", 4)) 
            type=2;
-       if(type)
-       {
+       if(type) {
            char*fontname = (char*)malloc(strlen(dirname)+strlen(name)+2);
            strcpy(fontname, dirname);
             strcat(fontname, dirseparator());
@@ -2204,13 +2189,11 @@ void GFXOutputDev::beginTransparencyGroup(GfxState *state, double *bbox,
                                      GBool forSoftMask)
 {
     const char*colormodename = "";
-    BBox rect = mkBBox(state, bbox, this->width, this->height);
 
     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("using clipping rect %f/%f/%f/%f\n", rect.posx,rect.posy,rect.width,rect.height);
     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;