added support for truetype libs using ttf2pt1.
authorkramm <kramm>
Fri, 23 Nov 2001 15:59:18 +0000 (15:59 +0000)
committerkramm <kramm>
Fri, 23 Nov 2001 15:59:18 +0000 (15:59 +0000)
pdf2swf/SWFOutputDev.cc
pdf2swf/swfoutput.cc
pdf2swf/swfoutput.h

index e32a293..5d53fbd 100644 (file)
@@ -44,6 +44,7 @@
 #include "swfoutput.h"
 extern "C" {
 #include "../lib/log.h"
+#include "ttf2pt1.h"
 }
 
 static PDFDoc*doc = 0;
@@ -189,12 +190,14 @@ public:
   int clipping[64];
   int clippos;
 
-  int setT1Font(char*name,FontEncoding*enc);
-  char* substitutefont(GfxFont*gfxFont);
+  int searchT1Font(char*name);
+  char* substituteFont(GfxFont*gfxFont, char*oldname);
+  char* writeEmbeddedFontToFile(GfxFont*font);
   int t1id;
   int jpeginfo; // did we write "File contains jpegs" yet?
   int pbminfo; // did we write "File contains jpegs" yet?
   int linkinfo; // did we write "File contains links" yet?
+  int ttfinfo; // did we write "File contains TrueType Fonts" yet?
 
   GfxState *laststate;
 };
@@ -330,7 +333,6 @@ void showFontError(GfxFont*font, int nr)
       logf("<warning> The following font caused problems (substituting):");
     else if(nr == 2)
       logf("<warning> This document contains Type 3 Fonts: (some text may be incorrectly displayed)");
-
     dumpFontInfo("<warning>", font);
 }
 
@@ -393,6 +395,7 @@ void dumpFontInfo(char*loglevel, GfxFont*font)
 SWFOutputDev::SWFOutputDev() 
 {
     jpeginfo = 0;
+    ttfinfo = 0;
     linkinfo = 0;
     pbminfo = 0;
     clippos = 0;
@@ -562,7 +565,7 @@ void SWFOutputDev::drawChar(GfxState *state, double x, double y, double dx, doub
        state->transform(x, y, &x1, &y1);
 
        if(enc->getCharName(c))
-         swfoutput_drawchar(&output, x1, y1, enc->getCharName(c));
+         swfoutput_drawchar(&output, x1, y1, enc->getCharName(c), c);
        else
          logf("<warning> couldn't get name for character %02x from Encoding", c);
     }
@@ -754,7 +757,7 @@ void SWFOutputDev::restoreState(GfxState *state) {
 
 char type3Warning=0;
 
-int SWFOutputDev::setT1Font(char*name, FontEncoding*encoding) 
+int SWFOutputDev::searchT1Font(char*name) 
 {      
     int i;
     
@@ -779,11 +782,7 @@ int SWFOutputDev::setT1Font(char*name, FontEncoding*encoding)
                pdf2t1map[i].id = mapid;
        }
     }
-    if(id<0)
-     return 0;
-
-    this->t1id = id;
-    return 1;
+    return id;
 }
 
 void SWFOutputDev::updateLineWidth(GfxState *state)
@@ -812,10 +811,9 @@ void SWFOutputDev::updateStrokeColor(GfxState *state)
                                      (char)(rgb.b*255), (char)(opaq*255));
 }
 
-char*writeEmbeddedFontToFile(GfxFont*font)
+char*SWFOutputDev::writeEmbeddedFontToFile(GfxFont*font)
 {
       char*tmpFileName = NULL;
-      char*fileName = NULL;
       FILE *f;
       int c;
       char *fontBuf;
@@ -854,12 +852,26 @@ char*writeEmbeddedFontToFile(GfxFont*font)
        strObj.free();
       }
       fclose(f);
-      fileName = tmpFileName;
-      if(!fileName) {
-         logf("<error> Embedded font writer didn't create a file");
-         return 0;
+
+      if(font->getType() == fontTrueType)
+      {
+         if(!ttfinfo) {
+             logf("<notice> File contains TrueType fonts");
+             ttfinfo = 1;
+         }
+         char name2[80];
+         int r1 = lrand48();
+         int r2 = lrand48();
+         sprintf(name2,"%04x%04x",r1,r2);
+         char*a[] = {"./ttf2pt1","-pttf","-b", tmpFileName, name2};
+         logf("<verbose> Invoking ttf2pt1...");
+         ttf2pt1_main(5,a);
+         unlink(tmpFileName);
+         sprintf(name2,"%04x%04x.pfb",r1,r2);
+         tmpFileName = strdup(name2);
       }
-      return fileName;
+
+      return tmpFileName;
 }
 
 char* gfxFontName(GfxFont* gfxFont)
@@ -877,7 +889,11 @@ char* gfxFontName(GfxFont* gfxFont)
       }
 }
 
-char* SWFOutputDev::substitutefont(GfxFont*gfxFont)
+char* substitutetarget[256];
+char* substitutesource[256];
+int substitutepos = 0;
+
+char* SWFOutputDev::substituteFont(GfxFont*gfxFont, char* oldname)
 {
       //substitute font
       char* fontname = 0;
@@ -950,28 +966,70 @@ char* SWFOutputDev::substitutefont(GfxFont*gfxFont)
          }
        }
       }
-      if(fontname)
-        setT1Font(fontname, gfxFont->getEncoding());
+      if(fontname) {
+        this->t1id = searchT1Font(fontname);
+      }
+      if(substitutepos>=sizeof(substitutesource)/sizeof(char*)) {
+         logf("<fatal> Too many fonts in file.");
+         exit(1);
+      }
+      substitutesource[substitutepos] = oldname;
+      substitutetarget[substitutepos] = fontname;
+      logf("<verbose> substituting %s -> %s", oldname, fontname);
+      substitutepos ++;
       return fontname;
 }
 
+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 SWFOutputDev::updateFont(GfxState *state) 
 {
-  char * fontname = 0;
   GfxFont*gfxFont = state->getFont();
   char * fileName = 0;
     
   if (!gfxFont) {
     return;
   }  
-  
-  if(gfxFont->getName()) {
-    fontname = gfxFont->getName()->getCString();
+  char * fontname = gfxFontName(gfxFont);
+  int t;
+  for(t=0;t<substitutepos;t++) {
+      if(!strcmp(fontname, substitutesource[t])) {
+         fontname = substitutetarget[t];
+         break;
+      }
   }
 
-  if(swfoutput_queryfont(&output, gfxFontName(gfxFont)))
+  if(swfoutput_queryfont(&output, fontname))
   {
-      swfoutput_setfont(&output, gfxFontName(gfxFont), -1, 0);
+      swfoutput_setfont(&output, fontname, -1, 0);
       return;
   }
 
@@ -987,25 +1045,55 @@ void SWFOutputDev::updateFont(GfxState *state)
   if(embedded) {
     if (!gfxFont->is16Bit() &&
        (gfxFont->getType() == fontType1 ||
-        gfxFont->getType() == fontType1C)) {
+        gfxFont->getType() == fontType1C ||
+        gfxFont->getType() == fontTrueType)) {
        
        fileName = writeEmbeddedFontToFile(gfxFont);
-       if(!fileName)
+       if(!fileName) {
+         logf("<error> Couldn't write font to file");
+         showFontError(gfxFont,0);
          return ;
+       }
        this->t1id = T1_AddFont(fileName);
+       if(this->t1id<0) {
+         logf("<error> Couldn't load font from file");
+         showFontError(gfxFont,0);
+         unlinkfont(fileName);
+         return ;
+       }
     }
     else {
        showFontError(gfxFont,0);
-       fontname = substitutefont(gfxFont);
+       fontname = substituteFont(gfxFont, fontname);
     }
   } else {
-    if(!fontname || !setT1Font(state->getFont()->getName()->getCString(), gfxFont->getEncoding()))
-       fontname = substitutefont(gfxFont);
+    if(fontname) {
+       int newt1id = searchT1Font(fontname);
+       if(newt1id<0) {
+           fontname = substituteFont(gfxFont, fontname);
+       } else
+           this->t1id = newt1id;
+    }
+    else
+       fontname = substituteFont(gfxFont, fontname);
+  }
+
+  if(t1id<0) {
+      showFontError(gfxFont,0);
+  }
+  /* we may have done some substitutions here, so check
+     again if this font is cached. */
+  if(swfoutput_queryfont(&output, fontname))
+  {
+      swfoutput_setfont(&output, fontname, -1, 0);
+      return;
   }
 
-  swfoutput_setfont(&output,gfxFontName(gfxFont),this->t1id, fileName);
+  logf("<verbose> Creating new SWF font: t1id: %d, filename: %s name:%s", this->t1id, fileName, fontname);
+  swfoutput_setfont(&output, fontname, this->t1id, fileName);
   if(fileName)
-      unlink(fileName);
+      unlinkfont(fileName);
 }
 
 int pic_xids[1024];
index f84ebee..74c982d 100644 (file)
@@ -421,7 +421,7 @@ void putcharacter(struct swfoutput*obj, int fontid, int charid,
 
 
 /* process a character. */
-void drawchar(struct swfoutput*obj, SWFFont*font, char*character, swfmatrix*m)
+void drawchar(struct swfoutput*obj, SWFFont*font, char*character, int charnr, swfmatrix*m)
 {
     int usefonts=1;
     if(m->m12!=0 || m->m21!=0)
@@ -431,7 +431,7 @@ void drawchar(struct swfoutput*obj, SWFFont*font, char*character, swfmatrix*m)
 
     if(usefonts && ! drawonlyshapes)
     {
-        int charid = font->getSWFCharID(character);
+        int charid = font->getSWFCharID(character, charnr);
         if(shapeid>=0)
             endshape();
         if(textid<0)
@@ -505,32 +505,45 @@ SWFFont::SWFFont(char*name, int id, char*filename)
     this->name = strdup(T1_GetFontFileName(id));
     this->fontid = strdup(name);
     this->t1id = id;
-
+    
     char**a= T1_GetAllCharNames(id);
-    int t=0, outlinepos=0;
+    int t, outlinepos=0;
     char*map[256];
+
+    t=0;
     while(a[t])
         t++;
     this->charnum = t;
-    if(!t) 
+
+    if(!charnum) 
         return;
-    logf("<verbose> Font %s(%d): Storing %d outlines.\n", name, id, t);
+    logf("<verbose> Font %s(%d): Storing %d outlines.\n", name, id, charnum);
+
+    this->standardtablesize = 256;
+    if(this->charnum < this->standardtablesize)
+       this->standardtablesize = this->charnum;
+    this->standardtable = (char**)malloc(standardtablesize*sizeof(char*));
+
+    for(t = 0; t < this->standardtablesize; t++) {
+       char*name = T1_GetCharName(id,t);
+       if(!name)
+           name = "";
+       standardtable[t] = strdup(name);
+    }
     
-    outline = (T1_OUTLINE**)malloc(t*sizeof(T1_OUTLINE*));
-    charname = (char**)malloc(t*sizeof(char*));
-    width = (int*)malloc(t*sizeof(int));
-    memset(width, 0, t*sizeof(int));
-    memset(charname, 0, t*sizeof(char*));
-    used = (char*)malloc(t*sizeof(char));
-    char2swfcharid = (U16*)malloc(t*2);
-    swfcharid2char = (U16*)malloc(t*2);
+    outline = (T1_OUTLINE**)malloc(charnum*sizeof(T1_OUTLINE*));
+    charname = (char**)malloc(charnum*sizeof(char*));
+    width = (int*)malloc(charnum*sizeof(int));
+    memset(width, 0, charnum*sizeof(int));
+    memset(charname, 0, charnum*sizeof(char*));
+    used = (char*)malloc(charnum*sizeof(char));
+    char2swfcharid = (U16*)malloc(charnum*2);
+    swfcharid2char = (U16*)malloc(charnum*2);
     swfcharpos = 0;
 
-    memset(used,0,t*sizeof(char));
+    memset(used,0,charnum*sizeof(char));
 
     this->swfid = ++currentswfid;
-
     
     t=0;
     while(*a)
@@ -555,9 +568,11 @@ SWFFont::SWFFont(char*name, int id, char*filename)
             // parsecharacters
             for(s=0;s<t;s++)
             {
+               char* name = T1_GetCharName(id, s);
+               if(!name) name = "";
                 this->outline[outlinepos] = T1_CopyOutline(T1_GetCharOutline(id, s, 100.0, 0));
                this->width[outlinepos] = T1_GetCharWidth(id, s);
-                this->charname[outlinepos] = strdup(T1_GetCharName(id, s));
+                this->charname[outlinepos] = strdup(name);
                 outlinepos++;
             }
             t=0;
@@ -577,7 +592,7 @@ SWFFont::~SWFFont()
        for(t=0;t<this->charnum;t++) 
        {
            if(this->charname[t])
-             getSWFCharID(this->charname[t]);
+             getSWFCharID(this->charname[t], -1);
        }
     }
     
@@ -647,6 +662,11 @@ SWFFont::~SWFFont()
     free(outline);
     for(t=0;t<charnum;t++)
         free(charname[t]);
+    for(t=0;t<standardtablesize;t++)
+       if(standardtable[t]) {
+           free(standardtable[t]);
+       }
+    free(standardtable);
     free(charname);
     free(width);
     free(used);
@@ -672,7 +692,7 @@ T1_OUTLINE*SWFFont::getOutline(char*name)
     return 0;
 }
 
-int SWFFont::getSWFCharID(char*name)
+int SWFFont::getSWFCharID(char*name, int charnr)
 {
     int t;
     for(t=0;t<this->charnum;t++) {
@@ -686,6 +706,9 @@ int SWFFont::getSWFCharID(char*name)
             return char2swfcharid[t];
         }
     }
+    if(this->standardtable && charnr>=0 && charnr < this->standardtablesize) {
+       return getSWFCharID(this->standardtable[charnr], -1);
+    }
     logf("<warning> Didn't find character '%s' in font '%s'", name, this->name);
     return 0;
 }
@@ -767,7 +790,7 @@ void swfoutput_setfontmatrix(struct swfoutput*obj,double m11,double m12,
 }
 
 /* draws a character at x,y. */
-void swfoutput_drawchar(struct swfoutput* obj,double x,double y,char*character) 
+void swfoutput_drawchar(struct swfoutput* obj,double x,double y,char*character, int charnr) 
 {
     swfmatrix m;
     m.m11 = obj->fontm11;
@@ -776,7 +799,7 @@ void swfoutput_drawchar(struct swfoutput* obj,double x,double y,char*character)
     m.m22 = obj->fontm22;
     m.m13 = x;
     m.m23 = y;
-    drawchar(obj, obj->font, character, &m);
+    drawchar(obj, obj->font, character, charnr, &m);
 }
 
 /* initialize the swf writer */
index 530d11c..1efc9cc 100644 (file)
@@ -46,6 +46,9 @@ class SWFFont
     U16*swfcharid2char;
     int swfcharpos;
 
+    char**standardtable;
+    int standardtablesize;
+
     public:
     
     int t1id;
@@ -55,7 +58,7 @@ class SWFFont
     SWFFont(char*name, int t1id, char*filename);
     SWFFont::~SWFFont();
     T1_OUTLINE*getOutline(char*charname);
-    int getSWFCharID(char*name);
+    int getSWFCharID(char*name, int charnr);
     char*getName();
     char*getCharName(int t);
     int getCharWidth(int t) {return width[t];}
@@ -90,7 +93,7 @@ void swfoutput_setstrokecolor(struct swfoutput*, unsigned char r, unsigned char
 void swfoutput_setfontmatrix(struct swfoutput*,double,double,double,double);
 void swfoutput_setlinewidth(struct swfoutput*, double linewidth);
 
-void swfoutput_drawchar(struct swfoutput*,double x,double y,char*a);
+void swfoutput_drawchar(struct swfoutput*,double x,double y,char*a, int charnr);
 void swfoutput_drawpath(struct swfoutput*, T1_OUTLINE*outline, struct swfmatrix*m);
 void swfoutput_startclip(struct swfoutput*, T1_OUTLINE*outline, struct swfmatrix*m);
 void swfoutput_endclip(struct swfoutput*);