beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / pdf / pdfglyph.w
blob93096d025e5cefb38fcc8a9ca0d7b5de3fd7b94f
1 % pdfglyph.w
3 % Copyright 2009-2011 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"
23 #include "pdf/pdfpage.h"
25 #define pdf2double(a) ((double) (a).m / ten_pow[(a).e])
27 @ eternal constants
30 #define one_bp ((double) 65536 * (double) 72.27 / 72) /* number of sp per 1bp */
31 #define e_tj 3 /* must be 3; movements in []TJ are in fontsize/$10^3$ units */
33 @ @c
34 static int64_t pdf_char_width(pdfstructure * p, internal_font_number f, int i)
36 /* use exactly this formula also for calculating the /Width array values */
37 return i64round((double) char_width(f, i) / font_size(f) * ten_pow[e_tj + p->cw.e]);
40 @ @c
41 void pdf_print_charwidth(PDF pdf, internal_font_number f, int i)
43 pdffloat cw;
44 pdfstructure *p = pdf->pstruct;
45 cw.m = pdf_char_width(p, f, i);
46 cw.e = p->cw.e;
47 print_pdffloat(pdf, cw);
50 @ @c
51 static void setup_fontparameters(PDF pdf, internal_font_number f, int ex_glyph)
53 float slant, extend, expand, scale = 1.0;
54 float u = 1.0;
55 pdfstructure *p = pdf->pstruct;
56 /* fix mantis bug \# 0000200 (acroread "feature") */
57 if ((font_format(f) == opentype_format || (font_format(f) == type1_format && font_encodingbytes(f) == 2)) && font_units_per_em(f) > 0)
58 u = font_units_per_em(f) / 1000.0;
59 pdf->f_cur = f;
60 p->f_pdf = pdf_set_font(pdf, f);
61 p->fs.m = i64round(font_size(f) / u / one_bp * ten_pow[p->fs.e]);
62 slant = font_slant(f) / 1000.0;
63 extend = font_extend(f) / 1000.0;
64 expand = 1.0 + (ex_glyph/1) / 1000.0;
65 p->tj_delta.e = p->cw.e - 1; /* "- 1" makes less corrections inside []TJ */
66 /* no need to be more precise than TeX (1sp) */
67 while (p->tj_delta.e > 0 && (double) font_size(f) / ten_pow[p->tj_delta.e + e_tj] < 0.5)
68 p->tj_delta.e--; /* happens for very tiny fonts */
69 p->tm[0].m = i64round(scale * expand * extend * ten_pow[p->tm[0].e]);
70 p->tm[2].m = i64round(slant * ten_pow[p->tm[2].e]);
71 p->tm[3].m = i64round(scale * ten_pow[p->tm[3].e]);
72 p->k2 = ten_pow[e_tj + p->cw.e] * scale / (ten_pow[p->pdf.h.e] * pdf2double(p->fs) * pdf2double(p->tm[0]));
73 p->cur_ex = ex_glyph ; /* we keep track of the state of ex */
77 @ @c
78 static void set_font(PDF pdf)
80 pdfstructure *p = pdf->pstruct;
81 pdf_printf(pdf, "/F%d", (int) p->f_pdf);
82 pdf_print_resname_prefix(pdf);
83 pdf_out(pdf, ' ');
84 print_pdffloat(pdf, p->fs);
85 pdf_puts(pdf, " Tf ");
86 p->f_pdf_cur = p->f_pdf;
87 p->fs_cur.m = p->fs.m;
88 p->need_tf = false;
89 p->need_tm = true; /* always follow Tf by Tm */
92 @ @c
93 static void set_textmatrix(PDF pdf, scaledpos pos)
95 boolean move;
96 pdfstructure *p = pdf->pstruct;
97 if (!is_textmode(p))
98 normal_error("pdf backend","text mode expected in set_textmatrix");
99 move = calc_pdfpos(p, pos);
100 if (p->need_tm || move) {
101 print_pdf_matrix(pdf, p->tm);
102 pdf_puts(pdf, " Tm ");
103 p->pdf.h.m = p->pdf_bt_pos.h.m + p->tm[4].m; /* Tm replaces */
104 p->pdf.v.m = p->pdf_bt_pos.v.m + p->tm[5].m;
105 p->need_tm = false;
107 p->tm0_cur.m = p->tm[0].m;
110 @ Print out a character to PDF buffer; the character will be printed in octal
111 form in the following cases: chars <= 32, backslash (92), left parenthesis
112 (40), and right parenthesis (41).
115 static void pdf_print_char(PDF pdf, int c)
117 if (c > 255)
118 return;
119 /* pdf_print_escaped(c) */
120 if (c <= 32 || c == '\\' || c == '(' || c == ')' || c > 127) {
121 pdf_room(pdf, 4);
122 pdf_quick_out(pdf, '\\');
123 pdf_quick_out(pdf, (unsigned char) ('0' + ((c >> 6) & 0x3)));
124 pdf_quick_out(pdf, (unsigned char) ('0' + ((c >> 3) & 0x7)));
125 pdf_quick_out(pdf, (unsigned char) ('0' + (c & 0x7)));
126 } else
127 pdf_out(pdf, c);
130 static void pdf_print_wide_char(PDF pdf, int c)
132 char hex[5];
133 snprintf(hex, 5, "%04X", c);
134 pdf_out_block(pdf, (const char *) hex, 4);
137 @ @c
138 static void begin_charmode(PDF pdf, internal_font_number f, pdfstructure * p)
140 if (!is_chararraymode(p))
141 normal_error("pdf backend","char array mode expected in begin_char_mode");
142 if (font_encodingbytes(f) == 2) {
143 p->ishex = 1;
144 pdf_out(pdf, '<');
145 } else {
146 p->ishex = 0;
147 pdf_out(pdf, '(');
149 p->mode = PMODE_CHAR;
152 @ @c
153 void end_charmode(PDF pdf)
155 pdfstructure *p = pdf->pstruct;
156 if (!is_charmode(p))
157 normal_error("pdf backend","char mode expected in end_char_mode");
158 if (p->ishex == 1) {
159 p->ishex = 0;
160 pdf_out(pdf, '>');
161 } else {
162 pdf_out(pdf, ')');
164 p->mode = PMODE_CHARARRAY;
167 @ @c
168 static void begin_chararray(PDF pdf)
170 pdfstructure *p = pdf->pstruct;
171 if (!is_textmode(p))
172 normal_error("pdf backend","text mode expected in begin_char_array");
173 p->pdf_tj_pos = p->pdf;
174 p->cw.m = 0;
175 pdf_out(pdf, '[');
176 p->mode = PMODE_CHARARRAY;
179 @ @c
180 void end_chararray(PDF pdf)
182 pdfstructure *p = pdf->pstruct;
183 if (!is_chararraymode(p))
184 normal_error("pdf backend","char array mode expected in end_char_array");
185 pdf_puts(pdf, "]TJ\n");
186 p->pdf = p->pdf_tj_pos;
187 p->mode = PMODE_TEXT;
190 @ We need to adapt the tm when a font changes. A change can be a change in id
191 (frontend) or pdf reference (backend, as we share font resources). At such a
192 change we also need to adapt to the slant and extend. Initially we also need to
193 take the exfactor of a glyph into account. When the font is unchanged, we still
194 need to check each glyph for a change in exfactor. We store the current one on
195 the state record so that we can minimize testing.
198 void pdf_place_glyph(PDF pdf, internal_font_number f, int c, int ex)
200 boolean move;
201 pdfstructure *p = pdf->pstruct;
202 scaledpos pos = pdf->posstruct->pos;
203 if (!char_exists(f, c))
204 return;
205 if (p->need_tf || f != pdf->f_cur || p->f_pdf != p->f_pdf_cur || p->fs.m != p->fs_cur.m || is_pagemode(p)) {
206 pdf_goto_textmode(pdf);
207 setup_fontparameters(pdf, f, ex);
208 set_font(pdf);
209 } else if (p->tm0_cur.m != p->tm[0].m || p->cur_ex != ex) {
210 setup_fontparameters(pdf, f, ex);
211 p->need_tm = true;
213 /* all movements */
214 move = calc_pdfpos(p, pos); /* within text or chararray or char mode */
215 if (move || p->need_tm) {
216 if (p->need_tm || (p->wmode == WMODE_H && (p->pdf_bt_pos.v.m + p->tm[5].m) != p->pdf.v.m)
217 || (p->wmode == WMODE_V && (p->pdf_bt_pos.h.m + p->tm[4].m) != p->pdf.h.m)
218 || abs(p->tj_delta.m) >= 1000000) {
219 pdf_goto_textmode(pdf);
220 set_textmatrix(pdf, pos);
221 begin_chararray(pdf);
222 move = calc_pdfpos(p, pos); /* for fine adjustment */
224 if (move) {
225 if (is_charmode(p))
226 end_charmode(pdf);
227 print_pdffloat(pdf, p->tj_delta);
228 p->cw.m -= p->tj_delta.m * ten_pow[p->cw.e - p->tj_delta.e];
231 /* glyph output */
232 if (is_chararraymode(p))
233 begin_charmode(pdf, f, p);
234 else if (!is_charmode(p))
235 normal_error("pdf backend","char (array) mode expected in place_glyph");
236 pdf_mark_char(f, c);
237 if (font_encodingbytes(f) == 2)
238 pdf_print_wide_char(pdf, char_index(f, c));
239 else
240 pdf_print_char(pdf, c);
241 p->cw.m += pdf_char_width(p, p->f_pdf, c); /* aka |adv_char_width()| */