implemented two levels of font cache
authorkramm <kramm>
Thu, 18 Oct 2001 20:36:17 +0000 (20:36 +0000)
committerkramm <kramm>
Thu, 18 Oct 2001 20:36:17 +0000 (20:36 +0000)
pdf2swf/SWFOutputDev.cc
pdf2swf/swfoutput.cc
pdf2swf/swfoutput.h

index 7563762..b2573d8 100644 (file)
@@ -393,9 +393,12 @@ void dumpFontInfo(char*loglevel, GfxFont*font)
      logf("%sType: TrueType\n",loglevel);
     break;
   }
+  
+  Ref embRef;
+  GBool embedded = font->getEmbeddedFontID(&embRef);
   name = font->getEmbeddedFontName();
-  if(name)
-   logf("%sEmbedded name: %s\n",loglevel, name);
+  if(embedded)
+   logf("%sEmbedded name: %s id: %d\n",loglevel, name, embRef.num);
 
   gstr = font->getExtFontFile();
   if(gstr)
@@ -722,6 +725,10 @@ int SWFOutputDev::setT1Font(char*name, FontEncoding*encoding)
     if(id<0)
      return 0;
 
+    /* T1 allows us to recode only once. Therefore, remove
+       and reload the font to reset it */
+    T1_DeleteFont(id);
+    T1_LoadFont(id);
     initT1Font(id, encoding);
 }
 
@@ -730,8 +737,10 @@ int SWFOutputDev::initT1Font(int id, FontEncoding*encoding)
     int encStrSize;
     char *encPtr;
     int i;
-    T1_DeleteFont(id);
-    T1_LoadFont(id);
+
+    if(!T1_GetFontName(id))
+       T1_LoadFont(id);
+
     /* reencode the font: 
      * This is the only way to get the unmapped characters
      * from t1lib
@@ -789,58 +798,37 @@ void SWFOutputDev::updateStrokeColor(GfxState *state)
                                      (char)(rgb.b*255), (char)(opaq*255));
 }
 
-void SWFOutputDev::updateFont(GfxState *state) 
+char*writeEmbeddedFontToFile(GfxFont*font)
 {
-  double m11, m12, m21, m22;
-  char * fontname = 0;
-  GfxFont*gfxFont = state->getFont();
-  char * filename;
-
-  if (!gfxFont) {
-    return;
-  }  
-  // look for Type 3 font
-  if (!type3Warning && gfxFont->getType() == fontType3) {
-    type3Warning = gTrue;
-    showFontError(gfxFont, 2);
-  }
-  //dumpFontInfo (gfxFont);
-  
-
-  Ref embRef;
-  GBool embedded = gfxFont->getEmbeddedFontID(&embRef);
-  if(embedded) {
-    char*tmpFileName = NULL;
-    char*fileName = NULL;
-    FILE *f;
-    char *fontBuf;
-    int fontLen;
-    Type1CFontConverter *cvt;
-    Ref embRef;
-    Object refObj, strObj;
-    int c;
-    if (!gfxFont->is16Bit() &&
-       (gfxFont->getType() == fontType1 ||
-        gfxFont->getType() == fontType1C) &&
-       gfxFont->getEmbeddedFontID(&embRef)) {
+      char*tmpFileName = NULL;
+      char*fileName = NULL;
+      FILE *f;
+      int c;
+      char *fontBuf;
+      int fontLen;
+      Type1CFontConverter *cvt;
+      Ref embRef;
+      Object refObj, strObj;
       tmpFileName = "tmpfont";
+      font->getEmbeddedFontID(&embRef);
+
       f = fopen(tmpFileName, "wb");
       if (!f) {
        logf("<error> Couldn't create temporary Type 1 font file");
-       return;
+       return 0;
       }
-      if (gfxFont->getType() == fontType1C) {
-       if (!(fontBuf = gfxFont->readEmbFontFile(&fontLen))) {
+      if (font->getType() == fontType1C) {
+       if (!(fontBuf = font->readEmbFontFile(&fontLen))) {
          fclose(f);
          logf("<error> Couldn't read embedded font file");
-         return ;
+         return 0;
        }
        cvt = new Type1CFontConverter(fontBuf, fontLen, f);
        cvt->convert();
        delete cvt;
        gfree(fontBuf);
       } else {
-       gfxFont->getEmbeddedFontID(&embRef);
+       font->getEmbeddedFontID(&embRef);
        refObj.initRef(embRef.num, embRef.gen);
        refObj.fetch(&strObj);
        refObj.free();
@@ -855,14 +843,71 @@ void SWFOutputDev::updateFont(GfxState *state)
       fileName = tmpFileName;
       if(!fileName) {
          logf("<error> Embedded font writer didn't create a file");
-         return ;
+         return 0;
       }
+      return fileName;
+}
+
+int embeddedids[128];
+int embeddedt1ids[128];
+int embedded_mappos = 0;
+int embedded_maxpos = 128;
+
+void SWFOutputDev::updateFont(GfxState *state) 
+{
+  double m11, m12, m21, m22;
+  char * fontname = 0;
+  GfxFont*gfxFont = state->getFont();
+
+  if (!gfxFont) {
+    return;
+  }  
+
+  if(swfoutput_queryfont(&output, gfxFont->getID().num))
+  {
+      swfoutput_setfont(&output, gfxFont->getID().num, -1);
+      return;
+  }
+
+  // look for Type 3 font
+  if (!type3Warning && gfxFont->getType() == fontType3) {
+    type3Warning = gTrue;
+    showFontError(gfxFont, 2);
+  }
+  //dumpFontInfo ("<notice>", gfxFont);
+
+  Ref embRef;
+  GBool embedded = gfxFont->getEmbeddedFontID(&embRef);
+  if(embedded) {
+    int t;
+    for(t=0;t<embedded_mappos;t++)
+       if(embeddedids[t] == embRef.num)
+           break;
+    if(t==embedded_mappos)
+    {
+       char*fileName;
+       if (!gfxFont->is16Bit() &&
+           (gfxFont->getType() == fontType1 ||
+            gfxFont->getType() == fontType1C)) {
+           
+           fileName = writeEmbeddedFontToFile(gfxFont);
+           if(!fileName)
+             return ;
+       }
+       else {
+           showFontError(gfxFont,0);
+           return ;
+       }
+       t1id = T1_AddFont(fileName);
+       embeddedids[embedded_mappos] = embRef.num;
+       embeddedt1ids[embedded_mappos] = t1id;
+       if(embedded_mappos < embedded_maxpos-1)
+           embedded_mappos++;
     }
-    else {
-       showFontError(gfxFont,0);
-       return ;
+    else 
+    {
+       t1id = embeddedt1ids[t];
     }
-    t1id = T1_AddFont(fileName);
     initT1Font(t1id, gfxFont->getEncoding());
   } else {
     fontname = NULL;
index cb8e8f8..2993ffc 100644 (file)
@@ -195,28 +195,26 @@ void drawpath(T1_OUTLINE*outline, struct swfmatrix*m, char*namehint)
        outline = outline->link;
     }
 }
+    //logf("<debug> Font name is %s", T1_GetFontFileName(t1fontindex));
+    //logf("<debug> char 0x%02x is named %s\n",character,charname);
+    //logf("<debug> bbox: %d %d %d %d\n",bbox.llx,bbox.lly,bbox.urx,bbox.ury);
+    //char*charname = T1_GetCharName(t1fontindex, character);
 
 /* process a character. */
-void drawchar(struct swfoutput*obj, int t1fontindex, char character, swfmatrix*m)
-{
-
-    /* <T1 stuff> */
-    T1_OUTLINE*outline;
-    int width = T1_GetCharWidth(t1fontindex, character);
-    BBox bbox = T1_GetCharBBox(t1fontindex, character);
-    char*charname= T1_GetCharName(t1fontindex, character);
-    logf("<debug> Font name is %s", T1_GetFontFileName(t1fontindex));
-    logf("<debug> char 0x%02x is named %s\n",character,charname);
-    logf("<debug> bbox: %d %d %d %d\n",bbox.llx,bbox.lly,bbox.urx,bbox.ury);
-    if(!charname || charname[0] == '.') 
+void drawchar(struct swfoutput*obj, SWFFont*font, char character, swfmatrix*m)
+{
+    T1_OUTLINE*outline = font->getOutline(character);
+    char* charname = font->getCharName(character);
+
+    if(!outline)
     {
      /* for newline, we don't print an error. FIXME: We shouldn't get newlines here
        in the first place
       */
      if(character != '\n') {
         logf("<error> Char to set is not defined!");
-        logf("<error> -  font file is %s\n", T1_GetFontFileName(t1fontindex));
-        logf("<error> -  char 0x%02x is named %s\n",character,charname);
+        logf("<error> -  font file is %s\n", font->getName());
+        logf("<error> -  char 0x%02x is named %s\n",character, charname);
      }
      return;
     }
@@ -225,9 +223,6 @@ void drawchar(struct swfoutput*obj, int t1fontindex, char character, swfmatrix*m
     m2.m21/=100;
     m2.m12/=100;
     m2.m22/=100;
-    outline =  T1_GetCharOutline( t1fontindex, character, 100.0, 0);
-
-    /** </T1 stuff> **/
 
     if(shapeid<0)
        startshape(obj);
@@ -259,11 +254,96 @@ void swfoutput_drawpath(swfoutput*output, T1_OUTLINE*outline, struct swfmatrix*m
     drawpath(outline,m, 0); 
 }
 
+SWFFont::SWFFont(int t1fontindex)
+{
+    int t;
+    for(t=0;t<256;t++)
+    {
+       int width = T1_GetCharWidth(t1fontindex, t);
+       BBox bbox = T1_GetCharBBox(t1fontindex, t);
+       T1_OUTLINE*outline = T1_GetCharOutline(t1fontindex,t,100.0,0);
+
+       char*name;
+       this->outline[t] =  T1_CopyOutline(outline);
+
+       name = T1_GetCharName(t1fontindex, t);
+       if(!name || name[0]=='.')
+       {
+           this->charname[t] = 0;
+           this->outline[t] = 0;
+       }
+       else
+           this->charname[t] = strdup(name);
+    }
+    this->name = strdup(T1_GetFontFileName(t1fontindex));
+}
+
+T1_OUTLINE*SWFFont::getOutline(unsigned char nr)
+{
+    return outline[nr];
+}
+
+char*SWFFont::getCharName(int t)
+{
+    return this->charname[t];
+}
+
+char*SWFFont::getName()
+{
+    return this->name;
+}
+
+struct fontlist_t 
+{
+    SWFFont * font;
+    fontlist_t*next;
+} *fontlist = 0;
 
 /* set's the t1 font index of the font to use for swfoutput_drawchar(). */
-int swfoutput_setfont(struct swfoutput*obj, int fontid, int t1id)
+void swfoutput_setfont(struct swfoutput*obj, int fontid, int t1id)
 {
-    obj->t1font = t1id;
+    fontlist_t*last=0,*iterator;
+    if(obj->font && obj->font->id == fontid)
+       return;
+
+    iterator = fontlist;
+    while(iterator) {
+       if(iterator->font->id == fontid)
+           break;
+       last = iterator;
+       iterator = iterator->next;
+    }
+    if(iterator) 
+    {
+       obj->font = iterator->font;
+       return ;
+    }
+
+    if(t1id<0) {
+       logf("<error> internal error: t1id:%d, fontid:%d\n", t1id,fontid);
+    }
+    
+    SWFFont*font = new SWFFont(t1id);
+    iterator = new fontlist_t;
+    iterator->font = font;
+    iterator->next = 0;
+
+    if(last) 
+       last->next = iterator;
+    else 
+       fontlist = iterator;
+    obj->font = font;
+}
+
+int swfoutput_queryfont(struct swfoutput*obj, int fontid)
+{
+    fontlist_t *iterator = fontlist;
+    while(iterator) {
+       if(iterator->font->id == fontid)
+           return 1;
+       iterator = iterator->next;
+    }
+    return 0;
 }
 
 /* set's the matrix which is to be applied to characters drawn by
@@ -287,7 +367,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->t1font, character, &m);
+    drawchar(obj, obj->font, character, &m);
 }
 
 /* initialize the swf writer */
@@ -303,7 +383,7 @@ void swfoutput_init(struct swfoutput* obj, char*_filename, int _sizex, int _size
 
   logf("<verbose> initializing swf output for size %d*%d\n", sizex,sizey);
 
-  obj->t1font = 0;
+  obj->font = 0;
   
   memset(&swf,0x00,sizeof(SWF));
 
index 6583015..8db8f3a 100644 (file)
@@ -26,11 +26,28 @@ struct swfcoord {
     twip y;
 };
 
+class SWFFont
+{
+    T1_OUTLINE*(outline[256]);
+    char*(charname[256]);
+    char*name;
+
+    public:
+    
+    int id;
+
+    SWFFont(int t1id);
+    T1_OUTLINE*getOutline(unsigned char nr);
+    char*getName();
+    char*getCharName(int t);
+};
+
 struct swfoutput 
 {
-    int t1font;
+    //int t1font;
     double fontm11,fontm12,fontm21,fontm22;
     unsigned short int linewidth;
+    SWFFont*font;
     RGBA strokergb;
     RGBA fillrgb;
 };
@@ -46,7 +63,8 @@ void swfoutput_setprotected(); //write PROTECT tag
 
 void swfoutput_newpage(struct swfoutput*);
 
- int swfoutput_setfont(struct swfoutput*, int fontid, int t1font);
+void swfoutput_setfont(struct swfoutput*, int fontid, int t1font);
+int swfoutput_queryfont(struct swfoutput*, int fontid);
 void swfoutput_setdrawmode(struct swfoutput*, int drawmode);
 void swfoutput_setfillcolor(struct swfoutput*, unsigned char r, unsigned char g, unsigned char b, unsigned char a);
 void swfoutput_setstrokecolor(struct swfoutput*, unsigned char r, unsigned char g, unsigned char b, unsigned char a);