beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / pdf / pdfsetmatrix.w
blobb107033b984dc18617e67dd0d3af9b2604674fa2
1 % pdfsetmatrix.w
3 % Copyright 2009 Taco Hoekwater <taco@@luatex.org>
5 % This file is part of LuaTeX.
7 % LuaTeX is free software; you can redistribute it and/or modify it under
8 % the terms of the GNU General Public License as published by the Free
9 % Software Foundation; either version 2 of the License, or (at your
10 % option) any later version.
12 % LuaTeX is distributed in the hope that it will be useful, but WITHOUT
13 % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 % FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 % License for more details.
17 % You should have received a copy of the GNU General Public License along
18 % with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
20 @ @c
22 #include "ptexlib.h"
24 @ stack for \.{\\pdfextension setmatrix}
27 matrix_entry *matrix_stack = NULL;
28 int matrix_stack_size = 0;
29 int matrix_stack_used = 0;
31 @ @c
32 boolean matrixused(void)
34 return matrix_stack_used > 0;
37 static void matrix_stack_room(void)
39 matrix_entry *new_stack;
40 if (matrix_stack_used >= matrix_stack_size) {
41 matrix_stack_size += STACK_INCREMENT;
42 new_stack = xtalloc((unsigned) matrix_stack_size, matrix_entry);
43 memcpy((void *) new_stack, (void *) matrix_stack, (unsigned) matrix_stack_used * sizeof(matrix_entry));
44 xfree(matrix_stack);
45 matrix_stack = new_stack;
49 @ \.{\\pdfextension setmatrix{a b c d}}
51 |e| := pos.h
53 |f| := pos.v
55 |M_top|: current active matrix at the top of the matrix stack
57 The origin of \.{\\pdfextension setmatrix} is the current point. The annotation
58 coordinate system is the original page coordinate system. When pdfTeX calculates
59 annotation rectangles it does not take into account this transformations, it uses
60 the original coordinate system. To get the corrected values, first we go back to
61 the origin, perform the transformation and go back:
63 {\obeylines\obeyspaces\tt
64 ( 1 0 0 ) ( a b 0 ) ( 1 0 0 )
65 ( 0 1 0 ) x ( c d 0 ) x ( 0 1 0 ) x M\_top
66 ( -e -f 1 ) ( 0 0 1 ) ( e f 1 )
68 ( 1 0 0 ) ( a b 0 )
69 = ( 0 1 0 ) x ( c d 0 ) x M\_top
70 ( e f 1 ) ( -e -f 1 )
72 ( a b 0 )
73 = ( c d 0 ) x M\_top
74 ( e(1-a)-fc f(1-d)-eb 1 )
78 static void pdfsetmatrix(const char *in, scaledpos pos)
81 Argument of \.{\\pdfextension setmatrix} starts with |str_pool[in]| and ends
82 before |str_pool[pool_ptr]|.
84 matrix_entry x, *y, *z;
85 if (global_shipping_mode == SHIPPING_PAGE) {
86 if (sscanf((const char *) in, " %lf %lf %lf %lf ", &x.a, &x.b, &x.c, &x.d) != 4) {
87 formatted_warning("pdf backend","unrecognized format of setmatrix: %s", in);
88 return;
90 /* calculate this transformation matrix */
91 x.e = (double) pos.h * (1.0 - x.a) - (double) pos.v * x.c;
92 x.f = (double) pos.v * (1.0 - x.d) - (double) pos.h * x.b;
93 matrix_stack_room();
94 z = &matrix_stack[matrix_stack_used];
95 if (matrix_stack_used > 0) {
96 y = &matrix_stack[matrix_stack_used - 1];
97 z->a = x.a * y->a + x.b * y->c;
98 z->b = x.a * y->b + x.b * y->d;
99 z->c = x.c * y->a + x.d * y->c;
100 z->d = x.c * y->b + x.d * y->d;
101 z->e = x.e * y->a + x.f * y->c + y->e;
102 z->f = x.e * y->b + x.f * y->d + y->f;
103 } else {
104 z->a = x.a;
105 z->b = x.b;
106 z->c = x.c;
107 z->d = x.d;
108 z->e = x.e;
109 z->f = x.f;
111 matrix_stack_used++;
115 @ Apply matrix to point (x,y)
117 {\obeylines\obeyspaces\tt
118 ( a b 0 )
119 ( x y 1 ) x ( c d 0 ) = ( xa+yc+e xb+yd+f 1 )
120 ( e f 1 )
123 If \.{\\pdfextension setmatrix} wasn't used, then return the value unchanged.
125 @ Return values for matrix tranform functions:
128 static scaled ret_llx;
129 static scaled ret_lly;
130 static scaled ret_urx;
131 static scaled ret_ury;
133 scaled getllx(void)
135 return ret_llx;
138 scaled getlly(void)
140 return ret_lly;
143 scaled geturx(void)
145 return ret_urx;
148 scaled getury(void)
150 return ret_ury;
153 @ @c
154 static int last_llx;
155 static int last_lly;
156 static int last_urx;
157 static int last_ury;
159 #define DO_ROUND(x) ((x > 0) ? (x + .5) : (x - .5))
160 #define DO_MIN(a, b) ((a < b) ? a : b)
161 #define DO_MAX(a, b) ((a > b) ? a : b)
163 static void do_matrixtransform(scaled x, scaled y, scaled * retx, scaled * rety)
165 matrix_entry *m = &matrix_stack[matrix_stack_used - 1];
166 double x_old = x;
167 double y_old = y;
168 double x_new = x_old * m->a + y_old * m->c + m->e;
169 double y_new = x_old * m->b + y_old * m->d + m->f;
170 *retx = (scaled) DO_ROUND(x_new);
171 *rety = (scaled) DO_ROUND(y_new);
174 void matrixtransformrect(scaled llx, scaled lly, scaled urx, scaled ury)
176 scaled x1, x2, x3, x4, y1, y2, y3, y4;
177 if (global_shipping_mode == SHIPPING_PAGE && matrix_stack_used > 0) {
178 last_llx = llx;
179 last_lly = lly;
180 last_urx = urx;
181 last_ury = ury;
182 do_matrixtransform(llx, lly, &x1, &y1);
183 do_matrixtransform(llx, ury, &x2, &y2);
184 do_matrixtransform(urx, lly, &x3, &y3);
185 do_matrixtransform(urx, ury, &x4, &y4);
186 ret_llx = DO_MIN(DO_MIN(x1, x2), DO_MIN(x3, x4));
187 ret_lly = DO_MIN(DO_MIN(y1, y2), DO_MIN(y3, y4));
188 ret_urx = DO_MAX(DO_MAX(x1, x2), DO_MAX(x3, x4));
189 ret_ury = DO_MAX(DO_MAX(y1, y2), DO_MAX(y3, y4));
190 } else {
191 ret_llx = llx;
192 ret_lly = lly;
193 ret_urx = urx;
194 ret_ury = ury;
198 void matrixtransformpoint(scaled x, scaled y)
200 if (global_shipping_mode == SHIPPING_PAGE && matrix_stack_used > 0) {
201 do_matrixtransform(x, y, &ret_llx, &ret_lly);
202 } else {
203 ret_llx = x;
204 ret_lly = y;
208 void matrixrecalculate(scaled urx)
210 matrixtransformrect(last_llx, last_lly, urx, last_ury);
213 @ @c
214 void pdf_out_setmatrix(PDF pdf, halfword p)
216 scaledpos pos = pdf->posstruct->pos;
217 int old_setting; /* holds print |selector| */
218 str_number s;
219 old_setting = selector;
220 selector = new_string;
221 show_token_list(token_link(pdf_setmatrix_data(p)), null, -1);
222 pdfsetmatrix((char *) cur_string, pos);
223 tprint(" 0 0 cm");
224 selector = old_setting;
225 s = make_string();
226 pdf_literal(pdf, s, set_origin, false);
227 flush_str(s);