1% writet3.w 2% 3% Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org> 4% Copyright 2006-2011 Taco Hoekwater <taco@@luatex.org> 5% 6% This file is part of LuaTeX. 7% 8% LuaTeX is free software; you can redistribute it and/or modify it under 9% the terms of the GNU General Public License as published by the Free 10% Software Foundation; either version 2 of the License, or (at your 11% option) any later version. 12% 13% LuaTeX is distributed in the hope that it will be useful, but WITHOUT 14% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16% License for more details. 17% 18% You should have received a copy of the GNU General Public License along 19% with LuaTeX; if not, see <http://www.gnu.org/licenses/>. 20 21@ @c 22 23 24#include "ptexlib.h" 25#include <kpathsea/tex-glyph.h> 26#include <kpathsea/magstep.h> 27#include <string.h> 28 29#define T3_BUF_SIZE 1024 30 31typedef char t3_line_entry; 32define_array(t3_line); 33 34FILE *t3_file; 35static boolean t3_image_used; 36 37static int t3_char_procs[256]; 38static float t3_char_widths[256]; 39static int t3_glyph_num; 40static float t3_font_scale; 41static int t3_b0, t3_b1, t3_b2, t3_b3; 42static boolean is_pk_font; 43 44/* not static because used by pkin.c */ 45unsigned char *t3_buffer = NULL; 46int t3_size = 0; 47int t3_curbyte = 0; 48 49#define t3_check_eof() \ 50 if (t3_eof()) \ 51 luatex_fail("unexpected end of file"); 52 53@ 54@c 55static void update_bbox(int llx, int lly, int urx, int ury, 56 boolean is_first_glyph) 57{ 58 if (is_first_glyph) { 59 t3_b0 = llx; 60 t3_b1 = lly; 61 t3_b2 = urx; 62 t3_b3 = ury; 63 } else { 64 if (llx < t3_b0) 65 t3_b0 = llx; 66 if (lly < t3_b1) 67 t3_b1 = lly; 68 if (urx > t3_b2) 69 t3_b2 = urx; 70 if (ury > t3_b3) 71 t3_b3 = ury; 72 } 73} 74 75static int get_pk_font_scale(internal_font_number f, int precision, 76 int scale_factor) 77{ 78 return 79 divide_scaled(scale_factor, 80 divide_scaled(font_size(f), one_hundred_bp, 81 precision + 2), 0); 82} 83 84static int pk_char_width(internal_font_number f, scaled w, int precision, 85 int scale_factor) 86{ 87 return 88 divide_scaled(divide_scaled(w, font_size(f), 7), 89 get_pk_font_scale(f, precision, scale_factor), 0); 90} 91 92@ 93@c 94static boolean writepk(PDF pdf, internal_font_number f) 95{ 96 kpse_glyph_file_type font_ret; 97 int llx, lly, urx, ury; 98 int cw, rw, i, j; 99 pdffloat pf; 100 halfword *row; 101 char *name; 102 char *ftemp = NULL; 103 chardesc cd; 104 boolean is_null_glyph, check_preamble; 105 int dpi; 106 int callback_id = 0; 107 int file_opened = 0; 108 unsigned mallocsize = 0; 109 xfree(t3_buffer); 110 t3_curbyte = 0; 111 t3_size = 0; 112 113 callback_id = callback_defined(find_pk_file_callback); 114 115 if (callback_id > 0) { 116 dpi = round((float) pdf->pk_resolution * 117 (((float) font_size(f)) / (float) font_dsize(f))); 118 /* <base>.dpi/<fontname>.<tdpi>pk */ 119 cur_file_name = font_name(f); 120 mallocsize = (unsigned) (strlen(cur_file_name) + 24 + 9); 121 name = xmalloc(mallocsize); 122 snprintf(name, (size_t) mallocsize, "%ddpi/%s.%dpk", 123 (int) pdf->pk_resolution, cur_file_name, (int) dpi); 124 if (run_callback(callback_id, "S->S", name, &ftemp)) { 125 if (ftemp != NULL && strlen(ftemp)) { 126 free(name); 127 name = xstrdup(ftemp); 128 free(ftemp); 129 } 130 } 131 } else { 132 dpi = (int) 133 kpse_magstep_fix((unsigned) round 134 ((float) pdf->pk_resolution * 135 ((float) font_size(f) / (float) font_dsize(f))), 136 (unsigned) pdf->pk_resolution, NULL); 137 cur_file_name = font_name(f); 138 name = kpse_find_pk(cur_file_name, (unsigned) dpi, &font_ret); 139 if (name == NULL || 140 !FILESTRCASEEQ(cur_file_name, font_ret.name) || 141 !kpse_bitmap_tolerance((float) font_ret.dpi, (float) dpi)) { 142 luatex_fail("Font %s at %i not found", cur_file_name, (int) dpi); 143 } 144 } 145 callback_id = callback_defined(read_pk_file_callback); 146 if (callback_id > 0) { 147 if (! 148 (run_callback 149 (callback_id, "S->bSd", name, &file_opened, &t3_buffer, &t3_size) 150 && file_opened && t3_size > 0)) { 151 luatex_warn("Font %s at %i not found", cur_file_name, (int) dpi); 152 cur_file_name = NULL; 153 return false; 154 } 155 } else { 156 t3_file = xfopen(name, FOPEN_RBIN_MODE); 157 recorder_record_input(name); 158 t3_read_file(); 159 t3_close(); 160 } 161 t3_image_used = true; 162 is_pk_font = true; 163 report_start_file(filetype_font,(char *) name); 164 cd.rastersize = 256; 165 cd.raster = xtalloc((unsigned long) cd.rastersize, halfword); 166 check_preamble = true; 167 while (readchar(check_preamble, &cd) != 0) { 168 check_preamble = false; 169 if (!pdf_char_marked(f, cd.charcode)) 170 continue; 171 t3_char_widths[cd.charcode] = (float) 172 pk_char_width(f, get_charwidth(f, cd.charcode), 173 pdf->decimal_digits, pdf->pk_scale_factor); 174 if (cd.cwidth < 1 || cd.cheight < 1) { 175 cd.xescape = cd.cwidth = round(t3_char_widths[cd.charcode] / 100.0); 176 cd.cheight = 1; 177 cd.xoff = 0; 178 cd.yoff = 0; 179 is_null_glyph = true; 180 } else 181 is_null_glyph = false; 182 llx = -cd.xoff; 183 lly = cd.yoff - cd.cheight + 1; 184 urx = cd.cwidth + llx + 1; 185 ury = cd.cheight + lly; 186 update_bbox(llx, lly, urx, ury, t3_glyph_num == 0); 187 t3_glyph_num++; 188 t3_char_procs[cd.charcode] = pdf_create_obj(pdf, obj_type_others, 0); 189 pdf_begin_obj(pdf, t3_char_procs[cd.charcode], OBJSTM_NEVER); 190 pdf_begin_dict(pdf); 191 pdf_dict_add_streaminfo(pdf); 192 pdf_end_dict(pdf); 193 pdf_begin_stream(pdf); 194 setpdffloat(pf, (int64_t) t3_char_widths[cd.charcode], 2); 195 print_pdffloat(pdf, pf); 196 pdf_printf(pdf, " 0 %i %i %i %i d1\n", 197 (int) llx, (int) lly, (int) urx, (int) ury); 198 if (is_null_glyph) 199 goto end_stream; 200 pdf_printf(pdf, "q\n%i 0 0 %i %i %i cm\nBI\n", (int) cd.cwidth, 201 (int) cd.cheight, (int) llx, (int) lly); 202 pdf_printf(pdf, "/W %i\n/H %i\n", (int) cd.cwidth, (int) cd.cheight); 203 pdf_puts(pdf, "/IM true\n/BPC 1\n/D [1 0]\nID "); 204 cw = (cd.cwidth + 7) / 8; 205 rw = (cd.cwidth + 15) / 16; 206 row = cd.raster; 207 for (i = 0; i < cd.cheight; i++) { 208 for (j = 0; j < rw - 1; j++) { 209 pdf_out(pdf, (unsigned char) (*row / 256)); 210 pdf_out(pdf, (unsigned char) (*row % 256)); 211 row++; 212 } 213 pdf_out(pdf, (unsigned char) (*row / 256)); 214 if (2 * rw == cw) 215 pdf_out(pdf, (unsigned char) (*row % 256)); 216 row++; 217 } 218 pdf_puts(pdf, "\nEI\nQ\n"); 219 end_stream: 220 pdf_end_stream(pdf); 221 pdf_end_obj(pdf); 222 } 223 xfree(cd.raster); 224 cur_file_name = NULL; 225 return true; 226} 227 228@ 229@c 230void writet3(PDF pdf, internal_font_number f) 231{ 232 int i; 233 char s[32]; 234 int wptr, eptr, cptr; 235 int first_char, last_char; 236 int pk_font_scale; 237 pdffloat pf; 238 boolean is_notdef; 239 240 t3_glyph_num = 0; 241 t3_image_used = false; 242 for (i = 0; i < 256; i++) { 243 t3_char_procs[i] = 0; 244 t3_char_widths[i] = 0; 245 } 246 is_pk_font = false; 247 248 xfree(t3_buffer); 249 t3_curbyte = 0; 250 t3_size = 0; 251 if (!writepk(pdf, f)) 252 return; 253 for (i = font_bc(f); i <= font_ec(f); i++) 254 if (pdf_char_marked(f, i)) 255 break; 256 first_char = i; 257 for (i = font_ec(f); i > first_char; i--) 258 if (pdf_char_marked(f, i)) 259 break; 260 last_char = i; 261 262 /* Type 3 font dictionary */ 263 pdf_begin_obj(pdf, pdf_font_num(f), OBJSTM_ALWAYS); 264 pdf_begin_dict(pdf); 265 pdf_dict_add_name(pdf, "Type", "Font"); 266 pdf_dict_add_name(pdf, "Subtype", "Type3"); 267 snprintf(s, 31, "F%i", (int) f); 268 pdf_dict_add_name(pdf, "Name", s); 269 if (pdf_font_attr(f) != get_nullstr() && pdf_font_attr(f) != 0) { 270 pdf_out(pdf, '\n'); 271 pdf_print(pdf, pdf_font_attr(f)); 272 pdf_out(pdf, '\n'); 273 } 274 if (is_pk_font) { 275 pk_font_scale = 276 get_pk_font_scale(f, pdf->decimal_digits, pdf->pk_scale_factor); 277 pdf_add_name(pdf, "FontMatrix"); 278 pdf_begin_array(pdf); 279 setpdffloat(pf, (int64_t) pk_font_scale, 5); 280 print_pdffloat(pdf, pf); 281 pdf_puts(pdf, " 0 0 "); 282 print_pdffloat(pdf, pf); 283 pdf_puts(pdf, " 0 0"); 284 pdf_end_array(pdf); 285 } else { 286 pdf_add_name(pdf, "FontMatrix"); 287 pdf_begin_array(pdf); 288 pdf_printf(pdf, "%g 0 0 %g 0 0", 289 (double) t3_font_scale, (double) t3_font_scale); 290 pdf_end_array(pdf); 291 } 292 pdf_add_name(pdf, font_key[FONTBBOX1_CODE].pdfname); 293 pdf_begin_array(pdf); 294 pdf_add_int(pdf, (int) t3_b0); 295 pdf_add_int(pdf, (int) t3_b1); 296 pdf_add_int(pdf, (int) t3_b2); 297 pdf_add_int(pdf, (int) t3_b3); 298 pdf_end_array(pdf); 299 pdf_add_name(pdf, "Resources"); 300 pdf_begin_dict(pdf); 301 pdf_add_name(pdf, "ProcSet"); 302 pdf_begin_array(pdf); 303 pdf_add_name(pdf, "PDF"); 304 if (t3_image_used) 305 pdf_add_name(pdf, "ImageB"); 306 pdf_end_array(pdf); 307 pdf_end_dict(pdf); 308 pdf_dict_add_int(pdf, "FirstChar", first_char); 309 pdf_dict_add_int(pdf, "LastChar", last_char); 310 wptr = pdf_create_obj(pdf, obj_type_others, 0); 311 eptr = pdf_create_obj(pdf, obj_type_others, 0); 312 cptr = pdf_create_obj(pdf, obj_type_others, 0); 313 pdf_dict_add_ref(pdf, "Widths", (int) wptr); 314 pdf_dict_add_ref(pdf, "Encoding", (int) eptr); 315 pdf_dict_add_ref(pdf, "CharProcs", (int) cptr); 316 pdf_end_dict(pdf); 317 pdf_end_obj(pdf); 318 319 /* chars width array */ 320 pdf_begin_obj(pdf, wptr, OBJSTM_ALWAYS); 321 pdf_begin_array(pdf); 322 if (is_pk_font) 323 for (i = first_char; i <= last_char; i++) { 324 setpdffloat(pf, (int64_t) t3_char_widths[i], 2); 325 print_pdffloat(pdf, pf); 326 pdf_out(pdf, ' '); 327 } else 328 for (i = first_char; i <= last_char; i++) 329 pdf_add_int(pdf, (int) t3_char_widths[i]); 330 pdf_end_array(pdf); 331 pdf_end_obj(pdf); 332 333 /* encoding dictionary */ 334 pdf_begin_obj(pdf, eptr, OBJSTM_ALWAYS); 335 pdf_begin_dict(pdf); 336 pdf_dict_add_name(pdf, "Type", "Encoding"); 337 pdf_add_name(pdf, "Differences"); 338 pdf_begin_array(pdf); 339 pdf_add_int(pdf, first_char); 340 if (t3_char_procs[first_char] == 0) { 341 pdf_add_name(pdf, notdef); 342 is_notdef = true; 343 } else { 344 snprintf(s, 31, "a%i", first_char); 345 pdf_add_name(pdf, s); 346 is_notdef = false; 347 } 348 for (i = first_char + 1; i <= last_char; i++) { 349 if (t3_char_procs[i] == 0) { 350 if (!is_notdef) { 351 pdf_add_int(pdf, i); 352 pdf_add_name(pdf, notdef); 353 is_notdef = true; 354 } 355 } else { 356 if (is_notdef) { 357 pdf_add_int(pdf, i); 358 is_notdef = false; 359 } 360 snprintf(s, 31, "a%i", i); 361 pdf_add_name(pdf, s); 362 } 363 } 364 pdf_end_array(pdf); 365 pdf_end_dict(pdf); 366 pdf_end_obj(pdf); 367 368 /* CharProcs dictionary */ 369 pdf_begin_obj(pdf, cptr, OBJSTM_ALWAYS); 370 pdf_begin_dict(pdf); 371 for (i = first_char; i <= last_char; i++) 372 if (t3_char_procs[i] != 0) { 373 snprintf(s, 31, "a%i", (int) i); 374 pdf_dict_add_ref(pdf, s, (int) t3_char_procs[i]); 375 } 376 pdf_end_dict(pdf); 377 pdf_end_obj(pdf); 378 report_stop_file(filetype_font); 379 cur_file_name = NULL; 380} 381