X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=lib%2Fdevices%2Fpdf.c;h=9e6365b2d5cd67d89977a8d6111eb46cd0d71b3f;hp=720abd19e165719ea64cdf65af00d725c617cef4;hb=2391d7ae5d8a145a250a8b80ab8c93ba74eba030;hpb=580c48fef10df9184cf2728338e89f7db0fef2f5 diff --git a/lib/devices/pdf.c b/lib/devices/pdf.c index 720abd1..9e6365b 100644 --- a/lib/devices/pdf.c +++ b/lib/devices/pdf.c @@ -22,16 +22,24 @@ #include #include #include +#include #include #include +#include +#include "../os.h" +#include "../q.h" +#include "../jpeg.h" #include "../types.h" #include "../mem.h" #include "../gfxdevice.h" #include "../gfxtools.h" +#include "../gfximage.h" typedef struct _internal { PDF* p; char*tempfile; + double lastx,lasty; + gfxfontlist_t*fontlist; } internal_t; int pdf_setparameter(gfxdevice_t*dev, const char*key, const char*value) @@ -43,21 +51,31 @@ int pdf_setparameter(gfxdevice_t*dev, const char*key, const char*value) void pdf_startpage(gfxdevice_t*dev, int width, int height) { internal_t*i = (internal_t*)dev->internal; - - i->tempfile = strdup("tmp.pdf"); - PDF_open_file(i->p, i->tempfile); - PDF_set_parameter(i->p, "usercoordinates", "true"); - PDF_set_parameter(i->p, "topdown", "true"); + + if(!i->tempfile) { + i->tempfile = strdup(mktempname(0)); + PDF_open_file(i->p, i->tempfile); + PDF_set_parameter(i->p, "usercoordinates", "true"); + PDF_set_parameter(i->p, "topdown", "true"); + } + PDF_begin_page(i->p, width, height); PDF_set_parameter(i->p, "fillrule", "evenodd"); } -static int mkline(gfxline_t*line, PDF*p) +static int mkline(gfxline_t*line, PDF*p, char fill) { + double x,y; + char first = 1; int ret = 0; - double x=0,y=0; + char free_line = 0; + if(fill) { + line = gfxline_restitch(gfxline_clone(line)); + free_line = 1; + } while(line) { - if(line->type == gfx_moveTo) { + 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); @@ -77,6 +95,8 @@ static int mkline(gfxline_t*line, PDF*p) y = line->y; line = line->next; } + if(free_line) + gfxline_free(line); return ret; } @@ -84,11 +104,10 @@ void pdf_startclip(gfxdevice_t*dev, gfxline_t*line) { internal_t*i = (internal_t*)dev->internal; PDF_save(i->p); - PDF_set_parameter(i->p, "fillrule", "evenodd"); - if(mkline(line, i->p)) + if(mkline(line, i->p, 1)) PDF_clip(i->p); else - ; // TODO: not sure about this + ; // TODO: strictly speaking, an empty clip clears everything } void pdf_endclip(gfxdevice_t*dev) @@ -99,13 +118,15 @@ void pdf_endclip(gfxdevice_t*dev) void pdf_stroke(gfxdevice_t*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; + if(width<1e-6) + return; PDF_setlinewidth(i->p, width); PDF_setlinecap(i->p, cap_style==gfx_capButt?0:(cap_style==gfx_capRound?1:2)); PDF_setlinejoin(i->p, joint_style==gfx_joinMiter?0:(joint_style==gfx_joinRound?1:2)); PDF_setrgbcolor_stroke(i->p, color->r/255.0, color->g/255.0, color->b/255.0); if(joint_style==gfx_joinMiter) PDF_setmiterlimit(i->p, miterLimit); - if(mkline(line, i->p)) + if(mkline(line, i->p, 0)) PDF_stroke(i->p); } @@ -113,9 +134,8 @@ 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); - PDF_set_parameter(i->p, "fillrule", "evenodd"); - if(mkline(line, i->p)) { + if(mkline(line, i->p, 1)) { PDF_fill(i->p); } } @@ -124,8 +144,20 @@ void pdf_fillbitmap(gfxdevice_t*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t { internal_t*i = (internal_t*)dev->internal; - //PDFLIB_API int PDFLIB_CALL - //PDF_load_image(i->pPDF *p, const char *imagetype, const char *filename, int len, const char *optlist); + 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; + 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); + 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); } void pdf_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*matrix) @@ -133,30 +165,87 @@ void pdf_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*gradient, g internal_t*i = (internal_t*)dev->internal; } +static char type3 = 1; + void pdf_addfont(gfxdevice_t*dev, gfxfont_t*font) { internal_t*i = (internal_t*)dev->internal; + + if(type3) { + int fontid = 0; + if(!gfxfontlist_hasfont(i->fontlist, font)) { + + static int fontnr = 1; + char fontname[32]; + sprintf(fontname, "font%d", fontnr++); + int l = strlen(fontname); + char fontname2[64]; + int t; + for(t=0;tp, fontname2, l*2, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, ""); + int num = font->num_glyphs<256-32?font->num_glyphs:256-32; + for(t=0;tglyphs[t]; + gfxbbox_t bbox = gfxline_getbbox(g->line); + char name[32]; + sprintf(name, "chr%d", t+32); + PDF_encoding_set_char(i->p, fontname, t+32, name, 0); + PDF_begin_glyph(i->p, name, g->advance, bbox.xmin, bbox.ymin, bbox.xmax, bbox.ymax); + if(mkline(g->line, i->p, 1)) + PDF_fill(i->p); + PDF_end_glyph(i->p); + } + PDF_end_font(i->p); + fontid = PDF_load_font(i->p, fontname2, l*2, fontname, ""); + + i->fontlist = gfxfontlist_addfont2(i->fontlist, font, (void*)(ptroff_t)fontid); + } + } } void pdf_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyphnr, gfxcolor_t*color, gfxmatrix_t*matrix) { internal_t*i = (internal_t*)dev->internal; + if(!font) return; - /* align characters to whole pixels */ - matrix->tx = (int)matrix->tx; - matrix->ty = (int)matrix->ty; gfxglyph_t*glyph = &font->glyphs[glyphnr]; - gfxline_t*line2 = gfxline_clone(glyph->line); - gfxline_transform(line2, matrix); PDF_setrgbcolor_fill(i->p, color->r/255.0, color->g/255.0, color->b/255.0); - PDF_set_parameter(i->p, "fillrule", "evenodd"); - - if(mkline(line2, i->p)) { - PDF_fill(i->p); + char as_shape = 0; + if(!type3) as_shape=1; + 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) < 1e-6) as_shape=1; + + if(as_shape) { + gfxline_t*line2 = gfxline_clone(glyph->line); + gfxline_transform(line2, matrix); + if(mkline(line2, i->p, 1)) { + PDF_fill(i->p); + } + gfxline_free(line2); + } else { + assert(gfxfontlist_hasfont(i->fontlist, font)); + int fontid = (int)(ptroff_t)gfxfontlist_getuserdata(i->fontlist, font->id); + PDF_setfont(i->p, fontid, matrix->m00); + char name[32]; + 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; } - gfxline_free(line2); return; } @@ -169,8 +258,6 @@ void pdf_endpage(gfxdevice_t*dev) { internal_t*i = (internal_t*)dev->internal; PDF_end_page(i->p); - PDF_close(i->p); - PDF_delete(i->p); } typedef struct pdfresult_internal { @@ -212,6 +299,9 @@ void* pdfresult_get(gfxresult_t*gfx, const char*name) gfxresult_t* pdf_finish(gfxdevice_t*dev) { internal_t*i = (internal_t*)dev->internal; + + PDF_close(i->p); + PDF_delete(i->p); gfxresult_t*result = (gfxresult_t*)malloc(sizeof(gfxresult_t)); memset(result, 0, sizeof(gfxresult_t)); @@ -249,6 +339,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(); }