X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=lib%2Fdevices%2Frecord.c;h=abace9b8e1cc947131fbdc67d9aea7f7287be778;hp=b14d51ae68714936cacc103fbf4128b62510a7b0;hb=8589e0d1f5e47c05458033e750fd6182ca704fbe;hpb=b98e8c802642cef8401f1292eb4b5105c2ffaa50 diff --git a/lib/devices/record.c b/lib/devices/record.c index b14d51a..abace9b 100644 --- a/lib/devices/record.c +++ b/lib/devices/record.c @@ -35,14 +35,20 @@ #include "../types.h" #include "../bitio.h" #include "../log.h" +#include "../os.h" #include "record.h" typedef struct _internal { gfxfontlist_t* fontlist; writer_t w; + int cliplevel; + char use_tempfile; + char*filename; } internal_t; typedef struct _internal_result { + char use_tempfile; + char*filename; void*data; int length; } internal_result_t; @@ -69,7 +75,7 @@ typedef struct _internal_result { static int record_setparameter(struct _gfxdevice*dev, const char*key, const char*value) { internal_t*i = (internal_t*)dev->internal; - msg(" record: SETPARAM %s %s\n", key, value); + msg(" record: %08x SETPARAM %s %s\n", dev, key, value); writer_writeU8(&i->w, OP_SETPARAM); writer_writeString(&i->w, key); writer_writeString(&i->w, value); @@ -240,6 +246,8 @@ static void dumpFont(writer_t*w, gfxfont_t*font) writer_writeString(w, font->id); writer_writeU32(w, font->num_glyphs); writer_writeU32(w, font->max_unicode); + writer_writeDouble(w, font->ascent); + writer_writeDouble(w, font->descent); int t; for(t=0;tnum_glyphs;t++) { dumpLine(w, font->glyphs[t].line); @@ -254,6 +262,12 @@ static void dumpFont(writer_t*w, gfxfont_t*font) for(t=0;tmax_unicode;t++) { writer_writeU32(w, font->unicode2glyph[t]); } + writer_writeU32(w, font->kerning_size); + for(t=0;tkerning_size;t++) { + writer_writeU32(w, font->kerning[t].c1); + writer_writeU32(w, font->kerning[t].c2); + writer_writeU32(w, font->kerning[t].advance); + } } static gfxfont_t*readFont(reader_t*r) { @@ -261,6 +275,8 @@ static gfxfont_t*readFont(reader_t*r) font->id = reader_readString(r); font->num_glyphs = reader_readU32(r); font->max_unicode = reader_readU32(r); + font->ascent = reader_readDouble(r); + font->descent = reader_readDouble(r); font->glyphs = (gfxglyph_t*)rfx_calloc(sizeof(gfxglyph_t)*font->num_glyphs); font->unicode2glyph = (int*)rfx_calloc(sizeof(font->unicode2glyph[0])*font->max_unicode); int t; @@ -277,13 +293,22 @@ static gfxfont_t*readFont(reader_t*r) for(t=0;tmax_unicode;t++) { font->unicode2glyph[t] = reader_readU32(r); } + font->kerning_size = reader_readU32(r); + if(font->kerning_size) { + font->kerning = malloc(sizeof(gfxkerning_t)*font->kerning_size); + for(t=0;tkerning_size;t++) { + font->kerning[t].c1 = reader_readU32(r); + font->kerning[t].c2 = reader_readU32(r); + font->kerning[t].advance = reader_readU32(r); + } + } return font; } static void record_stroke(struct _gfxdevice*dev, gfxline_t*line, gfxcoord_t width, gfxcolor_t*color, gfx_capType cap_style, gfx_joinType joint_style, gfxcoord_t miterLimit) { internal_t*i = (internal_t*)dev->internal; - msg(" record: STROKE\n"); + msg(" record: %08x STROKE\n", dev); writer_writeU8(&i->w, OP_STROKE); writer_writeDouble(&i->w, width); writer_writeDouble(&i->w, miterLimit); @@ -296,22 +321,27 @@ static void record_stroke(struct _gfxdevice*dev, gfxline_t*line, gfxcoord_t widt static void record_startclip(struct _gfxdevice*dev, gfxline_t*line) { internal_t*i = (internal_t*)dev->internal; - msg(" record: STARTCLIP\n"); + msg(" record: %08x STARTCLIP\n", dev); writer_writeU8(&i->w, OP_STARTCLIP); dumpLine(&i->w, line); + i->cliplevel++; } static void record_endclip(struct _gfxdevice*dev) { internal_t*i = (internal_t*)dev->internal; - msg(" record: ENDCLIP\n"); + msg(" record: %08x ENDCLIP\n", dev); writer_writeU8(&i->w, OP_ENDCLIP); + i->cliplevel--; + if(i->cliplevel<0) { + msg(" record: endclip() without startclip()"); + } } static void record_fill(struct _gfxdevice*dev, gfxline_t*line, gfxcolor_t*color) { internal_t*i = (internal_t*)dev->internal; - msg(" record: FILL\n"); + msg(" record: %08x FILL\n", dev); writer_writeU8(&i->w, OP_FILL); dumpColor(&i->w, color); dumpLine(&i->w, line); @@ -320,7 +350,7 @@ static void record_fill(struct _gfxdevice*dev, gfxline_t*line, gfxcolor_t*color) static void record_fillbitmap(struct _gfxdevice*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*matrix, gfxcxform_t*cxform) { internal_t*i = (internal_t*)dev->internal; - msg(" record: FILLBITMAP\n"); + msg(" record: %08x FILLBITMAP\n", dev); writer_writeU8(&i->w, OP_FILLBITMAP); dumpImage(&i->w, img); dumpMatrix(&i->w, matrix); @@ -331,7 +361,7 @@ static void record_fillbitmap(struct _gfxdevice*dev, gfxline_t*line, gfximage_t* static void record_fillgradient(struct _gfxdevice*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*matrix) { internal_t*i = (internal_t*)dev->internal; - msg(" record: FILLGRADIENT\n"); + msg(" record: %08x FILLGRADIENT %08x\n", dev, gradient); writer_writeU8(&i->w, OP_FILLGRADIENT); writer_writeU8(&i->w, type); dumpGradient(&i->w, gradient); @@ -342,10 +372,12 @@ static void record_fillgradient(struct _gfxdevice*dev, gfxline_t*line, gfxgradie static void record_addfont(struct _gfxdevice*dev, gfxfont_t*font) { internal_t*i = (internal_t*)dev->internal; - msg(" record: ADDFONT\n"); - writer_writeU8(&i->w, OP_ADDFONT); - dumpFont(&i->w, font); - i->fontlist = gfxfontlist_addfont(i->fontlist, font); + msg(" record: %08x ADDFONT %s\n", dev, font->id); + if(font && !gfxfontlist_hasfont(i->fontlist, font)) { + writer_writeU8(&i->w, OP_ADDFONT); + dumpFont(&i->w, font); + i->fontlist = gfxfontlist_addfont(i->fontlist, font); + } } static void record_drawchar(struct _gfxdevice*dev, gfxfont_t*font, int glyphnr, gfxcolor_t*color, gfxmatrix_t*matrix) @@ -353,10 +385,9 @@ static void record_drawchar(struct _gfxdevice*dev, gfxfont_t*font, int glyphnr, internal_t*i = (internal_t*)dev->internal; if(font && !gfxfontlist_hasfont(i->fontlist, font)) { record_addfont(dev, font); - i->fontlist = gfxfontlist_addfont(i->fontlist, font); } - msg(" record: DRAWCHAR %d\n", glyphnr); + msg(" record: %08x DRAWCHAR %d\n", glyphnr, dev); writer_writeU8(&i->w, OP_DRAWCHAR); if(font) writer_writeString(&i->w, font->id); @@ -370,7 +401,7 @@ static void record_drawchar(struct _gfxdevice*dev, gfxfont_t*font, int glyphnr, static void record_startpage(struct _gfxdevice*dev, int width, int height) { internal_t*i = (internal_t*)dev->internal; - msg(" record: STARTPAGE\n"); + msg(" record: %08x STARTPAGE\n", dev); writer_writeU8(&i->w, OP_STARTPAGE); writer_writeU16(&i->w, width); writer_writeU16(&i->w, height); @@ -379,44 +410,43 @@ static void record_startpage(struct _gfxdevice*dev, int width, int height) static void record_endpage(struct _gfxdevice*dev) { internal_t*i = (internal_t*)dev->internal; - msg(" record: ENDPAGE\n"); + msg(" record: %08x ENDPAGE\n", dev); writer_writeU8(&i->w, OP_ENDPAGE); } static void record_drawlink(struct _gfxdevice*dev, gfxline_t*line, const char*action) { internal_t*i = (internal_t*)dev->internal; - msg(" record: DRAWLINK\n"); + msg(" record: %08x DRAWLINK\n", dev); writer_writeU8(&i->w, OP_DRAWLINK); dumpLine(&i->w, line); writer_writeString(&i->w, action); } -static void replay(struct _gfxdevice*recorddev, gfxdevice_t*device, void*data, int length) +static void replay(struct _gfxdevice*dev, gfxdevice_t*out, reader_t*r) { internal_t*i = 0; - if(recorddev) { - i = (internal_t*)recorddev->internal; + if(dev) { + i = (internal_t*)dev->internal; } - reader_t r2; - reader_t*r = &r2; - reader_init_memreader(r, data, length); gfxfontlist_t* fontlist = gfxfontlist_create(); - while(r->pos < length) { - unsigned char op = reader_readU8(r); + while(1) { + unsigned char op; + if(r->read(r, &op, 1)!=1) + break; + switch(op) { case OP_END: - msg(" replay: END"); - return; + goto finish; case OP_SETPARAM: { msg(" replay: SETPARAM"); char*key; char*value; key = reader_readString(r); value = reader_readString(r); - device->setparameter(device, key, value); + out->setparameter(out, key, value); free(key); free(value); break; @@ -425,11 +455,12 @@ static void replay(struct _gfxdevice*recorddev, gfxdevice_t*device, void*data, i msg(" replay: STARTPAGE"); U16 width = reader_readU16(r); U16 height = reader_readU16(r); - device->startpage(device, width, height); + out->startpage(out, width, height); break; } case OP_ENDPAGE: { msg(" replay: ENDPAGE"); + out->endpage(out); break; } case OP_FINISH: { @@ -456,27 +487,27 @@ static void replay(struct _gfxdevice*recorddev, gfxdevice_t*device, void*data, i case 2: jointtype = gfx_joinBevel; break; } gfxline_t* line = readLine(r); - device->stroke(device, line, width, &color, captype, jointtype,miterlimit); + out->stroke(out, line, width, &color, captype, jointtype,miterlimit); gfxline_free(line); break; } case OP_STARTCLIP: { msg(" replay: STARTCLIP"); gfxline_t* line = readLine(r); - device->startclip(device, line); + out->startclip(out, line); gfxline_free(line); break; } case OP_ENDCLIP: { msg(" replay: ENDCLIP"); - device->endclip(device); + out->endclip(out); break; } case OP_FILL: { msg(" replay: FILL"); gfxcolor_t color = readColor(r); gfxline_t* line = readLine(r); - device->fill(device, line, &color); + out->fill(out, line, &color); gfxline_free(line); break; } @@ -486,9 +517,11 @@ static void replay(struct _gfxdevice*recorddev, gfxdevice_t*device, void*data, i gfxmatrix_t matrix = readMatrix(r); gfxline_t* line = readLine(r); gfxcxform_t* cxform = readCXForm(r); - device->fillbitmap(device, line, &img, &matrix, cxform); + out->fillbitmap(out, line, &img, &matrix, cxform); + gfxline_free(line); if(cxform) free(cxform); + free(img.data);img.data=0; break; } case OP_FILLGRADIENT: { @@ -504,23 +537,23 @@ static void replay(struct _gfxdevice*recorddev, gfxdevice_t*device, void*data, i gfxgradient_t*gradient = readGradient(r); gfxmatrix_t matrix = readMatrix(r); gfxline_t* line = readLine(r); - device->fillgradient(device, line, gradient, type, &matrix); + out->fillgradient(out, line, gradient, type, &matrix); break; } case OP_DRAWLINK: { msg(" replay: DRAWLINK"); gfxline_t* line = readLine(r); char* s = reader_readString(r); - device->drawlink(device,line,s); + out->drawlink(out,line,s); gfxline_free(line); free(s); break; } case OP_ADDFONT: { - msg(" replay: ADDFONT"); + msg(" replay: ADDFONT out=%08x(%s)", out, out->name); gfxfont_t*font = readFont(r); fontlist = gfxfontlist_addfont(fontlist, font); - device->addfont(device, font); + out->addfont(out, font); break; } case OP_DRAWCHAR: { @@ -533,36 +566,55 @@ static void replay(struct _gfxdevice*recorddev, gfxdevice_t*device, void*data, i msg(" replay: DRAWCHAR font=%s glyph=%d", id, glyph); gfxcolor_t color = readColor(r); gfxmatrix_t matrix = readMatrix(r); - device->drawchar(device, font, glyph, &color, &matrix); + out->drawchar(out, font, glyph, &color, &matrix); free(id); break; } } } +finish: r->dealloc(r); - gfxfontlist_free(fontlist, 1); + /* 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); } void gfxresult_record_replay(gfxresult_t*result, gfxdevice_t*device) { internal_result_t*i = (internal_result_t*)result->internal; - replay(0, device, i->data, i->length); + + reader_t r; + if(i->use_tempfile) { + reader_init_filereader2(&r, i->filename); + } else { + reader_init_memreader(&r, i->data, i->length); + } + + replay(0, device, &r); } static void record_result_write(gfxresult_t*r, int filedesc) { internal_result_t*i = (internal_result_t*)r->internal; - write(filedesc, i->data, i->length); + if(i->data) { + write(filedesc, i->data, i->length); + } } static int record_result_save(gfxresult_t*r, const char*filename) { internal_result_t*i = (internal_result_t*)r->internal; - FILE*fi = fopen(filename, "wb"); - if(!fi) { - fprintf(stderr, "Couldn't open file %s for writing\n", filename); - return -1; + if(i->use_tempfile) { + move_file(i->filename, filename); + } else { + FILE*fi = fopen(filename, "wb"); + if(!fi) { + fprintf(stderr, "Couldn't open file %s for writing\n", filename); + return -1; + } + fwrite(i->data, i->length, 1, fi); + fclose(fi); } - fwrite(i->data, i->length, 1, fi); - fclose(fi); return 0; } static void*record_result_get(gfxresult_t*r, const char*name) @@ -581,6 +633,10 @@ static void record_result_destroy(gfxresult_t*r) if(i->data) { free(i->data);i->data = 0; } + if(i->filename) { + unlink(i->filename); + free(i->filename); + } free(r->internal);r->internal = 0; free(r); } @@ -614,25 +670,42 @@ void gfxdevice_record_flush(gfxdevice_t*dev, gfxdevice_t*out) { internal_t*i = (internal_t*)dev->internal; if(out) { - int len=0; - void*data = writer_growmemwrite_memptr(&i->w, &len); - replay(dev, out, data, len); + if(!i->use_tempfile) { + int len=0; + void*data = writer_growmemwrite_memptr(&i->w, &len); + reader_t r; + reader_init_memreader(&r, data, len); + replay(dev, out, &r); + writer_growmemwrite_reset(&i->w); + } else { + msg(" Flushing not supported for file based record device"); + exit(1); + } } - writer_growmemwrite_reset(&i->w); } static gfxresult_t* record_finish(struct _gfxdevice*dev) { internal_t*i = (internal_t*)dev->internal; - msg(" record: END\n"); + msg(" record: %08x END", dev); + + if(i->cliplevel) { + msg(" Warning: unclosed cliplevels"); + } writer_writeU8(&i->w, OP_END); gfxfontlist_free(i->fontlist, 0); internal_result_t*ir = (internal_result_t*)rfx_calloc(sizeof(gfxresult_t)); - ir->data = writer_growmemwrite_getmem(&i->w); - ir->length = i->w.pos; + + ir->use_tempfile = i->use_tempfile; + if(i->use_tempfile) { + ir->filename = i->filename; + } else { + ir->data = writer_growmemwrite_getmem(&i->w); + ir->length = i->w.pos; + } i->w.finish(&i->w); gfxresult_t*result= (gfxresult_t*)rfx_calloc(sizeof(gfxresult_t)); @@ -645,7 +718,8 @@ static gfxresult_t* record_finish(struct _gfxdevice*dev) return result; } -void gfxdevice_record_init(gfxdevice_t*dev) + +void gfxdevice_record_init(gfxdevice_t*dev, char use_tempfile) { internal_t*i = (internal_t*)rfx_calloc(sizeof(internal_t)); memset(dev, 0, sizeof(gfxdevice_t)); @@ -653,9 +727,17 @@ void gfxdevice_record_init(gfxdevice_t*dev) dev->name = "record"; dev->internal = i; - - writer_init_growingmemwriter(&i->w, 1048576); + + i->use_tempfile = use_tempfile; + if(!use_tempfile) { + writer_init_growingmemwriter(&i->w, 1048576); + } else { + char buffer[128]; + i->filename = strdup(mktempname(buffer, "gfx")); + writer_init_filewriter2(&i->w, i->filename); + } i->fontlist = gfxfontlist_create(); + i->cliplevel = 0; dev->setparameter = record_setparameter; dev->startpage = record_startpage;