3 Part of the swftools package.
5 Copyright (c) 2005 Matthias Kramm <kramm@quiss.org>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
32 #include "../gfxdevice.h"
33 #include "../gfxtools.h"
38 typedef struct _internal {
39 gfxfontlist_t* fontlist;
43 typedef struct _internal_result {
49 #define OP_SETPARAM 0x01
50 #define OP_STROKE 0x02
51 #define OP_STARTCLIP 0x03
52 #define OP_ENDCLIP 0x04
54 #define OP_FILLBITMAP 0x06
55 #define OP_FILLGRADIENT 0x07
56 #define OP_ADDFONT 0x08
57 #define OP_DRAWCHAR 0x09
58 #define OP_DRAWLINK 0x0a
59 #define OP_STARTPAGE 0x0b
60 #define OP_ENDPAGE 0x0c
61 #define OP_FINISH 0x0d
63 #define OP_MOVETO 0x0e
64 #define OP_LINETO 0x0f
65 #define OP_SPLINETO 0x10
67 static int record_setparameter(struct _gfxdevice*dev, const char*key, const char*value)
69 internal_t*i = (internal_t*)dev->internal;
70 writer_writeU8(&i->w, OP_SETPARAM);
71 writer_writeString(&i->w, key);
72 writer_writeString(&i->w, value);
76 static void dumpLine(writer_t*w, gfxline_t*line)
79 if(line->type == gfx_moveTo) {
80 writer_writeU8(w, OP_MOVETO);
81 writer_writeDouble(w, line->x);
82 writer_writeDouble(w, line->y);
83 } else if(line->type == gfx_lineTo) {
84 writer_writeU8(w, OP_LINETO);
85 writer_writeDouble(w, line->x);
86 writer_writeDouble(w, line->y);
87 } else if(line->type == gfx_splineTo) {
88 writer_writeU8(w, OP_SPLINETO);
89 writer_writeDouble(w, line->x);
90 writer_writeDouble(w, line->y);
91 writer_writeDouble(w, line->sx);
92 writer_writeDouble(w, line->sy);
96 writer_writeU8(w, OP_END);
98 static gfxline_t* readLine(reader_t*r)
100 gfxline_t*start = 0, *pos = 0;
102 unsigned char op = reader_readU8(r);
105 gfxline_t*line = (gfxline_t*)rfx_calloc(sizeof(gfxline_t));
112 if(op == OP_MOVETO) {
113 line->type = gfx_moveTo;
114 line->x = reader_readDouble(r);
115 line->y = reader_readDouble(r);
116 } else if(op == OP_LINETO) {
117 line->type = gfx_lineTo;
118 line->x = reader_readDouble(r);
119 line->y = reader_readDouble(r);
120 } else if(op == OP_SPLINETO) {
121 line->type = gfx_splineTo;
122 line->x = reader_readDouble(r);
123 line->y = reader_readDouble(r);
124 line->sx = reader_readDouble(r);
125 line->sy = reader_readDouble(r);
130 static gfximage_t readImage(reader_t*r)
133 img.width = reader_readU16(r);
134 img.height = reader_readU16(r);
135 img.data = (gfxcolor_t*)rfx_alloc(img.width*img.height*4);
136 r->read(r, img.data, img.width*img.height*4);
139 static gfxmatrix_t readMatrix(reader_t*r)
142 matrix.m00 = reader_readDouble(r);
143 matrix.m01 = reader_readDouble(r);
144 matrix.m10 = reader_readDouble(r);
145 matrix.m11 = reader_readDouble(r);
146 matrix.tx = reader_readDouble(r);
147 matrix.ty = reader_readDouble(r);
150 static gfxcolor_t readColor(reader_t*r)
153 col.r = reader_readU8(r);
154 col.g = reader_readU8(r);
155 col.b = reader_readU8(r);
156 col.a = reader_readU8(r);
159 static gfxgradient_t* readGradient(reader_t*r)
161 gfxgradient_t*start = 0, *pos = 0;
163 U8 op = reader_readU8(r);
166 gfxgradient_t*g = (gfxgradient_t*)rfx_calloc(sizeof(gfxgradient_t));
173 g->color = readColor(r);
174 g->pos = reader_readFloat(r);
178 static gfxcxform_t* readCXForm(reader_t*r)
180 U8 type = reader_readU8(r);
183 gfxcxform_t* c = (gfxcxform_t*)rfx_calloc(sizeof(gfxcxform_t));
184 c->rr = reader_readFloat(r); c->rg = reader_readFloat(r); c->rb = reader_readFloat(r); c->ra = reader_readFloat(r);
185 c->gr = reader_readFloat(r); c->gg = reader_readFloat(r); c->gb = reader_readFloat(r); c->ga = reader_readFloat(r);
186 c->br = reader_readFloat(r); c->bg = reader_readFloat(r); c->bb = reader_readFloat(r); c->ba = reader_readFloat(r);
187 c->ar = reader_readFloat(r); c->ag = reader_readFloat(r); c->ab = reader_readFloat(r); c->aa = reader_readFloat(r);
191 static void dumpColor(writer_t*w, gfxcolor_t*color)
193 writer_writeU8(w, color->r);
194 writer_writeU8(w, color->g);
195 writer_writeU8(w, color->b);
196 writer_writeU8(w, color->a);
198 static void dumpMatrix(writer_t*w, gfxmatrix_t*matrix)
200 writer_writeDouble(w, matrix->m00);
201 writer_writeDouble(w, matrix->m01);
202 writer_writeDouble(w, matrix->m10);
203 writer_writeDouble(w, matrix->m11);
204 writer_writeDouble(w, matrix->tx);
205 writer_writeDouble(w, matrix->ty);
207 static void dumpGradient(writer_t*w, gfxgradient_t*gradient)
210 writer_writeU8(w, 1);
211 dumpColor(w, &gradient->color);
212 writer_writeFloat(w, gradient->pos);
213 gradient = gradient->next;
215 writer_writeU8(w, 0);
217 static void dumpImage(writer_t*w, gfximage_t*image)
219 writer_writeU16(w, image->width);
220 writer_writeU16(w, image->height);
221 w->write(w, image->data, image->width*image->height*4);
223 static void dumpCXForm(writer_t*w, gfxcxform_t*c)
226 writer_writeU8(w, 0);
228 writer_writeU8(w, 1);
229 writer_writeFloat(w, c->rr); writer_writeFloat(w, c->rg); writer_writeFloat(w, c->rb); writer_writeFloat(w, c->ra);
230 writer_writeFloat(w, c->gr); writer_writeFloat(w, c->gg); writer_writeFloat(w, c->gb); writer_writeFloat(w, c->ga);
231 writer_writeFloat(w, c->br); writer_writeFloat(w, c->bg); writer_writeFloat(w, c->bb); writer_writeFloat(w, c->ba);
232 writer_writeFloat(w, c->ar); writer_writeFloat(w, c->ag); writer_writeFloat(w, c->ab); writer_writeFloat(w, c->aa);
235 static void dumpFont(writer_t*w, gfxfont_t*font)
237 writer_writeString(w, font->id);
238 writer_writeU32(w, font->num_glyphs);
239 writer_writeU32(w, font->max_unicode);
241 for(t=0;t<font->num_glyphs;t++) {
242 dumpLine(w, font->glyphs[t].line);
243 writer_writeDouble(w, font->glyphs[t].advance);
244 writer_writeU32(w, font->glyphs[t].unicode);
245 if(font->glyphs[t].name) {
246 writer_writeString(w,font->glyphs[t].name);
251 for(t=0;t<font->max_unicode;t++) {
252 writer_writeU32(w, font->unicode2glyph[t]);
255 static gfxfont_t*readFont(reader_t*r)
257 gfxfont_t* font = (gfxfont_t*)rfx_calloc(sizeof(gfxfont_t));
258 font->id = reader_readString(r);
259 font->num_glyphs = reader_readU32(r);
260 font->max_unicode = reader_readU32(r);
261 font->glyphs = (gfxglyph_t*)rfx_calloc(sizeof(gfxglyph_t)*font->num_glyphs);
262 font->unicode2glyph = (int*)rfx_calloc(sizeof(font->unicode2glyph[0])*font->max_unicode);
264 for(t=0;t<font->num_glyphs;t++) {
265 font->glyphs[t].line = readLine(r);
266 font->glyphs[t].advance = reader_readDouble(r);
267 font->glyphs[t].unicode = reader_readU32(r);
268 font->glyphs[t].name = reader_readString(r);
269 if(!font->glyphs[t].name[0]) {
270 free((void*)(font->glyphs[t].name));
271 font->glyphs[t].name = 0;
274 for(t=0;t<font->max_unicode;t++) {
275 font->unicode2glyph[t] = reader_readU32(r);
280 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)
282 internal_t*i = (internal_t*)dev->internal;
283 writer_writeU8(&i->w, OP_STROKE);
284 writer_writeDouble(&i->w, width);
285 writer_writeDouble(&i->w, miterLimit);
286 dumpColor(&i->w, color);
287 writer_writeU8(&i->w, cap_style);
288 writer_writeU8(&i->w, joint_style);
289 dumpLine(&i->w, line);
292 static void record_startclip(struct _gfxdevice*dev, gfxline_t*line)
294 internal_t*i = (internal_t*)dev->internal;
295 writer_writeU8(&i->w, OP_STARTCLIP);
296 dumpLine(&i->w, line);
299 static void record_endclip(struct _gfxdevice*dev)
301 internal_t*i = (internal_t*)dev->internal;
302 writer_writeU8(&i->w, OP_ENDCLIP);
305 static void record_fill(struct _gfxdevice*dev, gfxline_t*line, gfxcolor_t*color)
307 internal_t*i = (internal_t*)dev->internal;
308 writer_writeU8(&i->w, OP_FILL);
309 dumpColor(&i->w, color);
310 dumpLine(&i->w, line);
313 static void record_fillbitmap(struct _gfxdevice*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*matrix, gfxcxform_t*cxform)
315 internal_t*i = (internal_t*)dev->internal;
316 writer_writeU8(&i->w, OP_FILLBITMAP);
317 dumpImage(&i->w, img);
318 dumpMatrix(&i->w, matrix);
319 dumpLine(&i->w, line);
320 dumpCXForm(&i->w, cxform);
323 static void record_fillgradient(struct _gfxdevice*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*matrix)
325 internal_t*i = (internal_t*)dev->internal;
326 writer_writeU8(&i->w, OP_FILLGRADIENT);
327 writer_writeU8(&i->w, type);
328 dumpGradient(&i->w, gradient);
329 dumpMatrix(&i->w, matrix);
330 dumpLine(&i->w, line);
333 static void record_addfont(struct _gfxdevice*dev, gfxfont_t*font)
335 internal_t*i = (internal_t*)dev->internal;
336 writer_writeU8(&i->w, OP_ADDFONT);
337 dumpFont(&i->w, font);
338 i->fontlist = gfxfontlist_addfont(i->fontlist, font);
341 static void record_drawchar(struct _gfxdevice*dev, gfxfont_t*font, int glyphnr, gfxcolor_t*color, gfxmatrix_t*matrix)
343 internal_t*i = (internal_t*)dev->internal;
344 if(font && !gfxfontlist_hasfont(i->fontlist, font))
345 record_addfont(dev, font);
347 writer_writeU8(&i->w, OP_DRAWCHAR);
349 writer_writeString(&i->w, font->id);
351 writer_writeString(&i->w, "*NULL*");
352 writer_writeU32(&i->w, glyphnr);
353 dumpColor(&i->w, color);
354 dumpMatrix(&i->w, matrix);
357 static void record_startpage(struct _gfxdevice*dev, int width, int height)
359 internal_t*i = (internal_t*)dev->internal;
360 writer_writeU8(&i->w, OP_STARTPAGE);
361 writer_writeU16(&i->w, width);
362 writer_writeU16(&i->w, height);
365 static void record_endpage(struct _gfxdevice*dev)
367 internal_t*i = (internal_t*)dev->internal;
368 writer_writeU8(&i->w, OP_ENDPAGE);
371 static void record_drawlink(struct _gfxdevice*dev, gfxline_t*line, const char*action)
373 internal_t*i = (internal_t*)dev->internal;
374 writer_writeU8(&i->w, OP_DRAWLINK);
375 dumpLine(&i->w, line);
376 writer_writeString(&i->w, action);
379 void gfxresult_record_replay(gfxresult_t*result, gfxdevice_t*device)
381 internal_result_t*i = (internal_result_t*)result->internal;
384 reader_init_memreader(r, i->data, i->length);
385 gfxfontlist_t* fontlist = gfxfontlist_create();
388 unsigned char op = reader_readU8(r);
395 key = reader_readString(r);
396 value = reader_readString(r);
397 device->setparameter(device, key, value);
403 U16 width = reader_readU16(r);
404 U16 height = reader_readU16(r);
405 device->startpage(device, width, height);
415 double width = reader_readDouble(r);
416 double miterlimit = reader_readDouble(r);
417 gfxcolor_t color = readColor(r);
419 int v = reader_readU8(r);
421 case 0: captype = gfx_capButt; break;
422 case 1: captype = gfx_capRound; break;
423 case 2: captype = gfx_capSquare; break;
425 gfx_joinType jointtype;
426 v = reader_readU8(r);
428 case 0: jointtype = gfx_joinMiter; break;
429 case 1: jointtype = gfx_joinRound; break;
430 case 2: jointtype = gfx_joinBevel; break;
432 gfxline_t* line = readLine(r);
433 device->stroke(device, line, width, &color, captype, jointtype,miterlimit);
438 gfxline_t* line = readLine(r);
439 device->startclip(device, line);
444 device->endclip(device);
448 gfxcolor_t color = readColor(r);
449 gfxline_t* line = readLine(r);
450 device->fill(device, line, &color);
454 case OP_FILLBITMAP: {
455 gfximage_t img = readImage(r);
456 gfxmatrix_t matrix = readMatrix(r);
457 gfxline_t* line = readLine(r);
458 gfxcxform_t* cxform = readCXForm(r);
459 device->fillbitmap(device, line, &img, &matrix, cxform);
464 case OP_FILLGRADIENT: {
465 gfxgradienttype_t type;
466 int v = reader_readU8(r);
469 type = gfxgradient_radial; break;
471 type = gfxgradient_linear; break;
473 gfxgradient_t*gradient = readGradient(r);
474 gfxmatrix_t matrix = readMatrix(r);
475 gfxline_t* line = readLine(r);
476 device->fillgradient(device, line, gradient, type, &matrix);
480 gfxline_t* line = readLine(r);
481 char* s = reader_readString(r);
482 device->drawlink(device,line,s);
488 gfxfont_t*font = readFont(r);
489 fontlist = gfxfontlist_addfont(fontlist, font);
490 device->addfont(device, font);
494 char* id = reader_readString(r);
495 gfxfont_t*font = id?gfxfontlist_findfont(fontlist, id):0;
496 U32 glyph = reader_readU32(r);
497 gfxcolor_t color = readColor(r);
498 gfxmatrix_t matrix = readMatrix(r);
499 device->drawchar(device, font, glyph, &color, &matrix);
507 static void record_result_write(gfxresult_t*r, int filedesc)
509 internal_result_t*i = (internal_result_t*)r->internal;
510 write(filedesc, i->data, i->length);
512 static int record_result_save(gfxresult_t*r, const char*filename)
514 internal_result_t*i = (internal_result_t*)r->internal;
515 FILE*fi = fopen(filename, "wb");
517 fprintf(stderr, "Couldn't open file %s for writing\n", filename);
520 fwrite(i->data, i->length, 1, fi);
524 static void*record_result_get(gfxresult_t*r, const char*name)
526 internal_result_t*i = (internal_result_t*)r->internal;
527 if(!strcmp(name, "data")) {
529 } else if(!strcmp(name, "length")) {
534 static void record_result_destroy(gfxresult_t*r)
536 internal_result_t*i = (internal_result_t*)r->internal;
537 free(i->data);i->data = 0;
538 free(r->internal);r->internal = 0;
543 static gfxresult_t* record_finish(struct _gfxdevice*dev)
545 internal_t*i = (internal_t*)dev->internal;
547 writer_writeU8(&i->w, OP_END);
549 internal_result_t*ir = (internal_result_t*)rfx_calloc(sizeof(gfxresult_t));
550 ir->data = writer_growmemwrite_getmem(&i->w);
551 ir->length = i->w.pos;
553 gfxresult_t*result= (gfxresult_t*)rfx_calloc(sizeof(gfxresult_t));
554 result->save = record_result_save;
555 result->get = record_result_get;
556 result->destroy = record_result_destroy;
557 result->internal = ir;
559 free(dev->internal);memset(dev, 0, sizeof(gfxdevice_t));
563 void gfxdevice_record_init(gfxdevice_t*dev)
565 internal_t*i = (internal_t*)rfx_calloc(sizeof(internal_t));
566 memset(dev, 0, sizeof(gfxdevice_t));
568 dev->name = "record";
572 writer_init_growingmemwriter(&i->w, 1048576);
573 i->fontlist = gfxfontlist_create();
575 dev->setparameter = record_setparameter;
576 dev->startpage = record_startpage;
577 dev->startclip = record_startclip;
578 dev->endclip = record_endclip;
579 dev->stroke = record_stroke;
580 dev->fill = record_fill;
581 dev->fillbitmap = record_fillbitmap;
582 dev->fillgradient = record_fillgradient;
583 dev->addfont = record_addfont;
584 dev->drawchar = record_drawchar;
585 dev->drawlink = record_drawlink;
586 dev->endpage = record_endpage;
587 dev->finish = record_finish;