diff options
Diffstat (limited to 'Build/source/texk/dvipdfm-x/pdfdraw.c')
-rw-r--r-- | Build/source/texk/dvipdfm-x/pdfdraw.c | 1888 |
1 files changed, 0 insertions, 1888 deletions
diff --git a/Build/source/texk/dvipdfm-x/pdfdraw.c b/Build/source/texk/dvipdfm-x/pdfdraw.c deleted file mode 100644 index 66549e193b1..00000000000 --- a/Build/source/texk/dvipdfm-x/pdfdraw.c +++ /dev/null @@ -1,1888 +0,0 @@ -/* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2002-2020 by Jin-Hwan Cho and Shunsaku Hirata, - the dvipdfmx project team. - - Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -*/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <math.h> - -#include "system.h" -#include "error.h" -#include "mem.h" -#include "mfileio.h" -#include "dpxconf.h" -#include "dpxutil.h" -#include "numbers.h" - -#include "pdfdoc.h" -#include "pdfdev.h" -#include "pdfcolor.h" -#include "pdfparse.h" -#include "pdfobj.h" - -#include "pdfdraw.h" - -#define OUR_EPSILON 2.5e-16 - -/* - * Numbers are rounding to 0-5 fractional digits - * in output routine. - */ -#define detM(M) ((M).a * (M).d - (M).b * (M).c) -#define detP(M) ((M)->a * (M)->d - (M)->b * (M)->c) - - -static /* __inline__ */ int -inversematrix (pdf_tmatrix *W, const pdf_tmatrix *M) -{ - double det; - - det = detP(M); - if (fabs(det) < OUR_EPSILON) { - WARN("Inverting matrix with zero determinant..."); - return -1; /* result is undefined. */ - } - - W->a = (M->d) / det; W->b = -(M->b) / det; - W->c = -(M->c) / det; W->d = (M->a) / det; - W->e = (M->c) * (M->f) - (M->d) * (M->e); - W->f = (M->b) * (M->e) - (M->a) * (M->f); - W->e /= det; - W->f /= det; - - return 0; -} - -/* pdf_coord as vector */ -#define vecprd(v,w) ((v).x * (w).x + (v).y * (w).y) -#define vecrot(v,w) ((v).x * (w).y - (v).y * (w).x) -#define dsign(v) (((v) >= 0.0) ? 1.0 : -1.0) -/* acos => [0, pi] */ -#define vecang(v,w) ( \ - dsign(vecrot((v),(w))) * \ - acos(vecprd((v),(w)) / sqrt(vecprd((v),(v)) * vecprd((w),(w)))) \ -) - -static /* __inline__ */ int -pdf_coord__equal (const pdf_coord *p1, const pdf_coord *p2) -{ - if (fabs(p1->x - p2->x) < 1.e-7 && - fabs(p1->y - p2->y) < 1.e-7) - return 1; - return 0; -} -#define COORD_EQUAL(p,q) pdf_coord__equal((p),(q)) - -#if 0 -static int -pdf_coord__sort_compar_X (const void *pp1, const void *pp2) -{ - pdf_coord *p1 = (pdf_coord *)pp1; - pdf_coord *p2 = (pdf_coord *)pp2; - - if (pdf_coord__equal(p1, p2)) - return 0; - else - return (int) dsign(p1->x - p2->x); - - return 1; -} - -static int -pdf_coord__sort_compar_Y (const void *pp1, const void *pp2) -{ - pdf_coord *p1 = (pdf_coord *)pp1; - pdf_coord *p2 = (pdf_coord *)pp2; - - if (pdf_coord__equal(p1, p2)) - return 0; - else - return (int) dsign(p1->y - p2->y); - - return 1; -} -#endif - - -static /* __inline__ */ int -pdf_coord__transform (pdf_coord *p, const pdf_tmatrix *M) -{ - double x, y; - - x = p->x; y = p->y; - p->x = x * M->a + y * M->c + M->e; - p->y = x * M->b + y * M->d + M->f; - - return 0; -} - -static /* __inline__ */ int -pdf_coord__itransform (pdf_coord *p, const pdf_tmatrix *M) -{ - pdf_tmatrix W; - double x, y; - int error; - - error = inversematrix(&W, M); - if (error) - return error; - - x = p->x; y = p->y; - p->x = x * W.a + y * W.c + W.e; - p->y = x * W.b + y * W.d + W.f; - - return 0; -} - -static /* __inline__ */ int -pdf_coord__dtransform (pdf_coord *p, const pdf_tmatrix *M) -{ - double x, y; - - x = p->x; y = p->y; - p->x = x * M->a + y * M->c; - p->y = x * M->b + y * M->d; - - return 0; -} - -static /* __inline__ */ int -pdf_coord__idtransform (pdf_coord *p, const pdf_tmatrix *M) -{ - pdf_tmatrix W; - double x, y; - int error; - - error = inversematrix(&W, M); - if (error) - return error; - - x = p->x; y = p->y; - p->x = x * W.a + y * W.c; - p->y = x * W.b + y * W.d; - - return 0; -} - - -/* Modify M itself */ -void -pdf_invertmatrix (pdf_tmatrix *M) -{ - pdf_tmatrix W; - double det; - - ASSERT(M); - - det = detP(M); - if (fabs(det) < OUR_EPSILON) { - WARN("Inverting matrix with zero determinant..."); - W.a = 1.0; W.c = 0.0; - W.b = 0.0; W.d = 1.0; - W.e = 0.0; W.f = 0.0; - } else { - W.a = (M->d) / det; W.b = -(M->b) / det; - W.c = -(M->c) / det; W.d = (M->a) / det; - W.e = (M->c) * (M->f) - (M->d) * (M->e); - W.f = (M->b) * (M->e) - (M->a) * (M->f); - W.e /= det; W.f /= det; - } - - pdf_copymatrix(M, &W); - - return; -} - - -typedef struct pa_elem_ -{ - int type; - pdf_coord p[3]; -} pa_elem; - -/* each subpath delimitted by moveto */ -struct pdf_path_ -{ - int num_paths; - int max_paths; - pa_elem *path; -}; - -static const struct { - char opchr; /* PDF operator char */ - int n_pts; /* number of *points* */ - const char *strkey; -} petypes[] = { -#define PE_TYPE__INVALID -1 -#define PE_TYPE__MOVETO 0 - {'m', 1, "moveto" }, -#define PE_TYPE__LINETO 1 - {'l', 1, "lineto" }, -#define PE_TYPE__CURVETO 2 - {'c', 3, "curveto" }, - /* no PS correspondence for v and y */ -#define PE_TYPE__CURVETO_V 3 - {'v', 2, "vcurveto"}, /* current point replicated */ -#define PE_TYPE__CURVETO_Y 4 - {'y', 2, "ycurveto"}, /* last point replicated */ -#define PE_TYPE__CLOSEPATH 5 - {'h', 0, "closepath"}, -#define PE_TYPE__TERMINATE 6 - {' ', 0, NULL} -}; - -#define PE_VALID(p) ((p) && \ - (p)->type > PE_TYPE__INVALID && (p)->type < PE_TYPE__TERMINATE) -#define PE_N_PTS(p) (PE_VALID((p)) ? petypes[(p)->type].n_pts : 0) -#define PE_OPCHR(p) (PE_VALID((p)) ? petypes[(p)->type].opchr : ' ') - -#define PA_LENGTH(pa) ((pa)->num_paths) - -#define GS_FLAG_CURRENTPOINT_SET (1 << 0) - - -#define FORMAT_BUFF_LEN 1024 -static char fmt_buf[FORMAT_BUFF_LEN]; - -static void -init_a_path (pdf_path *p) -{ - ASSERT(p); - - p->num_paths = 0; - p->max_paths = 0; - p->path = NULL; - - return; -} - -static void -pdf_path__clearpath (pdf_path *p) -{ - ASSERT(p); - - p->num_paths = 0; - - return; -} - -static int -pdf_path__growpath (pdf_path *p, int max_pe) -{ - if (max_pe < p->max_paths) - return 0; - - p->max_paths = MAX(p->max_paths + 8, max_pe); - p->path = RENEW(p->path, p->max_paths, pa_elem); - - return 0; -} - -static void -clear_a_path (pdf_path *p) -{ - ASSERT(p); - - if (p->path) - RELEASE(p->path); - p->path = NULL; - p->num_paths = 0; - p->max_paths = 0; - - return; -} - -static int -pdf_path__copypath (pdf_path *p1, const pdf_path *p0) -{ - pa_elem *pe0, *pe1; - int i; - - pdf_path__growpath(p1, PA_LENGTH(p0)); - for (i = 0; i < PA_LENGTH(p0); i++) { - pe1 = &(p1->path[i]); - pe0 = &(p0->path[i]); - /* FIXME */ - pe1->type = pe0->type; - pe1->p[0].x = pe0->p[0].x; - pe1->p[0].y = pe0->p[0].y; - pe1->p[1].x = pe0->p[1].x; - pe1->p[1].y = pe0->p[1].y; - pe1->p[2].x = pe0->p[2].x; - pe1->p[2].y = pe0->p[2].y; - } - p1->num_paths = PA_LENGTH(p0); - - return 0; -} - - -/* start new subpath */ -static int -pdf_path__moveto (pdf_path *pa, - pdf_coord *cp, - const pdf_coord *p0) -{ - pa_elem *pe; - - pdf_path__growpath(pa, PA_LENGTH(pa) + 1); - if (PA_LENGTH(pa) > 0) { - pe = &pa->path[pa->num_paths-1]; - if (pe->type == PE_TYPE__MOVETO) { - pe->p[0].x = cp->x = p0->x; - pe->p[0].y = cp->y = p0->y; - return 0; - } - } - pe = &pa->path[pa->num_paths++]; - pe->type = PE_TYPE__MOVETO; - pe->p[0].x = cp->x = p0->x; - pe->p[0].y = cp->y = p0->y; - - return 0; -} - -/* Do 'compression' of path while adding new path elements. - * Sequantial moveto command will be replaced with a - * single moveto. If cp is not equal to the last point in pa, - * then moveto is inserted (starting new subpath). - * FIXME: - * 'moveto' must be used to enforce starting new path. - * This affects how 'closepath' is treated. - */ -static pa_elem * -pdf_path__next_pe (pdf_path *pa, const pdf_coord *cp) -{ - pa_elem *pe; - - pdf_path__growpath(pa, PA_LENGTH(pa) + 2); - if (PA_LENGTH(pa) == 0) { - pe = &pa->path[pa->num_paths++]; - pe->type = PE_TYPE__MOVETO; - pe->p[0].x = cp->x; - pe->p[0].y = cp->y; - - return &pa->path[pa->num_paths++]; - } - - pe = &pa->path[pa->num_paths-1]; - switch (pe->type) { - case PE_TYPE__MOVETO: - pe->p[0].x = cp->x; - pe->p[0].y = cp->y; - break; - case PE_TYPE__LINETO: - if (!COORD_EQUAL(&pe->p[0], cp)) { - pe = &pa->path[pa->num_paths++]; - pe->type = PE_TYPE__MOVETO; - pe->p[0].x = cp->x; - pe->p[0].y = cp->y; - } - break; - case PE_TYPE__CURVETO: - if (!COORD_EQUAL(&pe->p[2], cp)) { - pe = &pa->path[pa->num_paths++]; - pe->type = PE_TYPE__MOVETO; - pe->p[0].x = cp->x; - pe->p[0].y = cp->y; - } - break; - case PE_TYPE__CURVETO_Y: - case PE_TYPE__CURVETO_V: - if (!COORD_EQUAL(&pe->p[1], cp)) { - pe = &pa->path[pa->num_paths++]; - pe->type = PE_TYPE__MOVETO; - pe->p[0].x = cp->x; - pe->p[0].y = cp->y; - } - break; - case PE_TYPE__CLOSEPATH: - pe = &pa->path[pa->num_paths++]; - pe->type = PE_TYPE__MOVETO; - pe->p[0].x = cp->x; - pe->p[0].y = cp->y; - break; - } - - return &pa->path[pa->num_paths++]; -} - -static int -pdf_path__transform (pdf_path *pa, const pdf_tmatrix *M) -{ - pa_elem *pe; - int n = 0, i; - - ASSERT(pa && M); - - for (i = 0; i < PA_LENGTH(pa); i++) { - pe = &(pa->path[i]); - n = PE_N_PTS(pe); - while (n-- > 0) - pdf_coord__transform(&(pe->p[n]), M); - } - - return 0; -} - - -/* Path Construction */ -static int -pdf_path__lineto (pdf_path *pa, - pdf_coord *cp, - const pdf_coord *p0) -{ - pa_elem *pe; - - pe = pdf_path__next_pe(pa, cp); - pe->type = PE_TYPE__LINETO; - pe->p[0].x = cp->x = p0->x; - pe->p[0].y = cp->y = p0->y; - - return 0; -} - -static int -pdf_path__curveto (pdf_path *pa, - pdf_coord *cp, - const pdf_coord *p0, - const pdf_coord *p1, - const pdf_coord *p2 - ) -{ - pa_elem *pe; - - pe = pdf_path__next_pe(pa, cp); - if (COORD_EQUAL(cp, p0)) { - pe->type = PE_TYPE__CURVETO_V; - pe->p[0].x = p1->x; - pe->p[0].y = p1->y; - pe->p[1].x = cp->x = p2->x; - pe->p[1].y = cp->y = p2->y; - } else if (COORD_EQUAL(p1, p2)) { - pe->type = PE_TYPE__CURVETO_Y; - pe->p[0].x = p0->x; - pe->p[0].y = p0->y; - pe->p[1].x = cp->x = p1->x; - pe->p[1].y = cp->y = p1->y; - } else { - pe->type = PE_TYPE__CURVETO; - pe->p[0].x = p0->x; - pe->p[0].y = p0->y; - pe->p[1].x = p1->x; - pe->p[1].y = p1->y; - pe->p[2].x = cp->x = p2->x; - pe->p[2].y = cp->y = p2->y; - } - - return 0; -} - -#if 0 -#define QB_TWO_THIRD (2.0/3.0) -#define QB_ONE_THIRD (1.0/3.0) - -static int -pdf_path__curveto_QB (pdf_path *pa, - pdf_coord *cp, - const pdf_coord *p0, - const pdf_coord *p1 - ) -{ - pdf_coord q0, q1; - - q0.x = cp->x + QB_TWO_THIRD * (p0->x - cp->x); - q0.y = cp->y + QB_TWO_THIRD * (p0->y - cp->y); - q1.x = p0->x + QB_ONE_THIRD * (p1->x - p0->x); - q1.y = p0->y + QB_ONE_THIRD * (p1->y - p0->y); - /* q2 == p1 */ - - return pdf_path__curveto(pa, cp, &q0, &q1, p1); -} -#endif - - -/* This isn't specified as cp to somewhere. */ -static int -pdf_path__elliptarc (pdf_path *pa, - pdf_coord *cp, - const pdf_coord *ca, /* ellipsis center */ - double r_x, /* x radius */ - double r_y, /* y radius */ - double xar, /* x-axis-rotation (deg!) */ - double a_0, /* start angle */ - double a_1, /* stop angle */ - int a_d /* arc orientation */ - ) -{ - double b, b_x, b_y; - double d_a, q; - pdf_coord p0, p1, p2, p3; - pdf_coord e0, e1; - pdf_tmatrix T; - int n_c; /* number of segments */ - int i, error = 0; - - if (fabs(r_x) < OUR_EPSILON || - fabs(r_y) < OUR_EPSILON) - return -1; - - if (a_d < 0) { - for ( ; a_1 > a_0; a_1 -= 360.0); - } else { - for ( ; a_1 < a_0; a_0 -= 360.0); - } - - d_a = a_1 - a_0; - for (n_c = 1; fabs(d_a) > 90.0 * n_c; n_c++); - d_a /= n_c; - if (fabs(d_a) < OUR_EPSILON) - return -1; - - a_0 *= M_PI / 180.0; - a_1 *= M_PI / 180.0; - d_a *= M_PI / 180.0; - xar *= M_PI / 180.0; - T.a = cos(xar); T.c = -sin(xar); - T.b = -T.c ; T.d = T.a; - T.e = 0.0 ; T.f = 0.0; - - /* A parameter that controls cb-curve (off-curve) points */ - b = 4.0 * (1.0 - cos(.5 * d_a)) / (3.0 * sin(.5 * d_a)); - b_x = r_x * b; - b_y = r_y * b; - - p0.x = r_x * cos(a_0); - p0.y = r_y * sin(a_0); - pdf_coord__transform(&p0, &T); - p0.x += ca->x; p0.y += ca->y; - if (PA_LENGTH(pa) == 0) { - pdf_path__moveto(pa, cp, &p0); - } else if (!COORD_EQUAL(cp, &p0)) { - pdf_path__lineto(pa, cp, &p0); /* add line seg */ - } - for (i = 0; !error && i < n_c; i++) { - q = a_0 + i * d_a; - e0.x = cos(q); e0.y = sin(q); - e1.x = cos(q + d_a); e1.y = sin(q + d_a); - - /* Condition for tangent vector requirs - * d1 = p1 - p0 = f ( sin a, -cos a) - * d2 = p2 - p3 = g ( sin b, -cos b) - * and from symmetry - * g^2 = f^2 - */ - p0.x = r_x * e0.x; /* s.p. */ - p0.y = r_y * e0.y; - p3.x = r_x * e1.x; /* e.p. */ - p3.y = r_y * e1.y; - - p1.x = -b_x * e0.y; - p1.y = b_y * e0.x; - p2.x = b_x * e1.y; - p2.y = -b_y * e1.x; - - pdf_coord__transform(&p0, &T); - pdf_coord__transform(&p1, &T); - pdf_coord__transform(&p2, &T); - pdf_coord__transform(&p3, &T); - p0.x += ca->x; p0.y += ca->y; - p3.x += ca->x; p3.y += ca->y; - p1.x += p0.x ; p1.y += p0.y ; - p2.x += p3.x ; p2.y += p3.y ; - - error = pdf_path__curveto(pa, &p0, &p1, &p2, &p3); - cp->x = p3.x; cp->y = p3.y; - } - - return error; -} - -static int -pdf_path__closepath (pdf_path *pa, pdf_coord *cp /* no arg */) -{ - pa_elem *pe = NULL; - int i; - - /* search for start point of the last subpath */ - for (i = PA_LENGTH(pa) - 1; i >= 0; i--) { - pe = &pa->path[i]; - if (pe->type == PE_TYPE__MOVETO) - break; - } - - if (!pe || i < 0) - return -1; /* No path or no start point(!) */ - - cp->x = pe->p[0].x; - cp->y = pe->p[0].y; - - pdf_path__growpath(pa, PA_LENGTH(pa) + 1); - - /* NOTE: - * Manually closed path without closepath is not - * affected by linejoin. A path with coincidental - * starting and ending point is not the same as - * 'closed' path. - */ - pe = &pa->path[pa->num_paths++]; - pe->type = PE_TYPE__CLOSEPATH; - - return 0; -} - -/* - * x y width height re - * - * is equivalent to - * - * x y m - * (x + width) y l - * (x + width) (y + height) l - * x (y + height) l - * h - */ -/* Just for quick test */ -static /* __inline__ */ int -pdf_path__isarect (pdf_path *pa, - int f_ir /* fill-rule is ignorable */ - ) -{ - pa_elem *pe0, *pe1, *pe2, *pe3, *pe4; - - if (PA_LENGTH(pa) == 5) { - pe0 = &(pa->path[0]); - pe1 = &(pa->path[1]); - pe2 = &(pa->path[2]); - pe3 = &(pa->path[3]); - pe4 = &(pa->path[4]); - if (pe0->type == PE_TYPE__MOVETO && - pe1->type == PE_TYPE__LINETO && - pe2->type == PE_TYPE__LINETO && - pe3->type == PE_TYPE__LINETO && - pe4->type == PE_TYPE__CLOSEPATH) { - if (pe1->p[0].y - pe0->p[0].y == 0 && - pe2->p[0].x - pe1->p[0].x == 0 && - pe3->p[0].y - pe2->p[0].y == 0) { - if (pe1->p[0].x - pe0->p[0].x - == pe2->p[0].x - pe3->p[0].x) { - return 1; - } - /* Winding number is different but ignore it here. */ - } else if (f_ir && - pe1->p[0].x - pe0->p[0].x == 0 && - pe2->p[0].y - pe1->p[0].y == 0 && - pe3->p[0].x - pe2->p[0].x == 0) { - if (pe1->p[0].y - pe0->p[0].y - == pe2->p[0].y - pe3->p[0].y) { - return 1; - } - } - } - } - - return 0; -} - -/* Path Painting */ -/* F is obsoleted */ -#define PT_OP_VALID(c) ( \ - (c) == 'f' || (c) == 'F' || \ - (c) == 's' || (c) == 'S' || \ - (c) == 'b' || (c) == 'B' || \ - (c) == 'W' \ -) - -static /* __inline__ */ int -INVERTIBLE_MATRIX (const pdf_tmatrix *M) -{ - if (fabs(detP(M)) < OUR_EPSILON) { - WARN("Transformation matrix not invertible."); - WARN("--- M = [%g %g %g %g %g %g]", - M->a, M->b, M->c, M->d, M->e, M->f); - return -1; - } - return 0; -} - -/* rectfill, rectstroke, rectclip, recteoclip - * - * Draw isolated rectangle without actually doing gsave/grestore operation. - * - * TODO: - * linestyle, fill-opacity, stroke-opacity,.... - * As this routine draw a single graphics object - * each time, there should be options for specifying - * various drawing styles, which might inherite - * current graphcs state parameter. - */ -static int -pdf_dev__rectshape (const pdf_rect *r, - const pdf_tmatrix *M, - char opchr - ) -{ - char *buf = fmt_buf; - int len = 0; - int isclip = 0; - pdf_coord p; - double wd, ht; - - ASSERT(r && PT_OP_VALID(opchr)); - - isclip = (opchr == 'W') ? 1 : 0; - - /* disallow matrix for clipping. - * q ... clip Q does nothing and - * n M cm ... clip n alter CTM. - */ - if (M && (isclip || - !INVERTIBLE_MATRIX(M))) - return -1; - - graphics_mode(); - - if (!isclip) { - pdf_dev_gsave(); - } - pdf_dev_newpath(); - if (!isclip && M) { - pdf_dev_concat(M); - } - - p.x = r->llx; p.y = r->lly; - wd = r->urx - r->llx; - ht = r->ury - r->lly; - buf[len++] = ' '; - len += pdf_sprint_coord (buf + len, &p); - buf[len++] = ' '; - len += pdf_sprint_length(buf + len, wd); - buf[len++] = ' '; - len += pdf_sprint_length(buf + len, ht); - buf[len++] = ' '; - buf[len++] = 'r'; buf[len++] = 'e'; - - buf[len++] = ' '; - buf[len++] = opchr; - - pdf_doc_add_page_content(buf, len); - - if (isclip) { - pdf_dev_newpath(); - } else { - pdf_dev_grestore(); - } - - return 0; -} - -/* FIXME */ -static int -pdf_dev__flushpath (pdf_path *pa, - char opchr, - int rule, - int ignore_rule) -{ - pa_elem *pe, *pe1; - char *b = fmt_buf; - int b_len = FORMAT_BUFF_LEN; - pdf_rect r; /* FIXME */ - pdf_coord *pt; - int n_pts, n_seg; - int len = 0; - int isrect, i, j; - - ASSERT(pa && PT_OP_VALID(opchr)); - - if (PA_LENGTH(pa) <= 0) - return 0; - - graphics_mode(); - isrect = pdf_path__isarect(pa, ignore_rule); - if (isrect) { - pe = &(pa->path[0]); - pe1 = &(pa->path[2]); - - r.llx = pe->p[0].x; - r.lly = pe->p[0].y; - r.urx = pe1->p[0].x - pe->p[0].x; /* width... */ - r.ury = pe1->p[0].y - pe->p[0].y; /* height... */ - - b[len++] = ' '; - len += pdf_sprint_rect(b + len, &r); - b[len++] = ' '; - b[len++] = 'r'; - b[len++] = 'e'; - pdf_doc_add_page_content(b, len); /* op: re */ - len = 0; - } else { - n_seg = PA_LENGTH(pa); - for (i = 0, len = 0, pe = &pa->path[0]; - i < n_seg; pe++, i++) { - n_pts = PE_N_PTS(pe); - for (j = 0, pt = &pe->p[0]; - j < n_pts; j++, pt++) { - b[len++] = ' '; - len += pdf_sprint_coord(b + len, pt); - } - b[len++] = ' '; - b[len++] = PE_OPCHR(pe); - if (len + 128 > b_len) { - pdf_doc_add_page_content(b, len); /* op: m l c v y h */ - len = 0; - } - } - if (len > 0) { - pdf_doc_add_page_content(b, len); /* op: m l c v y h */ - len = 0; - } - } - - b[len++] = ' '; - b[len++] = opchr; - if (rule == PDF_FILL_RULE_EVENODD) - b[len++] = '*'; - - pdf_doc_add_page_content(b, len); /* op: f F s S b B W f* F* s* S* b* B* W* */ - - return 0; -} - -/* ExtGState stack */ -static dpx_stack xgs_stack; -static int xgs_count = 0; - -struct xgs_res { - pdf_obj *object; - pdf_obj *accumlated; -}; - -static const char default_xgs[] = "\ -<< /Type /ExtGState\ - /LW 1 /LC 0 /LJ 0 /ML 10 /D [[] 0]\ - /RI /RelativeColorimetric /SA false /BM /Normal /SMask /None\ - /AIS false /TK false /CA 1 /ca 1\ - /OP false /op false /OPM 0 /FL 1\ ->>"; - -static void -init_xgstate (void) -{ - dpx_stack_init(&xgs_stack); - xgs_count = 0; - - return; -} - -static void -clear_xgstate (void) -{ - struct xgs_res *xgs; - - while ((xgs = dpx_stack_pop(&xgs_stack)) != NULL) { - pdf_release_obj(xgs->object); - pdf_release_obj(xgs->accumlated); - RELEASE(xgs); - } - - return; -} - -/* Graphics State */ -typedef struct pdf_gstate_ -{ - pdf_coord cp; - - pdf_tmatrix matrix; /* cm, - */ - - pdf_color strokecolor; - pdf_color fillcolor; - /* colorspace here */ - - struct { - int num_dash; - double pattern[PDF_DASH_SIZE_MAX]; - double offset; - } linedash; /* d, D */ - - double linewidth; /* w, LW */ - - int linecap; /* J, LC */ - int linejoin; /* j, LJ */ - double miterlimit; /* M, ML */ - - int flatness; /* i, FL, 0 to 100 (0 for use device-default) */ - - /* internal */ - pdf_path path; - int flags; - - pdf_obj *extgstate; -} pdf_gstate; - -static dpx_stack gs_stack; - -static void -init_a_gstate (pdf_gstate *gs) -{ - gs->cp.x = 0.0; - gs->cp.y = 0.0; - - pdf_setmatrix(&gs->matrix, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); - - pdf_color_black(&gs->strokecolor); - pdf_color_black(&gs->fillcolor); - - gs->linedash.num_dash = 0; - gs->linedash.offset = 0; - gs->linecap = 0; - gs->linejoin = 0; - gs->linewidth = 1.0; - gs->miterlimit = 10.0; - - gs->flatness = 1; /* default to 1 in PDF */ - - /* Internal variables */ - gs->flags = 0; - init_a_path(&gs->path); - - gs->extgstate = NULL; - - return; -} - -static void -clear_a_gstate (pdf_gstate *gs) -{ - clear_a_path(&gs->path); - if (gs->extgstate) - pdf_release_obj(gs->extgstate); - memset(gs, 0, sizeof(pdf_gstate)); - - return; -} - -static void -copy_a_gstate (pdf_gstate *gs1, pdf_gstate *gs2) -{ - int i; - - ASSERT(gs1 && gs2); - - gs1->cp.x = gs2->cp.x; - gs1->cp.y = gs2->cp.y; - - pdf_copymatrix(&gs1->matrix, &gs2->matrix); - - /* TODO: - * Path should be linked list and gsave only - * record starting point within path rather than - * copying whole path. - */ - pdf_path__copypath(&gs1->path, &gs2->path); - - gs1->linedash.num_dash = gs2->linedash.num_dash; - for (i = 0; i < gs2->linedash.num_dash; i++) { - gs1->linedash.pattern[i] = gs2->linedash.pattern[i]; - } - gs1->linedash.offset = gs2->linedash.offset; - - gs1->linecap = gs2->linecap; - gs1->linejoin = gs2->linejoin; - gs1->linewidth = gs2->linewidth; - gs1->miterlimit = gs2->miterlimit; - gs1->flatness = gs2->flatness; - - pdf_color_copycolor(&gs1->fillcolor , &gs2->fillcolor); - pdf_color_copycolor(&gs1->strokecolor, &gs2->strokecolor); - - gs1->extgstate = gs2->extgstate ? pdf_link_obj(gs2->extgstate) : NULL; - - return; -} - -static int -pdf_dev_set_xgstate (pdf_obj *diff, pdf_obj *accumlated) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - char buf[64], res_name[16]; - int len = 0, id; - - id = xgs_count; - snprintf(res_name, 16, "DPX_GS%d", id); - res_name[15] = '\0'; - len += snprintf(buf, 64, " /%s gs", res_name); - pdf_doc_add_page_content(buf, len); - pdf_doc_add_page_resource("ExtGState", res_name, pdf_link_obj(diff)); - if (gs->extgstate) - pdf_release_obj(gs->extgstate); - gs->extgstate = pdf_link_obj(accumlated); - xgs_count++; - - return 0; -} - -int -pdf_dev_reset_xgstate (int force) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs; - pdf_obj *current, *target, *keys, *diff; - struct xgs_res *xgs; - int i, need_reset = 0; - - gs = dpx_stack_top(gss); - xgs = dpx_stack_top(&xgs_stack); - if (xgs) { - target = pdf_link_obj(xgs->accumlated); - } else { - const char *ptr, *endptr; - - if (!gs->extgstate && !force) - return 0; - ptr = default_xgs; - endptr = ptr + strlen(ptr); - target = parse_pdf_dict(&ptr, endptr, NULL); - } - if (gs->extgstate) { - current = pdf_link_obj(gs->extgstate); - } else { - const char *ptr, *endptr; - ptr = default_xgs; - endptr = ptr + strlen(ptr); - current = parse_pdf_dict(&ptr, endptr, NULL); - } - - diff = pdf_new_dict(); - keys = pdf_dict_keys(target); - for (i = 0; i < pdf_array_length(keys); i++) { - pdf_obj *key, *value1, *value2; - int is_diff = 0; - - key = pdf_get_array(keys, i); - value1 = pdf_lookup_dict(target, pdf_name_value(key)); - value2 = pdf_lookup_dict(current, pdf_name_value(key)); - is_diff = pdf_compare_object(value1, value2); - if (is_diff) { - pdf_add_dict(diff, pdf_link_obj(key), pdf_link_obj(value1)); - need_reset = 1; - } - } - pdf_release_obj(keys); - if (need_reset) - pdf_dev_set_xgstate(diff, target); - pdf_release_obj(diff); - pdf_release_obj(current); - pdf_release_obj(target); - - return 0; -} - -void -pdf_dev_xgstate_push (pdf_obj *object) -{ - struct xgs_res *target, *current; - pdf_obj *accumlated; - - target = NEW(1, struct xgs_res); - target->object = object; - current = dpx_stack_top(&xgs_stack); - if (!current) { - const char *ptr, *endptr; - ptr = default_xgs; - endptr = ptr + strlen(default_xgs); - accumlated = parse_pdf_dict(&ptr, endptr, NULL); - } else { - accumlated = pdf_new_dict(); - pdf_merge_dict(accumlated, current->accumlated); - } - pdf_merge_dict(accumlated, object); - target->accumlated = accumlated; - dpx_stack_push(&xgs_stack, target); - - pdf_dev_set_xgstate(target->object, target->accumlated); - - return; -} - -void -pdf_dev_xgstate_pop (void) -{ - struct xgs_res *current, *target; - pdf_obj *accumlated, *revert, *keys; - int i; - - current = dpx_stack_pop(&xgs_stack); - target = dpx_stack_top(&xgs_stack); - if (!current) { - WARN("Too many pop operation for ExtGState!"); - return; - } - if (!target) { - const char *ptr, *endptr; - ptr = default_xgs; - endptr = ptr + strlen(default_xgs); - accumlated = parse_pdf_dict(&ptr, endptr, NULL); - } else { - accumlated = pdf_link_obj(target->accumlated); - } - keys = pdf_dict_keys(current->object); - revert = pdf_new_dict(); - for (i = 0; i < pdf_array_length(keys); i++) { - pdf_obj *key, *value; - key = pdf_get_array(keys, i); - value = pdf_lookup_dict(accumlated, pdf_name_value(key)); - if (!value) { - WARN("No previous ExtGState entry known for \"%s\", ignoring...", pdf_name_value(key)); - } else { - pdf_add_dict(revert, pdf_link_obj(key), pdf_link_obj(value)); - } - } - pdf_dev_set_xgstate(revert, accumlated); - pdf_release_obj(revert); - pdf_release_obj(keys); - pdf_release_obj(accumlated); - - pdf_release_obj(current->object); - pdf_release_obj(current->accumlated); - RELEASE(current); - - return; -} - -void -pdf_dev_init_gstates (void) -{ - pdf_gstate *gs; - - dpx_stack_init(&gs_stack); - - gs = NEW(1, pdf_gstate); - init_a_gstate(gs); - - dpx_stack_push(&gs_stack, gs); /* Initial state */ - init_xgstate(); - - return; -} - -void -pdf_dev_clear_gstates (void) -{ - pdf_gstate *gs; - - if (dpx_stack_depth(&gs_stack) > 1) /* at least 1 elem. */ - WARN("GS stack depth is not zero at the end of the document."); - - while ((gs = dpx_stack_pop(&gs_stack)) != NULL) { - clear_a_gstate(gs); - RELEASE(gs); - } - - clear_xgstate(); - - return; -} - -int -pdf_dev_gsave (void) -{ - pdf_gstate *gs0, *gs1; - - gs0 = dpx_stack_top(&gs_stack); - gs1 = NEW(1, pdf_gstate); - init_a_gstate(gs1); - copy_a_gstate(gs1, gs0); - dpx_stack_push(&gs_stack, gs1); - - pdf_doc_add_page_content(" q", 2); /* op: q */ - - return 0; -} - -int -pdf_dev_grestore (void) -{ - pdf_gstate *gs; - - if (dpx_stack_depth(&gs_stack) <= 1) { /* Initial state at bottom */ - WARN("Too many grestores."); - return -1; - } - - gs = dpx_stack_pop(&gs_stack); - clear_a_gstate(gs); - RELEASE(gs); - - pdf_doc_add_page_content(" Q", 2); /* op: Q */ - - pdf_dev_reset_fonts(0); - - return 0; -} - - -int -pdf_dev_push_gstate (void) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs0; - - gs0 = NEW(1, pdf_gstate); - - init_a_gstate(gs0); - - dpx_stack_push(gss, gs0); - - return 0; -} - - -int -pdf_dev_pop_gstate (void) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs; - - if (dpx_stack_depth(gss) <= 1) { /* Initial state at bottom */ - WARN("Too many grestores."); - return -1; - } - - gs = dpx_stack_pop(gss); - clear_a_gstate(gs); - RELEASE(gs); - - return 0; -} - - -int -pdf_dev_current_depth (void) -{ - return (dpx_stack_depth(&gs_stack) - 1); /* 0 means initial state */ -} - -void -pdf_dev_grestore_to (int depth) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs; - - ASSERT(depth >= 0); - - if (dpx_stack_depth(gss) > depth + 1) { - WARN("Closing pending transformations at end of page/XObject."); - } - - while (dpx_stack_depth(gss) > depth + 1) { - pdf_doc_add_page_content(" Q", 2); /* op: Q */ - gs = dpx_stack_pop(gss); - clear_a_gstate(gs); - RELEASE(gs); - } - pdf_dev_reset_fonts(0); - - return; -} - -int -pdf_dev_currentpoint (pdf_coord *p) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - pdf_coord *cpt = &gs->cp; - - ASSERT(p); - - p->x = cpt->x; p->y = cpt->y; - - return 0; -} - -int -pdf_dev_currentmatrix (pdf_tmatrix *M) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - pdf_tmatrix *CTM = &gs->matrix; - - ASSERT(M); - - pdf_copymatrix(M, CTM); - - return 0; -} - -#if 0 -int -pdf_dev_currentcolor (pdf_color *color, int is_fill) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - pdf_color *fcl = &gs->fillcolor; - pdf_color *scl = &gs->strokecolor; - - ASSERT(color); - - pdf_color_copycolor(color, is_fill ? fcl : scl); - - return 0; -} -#endif /* 0 */ - -/* - * FIXME: Please use a macro instead of using 0x20! - * mask == 0 means stroking color, mask == 0x20 nonstroking color - * - * force == 1 means that operators will be generated even if - * the color is the same as the current graphics state color - */ -void -pdf_dev_set_color (const pdf_color *color, char mask, int force) -{ - int len; - - pdf_gstate *gs = dpx_stack_top(&gs_stack); - pdf_color *current = mask ? &gs->fillcolor : &gs->strokecolor; - - if (!(pdf_dev_get_param(PDF_DEV_PARAM_COLORMODE) && - (force || pdf_color_compare(color, current)))) - /* If "color" is already the current color, then do nothing - * unless a color operator is forced - */ - return; - - graphics_mode(); - len = pdf_color_set_color(color, fmt_buf, FORMAT_BUFF_LEN, mask); - pdf_doc_add_page_content(fmt_buf, len); /* op: RG K G rg k g etc. */ - pdf_color_copycolor(current, color); -} - -int -pdf_dev_concat (const pdf_tmatrix *M) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - pdf_path *cpa = &gs->path; - pdf_coord *cpt = &gs->cp; - pdf_tmatrix *CTM = &gs->matrix; - pdf_tmatrix W = {0, 0, 0, 0, 0, 0}; /* Init to avoid compiler warning */ - char *buf = fmt_buf; - int len = 0; - - ASSERT(M); - - /* Adobe Reader erases page content if there are - * non invertible transformation. - */ - if (fabs(detP(M)) < OUR_EPSILON) { - WARN("Transformation matrix not invertible."); - WARN("--- M = [%g %g %g %g %g %g]", - M->a, M->b, M->c, M->d, M->e, M->f); - return -1; - } - - if (fabs(M->a - 1.0) > OUR_EPSILON || fabs(M->b) > OUR_EPSILON - || fabs(M->c) > OUR_EPSILON || fabs(M->d - 1.0) > OUR_EPSILON - || fabs(M->e) > OUR_EPSILON || fabs(M->f) > OUR_EPSILON) { - buf[len++] = ' '; - len += pdf_sprint_matrix(buf + len, M); - buf[len++] = ' '; - buf[len++] = 'c'; - buf[len++] = 'm'; - pdf_doc_add_page_content(buf, len); /* op: cm */ - - pdf_concatmatrix(CTM, M); - } - inversematrix(&W, M); - - pdf_path__transform (cpa, &W); - pdf_coord__transform(cpt, &W); - - return 0; -} - -/* - * num w LW linewidth (g.t. 0) - * int J LC linecap - * int j LJ linejoin - * num M ML miter limit (g.t. 0) - * array num d D line dash - * int ri RI renderint intnet - * int i FL flatness tolerance (0-100) - * name gs -- name: res. name of ExtGState dict. - */ -int -pdf_dev_setmiterlimit (double mlimit) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - int len = 0; - char *buf = fmt_buf; - - if (gs->miterlimit != mlimit) { - buf[len++] = ' '; - len += pdf_sprint_length(buf + len, mlimit); - buf[len++] = ' '; - buf[len++] = 'M'; - pdf_doc_add_page_content(buf, len); /* op: M */ - gs->miterlimit = mlimit; - } - - return 0; -} - -int -pdf_dev_setlinecap (int capstyle) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - int len = 0; - char *buf = fmt_buf; - - if (gs->linecap != capstyle) { - len = sprintf(buf, " %d J", capstyle); - pdf_doc_add_page_content(buf, len); /* op: J */ - gs->linecap = capstyle; - } - - return 0; -} - -int -pdf_dev_setlinejoin (int joinstyle) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - int len = 0; - char *buf = fmt_buf; - - if (gs->linejoin != joinstyle) { - len = sprintf(buf, " %d j", joinstyle); - pdf_doc_add_page_content(buf, len); /* op: j */ - gs->linejoin = joinstyle; - } - - return 0; -} - -int -pdf_dev_setlinewidth (double width) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - int len = 0; - char *buf = fmt_buf; - - if (gs->linewidth != width) { - buf[len++] = ' '; - len += pdf_sprint_length(buf + len, width); - buf[len++] = ' '; - buf[len++] = 'w'; - pdf_doc_add_page_content(buf, len); /* op: w */ - gs->linewidth = width; - } - - return 0; -} - -int -pdf_dev_setdash (int count, double *pattern, double offset) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - int len = 0; - char *buf = fmt_buf; - int i; - - gs->linedash.num_dash = count; - gs->linedash.offset = offset; - pdf_doc_add_page_content(" [", 2); /* op: */ - for (i = 0; i < count; i++) { - buf[0] = ' '; - len = pdf_sprint_length (buf + 1, pattern[i]); - pdf_doc_add_page_content(buf, len + 1); /* op: */ - gs->linedash.pattern[i] = pattern[i]; - } - pdf_doc_add_page_content("] ", 2); /* op: */ - len = pdf_sprint_length (buf, offset); - pdf_doc_add_page_content(buf, len); /* op: */ - pdf_doc_add_page_content(" d", 2); /* op: d */ - - return 0; -} - -#if 0 -int -pdf_dev_setflat (int flatness) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - int len = 0; - char *buf = fmt_buf; - - if (flatness < 0 || flatness > 100) - return -1; - - if (gs->flatness != flatness) { - gs->flatness = flatness; - len = sprintf(buf, " %d i", flatness); - pdf_doc_add_page_content(buf, len); /* op: i */ - } - - return 0; -} -#endif - -/* ZSYUEDVEDEOF */ -int -pdf_dev_clip (void) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - pdf_path *cpa = &gs->path; - - return pdf_dev__flushpath(cpa, 'W', PDF_FILL_RULE_NONZERO, 0); -} - -int -pdf_dev_eoclip (void) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - pdf_path *cpa = &gs->path; - - return pdf_dev__flushpath(cpa, 'W', PDF_FILL_RULE_EVENODD, 0); -} - -int -pdf_dev_flushpath (char p_op, int fill_rule) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - pdf_path *cpa = &gs->path; - int error = 0; - - /* last arg 'ignore_rule' is only for single object - * that can be converted to a rect where fill rule - * is inessential. - */ - error = pdf_dev__flushpath(cpa, p_op, fill_rule, 1); - pdf_path__clearpath(cpa); - - gs->flags &= ~GS_FLAG_CURRENTPOINT_SET; - - return error; -} - -int -pdf_dev_newpath (void) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - pdf_path *p = &gs->path; - - if (PA_LENGTH(p) > 0) { - pdf_path__clearpath (p); - } - /* The following is required for "newpath" operator in mpost.c. */ - pdf_doc_add_page_content(" n", 2); /* op: n */ - - return 0; -} - -int -pdf_dev_moveto (double x, double y) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - pdf_path *cpa = &gs->path; - pdf_coord *cpt = &gs->cp; - pdf_coord p; - - p.x = x; p.y = y; - return pdf_path__moveto(cpa, cpt, &p); /* cpt updated */ -} - -int -pdf_dev_rmoveto (double x, double y) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - pdf_path *cpa = &gs->path; - pdf_coord *cpt = &gs->cp; - pdf_coord p; - - p.x = cpt->x + x; - p.y = cpt->y + y; - return pdf_path__moveto(cpa, cpt, &p); /* cpt updated */ -} - -int -pdf_dev_lineto (double x, double y) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - pdf_path *cpa = &gs->path; - pdf_coord *cpt = &gs->cp; - pdf_coord p0; - - p0.x = x; p0.y = y; - - return pdf_path__lineto(cpa, cpt, &p0); -} - -int -pdf_dev_rlineto (double x, double y) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - pdf_path *cpa = &gs->path; - pdf_coord *cpt = &gs->cp; - pdf_coord p0; - - p0.x = x + cpt->x; p0.y = y + cpt->y; - - return pdf_path__lineto(cpa, cpt, &p0); -} - -int -pdf_dev_curveto (double x0, double y0, - double x1, double y1, - double x2, double y2) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - pdf_path *cpa = &gs->path; - pdf_coord *cpt = &gs->cp; - pdf_coord p0, p1, p2; - - p0.x = x0; p0.y = y0; - p1.x = x1; p1.y = y1; - p2.x = x2; p2.y = y2; - - return pdf_path__curveto(cpa, cpt, &p0, &p1, &p2); -} - -int -pdf_dev_rcurveto (double x0, double y0, - double x1, double y1, - double x2, double y2) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - pdf_path *cpa = &gs->path; - pdf_coord *cpt = &gs->cp; - pdf_coord p0, p1, p2; - - p0.x = x0 + cpt->x; p0.y = y0 + cpt->y; - p1.x = x1 + cpt->x; p1.y = y1 + cpt->y; - p2.x = x2 + cpt->x; p2.y = y2 + cpt->y; - - return pdf_path__curveto(cpa, cpt, &p0, &p1, &p2); -} - - -int -pdf_dev_closepath (void) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - pdf_coord *cpt = &gs->cp; - pdf_path *cpa = &gs->path; - - return pdf_path__closepath(cpa, cpt); -} - - -void -pdf_dev_dtransform (pdf_coord *p, const pdf_tmatrix *M) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - pdf_tmatrix *CTM = &gs->matrix; - - ASSERT(p); - - pdf_coord__dtransform(p, (M ? M : CTM)); - - return; -} - -void -pdf_dev_idtransform (pdf_coord *p, const pdf_tmatrix *M) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - pdf_tmatrix *CTM = &gs->matrix; - - ASSERT(p); - - pdf_coord__idtransform(p, (M ? M : CTM)); - - return; -} - -void -pdf_dev_transform (pdf_coord *p, const pdf_tmatrix *M) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - pdf_tmatrix *CTM = &gs->matrix; - - ASSERT(p); - - pdf_coord__transform(p, (M ? M : CTM)); - - return; -} - -void -pdf_dev_itransform (pdf_coord *p, const pdf_tmatrix *M) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - pdf_tmatrix *CTM = &gs->matrix; - - ASSERT(p); - - pdf_coord__itransform(p, (M ? M : CTM)); - - return; -} - -int -pdf_dev_arc (double c_x , double c_y, double r, - double a_0 , double a_1) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - pdf_path *cpa = &gs->path; - pdf_coord *cpt = &gs->cp; - pdf_coord c; - - c.x = c_x; c.y = c_y; - - return pdf_path__elliptarc(cpa, cpt, &c, r, r, 0.0, a_0, a_1, +1); -} - -/* *negative* arc */ -int -pdf_dev_arcn (double c_x , double c_y, double r, - double a_0 , double a_1) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - pdf_path *cpa = &gs->path; - pdf_coord *cpt = &gs->cp; - pdf_coord c; - - c.x = c_x; c.y = c_y; - - return pdf_path__elliptarc(cpa, cpt, &c, r, r, 0.0, a_0, a_1, -1); -} - -int -pdf_dev_arcx (double c_x , double c_y, - double r_x , double r_y, - double a_0 , double a_1, - int a_d , - double xar) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - pdf_path *cpa = &gs->path; - pdf_coord *cpt = &gs->cp; - pdf_coord c; - - c.x = c_x; c.y = c_y; - - return pdf_path__elliptarc(cpa, cpt, &c, r_x, r_y, xar, a_0, a_1, a_d); -} - -/* Required by Tpic */ -int -pdf_dev_bspline (double x0, double y0, - double x1, double y1, double x2, double y2) -{ - dpx_stack *gss = &gs_stack; - pdf_gstate *gs = dpx_stack_top(gss); - pdf_path *cpa = &gs->path; - pdf_coord *cpt = &gs->cp; - pdf_coord p1, p2, p3; - - p1.x = x0 + 2.0 * (x1 - x0) / 3.0; - p1.y = y0 + 2.0 * (y1 - y0) / 3.0; - p2.x = x1 + (x2 - x1) / 3.0; - p2.y = y1 + (y2 - y1) / 3.0; - p3.x = x2; - p3.y = y2; - - return pdf_path__curveto(cpa, cpt, &p1, &p2, &p3); -} - -int -pdf_dev_rectstroke (double x, double y, - double w, double h, - const pdf_tmatrix *M /* optional */ - ) -{ - pdf_rect r; - - r.llx = x; - r.lly = y; - r.urx = x + w; - r.ury = y + h; - - return pdf_dev__rectshape(&r, M, 'S'); -} - -int -pdf_dev_rectfill (double x, double y, - double w, double h) -{ - pdf_rect r; - - r.llx = x; - r.lly = y; - r.urx = x + w; - r.ury = y + h; - - return pdf_dev__rectshape(&r, NULL, 'f'); -} - -int -pdf_dev_rectclip (double x, double y, - double w, double h) -{ - pdf_rect r; - - r.llx = x; - r.lly = y; - r.urx = x + w; - r.ury = y + h; - - return pdf_dev__rectshape(&r, NULL, 'W'); -} |