fixed mem leaks
[swftools.git] / lib / devices / record.c
index 796e086..48b57f6 100644 (file)
@@ -34,6 +34,7 @@
 #include <assert.h>
 #include "../gfxdevice.h"
 #include "../gfxtools.h"
+#include "../gfxfont.h"
 #include "../types.h"
 #include "../bitio.h"
 #include "../log.h"
@@ -97,6 +98,7 @@ typedef struct _internal_result {
 #define OP_FINISH 0x0d
 
 #define FLAG_SAME_AS_LAST 0x10
+#define FLAG_ZERO_FONT 0x20
 
 #define LINE_MOVETO 0x0e
 #define LINE_LINETO 0x0f
@@ -185,6 +187,7 @@ static void dumpImage(writer_t*w, state_t*state, gfximage_t*img)
     //48.0% images (3488650 bytes) (without filter, Z_BEST_SPEED)
     //55.3% images (4665889 bytes) (without filter, fastlz level 2)
     //55.6% images (4726334 bytes) (without filter, fastlz level 1)
+    //83.0% images (18091804 bytes) (no compression)
 
     gfxcolor_t*image;
 #ifdef FILTER_IMAGES
@@ -206,7 +209,7 @@ static void dumpImage(writer_t*w, state_t*state, gfximage_t*img)
 #ifdef HAVE_FASTLZ
     compressdata_size = fastlz_compress_level(2, (void*)image, size*sizeof(gfxcolor_t), compressdata);
 #else
-    compress2(compressdata, &compressdata_size, (void*)image, sizeof(gfxcolor_t)*size, 6);
+    compress2(compressdata, &compressdata_size, (void*)image, sizeof(gfxcolor_t)*size, Z_BEST_SPEED);
 #endif
 
     writer_writeU32(w, compressdata_size);
@@ -450,6 +453,17 @@ static gfxfont_t*readFont(reader_t*r, state_t*state)
 
 /* ----------------- reading/writing of primitives with caching -------------- */
 
+void state_clear(state_t*state)
+{
+    int t;
+    for(t=0;t<sizeof(state->last_string)/sizeof(state->last_string[0]);t++) {
+       if(state->last_string[t]) {
+           free(state->last_string[t]);
+           state->last_string[t] = 0;
+       }
+    }
+}
+
 static char* read_string(reader_t*r, state_t*state, U8 id, U8 flags)
 {
     assert(id>=0 && id<16);
@@ -458,6 +472,9 @@ static char* read_string(reader_t*r, state_t*state, U8 id, U8 flags)
        return strdup(state->last_string[id]);
     }
     char*s = reader_readString(r);
+    if(state->last_string[id]) {
+       free(state->last_string[id]);
+    }
     state->last_string[id] = strdup(s);
     return s;
 }
@@ -578,16 +595,22 @@ static void record_drawchar(struct _gfxdevice*dev, gfxfont_t*font, int glyphnr,
     }
 
     msg("<trace> record: %08x DRAWCHAR %d\n", glyphnr, dev);
-    const char*font_id = font->id?font->id:"*NULL*";
+    const char*font_id = (font&&font->id)?font->id:"*NULL*";
     
     gfxmatrix_t*l = &i->state.last_matrix[OP_DRAWCHAR];
 
+    U8 flags = 0;
+    if(!font)
+       flags |= FLAG_ZERO_FONT;
+
     char same_font = i->state.last_string[OP_DRAWCHAR] && !strcmp(i->state.last_string[OP_DRAWCHAR], font_id);
     char same_matrix = (l->m00 == matrix->m00) && (l->m01 == matrix->m01) && (l->m10 == matrix->m10) && (l->m11 == matrix->m11);
     char same_color = !memcmp(color, &i->state.last_color[OP_DRAWCHAR], sizeof(gfxcolor_t));
-    U8 flags = 0;
+
+    /* FIXME
     if(same_font && same_matrix && same_color)
        flags |= FLAG_SAME_AS_LAST;
+    */
 
     writer_writeU8(&i->w, OP_DRAWCHAR|flags);
     writer_writeU32(&i->w, glyphnr);
@@ -596,10 +619,15 @@ static void record_drawchar(struct _gfxdevice*dev, gfxfont_t*font, int glyphnr,
 #endif
 
     if(!(flags&FLAG_SAME_AS_LAST)) {
-       writer_writeString(&i->w, font_id);
+       if(!(flags&FLAG_ZERO_FONT))
+           writer_writeString(&i->w, font_id);
        dumpColor(&i->w, &i->state, color);
        dumpMatrix(&i->w, &i->state, matrix);
+
+       if(i->state.last_string[OP_DRAWCHAR])
+           free(i->state.last_string[OP_DRAWCHAR]);
        i->state.last_string[OP_DRAWCHAR] = strdup(font_id);
+
        i->state.last_color[OP_DRAWCHAR] = *color;
        i->state.last_matrix[OP_DRAWCHAR] = *matrix;
     } else {
@@ -634,18 +662,20 @@ static void record_drawlink(struct _gfxdevice*dev, gfxline_t*line, const char*ac
 
 /* ------------------------------- replaying --------------------------------- */
 
-static void replay(struct _gfxdevice*dev, gfxdevice_t*out, reader_t*r)
+static void replay(struct _gfxdevice*dev, gfxdevice_t*out, reader_t*r, gfxfontlist_t**fontlist)
 {
     internal_t*i = 0;
     if(dev) {
        i = (internal_t*)dev->internal;
     }
+    gfxfontlist_t*_fontlist=0;
+    if(!fontlist) {
+       fontlist = &_fontlist;
+    }
 
     state_t state;
     memset(&state, 0, sizeof(state));
 
-    gfxfontlist_t* fontlist = gfxfontlist_create();
-
     while(1) {
        unsigned char op;
        if(r->read(r, &op, 1)!=1)
@@ -768,37 +798,42 @@ static void replay(struct _gfxdevice*dev, gfxdevice_t*out, reader_t*r)
            case OP_ADDFONT: {
                msg("<trace> replay: ADDFONT out=%08x(%s)", out, out->name);
                gfxfont_t*font = readFont(r, &state);
-               fontlist = gfxfontlist_addfont(fontlist, font);
-               out->addfont(out, font);
+               if(!gfxfontlist_hasfont(*fontlist, font)) {
+                   *fontlist = gfxfontlist_addfont(*fontlist, font);
+                   out->addfont(out, font);
+               } else {
+                   gfxfont_free(font);
+               }
                break;
            }
            case OP_DRAWCHAR: {
                U32 glyph = reader_readU32(r);
                gfxmatrix_t m = {1,0,0, 0,1,0};
-               char* id = read_string(r, &state, op, flags);
+               char* id = 0;
+               if(!(flags&FLAG_ZERO_FONT))
+                   id = read_string(r, &state, op, flags);
                gfxcolor_t color = read_color(r, &state, op, flags);
                gfxmatrix_t matrix = read_matrix(r, &state, op, flags);
 
-               gfxfont_t*font = id?gfxfontlist_findfont(fontlist, id):0;
+               gfxfont_t*font = id?gfxfontlist_findfont(*fontlist, id):0;
                if(i && !font) {
                    font = gfxfontlist_findfont(i->fontlist, id);
                }
                msg("<trace> replay: DRAWCHAR font=%s glyph=%d", id, glyph);
                out->drawchar(out, font, glyph, &color, &matrix);
-               free(id);
+               if(id)
+                   free(id);
                break;
            }
        }
     }
 finish:
+    state_clear(&state);
     r->dealloc(r);
-    /* problem: if we just replayed into a device which stores the
-       font for later use (the record device itself is a nice example),
-       then we can't free it yet */
-    //gfxfontlist_free(fontlist, 1);
-    gfxfontlist_free(fontlist, 0);
+    if(_fontlist)
+       gfxfontlist_free(_fontlist, 0);
 }
-void gfxresult_record_replay(gfxresult_t*result, gfxdevice_t*device)
+void gfxresult_record_replay(gfxresult_t*result, gfxdevice_t*device, gfxfontlist_t**fontlist)
 {
     internal_result_t*i = (internal_result_t*)result->internal;
     
@@ -809,7 +844,7 @@ void gfxresult_record_replay(gfxresult_t*result, gfxdevice_t*device)
        reader_init_memreader(&r, i->data, i->length);
     }
 
-    replay(0, device, &r);
+    replay(0, device, &r, fontlist);
 }
 
 static void record_result_write(gfxresult_t*r, int filedesc)
@@ -884,7 +919,7 @@ static void hexdumpMem(unsigned char*data, int len)
     }
 }
 
-void gfxdevice_record_flush(gfxdevice_t*dev, gfxdevice_t*out)
+void gfxdevice_record_flush(gfxdevice_t*dev, gfxdevice_t*out, gfxfontlist_t**fontlist)
 {
     internal_t*i = (internal_t*)dev->internal;
     if(out) {
@@ -893,7 +928,7 @@ void gfxdevice_record_flush(gfxdevice_t*dev, gfxdevice_t*out)
            void*data = writer_growmemwrite_memptr(&i->w, &len);
            reader_t r;
            reader_init_memreader(&r, data, len);
-           replay(dev, out, &r);
+           replay(dev, out, &r, fontlist);
            writer_growmemwrite_reset(&i->w);
        } else {
            msg("<fatal> Flushing not supported for file based record device");
@@ -911,6 +946,8 @@ static gfxresult_t* record_finish(struct _gfxdevice*dev)
        msg("<error> Warning: unclosed cliplevels");
     }
 
+    state_clear(&i->state);
+
 #ifdef STATS
     int total = i->w.pos;
     if(total && i->use_tempfile) {