diff options
Diffstat (limited to 'cd/src/drv')
-rwxr-xr-x | cd/src/drv/cd0emf.c | 8 | ||||
-rwxr-xr-x | cd/src/drv/cd0prn.c | 8 | ||||
-rwxr-xr-x | cd/src/drv/cdcgm.c | 14 | ||||
-rwxr-xr-x | cd/src/drv/cddebug.c | 125 | ||||
-rwxr-xr-x | cd/src/drv/cddgn.c | 13 | ||||
-rwxr-xr-x | cd/src/drv/cddxf.c | 206 | ||||
-rw-r--r-- | cd/src/drv/cdgl.c | 1559 | ||||
-rwxr-xr-x | cd/src/drv/cdirgb.c | 235 | ||||
-rwxr-xr-x | cd/src/drv/cdmf.c | 93 | ||||
-rwxr-xr-x | cd/src/drv/cdpdf.c | 399 | ||||
-rwxr-xr-x | cd/src/drv/cdpicture.c | 284 | ||||
-rwxr-xr-x | cd/src/drv/cdps.c | 486 | ||||
-rwxr-xr-x | cd/src/drv/cgm.c | 4 |
13 files changed, 3018 insertions, 416 deletions
diff --git a/cd/src/drv/cd0emf.c b/cd/src/drv/cd0emf.c index 13beb4c..7e05134 100755 --- a/cd/src/drv/cd0emf.c +++ b/cd/src/drv/cd0emf.c @@ -6,11 +6,19 @@ #include <stdlib.h> #include "cd.h" +#include "cd_private.h" #include "cdemf.h" cdContext* cdContextEMF(void) { + if (cdUseContextPlus(CD_QUERY)) + { + cdContext* ctx = cdGetContextPlus(CD_CTX_EMF); + if (ctx != NULL) + return ctx; + } + return NULL; } diff --git a/cd/src/drv/cd0prn.c b/cd/src/drv/cd0prn.c index 429a392..fa313d8 100755 --- a/cd/src/drv/cd0prn.c +++ b/cd/src/drv/cd0prn.c @@ -6,12 +6,20 @@ #include <stdlib.h> #include "cd.h" +#include "cd_private.h" #include "cdprint.h" cdContext* cdContextPrinter(void) { + if (cdUseContextPlus(CD_QUERY)) + { + cdContext* ctx = cdGetContextPlus(CD_CTX_PRINTER); + if (ctx != NULL) + return ctx; + } + return NULL; } diff --git a/cd/src/drv/cdcgm.c b/cd/src/drv/cdcgm.c index ab47c1e..19f6ad7 100755 --- a/cd/src/drv/cdcgm.c +++ b/cd/src/drv/cdcgm.c @@ -566,6 +566,12 @@ static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n) case CD_FILL: cgm_polygon( ctxcanvas->cgm, n, fpoly); break; + case CD_BEZIER: + cdfSimPolyBezier(ctxcanvas->canvas, (cdfPoint*)fpoly, n); + break; + case CD_PATH: + cdfSimPolyPath(ctxcanvas->canvas, (cdfPoint*)fpoly, n); + break; } free(fpoly); @@ -595,6 +601,12 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n) case CD_FILL: cgm_polygon( ctxcanvas->cgm, n, fpoly); break; + case CD_BEZIER: + cdfSimPolyBezier(ctxcanvas->canvas, poly, n); + break; + case CD_PATH: + cdfSimPolyPath(ctxcanvas->canvas, poly, n); + break; } } @@ -1122,7 +1134,7 @@ static cdContext cdCGMContext = CD_CAP_LINECAP | CD_CAP_LINEJOIN | CD_CAP_REGION | CD_CAP_CHORD | CD_CAP_FONTDIM | CD_CAP_TEXTSIZE | CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB | - CD_CAP_TEXTORIENTATION), + CD_CAP_TEXTORIENTATION | CD_CAP_PATH | CD_CAP_BEZIER), 0, cdcreatecanvas, cdinittable, diff --git a/cd/src/drv/cddebug.c b/cd/src/drv/cddebug.c index 23d8446..bd91209 100755 --- a/cd/src/drv/cddebug.c +++ b/cd/src/drv/cddebug.c @@ -27,6 +27,7 @@ #define CDDBG_BEGIN "Begin" #define CDDBG_VERTEX "Vertex" #define CDDBG_END "End" +#define CDDBG_PATHSET "PathSet" #define CDDBG_MARK "Mark" #define CDDBG_BACKOPACITY "BackOpacity" #define CDDBG_WRITEMODE "WriteMode" @@ -68,7 +69,6 @@ struct _cdCtxCanvas { cdCanvas* canvas; - char* filename; FILE* file; int last_line_style; int last_fill_mode; @@ -237,7 +237,8 @@ static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n) "CD_CLOSED_LINES", "CD_CLIP", "CD_BEZIER", - "CD_REGION" + "CD_REGION", + "CD_PATH" }; if (mode == CD_FILL && ctxcanvas->canvas->fill_mode != ctxcanvas->last_fill_mode) @@ -255,8 +256,61 @@ static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n) else fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_BEGIN, enum2str[mode]); - for(i = 0; i<n; i++) - fprintf(ctxcanvas->file, "%s(%d, %d)\n", CDDBG_VERTEX, poly[i].x, poly[i].y); + if (mode == CD_PATH) + { + const char* path2str[] = { + "CD_PATH_NEW", + "CD_PATH_MOVETO", + "CD_PATH_LINETO", + "CD_PATH_ARC", + "CD_PATH_CURVETO", + "CD_PATH_CLOSE", + "CD_PATH_FILL", + "CD_PATH_STROKE", + "CD_PATH_FILLSTROKE", + "CD_PATH_CLIP" + }; + int p; + + i = 0; + for (p=0; p<ctxcanvas->canvas->path_n; p++) + { + fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_PATHSET, path2str[ctxcanvas->canvas->path[p]]); + + switch(ctxcanvas->canvas->path[p]) + { + case CD_PATH_MOVETO: + case CD_PATH_LINETO: + if (i+1 > n) + { + fprintf(ctxcanvas->file, "ERROR: not enough points in path\n"); + return; + } + fprintf(ctxcanvas->file, "%s(%d, %d)\n", CDDBG_VERTEX, poly[i].x, poly[i].y); + i++; + break; + case CD_PATH_CURVETO: + case CD_PATH_ARC: + { + if (i+3 > n) + { + fprintf(ctxcanvas->file, "ERROR: not enough points in path\n"); + return; + } + fprintf(ctxcanvas->file, "%s(%d, %d)\n", CDDBG_VERTEX, poly[i].x, poly[i].y); + fprintf(ctxcanvas->file, "%s(%d, %d)\n", CDDBG_VERTEX, poly[i+1].x, poly[i+1].y); + fprintf(ctxcanvas->file, "%s(%d, %d)\n", CDDBG_VERTEX, poly[i+2].x, poly[i+2].y); + i += 3; + } + break; + } + } + } + else + { + for(i = 0; i<n; i++) + fprintf(ctxcanvas->file, "%s(%d, %d)\n", CDDBG_VERTEX, poly[i].x, poly[i].y); + } fprintf(ctxcanvas->file, "%s()\n", CDDBG_END); } @@ -285,8 +339,61 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n) fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_BEGIN, enum2str[mode]); - for(i = 0; i<n; i++) - fprintf(ctxcanvas->file, "%s(%g, %g)\n", CDDBG_FVERTEX, poly[i].x, poly[i].y); + if (mode == CD_PATH) + { + const char* path2str[] = { + "CD_PATH_NEW", + "CD_PATH_MOVETO", + "CD_PATH_LINETO", + "CD_PATH_ARC", + "CD_PATH_CURVETO", + "CD_PATH_CLOSE", + "CD_PATH_FILL", + "CD_PATH_STROKE", + "CD_PATH_FILLSTROKE", + "CD_PATH_CLIP" + }; + int p; + + i = 0; + for (p=0; p<ctxcanvas->canvas->path_n; p++) + { + fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_PATHSET, path2str[ctxcanvas->canvas->path[p]]); + + switch(ctxcanvas->canvas->path[p]) + { + case CD_PATH_MOVETO: + case CD_PATH_LINETO: + if (i+1 > n) + { + fprintf(ctxcanvas->file, "ERROR: not enough points in path\n"); + return; + } + fprintf(ctxcanvas->file, "%s(%g, %g)\n", CDDBG_VERTEX, poly[i].x, poly[i].y); + i++; + break; + case CD_PATH_CURVETO: + case CD_PATH_ARC: + { + if (i+3 > n) + { + fprintf(ctxcanvas->file, "ERROR: not enough points in path\n"); + return; + } + fprintf(ctxcanvas->file, "%s(%g, %g)\n", CDDBG_VERTEX, poly[i].x, poly[i].y); + fprintf(ctxcanvas->file, "%s(%g, %g)\n", CDDBG_VERTEX, poly[i+1].x, poly[i+1].y); + fprintf(ctxcanvas->file, "%s(%g, %g)\n", CDDBG_VERTEX, poly[i+2].x, poly[i+2].y); + i += 3; + } + break; + } + } + } + else + { + for(i = 0; i<n; i++) + fprintf(ctxcanvas->file, "%s(%g, %g)\n", CDDBG_FVERTEX, poly[i].x, poly[i].y); + } fprintf(ctxcanvas->file, "%s()\n", CDDBG_END); } @@ -601,7 +708,6 @@ static void cdgettextsize(cdCtxCanvas* ctxcanvas, const char *s, int len, int *w static void cdkillcanvas(cdCtxCanvas *ctxcanvas) { fprintf(ctxcanvas->file, "KillCanvas()\n"); - free(ctxcanvas->filename); fclose(ctxcanvas->file); memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); free(ctxcanvas); @@ -613,7 +719,6 @@ static void cdcreatecanvas(cdCanvas *canvas, void *data) char* strdata = (char*)data; double w_mm = INT_MAX*3.78, h_mm = INT_MAX*3.78, res = 3.78; cdCtxCanvas* ctxcanvas; - int size; strdata += cdGetFileName(strdata, filename); if (filename[0] == 0) @@ -631,10 +736,6 @@ static void cdcreatecanvas(cdCanvas *canvas, void *data) return; } - size = strlen(filename); - ctxcanvas->filename = malloc(size+1); - memcpy(ctxcanvas->filename, filename, size+1); - ctxcanvas->canvas = canvas; /* update canvas context */ diff --git a/cd/src/drv/cddgn.c b/cd/src/drv/cddgn.c index d7dd5f9..dd049fd 100755 --- a/cd/src/drv/cddgn.c +++ b/cd/src/drv/cddgn.c @@ -1066,6 +1066,17 @@ static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n) { short is_fill=0; + if (mode == CD_BEZIER) + { + cdSimPolyBezier(ctxcanvas->canvas, poly, n); + return; + } + if (mode == CD_PATH) + { + cdSimPolyPath(ctxcanvas->canvas, poly, n); + return; + } + if(mode == CD_FILL && ctxcanvas->fill_type == NOFILL) mode = CD_CLOSED_LINES; @@ -1667,7 +1678,7 @@ static void cdinittable(cdCanvas* canvas) static cdContext cdDGNContext = { - CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_PLAY | + CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_PLAY | CD_CAP_PATH | CD_CAP_BEZIER | CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB | CD_CAP_CLIPAREA | CD_CAP_CLIPPOLY | CD_CAP_RECT | CD_CAP_LINECAP | CD_CAP_LINEJOIN | CD_CAP_REGION | CD_CAP_CHORD | diff --git a/cd/src/drv/cddxf.c b/cd/src/drv/cddxf.c index db05978..c5d0df5 100755 --- a/cd/src/drv/cddxf.c +++ b/cd/src/drv/cddxf.c @@ -9,6 +9,7 @@ #include <string.h> #include <math.h> #include <limits.h> + #include "cd.h" #include "cd_private.h" #include "cddxf.h" @@ -182,6 +183,123 @@ static void writepolyf (cdCtxCanvas *ctxcanvas, cdfPoint *poly, int nv) /* write fprintf ( ctxcanvas->file, "SEQEND\n" ); } +static void writehatch (cdCtxCanvas *ctxcanvas, cdPoint *poly, int nv) /* write polygon */ +{ + int i; + + fprintf ( ctxcanvas->file, "0\n" ); + fprintf ( ctxcanvas->file, "HATCH\n" ); + fprintf ( ctxcanvas->file, "8\n" ); + fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->layer); /* current layer */ + fprintf ( ctxcanvas->file, "62\n" ); + fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->fgcolor ); + + fprintf ( ctxcanvas->file, "10\n" ); + fprintf ( ctxcanvas->file, "0.0\n" ); + fprintf ( ctxcanvas->file, "20\n" ); + fprintf ( ctxcanvas->file, "0.0\n" ); + fprintf ( ctxcanvas->file, "30\n" ); + fprintf ( ctxcanvas->file, "0.0\n" ); + + fprintf ( ctxcanvas->file, "210\n" ); + fprintf ( ctxcanvas->file, "0.0\n" ); + fprintf ( ctxcanvas->file, "220\n" ); + fprintf ( ctxcanvas->file, "0.0\n" ); + fprintf ( ctxcanvas->file, "230\n" ); + fprintf ( ctxcanvas->file, "1.0\n" ); + + fprintf ( ctxcanvas->file, "2\n" ); + fprintf ( ctxcanvas->file, "SOLID\n" ); + fprintf ( ctxcanvas->file, "70\n" ); + fprintf ( ctxcanvas->file, "1\n" ); + fprintf ( ctxcanvas->file, "71\n" ); + fprintf ( ctxcanvas->file, "0\n" ); + fprintf ( ctxcanvas->file, "91\n" ); + fprintf ( ctxcanvas->file, "1\n" ); + + fprintf ( ctxcanvas->file, "92\n" ); + fprintf ( ctxcanvas->file, "2\n" ); + fprintf ( ctxcanvas->file, "72\n" ); + fprintf ( ctxcanvas->file, "1\n" ); + + fprintf ( ctxcanvas->file, "73\n" ); + fprintf ( ctxcanvas->file, "1\n" ); + fprintf ( ctxcanvas->file, "93\n" ); /* entire polygon line width */ + fprintf ( ctxcanvas->file, "%d\n", nv ); + for ( i=0; i<nv; i++ ) + { + fprintf ( ctxcanvas->file, "10\n" ); + fprintf ( ctxcanvas->file, "%f\n", poly[i].x/ctxcanvas->canvas->xres ); + fprintf ( ctxcanvas->file, "20\n" ); + fprintf ( ctxcanvas->file, "%f\n", poly[i].y/ctxcanvas->canvas->xres ); + } + + fprintf ( ctxcanvas->file, "97\n" ); + fprintf ( ctxcanvas->file, "0\n" ); + fprintf ( ctxcanvas->file, "75\n" ); + fprintf ( ctxcanvas->file, "0\n" ); + fprintf ( ctxcanvas->file, "76\n" ); + fprintf ( ctxcanvas->file, "1\n" ); +} + +static void writehatchf (cdCtxCanvas *ctxcanvas, cdfPoint *poly, int nv) /* write polygon */ +{ + int i; + + fprintf ( ctxcanvas->file, "0\n" ); + fprintf ( ctxcanvas->file, "HATCH\n" ); + fprintf ( ctxcanvas->file, "8\n" ); + fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->layer); /* current layer */ + fprintf ( ctxcanvas->file, "62\n" ); + fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->fgcolor ); + + fprintf ( ctxcanvas->file, "10\n" ); + fprintf ( ctxcanvas->file, "0.0\n" ); + fprintf ( ctxcanvas->file, "20\n" ); + fprintf ( ctxcanvas->file, "0.0\n" ); + fprintf ( ctxcanvas->file, "30\n" ); + fprintf ( ctxcanvas->file, "0.0\n" ); + + fprintf ( ctxcanvas->file, "210\n" ); + fprintf ( ctxcanvas->file, "0.0\n" ); + fprintf ( ctxcanvas->file, "220\n" ); + fprintf ( ctxcanvas->file, "0.0\n" ); + fprintf ( ctxcanvas->file, "230\n" ); + fprintf ( ctxcanvas->file, "1.0\n" ); + + fprintf ( ctxcanvas->file, "2\n" ); + fprintf ( ctxcanvas->file, "SOLID\n" ); + fprintf ( ctxcanvas->file, "70\n" ); + fprintf ( ctxcanvas->file, "1\n" ); + fprintf ( ctxcanvas->file, "71\n" ); + fprintf ( ctxcanvas->file, "0\n" ); + fprintf ( ctxcanvas->file, "91\n" ); /* entire polygon line width */ + fprintf ( ctxcanvas->file, "1\n" ); + + fprintf ( ctxcanvas->file, "92\n" ); + fprintf ( ctxcanvas->file, "2\n" ); + fprintf ( ctxcanvas->file, "72\n" ); + fprintf ( ctxcanvas->file, "1\n" ); + + fprintf ( ctxcanvas->file, "73\n" ); + fprintf ( ctxcanvas->file, "1\n" ); + fprintf ( ctxcanvas->file, "93\n" ); /* entire polygon line width */ + fprintf ( ctxcanvas->file, "%d\n", nv ); + for ( i=0; i<nv; i++ ) + { + fprintf ( ctxcanvas->file, "10\n" ); + fprintf ( ctxcanvas->file, "%f\n", poly[i].x/ctxcanvas->canvas->xres ); + fprintf ( ctxcanvas->file, "20\n" ); + fprintf ( ctxcanvas->file, "%f\n", poly[i].y/ctxcanvas->canvas->xres ); + } + fprintf ( ctxcanvas->file, "97\n" ); + fprintf ( ctxcanvas->file, "0\n" ); + fprintf ( ctxcanvas->file, "75\n" ); + fprintf ( ctxcanvas->file, "0\n" ); + fprintf ( ctxcanvas->file, "76\n" ); + fprintf ( ctxcanvas->file, "1\n" ); +} + static void deflines (cdCtxCanvas *ctxcanvas) /* define lines */ { int i, j; @@ -323,6 +441,17 @@ static void cdflush (cdCtxCanvas *ctxcanvas) /*==========================================================================*/ static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n) { + if (mode == CD_BEZIER) + { + cdSimPolyBezier(ctxcanvas->canvas, poly, n); + return; + } + if (mode == CD_PATH) + { + cdSimPolyPath(ctxcanvas->canvas, poly, n); + return; + } + if (mode == CD_CLOSED_LINES || mode == CD_FILL) { poly[n].x = poly[0].x; @@ -330,7 +459,10 @@ static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n) n++; } - writepoly (ctxcanvas, poly, n); /* write polygon */ + if( mode == CD_FILL ) + writehatch (ctxcanvas, poly, n); /* write fill area */ + else + writepoly (ctxcanvas, poly, n); /* write polygon */ } static void cdline (cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2) @@ -344,7 +476,7 @@ static void cdline (cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2) writepoly (ctxcanvas, line, 2); /* draw line as a polygon */ } -static void cdboxrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) { cdPoint rect[5]; /* uses new array of points to avoid */ @@ -361,8 +493,36 @@ static void cdboxrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int writepoly (ctxcanvas, rect, 5); /* draw box as a polygon */ } +static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + cdPoint rect[5]; /* uses new array of points to avoid */ + + rect[0].x = xmin; + rect[0].y = ymin; + rect[1].x = xmin; + rect[1].y = ymax; + rect[2].x = xmax; /* box edges */ + rect[2].y = ymax; + rect[3].x = xmax; + rect[3].y = ymin; + rect[4].x = xmin; + rect[4].y = ymin; + writehatch (ctxcanvas, rect, 5); /* write fill area */ +} + static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n) { + if (mode == CD_BEZIER) + { + cdfSimPolyBezier(ctxcanvas->canvas, poly, n); + return; + } + if (mode == CD_PATH) + { + cdfSimPolyPath(ctxcanvas->canvas, poly, n); + return; + } + if (mode == CD_CLOSED_LINES || mode == CD_FILL) { poly[n].x = poly[0].x; @@ -370,7 +530,10 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n) n++; } - writepolyf (ctxcanvas, poly, n); /* write polygon */ + if( mode == CD_FILL ) + writehatchf (ctxcanvas, poly, n); /* write fill area */ + else + writepolyf (ctxcanvas, poly, n); /* write polygon */ } static void cdfline (cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2) @@ -384,7 +547,7 @@ static void cdfline (cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, do writepolyf (ctxcanvas, line, 2); /* draw line as a polygon */ } -static void cdfboxrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) { cdfPoint rect[5]; /* uses new array of points to avoid */ @@ -401,6 +564,23 @@ static void cdfboxrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double writepolyf (ctxcanvas, rect, 5); /* draw box as a polygon */ } +static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ + cdfPoint rect[5]; /* uses new array of points to avoid */ + + rect[0].x = xmin; + rect[0].y = ymin; + rect[1].x = xmin; + rect[1].y = ymax; + rect[2].x = xmax; /* box edges */ + rect[2].y = ymax; + rect[3].x = xmax; + rect[3].y = ymin; + rect[4].x = xmin; + rect[4].y = ymin; + writehatchf (ctxcanvas, rect, 5); /* write fill area */ +} + /*--------------------------------------------------------------------------*/ /* gives radius of the circle most resembling elliptic arc at angle t */ /*--------------------------------------------------------------------------*/ @@ -503,6 +683,7 @@ static void cdarc (cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double bulge = calc_bulge (a, b, t, t+seg_angle); /* and t+seg_angle and write */ writevertex (ctxcanvas, xc, yc, a, b, t, bulge); /* vertex at t */ } + writevertex (ctxcanvas, xc, yc, a, b, t2, 0); /* bulge of last vertex is useless */ fprintf ( ctxcanvas->file, "0\n" ); @@ -551,12 +732,15 @@ static void cdsector (cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, doub if ((a2-a1) != 360) writevertex (ctxcanvas, xc, yc, 0, 0, 0, 0); /* center */ + for (i=0, t=t1; i<nseg; i++, t+=seg_angle) { /* calculate bulge between t */ bulge = calc_bulge (a, b, t, t+seg_angle); /* and t+seg_angle and write */ writevertex (ctxcanvas, xc, yc, a, b, t, bulge); /* vertex at t */ } + writevertex (ctxcanvas, xc, yc, a, b, t2, 0); /* bulge of last vertex is useless */ + if ((a2-a1) != 360) writevertex (ctxcanvas, xc, yc, 0, 0, 0, 0); /* center */ @@ -1066,6 +1250,10 @@ static void cdcreatecanvas(cdCanvas* canvas, void *data) fprintf (ctxcanvas->file, "SECTION\n"); /* header maker */ fprintf (ctxcanvas->file, "2\n"); fprintf (ctxcanvas->file, "HEADER\n"); + fprintf (ctxcanvas->file, " 9\n"); + fprintf (ctxcanvas->file, "$ACADVER\n"); + fprintf (ctxcanvas->file, " 1\n"); + fprintf (ctxcanvas->file, "AC1006\n"); /* AutoCad R10 */ fprintf (ctxcanvas->file, "9\n"); fprintf (ctxcanvas->file, "$LIMCHECK\n"); fprintf (ctxcanvas->file, "70\n"); @@ -1142,12 +1330,12 @@ static void cdinittable(cdCanvas* canvas) canvas->cxPixel = cdpixel; canvas->cxLine = cdline; canvas->cxPoly = cdpoly; - canvas->cxRect = cdboxrect; - canvas->cxBox = cdboxrect; + canvas->cxRect = cdrect; + canvas->cxBox = cdbox; canvas->cxFLine = cdfline; canvas->cxFPoly = cdfpoly; - canvas->cxFRect = cdfboxrect; - canvas->cxFBox = cdfboxrect; + canvas->cxFRect = cdfrect; + canvas->cxFBox = cdfbox; canvas->cxArc = cdarc; canvas->cxSector = cdsector; canvas->cxText = cdtext; @@ -1169,7 +1357,7 @@ static void cdinittable(cdCanvas* canvas) static cdContext cdDXFContext = { CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_PLAY | CD_CAP_PALETTE | - CD_CAP_CLIPAREA | CD_CAP_CLIPPOLY | + CD_CAP_CLIPAREA | CD_CAP_CLIPPOLY | CD_CAP_PATH | CD_CAP_BEZIER | CD_CAP_LINECAP | CD_CAP_LINEJOIN | CD_CAP_REGION | CD_CAP_CHORD | CD_CAP_IMAGERGB | CD_CAP_IMAGEMAP | CD_CAP_IMAGESRV | CD_CAP_BACKGROUND | CD_CAP_BACKOPACITY | CD_CAP_WRITEMODE | diff --git a/cd/src/drv/cdgl.c b/cd/src/drv/cdgl.c new file mode 100644 index 0000000..4357e5a --- /dev/null +++ b/cd/src/drv/cdgl.c @@ -0,0 +1,1559 @@ +/** \file + * \brief OpenGL Base Driver + * + * See Copyright Notice in cd.h + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#ifdef WIN32 +#include <windows.h> +#else +#include <iconv.h> +#endif + +#include <GL/gl.h> + +#include <FTGL/ftgl.h> + +#include "cd.h" +#include "cd_private.h" +#include "cdgl.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#define NUM_HATCHES 6 +#define HATCH_WIDTH 8 +#define HATCH_HEIGHT 8 + +/* +** 6 predefined patterns to be accessed through cdHatch( +CD_HORIZONTAL | CD_VERTICAL | CD_FDIAGONAL | CD_BDIAGONAL | +CD_CROSS | CD_DIAGCROSS) + +*/ +static char hatches[NUM_HATCHES][8] = { + {0x00,0x00,0xFF,0x00,0x00,0x00,0xFF,0x00}, /* HORIZONTAL */ + {0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22}, /* VERTICAL */ + {0x08,0x10,0x20,0x40,0x80,0x01,0x02,0x04}, /* FDIAGONAL */ + {0x10,0x08,0x04,0x02,0x01,0x80,0x40,0x20}, /* BDIAGONAL */ + {0x22,0x22,0xFF,0x22,0x22,0x22,0xFF,0x22}, /* CROSS */ + {0x18,0x18,0x24,0x42,0x81,0x81,0x42,0x24} /* DIAGCROSS */ +}; + +struct _cdCtxImage +{ + unsigned int w, h, depth; + GLubyte* img; +}; + +struct _cdCtxCanvas +{ + cdCanvas* canvas; + + FTGLfont *font; + + char* glLastConvertUTF8; + + float rotate_angle; + int rotate_center_x; + int rotate_center_y; + + int poly_holes[500]; + int holes; +}; + +/******************************************************/ + +static char* cdglStrConvertToUTF8(cdCtxCanvas *ctxcanvas, const char* str, int len) +{ + if (ctxcanvas->glLastConvertUTF8) + free(ctxcanvas->glLastConvertUTF8); + +#ifdef WIN32 + { + wchar_t* toUnicode; + int wlen = MultiByteToWideChar(CP_ACP, 0, str, len, NULL, 0); + if(!wlen) + return (char*)str; + + toUnicode = (wchar_t*)calloc((wlen+1), sizeof(wchar_t)); + MultiByteToWideChar(CP_ACP, 0, str, len, toUnicode, wlen); + toUnicode[wlen] = 0; + + len = WideCharToMultiByte(CP_UTF8, 0, toUnicode, wlen, NULL, 0, NULL, NULL); + if(!len) + return (char*)str; + + ctxcanvas->glLastConvertUTF8 = (char*)calloc((len+1), sizeof(char)); + WideCharToMultiByte(CP_UTF8, 0, toUnicode, wlen, ctxcanvas->glLastConvertUTF8, len, NULL, NULL); + ctxcanvas->glLastConvertUTF8[len] = 0; + + free(toUnicode); + } +#else + { + /* Based on http://www.lemoda.net/c/iconv-example/iconv-example.html + Last access: June 15th, 2010. */ + iconv_t cd; + size_t ulen = (size_t)len; + size_t utf8len = ulen*2; + char* utf8 = calloc(utf8len, 1); + + cd = iconv_open("UTF-8", "ISO-8859-1"); + if(cd == (iconv_t)-1) + return (char*)str; + + ctxcanvas->glLastConvertUTF8 = utf8; + iconv(cd, (char**)&str, &ulen, &utf8, &utf8len); + + iconv_close(cd); + } +#endif + + return ctxcanvas->glLastConvertUTF8; +} + +/******************************************************/ + +static void cdkillcanvas(cdCtxCanvas *ctxcanvas) +{ + if(ctxcanvas->font) + ftglDestroyFont(ctxcanvas->font); + + if (ctxcanvas->glLastConvertUTF8) + free(ctxcanvas->glLastConvertUTF8); + + free(ctxcanvas); +} + +/******************************************************/ + +static void cdflush(cdCtxCanvas *ctxcanvas) +{ + glFlush(); + (void)ctxcanvas; +} + +/******************************************************/ + +static int cdclip(cdCtxCanvas *ctxcanvas, int clip_mode) +{ + switch (clip_mode) + { + case CD_CLIPOFF: + if(glIsEnabled(GL_SCISSOR_TEST)) + glDisable(GL_SCISSOR_TEST); + break; + case CD_CLIPAREA: + { + glEnable(GL_SCISSOR_TEST); + glScissor(ctxcanvas->canvas->clip_rect.xmin, ctxcanvas->canvas->clip_rect.ymin, + (ctxcanvas->canvas->clip_rect.xmax - ctxcanvas->canvas->clip_rect.xmin), + (ctxcanvas->canvas->clip_rect.ymax - ctxcanvas->canvas->clip_rect.ymin)); + break; + } + case CD_CLIPPOLYGON: + break; + case CD_CLIPREGION: + break; + } + + return clip_mode; +} + +static void cdfcliparea(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ + if (ctxcanvas->canvas->clip_mode == CD_CLIPAREA) + { + ctxcanvas->canvas->clip_rect.xmin = (int)xmin; + ctxcanvas->canvas->clip_rect.ymin = (int)ymin; + ctxcanvas->canvas->clip_rect.xmax = (int)xmax; + ctxcanvas->canvas->clip_rect.ymax = (int)ymax; + cdclip(ctxcanvas, CD_CLIPAREA); + } +} + +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 cdwritemode(cdCtxCanvas *ctxcanvas, int write_mode) +{ + switch (write_mode) + { + case CD_REPLACE: + if(glIsEnabled(GL_COLOR_LOGIC_OP)) + glDisable(GL_COLOR_LOGIC_OP); + break; + case CD_XOR: + glEnable(GL_COLOR_LOGIC_OP); + glLogicOp(GL_XOR); + break; + case CD_NOT_XOR: + glEnable(GL_COLOR_LOGIC_OP); + glLogicOp(GL_EQUIV); + break; + } + + (void)ctxcanvas; + return write_mode; +} + +static int cdhatch(cdCtxCanvas *ctxcanvas, int hatch_style) +{ + GLubyte pattern[128]; + int x, y, pos = 0; + + glEnable(GL_POLYGON_STIPPLE); + + for (y = 0; y < 128; y+=8) + { + for (x = 0; x < 8; x++) + pattern[x+y] = hatches[hatch_style][pos]; + pos++; + + if(pos > 7) /* repeat the pattern */ + pos = 0; + } + glPolygonStipple(pattern); + + (void)ctxcanvas; + return hatch_style; +} + +static int cdinteriorstyle(cdCtxCanvas *ctxcanvas, int style) +{ + switch (style) + { + case CD_HOLLOW: + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + break; + case CD_SOLID: + case CD_HATCH : + case CD_STIPPLE: + case CD_PATTERN: + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + break; + } + + switch (style) + { + case CD_STIPPLE: + case CD_PATTERN: + case CD_HOLLOW: + case CD_SOLID: + if(glIsEnabled(GL_POLYGON_STIPPLE)) + glDisable(GL_POLYGON_STIPPLE); + break; + case CD_HATCH: + cdhatch(ctxcanvas, ctxcanvas->canvas->hatch_style); + break; + } + + return style; +} + +static void cdpattern(cdCtxCanvas *ctxcanvas, int n, int m, const long int *pattern) +{ + (void)pattern; + (void)m; + (void)n; + cdinteriorstyle(ctxcanvas, CD_SOLID); +} + +static void cdstipple(cdCtxCanvas *ctxcanvas, int n, int m, const unsigned char *stipple) +{ + (void)stipple; + (void)m; + (void)n; + cdinteriorstyle(ctxcanvas, CD_SOLID); +} + +static int cdlinestyle(cdCtxCanvas *ctxcanvas, int style) +{ + switch (style) + { + case CD_CONTINUOUS: + if(glIsEnabled(GL_LINE_STIPPLE)) + glDisable(GL_LINE_STIPPLE); + return style; + break; + case CD_DASHED: + case CD_DOTTED: + case CD_DASH_DOT: + case CD_DASH_DOT_DOT: + case CD_CUSTOM: + glEnable(GL_LINE_STIPPLE); + break; + } + + switch (style) + { + case CD_DASHED: + glLineStipple(1, 0x3F); + break; + case CD_DOTTED: + glLineStipple(1, 0x33); + break; + case CD_DASH_DOT: + glLineStipple(1, 0x33F); + break; + case CD_DASH_DOT_DOT: + glLineStipple(1, 0x333F); + break; + case CD_CUSTOM: + /* style patterns more than 16 bits are not drawn completely */ + glLineStipple(1, (GLushort)*ctxcanvas->canvas->line_dashes); + break; + } + + return style; +} + +static int cdlinewidth(cdCtxCanvas *ctxcanvas, int width) +{ + if (width == 0) + width = 1; + + glLineWidth((GLfloat)width); + + (void)ctxcanvas; + return width; +} + +/***********************************************************************************/ +/* Functions to get the font name path */ +/* Base source = https://www.h3dapi.org:8090/H3DAPI/trunk/H3DAPI/src/FontStyle.cpp */ +/***********************************************************************************/ +#ifdef WIN32 +static LONG cdglWGetNextNameValue(HKEY key, LPCTSTR subkey, LPTSTR szName, LPTSTR szData) +{ + static HKEY hkey = NULL; + static DWORD dwIndex = 0; + LONG retval; + + if (subkey == NULL && szName == NULL && szData == NULL) + { + if (hkey) + RegCloseKey(hkey); + + hkey = NULL; + dwIndex = 0; + return ERROR_SUCCESS; + } + + if (subkey && subkey[0] != 0) + { + retval = RegOpenKeyEx(key, subkey, 0, KEY_READ, &hkey); + if (retval != ERROR_SUCCESS) + return retval; + + dwIndex = 0; + } + else + dwIndex++; + + *szName = 0; + *szData = 0; + + { + char szValueName[MAX_PATH]; + DWORD dwValueNameSize = sizeof(szValueName)-1; + BYTE szValueData[MAX_PATH]; + DWORD dwValueDataSize = sizeof(szValueData)-1; + DWORD dwType = 0; + + retval = RegEnumValue(hkey, dwIndex, szValueName, &dwValueNameSize, NULL, &dwType, szValueData, &dwValueDataSize); + if (retval == ERROR_SUCCESS) + { + lstrcpy(szName, (char *)szValueName); + lstrcpy(szData, (char *)szValueData); + } + } + + return retval; +} + +static int sReadStringKey(HKEY base_key, char* key_name, char* value_name, char* value) +{ + HKEY key; + DWORD max_size = 512; + + if (RegOpenKeyEx(base_key, key_name, 0, KEY_READ, &key) != ERROR_SUCCESS) + return 0; + + if (RegQueryValueEx(key, value_name, NULL, NULL, (LPBYTE)value, &max_size) != ERROR_SUCCESS) + { + RegCloseKey(key); + return 0; + } + + RegCloseKey(key); + return 1; +} + +static char* sGetFontDir(void) +{ + static char font_dir[1024]; + if (!sReadStringKey(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Fonts", font_dir)) + return ""; + else + return font_dir; +} + +static int sGetFontFileName(const char *font_name, int bold, int italic, char* fileName) +{ + TCHAR szName[2 * MAX_PATH]; + TCHAR szData[2 * MAX_PATH]; + LPCTSTR strFont = "Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"; + char localFontName[256]; + int bResult = 0; + + if (cdStrEqualNoCase(font_name, "Courier") || cdStrEqualNoCase(font_name, "Monospace")) + font_name = "Courier New"; + else if (cdStrEqualNoCase(font_name, "Times") || cdStrEqualNoCase(font_name, "Serif")) + font_name = "Times New Roman"; + else if (cdStrEqualNoCase(font_name, "Helvetica") || cdStrEqualNoCase(font_name, "Sans")) + font_name = "Arial"; + + strcpy(localFontName, font_name); + + if (bold) + strcat(localFontName, " Bold"); + + if (italic) + strcat(localFontName, " Italic"); + + while (cdglWGetNextNameValue(HKEY_LOCAL_MACHINE, strFont, szName, szData) == ERROR_SUCCESS) + { + if (cdStrEqualNoCasePartial(szName, localFontName)) + { + //"%s/%s.ttf" + sprintf(fileName, "%s\\%s", sGetFontDir(), szData); + bResult = 1; + break; + } + strFont = NULL; + } + + /* close the registry key */ + cdglWGetNextNameValue(HKEY_LOCAL_MACHINE, NULL, NULL, NULL); + + return bResult; +} +#else +#ifndef NO_FONTCONFIG +#include <fontconfig/fontconfig.h> + +static int sGetFontFileName(const char *font_name, int bold, int italic, char* fileName) +{ + char styles[4][20]; + int style_size; + FcObjectSet *os = 0; + FcFontSet *fs; + FcPattern *pat; + int bResult = 0; + + if (cdStrEqualNoCase(font_name, "Courier") || cdStrEqualNoCase(font_name, "Courier New") || cdStrEqualNoCase(font_name, "Monospace")) + font_name = "freemono"; + else if (cdStrEqualNoCase(font_name, "Times") || cdStrEqualNoCase(font_name, "Times New Roman")|| cdStrEqualNoCase(font_name, "Serif")) + font_name = "freeserif"; + else if (cdStrEqualNoCase(font_name, "Helvetica") || cdStrEqualNoCase(font_name, "Arial") || cdStrEqualNoCase(font_name, "Sans")) + font_name = "freesans"; + + if( bold && italic ) + { + strcpy(styles[0], "BoldItalic"); + strcpy(styles[1], "Bold Italic"); + strcpy(styles[2], "Bold Oblique"); + strcpy(styles[3], "BoldOblique"); + style_size = 4; + } + else if( bold ) + { + strcpy(styles[0], "Bold"); + style_size = 1; + } + else if( italic ) + { + strcpy(styles[0], "Italic"); + strcpy(styles[1], "Oblique"); + style_size = 2; + } + else + { + strcpy(styles[0], "Regular"); + strcpy(styles[1], "Normal"); + strcpy(styles[2], "Medium"); + style_size = 3; + } + + pat = FcPatternCreate(); + os = FcObjectSetBuild(FC_FAMILY, FC_FILE, FC_STYLE, NULL); + fs = FcFontList(NULL, pat, os); + if (pat) + FcPatternDestroy(pat); + + if(fs) + { + int j, s; + + for (j = 0; j < fs->nfont; j++) + { + FcChar8 *file; + FcChar8 *style; + FcChar8 *family; + + FcPatternGetString(fs->fonts[j], FC_FILE, 0, &file); + FcPatternGetString(fs->fonts[j], FC_STYLE, 0, &style ); + FcPatternGetString(fs->fonts[j], FC_FAMILY, 0, &family ); + + if (cdStrEqualNoCasePartial((char*)family, font_name)) + { + /* check if the font is of the correct type. */ + for(s = 0; s < style_size; s++ ) + { + if (cdStrEqualNoCase(styles[s], (char*)style)) + { + strcpy(fileName, (char*)file); + bResult = 1; + FcFontSetDestroy (fs); + return bResult; + } + + /* set value to use if no more correct font of same family is found. */ + strcpy(fileName, (char*)file); + bResult = 1; + } + } + } + FcFontSetDestroy (fs); + } + + return bResult; +} +#else +static int sGetFontFileName(const char *font_name, int bold, int italic, char* fileName) +{ + (void)font_name; + (void)bold; + (void)italic; + (void)fileName; + return 0; +} +#endif +#endif + +static int cdfont(cdCtxCanvas *ctxcanvas, const char *typeface, int style, int size) +{ + int is_italic = 0, is_bold = 0; /* default is CD_PLAIN */ + char strFontFileName[10240]; + + if (style & CD_BOLD) + is_bold = 1; + + if (style & CD_ITALIC) + is_italic = 1; + + /* search for the font in the system */ + if (!sGetFontFileName(typeface, is_bold, is_italic, strFontFileName)) + { + /* try typeface as a file title, compose to get a filename */ + if (!cdGetFontFileName(typeface, strFontFileName)) + { + /* try the same configuration of the simulation driver */ + static char * cd_ttf_font_style[4] = { + "", + "bd", + "i", + "bi"}; + char* face = NULL; + + /* check for the pre-defined names */ + if (cdStrEqualNoCase(typeface, "System")) + face = "cour"; + else if (cdStrEqualNoCase(typeface, "Courier")) + face = "cour"; + else if (cdStrEqualNoCase(typeface, "Times")) + face = "times"; + else if (cdStrEqualNoCase(typeface, "Helvetica")) + face = "arial"; + + if (face) + { + /* create a shortname for the file title */ + char shorname[100]; + sprintf(shorname, "%s%s", face, cd_ttf_font_style[style&3]); + if (!cdGetFontFileName(shorname, strFontFileName)) + strcpy(strFontFileName, typeface); /* try the typeface as file name */ + } + else + strcpy(strFontFileName, typeface); /* try the typeface as file name */ + } + } + + ctxcanvas->font = ftglCreateBufferFont(strFontFileName); + if (!ctxcanvas->font) + return 0; + + if (size < 0) + size = cdGetFontSizePoints(ctxcanvas->canvas, size); + + ftglSetFontFaceSize(ctxcanvas->font, size, 72); + ftglSetFontCharMap(ctxcanvas->font, ft_encoding_unicode); + + return 1; +} + +static void cdgetfontdim(cdCtxCanvas *ctxcanvas, int *max_width, int *height, int *ascent, int *descent) +{ + if(!ctxcanvas->font) + return; + + if (max_width) *max_width = (int)ftglGetFontAdvance(ctxcanvas->font, "W"); + if (height) *height = (int)ftglGetFontLineHeight(ctxcanvas->font); + if (ascent) *ascent = (int)ftglGetFontAscender(ctxcanvas->font); + if (descent) *descent = (int)ftglGetFontDescender(ctxcanvas->font); +} + +static long int cdforeground(cdCtxCanvas *ctxcanvas, long int color) +{ + unsigned char r, g, b; + (void)ctxcanvas; + + cdDecodeColor(color, &r, &g, &b); + glColor4ub(r, g, b, cdDecodeAlpha(color)); + + return color; +} + +static void cdclear(cdCtxCanvas* ctxcanvas) +{ + unsigned char r, g, b; + cdDecodeColor(ctxcanvas->canvas->background, &r, &g, &b); + glClearColor((GLclampf)((double)r/255.0), (GLclampf)((double)g/255.0), (GLclampf)((double)b/255.0), 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + +static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2) +{ + glBegin(GL_LINES); + glVertex2d(x1, y1); + glVertex2d(x2, y2); + glEnd(); + + (void)ctxcanvas; +} + +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) +{ + glBegin(GL_LINE_LOOP); + glVertex2d(xmin, ymin); + glVertex2d(xmax, ymin); + glVertex2d(xmax, ymax); + glVertex2d(xmin, ymax); + glEnd(); + + (void)ctxcanvas; +} + +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) +{ + if(ctxcanvas->canvas->back_opacity == CD_OPAQUE && glIsEnabled(GL_POLYGON_STIPPLE)) + { + /* draw twice, one with background color only, and one with foreground color */ + glDisable(GL_POLYGON_STIPPLE); + glColor4ub(cdRed(ctxcanvas->canvas->background), cdGreen(ctxcanvas->canvas->background), cdBlue(ctxcanvas->canvas->background), cdAlpha(ctxcanvas->canvas->background)); + + glBegin(GL_QUADS); + glVertex2d(xmin, ymin); + glVertex2d(xmax, ymin); + glVertex2d(xmax, ymax); + glVertex2d(xmin, ymax); + glEnd(); + + glColor4ub(cdRed(ctxcanvas->canvas->foreground), cdGreen(ctxcanvas->canvas->foreground), cdBlue(ctxcanvas->canvas->foreground), cdAlpha(ctxcanvas->canvas->foreground)); + glEnable(GL_POLYGON_STIPPLE); + } + + glBegin(GL_QUADS); + glVertex2d(xmin, ymin); + glVertex2d(xmax, ymin); + glVertex2d(xmax, ymax); + glVertex2d(xmin, ymax); + glEnd(); + + (void)ctxcanvas; +} + +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 cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *s, int len) +{ + int stipple = 0; + float bounds[6]; + int w, h, descent, baseline; + double x_origin = x; + double y_origin = y; + + if (!ctxcanvas->font) + return; + + s = cdglStrConvertToUTF8(ctxcanvas, s, len); + ftglGetFontBBox(ctxcanvas->font, s, len, bounds); + + descent = (int)ftglGetFontDescender(ctxcanvas->font); + w = (int)ceil(bounds[3] - bounds[0]); + h = (int)ceil(bounds[4] - bounds[1]); + baseline = (int)ftglGetFontLineHeight(ctxcanvas->font) - (int)ftglGetFontAscender(ctxcanvas->font); + + switch (ctxcanvas->canvas->text_alignment) + { + case CD_BASE_RIGHT: + case CD_NORTH_EAST: + case CD_EAST: + case CD_SOUTH_EAST: + x = x - w; + break; + case CD_BASE_CENTER: + case CD_CENTER: + case CD_NORTH: + case CD_SOUTH: + x = x - w/2; + break; + case CD_BASE_LEFT: + case CD_NORTH_WEST: + case CD_WEST: + case CD_SOUTH_WEST: + x = x; + break; + } + + switch (ctxcanvas->canvas->text_alignment) + { + case CD_BASE_LEFT: + case CD_BASE_CENTER: + case CD_BASE_RIGHT: + y = y; + break; + case CD_SOUTH_EAST: + case CD_SOUTH_WEST: + case CD_SOUTH: + y = y - descent; + break; + case CD_NORTH_EAST: + case CD_NORTH: + case CD_NORTH_WEST: + y = y - h/2 - baseline; + break; + case CD_CENTER: + case CD_EAST: + case CD_WEST: + y = y - baseline; + break; + } + + if (ctxcanvas->canvas->text_orientation != 0) + { + double angle = CD_DEG2RAD * ctxcanvas->canvas->text_orientation; + double cos_angle = cos(angle); + double sin_angle = sin(angle); + cdfRotatePoint(ctxcanvas->canvas, x, y, x_origin, y_origin, &x, &y, sin_angle, cos_angle); + } + + if(glIsEnabled(GL_POLYGON_STIPPLE)) + { + stipple = 1; + glDisable(GL_POLYGON_STIPPLE); + } + + glPushMatrix(); + glTranslated(x, y, 0.0); + glRotated(ctxcanvas->canvas->text_orientation, 0, 0, 1); + ftglRenderFont(ctxcanvas->font, s, FTGL_RENDER_ALL); + glPopMatrix(); + + if(stipple) + glEnable(GL_POLYGON_STIPPLE); +} + +static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *s, int len) +{ + cdftext(ctxcanvas, (double)x, (double)y, s, len); +} + +static void cdgettextsize(cdCtxCanvas *ctxcanvas, const char *s, int len, int *width, int *height) +{ + float bounds[6]; + + if (!ctxcanvas->font) + return; + + s = cdglStrConvertToUTF8(ctxcanvas, s, len); + ftglGetFontBBox(ctxcanvas->font, s, len, bounds); + + if (width) *width = (int)ceil(bounds[3] - bounds[0]); + if (height) *height = (int)ceil(bounds[4] - bounds[1]); +} + +static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n) +{ + int i; + + if (mode == CD_CLIP) + return; + + if (mode == CD_BEZIER) + { + int i, prec = 100; + float (*points)[3] = malloc(n * sizeof(*points)); + + for(i = 0; i < n; i++) + { + points[i][0] = (float)poly[i].x; + points[i][1] = (float)poly[i].y; + points[i][2] = 0; + } + + glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, n, &points[0][0]); + glEnable(GL_MAP1_VERTEX_3); + glMapGrid1f(prec, 0.0, 1.0); + glEvalMesh1(GL_LINE, 0, prec); + glDisable(GL_MAP1_VERTEX_3); + + free(points); + return; + } + + if (mode == CD_PATH) + { + cdSimPolyPath(ctxcanvas->canvas, poly, n); + return; + } + + switch (mode) + { + case CD_CLOSED_LINES : + glBegin(GL_LINE_LOOP); + break; + case CD_OPEN_LINES : + glBegin(GL_LINE_STRIP); + break; + case CD_FILL : + if(ctxcanvas->canvas->back_opacity == CD_OPAQUE && glIsEnabled(GL_POLYGON_STIPPLE)) + { + /* draw twice, one with background color only, and one with foreground color */ + glDisable(GL_POLYGON_STIPPLE); + glColor4ub(cdRed(ctxcanvas->canvas->background), cdGreen(ctxcanvas->canvas->background), cdBlue(ctxcanvas->canvas->background), cdAlpha(ctxcanvas->canvas->background)); + + glBegin(GL_POLYGON); + for(i = 0; i < n; i++) + glVertex2i(poly[i].x, poly[i].y); + glEnd(); + + glColor4ub(cdRed(ctxcanvas->canvas->foreground), cdGreen(ctxcanvas->canvas->foreground), cdBlue(ctxcanvas->canvas->foreground), cdAlpha(ctxcanvas->canvas->foreground)); + glEnable(GL_POLYGON_STIPPLE); + } + + glBegin(GL_POLYGON); + break; + } + + for(i = 0; i < n; i++) + glVertex2i(poly[i].x, poly[i].y); + glEnd(); + + (void)ctxcanvas; +} + +static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n) +{ + int i; + + if (mode == CD_CLIP) + return; + + if (mode == CD_BEZIER) + { + int i, prec = 100; + double (*points)[3] = malloc(n * sizeof(*points)); + + for(i = 0; i < n; i++) + { + points[i][0] = poly[i].x; + points[i][1] = poly[i].y; + points[i][2] = 0; + } + + glMap1d(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, n, &points[0][0]); + glEnable(GL_MAP1_VERTEX_3); + glMapGrid1d(prec, 0.0, 1.0); + glEvalMesh1(GL_LINE, 0, prec); + glDisable(GL_MAP1_VERTEX_3); + + free(points); + return; + } + + if (mode == CD_PATH) + { + cdfSimPolyPath(ctxcanvas->canvas, poly, n); + return; + } + + switch (mode) + { + case CD_CLOSED_LINES : + glBegin(GL_LINE_LOOP); + break; + case CD_OPEN_LINES : + glBegin(GL_LINE_STRIP); + break; + case CD_FILL : + if(ctxcanvas->canvas->back_opacity == CD_OPAQUE && glIsEnabled(GL_POLYGON_STIPPLE)) + { + glDisable(GL_POLYGON_STIPPLE); + glColor4ub(cdRed(ctxcanvas->canvas->background), cdGreen(ctxcanvas->canvas->background), cdBlue(ctxcanvas->canvas->background), cdAlpha(ctxcanvas->canvas->background)); + + glBegin(GL_POLYGON); + for(i = 0; i < n; i++) + glVertex2d(poly[i].x, poly[i].y); + glEnd(); + + glColor4ub(cdRed(ctxcanvas->canvas->foreground), cdGreen(ctxcanvas->canvas->foreground), cdBlue(ctxcanvas->canvas->foreground), cdAlpha(ctxcanvas->canvas->foreground)); + glEnable(GL_POLYGON_STIPPLE); + } + + glBegin(GL_POLYGON); + break; + } + + for(i = 0; i < n; i++) + glVertex2d(poly[i].x, poly[i].y); + glEnd(); + + (void)ctxcanvas; +} + +/******************************************************/ + +static void cdglGetImageData(GLubyte* glImage, unsigned char *r, unsigned char *g, unsigned char *b, int w, int h) +{ + int y, x; + unsigned char *pixline_data; + int rowstride, channels = 3; + + rowstride = w * channels; + + /* planes are separated in image data */ + for (y = 0; y < h; y++) + { + int lineoffset = y * w; + pixline_data = (unsigned char*)glImage + y * rowstride; + for(x = 0; x < w; x++) + { + int pos = x*channels; + r[lineoffset+x] = pixline_data[pos]; + g[lineoffset+x] = pixline_data[pos+1]; + b[lineoffset+x] = pixline_data[pos+2]; + } + } +} + +static GLubyte* cdglCreateImageRGBA(int width, int height, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int image_width) +{ + GLubyte* pixline_data; + GLubyte* glImage; + int x, y; + int channels = a ? 4 : 3; + int rowstride = width * channels; + int lineoffset; + + glImage = (GLubyte*)malloc(rowstride * height); + + /* planes are separated in image data */ + for (y = 0; y < height; y++) + { + lineoffset = y * image_width; + pixline_data = glImage + y * rowstride; + + for(x=0;x<width;x++) + { + int pos = x*channels; + pixline_data[pos] = r[lineoffset+x]; + pixline_data[pos+1] = g[lineoffset+x]; + pixline_data[pos+2] = b[lineoffset+x]; + + if (a) + pixline_data[pos+3] = a[lineoffset+x]; + } + } + + return glImage; +} + +static GLubyte* cdglCreateImageMap(int width, int height, const long* colors, const unsigned char *map, int image_width) +{ + const GLubyte *line_data; + GLubyte *pixline_data; + GLubyte *glImage; + int x, y, channels = 3; + int rowstride = width * channels; + + glImage = (GLubyte*)malloc(rowstride * height); + + for (y = 0; y < height; y++) + { + pixline_data = glImage + y * rowstride; + line_data = map + y * image_width; + + for (x=0; x<width; x++) + { + GLubyte index = line_data[x]; + long c = colors[index]; + GLubyte *r = &pixline_data[channels*x], + *g = r+1, + *b = g+1; + + *r = cdRed(c); + *g = cdGreen(c); + *b = cdBlue(c); + } + } + + return glImage; +} + +static void cdgetimagergb(cdCtxCanvas *ctxcanvas, unsigned char *r, unsigned char *g, unsigned char *b, int x, int y, int w, int h) +{ + GLubyte* glImage = (GLubyte*)malloc((w*3)*h); /* each pixel uses 3 bytes (RGB) */ + + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + glReadPixels(x, y, w, h, GL_RGB, GL_UNSIGNED_BYTE, glImage); + if (!glImage) + return; + + cdglGetImageData(glImage, r, g, b, w, h); + + (void)ctxcanvas; + + free(glImage); +} + +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) +{ + /* Images are bitmaps, and cannot be directly rotated or scaled */ + GLubyte* glImage; + int rw = xmax-xmin+1; + int rh = ymax-ymin+1; + + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + + glImage = cdglCreateImageRGBA(rw, rh, r, g, b, NULL, iw); + if (!glImage) + return; + + /* adjusts when the initial position (x,y) are less than 0 */ + if(x < 0) + { + w -= x; + x = 0; + } + + if(y < 0) + { + h -= y; + y = 0; + } + + if (w != rw || w != rh) + glPixelZoom((GLfloat)w/rw, (GLfloat)h/rh); + + glRasterPos2i(x, y); + glDrawPixels(rw, rh, GL_RGB, GL_UNSIGNED_BYTE, glImage); + + (void)ih; + (void)ctxcanvas; + + free(glImage); +} + +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) +{ + /* Images are bitmaps, and cannot be directly rotated or scaled */ + int blend = 1; + GLubyte* glImage; + int rw = xmax-xmin+1; + int rh = ymax-ymin+1; + + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + + glImage = cdglCreateImageRGBA(rw, rh, r, g, b, a, iw); + if (!glImage) + return; + + /* adjusts when the initial position (x,y) are less than 0 */ + if(x < 0) + { + w -= x; + x = 0; + } + + if(y < 0) + { + h -= y; + y = 0; + } + + if (w != rw || h != rh) + glPixelZoom((GLfloat)w/rw, (GLfloat)h/rh); + + if (!glIsEnabled(GL_BLEND)) + { + blend = 0; + glEnable(GL_BLEND); + } + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glRasterPos2i(x, y); + glDrawPixels(rw, rh, GL_RGBA, GL_UNSIGNED_BYTE, glImage); + + if (!blend) + glDisable(GL_BLEND); + + (void)ih; + (void)ctxcanvas; + + free(glImage); +} + +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) +{ + /* Images are bitmaps, and cannot be directly rotated or scaled */ + GLubyte* glImage; + int rw = xmax-xmin+1; + int rh = ymax-ymin+1; + + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + + glImage = cdglCreateImageMap(rw, rh, colors, index, iw); + if (!glImage) + return; + + /* adjusts when the initial position (x,y) are less than 0 */ + if(x < 0) + { + w -= x; + x = 0; + } + + if(y < 0) + { + h -= y; + y = 0; + } + + if (w != rw || h != rh) + glPixelZoom((GLfloat)w/rw, (GLfloat)h/rh); + + glRasterPos2i(x, y); + glDrawPixels(rw, rh, GL_RGB, GL_UNSIGNED_BYTE, glImage); + + (void)ih; + (void)ctxcanvas; + + free(glImage); +} + +static void cdpixel(cdCtxCanvas *ctxcanvas, int x, int y, long int color) +{ + glColor4ub(cdRed(color), cdGreen(color), cdBlue(color), cdAlpha(color)); + + /* Draw pixel */ + glPointSize(1); + glBegin(GL_POINTS); + glVertex2i(x, y); + glEnd(); + + /* restore the foreground color */ + glColor4ub(cdRed(ctxcanvas->canvas->foreground), cdGreen(ctxcanvas->canvas->foreground), cdBlue(ctxcanvas->canvas->foreground), cdAlpha(ctxcanvas->canvas->foreground)); + + (void)ctxcanvas; +} + +static cdCtxImage *cdcreateimage (cdCtxCanvas *ctxcanvas, int w, int h) +{ + cdCtxImage *ctximage = (cdCtxImage *)malloc(sizeof(cdCtxImage)); + + ctximage->w = w; + ctximage->h = h; + ctximage->depth = ctxcanvas->canvas->bpp; + + ctximage->img = (GLubyte*)malloc(w*h*4); /* each pixel uses 4 bytes (RGBA) */ + + if (!ctximage->img) + { + free(ctximage); + return (void*)0; + } + + return (void*)ctximage; +} + +static void cdgetimage (cdCtxCanvas *ctxcanvas, cdCtxImage *ctximage, int x, int y) +{ + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + glReadPixels(x, y - ctximage->h+1, ctximage->w, ctximage->h, GL_RGBA, GL_UNSIGNED_BYTE, ctximage->img); + + (void)ctxcanvas; +} + +static void cdputimagerect (cdCtxCanvas *ctxcanvas, cdCtxImage *ctximage, int x, int y, int xmin, int xmax, int ymin, int ymax) +{ + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + glRasterPos2i(x, y); + glDrawPixels(xmax-xmin+1, ymax-ymin+1, GL_RGBA, GL_UNSIGNED_BYTE, ctximage->img); + + (void)ctxcanvas; +} + +static void cdkillimage (cdCtxImage *ctximage) +{ + free(ctximage->img); + free(ctximage); +} + +static void cdscrollarea (cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax, int dx, int dy) +{ + glRasterPos2i(xmin+dx, ymin+dy); + glCopyPixels(xmin, ymin, xmax-xmin+1, ymax-ymin+1, GL_RGBA); + + (void)ctxcanvas; +} + +static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix) +{ + if (matrix) + { + GLdouble transformMTX[4][4]; + + transformMTX[0][0] = matrix[0]; transformMTX[0][1] = matrix[1]; transformMTX[0][2] = 0.0; transformMTX[0][3] = 0.0; + transformMTX[1][0] = matrix[2]; transformMTX[1][1] = matrix[3]; transformMTX[1][2] = 0.0; transformMTX[1][3] = 0.0; + transformMTX[2][0] = 0.0; transformMTX[2][1] = 0.0; transformMTX[2][2] = 1.0; transformMTX[2][3] = 0.0; + transformMTX[3][0] = matrix[4]; transformMTX[3][1] = matrix[5]; transformMTX[3][2] = 0.0; transformMTX[3][3] = 1.0; + + glLoadIdentity(); + glMultMatrixd(&transformMTX[0][0]); + } + else + glLoadIdentity(); + + (void)ctxcanvas; +} + +/******************************************************************/ +static void set_alpha_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ + if (!data || data[0] == '0') + { + glDisable(GL_BLEND); + } + else + { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + (void)ctxcanvas; +} + +static char* get_alpha_attrib(cdCtxCanvas* ctxcanvas) +{ + (void)ctxcanvas; + + if (glIsEnabled(GL_BLEND)) + return "1"; + else + return "0"; +} + +static cdAttribute alpha_attrib = +{ + "ALPHA", + set_alpha_attrib, + get_alpha_attrib +}; + +static void set_aa_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ + if (!data || data[0] == '0') + { + glDisable(GL_POINT_SMOOTH); + glDisable(GL_LINE_SMOOTH); + glDisable(GL_POLYGON_SMOOTH); + } + else + { + glEnable(GL_POINT_SMOOTH); + glEnable(GL_LINE_SMOOTH); + glEnable(GL_POLYGON_SMOOTH); + + glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); + } + + (void)ctxcanvas; +} + +static char* get_aa_attrib(cdCtxCanvas* ctxcanvas) +{ + (void)ctxcanvas; + + if (glIsEnabled(GL_LINE_SMOOTH)) + return "1"; + else + return "0"; +} + +static cdAttribute aa_attrib = +{ + "ANTIALIAS", + set_aa_attrib, + get_aa_attrib +}; + +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_rotate_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ + if (data) + { + sscanf(data, "%g %d %d", &ctxcanvas->rotate_angle, + &ctxcanvas->rotate_center_x, + &ctxcanvas->rotate_center_y); + + cdCanvasTransformTranslate(ctxcanvas->canvas, ctxcanvas->rotate_center_x, ctxcanvas->rotate_center_y); + cdCanvasTransformRotate(ctxcanvas->canvas, ctxcanvas->rotate_angle); + cdCanvasTransformTranslate(ctxcanvas->canvas, -ctxcanvas->rotate_center_x, -ctxcanvas->rotate_center_y); + } + else + { + ctxcanvas->rotate_angle = 0; + ctxcanvas->rotate_center_x = 0; + ctxcanvas->rotate_center_y = 0; + + cdCanvasTransform(ctxcanvas->canvas, NULL); + } +} + +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_size_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ + if (data) + { + cdCanvas* canvas = ctxcanvas->canvas; + float res = (float)canvas->xres; + sscanf(data, "%dx%d %g", &canvas->w, &canvas->h, &res); + canvas->yres = canvas->xres = res; + canvas->w_mm = ((double)canvas->w) / canvas->xres; + canvas->h_mm = ((double)canvas->h) / canvas->yres; + } +} + +static cdAttribute size_attrib = +{ + "SIZE", + set_size_attrib, + NULL +}; + +static char* get_version_attrib(cdCtxCanvas* ctxcanvas) +{ + (void)ctxcanvas; + return (char*)glGetString(GL_VERSION); +} + +static cdAttribute version_attrib = +{ + "GLVERSION", + NULL, + get_version_attrib +}; + +static void cdcreatecanvas(cdCanvas* canvas, void *data) +{ + cdCtxCanvas* ctxcanvas; + int w = 0, h = 0; + float res = (float)3.78; + char* str_data = (char*)data; + + sscanf(str_data, "%dx%d %g", &w, &h, &res); + + if (w == 0 || h == 0) + return; + + ctxcanvas = (cdCtxCanvas *)malloc(sizeof(cdCtxCanvas)); + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + + canvas->xres = res; + canvas->yres = res; + + canvas->w_mm = ((double)canvas->w) / canvas->xres; + canvas->h_mm = ((double)canvas->h) / canvas->yres; + + ctxcanvas->canvas = canvas; + canvas->ctxcanvas = ctxcanvas; + + ctxcanvas->glLastConvertUTF8 = NULL; + + cdRegisterAttribute(canvas, &rotate_attrib); + cdRegisterAttribute(canvas, &version_attrib); + cdRegisterAttribute(canvas, &poly_attrib); + cdRegisterAttribute(canvas, &size_attrib); + cdRegisterAttribute(canvas, &alpha_attrib); + cdRegisterAttribute(canvas, &aa_attrib); + + cdCanvasSetAttribute(canvas, "ALPHA", "1"); + cdCanvasSetAttribute(canvas, "ANTIALIAS", "1"); +} + +static void cdinittable(cdCanvas* canvas) +{ + canvas->cxFlush = cdflush; + canvas->cxClear = cdclear; + + canvas->cxPixel = cdpixel; + canvas->cxLine = cdline; + canvas->cxPoly = cdpoly; + canvas->cxRect = cdrect; + canvas->cxBox = cdbox; + canvas->cxArc = cdSimArc; + canvas->cxSector = cdSimSector; + canvas->cxChord = cdSimChord; + + canvas->cxText = cdtext; + canvas->cxFont = cdfont; + canvas->cxGetFontDim = cdgetfontdim; + canvas->cxGetTextSize = cdgettextsize; + + canvas->cxClip = cdclip; + canvas->cxClipArea = cdcliparea; + canvas->cxWriteMode = cdwritemode; + canvas->cxLineStyle = cdlinestyle; + canvas->cxLineWidth = cdlinewidth; + canvas->cxInteriorStyle = cdinteriorstyle; + canvas->cxHatch = cdhatch; + canvas->cxStipple = cdstipple; + canvas->cxPattern = cdpattern; + canvas->cxForeground = cdforeground; + canvas->cxTransform = cdtransform; + + canvas->cxFLine = cdfline; + canvas->cxFPoly = cdfpoly; + canvas->cxFRect = cdfrect; + canvas->cxFBox = cdfbox; + canvas->cxFArc = cdfSimArc; + canvas->cxFSector = cdfSimSector; + canvas->cxFChord = cdfSimChord; + canvas->cxFText = cdftext; + canvas->cxFClipArea = cdfcliparea; + + canvas->cxScrollArea = cdscrollarea; + canvas->cxCreateImage = cdcreateimage; + canvas->cxGetImage = cdgetimage; + canvas->cxPutImageRect = cdputimagerect; + canvas->cxKillImage = cdkillimage; + + canvas->cxGetImageRGB = cdgetimagergb; + canvas->cxPutImageRectRGB = cdputimagerectrgb; + canvas->cxPutImageRectMap = cdputimagerectmap; + canvas->cxPutImageRectRGBA = cdputimagerectrgba; + + canvas->cxKillCanvas = cdkillcanvas; +} + +static cdContext cdGLContext = +{ + CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_PALETTE | CD_CAP_LINEJOIN | CD_CAP_LINECAP | + CD_CAP_REGION | CD_CAP_STIPPLE | CD_CAP_PATTERN), + 0, + cdcreatecanvas, + cdinittable, + NULL, + NULL, +}; + +cdContext* cdContextGL(void) +{ + return &cdGLContext; +} diff --git a/cd/src/drv/cdirgb.c b/cd/src/drv/cdirgb.c index 433a684..0c2913f 100755 --- a/cd/src/drv/cdirgb.c +++ b/cd/src/drv/cdirgb.c @@ -275,7 +275,7 @@ static void sCombineRGBALine(cdCtxCanvas* ctxcanvas, int offset, const unsigned } } -static void irgbSolidLine(cdCanvas* canvas, int xmin, int y, int xmax) +static void irgbSolidLine(cdCanvas* canvas, int xmin, int y, int xmax, long color) { int x; unsigned long offset = y * canvas->w; @@ -292,7 +292,7 @@ static void irgbSolidLine(cdCanvas* canvas, int xmin, int y, int xmax) xmax = (canvas->w-1); for (x = xmin; x <= xmax; x++) - sCombineRGBColor(canvas->ctxcanvas, offset + x, canvas->foreground); + sCombineRGBColor(canvas->ctxcanvas, offset + x, color); } static void irgbPatternLine(cdCanvas* canvas, int xmin, int xmax, int y, int pw, const long *pattern) @@ -506,7 +506,7 @@ static void irgbClipPoly(cdCtxCanvas* ctxcanvas, unsigned char* clip_region, cdP memcpy(t_poly, poly, sizeof(cdPoint)*n); poly = t_poly; - for(i = 0; i < n; i++) + for(i = 0; i < n; i++) /* must duplicate because clip poly is stored */ cdMatrixTransformPoint(canvas->matrix, poly[i].x, poly[i].y, &poly[i].x, &poly[i].y); } @@ -568,79 +568,6 @@ static void irgbClipPoly(cdCtxCanvas* ctxcanvas, unsigned char* clip_region, cdP irgPostProcessIntersect(ctxcanvas->clip_region, ctxcanvas->canvas->w * ctxcanvas->canvas->h); } -static void irgbClipElipse(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2, int sector) -{ - float c, s, sx, sy, x, y, prev_x, prev_y; - double da; - int i, p; - cdPoint* poly; - - /* number of segments of equivalent poligonal for a full ellipse */ - int n = simCalcEllipseNumSegments(ctxcanvas->canvas, xc, yc, width, height); - - /* number of segments for the arc */ - n = cdRound((fabs(angle2-angle1)*n)/360); - if (n < 1) n = 1; - - poly = (cdPoint*)malloc(sizeof(cdPoint)*(n+2+1)); /* n+1 points +1 center */ - - /* converts degrees into radians */ - angle1 *= CD_DEG2RAD; - angle2 *= CD_DEG2RAD; - - /* generates arc points at origin with axis x and y */ - - da = (angle2-angle1)/n; - c = (float)cos(da); - s = (float)sin(da); - sx = -(width*s)/height; - sy = (height*s)/width; - - x = xc + (width/2.0f)*(float)cos(angle1); - y = yc + (height/2.0f)*(float)sin(angle1); - poly[0].x = _cdRound(x); - poly[0].y = _cdRound(y); - prev_x = x; - prev_y = y; - p = 1; - - for (i = 1; i < n+1; i++) /* n+1 points */ - { - x = xc + c*(prev_x-xc) + sx*(prev_y-yc); - y = yc + sy*(prev_x-xc) + c*(prev_y-yc); - - poly[p].x = _cdRound(x); - poly[p].y = _cdRound(y); - - if (poly[p-1].x != poly[p].x || poly[p-1].y != poly[p].y) - p++; - - prev_x = x; - prev_y = y; - } - - if (poly[p-1].x != poly[0].x || poly[p-1].y != poly[0].y) - { - if (sector) /* cdSector */ - { - /* add center */ - poly[p].x = xc; - poly[p].y = yc; - } - else /* cdChord */ - { - /* add initial point */ - poly[p].x = poly[0].x; - poly[p].y = poly[0].y; - } - p++; - } - - irgbClipPoly(ctxcanvas, ctxcanvas->clip_region, poly, p, ctxcanvas->canvas->combine_mode); - - free(poly); -} - static void irgbClipBox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) { int combine_mode = ctxcanvas->canvas->combine_mode; @@ -858,39 +785,31 @@ static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax { if (ctxcanvas->canvas->new_region) { + /* matrix transformation is done inside irgbClip* if necessary */ irgbClipBox(ctxcanvas, xmin, xmax, ymin, ymax); return; } - cdboxSIM(ctxcanvas, xmin, xmax, ymin, ymax); -} - -static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) -{ - if (ctxcanvas->canvas->new_region) - { - irgbClipElipse(ctxcanvas, xc, yc, w, h, a1, a2, 1); - return; - } - - cdsectorSIM(ctxcanvas, xc, yc, w, h, a1, a2); + cdSimBox(ctxcanvas, xmin, xmax, ymin, ymax); } -static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) { if (ctxcanvas->canvas->new_region) { - irgbClipElipse(ctxcanvas, xc, yc, w, h, a1, a2, 0); + /* matrix transformation is done inside irgbClip* if necessary */ + irgbClipBox(ctxcanvas, _cdRound(xmin), _cdRound(xmax), _cdRound(ymin), _cdRound(ymax)); return; } - cdchordSIM(ctxcanvas, xc, yc, w, h, a1, a2); + cdfSimBox(ctxcanvas, xmin, xmax, ymin, ymax); } static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n) { if (ctxcanvas->canvas->new_region) { + /* matrix transformation is done inside irgbClip* if necessary */ irgbClipPoly(ctxcanvas, ctxcanvas->clip_region, poly, n, ctxcanvas->canvas->combine_mode); return; } @@ -898,11 +817,15 @@ static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n) if (mode == CD_CLIP) { /* set directly to clip */ - memset(ctxcanvas->clip, 1, ctxcanvas->canvas->w * ctxcanvas->canvas->h); /* CD_CLIPOFF */ + + /* CD_CLIPOFF */ + memset(ctxcanvas->clip, 1, ctxcanvas->canvas->w * ctxcanvas->canvas->h); + + /* matrix transformation is done inside irgbClip* if necessary */ irgbClipPoly(ctxcanvas, ctxcanvas->clip, poly, n, CD_UNION); } else - cdpolySIM(ctxcanvas, mode, poly, n); + cdSimPoly(ctxcanvas, mode, poly, n); } static void cdgetimagergb(cdCtxCanvas* ctxcanvas, unsigned char *r, unsigned char *g, unsigned char *b, int x, int y, int w, int h) @@ -952,20 +875,27 @@ static void cdgetimagergb(cdCtxCanvas* ctxcanvas, unsigned char *r, unsigned cha } } +static void sFixImageY(int *topdown, int *y, int *h) +{ + if (*h < 0) + { + *h = -(*h); + *y -= (*h - 1); /* y is at top-left, move it to bottom-left */ + *topdown = 1; /* image pointer will start at top-left */ + } + else + *topdown = 0; +} + static void cdputimagerectrgba_matrix(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 t_xmin, t_xmax, t_ymin, t_ymax, - t_x, t_y, img_topdown = 0, dst_offset; + t_x, t_y, topdown, dst_offset; float i_x, i_y, xfactor, yfactor; unsigned char sr, sg, sb, sa = 255; double inv_matrix[6]; - if (h < 0) - { - h = -h; - y -= (h - 1); /* y is at top-left, move it to bottom-left */ - img_topdown = 1; /* image pointer will start at top-left */ - } + sFixImageY(&topdown, &y, &h); /* calculate the destination limits */ cdImageRGBCalcDstLimits(ctxcanvas->canvas, x, y, w, h, &t_xmin, &t_xmax, &t_ymin, &t_ymax, NULL); @@ -984,7 +914,7 @@ static void cdputimagerectrgba_matrix(cdCtxCanvas* ctxcanvas, int iw, int ih, co if (i_x > xmin && i_y > ymin && i_x < xmax+1 && i_y < ymax+1) { - if (img_topdown) /* image is top-bottom */ + if (topdown) /* image is top-bottom */ i_y = ih-1 - i_y; if (t_x == 350 && t_y == 383) @@ -1007,17 +937,12 @@ static void cdputimagerectrgba_matrix(cdCtxCanvas* ctxcanvas, int iw, int ih, co static void cdputimagerectmap_matrix(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 t_xmin, t_xmax, t_ymin, t_ymax, - t_x, t_y, img_topdown = 0, dst_offset; + t_x, t_y, topdown, dst_offset; float i_x, i_y, xfactor, yfactor; unsigned char si; double inv_matrix[6]; - if (h < 0) - { - h = -h; - y -= (h - 1); /* y is at top-left, move it to bottom-left */ - img_topdown = 1; /* image pointer will start at top-left (undocumented feature) */ - } + sFixImageY(&topdown, &y, &h); /* calculate the destination limits */ cdImageRGBCalcDstLimits(ctxcanvas->canvas, x, y, w, h, &t_xmin, &t_xmax, &t_ymin, &t_ymax, NULL); @@ -1036,7 +961,7 @@ static void cdputimagerectmap_matrix(cdCtxCanvas* ctxcanvas, int iw, int ih, con if (i_x > xmin && i_y > ymin && i_x < xmax+1 && i_y < ymax+1) { - if (img_topdown) /* image is top-bottom */ + if (topdown) /* image is top-bottom */ i_y = ih-1 - i_y; si = cdZeroOrderInterpolation(iw, ih, index, i_x, i_y); @@ -1048,7 +973,7 @@ static void cdputimagerectmap_matrix(cdCtxCanvas* ctxcanvas, int iw, int ih, con 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 l, c, xsize, ysize, xpos, ypos, src_offset, dst_offset, rh, rw, img_topdown = 0; + int l, c, xsize, ysize, xpos, ypos, src_offset, dst_offset, rh, rw, topdown; const unsigned char *src_red, *src_green, *src_blue; if (ctxcanvas->canvas->use_matrix) @@ -1057,12 +982,7 @@ static void cdputimagerectrgb(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsi return; } - if (h < 0) - { - h = -h; - y -= (h - 1); /* y is at top-left, move it to bottom-left */ - img_topdown = 1; /* image pointer will start at top-left */ - } + sFixImageY(&topdown, &y, &h); /* verifica se esta dentro da area de desenho */ if (x > (ctxcanvas->canvas->w-1) || y > (ctxcanvas->canvas->h-1) || @@ -1090,7 +1010,7 @@ static void cdputimagerectrgb(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsi for(l = 0; l < ysize; l++) { /* ajusta posicao inicial em source */ - if (img_topdown) + if (topdown) src_offset = YTab[(ih - 1) - (l + (ypos - y))] * iw; else src_offset = YTab[l + (ypos - y)] * iw; @@ -1117,7 +1037,7 @@ static void cdputimagerectrgb(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsi dst_offset = xpos + ypos * ctxcanvas->canvas->w; /* ajusta posicao inicial em source */ - if (img_topdown) + if (topdown) src_offset = (xpos - x + xmin) + ((ih - 1) - (ypos - y + ymin)) * iw; else src_offset = (xpos - x + xmin) + (ypos - y + ymin) * iw; @@ -1132,7 +1052,7 @@ static void cdputimagerectrgb(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsi dst_offset += ctxcanvas->canvas->w; - if (img_topdown) + if (topdown) { r -= iw; g -= iw; @@ -1150,7 +1070,7 @@ static void cdputimagerectrgb(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsi 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 l, c, xsize, ysize, xpos, ypos, src_offset, dst_offset, rw, rh, img_topdown = 0; + int l, c, xsize, ysize, xpos, ypos, src_offset, dst_offset, rw, rh, topdown; const unsigned char *src_red, *src_green, *src_blue, *src_alpha; if (ctxcanvas->canvas->use_matrix) @@ -1159,12 +1079,7 @@ static void cdputimagerectrgba(cdCtxCanvas* ctxcanvas, int iw, int ih, const uns return; } - if (h < 0) - { - h = -h; - y -= (h - 1); /* y is at top-left, move it to bottom-left */ - img_topdown = 1; /* image pointer will start at top-left */ - } + sFixImageY(&topdown, &y, &h); /* verifica se esta dentro da area de desenho */ if (x > (ctxcanvas->canvas->w-1) || y > (ctxcanvas->canvas->h-1) || @@ -1192,7 +1107,7 @@ static void cdputimagerectrgba(cdCtxCanvas* ctxcanvas, int iw, int ih, const uns for(l = 0; l < ysize; l++) { /* ajusta posicao inicial em source */ - if (img_topdown) + if (topdown) src_offset = YTab[(ih - 1) - (l + (ypos - y))] * iw; else src_offset = YTab[l + (ypos - y)] * iw; @@ -1220,7 +1135,7 @@ static void cdputimagerectrgba(cdCtxCanvas* ctxcanvas, int iw, int ih, const uns dst_offset = xpos + ypos * ctxcanvas->canvas->w; /* ajusta posicao inicial em source */ - if (img_topdown) + if (topdown) src_offset = (xpos - x + xmin) + ((ih - 1) - (ypos - y + ymin)) * iw; else src_offset = (xpos - x + xmin) + (ypos - y + ymin) * iw; @@ -1236,7 +1151,7 @@ static void cdputimagerectrgba(cdCtxCanvas* ctxcanvas, int iw, int ih, const uns dst_offset += ctxcanvas->canvas->w; - if (img_topdown) + if (topdown) { r -= iw; g -= iw; @@ -1256,7 +1171,7 @@ static void cdputimagerectrgba(cdCtxCanvas* ctxcanvas, int iw, int ih, const uns 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 l, c, xsize, ysize, xpos, ypos, src_offset, dst_offset, rw, rh, pal_size, idx, img_topdown = 0; + int l, c, xsize, ysize, xpos, ypos, src_offset, dst_offset, rw, rh, idx, topdown; const unsigned char *src_index; if (ctxcanvas->canvas->use_matrix) @@ -1265,12 +1180,7 @@ static void cdputimagerectmap(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsi return; } - if (h < 0) - { - h = -h; - y -= (h - 1); /* y is at top-left, move it to bottom-left */ - img_topdown = 1; /* image pointer will start at top-left */ - } + sFixImageY(&topdown, &y, &h); /* verifica se esta dentro da area de desenho */ if (x > (ctxcanvas->canvas->w-1) || y > (ctxcanvas->canvas->h-1) || @@ -1286,22 +1196,6 @@ static void cdputimagerectmap(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsi rw = xmax-xmin+1; rh = ymax-ymin+1; - /* Como nao sabemos o tamanho da palette a priori, - teremos que ver qual o maior indice usado na imagem. */ - pal_size = 0; - - for (l=0; l<ih; l++) - { - for (c=0; c<iw; c++) - { - idx = index[l*iw + c]; - if (idx > pal_size) - pal_size = idx; - } - } - - pal_size++; - /* testa se tem que fazer zoom */ if (rw != w || rh != h) { @@ -1314,7 +1208,7 @@ static void cdputimagerectmap(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsi for(l = 0; l < ysize; l++) { /* ajusta posicao inicial em source */ - if (img_topdown) + if (topdown) src_offset = YTab[(ih - 1) - (l + (ypos - y))] * iw; else src_offset = YTab[l + (ypos - y)] * iw; @@ -1340,7 +1234,7 @@ static void cdputimagerectmap(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsi dst_offset = xpos + ypos * ctxcanvas->canvas->w; /* ajusta posicao inicial em source */ - if (img_topdown) + if (topdown) src_offset = (xpos - x + xmin) + ((ih - 1) - (ypos - y + ymin)) * iw; else src_offset = (xpos - x + xmin) + (ypos - y + ymin) * iw; @@ -1357,7 +1251,7 @@ static void cdputimagerectmap(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsi dst_offset += ctxcanvas->canvas->w; - if (img_topdown) + if (topdown) index -= iw; else index += iw; @@ -1696,6 +1590,7 @@ static void set_rotate_attrib(cdCtxCanvas* ctxcanvas, char* data) { if (data) { + /* use this configuration when there is NO native tranformation support */ sscanf(data, "%g %d %d", &ctxcanvas->rotate_angle, &ctxcanvas->rotate_center_x, &ctxcanvas->rotate_center_y); @@ -1859,15 +1754,23 @@ static void cdinittable(cdCanvas* canvas) canvas->cxClear = cdclear; canvas->cxPixel = cdpixel; - canvas->cxLine = cdlineSIM; - canvas->cxRect = cdrectSIM; + canvas->cxLine = cdSimLine; + canvas->cxRect = cdSimRect; canvas->cxBox = cdbox; - canvas->cxArc = cdarcSIM; - canvas->cxSector = cdsector; - canvas->cxChord = cdchord; + canvas->cxArc = cdSimArc; + canvas->cxSector = cdSimSector; + canvas->cxChord = cdSimChord; canvas->cxPoly = cdpoly; canvas->cxText = NULL; + canvas->cxFLine = cdfSimLine; + canvas->cxFRect = cdfSimRect; + canvas->cxFBox = cdfbox; + canvas->cxFArc = cdfSimArc; + canvas->cxFSector = cdfSimSector; + canvas->cxFChord = cdfSimChord; + canvas->cxFPoly = cdfSimPoly; + canvas->cxKillCanvas = cdkillcanvas; /* use simulation */ @@ -1885,9 +1788,9 @@ static void cdinittable(cdCanvas* canvas) static cdContext cdImageRGBContext = { - CD_CAP_ALL & ~(CD_CAP_FLUSH | CD_CAP_PLAY | CD_CAP_FPRIMTIVES | - CD_CAP_LINECAP | CD_CAP_LINEJOIN | CD_CAP_REGION | - CD_CAP_PALETTE | CD_CAP_TEXTORIENTATION), + CD_CAP_ALL & ~(CD_CAP_FLUSH | CD_CAP_PLAY | + CD_CAP_LINECAP | CD_CAP_LINEJOIN | + CD_CAP_PALETTE ), 0, cdcreatecanvas, cdinittable, @@ -2003,9 +1906,9 @@ static void cdinittableDB(cdCanvas* canvas) static cdContext cdDBufferRGBContext = { - CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_FPRIMTIVES | - CD_CAP_LINECAP | CD_CAP_LINEJOIN | CD_CAP_REGION | - CD_CAP_PALETTE | CD_CAP_TEXTORIENTATION), + CD_CAP_ALL & ~(CD_CAP_PLAY | + CD_CAP_LINECAP | CD_CAP_LINEJOIN | + CD_CAP_PALETTE ), 0, cdcreatecanvasDB, cdinittableDB, diff --git a/cd/src/drv/cdmf.c b/cd/src/drv/cdmf.c index 727fcac..ddb109c 100755 --- a/cd/src/drv/cdmf.c +++ b/cd/src/drv/cdmf.c @@ -96,7 +96,8 @@ enum CDMF_FCHORD, /* 72 */ CDMF_FCLIPAREA, /* 73 */ CDMF_FONT, /* 74 */ - CDMF_RESETMATRIX /* 75 */ + CDMF_RESETMATRIX, /* 75 */ + CDMF_PATHSET /* 76 */ }; struct _cdCtxCanvas @@ -242,8 +243,49 @@ static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n) fprintf(ctxcanvas->file, "%d %d\n", CDMF_BEGIN, mode); - for(i = 0; i<n; i++) - fprintf(ctxcanvas->file, "%d %d %d\n", CDMF_VERTEX, poly[i].x, poly[i].y); + if (mode == CD_PATH) + { + int p; + + i = 0; + for (p=0; p<ctxcanvas->canvas->path_n; p++) + { + fprintf(ctxcanvas->file, "%d %d\n", CDMF_PATHSET, ctxcanvas->canvas->path[p]); + + switch(ctxcanvas->canvas->path[p]) + { + case CD_PATH_MOVETO: + case CD_PATH_LINETO: + if (i+1 > n) + { + fprintf(ctxcanvas->file, "ERROR: not enough points in path\n"); + return; + } + fprintf(ctxcanvas->file, "%d %d %d\n", CDMF_VERTEX, poly[i].x, poly[i].y); + i++; + break; + case CD_PATH_CURVETO: + case CD_PATH_ARC: + { + if (i+3 > n) + { + fprintf(ctxcanvas->file, "ERROR: not enough points in path\n"); + return; + } + fprintf(ctxcanvas->file, "%d %d %d\n", CDMF_VERTEX, poly[i].x, poly[i].y); + fprintf(ctxcanvas->file, "%d %d %d\n", CDMF_VERTEX, poly[i+1].x, poly[i+1].y); + fprintf(ctxcanvas->file, "%d %d %d\n", CDMF_VERTEX, poly[i+2].x, poly[i+2].y); + i += 3; + } + break; + } + } + } + else + { + for(i = 0; i<n; i++) + fprintf(ctxcanvas->file, "%d %d %d\n", CDMF_VERTEX, poly[i].x, poly[i].y); + } fprintf(ctxcanvas->file, "%d\n", CDMF_END); } @@ -260,8 +302,49 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n) fprintf(ctxcanvas->file, "%d %d\n", CDMF_BEGIN, mode); - for(i = 0; i<n; i++) - fprintf(ctxcanvas->file, "%d %g %g\n", CDMF_FVERTEX, poly[i].x, poly[i].y); + if (mode == CD_PATH) + { + int p; + + i = 0; + for (p=0; p<ctxcanvas->canvas->path_n; p++) + { + fprintf(ctxcanvas->file, "%d %d\n", CDMF_PATHSET, ctxcanvas->canvas->path[p]); + + switch(ctxcanvas->canvas->path[p]) + { + case CD_PATH_MOVETO: + case CD_PATH_LINETO: + if (i+1 > n) + { + fprintf(ctxcanvas->file, "ERROR: not enough points in path\n"); + return; + } + fprintf(ctxcanvas->file, "%d %g %g\n", CDMF_FVERTEX, poly[i].x, poly[i].y); + i++; + break; + case CD_PATH_CURVETO: + case CD_PATH_ARC: + { + if (i+3 > n) + { + fprintf(ctxcanvas->file, "ERROR: not enough points in path\n"); + return; + } + fprintf(ctxcanvas->file, "%d %g %g\n", CDMF_FVERTEX, poly[i].x, poly[i].y); + fprintf(ctxcanvas->file, "%d %g %g\n", CDMF_FVERTEX, poly[i+1].x, poly[i+1].y); + fprintf(ctxcanvas->file, "%d %g %g\n", CDMF_FVERTEX, poly[i+2].x, poly[i+2].y); + i += 3; + } + break; + } + } + } + else + { + for(i = 0; i<n; i++) + fprintf(ctxcanvas->file, "%d %g %g\n", CDMF_FVERTEX, poly[i].x, poly[i].y); + } fprintf(ctxcanvas->file, "%d\n", CDMF_END); } diff --git a/cd/src/drv/cdpdf.c b/cd/src/drv/cdpdf.c index a5d91d4..3211cba 100755 --- a/cd/src/drv/cdpdf.c +++ b/cd/src/drv/cdpdf.c @@ -56,36 +56,6 @@ struct _cdCtxCanvas /* -%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) @@ -93,7 +63,9 @@ static void setpdfdefaultvalues(cdCtxCanvas* ctxcanvas) int i; /* all the other values are set to 0 */ - setpdfpapersize(ctxcanvas, CD_A4); + cdSetPaperSize(CD_A4, &ctxcanvas->width_pt, &ctxcanvas->height_pt); + ctxcanvas->width_mm = ctxcanvas->width_pt/CD_MM2PT; + ctxcanvas->height_mm = ctxcanvas->height_pt/CD_MM2PT; ctxcanvas->res = 300; ctxcanvas->hatchboxsize = 8; ctxcanvas->opacity = 255; /* full opaque */ @@ -139,18 +111,16 @@ static void begin_page(cdCtxCanvas *ctxcanvas) static void init_pdf(cdCtxCanvas *ctxcanvas) { ctxcanvas->scale = 72.0/ctxcanvas->res; + ctxcanvas->canvas->xres = ctxcanvas->res/25.4; + ctxcanvas->canvas->yres = ctxcanvas->canvas->xres; - /* 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->w = cdRound(ctxcanvas->canvas->xres*ctxcanvas->canvas->w_mm); + ctxcanvas->canvas->h = cdRound(ctxcanvas->canvas->yres*ctxcanvas->canvas->h_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); } @@ -166,7 +136,7 @@ static void cdkillcanvas(cdCtxCanvas *ctxcanvas) free(ctxcanvas); } -static void update_fill(cdCtxCanvas *ctxcanvas, int fill) +static void sUpdateFill(cdCtxCanvas *ctxcanvas, int fill) { if (fill == 0) { @@ -311,7 +281,7 @@ static int cdclip(cdCtxCanvas *ctxcanvas, int mode) static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2) { - update_fill(ctxcanvas, 0); + sUpdateFill(ctxcanvas, 0); PDF_moveto(ctxcanvas->pdf, x1, y1); PDF_lineto(ctxcanvas->pdf, x2, y2); @@ -325,7 +295,7 @@ static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2) static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) { - update_fill(ctxcanvas, 0); + sUpdateFill(ctxcanvas, 0); PDF_rect(ctxcanvas->pdf, xmin, ymin, xmax-xmin, ymax-ymin); PDF_stroke(ctxcanvas->pdf); @@ -338,7 +308,7 @@ static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int yma static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) { - update_fill(ctxcanvas, 1); + sUpdateFill(ctxcanvas, 1); PDF_moveto(ctxcanvas->pdf, xmin, ymin); PDF_lineto(ctxcanvas->pdf, xmax, ymin); @@ -354,14 +324,16 @@ static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) { - update_fill(ctxcanvas, 0); + sUpdateFill(ctxcanvas, 0); + + /* angles in degrees counterclockwise, same as CD */ 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 */ + else /* Ellipse: change the scale to create from the circle */ { PDF_save(ctxcanvas->pdf); /* save to use the local transform */ @@ -383,12 +355,12 @@ static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) { - update_fill(ctxcanvas, 1); + sUpdateFill(ctxcanvas, 1); if (w==h) { PDF_moveto(ctxcanvas->pdf, xc, yc); - PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2); + PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*h, a1, a2); PDF_fill(ctxcanvas->pdf); } else /* Elipse: mudar a escala p/ criar a partir do circulo */ @@ -401,15 +373,7 @@ static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, do 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_fill(ctxcanvas->pdf); PDF_restore(ctxcanvas->pdf); /* restore from local */ } @@ -422,12 +386,12 @@ static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, doubl static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) { - update_fill(ctxcanvas, 1); + sUpdateFill(ctxcanvas, 1); if (w==h) { - PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2); - PDF_fill_stroke(ctxcanvas->pdf); + PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*h, a1, a2); + PDF_fill(ctxcanvas->pdf); } else /* Elipse: mudar a escala p/ criar a partir do circulo */ { @@ -435,10 +399,11 @@ static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, dou /* local transform */ PDF_translate(ctxcanvas->pdf, xc, yc); - PDF_scale(ctxcanvas->pdf, 1, w/h); + PDF_scale(ctxcanvas->pdf, w/h, 1); + PDF_translate(ctxcanvas->pdf, -xc, -yc); - PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2); - PDF_fill_stroke(ctxcanvas->pdf); + PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*h, a1, a2); + PDF_fill(ctxcanvas->pdf); PDF_restore(ctxcanvas->pdf); /* restore from local */ } @@ -487,8 +452,8 @@ static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *s, i 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); + get_green(ctxcanvas->canvas->foreground), + get_blue(ctxcanvas->canvas->foreground), 0); strcpy(options, ""); @@ -572,13 +537,121 @@ static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n) if (mode == CD_CLIP) return; + if (mode == CD_PATH) + { + int p, fill = 0; + + /* if there is any current path, remove it */ + /* Don't use PDF_endpath because here usually there will be no path scope */ + + for (p=0; p<ctxcanvas->canvas->path_n; p++) + { + if (ctxcanvas->canvas->path[p] == CD_PATH_FILL || + ctxcanvas->canvas->path[p] == CD_PATH_FILLSTROKE) + { + fill = 1; + break; + } + } + + /* must be set before starting path scope */ + sUpdateFill(ctxcanvas, 0); /* set always */ + if (fill) + { + PDF_set_parameter(ctxcanvas->pdf, "fillrule", ctxcanvas->canvas->fill_mode==CD_EVENODD? "evenodd": "winding"); + sUpdateFill(ctxcanvas, fill); + } + + i = 0; + for (p=0; p<ctxcanvas->canvas->path_n; p++) + { + switch(ctxcanvas->canvas->path[p]) + { + case CD_PATH_NEW: + /* Don't use PDF_endpath because here usually there will be no path scope */ + break; + case CD_PATH_MOVETO: + if (i+1 > n) return; + PDF_moveto(ctxcanvas->pdf, poly[i].x, poly[i].y); + i++; + break; + case CD_PATH_LINETO: + if (i+1 > n) return; + PDF_lineto(ctxcanvas->pdf, poly[i].x, poly[i].y); + i++; + break; + case CD_PATH_ARC: + { + double xc, yc, w, h, a1, a2; + + if (i+3 > n) return; + + if (!cdCanvasGetArcPathF(ctxcanvas->canvas, poly+i, &xc, &yc, &w, &h, &a1, &a2)) + return; + + if (w==h) + { + if ((a2-a1)<0) + PDF_arcn(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2); + else + PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2); + } + else /* Ellipse: change the scale to create from the circle */ + { + /* NOT SUPPORTED IN PATH SCOPE!!!! + PDF_save(ctxcanvas->pdf); + + PDF_translate(ctxcanvas->pdf, xc, yc); + PDF_scale(ctxcanvas->pdf, w/h, 1); + PDF_translate(ctxcanvas->pdf, -xc, -yc); */ + double s = h; + if (w > h) + s = w; + + if ((a2-a1)<0) + PDF_arcn(ctxcanvas->pdf, xc, yc, 0.5*s, a1, a2); + else + PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*s, a1, a2); + + /* PDF_restore(ctxcanvas->pdf); */ + } + + i += 3; + } + break; + case CD_PATH_CURVETO: + if (i+3 > n) return; + 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); + i += 3; + break; + case CD_PATH_CLOSE: + PDF_closepath(ctxcanvas->pdf); + break; + case CD_PATH_FILL: + PDF_fill(ctxcanvas->pdf); + break; + case CD_PATH_STROKE: + PDF_stroke(ctxcanvas->pdf); + break; + case CD_PATH_FILLSTROKE: + PDF_fill_stroke(ctxcanvas->pdf); + break; + case CD_PATH_CLIP: + PDF_clip(ctxcanvas->pdf); + break; + } + } + return; + } + if (mode == CD_FILL) - update_fill(ctxcanvas, 1); + sUpdateFill(ctxcanvas, 1); else - update_fill(ctxcanvas, 0); + sUpdateFill(ctxcanvas, 0); if (mode==CD_FILL) { + /* must be set before starting path scope */ if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD) PDF_set_parameter(ctxcanvas->pdf, "fillrule", "evenodd"); else @@ -634,13 +707,121 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n) if (mode == CD_CLIP) return; + if (mode == CD_PATH) + { + int p, fill = 0; + + /* if there is any current path, remove it */ + /* Don't use PDF_endpath because here usually there will be no path scope */ + + for (p=0; p<ctxcanvas->canvas->path_n; p++) + { + if (ctxcanvas->canvas->path[p] == CD_PATH_FILL || + ctxcanvas->canvas->path[p] == CD_PATH_FILLSTROKE) + { + fill = 1; + break; + } + } + + /* must be set before starting path scope */ + sUpdateFill(ctxcanvas, 0); /* set always */ + if (fill) + { + PDF_set_parameter(ctxcanvas->pdf, "fillrule", ctxcanvas->canvas->fill_mode==CD_EVENODD? "evenodd": "winding"); + sUpdateFill(ctxcanvas, fill); + } + + i = 0; + for (p=0; p<ctxcanvas->canvas->path_n; p++) + { + switch(ctxcanvas->canvas->path[p]) + { + case CD_PATH_NEW: + /* Don't use PDF_endpath because here usually there will be no path scope */ + break; + case CD_PATH_MOVETO: + if (i+1 > n) return; + PDF_moveto(ctxcanvas->pdf, poly[i].x, poly[i].y); + i++; + break; + case CD_PATH_LINETO: + if (i+1 > n) return; + PDF_lineto(ctxcanvas->pdf, poly[i].x, poly[i].y); + i++; + break; + case CD_PATH_ARC: + { + double xc, yc, w, h, a1, a2; + + if (i+3 > n) return; + + if (!cdfCanvasGetArcPath(ctxcanvas->canvas, poly+i, &xc, &yc, &w, &h, &a1, &a2)) + return; + + if (w==h) + { + if ((a2-a1)<0) + PDF_arcn(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2); + else + PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2); + } + else /* Ellipse: change the scale to create from the circle */ + { + /* NOT SUPPORTED IN PATH SCOPE!!!! + PDF_save(ctxcanvas->pdf); + + PDF_translate(ctxcanvas->pdf, xc, yc); + PDF_scale(ctxcanvas->pdf, w/h, 1); + PDF_translate(ctxcanvas->pdf, -xc, -yc); */ + double s = h; + if (w > h) + s = w; + + if ((a2-a1)<0) + PDF_arcn(ctxcanvas->pdf, xc, yc, 0.5*s, a1, a2); + else + PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*s, a1, a2); + + /* PDF_restore(ctxcanvas->pdf); */ + } + + i += 3; + } + break; + case CD_PATH_CURVETO: + if (i+3 > n) return; + 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); + i += 3; + break; + case CD_PATH_CLOSE: + PDF_closepath(ctxcanvas->pdf); + break; + case CD_PATH_FILL: + PDF_fill(ctxcanvas->pdf); + break; + case CD_PATH_STROKE: + PDF_stroke(ctxcanvas->pdf); + break; + case CD_PATH_FILLSTROKE: + PDF_fill_stroke(ctxcanvas->pdf); + break; + case CD_PATH_CLIP: + PDF_clip(ctxcanvas->pdf); + break; + } + } + return; + } + if (mode == CD_FILL) - update_fill(ctxcanvas, 1); + sUpdateFill(ctxcanvas, 1); else - update_fill(ctxcanvas, 0); + sUpdateFill(ctxcanvas, 0); if (mode==CD_FILL) { + /* must be set before starting path scope */ if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD) PDF_set_parameter(ctxcanvas->pdf, "fillrule", "evenodd"); else @@ -695,8 +876,8 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n) static int cdlinestyle(cdCtxCanvas *ctxcanvas, int style) { - double mm = (72.0/25.4) / ctxcanvas->scale; - char options[80]; + double mm = ctxcanvas->canvas->xres; + char options[200]; switch (style) { @@ -720,12 +901,12 @@ static int cdlinestyle(cdCtxCanvas *ctxcanvas, int style) case CD_CUSTOM : { int i; - + /* size here is in pixels, do not use mm */ 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); + sprintf(tmp, "%g ", (double)ctxcanvas->canvas->line_dashes[i]); strcat(options, tmp); } strcat(options, "}"); @@ -768,7 +949,6 @@ static void make_pattern(cdCtxCanvas *ctxcanvas, int n, int m, void* data, int ( 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++) @@ -802,21 +982,18 @@ static void cdpattern(cdCtxCanvas *ctxcanvas, int n, int m, const long int *patt 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 -1; + else + cdDecodeColor(ctxcanvas->canvas->background, r, g, b); } - return ret; + return 1; } static void cdstipple(cdCtxCanvas *ctxcanvas, int n, int m, const unsigned char *stipple) @@ -824,14 +1001,14 @@ static void cdstipple(cdCtxCanvas *ctxcanvas, int n, int m, const unsigned char make_pattern(ctxcanvas, n, m, (void*)stipple, uchar2rgb); } -static void make_hatch(cdCtxCanvas *ctxcanvas, int style) +static int cdhatch(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, + ctxcanvas->pattern = PDF_begin_pattern(ctxcanvas->pdf, hsize, hsize, ((double)hsize)*ctxcanvas->scale, ((double)hsize)*ctxcanvas->scale, 1); PDF_scale(ctxcanvas->pdf, ctxcanvas->scale, ctxcanvas->scale); @@ -883,11 +1060,6 @@ static void make_hatch(cdCtxCanvas *ctxcanvas, int style) PDF_end_pattern(ctxcanvas->pdf); PDF_resume_page(ctxcanvas->pdf, ""); -} - -static int cdhatch(cdCtxCanvas *ctxcanvas, int style) -{ - make_hatch(ctxcanvas, style); return style; } @@ -976,6 +1148,7 @@ static int cdfont(cdCtxCanvas *ctxcanvas, const char *type_face, int style, int static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix) { + /* reset to identity */ PDF_setmatrix(ctxcanvas->pdf, 1, 0, 0, 1, 0, 0); /* default coordinate system is in points, change it to pixels. */ @@ -1000,7 +1173,7 @@ static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix) 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; + int i, j, d, image, rw, rh, rgb_size, pos; char options[80]; unsigned char* rgb_data; @@ -1017,9 +1190,10 @@ static void cdputimagerectrgb(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsi 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++; + pos = i*iw+j; + rgb_data[d] = r[pos]; d++; + rgb_data[d] = g[pos]; d++; + rgb_data[d] = b[pos]; d++; } PDF_create_pvf(ctxcanvas->pdf, "cd_raw_rgb", 0, rgb_data, rgb_size, ""); @@ -1036,7 +1210,7 @@ static void cdputimagerectrgb(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsi 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; + int i, j, d, image, image_mask, rw, rh, alpha_size, rgb_size, pos; char options[80]; unsigned char *rgb_data, *alpha_data; @@ -1053,9 +1227,10 @@ static void cdputimagerectrgba(cdCtxCanvas *ctxcanvas, int iw, int ih, const uns 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++; + pos = i*iw+j; + rgb_data[d] = r[pos]; d++; + rgb_data[d] = g[pos]; d++; + rgb_data[d] = b[pos]; d++; } alpha_size = rw*rh; @@ -1066,7 +1241,8 @@ static void cdputimagerectrgba(cdCtxCanvas *ctxcanvas, int iw, int ih, const uns for (i=ymax; i>=ymin; i--) for (j=xmin; j<=xmax; j++) { - alpha_data[d] = a[i*iw+j]; d++; + pos = i*iw+j; + alpha_data[d] = a[pos]; d++; } PDF_create_pvf(ctxcanvas->pdf, "cd_raw_rgb", 0, rgb_data, rgb_size, ""); @@ -1089,9 +1265,10 @@ static void cdputimagerectrgba(cdCtxCanvas *ctxcanvas, int iw, int ih, const uns 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; + int i, j, d, rw, rh, image, rgb_size, pos; char options[80]; unsigned char* rgb_data; + unsigned char r, g, b; if (xmin<0 || ymin<0 || xmax-xmin+1>iw || ymax-ymin+1>ih) return; @@ -1106,8 +1283,8 @@ static void cdputimagerectmap(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsi 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); + pos = i*iw+j; + cdDecodeColor(colors[index[pos]], &r, &g, &b); rgb_data[d] = r; d++; rgb_data[d] = g; d++; rgb_data[d] = b; d++; @@ -1202,7 +1379,8 @@ static cdAttribute hatchboxsize_attrib = static void set_rotate_attrib(cdCtxCanvas *ctxcanvas, char* data) { - /* ignore ROTATE if transform is set */ + /* ignore ROTATE if transform is set, + because there is native support for transformations */ if (ctxcanvas->canvas->use_matrix) return; @@ -1219,15 +1397,7 @@ static void set_rotate_attrib(cdCtxCanvas *ctxcanvas, char* data) 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); - } + cdtransform(ctxcanvas, NULL); } static char* get_rotate_attrib(cdCtxCanvas *ctxcanvas) @@ -1469,7 +1639,9 @@ static void cdcreatecanvas(cdCanvas* canvas, void *data) { int paper; sscanf(line, "%d", &paper); - setpdfpapersize(ctxcanvas, paper); + cdSetPaperSize(paper, &ctxcanvas->width_pt, &ctxcanvas->height_pt); + ctxcanvas->width_mm = ctxcanvas->width_pt/CD_MM2PT; + ctxcanvas->height_mm = ctxcanvas->height_pt/CD_MM2PT; break; } case 'w': @@ -1501,7 +1673,7 @@ static void cdcreatecanvas(cdCanvas* canvas, void *data) /* update canvas context */ canvas->ctxcanvas = ctxcanvas; - if (ctxcanvas->landscape == 1) + if (ctxcanvas->landscape) { _cdSwapDouble(ctxcanvas->width_pt, ctxcanvas->height_pt); _cdSwapDouble(ctxcanvas->width_mm, ctxcanvas->height_mm); @@ -1513,7 +1685,9 @@ static void cdcreatecanvas(cdCanvas* canvas, void *data) static void cdinittable(cdCanvas* canvas) { canvas->cxFlush = cdflush; + canvas->cxPixel = cdpixel; + canvas->cxLine = cdline; canvas->cxPoly = cdpoly; canvas->cxRect = cdrect; @@ -1522,6 +1696,7 @@ static void cdinittable(cdCanvas* canvas) canvas->cxSector = cdsector; canvas->cxChord = cdchord; canvas->cxText = cdtext; + canvas->cxFLine = cdfline; canvas->cxFPoly = cdfpoly; canvas->cxFRect = cdfrect; @@ -1530,6 +1705,7 @@ static void cdinittable(cdCanvas* canvas) canvas->cxFSector = cdfsector; canvas->cxFChord = cdfchord; canvas->cxFText = cdftext; + canvas->cxGetFontDim = cdgetfontdim; canvas->cxGetTextSize = cdgettextsize; canvas->cxPutImageRectRGB = cdputimagerectrgb; @@ -1556,8 +1732,7 @@ 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_GETIMAGERGB), + CD_CAP_WRITEMODE | CD_CAP_GETIMAGERGB), 0, cdcreatecanvas, cdinittable, diff --git a/cd/src/drv/cdpicture.c b/cd/src/drv/cdpicture.c index a5533b2..8cd586e 100755 --- a/cd/src/drv/cdpicture.c +++ b/cd/src/drv/cdpicture.c @@ -27,6 +27,7 @@ typedef enum _tPrim CDPIC_CHORD, CDPIC_TEXT, CDPIC_POLY, + CDPIC_PATH, CDPIC_FLINE, CDPIC_FRECT, CDPIC_FBOX, @@ -35,6 +36,7 @@ typedef enum _tPrim CDPIC_FCHORD, CDPIC_FTEXT, CDPIC_FPOLY, + CDPIC_FPATH, CDPIC_PIXEL, CDPIC_IMAGEMAP, CDPIC_IMAGERGB, @@ -109,6 +111,24 @@ typedef struct _tfPoly cdfPoint* points; } tfPoly; /* Begin, Vertex and End */ +typedef struct _tPath +{ + int fill; + int n; + cdPoint* points; + int path_n; + int *path; +} tPath; /* Begin, PathSet, Vertex and End */ + +typedef struct _tfPath +{ + int fill; + int n; + cdfPoint* points; + int path_n; + int *path; +} tfPath; /* Begin, PathSet, Vertex and End */ + typedef struct _tText { int x, y; @@ -156,6 +176,8 @@ typedef struct _tPrimNode tfASC arcsectorchordf; tPoly poly; tfPoly polyf; + tPath path; + tfPath pathf; tText text; tfText textf; tPixel pixel; @@ -486,7 +508,7 @@ static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a prim->param.arcsectorchord.angle1 = a1; prim->param.arcsectorchord.angle2 = a2; picAddPrim(ctxcanvas, prim); - cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax); + cdCanvasGetArcBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax); picUpdateBBox(ctxcanvas, xmin, ymin, ctxcanvas->canvas->line_width); picUpdateBBox(ctxcanvas, xmax, ymax, ctxcanvas->canvas->line_width); } @@ -503,7 +525,7 @@ static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, doubl prim->param.arcsectorchordf.angle1 = a1; prim->param.arcsectorchordf.angle2 = a2; picAddPrim(ctxcanvas, prim); - cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax); + cdCanvasGetArcBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax); picUpdateBBox(ctxcanvas, xmin, ymin, ctxcanvas->canvas->line_width); picUpdateBBox(ctxcanvas, xmax, ymax, ctxcanvas->canvas->line_width); } @@ -520,7 +542,7 @@ static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, doubl prim->param.arcsectorchord.angle1 = a1; prim->param.arcsectorchord.angle2 = a2; picAddPrim(ctxcanvas, prim); - cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax); + cdCanvasGetArcBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax); picUpdateBBox(ctxcanvas, xmin, ymin, 0); picUpdateBBox(ctxcanvas, xmax, ymax, 0); picUpdateBBox(ctxcanvas, xc, yc, 0); @@ -538,7 +560,7 @@ static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, do prim->param.arcsectorchordf.angle1 = a1; prim->param.arcsectorchordf.angle2 = a2; picAddPrim(ctxcanvas, prim); - cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax); + cdCanvasGetArcBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax); picUpdateBBox(ctxcanvas, xmin, ymin, 0); picUpdateBBox(ctxcanvas, xmax, ymax, 0); picUpdateBBox(ctxcanvas, _cdRound(xc), _cdRound(yc), 0); @@ -556,7 +578,7 @@ static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double prim->param.arcsectorchord.angle1 = a1; prim->param.arcsectorchord.angle2 = a2; picAddPrim(ctxcanvas, prim); - cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax); + cdCanvasGetArcBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax); picUpdateBBox(ctxcanvas, xmin, ymin, 0); picUpdateBBox(ctxcanvas, xmax, ymax, 0); } @@ -573,7 +595,7 @@ static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, dou prim->param.arcsectorchordf.angle1 = a1; prim->param.arcsectorchordf.angle2 = a2; picAddPrim(ctxcanvas, prim); - cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax); + cdCanvasGetArcBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax); picUpdateBBox(ctxcanvas, xmin, ymin, 0); picUpdateBBox(ctxcanvas, xmax, ymax, 0); } @@ -608,16 +630,72 @@ static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *text picUpdateBBox(ctxcanvas, xmax, ymax, 0); } +static void cdpath(cdCtxCanvas *ctxcanvas, cdPoint* poly, int n) +{ + int i, p, fill = -1; + tPrimNode *prim; + + for (p=0; p<ctxcanvas->canvas->path_n; p++) + { + if (ctxcanvas->canvas->path[p] == CD_PATH_CLIP) + return; + else if (ctxcanvas->canvas->path[p] == CD_PATH_FILL || + ctxcanvas->canvas->path[p] == CD_PATH_FILLSTROKE) /* no support for both in cdPicture */ + { + fill = 1; + break; + } + else if (ctxcanvas->canvas->path[p] == CD_PATH_STROKE) + { + fill = -1; + break; + } + } + + if (fill == -1) + return; + + prim = primCreate(CDPIC_PATH); + prim->param.path.fill = fill; + + if (fill) + primAddAttrib_Fill(prim, ctxcanvas->canvas); + else + primAddAttrib_Line(prim, ctxcanvas->canvas); + + prim->param_buffer = malloc(n * sizeof(cdPoint) + ctxcanvas->canvas->path_n * sizeof(int)); + + prim->param.path.n = n; + prim->param.path.points = (cdPoint*)prim->param_buffer; + memcpy(prim->param.path.points, poly, n * sizeof(cdPoint)); + prim->param.path.path = (int*)((unsigned char*)prim->param_buffer + n * sizeof(cdPoint)); + memcpy(prim->param.path.path, ctxcanvas->canvas->path, ctxcanvas->canvas->path_n * sizeof(int)); + prim->param.path.path_n = ctxcanvas->canvas->path_n; + + picAddPrim(ctxcanvas, prim); + + for (i = 0; i < n; i++) + { + picUpdateBBox(ctxcanvas, poly[i].x, poly[i].y, 0); + } +} + static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n) { int i; tPrimNode *prim; if (mode == CD_CLIP || mode == CD_REGION) return; + if (mode == CD_PATH) + { + cdpath(ctxcanvas, poly, n); + return; + } prim = primCreate(CDPIC_POLY); if (mode == CD_FILL) primAddAttrib_Fill(prim, ctxcanvas->canvas); else primAddAttrib_Line(prim, ctxcanvas->canvas); + prim->param.poly.mode = mode; prim->param.poly.n = n; prim->param.poly.points = malloc(n * sizeof(cdPoint)); memcpy(prim->param.poly.points, poly, n * sizeof(cdPoint)); @@ -633,19 +711,75 @@ static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n) } } +static void cdfpath(cdCtxCanvas *ctxcanvas, cdfPoint* poly, int n) +{ + int i, p, fill = -1; + tPrimNode *prim; + + for (p=0; p<ctxcanvas->canvas->path_n; p++) + { + if (ctxcanvas->canvas->path[p] == CD_PATH_CLIP) + return; + else if (ctxcanvas->canvas->path[p] == CD_PATH_FILL || + ctxcanvas->canvas->path[p] == CD_PATH_FILLSTROKE) /* no support for both in cdPicture */ + { + fill = 1; + break; + } + else if (ctxcanvas->canvas->path[p] == CD_PATH_STROKE) + { + fill = -1; + break; + } + } + + if (fill == -1) + return; + + prim = primCreate(CDPIC_FPATH); + prim->param.pathf.fill = fill; + + if (fill) + primAddAttrib_Fill(prim, ctxcanvas->canvas); + else + primAddAttrib_Line(prim, ctxcanvas->canvas); + + prim->param_buffer = malloc(n * sizeof(cdfPoint) + ctxcanvas->canvas->path_n * sizeof(int)); + + prim->param.pathf.n = n; + prim->param.pathf.points = (cdfPoint*)prim->param_buffer; + memcpy(prim->param.pathf.points, poly, n * sizeof(cdfPoint)); + prim->param.pathf.path = (int*)((unsigned char*)prim->param_buffer + n * sizeof(cdfPoint)); + memcpy(prim->param.pathf.path, ctxcanvas->canvas->path, ctxcanvas->canvas->path_n * sizeof(int)); + prim->param.pathf.path_n = ctxcanvas->canvas->path_n; + + picAddPrim(ctxcanvas, prim); + + for (i = 0; i < n; i++) + { + picUpdateBBox(ctxcanvas, _cdRound(poly[i].x), _cdRound(poly[i].y), 0); + } +} + static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n) { int i; tPrimNode *prim; if (mode == CD_CLIP || mode == CD_REGION) return; + if (mode == CD_PATH) + { + cdfpath(ctxcanvas, poly, n); + return; + } prim = primCreate(CDPIC_FPOLY); if (mode == CD_FILL) primAddAttrib_Fill(prim, ctxcanvas->canvas); else primAddAttrib_Line(prim, ctxcanvas->canvas); + prim->param.polyf.mode = mode; prim->param.polyf.n = n; - prim->param.polyf.points = malloc(n * sizeof(cdPoint)); - memcpy(prim->param.polyf.points, poly, n * sizeof(cdPoint)); + prim->param.polyf.points = malloc(n * sizeof(cdfPoint)); + memcpy(prim->param.polyf.points, poly, n * sizeof(cdfPoint)); prim->param_buffer = prim->param.polyf.points; picAddPrim(ctxcanvas, prim); @@ -843,7 +977,7 @@ static int cdplay(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, void tPrimNode *prim; cdCanvas* pic_canvas = (cdCanvas*)data; cdCtxCanvas* ctxcanvas = pic_canvas->ctxcanvas; - int p, i, scale = 0, + int p, i, n, scale = 0, pic_xmin = ctxcanvas->xmin, pic_ymin = ctxcanvas->ymin; double factorX = 1, factorY = 1; @@ -949,6 +1083,72 @@ static int cdplay(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, void cdfCanvasVertex(canvas, sfScaleX(prim->param.polyf.points[p].x), sfScaleY(prim->param.polyf.points[p].y)); cdCanvasEnd(canvas); break; + case CDPIC_PATH: + if (prim->param.path.fill) + primUpdateAttrib_Fill(prim, canvas); + else + primUpdateAttrib_Line(prim, canvas); + cdCanvasBegin(canvas, CD_PATH); + n = 0; + for (p=0; p<prim->param.path.path_n; p++) + { + cdCanvasPathSet(canvas, prim->param.path.path[p]); + + switch(prim->param.path.path[p]) + { + case CD_PATH_MOVETO: + case CD_PATH_LINETO: + if (n+1 > n) break; + cdCanvasVertex(canvas, sScaleX(prim->param.path.points[n].x), sScaleY(prim->param.path.points[n].y)); + n++; + break; + case CD_PATH_CURVETO: + case CD_PATH_ARC: + { + if (n+3 > n) break; + cdCanvasVertex(canvas, sScaleX(prim->param.path.points[n].x), sScaleY(prim->param.path.points[n].y)); + cdCanvasVertex(canvas, sScaleX(prim->param.path.points[n+1].x), sScaleY(prim->param.path.points[n+1].y)); + cdCanvasVertex(canvas, sScaleX(prim->param.path.points[n+2].x), sScaleY(prim->param.path.points[n+2].y)); + n += 3; + } + break; + } + } + cdCanvasEnd(canvas); + break; + case CDPIC_FPATH: + if (prim->param.path.fill) + primUpdateAttrib_Fill(prim, canvas); + else + primUpdateAttrib_Line(prim, canvas); + cdCanvasBegin(canvas, CD_PATH); + n = 0; + for (p=0; p<prim->param.pathf.path_n; p++) + { + cdCanvasPathSet(canvas, prim->param.pathf.path[p]); + + switch(prim->param.pathf.path[p]) + { + case CD_PATH_MOVETO: + case CD_PATH_LINETO: + if (n+1 > n) break; + cdfCanvasVertex(canvas, sfScaleX(prim->param.pathf.points[n].x), sfScaleY(prim->param.pathf.points[n].y)); + n++; + break; + case CD_PATH_CURVETO: + case CD_PATH_ARC: + { + if (n+3 > n) break; + cdfCanvasVertex(canvas, sfScaleX(prim->param.pathf.points[n].x), sfScaleY(prim->param.pathf.points[n].y)); + cdfCanvasVertex(canvas, sfScaleX(prim->param.pathf.points[n+1].x), sfScaleY(prim->param.pathf.points[n+1].y)); + cdfCanvasVertex(canvas, sfScaleX(prim->param.pathf.points[n+2].x), sfScaleY(prim->param.pathf.points[n+2].y)); + n += 3; + } + break; + } + } + cdCanvasEnd(canvas); + break; case CDPIC_IMAGERGB: cdCanvasPutImageRectRGB(canvas, prim->param.imagergba.iw, prim->param.imagergba.ih, prim->param.imagergba.r, prim->param.imagergba.g, prim->param.imagergba.b, sScaleX(prim->param.imagergba.x), sScaleY(prim->param.imagergba.y), sScaleW(prim->param.imagergba.w), sScaleH(prim->param.imagergba.h), 0, 0, 0, 0); break; @@ -1043,6 +1243,72 @@ static int cdplay(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, void cdfCanvasVertex(canvas, prim->param.polyf.points[p].x, prim->param.polyf.points[p].y); cdCanvasEnd(canvas); break; + case CDPIC_PATH: + if (prim->param.path.fill) + primUpdateAttrib_Fill(prim, canvas); + else + primUpdateAttrib_Line(prim, canvas); + cdCanvasBegin(canvas, CD_PATH); + n = 0; + for (p=0; p<prim->param.path.path_n; p++) + { + cdCanvasPathSet(canvas, prim->param.path.path[p]); + + switch(prim->param.path.path[p]) + { + case CD_PATH_MOVETO: + case CD_PATH_LINETO: + if (n+1 > n) break; + cdCanvasVertex(canvas, prim->param.path.points[n].x, prim->param.path.points[n].y); + n++; + break; + case CD_PATH_CURVETO: + case CD_PATH_ARC: + { + if (n+3 > n) break; + cdCanvasVertex(canvas, prim->param.path.points[n].x, prim->param.path.points[n].y); + cdCanvasVertex(canvas, prim->param.path.points[n+1].x, prim->param.path.points[n+1].y); + cdCanvasVertex(canvas, prim->param.path.points[n+2].x, prim->param.path.points[n+2].y); + n += 3; + } + break; + } + } + cdCanvasEnd(canvas); + break; + case CDPIC_FPATH: + if (prim->param.path.fill) + primUpdateAttrib_Fill(prim, canvas); + else + primUpdateAttrib_Line(prim, canvas); + cdCanvasBegin(canvas, CD_PATH); + n = 0; + for (p=0; p<prim->param.pathf.path_n; p++) + { + cdCanvasPathSet(canvas, prim->param.pathf.path[p]); + + switch(prim->param.pathf.path[p]) + { + case CD_PATH_MOVETO: + case CD_PATH_LINETO: + if (n+1 > n) break; + cdfCanvasVertex(canvas, prim->param.pathf.points[n].x, prim->param.pathf.points[n].y); + n++; + break; + case CD_PATH_CURVETO: + case CD_PATH_ARC: + { + if (n+3 > n) break; + cdfCanvasVertex(canvas, prim->param.pathf.points[n].x, prim->param.pathf.points[n].y); + cdfCanvasVertex(canvas, prim->param.pathf.points[n+1].x, prim->param.pathf.points[n+1].y); + cdfCanvasVertex(canvas, prim->param.pathf.points[n+2].x, prim->param.pathf.points[n+2].y); + n += 3; + } + break; + } + } + cdCanvasEnd(canvas); + break; case CDPIC_IMAGERGB: cdCanvasPutImageRectRGB(canvas, prim->param.imagergba.iw, prim->param.imagergba.ih, prim->param.imagergba.r, prim->param.imagergba.g, prim->param.imagergba.b, prim->param.imagergba.x, prim->param.imagergba.y, prim->param.imagergba.w, prim->param.imagergba.h, 0, 0, 0, 0); break; diff --git a/cd/src/drv/cdps.c b/cd/src/drv/cdps.c index ef77c4d..08d6ba7 100755 --- a/cd/src/drv/cdps.c +++ b/cd/src/drv/cdps.c @@ -49,11 +49,11 @@ struct _cdCtxCanvas { cdCanvas* canvas; - FILE *file; /* Arquivo PS */ + 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 width_pt; /* Largura do papel (points) */ + double height_pt; /* 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 */ @@ -64,6 +64,7 @@ struct _cdCtxCanvas 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; @@ -73,45 +74,16 @@ struct _cdCtxCanvas 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); + cdSetPaperSize(CD_A4, &ctxcanvas->width_pt, &ctxcanvas->height_pt); + ctxcanvas->xmin = 25.4; /* ainda em mm, sera' convertido para points na init_ps */ ctxcanvas->xmax = 25.4; ctxcanvas->ymin = 25.4; @@ -278,8 +250,10 @@ static void set_default_matrix(cdCtxCanvas *ctxcanvas) fprintf(ctxcanvas->file, "setmatrix\n"); } - /* margin and scale */ + /* margin */ fprintf(ctxcanvas->file, "%g %g translate\n", ctxcanvas->xmin, ctxcanvas->ymin); + + /* default coordinate system is in points, change it to pixels. */ fprintf(ctxcanvas->file, "%g %g scale\n", ctxcanvas->scale, ctxcanvas->scale); } @@ -288,15 +262,15 @@ static void set_default_matrix(cdCtxCanvas *ctxcanvas) */ static void init_ps(cdCtxCanvas *ctxcanvas) { - double w, h; + double w_pt, h_pt; time_t now = time(NULL); - ctxcanvas->scale = 72.0/ctxcanvas->res; + /* convert margin values to actual limits */ ctxcanvas->xmin = mm2pt(ctxcanvas->xmin); - ctxcanvas->xmax = ctxcanvas->width - mm2pt(ctxcanvas->xmax); + ctxcanvas->xmax = ctxcanvas->width_pt - mm2pt(ctxcanvas->xmax); ctxcanvas->ymin = mm2pt(ctxcanvas->ymin); - ctxcanvas->ymax = ctxcanvas->height - mm2pt(ctxcanvas->ymax); + ctxcanvas->ymax = ctxcanvas->height_pt - mm2pt(ctxcanvas->ymax); ctxcanvas->bbmargin = mm2pt(ctxcanvas->bbmargin); fprintf(ctxcanvas->file, "%%!PS-Adobe-3.0 %s\n", ctxcanvas->eps ? "EPSF-3.0":""); @@ -338,9 +312,10 @@ static void init_ps(cdCtxCanvas *ctxcanvas) if (!ctxcanvas->eps && !ctxcanvas->level1) { + /* setpagedevice not allowed in EPS */ 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, "<< /PageSize [%g %g] >> setpagedevice\n", ctxcanvas->width_pt, ctxcanvas->height_pt); fprintf(ctxcanvas->file, "%%%%EndFeature\n"); } @@ -350,16 +325,20 @@ static void init_ps(cdCtxCanvas *ctxcanvas) fputs(change_font, ctxcanvas->file); fputs(re_encode, ctxcanvas->file); - w = ctxcanvas->xmax - ctxcanvas->xmin; - h = ctxcanvas->ymax - ctxcanvas->ymin; + ctxcanvas->scale = 72.0/ctxcanvas->res; + ctxcanvas->canvas->xres = ctxcanvas->res/25.4; + ctxcanvas->canvas->yres = ctxcanvas->canvas->xres; + + w_pt = ctxcanvas->xmax - ctxcanvas->xmin; + h_pt = ctxcanvas->ymax - ctxcanvas->ymin; + + ctxcanvas->canvas->w_mm = w_pt/CD_MM2PT; /* Converte p/ milimetros */ + ctxcanvas->canvas->h_mm = h_pt/CD_MM2PT; /* Converte p/ milimetros */ + + ctxcanvas->canvas->w = cdRound(ctxcanvas->canvas->xres*ctxcanvas->canvas->w_mm); + ctxcanvas->canvas->h = cdRound(ctxcanvas->canvas->yres*ctxcanvas->canvas->h_mm); - 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; @@ -425,7 +404,7 @@ 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) +static void sUpdateFill(cdCtxCanvas *ctxcanvas, int fill) { if (fill == 0) { @@ -533,7 +512,7 @@ static int cdclip(cdCtxCanvas *ctxcanvas, int mode) static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2) { - update_fill(ctxcanvas, 0); + sUpdateFill(ctxcanvas, 0); fprintf(ctxcanvas->file, "N %d %d %d %d LL\n", x1, y1, x2, y2); @@ -546,7 +525,7 @@ static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2) static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2) { - update_fill(ctxcanvas, 0); + sUpdateFill(ctxcanvas, 0); fprintf(ctxcanvas->file, "N %g %g %g %g LL\n", x1, y1, x2, y2); @@ -559,7 +538,7 @@ static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, dou static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) { - update_fill(ctxcanvas, 0); + sUpdateFill(ctxcanvas, 0); if (ctxcanvas->level1) { @@ -582,7 +561,7 @@ static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int yma static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) { - update_fill(ctxcanvas, 0); + sUpdateFill(ctxcanvas, 0); if (ctxcanvas->level1) { @@ -605,7 +584,7 @@ static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymi static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) { - update_fill(ctxcanvas, 1); + sUpdateFill(ctxcanvas, 1); if (ctxcanvas->level1) { @@ -628,7 +607,7 @@ static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) { - update_fill(ctxcanvas, 1); + sUpdateFill(ctxcanvas, 1); if (ctxcanvas->level1) { @@ -651,7 +630,9 @@ static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) { - update_fill(ctxcanvas, 0); + sUpdateFill(ctxcanvas, 0); + + /* angles in degrees counterclockwise, same as CD */ if (w==h) /* Circulo: PS implementa direto */ { @@ -675,7 +656,7 @@ static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a if (ctxcanvas->eps) { int xmin, xmax, ymin, ymax; - cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax); + cdCanvasGetArcBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax); bbox(ctxcanvas, xmin, ymin); bbox(ctxcanvas, xmax, ymax); } @@ -683,7 +664,7 @@ static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) { - update_fill(ctxcanvas, 0); + sUpdateFill(ctxcanvas, 0); if (w==h) /* Circulo: PS implementa direto */ { @@ -707,7 +688,7 @@ static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, doubl if (ctxcanvas->eps) { int xmin, xmax, ymin, ymax; - cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax); + cdCanvasGetArcBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax); bbox(ctxcanvas, xmin, ymin); bbox(ctxcanvas, xmax, ymax); } @@ -715,7 +696,7 @@ static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, doubl static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) { - update_fill(ctxcanvas, 1); + sUpdateFill(ctxcanvas, 1); if (w==h) /* Circulo: PS implementa direto */ { @@ -747,7 +728,7 @@ static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, doubl if (ctxcanvas->eps) { int xmin, xmax, ymin, ymax; - cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax); + cdCanvasGetArcBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax); bbox(ctxcanvas, xmin, ymin); bbox(ctxcanvas, xmax, ymax); bbox(ctxcanvas, xc, yc); @@ -756,7 +737,7 @@ static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, doubl static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) { - update_fill(ctxcanvas, 1); + sUpdateFill(ctxcanvas, 1); if (w==h) /* Circulo: PS implementa direto */ { @@ -788,7 +769,7 @@ static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, do if (ctxcanvas->eps) { int xmin, xmax, ymin, ymax; - cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax); + cdCanvasGetArcBox(_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); @@ -797,7 +778,7 @@ static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, do static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) { - update_fill(ctxcanvas, 1); + sUpdateFill(ctxcanvas, 1); if (w==h) /* Circulo: PS implementa direto */ { @@ -827,7 +808,7 @@ static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double if (ctxcanvas->eps) { int xmin, xmax, ymin, ymax; - cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax); + cdCanvasGetArcBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax); bbox(ctxcanvas, xmin, ymin); bbox(ctxcanvas, xmax, ymax); } @@ -835,7 +816,7 @@ static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) { - update_fill(ctxcanvas, 1); + sUpdateFill(ctxcanvas, 1); if (w==h) /* Circulo: PS implementa direto */ { @@ -865,7 +846,7 @@ static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, dou if (ctxcanvas->eps) { int xmin, xmax, ymin, ymax; - cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax); + cdCanvasGetArcBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax); bbox(ctxcanvas, xmin, ymin); bbox(ctxcanvas, xmax, ymax); } @@ -878,7 +859,7 @@ static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *s, int len) int i; int ascent, height, baseline; - update_fill(ctxcanvas, 0); + sUpdateFill(ctxcanvas, 0); cdCanvasGetFontDim(ctxcanvas->canvas, NULL, &height, &ascent, NULL); baseline = height - ascent; @@ -989,30 +970,242 @@ static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *s, int len) if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdTextEnd\n"); } +static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *s, int len) +{ + int i; + int ascent, height, baseline; + + sUpdateFill(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 (i=0; i<len; 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, "%g %g 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; + s = cdStrDupN(s, len); + cdCanvasGetTextBox(ctxcanvas->canvas, (int)x, (int)y, s, &xmin, &xmax, &ymin, &ymax); + free((char*)s); + fbbox(ctxcanvas, (double)xmin, (double)ymin); + fbbox(ctxcanvas, (double)xmax, (double)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_PATH) + { + int p; + + /* if there is any current path, remove it */ + fprintf(ctxcanvas->file, "newpath\n"); + + i = 0; + for (p=0; p<ctxcanvas->canvas->path_n; p++) + { + switch(ctxcanvas->canvas->path[p]) + { + case CD_PATH_NEW: + fprintf(ctxcanvas->file, "newpath\n"); + break; + case CD_PATH_MOVETO: + if (i+1 > n) return; + fprintf(ctxcanvas->file, "%d %d M\n", poly[i].x, poly[i].y); + i++; + break; + case CD_PATH_LINETO: + if (i+1 > n) return; + fprintf(ctxcanvas->file, "%d %d L\n", poly[i].x, poly[i].y); + i++; + break; + case CD_PATH_ARC: + { + int xc, yc, w, h; + double a1, a2; + char* arc = "arc"; + + if (i+3 > n) return; + + if (!cdCanvasGetArcPath(ctxcanvas->canvas, poly+i, &xc, &yc, &w, &h, &a1, &a2)) + return; + + if ((a2-a1)<0) + arc = "arcn"; + + if (w==h) /* Circulo: PS implementa direto */ + { + fprintf(ctxcanvas->file, "%d %d %g %g %g %s\n", xc, yc, 0.5*w, a1, a2, arc); + } + else /* Elipse: mudar a escala p/ criar a partir do circulo */ + { + 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, "0 0 %g %g %g %s\n", 0.5*w, a1, a2, arc); + fprintf(ctxcanvas->file, "setmatrix\n"); /* back to CTM */ + } + + i += 3; + } + break; + case CD_PATH_CURVETO: + if (i+3 > n) return; + 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); + i += 3; + break; + case CD_PATH_CLOSE: + fprintf(ctxcanvas->file, "closepath\n"); + break; + case CD_PATH_FILL: + sUpdateFill(ctxcanvas, 1); + if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD) + fprintf(ctxcanvas->file, "eofill\n"); + else + fprintf(ctxcanvas->file, "fill\n"); + break; + case CD_PATH_STROKE: + sUpdateFill(ctxcanvas, 0); + fprintf(ctxcanvas->file, "stroke\n"); + break; + case CD_PATH_FILLSTROKE: + sUpdateFill(ctxcanvas, 1); + fprintf(ctxcanvas->file, "gsave\n"); + if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD) + fprintf(ctxcanvas->file, "eofill\n"); + else + fprintf(ctxcanvas->file, "fill\n"); + fprintf(ctxcanvas->file, "grestore\n"); + sUpdateFill(ctxcanvas, 0); + fprintf(ctxcanvas->file, "stroke\n"); + break; + case CD_PATH_CLIP: + if (ctxcanvas->canvas->fill_mode==CD_EVENODD) + fprintf(ctxcanvas->file, "closepath eoclip\n"); + else + fprintf(ctxcanvas->file, "closepath clip\n"); + break; + } + } + return; + } + 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); + sUpdateFill(ctxcanvas, 1); else - update_fill(ctxcanvas, 0); - - if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdPoly %d Begin\n", mode); + sUpdateFill(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); @@ -1090,26 +1283,121 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n) { int i, hole_index = 0; + if (mode == CD_PATH) + { + int p; + + /* if there is any current path, remove it */ + fprintf(ctxcanvas->file, "newpath\n"); + + i = 0; + for (p=0; p<ctxcanvas->canvas->path_n; p++) + { + switch(ctxcanvas->canvas->path[p]) + { + case CD_PATH_NEW: + fprintf(ctxcanvas->file, "newpath\n"); + break; + case CD_PATH_MOVETO: + if (i+1 > n) return; + fprintf(ctxcanvas->file, "%g %g M\n", poly[i].x, poly[i].y); + i++; + break; + case CD_PATH_LINETO: + if (i+1 > n) return; + fprintf(ctxcanvas->file, "%g %g L\n", poly[i].x, poly[i].y); + i++; + break; + case CD_PATH_ARC: + { + double xc, yc, w, h, a1, a2; + char* arc = "arc"; + + if (i+3 > n) return; + + if (!cdfCanvasGetArcPath(ctxcanvas->canvas, poly+i, &xc, &yc, &w, &h, &a1, &a2)) + return; + + if ((a2-a1)<0) + arc = "arcn"; + + if (w==h) /* Circulo: PS implementa direto */ + { + fprintf(ctxcanvas->file, "%g %g %g %g %g %s\n", xc, yc, 0.5*w, a1, a2, arc); + } + else /* Elipse: mudar a escala p/ criar a partir do circulo */ + { + fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n"); /* fill new matrix from CTM */ + fprintf(ctxcanvas->file, "%g %g translate\n", xc, yc); + fprintf(ctxcanvas->file, "1 %g scale\n", ((double)h)/w); + fprintf(ctxcanvas->file, "0 0 %g %g %g %s\n", 0.5*w, a1, a2, arc); + fprintf(ctxcanvas->file, "setmatrix\n"); /* back to CTM */ + } + + i += 3; + } + break; + case CD_PATH_CURVETO: + if (i+3 > n) return; + fprintf(ctxcanvas->file, "%g %g %g %g %g %g B\n", poly[i].x, poly[i].y, + poly[i+1].x, poly[i+1].y, + poly[i+2].x, poly[i+2].y); + i += 3; + break; + case CD_PATH_CLOSE: + fprintf(ctxcanvas->file, "closepath\n"); + break; + case CD_PATH_FILL: + sUpdateFill(ctxcanvas, 1); + if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD) + fprintf(ctxcanvas->file, "eofill\n"); + else + fprintf(ctxcanvas->file, "fill\n"); + break; + case CD_PATH_STROKE: + sUpdateFill(ctxcanvas, 0); + fprintf(ctxcanvas->file, "stroke\n"); + break; + case CD_PATH_FILLSTROKE: + sUpdateFill(ctxcanvas, 1); + fprintf(ctxcanvas->file, "gsave\n"); + if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD) + fprintf(ctxcanvas->file, "eofill\n"); + else + fprintf(ctxcanvas->file, "fill\n"); + fprintf(ctxcanvas->file, "grestore\n"); + sUpdateFill(ctxcanvas, 0); + fprintf(ctxcanvas->file, "stroke\n"); + break; + case CD_PATH_CLIP: + if (ctxcanvas->canvas->fill_mode==CD_EVENODD) + fprintf(ctxcanvas->file, "C eoclip\n"); + else + fprintf(ctxcanvas->file, "C clip\n"); + break; + } + } + return; + } + 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); + sUpdateFill(ctxcanvas, 1); else - update_fill(ctxcanvas, 0); - - if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfPoly %d Begin\n", mode); + sUpdateFill(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); @@ -1166,7 +1454,7 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n) static int cdlinestyle(cdCtxCanvas *ctxcanvas, int style) { - double mm = (72.0/25.4) / ctxcanvas->scale; + double mm = ctxcanvas->canvas->xres; if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdLineStyle %d Begin\n", style); @@ -1191,9 +1479,9 @@ static int cdlinestyle(cdCtxCanvas *ctxcanvas, int style) break; case CD_CUSTOM : { - int i; + int i; /* size here is in pixels, do not use mm */ for (i = 0; i < ctxcanvas->canvas->line_dashes_count; i++) - fprintf(ctxcanvas->file, "%g ", ctxcanvas->canvas->line_dashes[i]*mm); + fprintf(ctxcanvas->file, "%g ", (double)ctxcanvas->canvas->line_dashes[i]); } break; } @@ -1379,6 +1667,7 @@ static int cdfont(cdCtxCanvas *ctxcanvas, const char *type_face, int style, int static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix) { + /* reset to identity */ set_default_matrix(ctxcanvas); if (matrix) @@ -1568,7 +1857,8 @@ static void cdpixel(cdCtxCanvas *ctxcanvas, int x, int y, long int color) static void set_rotate_attrib(cdCtxCanvas *ctxcanvas, char* data) { - /* ignore ROTATE if transform is set */ + /* ignore ROTATE if transform is set, + because there is native support for transformations */ if (ctxcanvas->canvas->use_matrix) return; @@ -1585,15 +1875,7 @@ static void set_rotate_attrib(cdCtxCanvas *ctxcanvas, char* data) 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); - } + cdtransform(ctxcanvas, NULL); } static char* get_rotate_attrib(cdCtxCanvas *ctxcanvas) @@ -1619,7 +1901,7 @@ static cdAttribute rotate_attrib = static void set_cmd_attrib(cdCtxCanvas *ctxcanvas, char* data) { - fprintf(ctxcanvas->file, data); + fprintf(ctxcanvas->file, "%s", data); } static cdAttribute cmd_attrib = @@ -1715,16 +1997,16 @@ static void cdcreatecanvas(cdCanvas* canvas, void *data) { int paper; sscanf(line, "%d", &paper); - setpspapersize(ctxcanvas, paper); + cdSetPaperSize(paper, &ctxcanvas->width_pt, &ctxcanvas->height_pt); break; } case 'w': sscanf(line, "%g", &num); - ctxcanvas->width = mm2pt(num); + ctxcanvas->width_pt = mm2pt(num); break; case 'h': sscanf(line, "%g", &num); - ctxcanvas->height = mm2pt(num); + ctxcanvas->height_pt = mm2pt(num); break; case 'l': sscanf(line, "%g", &num); @@ -1774,9 +2056,9 @@ static void cdcreatecanvas(cdCanvas* canvas, void *data) /* update canvas context */ canvas->ctxcanvas = ctxcanvas; - if (ctxcanvas->landscape == 1) + if (ctxcanvas->landscape) { - _cdSwapDouble(ctxcanvas->width, ctxcanvas->height); + _cdSwapDouble(ctxcanvas->width_pt, ctxcanvas->height_pt); _cdSwapDouble(ctxcanvas->xmin, ctxcanvas->ymin); _cdSwapDouble(ctxcanvas->xmax, ctxcanvas->ymax); } @@ -1787,7 +2069,9 @@ static void cdcreatecanvas(cdCanvas* canvas, void *data) static void cdinittable(cdCanvas* canvas) { canvas->cxFlush = cdflush; + canvas->cxPixel = cdpixel; + canvas->cxLine = cdline; canvas->cxPoly = cdpoly; canvas->cxRect = cdrect; @@ -1796,8 +2080,10 @@ static void cdinittable(cdCanvas* canvas) canvas->cxSector = cdsector; canvas->cxChord = cdchord; canvas->cxText = cdtext; + canvas->cxPutImageRectRGB = cdputimagerectrgb; canvas->cxPutImageRectMap = cdputimagerectmap; + canvas->cxFLine = cdfline; canvas->cxFPoly = cdfpoly; canvas->cxFRect = cdfrect; @@ -1805,6 +2091,8 @@ static void cdinittable(cdCanvas* canvas) canvas->cxFArc = cdfarc; canvas->cxFSector = cdfsector; canvas->cxFChord = cdfchord; + canvas->cxFText = cdftext; + canvas->cxClip = cdclip; canvas->cxFClipArea = cdfcliparea; canvas->cxLineStyle = cdlinestyle; diff --git a/cd/src/drv/cgm.c b/cd/src/drv/cgm.c index e86baaf..ea4d930 100755 --- a/cd/src/drv/cgm.c +++ b/cd/src/drv/cgm.c @@ -743,7 +743,7 @@ static void cgmb_s ( CGM *cgm, const char *s, int len ) else cgmb_putu8(cgm,l); - for ( i=0; i<len; s++ ) + for ( i=0; i<l; i++, s++ ) { if ( (i + bc) == 32766 ) { @@ -756,7 +756,7 @@ static void cgmb_s ( CGM *cgm, const char *s, int len ) else cgmb_putu16 ( cgm, l ); } - cgmb_putc ( cgm, s[i] ); + cgmb_putc ( cgm, *s ); } } |