diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/pdf/pdfsetmatrix.w')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/pdf/pdfsetmatrix.w | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/pdf/pdfsetmatrix.w b/Build/source/texk/web2c/luatexdir/pdf/pdfsetmatrix.w new file mode 100644 index 00000000000..765ac0fb1e2 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/pdf/pdfsetmatrix.w @@ -0,0 +1,238 @@ +% pdfsetmatrix.w +% +% Copyright 2009 Taco Hoekwater <taco@@luatex.org> + +% This file is part of LuaTeX. + +% LuaTeX 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. + +% LuaTeX 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 Lesser General Public +% License for more details. + +% You should have received a copy of the GNU General Public License along +% with LuaTeX; if not, see <http://www.gnu.org/licenses/>. + +@ @c +static const char _svn_version[] = + "$Id: pdfsetmatrix.w 3571 2010-04-02 13:50:45Z taco $ " + "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.60.0/source/texk/web2c/luatexdir/pdf/pdfsetmatrix.w $"; + +#include "ptexlib.h" + +@ stack for \.{\\pdfsetmatrix} + +@c +matrix_entry *matrix_stack = NULL; +int matrix_stack_size = 0; +int matrix_stack_used = 0; + +@ @c +boolean matrixused(void) +{ + return matrix_stack_used > 0; +} + +void matrix_stack_room(void) +{ + matrix_entry *new_stack; + + if (matrix_stack_used >= matrix_stack_size) { + matrix_stack_size += STACK_INCREMENT; + new_stack = xtalloc((unsigned) matrix_stack_size, matrix_entry); + memcpy((void *) new_stack, (void *) matrix_stack, + (unsigned) matrix_stack_used * sizeof(matrix_entry)); + xfree(matrix_stack); + matrix_stack = new_stack; + } +} + +@ \.{\\pdfsetmatrix{a b c d}} + + |e| := pos.h + + |f| := pos.v + + |M_top|: current active matrix at the top of + the matrix stack + + The origin of \.{\\pdfsetmatrix} is the current point. + The annotation coordinate system is the original + page coordinate system. When pdfTeX calculates + annotation rectangles it does not take into + account this transformations, it uses the original + coordinate system. To get the corrected values, + first we go back to the origin, perform the + transformation and go back: + +{\obeylines\obeyspaces\tt + ( 1 0 0 ) ( a b 0 ) ( 1 0 0 ) + ( 0 1 0 ) x ( c d 0 ) x ( 0 1 0 ) x M\_top + ( -e -f 1 ) ( 0 0 1 ) ( e f 1 ) + + ( 1 0 0 ) ( a b 0 ) + = ( 0 1 0 ) x ( c d 0 ) x M\_top + ( e f 1 ) ( -e -f 1 ) + + ( a b 0 ) + = ( c d 0 ) x M\_top + ( e(1-a)-fc f(1-d)-eb 1 ) +} + +@c +static void pdfsetmatrix(const char *in, scaledpos pos) +{ + /* Argument of \.{\\pdfsetmatrix} starts with |str_pool[in]| and ends + before |str_pool[pool_ptr]|. */ + + matrix_entry x, *y, *z; + + if (page_mode) { + if (sscanf((const char *) in, " %lf %lf %lf %lf ", + &x.a, &x.b, &x.c, &x.d) != 4) { + pdftex_warn("Unrecognized format of \\pdfsetmatrix{%s}", in); + return; + } + /* calculate this transformation matrix */ + x.e = (double) pos.h * (1.0 - x.a) - (double) pos.v * x.c; + x.f = (double) pos.v * (1.0 - x.d) - (double) pos.h * x.b; + matrix_stack_room(); + z = &matrix_stack[matrix_stack_used]; + if (matrix_stack_used > 0) { + y = &matrix_stack[matrix_stack_used - 1]; + z->a = x.a * y->a + x.b * y->c; + z->b = x.a * y->b + x.b * y->d; + z->c = x.c * y->a + x.d * y->c; + z->d = x.c * y->b + x.d * y->d; + z->e = x.e * y->a + x.f * y->c + y->e; + z->f = x.e * y->b + x.f * y->d + y->f; + } else { + z->a = x.a; + z->b = x.b; + z->c = x.c; + z->d = x.d; + z->e = x.e; + z->f = x.f; + } + matrix_stack_used++; + } +} + +@ Apply matrix to point (x,y) + +{\obeylines\obeyspaces\tt + ( a b 0 ) + ( x y 1 ) x ( c d 0 ) = ( xa+yc+e xb+yd+f 1 ) + ( e f 1 ) +} + +If \.{\\pdfsetmatrix} wasn't used, then return the value unchanged. + +@c +/* Return values for matrix tranform functions */ +static scaled ret_llx; +static scaled ret_lly; +static scaled ret_urx; +static scaled ret_ury; + +scaled getllx(void) +{ + return ret_llx; +} + +scaled getlly(void) +{ + return ret_lly; +} + +scaled geturx(void) +{ + return ret_urx; +} + +scaled getury(void) +{ + return ret_ury; +} + +@ @c +static int last_llx; +static int last_lly; +static int last_urx; +static int last_ury; + +#define DO_ROUND(x) ((x > 0) ? (x + .5) : (x - .5)) +#define DO_MIN(a, b) ((a < b) ? a : b) +#define DO_MAX(a, b) ((a > b) ? a : b) + +void do_matrixtransform(scaled x, scaled y, scaled * retx, scaled * rety) +{ + matrix_entry *m = &matrix_stack[matrix_stack_used - 1]; + double x_old = x; + double y_old = y; + double x_new = x_old * m->a + y_old * m->c + m->e; + double y_new = x_old * m->b + y_old * m->d + m->f; + *retx = (scaled) DO_ROUND(x_new); + *rety = (scaled) DO_ROUND(y_new); +} + +void matrixtransformrect(scaled llx, scaled lly, scaled urx, scaled ury) +{ + scaled x1, x2, x3, x4, y1, y2, y3, y4; + + if (page_mode && matrix_stack_used > 0) { + last_llx = llx; + last_lly = lly; + last_urx = urx; + last_ury = ury; + do_matrixtransform(llx, lly, &x1, &y1); + do_matrixtransform(llx, ury, &x2, &y2); + do_matrixtransform(urx, lly, &x3, &y3); + do_matrixtransform(urx, ury, &x4, &y4); + ret_llx = DO_MIN(DO_MIN(x1, x2), DO_MIN(x3, x4)); + ret_lly = DO_MIN(DO_MIN(y1, y2), DO_MIN(y3, y4)); + ret_urx = DO_MAX(DO_MAX(x1, x2), DO_MAX(x3, x4)); + ret_ury = DO_MAX(DO_MAX(y1, y2), DO_MAX(y3, y4)); + } else { + ret_llx = llx; + ret_lly = lly; + ret_urx = urx; + ret_ury = ury; + } +} + +void matrixtransformpoint(scaled x, scaled y) +{ + if (page_mode && matrix_stack_used > 0) { + do_matrixtransform(x, y, &ret_llx, &ret_lly); + } else { + ret_llx = x; + ret_lly = y; + } +} + +void matrixrecalculate(scaled urx) +{ + matrixtransformrect(last_llx, last_lly, urx, last_ury); +} + +@ @c +void pdf_out_setmatrix(PDF pdf, halfword p) +{ + scaledpos pos = pdf->posstruct->pos; + int old_setting; /* holds print |selector| */ + str_number s; + old_setting = selector; + selector = new_string; + show_token_list(token_link(pdf_setmatrix_data(p)), null, -1); + pdfsetmatrix((char *) cur_string, pos); + tprint(" 0 0 cm"); + selector = old_setting; + s = make_string(); + pdf_literal(pdf, s, set_origin, false); + flush_str(s); +} |