X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fdevices%2Fpdf.c;h=f6df3f52b359cb233cb59117ba3e251142370f02;hb=4c389168a91bf083e434885fbfd8f51c6dab56fc;hp=64c61714c9cdeaa6cb091c2d7b75edf7704c53ea;hpb=10b60d36fcf6cc9532bf397866c5bdc3393246eb;p=swftools.git diff --git a/lib/devices/pdf.c b/lib/devices/pdf.c index 64c6171..f6df3f5 100644 --- a/lib/devices/pdf.c +++ b/lib/devices/pdf.c @@ -31,12 +31,26 @@ #include "../jpeg.h" #include "../types.h" #include "../mem.h" +#include "../log.h" #include "../gfxdevice.h" #include "../gfxtools.h" +#include "../gfximage.h" typedef struct _internal { PDF* p; + + const char*config_pdfx; + char config_addblankpages; + double config_xpad; + double config_ypad; + int config_maxdpi; + + int width,height; + int num_pages; + char*tempfile; + char*page_opts; + double lastx,lasty; gfxfontlist_t*fontlist; } internal_t; @@ -61,94 +75,40 @@ void pdf_startpage(gfxdevice_t*dev, int width, int height) 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) { - 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; - } - - 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); + int ret = 0; + gfxline_t*free_line = 0; + if(fill) { + line = gfxline_restitch(gfxline_clone(line)); + free_line = line; + } + 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(free_line); return ret; } @@ -186,6 +146,12 @@ void pdf_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color) { internal_t*i = (internal_t*)dev->internal; PDF_setrgbcolor_fill(i->p, color->r/255.0, color->g/255.0, color->b/255.0); + if(color->a!=255) { + char opacityfill[80]; + sprintf(opacityfill, "opacityfill %f", color->a/256.0); + int gstate = PDF_create_gstate(i->p, opacityfill); + PDF_set_gstate(i->p, gstate); + } if(mkline(line, i->p, 1)) { PDF_fill(i->p); @@ -196,20 +162,81 @@ void pdf_fillbitmap(gfxdevice_t*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t { internal_t*i = (internal_t*)dev->internal; - double l1 = sqrt(matrix->m00*matrix->m00+matrix->m01*matrix->m01)*img->width; - double l2 = sqrt(matrix->m10*matrix->m10+matrix->m11*matrix->m11)*img->height; + int t,size=img->width*img->height; + int has_alpha=0; + for(t=0;tdata[t].a!=255) { + has_alpha=1; + break; + } + } + + double w = sqrt(matrix->m00*matrix->m00+matrix->m01*matrix->m01); + double h = sqrt(matrix->m10*matrix->m10+matrix->m11*matrix->m11); + double l1 = w*img->width; + double l2 = h*img->height; double r = atan2(matrix->m01, matrix->m00); /* fit_image needs the lower left corner of the image */ double x = matrix->tx + matrix->m10*img->height; double y = matrix->ty + matrix->m11*img->height; - char*tempfile = mktempname(0); + double dpi_x = 72.0 / w; + double dpi_y = 72.0 / h; + double dpi = dpi_x>dpi_y?dpi_x:dpi_y; + gfximage_t*rescaled_image = 0; + if(i->config_maxdpi && dpi > i->config_maxdpi) { + int newwidth = img->width*i->config_maxdpi/dpi; + int newheight = img->height*i->config_maxdpi/dpi; + rescaled_image = gfximage_rescale(img, newwidth, newheight); + msg(" Downscaling %dx%d image (dpi %f, %.0fx%.0f on page) to %dx%d (dpi %d)", + img->width, img->height, dpi, l1, l2, newwidth, newheight, i->config_maxdpi); + img = rescaled_image; + } + + char tempfile[128]; + mktempname(tempfile); + + gfximage_save_jpeg(img, tempfile, 96); + + int imgid=-1; + if(has_alpha) { + char tempfile2[128]; + mktempname(tempfile2); + int t; + int size = img->width*img->height; + unsigned char*alpha = malloc(size); + for(t=0;tdata[t].a; + } + jpeg_save_gray(alpha, img->width, img->height, 97, tempfile2); + free(alpha); + int maskid = PDF_load_image(i->p, "jpeg", tempfile2, 0, "mask"); + unlink(tempfile2); + char masked[80]; + if(maskid<0) { + msg(" Couldn't process mask jpeg of size %dx%d: error code %d", img->width, img->height, maskid); + return; + } + sprintf(masked, "masked %d", maskid); + imgid = PDF_load_image(i->p, "jpeg", tempfile, 0, masked); + } else { + imgid = PDF_load_image(i->p, "jpeg", tempfile, 0, ""); + } + + if(imgid<0) { + msg(" Couldn't process jpeg of size %dx%d: error code %d, file %s", img->width, img->height, imgid, tempfile); + return; + } + unlink(tempfile); + char options[80]; sprintf(options, "boxsize {%f %f} fitmethod meet rotate %f", l1, l2, r*180/M_PI); - gfximage_save_jpeg(img, tempfile, 99); - int imgid = PDF_load_image(i->p, "jpeg", tempfile, 0, ""); PDF_fit_image(i->p, imgid, x, y, options); + PDF_close_image(i->p, imgid); + + if(rescaled_image) + gfximage_free(rescaled_image); } void pdf_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*matrix) @@ -273,7 +300,7 @@ void pdf_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyphnr, gfxcolor_t*color 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); @@ -287,8 +314,16 @@ void pdf_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyphnr, gfxcolor_t*color int fontid = (int)(ptroff_t)gfxfontlist_getuserdata(i->fontlist, font->id); 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); + sprintf(name, "%c", glyphnr+32); + + 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; } @@ -311,6 +346,7 @@ typedef struct pdfresult_internal { void pdfresult_destroy(gfxresult_t*gfx) { pdfresult_internal_t*i = (pdfresult_internal_t*)gfx->internal; + unlink(i->tempfile); free(i->tempfile); free(gfx->internal);gfx->internal = 0; free(gfx); @@ -383,6 +419,8 @@ void gfxdevice_pdf_init(gfxdevice_t*dev) dev->endpage = pdf_endpage; dev->finish = pdf_finish; + i->lastx = -1e38; + i->lasty = -1e38; i->p = PDF_new(); }