1% pdfglyph.w 2% 3% Copyright 2009-2011 Taco Hoekwater <taco@@luatex.org> 4% 5% This file is part of LuaTeX. 6% 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. 11% 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. 16% 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/>. 19 20@ @c 21 22 23#include "ptexlib.h" 24#include "pdf/pdfpage.h" 25 26#define pdf2double(a) ((double) (a).m / ten_pow[(a).e]) 27 28@ eternal constants 29@c 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 */ 32 33@ @c 34static int64_t pdf_char_width(pdfstructure * p, internal_font_number f, int i) 35{ 36 /* use exactly this formula also for calculating the /Width array values */ 37 return 38 i64round((double) char_width(f, i) / font_size(f) * 39 ten_pow[e_tj + p->cw.e]); 40} 41 42@ @c 43void pdf_print_charwidth(PDF pdf, internal_font_number f, int i) 44{ 45 pdffloat cw; 46 pdfstructure *p = pdf->pstruct; 47 cw.m = pdf_char_width(p, f, i); 48 cw.e = p->cw.e; 49 print_pdffloat(pdf, cw); 50} 51 52@ @c 53static void setup_fontparameters(PDF pdf, internal_font_number f, int ex_glyph) 54{ 55 float slant, extend, expand, scale = 1.0; 56 float u = 1.0; 57 pdfstructure *p = pdf->pstruct; 58 /* fix mantis bug \# 0000200 (acroread "feature") */ 59 if ((font_format(f) == opentype_format || 60 (font_format(f) == type1_format && font_encodingbytes(f) == 2)) 61 && font_units_per_em(f) > 0) 62 u = font_units_per_em(f) / 1000.0; 63 pdf->f_cur = f; 64 p->f_pdf = pdf_set_font(pdf, f); 65 p->fs.m = i64round(font_size(f) / u / one_bp * ten_pow[p->fs.e]); 66 slant = font_slant(f) / 1000.0; 67 extend = font_extend(f) / 1000.0; 68 expand = 1.0 + (ex_glyph/1) / 1000.0; 69 p->tj_delta.e = p->cw.e - 1; /* "- 1" makes less corrections inside []TJ */ 70 /* no need to be more precise than TeX (1sp) */ 71 while (p->tj_delta.e > 0 72 && (double) font_size(f) / ten_pow[p->tj_delta.e + e_tj] < 0.5) 73 p->tj_delta.e--; /* happens for very tiny fonts */ 74 assert(p->cw.e >= p->tj_delta.e); /* else we would need, e. g., |ten_pow[-1]| */ 75 p->tm[0].m = i64round(scale * expand * extend * ten_pow[p->tm[0].e]); 76 p->tm[2].m = i64round(slant * ten_pow[p->tm[2].e]); 77 p->tm[3].m = i64round(scale * ten_pow[p->tm[3].e]); 78 p->k2 = 79 ten_pow[e_tj + 80 p->cw.e] * scale / (ten_pow[p->pdf.h.e] * pdf2double(p->fs) * 81 pdf2double(p->tm[0])); 82 p->cur_ex = ex_glyph ; /* we keep track of the state of ex */ 83} 84 85 86@ @c 87static void set_font(PDF pdf) 88{ 89 pdfstructure *p = pdf->pstruct; 90 pdf_printf(pdf, "/F%d", (int) p->f_pdf); 91 pdf_print_resname_prefix(pdf); 92 pdf_out(pdf, ' '); 93 print_pdffloat(pdf, p->fs); 94 pdf_puts(pdf, " Tf "); 95 p->f_pdf_cur = p->f_pdf; 96 p->fs_cur.m = p->fs.m; 97 p->need_tf = false; 98 p->need_tm = true; /* always follow Tf by Tm */ 99} 100 101@ @c 102static void set_textmatrix(PDF pdf, scaledpos pos) 103{ 104 boolean move; 105 pdfstructure *p = pdf->pstruct; 106 assert(is_textmode(p)); 107 move = calc_pdfpos(p, pos); 108 if (p->need_tm || move) { 109 print_pdf_matrix(pdf, p->tm); 110 pdf_puts(pdf, " Tm "); 111 p->pdf.h.m = p->pdf_bt_pos.h.m + p->tm[4].m; /* Tm replaces */ 112 p->pdf.v.m = p->pdf_bt_pos.v.m + p->tm[5].m; 113 p->need_tm = false; 114 } 115 p->tm0_cur.m = p->tm[0].m; 116} 117 118@ Print out a character to PDF buffer; the character will be printed in octal 119form in the following cases: chars <= 32, backslash (92), left parenthesis 120(40), and right parenthesis (41). 121@c 122static void pdf_print_char(PDF pdf, int c) 123{ 124 if (c > 255) 125 return; 126 /* pdf_print_escaped(c) */ 127 if (c <= 32 || c == '\\' || c == '(' || c == ')' || c > 127) { 128 pdf_room(pdf, 4); 129 pdf_quick_out(pdf, '\\'); 130 pdf_quick_out(pdf, (unsigned char) ('0' + ((c >> 6) & 0x3))); 131 pdf_quick_out(pdf, (unsigned char) ('0' + ((c >> 3) & 0x7))); 132 pdf_quick_out(pdf, (unsigned char) ('0' + (c & 0x7))); 133 } else 134 pdf_out(pdf, c); 135} 136 137static void pdf_print_wide_char(PDF pdf, int c) 138{ 139 char hex[5]; 140 snprintf(hex, 5, "%04X", c); 141 pdf_out_block(pdf, (const char *) hex, 4); 142} 143 144@ @c 145static void begin_charmode(PDF pdf, internal_font_number f, pdfstructure * p) 146{ 147 assert(is_chararraymode(p)); 148 if (font_encodingbytes(f) == 2) { 149 p->ishex = 1; 150 pdf_out(pdf, '<'); 151 } else { 152 p->ishex = 0; 153 pdf_out(pdf, '('); 154 } 155 p->mode = PMODE_CHAR; 156} 157 158@ @c 159void end_charmode(PDF pdf) 160{ 161 pdfstructure *p = pdf->pstruct; 162 assert(is_charmode(p)); 163 if (p->ishex == 1) { 164 p->ishex = 0; 165 pdf_out(pdf, '>'); 166 } else { 167 pdf_out(pdf, ')'); 168 } 169 p->mode = PMODE_CHARARRAY; 170} 171 172@ @c 173static void begin_chararray(PDF pdf) 174{ 175 pdfstructure *p = pdf->pstruct; 176 assert(is_textmode(p)); 177 p->pdf_tj_pos = p->pdf; 178 p->cw.m = 0; 179 pdf_out(pdf, '['); 180 p->mode = PMODE_CHARARRAY; 181} 182 183@ @c 184void end_chararray(PDF pdf) 185{ 186 pdfstructure *p = pdf->pstruct; 187 assert(is_chararraymode(p)); 188 pdf_puts(pdf, "]TJ\n"); 189 p->pdf = p->pdf_tj_pos; 190 p->mode = PMODE_TEXT; 191} 192 193@ @c 194void pdf_place_glyph(PDF pdf, internal_font_number f, int c, int ex) 195{ 196 boolean move; 197 pdfstructure *p = pdf->pstruct; 198 scaledpos pos = pdf->posstruct->pos; 199 200 if (!char_exists(f, c)) 201 return; 202 203/* 204 p->need_tf : okay, set somewhere else 205 f != pdf->f_cur : font change 206 p->f_pdf != p->f_pdf_cur : font change 207 p->fs.m ~= p->fs_cur.m : move 208 is_pagemode(p) -> stream change 209 p->tm0_cur.m -> p->tm[0].m : also move 210*/ 211 212 /* fix issue 857 */ 213 /* /\* ensure to be within BT...ET *\/ */ 214 /* if (is_pagemode(p)) { */ 215 /* pdf_goto_textmode(pdf); */ 216 /* p->need_tf = true; */ 217 /* } */ 218 /* /\* all font setup *\/ */ 219 /* if (true || f != pdf->f_cur || p->need_tf) { */ 220 /* setup_fontparameters(pdf, f, ex); */ 221 /* if (p->need_tf || p->f_pdf != p->f_pdf_cur || p->fs.m != p->fs_cur.m) { */ 222 /* pdf_goto_textmode(pdf); */ 223 /* set_font(pdf); */ 224 /* } else if (p->tm0_cur.m != p->tm[0].m) { */ 225 /* /\* catch in-line HZ expand change due to efcode *\/ */ 226 /* p->need_tm = true; */ 227 /* } */ 228 /* } */ 229 230 231 /* LS/HH: We need to adapt the tm when a font changes. A change can be a change in 232 id (frontend) or pdf reference (backend, as we share font resources). At 233 such a change we also need to adapt to the slant and extend. Initially 234 we also need to take the exfactor of a glyph into account. When the font is 235 unchanged, we still need to check each glyph for a change in exfactor. We 236 store the current one on the state record so that we can minimize testing. */ 237 238 /* is the p->need_tf test really needed ? */ 239 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)) { 240 pdf_goto_textmode(pdf); 241 setup_fontparameters(pdf, f, ex); 242 set_font(pdf); 243 } else if (p->tm0_cur.m != p->tm[0].m || p->cur_ex != ex) { 244 setup_fontparameters(pdf, f, ex); 245 p->need_tm = true; 246 } 247 248 /* all movements */ 249 move = calc_pdfpos(p, pos); /* within text or chararray or char mode */ 250 if (move || p->need_tm) { 251 if (p->need_tm || (p->wmode == WMODE_H 252 && (p->pdf_bt_pos.v.m + p->tm[5].m) != p->pdf.v.m) 253 || (p->wmode == WMODE_V 254 && (p->pdf_bt_pos.h.m + p->tm[4].m) != p->pdf.h.m) 255 || abs(p->tj_delta.m) >= 1000000) { 256 pdf_goto_textmode(pdf); 257 set_textmatrix(pdf, pos); 258 begin_chararray(pdf); 259 move = calc_pdfpos(p, pos); /* for fine adjustment */ 260 } 261 if (move) { 262 assert((p->wmode == WMODE_H 263 && (p->pdf_bt_pos.v.m + p->tm[5].m) == p->pdf.v.m) 264 || (p->wmode == WMODE_V 265 && (p->pdf_bt_pos.h.m + p->tm[4].m) == p->pdf.h.m)); 266 if (is_charmode(p)) 267 end_charmode(pdf); 268 assert(p->tj_delta.m != 0); 269 print_pdffloat(pdf, p->tj_delta); 270 p->cw.m -= p->tj_delta.m * ten_pow[p->cw.e - p->tj_delta.e]; 271 } 272 } 273 /* glyph output */ 274 assert(is_chararraymode(p) || is_charmode(p)); 275 if (is_chararraymode(p)) 276 begin_charmode(pdf, f, p); 277 pdf_mark_char(f, c); 278 if (font_encodingbytes(f) == 2) 279 pdf_print_wide_char(pdf, char_index(f, c)); 280 else 281 pdf_print_char(pdf, c); 282 p->cw.m += pdf_char_width(p, p->f_pdf, c); /* aka |adv_char_width()| */ 283} 284