fixed a memleak, made pdf device reorder bad unicode
authorMatthias Kramm <kramm@quiss.org>
Thu, 25 Feb 2010 20:30:19 +0000 (12:30 -0800)
committerMatthias Kramm <kramm@quiss.org>
Thu, 25 Feb 2010 20:30:19 +0000 (12:30 -0800)
lib/gfxfont.c
lib/gfxfont.h
lib/pdf/InfoOutputDev.cc
lib/ttf.h

index dda20db..d7a8803 100644 (file)
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
+#include <assert.h>
 #include "../config.h"
 #include "gfxdevice.h"
 #include "gfxtools.h"
 #include "gfxfont.h"
 #include "ttf.h"
 #include "../config.h"
 #include "gfxdevice.h"
 #include "gfxtools.h"
 #include "gfxfont.h"
 #include "ttf.h"
+#include "mem.h"
 
 static int loadfont_scale = 64;
 static int full_unicode = 1;
 
 static int loadfont_scale = 64;
 static int full_unicode = 1;
@@ -520,6 +522,75 @@ void gfxfont_free(gfxfont_t*font)
     free(font);
 }
 
     free(font);
 }
 
+static inline int invalid_unicode(int u)
+{
+    return (u<32 || (u>=0xe000 && u<0xf900));
+}
+void gfxfont_fix_unicode(gfxfont_t*font)
+{
+    int t;
+
+    /* find the current maximum unicode2glyph */
+    int max = 0;
+    for(t=0;t<font->num_glyphs;t++) {
+       int u = font->glyphs[t].unicode;
+       if(u > max)
+           max = u;
+    }
+    char*used = rfx_calloc(max+1);
+
+    /* now, remap all duplicates (and invalid characters) and
+       calculate the new maximum */
+    int remap_pos=0;
+    max = 0;
+    for(t=0;t<font->num_glyphs;t++) {
+       int u = font->glyphs[t].unicode;
+       if(u>=0) {
+           if(used[u] || invalid_unicode(u)) {
+               u = font->glyphs[t].unicode = 0xe000 + remap_pos++;
+           } else {
+               used[u] = 1;
+           }
+       }
+       if(u > max)
+           max = u;
+    }
+    free(used);
+    
+    if(!font->unicode2glyph) {
+       /* (re)generate unicode2glyph-to-glyph mapping table by reverse mapping
+          the glyph unicode2glyph's indexes into the mapping table. For collisions,
+          we prefer the smaller unicode2glyph value.*/
+       font->max_unicode = max+1;
+       font->unicode2glyph = malloc(sizeof(font->unicode2glyph[0])*(font->max_unicode));
+       memset(font->unicode2glyph, -1, sizeof(font->unicode2glyph[0])*(font->max_unicode));
+       
+       for(t=0;t<font->num_glyphs;t++) {
+           int u = font->glyphs[t].unicode;
+           if(u>=0) {
+               assert(font->unicode2glyph[u]<0); // we took care of duplicates, right?
+               font->unicode2glyph[u] = t;
+           }
+       }
+    } else {
+       /* add the new glyph indexes (most probably, that's only the remapped values
+          at 0xe000) to the unicode2glyph table. Notice: Unlike glyph2unicode, we don't
+          care about collisions in the unicode2glyph table */
+       int new_max_unicode = max+1;
+       if(font->max_unicode < new_max_unicode) {
+           font->unicode2glyph = rfx_realloc(font->unicode2glyph, sizeof(font->unicode2glyph[0])*(font->max_unicode));
+           memset(font->unicode2glyph+font->max_unicode, -1, sizeof(font->unicode2glyph[0])*(new_max_unicode - font->max_unicode));
+       }
+       for(t=0;t<font->num_glyphs;t++) {
+           int u = font->glyphs[t].unicode;
+           if(u>=0 && font->unicode2glyph[u]<0) {
+               font->unicode2glyph[u] = t;
+           }
+       }
+       font->max_unicode = new_max_unicode;
+    }
+}
+
 ttf_t* gfxfont_to_ttf(gfxfont_t*font)
 {
     ttf_t*ttf = ttf_new();
 ttf_t* gfxfont_to_ttf(gfxfont_t*font)
 {
     ttf_t*ttf = ttf_new();
@@ -595,7 +666,7 @@ ttf_t* gfxfont_to_ttf(gfxfont_t*font)
        dest->advance = src->advance*scale;
 
        int u = font->glyphs[t].unicode;
        dest->advance = src->advance*scale;
 
        int u = font->glyphs[t].unicode;
-       if(u<32 || (u>=0xe000 && u<0xf900)) {
+       if(invalid_unicode(u)) {
            u = 0xe000 + remap_pos++;
        }
        if(u > max_unicode)
            u = 0xe000 + remap_pos++;
        }
        if(u > max_unicode)
@@ -607,7 +678,7 @@ ttf_t* gfxfont_to_ttf(gfxfont_t*font)
     for(t=0;t<font->num_glyphs;t++) {
        gfxglyph_t*src = &font->glyphs[t];
        int u = font->glyphs[t].unicode;
     for(t=0;t<font->num_glyphs;t++) {
        gfxglyph_t*src = &font->glyphs[t];
        int u = font->glyphs[t].unicode;
-       if(u<32 || (u>=0xe000 && u<0xf900)) {
+       if(invalid_unicode(u)) {
            u = 0xe000 + remap_pos++;
        }
        if(u>=0 && u<ttf->unicode_size)
            u = 0xe000 + remap_pos++;
        }
        if(u>=0 && u<ttf->unicode_size)
@@ -617,7 +688,7 @@ ttf_t* gfxfont_to_ttf(gfxfont_t*font)
     if(font->unicode2glyph) {
        for(u=0;u<ttf->unicode_size;u++) {
            int g = font->unicode2glyph[u];
     if(font->unicode2glyph) {
        for(u=0;u<ttf->unicode_size;u++) {
            int g = font->unicode2glyph[u];
-           if(u<32 || (u>=0xe000 && u<0xf900))
+           if(invalid_unicode(u))
                continue;
            if(g>=0 && !ttf->unicode[u]) {
                ttf->unicode[u] = g+offset;
                continue;
            if(g>=0 && !ttf->unicode[u]) {
                ttf->unicode[u] = g+offset;
@@ -638,5 +709,6 @@ void gfxfont_save(gfxfont_t*font, const char*filename)
 {
     ttf_t*ttf = gfxfont_to_ttf(font);
     ttf_save(ttf, filename);
 {
     ttf_t*ttf = gfxfont_to_ttf(font);
     ttf_save(ttf, filename);
+    ttf_destroy(ttf);
 }
 
 }
 
index 1058db6..f31d71f 100644 (file)
@@ -34,6 +34,7 @@ extern "C" {
    still looks good. 1=normal, 0.5=double resolution etc. */
 gfxfont_t* gfxfont_load(char*id, char*filename, unsigned int flags, double quality);
 void gfxfont_save(gfxfont_t*font, const char*filename);
    still looks good. 1=normal, 0.5=double resolution etc. */
 gfxfont_t* gfxfont_load(char*id, char*filename, unsigned int flags, double quality);
 void gfxfont_save(gfxfont_t*font, const char*filename);
+void gfxfont_fix_unicode(gfxfont_t*font);
 void gfxfont_free(gfxfont_t*font);
 
 #ifdef __cplusplus
 void gfxfont_free(gfxfont_t*font);
 
 #ifdef __cplusplus
index 7d7db0b..08a9cc3 100644 (file)
@@ -17,6 +17,7 @@
 #include "../log.h"
 #include "../types.h"
 #include "../q.h"
 #include "../log.h"
 #include "../types.h"
 #include "../q.h"
+#include "../gfxfont.h"
 #include <math.h>
 #include <assert.h>
 
 #include <math.h>
 #include <assert.h>
 
@@ -219,14 +220,8 @@ static gfxfont_t* createGfxFont(FontInfo*src)
            font->num_glyphs++;
        }
     }
            font->num_glyphs++;
        }
     }
-    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;
-       }
 
 
-    }
+    gfxfont_fix_unicode(font);
 
     int kerning_size = 0;
     for(t=0;t<src->num_glyphs;t++) {
 
     int kerning_size = 0;
     for(t=0;t<src->num_glyphs;t++) {
index d37f745..21460c1 100644 (file)
--- a/lib/ttf.h
+++ b/lib/ttf.h
@@ -179,6 +179,7 @@ ttf_t*ttf_load(void*data, int length);
 ttf_table_t*ttf_addtable(ttf_t*ttf, U32 tag);
 void ttf_create_truetype_tables(ttf_t*ttf);
 void ttf_dump(ttf_t*ttf);
 ttf_table_t*ttf_addtable(ttf_t*ttf, U32 tag);
 void ttf_create_truetype_tables(ttf_t*ttf);
 void ttf_dump(ttf_t*ttf);
+void ttf_destroy(ttf_t*ttf);
 void ttf_save(ttf_t*ttf, const char*filename);
 
 #endif
 void ttf_save(ttf_t*ttf, const char*filename);
 
 #endif