summaryrefslogtreecommitdiff
path: root/src/drv/cdps.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/drv/cdps.c')
-rw-r--r--src/drv/cdps.c1836
1 files changed, 1836 insertions, 0 deletions
diff --git a/src/drv/cdps.c b/src/drv/cdps.c
new file mode 100644
index 0000000..0d23608
--- /dev/null
+++ b/src/drv/cdps.c
@@ -0,0 +1,1836 @@
+/** \file
+ * \brief PS 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 "cdps.h"
+
+
+#define mm2pt(x) (CD_MM2PT*(x))
+
+#ifndef min
+#define min(a, b) ((a)<(b)?(a):(b))
+#endif
+#ifndef max
+#define max(a, b) ((a)>(b)?(a):(b))
+#endif
+
+/*
+** 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.)
+
+/* ATENTION: currentmatrix/setmatrix
+ Remeber that there is a tranformation set just after file open, to define margins and pixel scale.
+ So use transformations carefully.
+*/
+
+static unsigned char HatchBits[6][8] = { /* [style][y] (8x8) */
+ {0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00}, /* CD_HORIZONTAL */
+ {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, /* CD_VERTICAL */
+ {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}, /* CD_BDIAGONAL */
+ {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}, /* CD_FDIAGONAL */
+ {0x10, 0x10, 0x10, 0xFF, 0x10, 0x10, 0x10, 0x10}, /* CD_CROSS */
+ {0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81}};/* CD_DIAGCROSS */
+
+
+struct _cdCtxCanvas
+{
+ cdCanvas* canvas;
+
+ FILE *file; /* Arquivo PS */
+ int res; /* Resolucao */
+ int pages; /* Numero total de paginas */
+ double width; /* Largura do papel (points) */
+ double height; /* Altura do papel (points) */
+ double xmin, ymin; /* Definem as margens esquerda e inferior (points) */
+ double xmax, ymax; /* Definem as margens direita e superior (points) */
+ double bbxmin, bbymin; /* Definem a bounding box */
+ double bbxmax, bbymax; /* Definem a bounding box */
+ double bbmargin; /* Define a margem para a bounding box */
+ double scale; /* Fator de conversao de coordenadas (pixel2points) */
+ int eps; /* Postscrip encapsulado? */
+ int level1; /* if true generates level 1 only function calls */
+ int landscape; /* page orientation */
+ int debug; /* print debug strings in the file */
+ float rotate_angle;
+ int rotate_center_x,
+ rotate_center_y;
+
+ char *nativefontname[100]; /* Registra as fontes usadas */
+ int num_native_font;
+
+ int poly_holes[500];
+ int holes;
+
+};
+
+
+/*
+%F Ajusta o tamanho do papel em points.
+*/
+static void setpspapersize(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 = (double)paper[size].width;
+ ctxcanvas->height = (double)paper[size].height;
+}
+
+/*
+%F Registra os valores default para impressao.
+*/
+static void setpsdefaultvalues(cdCtxCanvas *ctxcanvas)
+{
+ /* all the other values are set to 0 */
+ setpspapersize(ctxcanvas, CD_A4);
+ ctxcanvas->xmin = 25.4; /* ainda em mm, sera' convertido para points na init_ps */
+ ctxcanvas->xmax = 25.4;
+ ctxcanvas->ymin = 25.4;
+ ctxcanvas->ymax = 25.4;
+ ctxcanvas->res = 300;
+}
+
+/*
+%F Insere o ponto (x, y) na BoundingBox corrente.
+Nao leva em consideracao a espessura das linhas.
+*/
+static void insertpoint(cdCtxCanvas *ctxcanvas, int x, int y)
+{
+ double xmin = x*ctxcanvas->scale + ctxcanvas->xmin - ctxcanvas->bbmargin;
+ double ymin = y*ctxcanvas->scale + ctxcanvas->ymin - ctxcanvas->bbmargin;
+
+ double xmax = x*ctxcanvas->scale + ctxcanvas->xmin + ctxcanvas->bbmargin;
+ double ymax = y*ctxcanvas->scale + ctxcanvas->ymin + ctxcanvas->bbmargin;
+
+ if (!ctxcanvas->bbxmin && !ctxcanvas->bbxmax && !ctxcanvas->bbymin && !ctxcanvas->bbymax)
+ {
+ ctxcanvas->bbxmin = xmin;
+ ctxcanvas->bbymin = ymin;
+
+ ctxcanvas->bbxmax = xmax;
+ ctxcanvas->bbymax = ymax;
+ }
+ else
+ {
+ if (ctxcanvas->canvas->clip_mode == CD_CLIPAREA)
+ {
+ ctxcanvas->bbxmin = max(ctxcanvas->canvas->clip_rect.xmin*ctxcanvas->scale + ctxcanvas->xmin, min(ctxcanvas->bbxmin, xmin));
+ ctxcanvas->bbymin = max(ctxcanvas->canvas->clip_rect.ymin*ctxcanvas->scale + ctxcanvas->ymin, min(ctxcanvas->bbymin, ymin));
+
+ ctxcanvas->bbxmax = min(ctxcanvas->canvas->clip_rect.xmax*ctxcanvas->scale + ctxcanvas->xmax, max(ctxcanvas->bbxmax, xmax));
+ ctxcanvas->bbymax = min(ctxcanvas->canvas->clip_rect.ymax*ctxcanvas->scale + ctxcanvas->ymax, max(ctxcanvas->bbymax, ymax));
+ }
+ else
+ {
+ ctxcanvas->bbxmin = max(ctxcanvas->xmin, min(ctxcanvas->bbxmin, xmin));
+ ctxcanvas->bbymin = max(ctxcanvas->ymin, min(ctxcanvas->bbymin, ymin));
+
+ ctxcanvas->bbxmax = min(ctxcanvas->xmax, max(ctxcanvas->bbxmax, xmax));
+ ctxcanvas->bbymax = min(ctxcanvas->ymax, max(ctxcanvas->bbymax, ymax));
+ }
+ }
+}
+
+/*
+%F Ajusta a BoundingBox para conter o ponto (x,y).
+Leva em consideracao a espessura das linhas.
+*/
+static void bbox(cdCtxCanvas *ctxcanvas, int x, int y)
+{
+ if (ctxcanvas->canvas->line_width > 1)
+ {
+ insertpoint(ctxcanvas, x-ctxcanvas->canvas->line_width, y-ctxcanvas->canvas->line_width);
+ insertpoint(ctxcanvas, x+ctxcanvas->canvas->line_width, y+ctxcanvas->canvas->line_width);
+ }
+ else
+ insertpoint(ctxcanvas, x, y);
+}
+
+static void fbbox(cdCtxCanvas *ctxcanvas, double x, double y)
+{
+ if (ctxcanvas->canvas->line_width > 1)
+ {
+ insertpoint(ctxcanvas, (int)(x-ctxcanvas->canvas->line_width), (int)(y-ctxcanvas->canvas->line_width));
+ insertpoint(ctxcanvas, (int)(x+ctxcanvas->canvas->line_width), (int)(y+ctxcanvas->canvas->line_width));
+ }
+ else
+ insertpoint(ctxcanvas, (int)x, (int)y);
+}
+
+static char new_codes[] = {"\
+/newcodes % foreign character encodings\n\
+[\n\
+160/space 161/exclamdown 162/cent 163/sterling 164/currency\n\
+165/yen 166/brokenbar 167/section 168/dieresis 169/copyright\n\
+170/ordfeminine 171/guillemotleft 172/logicalnot 173/hyphen 174/registered\n\
+175/macron 176/degree 177/plusminus 178/twosuperior 179/threesuperior\n\
+180/acute 181/mu 182/paragraph 183/periodcentered 184/cedilla\n\
+185/onesuperior 186/ordmasculine 187/guillemotright 188/onequarter\n\
+189/onehalf 190/threequarters 191/questiondown 192/Agrave 193/Aacute\n\
+194/Acircumflex 195/Atilde 196/Adieresis 197/Aring 198/AE 199/Ccedilla\n\
+200/Egrave 201/Eacute 202/Ecircumflex 203/Edieresis 204/Igrave 205/Iacute\n\
+206/Icircumflex 207/Idieresis 208/Eth 209/Ntilde 210/Ograve 211/Oacute\n\
+212/Ocircumflex 213/Otilde 214/Odieresis 215/multiply 216/Oslash\n\
+217/Ugrave 218/Uacute 219/Ucircumflex 220/Udieresis 221/Yacute 222/Thorn\n\
+223/germandbls 224/agrave 225/aacute 226/acircumflex 227/atilde\n\
+228/adieresis 229/aring 230/ae 231/ccedilla 232/egrave 233/eacute\n\
+234/ecircumflex 235/edieresis 236/igrave 237/iacute 238/icircumflex\n\
+239/idieresis 240/eth 241/ntilde 242/ograve 243/oacute 244/ocircumflex\n\
+245/otilde 246/odieresis 247/divide 248/oslash 249/ugrave 250/uacute\n\
+251/ucircumflex 252/udieresis 253/yacute 254/thorn 255/ydieresis\n\
+] def\n\
+"};
+
+static char change_font[] = {"\
+% change fonts using ISO Latin1 characters\n\
+/ChgFnt % size psname natname => font\n\
+{\n\
+ dup FontDirectory exch known % is re-encoded name known?\n\
+ { exch pop } % yes, get rid of long name\n\
+ { dup 3 1 roll ReEncode } ifelse % no, re-encode it\n\
+ findfont exch scalefont setfont\n\
+} def\n\
+"};
+
+static char re_encode[] = {"\
+/ReEncode %\n\
+{\n\
+ 12 dict begin\n\
+ /newname exch def\n\
+ /basename exch def\n\
+ /basedict basename findfont def\n\
+ /newfont basedict maxlength dict def\n\
+ basedict\n\
+ { exch dup /FID ne\n\
+ { dup /Encoding eq\n\
+ { exch dup length array copy newfont 3 1 roll put }\n\
+ { exch newfont 3 1 roll put } ifelse\n\
+ }\n\
+ { pop pop } ifelse\n\
+ } forall\n\
+ newfont /FontName newname put\n\
+ newcodes aload pop newcodes length 2 idiv\n\
+ { newfont /Encoding get 3 1 roll put } repeat\n\
+ newname newfont definefont pop\n\
+ end\n\
+} def\n\
+"};
+
+static void setcliprect(cdCtxCanvas* ctxcanvas, double xmin, double ymin, double xmax, double ymax)
+{
+ if (ctxcanvas->eps) /* initclip not allowed in EPS */
+ return;
+
+ fprintf(ctxcanvas->file, "initclip\n");
+
+ /* cliping geral para a margem */
+ if (ctxcanvas->level1)
+ {
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "%g %g M\n", xmin, ymin);
+ fprintf(ctxcanvas->file, "%g %g L\n", xmin, ymax);
+ fprintf(ctxcanvas->file, "%g %g L\n", xmax, ymax);
+ fprintf(ctxcanvas->file, "%g %g L\n", xmax, ymin);
+ fprintf(ctxcanvas->file, "C\n");
+ fprintf(ctxcanvas->file, "clip\n");
+ fprintf(ctxcanvas->file, "N\n");
+ }
+ else
+ fprintf(ctxcanvas->file, "%g %g %g %g rectclip\n", xmin, ymin, xmax-xmin, ymax-ymin);
+}
+
+static void set_default_matrix(cdCtxCanvas *ctxcanvas)
+{
+ if (ctxcanvas->eps)
+ fprintf(ctxcanvas->file, "oldmatrix setmatrix\n"); /* reset to current */
+ else
+ {
+ fprintf(ctxcanvas->file, "[0 0 0 0 0 0] defaultmatrix\n"); /* reset to default */
+ fprintf(ctxcanvas->file, "setmatrix\n");
+ }
+
+ /* margin and scale */
+ fprintf(ctxcanvas->file, "%g %g translate\n", ctxcanvas->xmin, ctxcanvas->ymin);
+ fprintf(ctxcanvas->file, "%g %g scale\n", ctxcanvas->scale, ctxcanvas->scale);
+}
+
+/*
+%F Inicializa o arquivo PS.
+*/
+static void init_ps(cdCtxCanvas *ctxcanvas)
+{
+ double w, h;
+
+ time_t now = time(NULL);
+
+ ctxcanvas->scale = 72.0/ctxcanvas->res;
+ ctxcanvas->xmin = mm2pt(ctxcanvas->xmin);
+ ctxcanvas->xmax = ctxcanvas->width - mm2pt(ctxcanvas->xmax);
+ ctxcanvas->ymin = mm2pt(ctxcanvas->ymin);
+ ctxcanvas->ymax = ctxcanvas->height - mm2pt(ctxcanvas->ymax);
+ ctxcanvas->bbmargin = mm2pt(ctxcanvas->bbmargin);
+
+ fprintf(ctxcanvas->file, "%%!PS-Adobe-3.0 %s\n", ctxcanvas->eps ? "EPSF-3.0":"");
+ fprintf(ctxcanvas->file, "%%%%Title: CanvasDraw\n");
+ fprintf(ctxcanvas->file, "%%%%Creator: CanvasDraw\n");
+ fprintf(ctxcanvas->file, "%%%%CreationDate: %s", asctime(localtime(&now)));
+ fprintf(ctxcanvas->file, "%%%%DocumentFonts: (atend)\n"); /* attend means at the end of the file, */
+ fprintf(ctxcanvas->file, "%%%%Pages: (atend)\n"); /* see killcanvas */
+ fprintf(ctxcanvas->file, "%%%%PageOrder: Ascend\n");
+ fprintf(ctxcanvas->file, "%%%%LanguageLevel: %d\n", ctxcanvas->level1 ? 1: 2);
+ fprintf(ctxcanvas->file, "%%%%Orientation: %s\n", ctxcanvas->landscape ? "Landscape": "Portrait");
+
+ if (ctxcanvas->eps)
+ {
+ fprintf(ctxcanvas->file, "%%%%BoundingBox: (atend)\n");
+ ctxcanvas->bbxmin = ctxcanvas->bbxmax = ctxcanvas->bbymin = ctxcanvas->bbymax = 0;
+ /* BoundingBox==Empty */
+ }
+
+ fprintf(ctxcanvas->file, "%%%%EndComments\n");
+ fprintf(ctxcanvas->file, "%%%%BeginProlog\n");
+
+ fprintf(ctxcanvas->file, "/N {newpath} bind def\n");
+ fprintf(ctxcanvas->file, "/C {closepath} bind def\n");
+ fprintf(ctxcanvas->file, "/M {moveto} bind def\n");
+ fprintf(ctxcanvas->file, "/L {lineto} bind def\n");
+ fprintf(ctxcanvas->file, "/B {curveto} bind def\n");
+ fprintf(ctxcanvas->file, "/S {stroke} bind def\n");
+ fprintf(ctxcanvas->file, "/LL {moveto lineto stroke} bind def\n");
+
+ if (!ctxcanvas->level1)
+ {
+ fprintf(ctxcanvas->file, "/RF {rectfill} bind def\n");
+ fprintf(ctxcanvas->file, "/RS {rectstroke} bind def\n");
+ }
+
+ fprintf(ctxcanvas->file, "%%%%EndProlog\n");
+ fprintf(ctxcanvas->file, "%%%%BeginSetup\n");
+
+ if (!ctxcanvas->eps && !ctxcanvas->level1)
+ {
+ fprintf(ctxcanvas->file, "%%%%IncludeFeature: *Resolution %d\n", ctxcanvas->res);
+ fprintf(ctxcanvas->file, "%%%%BeginFeature: *PageSize\n");
+ fprintf(ctxcanvas->file, "<< /PageSize [%g %g] >> setpagedevice\n", ctxcanvas->width, ctxcanvas->height); /* setpagedevice not allowed in EPS */
+ fprintf(ctxcanvas->file, "%%%%EndFeature\n");
+ }
+
+ fprintf(ctxcanvas->file, "%%%%EndSetup\n");
+
+ fputs(new_codes, ctxcanvas->file);
+ fputs(change_font, ctxcanvas->file);
+ fputs(re_encode, ctxcanvas->file);
+
+ w = ctxcanvas->xmax - ctxcanvas->xmin;
+ h = ctxcanvas->ymax - ctxcanvas->ymin;
+
+ ctxcanvas->canvas->w = (int)(w/ctxcanvas->scale + 0.5); /* Converte p/ unidades do usuario */
+ ctxcanvas->canvas->h = (int)(h/ctxcanvas->scale + 0.5); /* Converte p/ unidades do usuario */
+ ctxcanvas->canvas->w_mm = w/CD_MM2PT; /* Converte p/ milimetros */
+ ctxcanvas->canvas->h_mm = h/CD_MM2PT; /* Converte p/ milimetros */
+ ctxcanvas->canvas->bpp = 24;
+ ctxcanvas->canvas->xres = ctxcanvas->canvas->w / ctxcanvas->canvas->w_mm;
+ ctxcanvas->canvas->yres = ctxcanvas->canvas->h / ctxcanvas->canvas->h_mm;
+
+ fprintf(ctxcanvas->file, "%%%%Page: 1 1\n");
+ ctxcanvas->pages = 1;
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdCreateCanvas: Margin Begin\n");
+
+ if (ctxcanvas->eps)
+ fprintf(ctxcanvas->file, "/oldmatrix [0 0 0 0 0 0] currentmatrix def\n"); /* save current matrix */
+
+ set_default_matrix(ctxcanvas);
+
+ /* cliping geral para a margem */
+ setcliprect(ctxcanvas, 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h);
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdCreateCanvas: MarginEnd\n");
+}
+
+
+static void cdkillcanvas(cdCtxCanvas *ctxcanvas)
+{
+ int i;
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdKillCanvas\n");
+
+ fprintf(ctxcanvas->file, "showpage\n");
+ fprintf(ctxcanvas->file, "%%%%Trailer\n");
+ fprintf(ctxcanvas->file, "%%%%Pages: %d 1\n", ctxcanvas->pages);
+
+ if (ctxcanvas->eps)
+ {
+ int xmin = (int)ctxcanvas->bbxmin;
+ int xmax = (int)ctxcanvas->bbxmax;
+ int ymin = (int)ctxcanvas->bbymin;
+ int ymax = (int)ctxcanvas->bbymax;
+ if (xmax < ctxcanvas->bbxmax) xmax++;
+ if (ymax < ctxcanvas->bbymax) ymax++;
+ fprintf(ctxcanvas->file,"%%%%BoundingBox: %5d %5d %5d %5d\n",xmin,ymin,xmax,ymax);
+ }
+
+ fprintf(ctxcanvas->file, "%%%%DocumentFonts:");
+
+ for (i = 0; i < ctxcanvas->num_native_font; i++)
+ {
+ fprintf(ctxcanvas->file, " %s", ctxcanvas->nativefontname[i]);
+ free(ctxcanvas->nativefontname[i]);
+ }
+
+ putc('\n', ctxcanvas->file);
+ fprintf(ctxcanvas->file,"%%%%EOF");
+
+ fclose(ctxcanvas->file);
+
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+ free(ctxcanvas);
+}
+
+static void cddeactivate(cdCtxCanvas *ctxcanvas)
+{
+ fflush(ctxcanvas->file);
+}
+
+static int cdhatch(cdCtxCanvas *ctxcanvas, int style);
+static void cdstipple(cdCtxCanvas *ctxcanvas, int n, int m, const unsigned char *stipple);
+static void cdpattern(cdCtxCanvas *ctxcanvas, int n, int m, const long int *pattern);
+
+static void update_fill(cdCtxCanvas *ctxcanvas, int fill)
+{
+ if (fill == 0)
+ {
+ /* called before a NON filled primitive */
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdPsUpdateFill %d Begin\n", fill);
+
+ fprintf(ctxcanvas->file, "%g %g %g setrgbcolor\n", get_red(ctxcanvas->canvas->foreground),
+ get_green(ctxcanvas->canvas->foreground),
+ get_blue(ctxcanvas->canvas->foreground));
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPsUpdateFill %dEnd\n", fill);
+ }
+ else
+ {
+ /* called before a filled primitive */
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdPsUpdateFill %d Begin\n", fill);
+
+ if (ctxcanvas->canvas->interior_style == CD_SOLID)
+ {
+ fprintf(ctxcanvas->file, "%g %g %g setrgbcolor\n", get_red(ctxcanvas->canvas->foreground),
+ get_green(ctxcanvas->canvas->foreground),
+ get_blue(ctxcanvas->canvas->foreground));
+ }
+ else if (!ctxcanvas->level1)
+ {
+ fprintf(ctxcanvas->file, "cd_pattern\n");
+ fprintf(ctxcanvas->file, "setpattern\n");
+ }
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPsUpdateFill %dEnd\n", fill);
+ }
+}
+
+/*
+%F Comeca uma nova pagina.
+*/
+static void cdflush(cdCtxCanvas *ctxcanvas)
+{
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdFlush Begin\n");
+
+ if (!ctxcanvas->eps)
+ {
+ fprintf(ctxcanvas->file, "gsave\n");
+
+ fprintf(ctxcanvas->file, "showpage\n");
+ ctxcanvas->pages++;
+ fprintf(ctxcanvas->file, "%%%%Page: %d %d\n", ctxcanvas->pages, ctxcanvas->pages);
+
+ fprintf(ctxcanvas->file, "grestore\n");
+ }
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdFlushEnd\n");
+}
+
+
+/******************************************************/
+/* coordinate transformation */
+/******************************************************/
+
+static void cdfcliparea(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ if (ctxcanvas->canvas->clip_mode != CD_CLIPAREA)
+ return;
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfClipArea Begin\n");
+
+ setcliprect(ctxcanvas, xmin, ymin, xmax, ymax);
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdfClipAreaEnd\n");
+}
+
+static int cdclip(cdCtxCanvas *ctxcanvas, int mode)
+{
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdClip %d Begin\n", 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)
+ {
+ fprintf(ctxcanvas->file, "clip_polygon\n");
+ }
+ else
+ {
+ /* margin clipping only */
+ setcliprect(ctxcanvas, 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h);
+ }
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdClip %dEnd\n", mode);
+
+ return mode;
+}
+
+/******************************************************/
+/* primitives */
+/******************************************************/
+
+static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2)
+{
+ update_fill(ctxcanvas, 0);
+
+ fprintf(ctxcanvas->file, "N %d %d %d %d LL\n", x1, y1, x2, y2);
+
+ if (ctxcanvas->eps)
+ {
+ bbox(ctxcanvas, x1, y1);
+ bbox(ctxcanvas, x2, y2);
+ }
+}
+
+static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2)
+{
+ update_fill(ctxcanvas, 0);
+
+ fprintf(ctxcanvas->file, "N %g %g %g %g LL\n", x1, y1, x2, y2);
+
+ if (ctxcanvas->eps)
+ {
+ fbbox(ctxcanvas, x1, y1);
+ fbbox(ctxcanvas, x2, y2);
+ }
+}
+
+static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ update_fill(ctxcanvas, 0);
+
+ if (ctxcanvas->level1)
+ {
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "%d %d M\n", xmin, ymin);
+ fprintf(ctxcanvas->file, "%d %d L\n", xmin, ymax);
+ fprintf(ctxcanvas->file, "%d %d L\n", xmax, ymax);
+ fprintf(ctxcanvas->file, "%d %d L\n", xmax, ymin);
+ fprintf(ctxcanvas->file, "C S\n");
+ }
+ else
+ fprintf(ctxcanvas->file, "%d %d %d %d RS\n", xmin, ymin, xmax - xmin, ymax - ymin);
+
+ if (ctxcanvas->eps)
+ {
+ bbox(ctxcanvas, xmin, ymin);
+ bbox(ctxcanvas, xmax, ymax);
+ }
+}
+
+static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ update_fill(ctxcanvas, 0);
+
+ if (ctxcanvas->level1)
+ {
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "%g %g M\n", xmin, ymin);
+ fprintf(ctxcanvas->file, "%g %g L\n", xmin, ymax);
+ fprintf(ctxcanvas->file, "%g %g L\n", xmax, ymax);
+ fprintf(ctxcanvas->file, "%g %g L\n", xmax, ymin);
+ fprintf(ctxcanvas->file, "C S\n");
+ }
+ else
+ fprintf(ctxcanvas->file, "%g %g %g %g RS\n", xmin, ymin, xmax - xmin, ymax - ymin);
+
+ if (ctxcanvas->eps)
+ {
+ fbbox(ctxcanvas, xmin, ymin);
+ fbbox(ctxcanvas, xmax, ymax);
+ }
+}
+
+static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ update_fill(ctxcanvas, 1);
+
+ if (ctxcanvas->level1)
+ {
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "%d %d M\n", xmin, ymin);
+ fprintf(ctxcanvas->file, "%d %d L\n", xmin, ymax);
+ fprintf(ctxcanvas->file, "%d %d L\n", xmax, ymax);
+ fprintf(ctxcanvas->file, "%d %d L\n", xmax, ymin);
+ fprintf(ctxcanvas->file, "C fill\n");
+ }
+ else
+ fprintf(ctxcanvas->file, "%d %d %d %d RF\n", xmin, ymin, xmax - xmin, ymax - ymin);
+
+ if (ctxcanvas->eps)
+ {
+ bbox(ctxcanvas, xmin, ymin);
+ bbox(ctxcanvas, xmax, ymax);
+ }
+}
+
+static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ update_fill(ctxcanvas, 1);
+
+ if (ctxcanvas->level1)
+ {
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "%g %g M\n", xmin, ymin);
+ fprintf(ctxcanvas->file, "%g %g L\n", xmin, ymax);
+ fprintf(ctxcanvas->file, "%g %g L\n", xmax, ymax);
+ fprintf(ctxcanvas->file, "%g %g L\n", xmax, ymin);
+ fprintf(ctxcanvas->file, "C fill\n");
+ }
+ else
+ fprintf(ctxcanvas->file, "%g %g %g %g RF\n", xmin, ymin, xmax - xmin, ymax - ymin);
+
+ if (ctxcanvas->eps)
+ {
+ fbbox(ctxcanvas, xmin, ymin);
+ fbbox(ctxcanvas, xmax, ymax);
+ }
+}
+
+static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ update_fill(ctxcanvas, 0);
+
+ if (w==h) /* Circulo: PS implementa direto */
+ {
+ fprintf(ctxcanvas->file, "N %d %d %g %g %g arc S\n", xc, yc, 0.5*w, a1, a2);
+ }
+ else /* Elipse: mudar a escala p/ criar a partir do circulo */
+ {
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdArc Ellipse Begin\n");
+
+ fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n"); /* fill new matrix from CTM */
+ fprintf(ctxcanvas->file, "%d %d translate\n", xc, yc);
+ fprintf(ctxcanvas->file, "1 %g scale\n", ((double)h)/w);
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "0 0 %g %g %g arc\n", 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "S\n");
+ fprintf(ctxcanvas->file, "setmatrix\n"); /* back to CTM */
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdArc EllipseEnd\n");
+ }
+
+ if (ctxcanvas->eps)
+ {
+ int xmin, xmax, ymin, ymax;
+ cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax);
+ bbox(ctxcanvas, xmin, ymin);
+ bbox(ctxcanvas, xmax, 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) /* Circulo: PS implementa direto */
+ {
+ fprintf(ctxcanvas->file, "N %g %g %g %g %g arc S\n", xc, yc, 0.5*w, a1, a2);
+ }
+ else /* Elipse: mudar a escala p/ criar a partir do circulo */
+ {
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfArc Ellipse Begin\n");
+
+ fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n");
+ fprintf(ctxcanvas->file, "%g %g translate\n", xc, yc);
+ fprintf(ctxcanvas->file, "1 %g scale\n", h/w);
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "0 0 %g %g %g arc\n", 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "S\n");
+ fprintf(ctxcanvas->file, "setmatrix\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdfArc EllipseEnd\n");
+ }
+
+ if (ctxcanvas->eps)
+ {
+ int xmin, xmax, ymin, ymax;
+ cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax);
+ bbox(ctxcanvas, xmin, ymin);
+ bbox(ctxcanvas, xmax, ymax);
+ }
+}
+
+static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ update_fill(ctxcanvas, 1);
+
+ if (w==h) /* Circulo: PS implementa direto */
+ {
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdSector Circle Begin\n");
+
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "%d %d M\n", xc, yc);
+ fprintf(ctxcanvas->file, "%d %d %g %g %g arc\n", xc, yc, 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "C fill\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdSector CircleEnd\n");
+ }
+ else /* Elipse: mudar a escala p/ criar a partir do circulo */
+ {
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdSector Ellipse Begin\n");
+
+ fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n");
+ fprintf(ctxcanvas->file, "%d %d translate\n", xc, yc);
+ fprintf(ctxcanvas->file, "1 %g scale\n", ((double)h)/w);
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "0 0 M\n");
+ fprintf(ctxcanvas->file, "0 0 %g %g %g arc\n", 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "C fill\n");
+ fprintf(ctxcanvas->file, "setmatrix\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdSector EllipseEnd\n");
+ }
+
+ if (ctxcanvas->eps)
+ {
+ int xmin, xmax, ymin, ymax;
+ cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax);
+ bbox(ctxcanvas, xmin, ymin);
+ bbox(ctxcanvas, xmax, ymax);
+ bbox(ctxcanvas, xc, yc);
+ }
+}
+
+static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
+{
+ update_fill(ctxcanvas, 1);
+
+ if (w==h) /* Circulo: PS implementa direto */
+ {
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfSector Circle Begin\n");
+
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "%g %g M\n", xc, yc);
+ fprintf(ctxcanvas->file, "%g %g %g %g %g arc\n", xc, yc, 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "C fill\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdfSector CircleEnd\n");
+ }
+ else /* Elipse: mudar a escala p/ criar a partir do circulo */
+ {
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfSector Ellipse Begin\n");
+
+ fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n");
+ fprintf(ctxcanvas->file, "%g %g translate\n", xc, yc);
+ fprintf(ctxcanvas->file, "1 %g scale\n", h/w);
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "0 0 M\n");
+ fprintf(ctxcanvas->file, "0 0 %g %g %g arc\n", 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "C fill\n");
+ fprintf(ctxcanvas->file, "setmatrix\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdfSector EllipseEnd\n");
+ }
+
+ if (ctxcanvas->eps)
+ {
+ int xmin, xmax, ymin, ymax;
+ cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax);
+ bbox(ctxcanvas, xmin, ymin);
+ bbox(ctxcanvas, xmax, ymax);
+ fbbox(ctxcanvas, xc, yc);
+ }
+}
+
+static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ update_fill(ctxcanvas, 1);
+
+ if (w==h) /* Circulo: PS implementa direto */
+ {
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdChord Circle Begin\n");
+
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "%d %d %g %g %g arc\n", xc, yc, 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "C fill\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdChord CircleEnd\n");
+ }
+ else /* Elipse: mudar a escala p/ criar a partir do circulo */
+ {
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdChord Ellipse Begin\n");
+
+ fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n");
+ fprintf(ctxcanvas->file, "%d %d translate\n", xc, yc);
+ fprintf(ctxcanvas->file, "1 %g scale\n", ((double)h)/w);
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "0 0 %g %g %g arc\n", 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "C fill\n");
+ fprintf(ctxcanvas->file, "setmatrix\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdChord EllipseEnd\n");
+ }
+
+ if (ctxcanvas->eps)
+ {
+ int xmin, xmax, ymin, ymax;
+ cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax);
+ bbox(ctxcanvas, xmin, ymin);
+ bbox(ctxcanvas, xmax, ymax);
+ }
+}
+
+static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
+{
+ update_fill(ctxcanvas, 1);
+
+ if (w==h) /* Circulo: PS implementa direto */
+ {
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfChord Circle Begin\n");
+
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "%g %g %g %g %g arc\n", xc, yc, 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "C fill\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdfChord CircleEnd\n");
+ }
+ else /* Elipse: mudar a escala p/ criar a partir do circulo */
+ {
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfChord Ellipse Begin\n");
+
+ fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n");
+ fprintf(ctxcanvas->file, "%g %g translate\n", xc, yc);
+ fprintf(ctxcanvas->file, "1 %g scale\n", h/w);
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "0 0 %g %g %g arc\n", 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "C fill\n");
+ fprintf(ctxcanvas->file, "setmatrix\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdfChord EllipseEnd\n");
+ }
+
+ if (ctxcanvas->eps)
+ {
+ int xmin, xmax, ymin, ymax;
+ cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax);
+ bbox(ctxcanvas, xmin, ymin);
+ bbox(ctxcanvas, xmax, ymax);
+ }
+}
+
+static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix);
+
+static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *s)
+{
+ int i, length;
+ int ascent, height, baseline;
+
+ update_fill(ctxcanvas, 0);
+
+ cdCanvasGetFontDim(ctxcanvas->canvas, NULL, &height, &ascent, NULL);
+ baseline = height - ascent;
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdText Begin\n");
+
+ if (ctxcanvas->canvas->use_matrix || ctxcanvas->rotate_angle)
+ set_default_matrix(ctxcanvas);
+
+ fprintf(ctxcanvas->file, "N 0 0 M\n");
+ putc('(', ctxcanvas->file);
+
+ for (length = (int)strlen(s), i=0; i<length; i++)
+ {
+ if (s[i]=='(' || s[i]==')')
+ putc('\\', ctxcanvas->file);
+ putc(s[i], ctxcanvas->file);
+ }
+
+ fprintf(ctxcanvas->file, ")\n");
+ fprintf(ctxcanvas->file, "dup true charpath\n");
+ fprintf(ctxcanvas->file, "flattenpath\n");
+ fprintf(ctxcanvas->file, "pathbbox\n"); /* bbox na pilha: llx lly urx ury */
+ fprintf(ctxcanvas->file, "exch\n"); /* troca o topo: llx lly ury urx */
+ fprintf(ctxcanvas->file, "4 1 roll\n"); /* roda: urx llx lly ury */
+ fprintf(ctxcanvas->file, "exch\n"); /* troca o topo: urx llx ury lly */
+ fprintf(ctxcanvas->file, "sub\n"); /* subtrai: urx llx h */
+ fprintf(ctxcanvas->file, "3 1 roll\n"); /* roda: h urx llx */
+ fprintf(ctxcanvas->file, "sub\n"); /* subtrai: h w */
+ fprintf(ctxcanvas->file, "0 0\n"); /* empilha: h w 0 0 */
+ fprintf(ctxcanvas->file, "4 -1 roll\n"); /* roda: w 0 0 h */
+
+ if (ctxcanvas->canvas->use_matrix || ctxcanvas->rotate_angle)
+ cdtransform(ctxcanvas, ctxcanvas->canvas->use_matrix? ctxcanvas->canvas->matrix: NULL);
+
+ fprintf(ctxcanvas->file, "gsave\n"); /* save to use local transform */
+ fprintf(ctxcanvas->file, "%d %d translate\n", x, y);
+
+ if (ctxcanvas->canvas->text_orientation != 0)
+ fprintf(ctxcanvas->file, "%g rotate\n", ctxcanvas->canvas->text_orientation);
+
+ switch (ctxcanvas->canvas->text_alignment) /* Operacao em Y. topo da pilha: w x y h */
+ {
+ case CD_NORTH:
+ case CD_NORTH_EAST:
+ case CD_NORTH_WEST:
+ fprintf(ctxcanvas->file, "%d sub sub\n", baseline); /* empilha, subtrai, subtrai: w x y-(h-baseline) */
+ break;
+ case CD_EAST:
+ case CD_WEST:
+ case CD_CENTER:
+ fprintf(ctxcanvas->file, "2 div %d sub sub\n", baseline); /* empilha, divide, empilha, subtrai, subtrai: w x y-(h/2-baseline) */
+ break;
+ case CD_SOUTH_EAST:
+ case CD_SOUTH:
+ case CD_SOUTH_WEST:
+ fprintf(ctxcanvas->file, "pop %d add\n", baseline); /* desempilha, empilha, adiciona: w x y+baseline */
+ break;
+ case CD_BASE_RIGHT:
+ case CD_BASE_CENTER:
+ case CD_BASE_LEFT:
+ fprintf(ctxcanvas->file, "pop\n"); /* desempilha h: w x y */
+ break;
+ }
+
+ fprintf(ctxcanvas->file, "3 1 roll\n"); /* roda: y' w x */
+ fprintf(ctxcanvas->file, "exch\n"); /* inverte: y' x w */
+
+ switch (ctxcanvas->canvas->text_alignment) /* Operacao em X, topo da pilha: x w */
+ {
+ case CD_NORTH:
+ case CD_SOUTH:
+ case CD_CENTER:
+ case CD_BASE_CENTER:
+ fprintf(ctxcanvas->file, "2 div sub\n"); /* empilha, divide, subtrai: y' x-w/2 */
+ break;
+ case CD_NORTH_EAST:
+ case CD_EAST:
+ case CD_SOUTH_EAST:
+ case CD_BASE_RIGHT:
+ fprintf(ctxcanvas->file, "sub\n"); /* subtrai: y' x-w */
+ break;
+ case CD_SOUTH_WEST:
+ case CD_WEST:
+ case CD_NORTH_WEST:
+ case CD_BASE_LEFT:
+ fprintf(ctxcanvas->file, "pop\n"); /* desempilha: y' x */
+ break;
+ }
+
+ fprintf(ctxcanvas->file, "exch\n"); /* inverte: x' y' */
+ fprintf(ctxcanvas->file, "M\n"); /* moveto */
+
+ fprintf(ctxcanvas->file, "show\n");
+
+ if (ctxcanvas->eps)
+ {
+ int xmin, xmax, ymin, ymax;
+ cdCanvasGetTextBox(ctxcanvas->canvas, x, y, s, &xmin, &xmax, &ymin, &ymax);
+ bbox(ctxcanvas, xmin, ymin);
+ bbox(ctxcanvas, xmax, ymax);
+ }
+
+ fprintf(ctxcanvas->file, "grestore\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdTextEnd\n");
+}
+
+static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
+{
+ int i;
+
+ if (mode == CD_CLIP)
+ {
+ if (ctxcanvas->eps) /* initclip not allowed in EPS */
+ return;
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdPoly %d Begin\n", mode);
+
+ fprintf(ctxcanvas->file, "/clip_polygon {\n");
+ fprintf(ctxcanvas->file, "initclip\n");
+ }
+ else
+ {
+ if (mode == CD_FILL)
+ update_fill(ctxcanvas, 1);
+ else
+ update_fill(ctxcanvas, 0);
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdPoly %d Begin\n", mode);
+ }
+
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "%d %d M\n", poly[0].x, poly[0].y);
+
+ if (ctxcanvas->eps)
+ bbox(ctxcanvas, poly[0].x, poly[0].y);
+
+ if (mode == CD_BEZIER)
+ {
+ for (i=1; i<n; i+=3)
+ {
+ fprintf(ctxcanvas->file, "%d %d %d %d %d %d B\n", poly[i].x, poly[i].y,
+ poly[i+1].x, poly[i+1].y,
+ poly[i+2].x, poly[i+2].y);
+
+ if (ctxcanvas->eps)
+ {
+ bbox(ctxcanvas, poly[i].x, poly[i].y);
+ bbox(ctxcanvas, poly[i+2].x, poly[i+2].y);
+ bbox(ctxcanvas, poly[i+3].x, poly[i+3].y);
+ }
+ }
+ }
+ else
+ {
+ int hole_index = 0;
+
+ for (i=1; i<n; i++)
+ {
+ if (ctxcanvas->holes && i == ctxcanvas->poly_holes[hole_index])
+ {
+ fprintf(ctxcanvas->file, "%d %d M\n", poly[i].x, poly[i].y);
+ hole_index++;
+ }
+ else
+ fprintf(ctxcanvas->file, "%d %d L\n", poly[i].x, poly[i].y);
+
+ if (ctxcanvas->eps)
+ bbox(ctxcanvas, poly[i].x, poly[i].y);
+ }
+ }
+
+ switch (mode)
+ {
+ case CD_CLOSED_LINES :
+ fprintf(ctxcanvas->file, "C S\n");
+ break;
+ case CD_OPEN_LINES :
+ fprintf(ctxcanvas->file, "S\n");
+ break;
+ case CD_BEZIER :
+ fprintf(ctxcanvas->file, "S\n");
+ break;
+ case CD_FILL :
+ if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD)
+ fprintf(ctxcanvas->file, "eofill\n");
+ else
+ fprintf(ctxcanvas->file, "fill\n");
+ break;
+ case CD_CLIP :
+ if (ctxcanvas->canvas->fill_mode==CD_EVENODD)
+ fprintf(ctxcanvas->file, "C eoclip\n");
+ else
+ fprintf(ctxcanvas->file, "C clip\n");
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "} bind def\n");
+ if (ctxcanvas->canvas->clip_mode == CD_CLIPPOLYGON)
+ fprintf(ctxcanvas->file, "clip_polygon\n");
+ break;
+ }
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPoly %dEnd\n", mode);
+}
+
+static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
+{
+ int i, hole_index = 0;
+
+ if (mode == CD_CLIP)
+ {
+ if (ctxcanvas->eps) /* initclip not allowed in EPS */
+ return;
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfPoly %d Begin\n", mode);
+
+ fprintf(ctxcanvas->file, "/clip_polygon {\n");
+ fprintf(ctxcanvas->file, "initclip\n");
+ }
+ else
+ {
+ if (mode == CD_FILL)
+ update_fill(ctxcanvas, 1);
+ else
+ update_fill(ctxcanvas, 0);
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfPoly %d Begin\n", mode);
+ }
+
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "%g %g M\n", poly[0].x, poly[0].y);
+
+ if (ctxcanvas->eps)
+ fbbox(ctxcanvas, poly[0].x, poly[0].y);
+
+ for (i=1; i<n; i++)
+ {
+ if (ctxcanvas->holes && i == ctxcanvas->poly_holes[hole_index])
+ {
+ fprintf(ctxcanvas->file, "%g %g M\n", poly[i].x, poly[i].y);
+ hole_index++;
+ }
+ else
+ fprintf(ctxcanvas->file, "%g %g L\n", poly[i].x, poly[i].y);
+
+ if (ctxcanvas->eps)
+ fbbox(ctxcanvas, poly[i].x, poly[i].y);
+ }
+
+ switch (mode)
+ {
+ case CD_CLOSED_LINES :
+ fprintf(ctxcanvas->file, "C S\n");
+ break;
+ case CD_OPEN_LINES :
+ fprintf(ctxcanvas->file, "S\n");
+ break;
+ case CD_FILL :
+ if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD)
+ fprintf(ctxcanvas->file, "eofill\n");
+ else
+ fprintf(ctxcanvas->file, "fill\n");
+ break;
+ case CD_CLIP :
+ if (ctxcanvas->canvas->fill_mode==CD_EVENODD)
+ fprintf(ctxcanvas->file, "C eoclip\n");
+ else
+ fprintf(ctxcanvas->file, "C clip\n");
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "} bind def\n");
+ if (ctxcanvas->canvas->clip_mode == CD_CLIPPOLYGON)
+ fprintf(ctxcanvas->file, "clip_polygon\n");
+ break;
+ }
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdfPoly %dEnd\n", mode);
+}
+
+
+/******************************************************/
+/* attributes */
+/******************************************************/
+
+static int cdlinestyle(cdCtxCanvas *ctxcanvas, int style)
+{
+ double mm = (72.0/25.4) / ctxcanvas->scale;
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdLineStyle %d Begin\n", style);
+
+ fprintf(ctxcanvas->file, "[");
+
+ switch (style)
+ {
+ case CD_CONTINUOUS : /* empty dash */
+ fprintf(ctxcanvas->file, " ");
+ break;
+ case CD_DASHED :
+ fprintf(ctxcanvas->file, "%g %g", 3*mm, mm);
+ break;
+ case CD_DOTTED :
+ fprintf(ctxcanvas->file, "%g %g", mm, mm);
+ break;
+ case CD_DASH_DOT :
+ fprintf(ctxcanvas->file, "%g %g %g %g", 3*mm, mm, mm, mm);
+ break;
+ case CD_DASH_DOT_DOT :
+ fprintf(ctxcanvas->file, "%g %g %g %g %g %g", 3*mm, mm, mm, mm, mm, mm);
+ break;
+ case CD_CUSTOM :
+ {
+ int i;
+ for (i = 0; i < ctxcanvas->canvas->line_dashes_count; i++)
+ fprintf(ctxcanvas->file, "%g ", ctxcanvas->canvas->line_dashes[i]*mm);
+ }
+ break;
+ }
+
+ fprintf(ctxcanvas->file, "] 0 setdash\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdLineStyle %dEnd\n", style);
+
+ return style;
+}
+
+static int cdlinewidth(cdCtxCanvas *ctxcanvas, int width)
+{
+ fprintf(ctxcanvas->file, "%d setlinewidth\n", width);
+ return width;
+}
+
+static int cdlinejoin(cdCtxCanvas *ctxcanvas, int join)
+{
+ int cd2ps_join[] = {0, 2, 1};
+ fprintf(ctxcanvas->file, "%d setlinejoin\n", cd2ps_join[join]);
+ return join;
+}
+
+static int cdlinecap(cdCtxCanvas *ctxcanvas, int cap)
+{
+ int cd2ps_cap[] = {0, 2, 1};
+ fprintf(ctxcanvas->file, "%d setlinecap\n", cd2ps_cap[cap]);
+ return cap;
+}
+
+static void make_pattern(cdCtxCanvas *ctxcanvas, int n, int m, void* data, void (*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;
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdPsMakePattern Begin\n");
+
+ fprintf(ctxcanvas->file, "/cd_pattern\n");
+ fprintf(ctxcanvas->file, "currentfile %d string readhexstring\n", n*m*3);
+
+ for (j=0; j<m; j++)
+ {
+ for (i=0; i<n; i++)
+ {
+ data2rgb(ctxcanvas, n, i, j, data, &r, &g, &b);
+ fprintf(ctxcanvas->file, "%02x%02x%02x", (int)r, (int)g, (int)b);
+ }
+
+ fprintf(ctxcanvas->file, "\n");
+ }
+
+ fprintf(ctxcanvas->file, "pop\n");
+ fprintf(ctxcanvas->file, "/Pat exch def\n");
+ fprintf(ctxcanvas->file, "<<\n");
+ fprintf(ctxcanvas->file, " /PatternType 1\n");
+ fprintf(ctxcanvas->file, " /PaintType 1\n");
+ fprintf(ctxcanvas->file, " /TilingType 1\n");
+ fprintf(ctxcanvas->file, " /BBox [0 0 %d %d]\n", n, m);
+ fprintf(ctxcanvas->file, " /XStep %d /YStep %d\n", n, m);
+ fprintf(ctxcanvas->file, " /PaintProc {\n");
+ fprintf(ctxcanvas->file, " pop\n");
+ fprintf(ctxcanvas->file, " %d %d 8\n", n, m);
+ fprintf(ctxcanvas->file, " matrix\n");
+ fprintf(ctxcanvas->file, " Pat\n");
+ fprintf(ctxcanvas->file, " false 3\n");
+ fprintf(ctxcanvas->file, " colorimage\n");
+ fprintf(ctxcanvas->file, " }\n");
+ fprintf(ctxcanvas->file, ">>\n");
+ fprintf(ctxcanvas->file, "matrix\n");
+ fprintf(ctxcanvas->file, "makepattern\n");
+ fprintf(ctxcanvas->file, "def\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPsMakePatternEnd\n");
+}
+
+static void 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);
+}
+
+static void cdpattern(cdCtxCanvas *ctxcanvas, int n, int m, const long int *pattern)
+{
+ if (ctxcanvas->level1)
+ return;
+
+ make_pattern(ctxcanvas, n, m, (void*)pattern, long2rgb);
+}
+
+static void uchar2rgb(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b)
+{
+ unsigned char* uchar_data = (unsigned char*)data;
+ if (uchar_data[j*n+i])
+ cdDecodeColor(ctxcanvas->canvas->foreground, r, g, b);
+ else
+ cdDecodeColor(ctxcanvas->canvas->background, r, g, b);
+}
+
+static void cdstipple(cdCtxCanvas *ctxcanvas, int n, int m, const unsigned char *stipple)
+{
+ if (ctxcanvas->level1)
+ return;
+
+ make_pattern(ctxcanvas, n, m, (void*)stipple, uchar2rgb);
+}
+
+static void ucharh2rgb(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b)
+{
+ unsigned char* uchar_data = (unsigned char*)data;
+ static unsigned char hatch;
+ (void)n;
+ if (i == 0) hatch = uchar_data[j];
+ if (hatch & 0x80)
+ cdDecodeColor(ctxcanvas->canvas->foreground, r, g, b);
+ else
+ cdDecodeColor(ctxcanvas->canvas->background, r, g, b);
+ _cdRotateHatch(hatch);
+}
+
+static int cdhatch(cdCtxCanvas *ctxcanvas, int style)
+{
+ if (ctxcanvas->level1)
+ return ctxcanvas->canvas->hatch_style;
+
+ make_pattern(ctxcanvas, 8, 8, (void*)HatchBits[style], ucharh2rgb);
+
+ return style;
+}
+
+static void add_font_name(cdCtxCanvas *ctxcanvas, char *nativefontname)
+{
+ int size, i;
+ for (i = 0; i < ctxcanvas->num_native_font; i++)
+ {
+ if (cdStrEqualNoCase(ctxcanvas->nativefontname[i], nativefontname))
+ return;
+ }
+
+ size = strlen(nativefontname)+1;
+ ctxcanvas->nativefontname[ctxcanvas->num_native_font] = (char*)malloc(size);
+ memcpy(ctxcanvas->nativefontname[ctxcanvas->num_native_font], nativefontname, size);
+ ctxcanvas->num_native_font++;
+}
+
+static char *findfont(const char* type_face, int style)
+{
+ static char font[1024];
+
+ static char *type[] =
+ {
+ "", /* CD_PLAIN */
+ "-Bold", /* CD_BOLD */
+ "-Oblique", /* CD_ITALIC */
+ "-BoldOblique", /* CD_BOLD_ITALIC */
+
+ "-Roman", /* Plain p/ Times */
+ "-Bold", /* Bold p/ Times */
+ "-Italic", /* Italic p/ Times */
+ "-BoldItalic" /* BoldItalic p/ Times */
+ };
+
+ if (cdStrEqualNoCase(type_face, "System"))
+ type_face = "Courier";
+
+ if (cdStrEqualNoCase(type_face, "Times"))
+ style += 4;
+
+ sprintf(font, "%s%s", type_face, type[style]);
+
+ return font;
+}
+
+static int cdfont(cdCtxCanvas *ctxcanvas, const char *type_face, int style, int size)
+{
+ char *nativefontname = findfont(type_face, style&3); /* no underline or strikeout support */
+ int size_pixel = cdGetFontSizePixels(ctxcanvas->canvas, size);
+ fprintf(ctxcanvas->file, "%d /%s /%s-Latin1 ChgFnt\n", size_pixel, nativefontname, nativefontname);
+ add_font_name(ctxcanvas, nativefontname);
+ return 1;
+}
+
+static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix)
+{
+ set_default_matrix(ctxcanvas);
+
+ if (matrix)
+ {
+ fprintf(ctxcanvas->file, "[%g %g %g %g %g %g] concat\n", matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
+ }
+ else
+ {
+ if (ctxcanvas->rotate_angle)
+ {
+ /* rotation = translate to point + rotation + translate back */
+ fprintf(ctxcanvas->file, "%d %d translate\n", ctxcanvas->rotate_center_x, ctxcanvas->rotate_center_y);
+ fprintf(ctxcanvas->file, "%g rotate\n", (double)ctxcanvas->rotate_angle);
+ fprintf(ctxcanvas->file, "%d %d translate\n", -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, rw, rh;
+ rw = xmax-xmin+1;
+ rh = ymax-ymin+1;
+ (void)ih;
+
+ if (ctxcanvas->level1)
+ return;
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPutImageRectRGB Start\n");
+
+ fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n");
+ fprintf(ctxcanvas->file, "%d %d translate\n", x, y);
+ fprintf(ctxcanvas->file, "%d %d scale\n", w, h);
+
+ fprintf(ctxcanvas->file, "%d %d 8\n", rw, rh);
+ fprintf(ctxcanvas->file, "[%d 0 0 %d 0 0]\n", rw, rh);
+ fprintf(ctxcanvas->file, "{currentfile %d string readhexstring pop}\n", rw);
+ fprintf(ctxcanvas->file, "false 3\n");
+ fprintf(ctxcanvas->file, "colorimage\n");
+
+ for (j=ymin; j<=ymax; j++)
+ {
+ for (i=xmin; i<=xmax; i++)
+ {
+ int pos = j*iw+i;
+ fprintf(ctxcanvas->file, "%02x%02x%02x", (int)r[pos], (int)g[pos], (int)b[pos]);
+ }
+
+ fprintf(ctxcanvas->file, "\n");
+ }
+
+ fprintf(ctxcanvas->file, "setmatrix\n");
+
+ if (ctxcanvas->eps)
+ {
+ bbox(ctxcanvas, x, y);
+ bbox(ctxcanvas, x+rw-1, y+rh-1);
+ }
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPutImageRectRGBEnd\n");
+}
+
+static int isgray(int size, const unsigned char *index, const long int *colors)
+{
+ int i, pal_size = 0;
+ unsigned char r, g, b;
+
+ for (i = 0; i < size; i++)
+ {
+ if (index[i] > pal_size)
+ pal_size = index[i];
+ }
+
+ pal_size++;
+
+ for (i = 0; i < pal_size; i++)
+ {
+ cdDecodeColor(colors[i], &r, &g, &b);
+
+ if (i != r || r != g || g != b)
+ return 0;
+ }
+
+ return 1;
+}
+
+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, rw, rh, is_gray;
+ rw = xmax-xmin+1;
+ rh = ymax-ymin+1;
+ (void)ih;
+
+ is_gray = isgray(iw*ih, index, colors);
+
+ if (!is_gray && ctxcanvas->level1)
+ return;
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPutImageRectMap Start\n");
+
+ fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n");
+ fprintf(ctxcanvas->file, "%d %d translate\n", x, y);
+ fprintf(ctxcanvas->file, "%d %d scale\n", w, h);
+
+ fprintf(ctxcanvas->file, "%d %d 8\n", rw, rh);
+ fprintf(ctxcanvas->file, "[%d 0 0 %d 0 0]\n", rw, rh);
+ fprintf(ctxcanvas->file, "{currentfile %d string readhexstring pop}\n", rw);
+
+ if (is_gray)
+ {
+ fprintf(ctxcanvas->file, "image\n");
+
+ for (j=ymin; j<=ymax; j++)
+ {
+ for (i=xmin; i<=xmax; i++)
+ {
+ int pos = j*iw+i;
+ fprintf(ctxcanvas->file, "%02x", (int)index[pos]);
+ }
+
+ fprintf(ctxcanvas->file, "\n");
+ }
+ }
+ else
+ {
+ fprintf(ctxcanvas->file, "false 3\n");
+ fprintf(ctxcanvas->file, "colorimage\n");
+
+ for (j=ymin; j<=ymax; j++)
+ {
+ for (i=xmin; i<=xmax; i++)
+ {
+ int pos = j*iw+i;
+ unsigned char r, g, b;
+ cdDecodeColor(colors[index[pos]], &r, &g, &b);
+ fprintf(ctxcanvas->file, "%02x%02x%02x", (int)r, (int)g, (int)b);
+ }
+
+ fprintf(ctxcanvas->file, "\n");
+ }
+ }
+
+ fprintf(ctxcanvas->file, "setmatrix\n");
+
+ if (ctxcanvas->eps)
+ {
+ bbox(ctxcanvas, x, y);
+ bbox(ctxcanvas, x+rw-1, y+rh-1);
+ }
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPutImageRectMapEnd\n");
+}
+
+/******************************************************/
+/* server images */
+/******************************************************/
+
+static void cdpixel(cdCtxCanvas *ctxcanvas, int x, int y, long int color)
+{
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPixel Start\n");
+
+ fprintf(ctxcanvas->file, "%g %g %g setrgbcolor\n",
+ get_red(color), get_green(color), get_blue(color));
+
+ if (ctxcanvas->level1)
+ {
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "%d %d 1 0 360 arc\n", x, y);
+ fprintf(ctxcanvas->file, "C fill\n");
+ }
+ else
+ fprintf(ctxcanvas->file, "%d %d 1 1 RF\n", x, y);
+
+ if (ctxcanvas->eps)
+ bbox(ctxcanvas, x, y);
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPixelEnd\n");
+}
+
+/******************************************************/
+/* custom attributes */
+/******************************************************/
+
+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;
+ }
+
+ set_default_matrix(ctxcanvas);
+
+ if (ctxcanvas->rotate_angle)
+ {
+ /* rotation = translate to point + rotation + translate back */
+ fprintf(ctxcanvas->file, "%d %d translate\n", ctxcanvas->rotate_center_x, ctxcanvas->rotate_center_y);
+ fprintf(ctxcanvas->file, "%g rotate\n", (double)ctxcanvas->rotate_angle);
+ fprintf(ctxcanvas->file, "%d %d translate\n", -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_cmd_attrib(cdCtxCanvas *ctxcanvas, char* data)
+{
+ fprintf(ctxcanvas->file, data);
+}
+
+static cdAttribute cmd_attrib =
+{
+ "CMD",
+ set_cmd_attrib,
+ NULL
+};
+
+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
+};
+
+/*
+%F Cria um novo canvas PS
+Parametros passados em data:
+nome nome do arquivo de saida <= 255 caracteres
+-p[num] tamanho do papel (A0-5, LETTER, LEGAL)
+-w[num] largura do papel em milimetros
+-h[num] altura do papel em milimetros
+-l[num] margem esquerda em milimetros
+-r[num] margem direita em milimetros
+-b[num] margem inferior em milimetros
+-t[num] margem superior em milimetros
+-s[num] resolucao em dpi
+-e encapsulated postscript
+-1 level 1 operators only
+-d[num] margem da bbox em milimetros para eps
+*/
+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;
+
+ if ((ctxcanvas->file = fopen(filename, "w")) == NULL)
+ {
+ free(ctxcanvas);
+ return;
+ }
+
+ ctxcanvas->holes = 0;
+ cdRegisterAttribute(canvas, &poly_attrib);
+ cdRegisterAttribute(canvas, &cmd_attrib);
+ cdRegisterAttribute(canvas, &rotate_attrib);
+
+ setpsdefaultvalues(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);
+ setpspapersize(ctxcanvas, paper);
+ break;
+ }
+ case 'w':
+ sscanf(line, "%g", &num);
+ ctxcanvas->width = mm2pt(num);
+ break;
+ case 'h':
+ sscanf(line, "%g", &num);
+ ctxcanvas->height = mm2pt(num);
+ break;
+ case 'l':
+ sscanf(line, "%g", &num);
+ ctxcanvas->xmin = num;
+ break;
+ case 'r':
+ sscanf(line, "%g", &num);
+ ctxcanvas->xmax = num; /* right margin, must be converted to xmax */
+ break;
+ case 'b':
+ sscanf(line, "%g", &num);
+ ctxcanvas->ymin = num;
+ break;
+ case 't':
+ sscanf(line, "%g", &num);
+ ctxcanvas->ymax = num; /* top margin, must be converted to ymax */
+ break;
+ case 's':
+ sscanf(line, "%d", &(ctxcanvas->res));
+ break;
+ case 'e':
+ ctxcanvas->eps = 1;
+ break;
+ case 'o':
+ ctxcanvas->landscape = 1;
+ break;
+ case '1':
+ ctxcanvas->level1 = 1;
+ break;
+ case 'g':
+ ctxcanvas->debug = 1;
+ break;
+ case 'd':
+ sscanf(line, "%g", &num);
+ ctxcanvas->bbmargin = num;
+ 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, ctxcanvas->height);
+ _cdSwapDouble(ctxcanvas->xmin, ctxcanvas->ymin);
+ _cdSwapDouble(ctxcanvas->xmax, ctxcanvas->ymax);
+ }
+
+ init_ps(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->cxPutImageRectRGB = cdputimagerectrgb;
+ canvas->cxPutImageRectMap = cdputimagerectmap;
+ canvas->cxFLine = cdfline;
+ canvas->cxFPoly = cdfpoly;
+ canvas->cxFRect = cdfrect;
+ canvas->cxFBox = cdfbox;
+ canvas->cxFArc = cdfarc;
+ canvas->cxFSector = cdfsector;
+ canvas->cxFChord = cdfchord;
+ canvas->cxClip = cdclip;
+ 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;
+ canvas->cxDeactivate = cddeactivate;
+}
+
+static cdContext cdPSContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_PLAY | CD_CAP_PALETTE |
+ CD_CAP_REGION | CD_CAP_IMAGESRV |
+ CD_CAP_BACKGROUND | CD_CAP_BACKOPACITY | CD_CAP_WRITEMODE |
+ CD_CAP_FONTDIM | CD_CAP_TEXTSIZE |
+ CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB),
+ 0,
+ cdcreatecanvas,
+ cdinittable,
+ NULL,
+ NULL,
+};
+
+cdContext* cdContextPS(void)
+{
+ return &cdPSContext;
+}