X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=lib%2Fdevices%2Frecord.c;h=48b57f659a698031f58a1fdd4d249b9bd0c27e7b;hp=436523005a0212806dd3887062474872de770ab4;hb=f32de5188d6ec5a3b70ced18669e27e0b250bf50;hpb=e321a0df2c56ff61602b13c1440465911b231f89 diff --git a/lib/devices/record.c b/lib/devices/record.c index 4365230..48b57f6 100644 --- a/lib/devices/record.c +++ b/lib/devices/record.c @@ -34,6 +34,7 @@ #include #include "../gfxdevice.h" #include "../gfxtools.h" +#include "../gfxfont.h" #include "../types.h" #include "../bitio.h" #include "../log.h" @@ -45,6 +46,8 @@ #include "record.h" //#define STATS +#define COMPRESS_IMAGES +//#define FILTER_IMAGES typedef struct _state { char*last_string[16]; @@ -95,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 @@ -169,41 +173,52 @@ static gfxline_t* readLine(reader_t*r, state_t*s) return start; } -#define COMPRESS_IMAGES static void dumpImage(writer_t*w, state_t*state, gfximage_t*img) { int oldpos = w->pos; writer_writeU16(w, img->width); writer_writeU16(w, img->height); #ifdef COMPRESS_IMAGES - //45.2% images (3055340 bytes) (without filter) - //39.9% images (2458904 bytes) (with filter, Z_BEST_SPEED) //35.3% images (2027305 bytes) (with filter, Z_BEST_COMPRESSION) + //39.9% images (2458904 bytes) (with filter, Z_BEST_SPEED) + //45.2% images (3055340 bytes) (without filter) + //45.9% images (3149247 bytes) (without filter, 5) //48.0% images (3480495 bytes) (with filter, fastlz) + //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 unsigned char*filter = malloc(img->height); int y; - gfxcolor_t*image = malloc(img->width*img->height*sizeof(gfxcolor_t)); + image = malloc(img->width*img->height*sizeof(gfxcolor_t)); for(y=0;yheight;y++) { filter[y] = png_apply_filter_32( (void*)&image[y*img->width], (void*)&img->data[y*img->width], img->width, y); } +#else + image = img->data; +#endif int size = img->width*img->height; uLongf compressdata_size = compressBound(size*sizeof(gfxcolor_t)); void*compressdata = malloc(compressdata_size); #ifdef HAVE_FASTLZ - compressdata_size = fastlz_compress_level(1, (void*)image, size*sizeof(gfxcolor_t), compressdata); + compressdata_size = fastlz_compress_level(2, (void*)image, size*sizeof(gfxcolor_t), compressdata); #else compress2(compressdata, &compressdata_size, (void*)image, sizeof(gfxcolor_t)*size, Z_BEST_SPEED); #endif writer_writeU32(w, compressdata_size); +#ifdef FILTER_IMAGES w->write(w, filter, img->height); - w->write(w, compressdata, compressdata_size); - free(image); free(filter); + free(image); +#endif + w->write(w, compressdata, compressdata_size); #else w->write(w, img->data, img->width*img->height*sizeof(gfxcolor_t)); #endif @@ -221,16 +236,19 @@ static gfximage_t readImage(reader_t*r, state_t*state) #ifdef COMPRESS_IMAGES uLongf compressdata_size = reader_readU32(r); void*compressdata = malloc(compressdata_size); +# ifdef FILTER_IMAGES unsigned char*filter = malloc(img.height); r->read(r, filter, img.height); +# endif r->read(r, compressdata, compressdata_size); -#ifdef HAVE_FASTLZ +# ifdef HAVE_FASTLZ fastlz_decompress(compressdata, compressdata_size, (void*)img.data, size); -#else +# else uncompress((void*)img.data, &size, compressdata, compressdata_size); -#endif +# endif +# ifdef FILTER_IMAGES int y; unsigned char*line = malloc(img.width*sizeof(gfxcolor_t)); for(y=0;yread(r, img.data, size); #endif @@ -432,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;tlast_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); @@ -440,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; } @@ -560,16 +595,22 @@ static void record_drawchar(struct _gfxdevice*dev, gfxfont_t*font, int glyphnr, } msg(" 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); @@ -578,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 { @@ -616,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) @@ -750,37 +798,42 @@ static void replay(struct _gfxdevice*dev, gfxdevice_t*out, reader_t*r) case OP_ADDFONT: { msg(" 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(" 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; @@ -791,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) @@ -866,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) { @@ -875,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(" Flushing not supported for file based record device"); @@ -893,6 +946,8 @@ static gfxresult_t* record_finish(struct _gfxdevice*dev) msg(" Warning: unclosed cliplevels"); } + state_clear(&i->state); + #ifdef STATS int total = i->w.pos; if(total && i->use_tempfile) {