X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=lib%2Fgfxtools.c;h=f6853daff5caa667b665277df2342cbc6d29b7de;hp=d8aef3f099c7341af079b6f6d6a1d84782897c28;hb=395359a0831639fcc30aab4ea897e23ff8ab420c;hpb=0e9d27093c3e6e8e316fbc08bb9d422d74da2fd1 diff --git a/lib/gfxtools.c b/lib/gfxtools.c index d8aef3f..f6853da 100644 --- a/lib/gfxtools.c +++ b/lib/gfxtools.c @@ -29,6 +29,7 @@ #include "gfxtools.h" #include "gfxfont.h" #include "jpeg.h" +#include "q.h" typedef struct _linedraw_internal { @@ -233,7 +234,7 @@ void gfxtool_draw_dashed_line(gfxdrawer_t*d, gfxline_t*line, float*r, float phas return; } if(r[0]<0 || phase<0) { - fprintf(stderr, "gfxtool: invalid (negative) dashes: %f, phase=%f", r[0], phase); + fprintf(stderr, "gfxtool: invalid (negative) dashes: %f, phase=%f\n", r[0], phase); return; } @@ -655,6 +656,13 @@ gfxbbox_t gfxbbox_expand_to_point(gfxbbox_t box, gfxcoord_t x, gfxcoord_t y) return box; } +gfxbbox_t gfxbbox_expand_to_bbox(gfxbbox_t box, gfxbbox_t box2) +{ + gfxbbox_expand_to_point(box, box2.xmin, box2.ymin); + gfxbbox_expand_to_point(box, box2.xmax, box2.ymax); + return box; +} + void gfxbbox_intersect(gfxbbox_t*box1, gfxbbox_t*box2) { if(box2->xmin > box1->xmin) @@ -727,8 +735,8 @@ void gfxline_transform(gfxline_t*line, gfxmatrix_t*matrix) void gfxmatrix_dump(gfxmatrix_t*m, FILE*fi, char*prefix) { - fprintf(fi, "%f %f | %f\n", m->m00, m->m10, m->tx); - fprintf(fi, "%f %f | %f\n", m->m01, m->m11, m->ty); + fprintf(fi, "%s%f %f | %f\n", prefix, m->m00, m->m10, m->tx); + fprintf(fi, "%s%f %f | %f\n", prefix, m->m01, m->m11, m->ty); } void gfxmatrix_transform(gfxmatrix_t*m, double* v, double*dest) @@ -1004,18 +1012,188 @@ void gfxline_dump(gfxline_t*line, FILE*fi, char*prefix) } } -void gfximage_save_jpeg(gfximage_t*img, char*filename, int quality) +static char gfxpoint_equals(void*c1, void*c2) { - unsigned char*data = malloc(img->width*img->height*3); - int t; - int size = img->width*img->height; - int s = 0; - for(t=0;tdata[t].r; - data[s+1] = img->data[t].g; - data[s+2] = img->data[t].b; - s+=3; + return !memcmp(c1, c2, sizeof(gfxpoint_t)); +} +static unsigned int gfxpoint_hash(void*c) +{ + return string_hash3(c, sizeof(gfxpoint_t)); +} +static void* gfxpoint_clone(void*c) +{ + void*n = malloc(sizeof(gfxpoint_t)); + memcpy(n, c, sizeof(gfxpoint_t)); + return n; +} +static void gfxpoint_destroy(void*c) +{ + free(c); +} +static type_t gfxpoint_type = { + hash: (hash_func)gfxpoint_hash, + equals: (equals_func)gfxpoint_equals, + dup: (dup_func)gfxpoint_clone, + free: (free_func)gfxpoint_destroy, +}; + +gfxline_t* gfxline_restitch(gfxline_t*line) +{ + dict_t*ff = dict_new2(&gfxpoint_type); + dict_t*rev = dict_new2(&gfxpoint_type); + + gfxline_t*prev=0; + while(line) { + gfxline_t*next = line->next; + if(line->type == gfx_moveTo && (line->next && line->next->type != gfx_moveTo)) { + gfxpoint_t xy = {line->x, line->y}; + dict_put(ff, &xy, line); + prev = line; + } else if(!line->next || line->next->type == gfx_moveTo) { + if(prev) { + gfxpoint_t xy = {line->x, line->y}; + dict_put(rev, &xy, prev); + line->next = 0; + } + } + line = next; + } + + gfxpoint_t pos = {0,0}; + + gfxline_t*result = 0; + gfxline_t*last = 0; + + char first = 1; + while(dict_count(ff)) { + char reverse = 0, stitch = 1; + gfxline_t*l = dict_lookup(ff, &pos); + if(l) { + char d = dict_del2(ff,&pos,l);assert(d); + } else { + l = dict_lookup(rev, &pos); + if(l) { + reverse = 1; + char d = dict_del2(rev,&pos,l);assert(d); + } + } + if(!l) { + /* try to find *any* entry. this is costly, but + doesn't happen too often */ + stitch = 0; + DICT_ITERATE_DATA(ff, gfxline_t*, l2) { + l = l2; + break; + } + assert(l); + gfxpoint_t xy = {l->x,l->y}; + char d = dict_del2(ff,&xy,l);assert(d); + } + + gfxline_t*end = l; + if(!reverse) { + while(end->next) end = end->next; + pos.x = end->x; + pos.y = end->y; + char d = dict_del2(rev,&pos,l);assert(d); + } else { + l = gfxline_reverse(l); + pos.x = end->x; + pos.y = end->y; + char d = dict_del2(ff,&pos,end);assert(d); + } + + assert(l->type == gfx_moveTo); + if(stitch && !first) { + /* cut away the moveTo */ + gfxline_t*next = l->next; + free(l); + l = next; + } + + if(!last) { + result = l; + last = end; + } else { + last->next = l; + last = end; + } + first = 0; + } + dict_destroy(ff); + dict_destroy(rev); + return result; +} + +gfxline_t* gfxline_reverse(gfxline_t*line) +{ + gfxline_t*b = 0; + while(line) { + gfxline_t*next = line->next; + if(next && next->type != gfx_moveTo) { + line->type = next->type; + line->sx = next->sx; + line->sy = next->sy; + } else { + line->type = gfx_moveTo; + } + line->next = b; + b = line; + line = next; + } + return b; +} + +void gfxgradient_destroy(gfxgradient_t*gradient) +{ + while(gradient) { + gfxgradient_t*next = gradient->next; + free(gradient); + gradient = next; + } +} + +gfxparams_t* gfxparams_new() +{ + return (gfxparams_t*)rfx_calloc(sizeof(gfxparams_t)); +} + +void gfxparams_store(gfxparams_t*params, const char*key, const char*value) +{ + gfxparam_t*o = params->params; + while(o) { + if(!strcmp(key, o->key)) { + /* overwrite old value */ + free((void*)o->value); + o->value = strdup(value); + return; + } + o = o->next; + } + gfxparam_t*p = (gfxparam_t*)malloc(sizeof(gfxparam_t)); + p->key = strdup(key); + p->value = strdup(value); + p->next = 0; + + if(params->last) { + params->last->next = p; + params->last = p; + } else { + params->params = p; + params->last = p; + } +} + +void gfxparams_free(gfxparams_t*params) +{ + gfxparam_t*p = params->params; + while(p) { + gfxparam_t*next = p->next; + free((void*)p->key); + if(p->value) free((void*)p->value); + free(p); + p = next; } - jpeg_save(data, img->width, img->height, quality, filename); + free(params); }