typedef struct _internal {
PDF* p;
char*tempfile;
+ double lastx,lasty;
gfxfontlist_t*fontlist;
} internal_t;
PDF_set_parameter(i->p, "fillrule", "evenodd");
}
-static char xy_equals(void*c1, void*c2)
-{
- return !memcmp(c1, c2, sizeof(double)*2);
-}
-static unsigned int xy_hash(void*c)
-{
- return string_hash3(c, sizeof(double)*2);
-}
-static void* xy_clone(void*c)
-{
- void*n = malloc(sizeof(double)*2);
- memcpy(n, c, sizeof(double)*2);
- return n;
-}
-static void xy_destroy(void*c)
-{
- free(c);
-}
-static type_t xy_type = {
- hash: (hash_func)xy_hash,
- equals: (equals_func)xy_equals,
- dup: (dup_func)xy_clone, // all signatures are static
- free: (free_func)xy_destroy,
-};
-
static int mkline(gfxline_t*line, PDF*p, char fill)
{
+ double x,y;
+ char first = 1;
int ret = 0;
-
- dict_t*start = dict_new2(&xy_type);
- gfxline_t*l = line;
- while(l) {
- if(l->type == gfx_moveTo) {
- double xy[2] = {l->x, l->y};
- dict_put(start, xy, l);
- }
- l = l->next;
+ char free_line = 0;
+ if(fill) {
+ line = gfxline_restitch(gfxline_clone(line));
+ free_line = 1;
}
-
- assert(!line || line->type == gfx_moveTo);
-
- double x=0,y=0;
- double pos[2] = {0,0};
- char first = 1;
-
- while(dict_count(start)) {
- gfxline_t*l = dict_lookup(start, pos);
- if(!l) {
- DICT_ITERATE_DATA(start, gfxline_t*, l2) {
- l = l2;
- break;
- }
- assert(l);
- double xy[2] = {l->x,l->y};
- char d = dict_del2(start,xy,l);
- assert(d);
+ while(line) {
+ if(line->type == gfx_moveTo && (x!=line->x || y!=line->y || first)) {
+ first = 0;
+ PDF_moveto(p, line->x, line->y);
+ } else if(line->type == gfx_lineTo) {
+ PDF_lineto(p, line->x, line->y);
+ ret = 1;
} else {
- char d = dict_del2(start,pos,l);
- assert(d);
- }
- while(l) {
- if(l->type == gfx_moveTo && (x!=l->x || y!=l->y || first)) {
- first = 0;
- PDF_moveto(p, l->x, l->y);
- } else if(l->type == gfx_lineTo) {
- PDF_lineto(p, l->x, l->y);
- ret = 1;
- } else {
- /* when converting a quadratic bezier to a cubic bezier, the
- two new control points are both 2/3 the way from the
- endpoints to the old control point */
- double c1x = (x + l->sx*2)/3;
- double c1y = (y + l->sy*2)/3;
- double c2x = (l->x + l->sx*2)/3;
- double c2y = (l->y + l->sy*2)/3;
- PDF_curveto(p, c1x, c1y, c2x, c2y, l->x, l->y);
- ret = 1;
- }
- x = l->x;
- y = l->y;
- pos[0] = x;
- pos[1] = y;
- l = l->next;
- if(l && l->type == gfx_moveTo)
- break;
+ /* when converting a quadratic bezier to a cubic bezier, the
+ two new control points are both 2/3 the way from the
+ endpoints to the old control point */
+ double c1x = (x + line->sx*2)/3;
+ double c1y = (y + line->sy*2)/3;
+ double c2x = (line->x + line->sx*2)/3;
+ double c2y = (line->y + line->sy*2)/3;
+ PDF_curveto(p, c1x, c1y, c2x, c2y, line->x, line->y);
+ ret = 1;
}
+ x = line->x;
+ y = line->y;
+ line = line->next;
}
- dict_destroy(start);
+ if(free_line)
+ gfxline_free(line);
return ret;
}
if(glyphnr>256-32) as_shape=1;
if(fabs(matrix->m00 + matrix->m11) > 0.01) as_shape=1;
if(fabs(fabs(matrix->m01) + fabs(matrix->m10)) > 0.01) as_shape=1;
- if(fabs(matrix->m00) < 0.01) as_shape=1;
+ if(fabs(matrix->m00) < 1e-6) as_shape=1;
if(as_shape) {
gfxline_t*line2 = gfxline_clone(glyph->line);
PDF_setfont(i->p, fontid, matrix->m00);
char name[32];
sprintf(name, "%c\0", glyphnr+32);
- PDF_show_xy2(i->p, name, strlen(name), matrix->tx, matrix->ty);
+
+ if(fabs(matrix->tx - i->lastx) > 0.001 || matrix->ty != i->lasty) {
+ PDF_show_xy2(i->p, name, strlen(name), matrix->tx, matrix->ty);
+ } else {
+ PDF_show2(i->p, name, strlen(name));
+ }
+
+ i->lastx = matrix->tx + glyph->advance*matrix->m00;
+ i->lasty = matrix->ty;
}
return;
}
dev->endpage = pdf_endpage;
dev->finish = pdf_finish;
+ i->lastx = -1e38;
+ i->lasty = -1e38;
i->p = PDF_new();
}
#include "gfxtools.h"
#include "gfxfont.h"
#include "jpeg.h"
+#include "q.h"
typedef struct _linedraw_internal
{
}
}
+static char gfxpoint_equals(void*c1, void*c2)
+{
+ 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) {
+ 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 gfximage_save_jpeg(gfximage_t*img, char*filename, int quality)
{
unsigned char*data = malloc(img->width*img->height*3);