diff options
Diffstat (limited to 'src/drv/cdpdf.c')
-rw-r--r-- | src/drv/cdpdf.c | 1491 |
1 files changed, 1491 insertions, 0 deletions
diff --git a/src/drv/cdpdf.c b/src/drv/cdpdf.c new file mode 100644 index 0000000..24509f6 --- /dev/null +++ b/src/drv/cdpdf.c @@ -0,0 +1,1491 @@ +/** \file + * \brief PDF Driver + * + * See Copyright Notice in cd.h + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <math.h> + +#include "cd.h" +#include "cd_private.h" +#include "cdpdf.h" + +#include "pdflib.h" + + +/* +** dada uma cor do CD, obtem uma de suas componentes, na faixa 0-1. +*/ +#define get_red(_) (((double)cdRed(_))/255.) +#define get_green(_) (((double)cdGreen(_))/255.) +#define get_blue(_) (((double)cdBlue(_))/255.) + +struct _cdCtxCanvas +{ + cdCanvas* canvas; + + PDF *pdf; /* Arquivo PDF */ + int res; /* Resolucao - DPI */ + int pages; /* Numero total de paginas */ + double width_pt; /* Largura do papel (points) */ + double height_pt; /* Altura do papel (points) */ + double width_mm; /* Largura do papel (mm) */ + double height_mm; /* Altura do papel (mm) */ + double scale; /* Fator de conversao de coordenadas (pixel2points) */ + int landscape; /* page orientation */ + float rotate_angle; + int rotate_center_x, + rotate_center_y; + + int font; + int underline; + int strikeover; + + int hatchboxsize; + int pattern; + int opacity; + int opacity_states[256]; + + int poly_holes[500]; + int holes; +}; + + +/* +%F Ajusta o tamanho do papel em points. +*/ +static void setpdfpapersize(cdCtxCanvas* ctxcanvas, int size) +{ + static struct + { + int width; + int height; + } paper[] = + { + { 2393, 3391 }, /* A0 */ + { 1689, 2393 }, /* A1 */ + { 1192, 1689 }, /* A2 */ + { 842, 1192 }, /* A3 */ + { 595, 842 }, /* A4 */ + { 420, 595 }, /* A5 */ + { 612, 792 }, /* LETTER */ + { 612, 1008 } /* LEGAL */ + }; + + if (size<CD_A0 || size>CD_LEGAL) + return; + + ctxcanvas->width_pt = paper[size].width; + ctxcanvas->height_pt = paper[size].height; + ctxcanvas->width_mm = ctxcanvas->width_pt/CD_MM2PT; + ctxcanvas->height_mm = ctxcanvas->height_pt/CD_MM2PT; +} + +/* +%F Registra os valores default para impressao. +*/ +static void setpdfdefaultvalues(cdCtxCanvas* ctxcanvas) +{ + int i; + + /* all the other values are set to 0 */ + setpdfpapersize(ctxcanvas, CD_A4); + ctxcanvas->res = 300; + ctxcanvas->hatchboxsize = 8; + ctxcanvas->opacity = 255; /* full opaque */ + + for (i=0; i<256; i++) + ctxcanvas->opacity_states[i] = -1; +} + +static void update_state(cdCtxCanvas *ctxcanvas) +{ + cdCanvas* canvas = ctxcanvas->canvas; + + if (!canvas->cxFont) /* just check if the first time */ + return; + + /* must set the current transform and line style if different from the default */ + + if (canvas->line_style != CD_CONTINUOUS) + canvas->cxLineStyle(ctxcanvas, canvas->line_style); + if (canvas->line_width != 1) + canvas->cxLineWidth(ctxcanvas, canvas->line_width); + if (canvas->line_cap != CD_CAPFLAT) + canvas->cxLineCap(ctxcanvas, canvas->line_cap); + if (canvas->line_join != CD_MITER) + canvas->cxLineJoin(ctxcanvas, canvas->line_join); + if (canvas->use_matrix) + canvas->cxTransform(ctxcanvas, canvas->matrix); + canvas->cxFont(ctxcanvas, canvas->font_type_face, canvas->font_style, canvas->font_size); +} + +static void begin_page(cdCtxCanvas *ctxcanvas) +{ + PDF_begin_page_ext(ctxcanvas->pdf, ctxcanvas->width_pt, ctxcanvas->height_pt, ""); + + /* default coordinate system is in points, change it to pixels. */ + PDF_scale(ctxcanvas->pdf, ctxcanvas->scale, ctxcanvas->scale); + + PDF_save(ctxcanvas->pdf); /* save the initial configuration, to be used when clipping is reset. */ + + update_state(ctxcanvas); +} + +static void init_pdf(cdCtxCanvas *ctxcanvas) +{ + ctxcanvas->scale = 72.0/ctxcanvas->res; + + /* Converte p/ unidades do usuario */ + ctxcanvas->canvas->w = (int)(ctxcanvas->width_pt/ctxcanvas->scale + 0.5); + ctxcanvas->canvas->h = (int)(ctxcanvas->height_pt/ctxcanvas->scale + 0.5); + + /* Passa o valor em milimetros para o canvas CD */ + ctxcanvas->canvas->w_mm = ctxcanvas->width_mm; + ctxcanvas->canvas->h_mm = ctxcanvas->height_mm; + + ctxcanvas->canvas->bpp = 24; + ctxcanvas->canvas->xres = ctxcanvas->canvas->w / ctxcanvas->canvas->w_mm; + ctxcanvas->canvas->yres = ctxcanvas->canvas->h / ctxcanvas->canvas->h_mm; + + begin_page(ctxcanvas); +} + +static void cdkillcanvas(cdCtxCanvas *ctxcanvas) +{ + PDF_restore(ctxcanvas->pdf); /* restore to match the save of the initial configuration. */ + PDF_end_page_ext(ctxcanvas->pdf, ""); + PDF_end_document(ctxcanvas->pdf, ""); + PDF_delete(ctxcanvas->pdf); + + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + free(ctxcanvas); +} + +static void update_fill(cdCtxCanvas *ctxcanvas, int fill) +{ + if (fill == 0) + { + /* called before a NON filled primitive */ + PDF_setcolor(ctxcanvas->pdf, "stroke", "rgb", get_red(ctxcanvas->canvas->foreground), + get_green(ctxcanvas->canvas->foreground), + get_blue(ctxcanvas->canvas->foreground), 0); + + } + else + { + /* called before a filled primitive */ + if (ctxcanvas->canvas->interior_style == CD_SOLID) + { + PDF_setcolor(ctxcanvas->pdf, "fill", "rgb", get_red(ctxcanvas->canvas->foreground), + get_green(ctxcanvas->canvas->foreground), + get_blue(ctxcanvas->canvas->foreground), 0); + } + else + PDF_setcolor(ctxcanvas->pdf, "fill", "pattern", (float)ctxcanvas->pattern, 0, 0, 0); + } +} + +/* +%F Comeca uma nova pagina. +*/ +static void cdflush(cdCtxCanvas *ctxcanvas) +{ + PDF_restore(ctxcanvas->pdf); /* restore to match the save of the initial configuration */ + + PDF_end_page_ext(ctxcanvas->pdf, ""); + + begin_page(ctxcanvas); +} + + +/******************************************************/ +/* coordinate transformation */ +/******************************************************/ + +static void resetcliprect(cdCtxCanvas* ctxcanvas) +{ + /* clipping is reset, by restoring the initial state */ + /* this will also reset the current transformation and line style */ + PDF_restore(ctxcanvas->pdf); + PDF_save(ctxcanvas->pdf); + + update_state(ctxcanvas); +} + +static void setcliprect(cdCtxCanvas* ctxcanvas, double xmin, double ymin, double xmax, double ymax) +{ + resetcliprect(ctxcanvas); + + PDF_moveto(ctxcanvas->pdf, xmin, ymin); + PDF_lineto(ctxcanvas->pdf, xmax, ymin); + PDF_lineto(ctxcanvas->pdf, xmax, ymax); + PDF_lineto(ctxcanvas->pdf, xmin, ymax); + + PDF_clip(ctxcanvas->pdf); +} + +static void cdfcliparea(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ + if (ctxcanvas->canvas->clip_mode != CD_CLIPAREA) + return; + + setcliprect(ctxcanvas, xmin, ymin, xmax, ymax); +} + +static void cdcliparea(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + cdfcliparea(ctxcanvas, (double)xmin, (double)xmax, (double)ymin, (double)ymax); +} + +static int cdclip(cdCtxCanvas *ctxcanvas, int mode) +{ + if (mode == CD_CLIPAREA) + { + ctxcanvas->canvas->clip_mode = CD_CLIPAREA; + + setcliprect(ctxcanvas, (double)ctxcanvas->canvas->clip_rect.xmin, + (double)ctxcanvas->canvas->clip_rect.ymin, + (double)ctxcanvas->canvas->clip_rect.xmax, + (double)ctxcanvas->canvas->clip_rect.ymax); + } + else if (mode == CD_CLIPPOLYGON) + { + int hole_index = 0; + int i; + + resetcliprect(ctxcanvas); + + if (ctxcanvas->canvas->clip_poly) + { + cdPoint *poly = ctxcanvas->canvas->clip_poly; + + PDF_moveto(ctxcanvas->pdf, poly[0].x, poly[0].y); + + for (i=1; i<ctxcanvas->canvas->clip_poly_n; i++) + { + if (ctxcanvas->holes && i == ctxcanvas->poly_holes[hole_index]) + { + PDF_moveto(ctxcanvas->pdf, poly[i].x, poly[i].y); + hole_index++; + } + else + PDF_lineto(ctxcanvas->pdf, poly[i].x, poly[i].y); + } + } + else if (ctxcanvas->canvas->clip_fpoly) + { + cdfPoint *poly = ctxcanvas->canvas->clip_fpoly; + + PDF_moveto(ctxcanvas->pdf, poly[0].x, poly[0].y); + + for (i=1; i<ctxcanvas->canvas->clip_poly_n; i++) + { + if (ctxcanvas->holes && i == ctxcanvas->poly_holes[hole_index]) + { + PDF_moveto(ctxcanvas->pdf, poly[i].x, poly[i].y); + hole_index++; + } + else + PDF_lineto(ctxcanvas->pdf, poly[i].x, poly[i].y); + } + } + + PDF_clip(ctxcanvas->pdf); + } + else if (mode == CD_CLIPOFF) + { + resetcliprect(ctxcanvas); + } + + return mode; +} + +/******************************************************/ +/* primitives */ +/******************************************************/ + +static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2) +{ + update_fill(ctxcanvas, 0); + + PDF_moveto(ctxcanvas->pdf, x1, y1); + PDF_lineto(ctxcanvas->pdf, x2, y2); + PDF_stroke(ctxcanvas->pdf); +} + +static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2) +{ + cdfline(ctxcanvas, (double)x1, (double)y1, (double)x2, (double)y2); +} + +static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ + update_fill(ctxcanvas, 0); + + PDF_rect(ctxcanvas->pdf, xmin, ymin, xmax-xmin, ymax-ymin); + PDF_stroke(ctxcanvas->pdf); +} + +static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + cdfrect(ctxcanvas, (double)xmin, (double)xmax, (double)ymin, (double)ymax); +} + +static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ + update_fill(ctxcanvas, 1); + + PDF_moveto(ctxcanvas->pdf, xmin, ymin); + PDF_lineto(ctxcanvas->pdf, xmax, ymin); + PDF_lineto(ctxcanvas->pdf, xmax, ymax); + PDF_lineto(ctxcanvas->pdf, xmin, ymax); + PDF_fill(ctxcanvas->pdf); +} + +static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + cdfbox(ctxcanvas, (double)xmin, (double)xmax, (double)ymin, (double)ymax); +} + +static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ + update_fill(ctxcanvas, 0); + + if (w==h) + { + PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2); + PDF_stroke(ctxcanvas->pdf); + } + else /* Elipse: mudar a escala p/ criar a partir do circulo */ + { + PDF_save(ctxcanvas->pdf); /* save to use the local transform */ + + PDF_translate(ctxcanvas->pdf, xc, yc); + PDF_scale(ctxcanvas->pdf, w/h, 1); + PDF_translate(ctxcanvas->pdf, -xc, -yc); + + PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*h, a1, a2); + PDF_stroke(ctxcanvas->pdf); + + PDF_restore(ctxcanvas->pdf); /* restore from local */ + } +} + +static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + cdfarc(ctxcanvas, (double)xc, (double)yc, (double)w, (double)h, a1, a2); +} + +static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ + update_fill(ctxcanvas, 1); + + if (w==h) + { + PDF_moveto(ctxcanvas->pdf, xc, yc); + PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2); + PDF_fill(ctxcanvas->pdf); + } + else /* Elipse: mudar a escala p/ criar a partir do circulo */ + { + PDF_save(ctxcanvas->pdf); /* save to use the local transform */ + + PDF_translate(ctxcanvas->pdf, xc, yc); + PDF_scale(ctxcanvas->pdf, w/h, 1); + PDF_translate(ctxcanvas->pdf, -xc, -yc); + + PDF_moveto(ctxcanvas->pdf, xc, yc); + PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*h, a1, a2); + + if (ctxcanvas->canvas->interior_style == CD_SOLID || + ctxcanvas->canvas->interior_style == CD_PATTERN) + PDF_fill(ctxcanvas->pdf); + else + { + PDF_lineto(ctxcanvas->pdf, xc, yc); + PDF_stroke(ctxcanvas->pdf); + } + + PDF_restore(ctxcanvas->pdf); /* restore from local */ + } +} + +static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + cdfsector(ctxcanvas, (double)xc, (double)yc, (double)w, (double)h, a1, a2); +} + +static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ + update_fill(ctxcanvas, 1); + + if (w==h) + { + PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2); + PDF_fill_stroke(ctxcanvas->pdf); + } + else /* Elipse: mudar a escala p/ criar a partir do circulo */ + { + PDF_save(ctxcanvas->pdf); /* save to use the local transform */ + + /* local transform */ + PDF_translate(ctxcanvas->pdf, xc, yc); + PDF_scale(ctxcanvas->pdf, 1, w/h); + + PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2); + PDF_fill_stroke(ctxcanvas->pdf); + + PDF_restore(ctxcanvas->pdf); /* restore from local */ + } +} + +static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + cdfchord(ctxcanvas, (double)xc, (double)yc, (double)w, (double)h, a1, a2); +} + +static void cdgetfontdim(cdCtxCanvas *ctxcanvas, int *max_width, int *height, int *ascent, int *descent) +{ + double fontsize, a, d, linegap; + + if (ctxcanvas->font<0) + return; + + fontsize = PDF_get_value(ctxcanvas->pdf, "fontsize", 0); + a = PDF_get_value(ctxcanvas->pdf, "ascender", 0); + d = PDF_get_value(ctxcanvas->pdf, "descender", 0); + + /* linegap = PDF_info_font(ctxcanvas->pdf, 1, "linegap", ""); - not supported call */ + linegap = 0.23 * a; /* use default value for linegap */ + a += linegap; + d += linegap; /* since d<0, it is a subtraction */ + + a *= fontsize; + d *= fontsize; + + if (ascent) *ascent = (int)a; + if (descent) *descent = (int)(-d); + if (height) *height = (int)(a - d); + if (max_width) *max_width = (int)(PDF_info_textline(ctxcanvas->pdf, "W", 0, "width", "")/ctxcanvas->scale); +} + +static void cdgettextsize(cdCtxCanvas *ctxcanvas, const char *s, int *width, int *height) +{ + if (ctxcanvas->font<0) + return; + if (height) cdgetfontdim(ctxcanvas, NULL, height, NULL, NULL); + if (width) *width = (int)(PDF_info_textline(ctxcanvas->pdf, s, 0, "width", "")/ctxcanvas->scale); +} + +static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *s) +{ + char temp[200], options[200]; + + PDF_setcolor(ctxcanvas->pdf, "fill", "rgb", get_red(ctxcanvas->canvas->foreground), + get_green(ctxcanvas->canvas->foreground), + get_blue(ctxcanvas->canvas->foreground), 0); + + strcpy(options, ""); + + sprintf(temp, "rotate=%g ", ctxcanvas->canvas->text_orientation); + strcat(options, temp); + + if (ctxcanvas->underline != 0) + strcat(options, "underline=true "); + else + strcat(options, "underline=false "); + + if (ctxcanvas->strikeover != 0) + strcat(options, "strikeout=true "); + else + strcat(options, "strikeout=false "); + + switch (ctxcanvas->canvas->text_alignment) + { + case CD_NORTH: + sprintf(temp, "position={50 100} matchbox { boxheight={ascender descender} }"); + strcat(options, temp); + break; + case CD_NORTH_EAST: + sprintf(temp, "position={100 100} matchbox { boxheight={ascender descender} }"); + strcat(options, temp); + break; + case CD_NORTH_WEST: + sprintf(temp, "position={0 100} matchbox { boxheight={ascender descender} }"); + strcat(options, temp); + break; + case CD_EAST: + sprintf(temp, "position={100 50} matchbox { boxheight={ascender descender} }"); + strcat(options, temp); + break; + case CD_WEST: + sprintf(temp, "position={0 50} matchbox { boxheight={ascender descender} }"); + strcat(options, temp); + break; + case CD_CENTER: + sprintf(temp, "position={50 50} matchbox { boxheight={ascender descender} }"); + strcat(options, temp); + break; + case CD_SOUTH_EAST: + sprintf(temp, "position={100 0} matchbox { boxheight={ascender descender} }"); + strcat(options, temp); + break; + case CD_SOUTH: + sprintf(temp, "position={50 0} matchbox { boxheight={ascender descender} }"); + strcat(options, temp); + break; + case CD_SOUTH_WEST: + sprintf(temp, "position={0 0} matchbox { boxheight={ascender descender} }"); + strcat(options, temp); + break; + case CD_BASE_RIGHT: + sprintf(temp, "position={100 0} matchbox { boxheight={ascender none} }"); + strcat(options, temp); + break; + case CD_BASE_CENTER: + sprintf(temp, "position={50 0} matchbox { boxheight={ascender none} }"); + strcat(options, temp); + break; + case CD_BASE_LEFT: + sprintf(temp, "position={0 0} matchbox { boxheight={ascender none} }"); + strcat(options, temp); + break; + } + + PDF_fit_textline(ctxcanvas->pdf, s, 0, x, y, options); +} + +static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *s) +{ + cdftext(ctxcanvas, (double)x, (double)y, s); +} + +static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n) +{ + int i; + + if (mode == CD_CLIP) + return; + + if (mode == CD_FILL) + update_fill(ctxcanvas, 1); + else + update_fill(ctxcanvas, 0); + + if (mode==CD_FILL) + { + if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD) + PDF_set_parameter(ctxcanvas->pdf, "fillrule", "evenodd"); + else + PDF_set_parameter(ctxcanvas->pdf, "fillrule", "winding"); + } + + PDF_moveto(ctxcanvas->pdf, poly[0].x, poly[0].y); + + if (mode == CD_BEZIER) + { + for (i=1; i<n; i+=3) + PDF_curveto(ctxcanvas->pdf, poly[i].x, poly[i].y, + poly[i+1].x, poly[i+1].y, + poly[i+2].x, poly[i+2].y); + } + else + { + int hole_index = 0; + + for (i=1; i<n; i++) + { + if (ctxcanvas->holes && i == ctxcanvas->poly_holes[hole_index]) + { + PDF_moveto(ctxcanvas->pdf, poly[i].x, poly[i].y); + hole_index++; + } + else + PDF_lineto(ctxcanvas->pdf, poly[i].x, poly[i].y); + } + } + + switch (mode) + { + case CD_CLOSED_LINES : + PDF_closepath_stroke(ctxcanvas->pdf); + break; + case CD_OPEN_LINES : + PDF_stroke(ctxcanvas->pdf); + break; + case CD_BEZIER : + PDF_stroke(ctxcanvas->pdf); + break; + case CD_FILL : + PDF_fill(ctxcanvas->pdf); + break; + } +} + +static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n) +{ + int i; + + if (mode == CD_CLIP) + return; + + if (mode == CD_FILL) + update_fill(ctxcanvas, 1); + else + update_fill(ctxcanvas, 0); + + if (mode==CD_FILL) + { + if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD) + PDF_set_parameter(ctxcanvas->pdf, "fillrule", "evenodd"); + else + PDF_set_parameter(ctxcanvas->pdf, "fillrule", "winding"); + } + + PDF_moveto(ctxcanvas->pdf, poly[0].x, poly[0].y); + + if (mode == CD_BEZIER) + { + for (i=1; i<n; i+=3) + PDF_curveto(ctxcanvas->pdf, poly[i].x, poly[i].y, + poly[i+1].x, poly[i+1].y, + poly[i+2].x, poly[i+2].y); + } + else + { + int hole_index = 0; + + for (i=1; i<n; i++) + { + if (ctxcanvas->holes && i == ctxcanvas->poly_holes[hole_index]) + { + PDF_moveto(ctxcanvas->pdf, poly[i].x, poly[i].y); + hole_index++; + } + else + PDF_lineto(ctxcanvas->pdf, poly[i].x, poly[i].y); + } + } + + switch (mode) + { + case CD_CLOSED_LINES : + PDF_closepath_stroke(ctxcanvas->pdf); + break; + case CD_OPEN_LINES : + PDF_stroke(ctxcanvas->pdf); + break; + case CD_BEZIER : + PDF_stroke(ctxcanvas->pdf); + break; + case CD_FILL : + PDF_fill(ctxcanvas->pdf); + break; + } +} + +/******************************************************/ +/* attributes */ +/******************************************************/ + +static int cdlinestyle(cdCtxCanvas *ctxcanvas, int style) +{ + double mm = (72.0/25.4) / ctxcanvas->scale; + char options[80]; + + switch (style) + { + case CD_CONTINUOUS : /* empty dash */ + PDF_setdash(ctxcanvas->pdf, 0, 0); + break; + case CD_DASHED : + PDF_setdash(ctxcanvas->pdf, 3*mm, mm); + break; + case CD_DOTTED : + PDF_setdash(ctxcanvas->pdf, mm, mm); + break; + case CD_DASH_DOT : + sprintf(options, "dasharray={%g %g %g %g}", 3*mm, mm, mm, mm); + PDF_setdashpattern(ctxcanvas->pdf, options); + break; + case CD_DASH_DOT_DOT : + sprintf(options, "dasharray={%g %g %g %g %g %g}", 3*mm, mm, mm, mm, mm, mm); + PDF_setdashpattern(ctxcanvas->pdf, options); + break; + case CD_CUSTOM : + { + int i; + + strcpy(options, "dasharray={"); + for (i = 0; i < ctxcanvas->canvas->line_dashes_count; i++) + { + char tmp[80]; + sprintf(tmp, "%g ", ctxcanvas->canvas->line_dashes[i]*mm); + strcat(options, tmp); + } + strcat(options, "}"); + PDF_setdashpattern(ctxcanvas->pdf, options); + } + break; + } + + return style; +} + +static int cdlinewidth(cdCtxCanvas *ctxcanvas, int width) +{ + if (width==0) width = 1; + + PDF_setlinewidth(ctxcanvas->pdf, width); + + return width; +} + +static int cdlinejoin(cdCtxCanvas *ctxcanvas, int join) +{ + int cd2ps_join[] = {0, 2, 1}; + PDF_setlinejoin(ctxcanvas->pdf, cd2ps_join[join]); + return join; +} + +static int cdlinecap(cdCtxCanvas *ctxcanvas, int cap) +{ + int cd2pdf_cap[] = {0, 2, 1}; + PDF_setlinecap(ctxcanvas->pdf, cd2pdf_cap[cap]); + return cap; +} + +static void make_pattern(cdCtxCanvas *ctxcanvas, int n, int m, void* data, int (*data2rgb)(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b)) +{ + int i, j; + unsigned char r, g, b; + + PDF_suspend_page(ctxcanvas->pdf, ""); + ctxcanvas->pattern = PDF_begin_pattern(ctxcanvas->pdf, n, m, + ((double)n)*ctxcanvas->scale, ((double)m)*ctxcanvas->scale, 1); + + PDF_scale(ctxcanvas->pdf, ctxcanvas->scale, ctxcanvas->scale); + + for (j=0; j<m; j++) + { + for (i=0; i<n; i++) + { + int ret = data2rgb(ctxcanvas, n, i, j, data, &r, &g, &b); + if (ret==-1) continue; + PDF_setcolor(ctxcanvas->pdf, "fill", "rgb", ((double)r)/255, ((double)g)/255, ((double)b)/255, 0); + PDF_rect(ctxcanvas->pdf, i, j, 1, 1); + PDF_fill(ctxcanvas->pdf); + } + } + + PDF_end_pattern(ctxcanvas->pdf); + PDF_resume_page(ctxcanvas->pdf, ""); +} + +static int long2rgb(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b) +{ + long* long_data = (long*)data; + (void)ctxcanvas; + cdDecodeColor(long_data[j*n+i], r, g, b); + return 1; +} + +static void cdpattern(cdCtxCanvas *ctxcanvas, int n, int m, const long int *pattern) +{ + make_pattern(ctxcanvas, n, m, (void*)pattern, long2rgb); +} + +static int uchar2rgb(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b) +{ + int ret = 1; + unsigned char* uchar_data = (unsigned char*)data; + if (uchar_data[j*n+i]) + { + cdDecodeColor(ctxcanvas->canvas->foreground, r, g, b); + ret = 1; + } + else + { + cdDecodeColor(ctxcanvas->canvas->background, r, g, b); + if (ctxcanvas->canvas->back_opacity==CD_TRANSPARENT) + ret = -1; + } + + return ret; +} + +static void cdstipple(cdCtxCanvas *ctxcanvas, int n, int m, const unsigned char *stipple) +{ + make_pattern(ctxcanvas, n, m, (void*)stipple, uchar2rgb); +} + +static void make_hatch(cdCtxCanvas *ctxcanvas, int style) +{ + unsigned char r, g, b; + int hsize = ctxcanvas->hatchboxsize - 1; + int hhalf = hsize / 2; + + PDF_suspend_page(ctxcanvas->pdf, ""); + ctxcanvas->pattern = PDF_begin_pattern(ctxcanvas->pdf, hsize + 1, hsize + 1, + ((double)hsize)*ctxcanvas->scale, ((double)hsize)*ctxcanvas->scale, 1); + + PDF_scale(ctxcanvas->pdf, ctxcanvas->scale, ctxcanvas->scale); + + if (ctxcanvas->canvas->back_opacity==CD_OPAQUE) + { + cdDecodeColor(ctxcanvas->canvas->background, &r, &g, &b); + PDF_setcolor(ctxcanvas->pdf, "fill", "rgb", ((double)r)/255, ((double)g)/255, ((double)b)/255, 0); + PDF_rect(ctxcanvas->pdf, 0, 0, hsize, hsize); + PDF_fill(ctxcanvas->pdf); + } + + cdDecodeColor(ctxcanvas->canvas->foreground, &r, &g, &b); + PDF_setcolor(ctxcanvas->pdf, "stroke", "rgb", ((double)r)/255, ((double)g)/255, ((double)b)/255, 0); + + switch(style) + { + case CD_HORIZONTAL: + PDF_moveto(ctxcanvas->pdf, 0, hhalf); + PDF_lineto(ctxcanvas->pdf, hsize, hhalf); + break; + case CD_VERTICAL: + PDF_moveto(ctxcanvas->pdf, hhalf, 0); + PDF_lineto(ctxcanvas->pdf, hhalf, hsize); + break; + case CD_BDIAGONAL: + PDF_moveto(ctxcanvas->pdf, 0, hsize); + PDF_lineto(ctxcanvas->pdf, hsize, 0); + break; + case CD_FDIAGONAL: + PDF_moveto(ctxcanvas->pdf, 0, 0); + PDF_lineto(ctxcanvas->pdf, hsize, hsize); + break; + case CD_CROSS: + PDF_moveto(ctxcanvas->pdf, hsize, 0); + PDF_lineto(ctxcanvas->pdf, hsize, hsize); + PDF_moveto(ctxcanvas->pdf, 0, hhalf); + PDF_lineto(ctxcanvas->pdf, hsize, hhalf); + break; + case CD_DIAGCROSS: + PDF_moveto(ctxcanvas->pdf, 0, 0); + PDF_lineto(ctxcanvas->pdf, hsize, hsize); + PDF_moveto(ctxcanvas->pdf, hsize, 0); + PDF_lineto(ctxcanvas->pdf, 0, hsize); + break; + } + + PDF_stroke(ctxcanvas->pdf); + + PDF_end_pattern(ctxcanvas->pdf); + PDF_resume_page(ctxcanvas->pdf, ""); +} + +static int cdhatch(cdCtxCanvas *ctxcanvas, int style) +{ + make_hatch(ctxcanvas, style); + return style; +} + +static int cdfont(cdCtxCanvas *ctxcanvas, const char *type_face, int style, int size) +{ + int newfont, sizepixel; + char nativefontname[1024]; + const char* options = ""; + + if (cdStrEqualNoCase(type_face, "System")) + type_face = "Courier"; + + strcpy(nativefontname, type_face); + + if (cdStrEqualNoCase(type_face, "Courier") || + cdStrEqualNoCase(type_face, "Helvetica")) + { + if (style&CD_BOLD && style&CD_ITALIC) + strcat(nativefontname, "-BoldOblique"); + else + { + if (style&CD_BOLD) + strcat(nativefontname, "-Bold"); + + if (style&CD_ITALIC) + strcat(nativefontname, "-Oblique"); + } + } + else if (cdStrEqualNoCase(type_face, "Times")) + { + if ((style&3) == CD_PLAIN) + strcat(nativefontname, "-Roman"); + if (style&CD_BOLD && style&CD_ITALIC) + strcat(nativefontname, "-BoldItalic"); + else + { + if (style&CD_BOLD) + strcat(nativefontname, "-Bold"); + + if (style&CD_ITALIC) + strcat(nativefontname, "-Italic"); + } + } + else + { + switch(style&3) + { + case CD_PLAIN: + options = "fontstyle=normal"; + break; + case CD_BOLD: + options = "fontstyle=bold"; + break; + case CD_ITALIC: + options = "fontstyle=italic"; + break; + case CD_BOLD_ITALIC: + options = "fontstyle=bolditalic"; + break; + } + } + + newfont = PDF_load_font(ctxcanvas->pdf, nativefontname, 0, "auto", options); + if (newfont<0) + { + /* must reload the previous one */ + return 0; + } + ctxcanvas->font = newfont; + + sizepixel = cdGetFontSizePixels(ctxcanvas->canvas, size); + PDF_setfont(ctxcanvas->pdf, ctxcanvas->font, sizepixel); + + if (style&CD_UNDERLINE) + ctxcanvas->underline = 1; + else + ctxcanvas->underline = 0; + + if (style&CD_STRIKEOUT) + ctxcanvas->strikeover = 1; + else + ctxcanvas->strikeover = 0; + + return 1; +} + +static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix) +{ + PDF_setmatrix(ctxcanvas->pdf, 1, 0, 0, 1, 0, 0); + + /* default coordinate system is in points, change it to pixels. */ + PDF_scale(ctxcanvas->pdf, ctxcanvas->scale, ctxcanvas->scale); + + if (matrix) + { + PDF_concat(ctxcanvas->pdf, matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]); + } + else if (ctxcanvas->rotate_angle) + { + /* rotation = translate to point + rotation + translate back */ + PDF_translate(ctxcanvas->pdf, ctxcanvas->rotate_center_x, ctxcanvas->rotate_center_y); + PDF_rotate(ctxcanvas->pdf, (double)ctxcanvas->rotate_angle); + PDF_translate(ctxcanvas->pdf, -ctxcanvas->rotate_center_x, -ctxcanvas->rotate_center_y); + } +} + +/******************************************************/ +/* client images */ +/******************************************************/ + +static void cdputimagerectrgb(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + int i, j, d, image, rw, rh, rgb_size; + char options[80]; + unsigned char* rgb_data; + + if (xmin<0 || ymin<0 || xmax-xmin+1>iw || ymax-ymin+1>ih) return; + + rw = xmax-xmin+1; + rh = ymax-ymin+1; + + rgb_size = 3*rw*rh; + rgb_data = (unsigned char*)malloc(rgb_size); + if (!rgb_data) return; + + d = 0; + for (i=ymax; i>=ymin; i--) + for (j=xmin; j<=xmax; j++) + { + rgb_data[d] = r[i*iw+j]; d++; + rgb_data[d] = g[i*iw+j]; d++; + rgb_data[d] = b[i*iw+j]; d++; + } + + PDF_create_pvf(ctxcanvas->pdf, "cd_raw_rgb", 0, rgb_data, rgb_size, ""); + + sprintf(options, "width=%d height=%d components=3 bpc=8", rw, rh); + image = PDF_load_image(ctxcanvas->pdf, "raw", "cd_raw_rgb", 0, options); + + sprintf(options, "boxsize={%d %d} fitmethod=meet", w, h); + PDF_fit_image(ctxcanvas->pdf, image, x, y, options); + + PDF_delete_pvf(ctxcanvas->pdf, "cd_raw_rgb", 0); + free(rgb_data); +} + +static void cdputimagerectrgba(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + int i, j, d, image, image_mask, rw, rh, alpha_size, rgb_size; + char options[80]; + unsigned char *rgb_data, *alpha_data; + + if (xmin<0 || ymin<0 || xmax-xmin+1>iw || ymax-ymin+1>ih) return; + + rw = xmax-xmin+1; + rh = ymax-ymin+1; + + rgb_size = 3*rw*rh; + rgb_data = (unsigned char*)malloc(rgb_size); + if (!rgb_data) return; + + d = 0; + for (i=ymax; i>=ymin; i--) + for (j=xmin; j<=xmax; j++) + { + rgb_data[d] = r[i*iw+j]; d++; + rgb_data[d] = g[i*iw+j]; d++; + rgb_data[d] = b[i*iw+j]; d++; + } + + alpha_size = rw*rh; + alpha_data = (unsigned char*)malloc(alpha_size); + if (!alpha_data) return; + + d = 0; + for (i=ymax; i>=ymin; i--) + for (j=xmin; j<=xmax; j++) + { + alpha_data[d] = a[i*iw+j]; d++; + } + + PDF_create_pvf(ctxcanvas->pdf, "cd_raw_rgb", 0, rgb_data, rgb_size, ""); + PDF_create_pvf(ctxcanvas->pdf, "cd_raw_alpha", 0, alpha_data, alpha_size, ""); + + sprintf(options, "width=%d height=%d components=1 bpc=8 imagewarning=true", rw, rh); + image_mask = PDF_load_image(ctxcanvas->pdf, "raw", "cd_raw_alpha", 0, options); + + sprintf(options, "width=%d height=%d components=3 bpc=8 masked=%d", rw, rh, image_mask); + image = PDF_load_image(ctxcanvas->pdf, "raw", "cd_raw_rgb", 0, options); + + sprintf(options, "boxsize={%d %d} fitmethod=meet", w, h); + PDF_fit_image(ctxcanvas->pdf, image, x, y, options); + + PDF_delete_pvf(ctxcanvas->pdf, "cd_raw_alpha", 0); + free(alpha_data); + PDF_delete_pvf(ctxcanvas->pdf, "cd_raw_rgb", 0); + free(rgb_data); +} + +static void cdputimagerectmap(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *index, const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + int i, j, d, rw, rh, image, rgb_size; + char options[80]; + unsigned char* rgb_data; + + if (xmin<0 || ymin<0 || xmax-xmin+1>iw || ymax-ymin+1>ih) return; + + rw = xmax-xmin+1; + rh = ymax-ymin+1; + + rgb_size = 3*rw*rh; + rgb_data = (unsigned char*)malloc(rgb_size); + if (!rgb_data) return; + + d = 0; + for (i=ymax; i>=ymin; i--) + for (j=xmin; j<=xmax; j++) + { + unsigned char r, g, b; + cdDecodeColor(colors[index[i*iw+j]], &r, &g, &b); + rgb_data[d] = r; d++; + rgb_data[d] = g; d++; + rgb_data[d] = b; d++; + } + + PDF_create_pvf(ctxcanvas->pdf, "cd_raw_rgb", 0, rgb_data, rgb_size, ""); + + sprintf(options, "width=%d height=%d components=3 bpc=8", rw, rh); + image = PDF_load_image(ctxcanvas->pdf, "raw", "cd_raw_rgb", 0, options); + + sprintf(options, "boxsize={%d %d} fitmethod=meet", w, h); + PDF_fit_image(ctxcanvas->pdf, image, x, y, options); + + PDF_delete_pvf(ctxcanvas->pdf, "cd_raw_rgb", 0); + free(rgb_data); +} + +/******************************************************/ +/* server images */ +/******************************************************/ + +static void cdpixel(cdCtxCanvas *ctxcanvas, int x, int y, long int color) +{ + PDF_setcolor(ctxcanvas->pdf, "fill", "rgb", get_red(color), get_green(color), get_blue(color), 0); + + PDF_moveto(ctxcanvas->pdf, x, y); + PDF_circle(ctxcanvas->pdf, x, y, .5); + + PDF_fill(ctxcanvas->pdf); +} + +/******************************************************/ +/* custom attributes */ +/******************************************************/ + +static void set_poly_attrib(cdCtxCanvas *ctxcanvas, char* data) +{ + int hole; + + if (data == NULL) + { + ctxcanvas->holes = 0; + return; + } + + sscanf(data, "%d", &hole); + ctxcanvas->poly_holes[ctxcanvas->holes] = hole; + ctxcanvas->holes++; +} + +static char* get_poly_attrib(cdCtxCanvas *ctxcanvas) +{ + static char holes[10]; + sprintf(holes, "%d", ctxcanvas->holes); + return holes; +} + +static cdAttribute poly_attrib = +{ + "POLYHOLE", + set_poly_attrib, + get_poly_attrib +}; + +static void set_hatchboxsize_attrib(cdCtxCanvas *ctxcanvas, char* data) +{ + int hatchboxsize; + + if (data == NULL) + { + ctxcanvas->hatchboxsize = 8; + return; + } + + sscanf(data, "%d", &hatchboxsize); + ctxcanvas->hatchboxsize = hatchboxsize; +} + +static char* get_hatchboxsize_attrib(cdCtxCanvas *ctxcanvas) +{ + static char size[10]; + sprintf(size, "%d", ctxcanvas->hatchboxsize); + return size; +} + +static cdAttribute hatchboxsize_attrib = +{ + "HATCHBOXSIZE", + set_hatchboxsize_attrib, + get_hatchboxsize_attrib +}; + +static void set_rotate_attrib(cdCtxCanvas *ctxcanvas, char* data) +{ + /* ignore ROTATE if transform is set */ + if (ctxcanvas->canvas->use_matrix) + return; + + if (data) + { + sscanf(data, "%g %d %d", &ctxcanvas->rotate_angle, + &ctxcanvas->rotate_center_x, + &ctxcanvas->rotate_center_y); + } + else + { + ctxcanvas->rotate_angle = 0; + ctxcanvas->rotate_center_x = 0; + ctxcanvas->rotate_center_y = 0; + } + + PDF_setmatrix(ctxcanvas->pdf, 1, 0, 0, 1, 0, 0); + + if (ctxcanvas->rotate_angle) + { + /* rotation = translate to point + rotation + translate back */ + PDF_translate(ctxcanvas->pdf, ctxcanvas->rotate_center_x, ctxcanvas->rotate_center_y); + PDF_rotate(ctxcanvas->pdf, (double)ctxcanvas->rotate_angle); + PDF_translate(ctxcanvas->pdf, -ctxcanvas->rotate_center_x, -ctxcanvas->rotate_center_y); + } +} + +static char* get_rotate_attrib(cdCtxCanvas *ctxcanvas) +{ + static char data[100]; + + if (!ctxcanvas->rotate_angle) + return NULL; + + sprintf(data, "%g %d %d", (double)ctxcanvas->rotate_angle, + ctxcanvas->rotate_center_x, + ctxcanvas->rotate_center_y); + + return data; +} + +static cdAttribute rotate_attrib = +{ + "ROTATE", + set_rotate_attrib, + get_rotate_attrib +}; + +static void set_pattern_attrib(cdCtxCanvas *ctxcanvas, char* data) +{ + if (data) + { + int n, m; + sscanf(data, "%dx%d", &n, &m); + + PDF_suspend_page(ctxcanvas->pdf, ""); + ctxcanvas->pattern = PDF_begin_pattern(ctxcanvas->pdf, n, m, + ((double)n)*ctxcanvas->scale, ((double)m)*ctxcanvas->scale, 1); + PDF_scale(ctxcanvas->pdf, ctxcanvas->scale, ctxcanvas->scale); + } + else + { + PDF_end_pattern(ctxcanvas->pdf); + PDF_resume_page(ctxcanvas->pdf, ""); + ctxcanvas->canvas->interior_style = CD_PATTERN; + } +} + +static cdAttribute pattern_attrib = +{ + "PATTERN", + set_pattern_attrib, + NULL +}; + +static void set_opacity_attrib(cdCtxCanvas *ctxcanvas, char* data) +{ + int state; + + if (data) + { + sscanf(data, "%d", &ctxcanvas->opacity); + if (ctxcanvas->opacity < 0) ctxcanvas->opacity = 0; + if (ctxcanvas->opacity > 255) ctxcanvas->opacity = 255; + } + else + ctxcanvas->opacity = 255; + + /* reuse the extended graphics state if the opacity is the same */ + if (ctxcanvas->opacity_states[ctxcanvas->opacity] == -1) + { + char options[50]; + sprintf(options, "opacityfill=%g opacitystroke=%g", ctxcanvas->opacity/255.0, ctxcanvas->opacity/255.0); + state = PDF_create_gstate(ctxcanvas->pdf, options); + ctxcanvas->opacity_states[ctxcanvas->opacity] = state; + } + else + state = ctxcanvas->opacity_states[ctxcanvas->opacity]; + + PDF_set_gstate(ctxcanvas->pdf, state); +} + +static char* get_opacity_attrib(cdCtxCanvas *ctxcanvas) +{ + static char data[50]; + sprintf(data, "%d", ctxcanvas->opacity); + return data; +} + +static cdAttribute opacity_attrib = +{ + "OPACITY", + set_opacity_attrib, + get_opacity_attrib +}; + +static char* get_pdf_attrib(cdCtxCanvas *ctxcanvas) +{ + return (char*)ctxcanvas->pdf; +} + +static cdAttribute pdf_attrib = +{ + "PDF", + NULL, + get_pdf_attrib +}; + +static void cdcreatecanvas(cdCanvas* canvas, void *data) +{ + char *line = (char *)data; + cdCtxCanvas *ctxcanvas; + char filename[10240] = ""; + + ctxcanvas = (cdCtxCanvas *)malloc(sizeof(cdCtxCanvas)); + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + + line += cdGetFileName(line, filename); + if (filename[0] == 0) + return; + + ctxcanvas->pdf = PDF_new(); + if (!ctxcanvas->pdf) + { + free(ctxcanvas); + return; + } + + if (PDF_begin_document(ctxcanvas->pdf, filename, 0, "") == -1) + { + PDF_delete(ctxcanvas->pdf); + free(ctxcanvas); + return; + } + + PDF_set_parameter(ctxcanvas->pdf, "fontwarning", "false"); + PDF_set_parameter(ctxcanvas->pdf, "errorpolicy", "return"); + + cdRegisterAttribute(canvas, &poly_attrib); + cdRegisterAttribute(canvas, &hatchboxsize_attrib); + cdRegisterAttribute(canvas, &rotate_attrib); + cdRegisterAttribute(canvas, &opacity_attrib); + cdRegisterAttribute(canvas, &pattern_attrib); + cdRegisterAttribute(canvas, &pdf_attrib); + + setpdfdefaultvalues(ctxcanvas); + + while (*line != '\0') + { + while (*line != '\0' && *line != '-') + line++; + + if (*line != '\0') + { + float num; + line++; + switch (*line++) + { + case 'p': + { + int paper; + sscanf(line, "%d", &paper); + setpdfpapersize(ctxcanvas, paper); + break; + } + case 'w': + sscanf(line, "%g", &num); + ctxcanvas->width_mm = num; + ctxcanvas->width_pt = CD_MM2PT*ctxcanvas->width_mm; + break; + case 'h': + sscanf(line, "%g", &num); + ctxcanvas->height_mm = num; + ctxcanvas->height_pt = CD_MM2PT*ctxcanvas->height_mm; + break; + case 's': + sscanf(line, "%d", &(ctxcanvas->res)); + break; + case 'o': + ctxcanvas->landscape = 1; + break; + } + } + + while (*line != '\0' && *line != ' ') + line++; + } + + /* store the base canvas */ + ctxcanvas->canvas = canvas; + + /* update canvas context */ + canvas->ctxcanvas = ctxcanvas; + + if (ctxcanvas->landscape == 1) + { + _cdSwapDouble(ctxcanvas->width_pt, ctxcanvas->height_pt); + _cdSwapDouble(ctxcanvas->width_mm, ctxcanvas->height_mm); + } + + init_pdf(ctxcanvas); +} + +static void cdinittable(cdCanvas* canvas) +{ + canvas->cxFlush = cdflush; + canvas->cxPixel = cdpixel; + canvas->cxLine = cdline; + canvas->cxPoly = cdpoly; + canvas->cxRect = cdrect; + canvas->cxBox = cdbox; + canvas->cxArc = cdarc; + canvas->cxSector = cdsector; + canvas->cxChord = cdchord; + canvas->cxText = cdtext; + canvas->cxFLine = cdfline; + canvas->cxFPoly = cdfpoly; + canvas->cxFRect = cdfrect; + canvas->cxFBox = cdfbox; + canvas->cxFArc = cdfarc; + canvas->cxFSector = cdfsector; + canvas->cxFChord = cdfchord; + canvas->cxFText = cdftext; + canvas->cxGetFontDim = cdgetfontdim; + canvas->cxGetTextSize = cdgettextsize; + canvas->cxPutImageRectRGB = cdputimagerectrgb; + canvas->cxPutImageRectMap = cdputimagerectmap; + canvas->cxPutImageRectRGBA = cdputimagerectrgba; + + canvas->cxClip = cdclip; + canvas->cxClipArea = cdcliparea; + canvas->cxFClipArea = cdfcliparea; + canvas->cxLineStyle = cdlinestyle; + canvas->cxLineWidth = cdlinewidth; + canvas->cxLineCap = cdlinecap; + canvas->cxLineJoin = cdlinejoin; + canvas->cxPattern = cdpattern; + canvas->cxStipple = cdstipple; + canvas->cxHatch = cdhatch; + canvas->cxFont = cdfont; + canvas->cxTransform = cdtransform; + + canvas->cxKillCanvas = cdkillcanvas; +} + +static cdContext cdPDFContext = +{ + CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_PLAY | CD_CAP_PALETTE | + CD_CAP_REGION | CD_CAP_IMAGESRV | CD_CAP_TEXTSIZE | + CD_CAP_BACKGROUND | CD_CAP_BACKOPACITY | CD_CAP_WRITEMODE | + CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB), + 0, + cdcreatecanvas, + cdinittable, + NULL, + NULL, +}; + +cdContext* cdContextPDF(void) +{ + return &cdPDFContext; +} + +/* +p.set_info("Creator", "PDFlib Cookbook") +*/ |