beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / pdf / pdfpage.w
blob90f63534d327943377eed5f13a92551238b16aab
1 % pdfpage.w
3 % Copyright 2006-2012 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 #include <stdlib.h>
25 #include <stdio.h>
26 #include <assert.h>
27 #include <math.h>
29 @ eternal constant: number of sp per 1bp
32 #define one_bp ((double) 65536 * (double) 72.27 / 72)
34 @ @c
35 void init_pdf_pagecalculations(PDF pdf)
37 pdfstructure *p;
38 int decimal_digits = pdf->decimal_digits;
39 if (pdf->pstruct == NULL)
40 pdf->pstruct = xmalloc(sizeof(pdfstructure));
41 p = pdf->pstruct;
42 setpdffloat(p->pdf.h, 0, decimal_digits);
43 setpdffloat(p->pdf.v, 0, decimal_digits);
44 p->cw.e = 1;
45 p->fs_cur.e = p->fs.e = (decimal_digits < 4 ? 5 : 6); /* "+ 2" makes less corrections inside []TJ */
46 /* for placement outside BT...ET */
47 setpdffloat(p->cm[0], 1, 0);
48 setpdffloat(p->cm[1], 0, 0);
49 setpdffloat(p->cm[2], 0, 0);
50 setpdffloat(p->cm[3], 1, 0);
51 setpdffloat(p->cm[4], 0, decimal_digits); /* horizontal movement on page */
52 setpdffloat(p->cm[5], 0, decimal_digits); /* vertical movement on page */
53 /* for placement inside BT...ET */
54 setpdffloat(p->tm0_cur, 0, 6); /* mantissa holds HZ expand * ExtendFont */
55 setpdffloat(p->tm[0], ten_pow[6], 6); /* mantissa holds HZ expand * ExtendFont */
56 setpdffloat(p->tm[1], 0, 0);
57 setpdffloat(p->tm[2], 0, 3); /* mantissa holds SlantFont, 0 = default */
58 setpdffloat(p->tm[3], ten_pow[6], 6);
59 setpdffloat(p->tm[4], 0, decimal_digits); /* mantissa holds delta from |pdf_bt_pos.h| */
60 setpdffloat(p->tm[5], 0, decimal_digits); /* mantissa holds delta from |pdf_bt_pos.v| */
61 /* */
62 p->f_pdf_cur = p->f_pdf = null_font;
63 p->fs_cur.m = p->fs.m = 0;
64 p->wmode = WMODE_H;
65 p->mode = PMODE_PAGE;
66 p->ishex = 0;
67 p->need_tf = false;
68 p->need_tm = false;
69 p->k1 = ten_pow[p->pdf.h.e] / one_bp;
72 @ @c
73 void synch_pos_with_cur(posstructure * pos, posstructure * refpos, scaledpos cur)
75 switch (pos->dir) {
76 case dir_TLT:
77 pos->pos.h = refpos->pos.h + cur.h;
78 pos->pos.v = refpos->pos.v - cur.v;
79 break;
80 case dir_TRT:
81 pos->pos.h = refpos->pos.h - cur.h;
82 pos->pos.v = refpos->pos.v - cur.v;
83 break;
84 case dir_LTL:
85 pos->pos.h = refpos->pos.h + cur.v;
86 pos->pos.v = refpos->pos.v - cur.h;
87 break;
88 case dir_RTT:
89 pos->pos.h = refpos->pos.h - cur.v;
90 pos->pos.v = refpos->pos.v - cur.h;
91 break;
92 default:
93 formatted_warning("pdf backend","forcing bad dir %i to TLT in synch_pos_with_cur",pos->dir);
94 pos->dir = dir_TLT;
95 pos->pos.h = refpos->pos.h + cur.h;
96 pos->pos.v = refpos->pos.v - cur.v;
97 break;
101 @ @c
102 boolean calc_pdfpos(pdfstructure * p, scaledpos pos)
104 scaledpos new;
105 boolean move_pdfpos = false;
106 switch (p->mode) {
107 case PMODE_PAGE:
108 new.h = i64round(pos.h * p->k1);
109 new.v = i64round(pos.v * p->k1);
110 p->cm[4].m = new.h - p->pdf.h.m; /* cm is concatenated */
111 p->cm[5].m = new.v - p->pdf.v.m;
112 if (new.h != p->pdf.h.m || new.v != p->pdf.v.m)
113 move_pdfpos = true;
114 break;
115 case PMODE_TEXT:
116 new.h = i64round(pos.h * p->k1);
117 new.v = i64round(pos.v * p->k1);
118 p->tm[4].m = new.h - p->pdf_bt_pos.h.m; /* Tm replaces */
119 p->tm[5].m = new.v - p->pdf_bt_pos.v.m;
120 if (new.h != p->pdf.h.m || new.v != p->pdf.v.m)
121 move_pdfpos = true;
122 break;
123 case PMODE_CHAR:
124 case PMODE_CHARARRAY:
125 switch (p->wmode) {
126 case WMODE_H:
127 new.h = i64round((pos.h * p->k1 - (double) p->pdf_tj_pos.h.m) * p->k2);
128 new.v = i64round(pos.v * p->k1);
129 p->tj_delta.m = -i64round((double) ((new.h - p->cw.m) / ten_pow[p->cw.e - p->tj_delta.e]));
130 p->tm[5].m = new.v - p->pdf_bt_pos.v.m; /* p->tm[4] is meaningless */
131 if (p->tj_delta.m != 0 || new.v != p->pdf.v.m)
132 move_pdfpos = true;
133 break;
134 case WMODE_V:
135 new.h = i64round(pos.h * p->k1);
136 new.v = i64round(((double) p->pdf_tj_pos.v.m - pos.v * p->k1) * p->k2);
137 p->tm[4].m = new.h - p->pdf_bt_pos.h.m; /* p->tm[5] is meaningless */
138 p->tj_delta.m = -i64round((double) ((new.v - p->cw.m) / ten_pow[p->cw.e - p->tj_delta.e]));
139 if (p->tj_delta.m != 0 || new.h != p->pdf.h.m)
140 move_pdfpos = true;
141 break;
142 default:
143 normal_error("pdf backend","unknown mode in char array in calc_pos");
144 break;
146 break;
147 default:
148 normal_error("pdf backend","unknown mode in calc_pos");
150 return move_pdfpos;
153 @ @c
154 void print_pdf_matrix(PDF pdf, pdffloat * tm)
156 int i;
157 for (i = 0; i < 5; i++) {
158 print_pdffloat(pdf, tm[i]);
159 pdf_out(pdf, ' ');
161 print_pdffloat(pdf, tm[i]);
164 @ @c
165 void pdf_print_cm(PDF pdf, pdffloat * cm)
167 print_pdf_matrix(pdf, cm);
168 pdf_puts(pdf, " cm\n");
171 @ @c
172 void pdf_set_pos(PDF pdf, scaledpos pos)
174 boolean move;
175 pdfstructure *p = pdf->pstruct;
176 if (!is_pagemode(p))
177 normal_error("pdf backend","page mode expected in set_pos");
178 move = calc_pdfpos(p, pos);
179 if (move) {
180 pdf_print_cm(pdf, p->cm);
181 p->pdf.h.m += p->cm[4].m;
182 p->pdf.v.m += p->cm[5].m;
186 @ @c
187 void pdf_set_pos_temp(PDF pdf, scaledpos pos)
189 boolean move;
190 pdfstructure *p = pdf->pstruct;
191 if (!is_pagemode(p))
192 normal_error("pdf backend","page mode expected in set_pos_temp");
193 move = calc_pdfpos(p, pos);
194 if (move) {
195 pdf_print_cm(pdf, p->cm);
199 @ @c
200 static void begin_text(PDF pdf)
202 pdfstructure *p = pdf->pstruct;
203 if (!is_pagemode(p))
204 normal_error("pdf backend","page mode expected in begin_text");
205 p->pdf_bt_pos = p->pdf;
206 pdf_puts(pdf, "BT\n");
207 p->mode = PMODE_TEXT;
208 p->need_tf = true;
211 static void end_text(PDF pdf)
213 pdfstructure *p = pdf->pstruct;
214 if (!is_textmode(p))
215 normal_error("pdf backend","text mode expected in end_text");
216 pdf_puts(pdf, "ET\n");
217 p->pdf = p->pdf_bt_pos;
218 p->mode = PMODE_PAGE;
221 void pdf_end_string_nl(PDF pdf)
223 pdfstructure *p = pdf->pstruct;
224 if (is_charmode(p))
225 end_charmode(pdf);
226 if (is_chararraymode(p))
227 end_chararray(pdf);
230 @ @c
231 void pdf_goto_pagemode(PDF pdf)
233 pdfstructure *p = pdf->pstruct;
234 if (!is_pagemode(p)) {
235 if (is_charmode(p))
236 end_charmode(pdf);
237 if (is_chararraymode(p))
238 end_chararray(pdf);
239 if (is_textmode(p))
240 end_text(pdf);
241 if (!is_pagemode(p))
242 normal_error("pdf backend","page mode expected in goto_page_mode");
246 void pdf_goto_textmode(PDF pdf)
248 pdfstructure *p = pdf->pstruct;
249 const scaledpos origin = {
250 0, 0
252 if (is_pagemode(p)) {
253 /* reset to page origin */
254 pdf_set_pos(pdf, origin);
255 begin_text(pdf);
256 } else if (!is_textmode(p)) {
257 if (is_charmode(p))
258 end_charmode(pdf);
259 if (is_chararraymode(p))
260 end_chararray(pdf);
261 if (!is_textmode(p))
262 normal_error("pdf backend","text mode expected in goto_text_mode");