added new output devices
[swftools.git] / lib / pdf / GFXOutputDev.cc
index 52b92a5..da5df32 100644 (file)
@@ -1,4 +1,4 @@
-/* pdfswf.cc
+/* GFXOutputDev.cc
    implements a pdf output device (OutputDev).
 
    This file is part of swftools.
@@ -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"
@@ -194,7 +191,7 @@ GFXOutputState::GFXOutputState() {
 
 GBool GFXOutputDev::interpretType3Chars() 
 {
-    return this->do_interpretType3Chars;
+    return gTrue;
 }
 
 typedef struct _drawnchar
@@ -241,11 +238,109 @@ public:
        chars[num_chars].charid = charid;
     }
 };
+    
+char* writeOutStdFont(fontentry* f)
+{
+    FILE*fi;
+    char namebuf1[512];
+    char namebuf2[512];
+    char* tmpFileName = mktmpname(namebuf1);
 
-static char*getFontID(GfxFont*font);
+    sprintf(namebuf2, "%s.afm", tmpFileName);
+    fi = fopen(namebuf2, "wb");
+    if(!fi)
+        return 0;
+    fwrite(f->afm, 1, f->afmlen, fi);
+    fclose(fi);
 
-GFXOutputDev::GFXOutputDev(parameter_t*p)
+    sprintf(namebuf2, "%s.pfb", tmpFileName);
+    fi = fopen(namebuf2, "wb");
+    if(!fi)
+        return 0;
+    fwrite(f->pfb, 1, f->pfblen, fi);
+    fclose(fi);
+    return strdup(namebuf2);
+}
+void unlinkfont(char* filename)
+{
+    int l;
+    if(!filename)
+       return;
+    msg("<verbose> Removing temporary font file %s", filename);
+    l=strlen(filename);
+    unlink(filename);
+    if(!strncmp(&filename[l-4],".afm",4)) {
+       memcpy(&filename[l-4],".pfb",4); unlink(filename);
+       memcpy(&filename[l-4],".pfa",4); unlink(filename);
+       memcpy(&filename[l-4],".afm",4);
+       return;
+    } else 
+    if(!strncmp(&filename[l-4],".pfa",4)) {
+       memcpy(&filename[l-4],".afm",4); unlink(filename);
+       memcpy(&filename[l-4],".pfa",4);
+       return;
+    } else 
+    if(!strncmp(&filename[l-4],".pfb",4)) {
+       memcpy(&filename[l-4],".afm",4); unlink(filename);
+       memcpy(&filename[l-4],".pfb",4);
+       return;
+    }
+}
+
+
+GFXGlobalParams::GFXGlobalParams()
+: GlobalParams("")
+{
+    //setupBaseFonts(char *dir); //not tested yet
+}
+GFXGlobalParams::~GFXGlobalParams()
 {
+    msg("<verbose> Performing cleanups");
+    int t;
+    for(t=0;t<sizeof(pdf2t1map)/sizeof(fontentry);t++) {
+       if(pdf2t1map[t].fullfilename) {
+           unlinkfont(pdf2t1map[t].fullfilename);
+       }
+    }
+}
+DisplayFontParam *GFXGlobalParams::getDisplayFont(GString *fontName)
+{
+    msg("<verbose> looking for font %s in global params\n", fontName->getCString());
+
+    char*name = fontName->getCString();
+    /* see if it is a pdf standard font */
+    int t;
+    for(t=0;t<sizeof(pdf2t1map)/sizeof(fontentry);t++) {
+       if(!strcmp(name, pdf2t1map[t].pdffont)) {
+           if(!pdf2t1map[t].fullfilename) {
+               pdf2t1map[t].fullfilename = writeOutStdFont(&pdf2t1map[t]);
+               if(!pdf2t1map[t].fullfilename) {
+                   msg("<error> Couldn't save default font- is the Temp Directory writable?");
+               } else {
+                   msg("<verbose> Storing standard PDF font %s at %s", name, pdf2t1map[t].fullfilename);
+               }
+           }
+           DisplayFontParam *dfp = new DisplayFontParam(new GString(fontName), displayFontT1);
+           dfp->t1.fileName = new GString(pdf2t1map[t].fullfilename);
+           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(InfoOutputDev*info, PDFDoc*doc)
+{
+    this->info = info;
+    this->doc = doc;
+    this->xref = doc->getXRef();
+
     this->jpeginfo = 0;
     this->textmodeinfo = 0;
     this->linkinfo = 0;
@@ -265,51 +360,43 @@ GFXOutputDev::GFXOutputDev(parameter_t*p)
     this->user_clipy2 = 0;
     this->current_text_stroke = 0;
     this->current_text_clip = 0;
-    this->fontlist = 0;
     this->outer_clip_box = 0;
     this->pages = 0;
     this->pagebuflen = 0;
     this->pagepos = 0;
-    this->config_use_fontconfig=1;
     this->config_break_on_warning=0;
-    this->do_interpretType3Chars = gTrue;
+    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,"rawtext")) {
-        this->do_interpretType3Chars = atoi(value)^1;
-    } else if(!strcmp(key,"breakonwarning")) {
+    if(!strcmp(key,"breakonwarning")) {
        this->config_break_on_warning = atoi(value);
-    } else if(!strcmp(key,"fontconfig")) {
-        this->config_use_fontconfig = atoi(value);
-    } else {
-        msg("<warning> Ignored parameter: %s=%s", key, 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)
@@ -329,20 +416,6 @@ void GFXOutputDev::setClip(int x1,int y1,int x2,int y2)
     this->user_clipy2 = y2;
 }
 
-static char*getFontID(GfxFont*font)
-{
-    Ref*ref = font->getID();
-    GString*gstr = font->getName();
-    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(buf);
-}
-
 static char*getFontName(GfxFont*font)
 {
     char*fontid;
@@ -368,113 +441,6 @@ static char*getFontName(GfxFont*font)
     return fontname;
 }
 
-static char mybuf[1024];
-static char* gfxstate2str(GfxState *state)
-{
-  char*bufpos = mybuf;
-  GfxRGB rgb;
-  bufpos+=sprintf(bufpos,"CTM[%.3f/%.3f/%.3f/%.3f/%.3f/%.3f] ",
-                                   state->getCTM()[0],
-                                   state->getCTM()[1],
-                                   state->getCTM()[2],
-                                   state->getCTM()[3],
-                                   state->getCTM()[4],
-                                   state->getCTM()[5]);
-  if(state->getX1()!=0.0)
-  bufpos+=sprintf(bufpos,"X1-%.1f ",state->getX1());
-  if(state->getY1()!=0.0)
-  bufpos+=sprintf(bufpos,"Y1-%.1f ",state->getY1());
-  bufpos+=sprintf(bufpos,"X2-%.1f ",state->getX2());
-  bufpos+=sprintf(bufpos,"Y2-%.1f ",state->getY2());
-  bufpos+=sprintf(bufpos,"PW%.1f ",state->getPageWidth());
-  bufpos+=sprintf(bufpos,"PH%.1f ",state->getPageHeight());
-  /*bufpos+=sprintf(bufpos,"FC[%.1f/%.1f] ",
-         state->getFillColor()->c[0], state->getFillColor()->c[1]);
-  bufpos+=sprintf(bufpos,"SC[%.1f/%.1f] ",
-         state->getStrokeColor()->c[0], state->getFillColor()->c[1]);*/
-/*  bufpos+=sprintf(bufpos,"FC[%.1f/%.1f/%.1f/%.1f/%.1f/%.1f/%.1f/%.1f]",
-         state->getFillColor()->c[0], state->getFillColor()->c[1],
-         state->getFillColor()->c[2], state->getFillColor()->c[3],
-         state->getFillColor()->c[4], state->getFillColor()->c[5],
-         state->getFillColor()->c[6], state->getFillColor()->c[7]);
-  bufpos+=sprintf(bufpos,"SC[%.1f/%.1f/%.1f/%.1f/%.1f/%.1f/%.1f/%.1f]",
-         state->getStrokeColor()->c[0], state->getFillColor()->c[1],
-         state->getStrokeColor()->c[2], state->getFillColor()->c[3],
-         state->getStrokeColor()->c[4], state->getFillColor()->c[5],
-         state->getStrokeColor()->c[6], state->getFillColor()->c[7]);*/
-  state->getFillRGB(&rgb);
-  if(rgb.r || rgb.g || rgb.b)
-  bufpos+=sprintf(bufpos,"FR[%.1f/%.1f/%.1f] ", rgb.r,rgb.g,rgb.b);
-  state->getStrokeRGB(&rgb);
-  if(rgb.r || rgb.g || rgb.b)
-  bufpos+=sprintf(bufpos,"SR[%.1f/%.1f/%.1f] ", rgb.r,rgb.g,rgb.b);
-  if(state->getFillColorSpace()->getNComps()>1)
-  bufpos+=sprintf(bufpos,"CS[[%d]] ",state->getFillColorSpace()->getNComps());
-  if(state->getStrokeColorSpace()->getNComps()>1)
-  bufpos+=sprintf(bufpos,"SS[[%d]] ",state->getStrokeColorSpace()->getNComps());
-  if(state->getFillPattern())
-  bufpos+=sprintf(bufpos,"FP%08x ", state->getFillPattern());
-  if(state->getStrokePattern())
-  bufpos+=sprintf(bufpos,"SP%08x ", state->getStrokePattern());
-  if(state->getFillOpacity()!=1.0)
-  bufpos+=sprintf(bufpos,"FO%.1f ", state->getFillOpacity());
-  if(state->getStrokeOpacity()!=1.0)
-  bufpos+=sprintf(bufpos,"SO%.1f ", state->getStrokeOpacity());
-
-  bufpos+=sprintf(bufpos,"LW%.1f ", state->getLineWidth());
-  double * dash;
-  int length;
-  double start;
-  state->getLineDash(&dash, &length, &start);
-  int t;
-  if(length)
-  {
-      bufpos+=sprintf(bufpos,"DASH%.1f[",start);
-      for(t=0;t<length;t++) {
-         bufpos+=sprintf(bufpos,"D%.1f",dash[t]);
-      }
-      bufpos+=sprintf(bufpos,"]");
-  }
-
-  if(state->getFlatness()!=1)
-  bufpos+=sprintf(bufpos,"F%d ", state->getFlatness());
-  if(state->getLineJoin()!=0)
-  bufpos+=sprintf(bufpos,"J%d ", state->getLineJoin());
-  if(state->getLineJoin()!=0)
-  bufpos+=sprintf(bufpos,"C%d ", state->getLineCap());
-  if(state->getLineJoin()!=0)
-  bufpos+=sprintf(bufpos,"ML%d ", state->getMiterLimit());
-
-  if(state->getFont() && getFontID(state->getFont()))
-  bufpos+=sprintf(bufpos,"F\"%s\" ",getFontID(state->getFont()));
-  bufpos+=sprintf(bufpos,"FS%.1f ", state->getFontSize());
-  bufpos+=sprintf(bufpos,"MAT[%.1f/%.1f/%.1f/%.1f/%.1f/%.1f] ", state->getTextMat()[0],state->getTextMat()[1],state->getTextMat()[2],
-                                  state->getTextMat()[3],state->getTextMat()[4],state->getTextMat()[5]);
-  if(state->getCharSpace())
-  bufpos+=sprintf(bufpos,"CS%.5f ", state->getCharSpace());
-  if(state->getWordSpace())
-  bufpos+=sprintf(bufpos,"WS%.5f ", state->getWordSpace());
-  if(state->getHorizScaling()!=1.0)
-  bufpos+=sprintf(bufpos,"SC%.1f ", state->getHorizScaling());
-  if(state->getLeading())
-  bufpos+=sprintf(bufpos,"L%.1f ", state->getLeading());
-  if(state->getRise())
-  bufpos+=sprintf(bufpos,"R%.1f ", state->getRise());
-  if(state->getRender())
-  bufpos+=sprintf(bufpos,"R%d ", state->getRender());
-  bufpos+=sprintf(bufpos,"P%08x ", state->getPath());
-  bufpos+=sprintf(bufpos,"CX%.1f ", state->getCurX());
-  bufpos+=sprintf(bufpos,"CY%.1f ", state->getCurY());
-  if(state->getLineX())
-  bufpos+=sprintf(bufpos,"LX%.1f ", state->getLineX());
-  if(state->getLineY())
-  bufpos+=sprintf(bufpos,"LY%.1f ", state->getLineY());
-  bufpos+=sprintf(bufpos," ");
-  return mybuf;
-}
-
 static void dumpFontInfo(const char*loglevel, GfxFont*font);
 static int lastdumps[1024];
 static int lastdumppos = 0;
@@ -570,7 +536,6 @@ static void dumpFontInfo(const char*loglevel, GfxFont*font)
 //void GFXOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, GBool inlineImg) {printf("void GFXOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, GBool inlineImg) \n");}
 //void GFXOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, GBool inlineImg) {printf("void GFXOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, GBool inlineImg) \n");}
 
-
 void dump_outline(gfxline_t*line)
 {
     while(line) {
@@ -680,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
@@ -723,8 +692,6 @@ void GFXOutputDev::strokeGfxline(GfxState *state, gfxline_t*line, int flags)
     if(dashnum && ldash) {
        float * dash = (float*)malloc(sizeof(float)*(dashnum+1));
        int t;
-       double cut = 0;
-       int fixzero = 0;
        msg("<trace> %d dashes", dashnum);
        msg("<trace> |  phase: %f", dashphase);
        for(t=0;t<dashnum;t++) {
@@ -756,6 +723,12 @@ void GFXOutputDev::strokeGfxline(GfxState *state, gfxline_t*line, int flags)
     if(flags&STROKE_FILL) {
         ArtSVP* svp = gfxstrokeToSVP(line, width, capType, joinType, miterLimit);
         gfxline_t*gfxline = SVPtogfxline(svp);
+       if(getLogLevel() >= LOGLEVEL_TRACE)  {
+           dump_outline(gfxline);
+       }
+       if(!gfxline) {
+           msg("<warning> Empty polygon (resulting from stroked line)");
+       }
         if(flags&STROKE_CLIP) {
             device->startclip(device, gfxline);
             states[statepos].clipping++;
@@ -835,16 +808,14 @@ void GFXOutputDev::clipToStrokePath(GfxState *state)
 {
     GfxPath * path = state->getPath();
     gfxline_t*line= gfxPath_to_gfxline(state, path, 0, user_movex + clipmovex, user_movey + clipmovey);
-    strokeGfxline(state, line, STROKE_FILL|STROKE_CLIP);
-    gfxline_free(line);
-}
 
-void GFXOutputDev::endframe()
-{
-    if(outer_clip_box) {
-       device->endclip(device);
-       outer_clip_box = 0;
+    if(getLogLevel() >= LOGLEVEL_TRACE)  {
+        msg("<trace> cliptostrokepath\n");
+        dump_outline(line);
     }
+
+    strokeGfxline(state, line, STROKE_FILL|STROKE_CLIP);
+    gfxline_free(line);
 }
 
 void GFXOutputDev::finish()
@@ -865,16 +836,7 @@ GFXOutputDev::~GFXOutputDev()
        free(this->pages); this->pages = 0;
     }
 
-    fontlist_t*l = this->fontlist;
-    while(l) {
-       fontlist_t*next = l->next;
-       l->next = 0;
-       gfxfont_free(l->font);
-       free(l->filename);l->filename=0;
-       free(l);
-       l = next;
-    }
-    this->fontlist = 0;
+    gfxfontlist_free(this->gfxfontlist, 1);
 };
 GBool GFXOutputDev::upsideDown() 
 {
@@ -919,85 +881,32 @@ char* makeStringPrintable(char*str)
     tmp_printstr[len] = 0;
     return tmp_printstr;
 }
-
-
-int getGfxCharID(gfxfont_t*font, int charnr, char *charname, int u)
+#define INTERNAL_FONT_SIZE 1024.0
+void GFXOutputDev::updateFontMatrix(GfxState*state)
 {
-    const char*uniname = 0;
-    if(!font)
-        return charnr;
-    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);
-               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,charname)) {
-               msg("<debug> Char [%d,>>%s<<,%d] maps to %d\n", charnr, charname, u, t);
-               return t;
-           }
-       }
-    }
+    double* ctm = state->getCTM();
+    double fontSize = state->getFontSize();
+    double*textMat = state->getTextMat();
 
-    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];
-    }
-    /* try to use the unicode|0xe000 (needed for some WingDings fonts)
-       FIXME: do this only if we know the font is wingdings?
-     */
-    u |= 0xe000;
-    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];
-    }
-
-    if(charnr>=0 && charnr<font->num_glyphs) {
-       msg("<debug> Char [>%d<,%s,%d] maps to %d\n", charnr, charname, u, charnr);
-       return charnr;
-    }
-    
-    return -1;
+    /*  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;
 }
 
-
 void GFXOutputDev::beginString(GfxState *state, GString *s) 
 { 
     int render = state->getRender();
@@ -1006,20 +915,6 @@ void GFXOutputDev::beginString(GfxState *state, GString *s)
     }
 
     msg("<trace> beginString(%s) render=%d", makeStringPrintable(s->getCString()), render);
-    double m11,m21,m12,m22;
-//    msg("<debug> %s beginstring \"%s\"\n", gfxstate2str(state), s->getCString());
-    state->getFontTransMat(&m11, &m12, &m21, &m22);
-    m11 *= state->getHorizScaling();
-    m21 *= state->getHorizScaling();
-
-    this->current_font_matrix.m00 = m11 / 1024.0;
-    this->current_font_matrix.m01 = m12 / 1024.0;
-    this->current_font_matrix.m10 = -m21 / 1024.0;
-    this->current_font_matrix.m11 = -m22 / 1024.0;
-    this->current_font_matrix.tx = 0;
-    this->current_font_matrix.ty = 0;
-
-    gfxmatrix_t m = this->current_font_matrix;
 }
 
 static gfxline_t* mkEmptyGfxShape(double x, double y)
@@ -1029,115 +924,60 @@ static gfxline_t* mkEmptyGfxShape(double x, double y)
     return line;
 }
 
+static char isValidUnicode(int c)
+{
+    if(c>=32 && c<0x2fffe)
+       return 1;
+    return 0;
+}
+
 void GFXOutputDev::drawChar(GfxState *state, double x, double y,
                        double dx, double dy,
                        double originX, double originY,
-                       CharCode c, int nBytes, Unicode *_u, int uLen)
+                       CharCode charid, int nBytes, Unicode *_u, int uLen)
 {
-    int render = state->getRender();
-    // check for invisible text -- this is used by Acrobat Capture
-    if (render == 3) {
-       msg("<debug> Ignoring invisible text: char %d at %f,%f", c, x, y);
+    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);
        return;
     }
+  
+    CharCode glyphid = current_fontinfo->glyphs[charid]->glyphid;
 
+    int render = state->getRender();
     gfxcolor_t col = getFillColor(state);
 
-    Gushort *CIDToGIDMap = 0;
+    // 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();
 
-    if(font->getType() == fontType3 && do_interpretType3Chars) {
+    if(font->getType() == fontType3) {
        /* type 3 chars are passed as graphics */
        msg("<debug> type3 char at %f/%f", x, y);
        return;
     }
-    
-    Unicode u=0;
-    char*name=0;
-
-    if(uLen)
-       u = _u[0];
-
-/*    char*fontname = getFontName(font);
-    if(u<256 && strstr(fontname, "ingdings")) {
-        // symbols are at 0xe000 in the unicode table
-        u |= 0xe000;
-    }
-    free(fontname);*/
-
-    if(font->isCIDFont()) {
-       GfxCIDFont*cfont = (GfxCIDFont*)font;
-
-       if(font->getType() == fontCIDType2)
-           CIDToGIDMap = cfont->getCIDToGID();
-    } else {
-       Gfx8BitFont*font8;
-       font8 = (Gfx8BitFont*)font;
-       char**enc=font8->getEncoding();
-       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);
-       c = CIDToGIDMap[c];
-    } else {
-       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 = -1;
-   
-    if(uLen<=1) {
-       charid = getGfxCharID(current_gfxfont, c, name, u);
-    } else {
-       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
-              the characters one-by-one. */
-           int t;
-           msg("<warning> ligature %d missing in font %s\n", c, current_gfxfont->id);
-           for(t=0;t<uLen;t++) {
-               drawChar(state, x, y, dx, dy, originX, originY, c, nBytes, _u+t, 1);
-           }
-           return;
-       }
-    }
-    if(charid<0) {
-       msg("<warning> Didn't find character '%s' (c=%d,u=%d) in current charset (%s, %d characters)", 
-               FIXNULL(name),c, u, FIXNULL((char*)current_gfxfont->id), current_gfxfont->num_glyphs);
-       return;
-    }
+    Unicode u = uLen?(_u[0]):0;
+    msg("<debug> drawChar(%f,%f,c='%c' (%d), u=%d <%d>) CID=%d render=%d glyphid=%d\n",x,y,(charid&127)>=32?charid:'?', charid, u, uLen, font->isCIDFont(), render, glyphid);
 
     gfxmatrix_t m = this->current_font_matrix;
     state->transform(x, y, &m.tx, &m.ty);
     m.tx += user_movex + clipmovex;
     m.ty += user_movey + clipmovey;
 
-    if((!name || strcmp(name, "space")) && charid!=32 && u!=32)
-    {
-        gfxline_t*l = current_gfxfont->glyphs[charid].line;
-        double x,y;
-        char ok = 0;
-        while(l) {
-            if((l->type == gfx_lineTo || l->type == gfx_splineTo) && l->x!=x && l->y!=y) {
-                ok = 1;
-            }
-            l = l->next;
-        }
-        if(!ok) {
-            msg("<warning> Drawing empty character charid=%d", charid);
-        }
-    }
-
-    if(render == RENDER_FILL) {
-       device->drawchar(device, current_gfxfont, charid, &col, &m);
+    if(render == RENDER_FILL || render == RENDER_INVISIBLE) {
+       device->drawchar(device, current_gfxfont, glyphid, &col, &m);
     } else {
        msg("<debug> Drawing glyph %d as shape", charid);
        if(!textmodeinfo) {
            msg("<notice> Some texts will be rendered as shape");
            textmodeinfo = 1;
        }
-       gfxline_t*glyph = current_gfxfont->glyphs[charid].line;
+       gfxline_t*glyph = current_gfxfont->glyphs[glyphid].line;
        gfxline_t*tglyph = gfxline_clone(glyph);
        gfxline_transform(tglyph, &m);
        if((render&3) != RENDER_INVISIBLE) {
@@ -1201,38 +1041,49 @@ void GFXOutputDev::endTextObject(GfxState *state)
 /* the logic seems to be as following:
    first, beginType3Char is called, with the charcode and the coordinates.
    if this function returns true, it already knew about the char and has now drawn it.
-   if the function returns false, it's a new char, and type3D1 is called with some parameters-
-   the all draw operations until endType3Char are part of the char (which in this moment is
+   if the function returns false, it's a new char, and type3D0 and/or type3D1 might be 
+   called with some parameters.
+   Afterwards, all draw operations until endType3Char are part of the char (which in this moment is
    at the position first passed to beginType3Char). the char ends with endType3Char.
 
    The drawing operations between beginType3Char and endType3Char are somewhat different to
-   the normal ones. For example, the fillcolor equals the stroke color.
+   the normal ones. For example, the fillcolor equals the stroke color. (Because the stroke
+   color determines the color of a font)
 */
 
-GBool GFXOutputDev::beginType3Char(GfxState *state, double x, double y, double dx, double dy, CharCode code, Unicode *u, int uLen)
+GBool GFXOutputDev::beginType3Char(GfxState *state, double x, double y, double dx, double dy, CharCode charid, Unicode *u, int uLen)
 {
-    msg("<debug> beginType3Char %d, %08x, %d", code, *u, uLen);
+    msg("<debug> beginType3Char %d u=%d", charid, uLen?u[0]:0);
     type3active = 1;
+    
+    if(config_extrafontdata && current_fontinfo) {
+
+       gfxmatrix_t m = this->current_font_matrix;
+       state->transform(0, 0, &m.tx, &m.ty);
+       m.m00*=INTERNAL_FONT_SIZE;
+       m.m01*=INTERNAL_FONT_SIZE;
+       m.m10*=INTERNAL_FONT_SIZE;
+       m.m11*=INTERNAL_FONT_SIZE;
+       m.tx += user_movex + clipmovex;
+       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);
+           return gFalse;
+       }
+       gfxcolor_t col={0,0,0,0};
+       CharCode glyphid = current_fontinfo->glyphs[charid]->glyphid;
+       device->drawchar(device, current_gfxfont, glyphid, &col, &m);
+    }
 
-    /*int t;
-
-    gfxcolor_t col={255,0,0,0};
-    gfxmatrix_t m = {1,0,0, 0,1,0};
-
-    for(t=0;t<uLen;t++) {
-       device->drawchar(device, 0, u[t], &col, &m);
-    }*/
 
     /* the character itself is going to be passed using the draw functions */
     return gFalse; /* gTrue= is_in_cache? */
 }
 
 void GFXOutputDev::type3D0(GfxState *state, double wx, double wy) {
-    msg("<debug> type3D0 width=%f height=%f", wx, wy);
 }
 void GFXOutputDev::type3D1(GfxState *state, double wx, double wy, double llx, double lly, double urx, double ury) {
-    msg("<debug> type3D1 width=%f height=%f bbox=(%f,%f,%f,%f)", wx, wy,
-           llx,lly,urx,ury);
 }
 
 void GFXOutputDev::endType3Char(GfxState *state)
@@ -1241,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;
@@ -1303,7 +1142,9 @@ void GFXOutputDev::startPage(int pageNum, GfxState *state, double crop_x1, doubl
     clippath[3].type = gfx_lineTo;clippath[3].x = x1; clippath[3].y = y2; clippath[3].next = &clippath[4];
     clippath[4].type = gfx_lineTo;clippath[4].x = x1; clippath[4].y = y1; clippath[4].next = 0;
     device->startclip(device, clippath); outer_clip_box = 1;
-    device->fill(device, clippath, &white);
+    if(!config_transparent) {
+        device->fill(device, clippath, &white);
+    }
 }
 
 
@@ -1526,63 +1367,6 @@ void GFXOutputDev::restoreState(GfxState *state) {
   statepos--;
 }
 
-char* writeOutStdFont(fontentry* f)
-{
-    FILE*fi;
-    char namebuf1[512];
-    char namebuf2[512];
-    char* tmpFileName = mktmpname(namebuf1);
-
-    sprintf(namebuf2, "%s.afm", tmpFileName);
-    fi = fopen(namebuf2, "wb");
-    if(!fi)
-        return 0;
-    fwrite(f->afm, 1, f->afmlen, fi);
-    fclose(fi);
-
-    sprintf(namebuf2, "%s.pfb", tmpFileName);
-    fi = fopen(namebuf2, "wb");
-    if(!fi)
-        return 0;
-    fwrite(f->pfb, 1, f->pfblen, fi);
-    fclose(fi);
-
-    return strdup(namebuf2);
-}
-
-char* GFXOutputDev::searchFont(const char*name) 
-{      
-    int i;
-    char*filename=0;
-       
-    msg("<verbose> SearchFont(%s)", name);
-
-    /* see if it is a pdf standard font */
-    for(i=0;i<sizeof(pdf2t1map)/sizeof(fontentry);i++) 
-    {
-       if(!strcmp(name, pdf2t1map[i].pdffont))
-       {
-            if(!pdf2t1map[i].fullfilename) {
-                pdf2t1map[i].fullfilename = writeOutStdFont(&pdf2t1map[i]);
-                if(!pdf2t1map[i].fullfilename) {
-                    msg("<error> Couldn't save default font- is the Temp Directory writable?");
-                } else {
-                    msg("<verbose> Storing standard PDF font %s at %s", name, pdf2t1map[i].fullfilename);
-                }
-            }
-           return strdup(pdf2t1map[i].fullfilename);
-       }
-    }
-    /* else look in all font files */
-    for(i=0;i<fontnum;i++) 
-    {
-       if(strstr(fonts[i].filename, name)) {
-           return strdup(fonts[i].filename);
-       }
-    }
-    return 0;
-}
-
 void GFXOutputDev::updateLineWidth(GfxState *state)
 {
     double width = state->getTransformedLineWidth();
@@ -1640,451 +1424,116 @@ void GFXOutputDev::updateStrokeColor(GfxState *state)
     state->getStrokeRGB(&rgb);
 }
 
-void FoFiWrite(void *stream, char *data, int len)
-{
-   int ret = fwrite(data, len, 1, (FILE*)stream);
-}
-
-char*GFXOutputDev::writeEmbeddedFontToFile(XRef*ref, GfxFont*font)
-{
-    char*tmpFileName = NULL;
-    FILE *f;
-    int c;
-    char *fontBuf;
-    int fontLen;
-    Ref embRef;
-    Object refObj, strObj;
-    char namebuf[512];
-    tmpFileName = mktmpname(namebuf);
-    int ret;
-
-    ret = font->getEmbeddedFontID(&embRef);
-    if(!ret) {
-       msg("<verbose> Didn't get embedded font id");
-       /* not embedded- the caller should now search the font
-          directories for this font */
-       return 0;
-    }
-
-    f = fopen(tmpFileName, "wb");
-    if (!f) {
-      msg("<error> Couldn't create temporary Type 1 font file");
-       return 0;
-    }
-
-    /*if(font->isCIDFont()) {
-       GfxCIDFont* cidFont = (GfxCIDFont *)font;
-       GString c = cidFont->getCollection();
-       msg("<notice> Collection: %s", c.getCString());
-    }*/
-
-    //if (font->getType() == fontType1C) {
-    if (0) { //font->getType() == fontType1C) {
-      if (!(fontBuf = font->readEmbFontFile(xref, &fontLen))) {
-       fclose(f);
-       msg("<error> Couldn't read embedded font file");
-       return 0;
-      }
-      FoFiType1C *cvt = FoFiType1C::make(fontBuf, fontLen);
-      if(!cvt) return 0;
-      cvt->convertToType1(0, NULL, gTrue, FoFiWrite, f);
-      //cvt->convertToCIDType0("test", f);
-      //cvt->convertToType0("test", f);
-      delete cvt;
-      gfree(fontBuf);
-    } else if(font->getType() == fontTrueType) {
-      msg("<verbose> writing font using TrueTypeFontFile::writeTTF");
-      if (!(fontBuf = font->readEmbFontFile(xref, &fontLen))) {
-       fclose(f);
-       msg("<error> Couldn't read embedded font file");
-       return 0;
-      }
-      FoFiTrueType *cvt = FoFiTrueType::make(fontBuf, fontLen);
-      cvt->writeTTF(FoFiWrite, f);
-      delete cvt;
-      gfree(fontBuf);
-    } else {
-      font->getEmbeddedFontID(&embRef);
-      refObj.initRef(embRef.num, embRef.gen);
-      refObj.fetch(ref, &strObj);
-      refObj.free();
-      strObj.streamReset();
-      int f4[4];
-      char f4c[4];
-      int t;
-      for(t=0;t<4;t++) {
-         f4[t] = strObj.streamGetChar();
-         f4c[t] = (char)f4[t];
-         if(f4[t] == EOF)
-             break;
-      }
-      if(t==4) {
-         if(!strncmp(f4c, "true", 4)) {
-             /* some weird TTF fonts don't start with 0,1,0,0 but with "true".
-                Change this on the fly */
-             f4[0] = f4[2] = f4[3] = 0;
-             f4[1] = 1;
-         }
-         fputc(f4[0], f);
-         fputc(f4[1], f);
-         fputc(f4[2], f);
-         fputc(f4[3], f);
-
-         while ((c = strObj.streamGetChar()) != EOF) {
-           fputc(c, f);
-         }
-      }
-      strObj.streamClose();
-      strObj.free();
-    }
-    fclose(f);
 
-    return strdup(tmpFileName);
-}
-    
-char* GFXOutputDev::searchForSuitableFont(GfxFont*gfxFont)
+gfxfont_t* createGfxFont(GfxFont*xpdffont, FontInfo*src)
 {
-    char*name = getFontName(gfxFont);
-    char*fontname = 0;
-    char*filename = 0;
+    gfxfont_t*font = (gfxfont_t*)malloc(sizeof(gfxfont_t));
+    memset(font, 0, sizeof(gfxfont_t));
 
-    if(!this->config_use_fontconfig)
-        return 0;
-    
-#ifdef HAVE_FONTCONFIG
-    FcPattern *pattern, *match;
-    FcResult result;
-    FcChar8 *v;
-
-    static int fcinitcalled = false; 
-        
-    msg("<debug> searchForSuitableFont(%s)", name);
-    
-    // call init ony once
-    if (!fcinitcalled) {
-        msg("<debug> Initializing FontConfig...");
-        fcinitcalled = true;
-       if(!FcInit()) {
-            msg("<debug> FontConfig Initialization failed. Disabling.");
-            config_use_fontconfig = 0;
-            return 0;
-        }
-        msg("<debug> ...initialized FontConfig");
-    }
-   
-    msg("<debug> FontConfig: Create \"%s\" Family Pattern", name);
-    pattern = FcPatternBuild(NULL, FC_FAMILY, FcTypeString, name, NULL);
-    if (gfxFont->isItalic()) // check for italic
-        msg("<debug> FontConfig: Adding Italic Slant");
-       FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC);
-    if (gfxFont->isBold()) // check for bold
-        msg("<debug> FontConfig: Adding Bold Weight");
-        FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD);
-
-    msg("<debug> FontConfig: Try to match...");
-    // configure and match using the original font name 
-    FcConfigSubstitute(0, pattern, FcMatchPattern); 
-    FcDefaultSubstitute(pattern);
-    match = FcFontMatch(0, pattern, &result);
-    
-    if (FcPatternGetString(match, "family", 0, &v) == FcResultMatch) {
-        msg("<debug> FontConfig: family=%s", (char*)v);
-        // if we get an exact match
-        if (strcmp((char *)v, name) == 0) {
-           if (FcPatternGetString(match, "file", 0, &v) == FcResultMatch) {
-               filename = strdup((char*)v); // mem leak
-               char *nfn = strrchr(filename, '/');
-               if(nfn) fontname = strdup(nfn+1);
-               else    fontname = filename;
-            }
-            msg("<debug> FontConfig: Returning \"%s\"", fontname);
-        } else {
-            // initialize patterns
-            FcPatternDestroy(pattern);
-           FcPatternDestroy(match);
-
-            // now match against serif etc.
-           if (gfxFont->isSerif()) {
-                msg("<debug> FontConfig: Create Serif Family Pattern");
-                pattern = FcPatternBuild (NULL, FC_FAMILY, FcTypeString, "serif", NULL);
-            } else if (gfxFont->isFixedWidth()) {
-                msg("<debug> FontConfig: Create Monospace Family Pattern");
-                pattern = FcPatternBuild (NULL, FC_FAMILY, FcTypeString, "monospace", NULL);
-            } else {
-                msg("<debug> FontConfig: Create Sans Family Pattern");
-                pattern = FcPatternBuild (NULL, FC_FAMILY, FcTypeString, "sans", NULL);
-            }
-
-            // check for italic
-            if (gfxFont->isItalic()) {
-                msg("<debug> FontConfig: Adding Italic Slant");
-                int bb = FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC);
-            }
-            // check for bold
-            if (gfxFont->isBold()) {
-                msg("<debug> FontConfig: Adding Bold Weight");
-                int bb = FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD);
-            }
-
-            msg("<debug> FontConfig: Try to match... (2)");
-            // configure and match using serif etc
-           FcConfigSubstitute (0, pattern, FcMatchPattern);
-            FcDefaultSubstitute (pattern);
-            match = FcFontMatch (0, pattern, &result);
-            
-            if (FcPatternGetString(match, "file", 0, &v) == FcResultMatch) {
-               filename = strdup((char*)v); // mem leak
-               char *nfn = strrchr(filename, '/');
-               if(nfn) fontname = strdup(nfn+1);
-               else    fontname = filename;
-           }
-            msg("<debug> FontConfig: Returning \"%s\"", fontname);
-        }        
-    }
-
-    //printf("FONTCONFIG: pattern");
-    //FcPatternPrint(pattern);
-    //printf("FONTCONFIG: match");
-    //FcPatternPrint(match);
-    FcPatternDestroy(pattern);
-    FcPatternDestroy(match);
-
-    pdfswf_addfont(filename);
-    return fontname;
-#else
-    return 0;
-#endif
-}
-
-char* GFXOutputDev::substituteFont(GfxFont*gfxFont, char* oldname)
-{
-    const char*fontname = 0, *filename = 0;
-    msg("<notice> substituteFont(%s)", oldname);
-
-    if(!(fontname = searchForSuitableFont(gfxFont))) {
-       fontname = "Times-Roman";
-    }
-    filename = searchFont(fontname);
-    if(!filename) {
-       msg("<error> Couldn't find font %s- did you install the default fonts?", fontname);
-       return 0;
-    }
-
-    if(substitutepos>=sizeof(substitutesource)/sizeof(char*)) {
-       msg("<fatal> Too many fonts in file.");
-       exit(1);
-    }
-    if(oldname) {
-       substitutesource[substitutepos] = strdup(oldname); //mem leak
-       substitutetarget[substitutepos] = fontname;
-       msg("<notice> substituting %s -> %s", FIXNULL(oldname), FIXNULL(fontname));
-       substitutepos ++;
-    }
-    return strdup(filename); //mem leak
-}
-
-void unlinkfont(char* filename)
-{
-    int l;
-    if(!filename)
-       return;
-    l=strlen(filename);
-    unlink(filename);
-    if(!strncmp(&filename[l-4],".afm",4)) {
-       memcpy(&filename[l-4],".pfb",4);
-       unlink(filename);
-       memcpy(&filename[l-4],".pfa",4);
-       unlink(filename);
-       memcpy(&filename[l-4],".afm",4);
-       return;
-    } else 
-    if(!strncmp(&filename[l-4],".pfa",4)) {
-       memcpy(&filename[l-4],".afm",4);
-       unlink(filename);
-       memcpy(&filename[l-4],".pfa",4);
-       return;
-    } else 
-    if(!strncmp(&filename[l-4],".pfb",4)) {
-       memcpy(&filename[l-4],".afm",4);
-       unlink(filename);
-       memcpy(&filename[l-4],".pfb",4);
-       return;
-    }
-}
-
-void GFXOutputDev::setXRef(PDFDoc*doc, XRef *xref) 
-{
-    this->doc = doc;
-    this->xref = xref;
-}
-
-int GFXOutputDev::setGfxFont(char*id, char*name, char*filename, double maxSize)
-{
-    gfxfont_t*font = 0;
-    fontlist_t*last=0,*l = this->fontlist;
-
-    if(!id)
-       msg("<error> Internal Error: FontID is null");
-
-    /* TODO: should this be part of the state? */
-    while(l) {
-       last = l;
-       if(!strcmp(l->font->id, id)) {
-           current_gfxfont = l->font;
-           font = l->font;
-           device->addfont(device, current_gfxfont);
-           return 1;
+    font->glyphs = (gfxglyph_t*)malloc(sizeof(gfxglyph_t)*src->num_glyphs);
+    memset(font->glyphs, 0, sizeof(gfxglyph_t)*src->num_glyphs);
+    font->id = strdup(getFontID(xpdffont));
+    int t;
+    double quality = (INTERNAL_FONT_SIZE * 0.05) / src->max_size;
+    double scale = 1;
+    //printf("%d glyphs\n", font->num_glyphs);
+    font->num_glyphs = 0;
+    for(t=0;t<src->num_glyphs;t++) {
+       if(src->glyphs[t]) {
+           SplashPath*path = src->glyphs[t]->path;
+           int len = path?path->getLength():0;
+           //printf("glyph %d) %08x (%d line segments)\n", t, path, len);
+           gfxglyph_t*glyph = &font->glyphs[font->num_glyphs];
+           src->glyphs[t]->glyphid = font->num_glyphs;
+           glyph->unicode = src->glyphs[t]->unicode;
+           if(glyph->unicode >= font->max_unicode)
+               font->max_unicode = glyph->unicode+1;
+           gfxdrawer_t drawer;
+           gfxdrawer_target_gfxline(&drawer);
+           int s;
+           int count = 0;
+           double xmax = 0;
+           for(s=0;s<len;s++) {
+               Guchar f;
+               double x, y;
+               path->getPoint(s, &x, &y, &f);
+               if(!s || x > xmax)
+                   xmax = x;
+               if(f&splashPathFirst) {
+                   drawer.moveTo(&drawer, x*scale, y*scale);
+               }
+               if(f&splashPathCurve) {
+                   double x2,y2;
+                   path->getPoint(++s, &x2, &y2, &f);
+                   if(f&splashPathCurve) {
+                       double x3,y3;
+                       path->getPoint(++s, &x3, &y3, &f);
+                       gfxdraw_cubicTo(&drawer, x*scale, y*scale, x2*scale, y2*scale, x3*scale, y3*scale, quality);
+                   } else {
+                       drawer.splineTo(&drawer, x*scale, y*scale, x2*scale, y2*scale);
+                   }
+               } else {
+                   drawer.lineTo(&drawer, x*scale, y*scale);
+               }
+            //   printf("%f %f %s %s\n", x, y, (f&splashPathCurve)?"curve":"",
+            //                           (f&splashPathFirst)?"first":"",
+            //                           (f&splashPathLast)?"last":"");
+           }
+           glyph->line = (gfxline_t*)drawer.result(&drawer);
+           glyph->advance = xmax*scale; // we don't know the real advance value, so this'll have to do
+           font->num_glyphs++;
        }
-       l = l->next;
-    }
-    if(!filename) return 0;
-
-    /* A font size of e.g. 9 means the font will be scaled down by
-       1024 and scaled up by 9. So to have a maximum error of 1/20px,
-       we have to divide 0.05 by (fontsize/1024)
-     */
-    double quality = (1024 * 0.05) / maxSize;
-   
-    msg("<verbose> Loading %s...", filename);
-    font = gfxfont_load(id, filename, quality);
-    if(!font) {
-       msg("<verbose> Couldn't load Font %s (%s)", filename, id);
-       return 0;
     }
-    msg("<verbose> Font %s (%s) loaded successfully", filename, id);
+    font->unicode2glyph = (int*)malloc(sizeof(int)*font->max_unicode);
+    memset(font->unicode2glyph, -1, sizeof(int)*font->max_unicode);
+    for(t=0;t<font->num_glyphs;t++) {
+       if(font->glyphs[t].unicode>0 && font->glyphs[t].unicode<font->max_unicode) {
+           font->unicode2glyph[font->glyphs[t].unicode] = t;
+       }
 
-    l = new fontlist_t;
-    l->font = font;
-    l->filename = strdup(filename);
-    l->next = 0;
-    current_gfxfont = l->font;
-    if(last) {
-       last->next = l;
-    } else {
-       this->fontlist = l;
     }
-    device->addfont(device, current_gfxfont);
-    return 1;
+    msg("<trace> %d glyphs.", t, font->num_glyphs);
+    return font;
 }
 
 void GFXOutputDev::updateFont(GfxState *state) 
 {
-    GfxFont*gfxFont = state->getFont();
-      
+    GfxFont* gfxFont = state->getFont();
     if (!gfxFont) {
-       return;
+       return; 
     }  
-    
-    char * fontid = getFontID(gfxFont);
-    char * fontname = getFontName(gfxFont);
-
-    double maxSize = 1.0;
-
-    if(this->info) {
-       maxSize = this->info->getMaximumFontSize(fontid);
-    }
-    
-    int t;
-    /* first, look if we substituted this font before-
-       this way, we don't initialize the T1 Fonts
-       too often */
-    for(t=0;t<substitutepos;t++) {
-       if(!strcmp(fontid, substitutesource[t])) {
-           free(fontid);fontid=0;
-           fontid = strdup(substitutetarget[t]);
-           break;
+    char*id = getFontID(gfxFont);
+    msg("<verbose> Updating font to %s", id);
+    if(gfxFont->getType() == fontType3) {
+       infofeature("Type3 fonts");
+       if(!config_extrafontdata) {
+           return;
        }
     }
-
-    /* second, see if this is a font which was used before-
-       if so, we are done */
-    if(setGfxFont(fontid, fontname, 0, 0)) {
-       free(fontid);
-       free(fontname);
-       return;
-    }
-/*    if(swfoutput_queryfont(&device, fontid))
-       swfoutput_setfont(&device, fontid, 0);
-       
-       msg("<debug> updateFont(%s) [cached]", fontid);
-       return;
-    }*/
-
-    // look for Type 3 font
-    if (gfxFont->getType() == fontType3) {
-       if(!type3Warning) {
-           type3Warning = gTrue;
-           showFontError(gfxFont, 2);
-       }
-       free(fontid);
-       free(fontname);
-       return;
+    if(!id) {
+       msg("<error> Internal Error: FontID is null");
+       return; 
     }
 
-    /* now either load the font, or find a substitution */
-
-    Ref embRef;
-    GBool embedded = gfxFont->getEmbeddedFontID(&embRef);
-
-    char*fileName = 0;
-    int del = 0;
-    if(embedded &&
-       (gfxFont->getType() == fontType1 ||
-       gfxFont->getType() == fontType1C ||
-        gfxFont->getType() == fontCIDType0C ||
-       gfxFont->getType() == fontTrueType ||
-       gfxFont->getType() == fontCIDType2
-       ))
-    {
-      fileName = writeEmbeddedFontToFile(xref, gfxFont);
-      if(!fileName) showFontError(gfxFont,0);
-      else del = 1;
-    } else {
-      fileName = searchFont(fontname);
-      if(!fileName) showFontError(gfxFont,0);
-    }
-    if(!fileName) {
-       char * fontname = getFontName(gfxFont);
-       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", fontname, lastfontdir);
-       else
-           msg("<warning> Try specifying one or more font directories");
-
-       fileName = substituteFont(gfxFont, fontid);
-       if(!fileName)
-           exit(1);
-       if(fontid) { free(fontid);fontid = strdup(substitutetarget[substitutepos-1]); /*ugly hack*/};
-       msg("<notice> Font is now %s (%s)", fontid, fileName);
+    this->current_fontinfo = this->info->getFont(id);
+    if(!this->current_fontinfo) {
+       msg("<error> Internal Error: no fontinfo for font %s\n", id);
     }
-
-    if(!fileName) {
-       msg("<error> Couldn't set font %s\n", fontid);
-       free(fontid);
-       free(fontname);
-       return;
+    if(!this->current_fontinfo->seen) {
+       dumpFontInfo("<verbose>", gfxFont);
     }
-       
-    msg("<verbose> updateFont(%s) -> %s (max size: %f)", fontid, fileName, maxSize);
-    dumpFontInfo("<verbose>", gfxFont);
-
-    //swfoutput_setfont(&device, fontid, fileName);
     
-    if(!setGfxFont(fontid, fontname, 0, 0)) {
-       setGfxFont(fontid, fontname, fileName, maxSize);
+    gfxfont_t*font = gfxfontlist_findfont(this->gfxfontlist,id);
+    if(!font) {
+       font = createGfxFont(gfxFont, current_fontinfo);
+        font->id = strdup(id);
+       this->gfxfontlist = gfxfontlist_addfont(this->gfxfontlist, font);
+       device->addfont(device, font);
     }
-   
-    if(fileName && del)
-       unlinkfont(fileName);
-
-    if(fileName)
-        free(fileName);
-    free(fontid);
-    free(fontname);
+    current_gfxfont = font;
+    free(id);
 
-    msg("<verbose> |");
+    updateFontMatrix(state);
 }
 
 #define SQR(x) ((x)*(x))
@@ -2561,7 +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("<notice> Adding font \"%s\".", filename);
        fonts[fontnum++] = f;
     } else {
        msg("<error> Too many external fonts. Not adding font file \"%s\".", filename);
@@ -2570,9 +2019,6 @@ void addGlobalFont(const char*filename)
 
 void addGlobalLanguageDir(const char*dir)
 {
-    if(!globalParams)
-        globalParams = new GlobalParams((char*)"");
-    
     msg("<notice> Adding %s to language pack directories", dir);
 
     int l;
@@ -2619,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());
@@ -2744,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;
@@ -2955,13 +2398,13 @@ void GFXOutputDev::clearSoftMask(GfxState *state)
     states[statepos].softmaskrecording = 0;
 }
   
-/*class MemCheck
-{
-    public: ~MemCheck()
-    {
-        delete globalParams;globalParams=0;
-        Object::memCheck(stderr);
-        gMemReport(stderr);
-    }
-} myMemCheck;*/
+//class MemCheck
+//{
+//    public: ~MemCheck()
+//    {
+//        delete globalParams;globalParams=0;
+//        Object::memCheck(stderr);
+//        gMemReport(stderr);
+//    }
+//} myMemCheck;