1% pdffont.w 2% 3% Copyright 2009-2014 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\def\pdfTeX{pdf\TeX} 21 22@ @c 23 24 25#include "ptexlib.h" 26 27@ @c 28#define font_id_text(A) cs_text(font_id_base+(A)) /* a frozen font identifier's name */ 29 30int pk_dpi; /* PK pixel density value from \.{texmf.cnf} */ 31 32 33@ As \pdfTeX{} should also act as a back-end driver, it needs to support virtual 34fonts too. Information about virtual fonts can be found in the source of some 35\.{DVI}-related programs. 36 37Whenever we want to write out a character in a font to PDF output, we 38should check whether the used character is a virtual or real character. 39The |has_packet()| C macro checks for this condition. 40 41 42@ The following code typesets a character to PDF output 43 44@c 45scaled_whd output_one_char(PDF pdf, halfword p) 46{ 47 scaled_whd ci; /* the real width, height and depth of the character */ 48 internal_font_number f = font(p); 49 int c = character(p); 50 int ex_glyph = ex_glyph(p)/1000; 51 ci = get_charinfo_whd(f, c); 52 if (!(char_exists(f,c))) { 53 char_warning(f,c); 54 return ci; 55 } 56 //ci.wd = round_xn_over_d(ci.wd, 1000 + ex_glyph, 1000); 57 ci.wd = ext_xn_over_d(ci.wd, 1000000 + ex_glyph(p), 1000000); 58 switch (pdf->posstruct->dir) { 59 case dir_TLT: 60 break; 61 case dir_TRT: 62 pos_left(ci.wd); 63 break; 64 case dir_LTL: 65 pos_down(ci.ht); 66 pos_left(ci.wd); 67 break; 68 case dir_RTT: 69 pos_down(ci.ht); 70 pos_left(ci.wd / 2); 71 break; 72 default: 73 assert(0); 74 } 75 if (has_packet(f, c)) { 76 do_vf_packet(pdf, f, c, ex_glyph); 77 } else 78 backend_out[glyph_node] (pdf, f, c, ex_glyph); /* |pdf_place_glyph(pdf, f, c, ex_glyph);| */ 79 return ci; 80} 81 82@ Mark |f| as a used font; set |font_used(f)|, |font_size(f)| and |pdf_font_num(f)| 83@c 84static void pdf_use_font(internal_font_number f, int fontnum) 85{ 86 set_font_used(f, true); 87 assert((fontnum > 0) || ((fontnum < 0) && (pdf_font_num(-fontnum) > 0))); 88 set_pdf_font_num(f, fontnum); 89} 90 91@ To set PDF font we need to find out fonts with the same name, because \TeX\ 92can load the same font several times for various sizes. For such fonts we 93define only one font resource. The array |pdf_font_num| holds the object 94number of font resource. A negative value of an entry of |pdf_font_num| 95indicates that the corresponding font shares the font resource with the font 96 97@c 98#define same(n,f,k) (n(f) != NULL && n(k) != NULL && strcmp(n(f), n(k)) == 0) 99 100static boolean font_shareable(internal_font_number f, internal_font_number k) 101{ 102 int ret = 0; 103 /* For some lua-loaded (for instance AFM) fonts, it is normal to have 104 a zero cidregistry, and such fonts do not have a fontmap entry yet 105 at this point, so the test should use the other branch */ 106 if (font_cidregistry(f) == NULL && font_cidregistry(k) == NULL && 107 font_encodingbytes(f) != 2 && font_encodingbytes(k) != 2) { 108 if (font_map(k) != NULL && 109 font_map(f) != NULL && (same(font_name, k, f))) { 110 ret = 1; 111 } 112 } else { 113 if ((same(font_filename, k, f) && same(font_fullname, k, f))) { 114 ret = 1; 115 } 116#ifdef DEBUG 117 printf("\nfont_shareable(%d:%s:%s,%d:%s:%s): => %d\n", 118 f, font_filename(f), font_fullname(f), 119 k, font_filename(k), font_fullname(k), ret); 120#endif 121 } 122 return ret; 123} 124 125@ create a font object 126@c 127void pdf_init_font(PDF pdf, internal_font_number f) 128{ 129 internal_font_number k/*, b*/; 130 fm_entry *fm; 131 int i, l; 132 assert(!font_used(f)); 133 134 ///* if |f| is auto expanded then ensure the base font is initialized */ 135 // 136 // if (font_auto_expand(f) && ((b = pdf_font_blink(f)) != null_font)) { 137 // if (!font_used(b)) 138 // pdf_init_font(pdf, b); 139 // set_font_map(f, font_map(b)); 140 // /* propagate slant and extend from unexpanded base font */ 141 // set_font_slant(f, font_slant(b)); 142 // set_font_extend(f, font_extend(b)); 143 //} 144 /* check whether |f| can share the font object with some |k|: we have 2 cases 145 here: 1) |f| and |k| have the same tfm name (so they have been loaded at 146 different sizes, eg 'cmr10' and 'cmr10 at 11pt'); 2) |f| has been auto 147 expanded from |k| 148 */ 149 150 /* take over slant and extend from map entry, if not already set; 151 this should also be the only place where getfontmap() may be called. */ 152 153 fm = getfontmap(font_name(f)); 154 if (font_map(f) == NULL && fm != NULL) { 155 font_map(f) = fm; 156 if (is_slantset(fm)) 157 font_slant(f) = fm->slant; 158 if (is_extendset(fm)) 159 font_extend(f) = fm->extend; 160 } 161 i = pdf->head_tab[obj_type_font]; 162 while (i != 0) { 163 k = obj_info(pdf, i); 164 if (font_shareable(f, k)) { 165 assert(pdf_font_num(k) != 0); 166 if (pdf_font_num(k) < 0) 167 pdf_use_font(f, pdf_font_num(k)); 168 else 169 pdf_use_font(f, -k); 170 return; 171 } 172 i = obj_link(pdf, i); 173 } 174 /* create a new font object for |f| */ 175 l = pdf_create_obj(pdf, obj_type_font, f); 176 pdf_use_font(f, l); 177} 178 179@ set the actual font on PDF page 180@c 181internal_font_number pdf_set_font(PDF pdf, internal_font_number f) 182{ 183 int ff; /* for use with |set_ff| */ 184 if (!font_used(f)) 185 pdf_init_font(pdf, f); 186 /* 187 set |ff| to the tfm number of the base font sharing the font object with |f|; 188 |ff| is either |f| itself (then it is its own base font), 189 or some font with the same tfm name at different size and/or expansion. 190 */ 191 ff = pdf_font_num(f) < 0 ? -pdf_font_num(f) : f; /* aka |set_ff(f)| */ 192 assert(pdf_font_num(ff) > 0); /* base font object number */ 193 addto_page_resources(pdf, obj_type_font, pdf_font_num(ff)); 194 return ff; 195} 196 197@ Here come some subroutines to deal with expanded fonts for HZ-algorithm. 198return 1 == identical 199@c 200static boolean cmp_font_name(int id, char *tt) 201{ 202 char *tid; 203 if (!is_valid_font(id)) 204 return 0; 205 tid = font_name(id); 206 if (tt == NULL && tid == NULL) 207 return 1; 208 if (tt == NULL || tid == NULL || strcmp(tid, tt) != 0) 209 return 0; 210 return 1; 211} 212 213@ @c 214internal_font_number tfm_lookup(char *s, scaled fs) 215{ /* looks up for a TFM with name |s| loaded at |fs| size; if found then flushes |s| */ 216 internal_font_number k; 217 if (fs != 0) { 218 for (k = 1; k <= max_font_id(); k++) { 219 if (cmp_font_name(k, s) && font_size(k) == fs) { 220 return k; 221 } 222 } 223 } else { 224 for (k = 1; k <= max_font_id(); k++) { 225 if (cmp_font_name(k, s)) { 226 return k; 227 } 228 } 229 } 230 return null_font; 231} 232 233@ @c 234int fix_expand_value(internal_font_number f, int e) 235{ /* return the multiple of |font_step(f)| that is nearest to |e| */ 236 int step; 237 int max_expand; 238 boolean neg; 239 if (e == 0) 240 return 0; 241 if (e < 0) { 242 e = -e; 243 neg = true; 244 max_expand = font_max_shrink(f); 245 } else { 246 neg = false; 247 max_expand = font_max_stretch(f); 248 } 249 if (e > max_expand) { 250 e = max_expand; 251 } else { 252 step = font_step(f); 253 if (e % step > 0) 254 e = step * round_xn_over_d(e, 1, step); 255 } 256 if (neg) 257 e = -e; 258 return e; 259} 260 261@ @c 262void set_expand_params(internal_font_number f, boolean auto_expand, 263 int stretch_limit, int shrink_limit, int font_step) 264{ /* expand a font with given parameters */ 265 set_font_step(f, font_step); 266 set_font_auto_expand(f, auto_expand); 267 set_font_max_shrink(f, shrink_limit); 268 set_font_max_stretch(f, stretch_limit); 269} 270 271@ @c 272void read_expand_font(void) 273{ /* read font expansion spec and load expanded font */ 274 int shrink_limit, stretch_limit, font_step; 275 internal_font_number f; 276 boolean auto_expand; 277 /* read font expansion parameters */ 278 scan_font_ident(); 279 f = cur_val; 280 if (f == null_font) 281 pdf_error("font expansion", "invalid font identifier"); 282 //if (pdf_font_blink(f) != null_font) 283 // pdf_error("font expansion", 284 // "\\pdffontexpand cannot be used this way (the base font has been expanded)"); 285 scan_optional_equals(); 286 scan_int(); 287 stretch_limit = fix_int(cur_val, 0, 1000); 288 scan_int(); 289 shrink_limit = fix_int(cur_val, 0, 500); 290 scan_int(); 291 font_step = fix_int(cur_val, 0, 100); 292 if (font_step == 0) 293 pdf_error("font expansion", "invalid step"); 294 stretch_limit = stretch_limit - stretch_limit % font_step; 295 if (stretch_limit < 0) 296 stretch_limit = 0; 297 shrink_limit = shrink_limit - shrink_limit % font_step; 298 if (shrink_limit < 0) 299 shrink_limit = 0; 300 if ((stretch_limit == 0) && (shrink_limit == 0)) 301 pdf_error("font expansion", "invalid limit(s)"); 302 auto_expand = false; 303 if (scan_keyword("autoexpand")) { 304 auto_expand = true; 305 /* Scan an optional space */ 306 get_x_token(); 307 if (cur_cmd != spacer_cmd) 308 back_input(); 309 } 310 311 if (font_step(f) != 0) { 312 /* this font has been expanded, ensure the expansion parameters are identical */ 313 if (font_step(f) != font_step) 314 pdf_error("font expansion", 315 "font has been expanded with different expansion step"); 316 317 if (((font_max_stretch(f) == 0) && (stretch_limit != 0)) || 318 ((font_max_stretch(f) > 0) 319 && (font_max_stretch(f) != stretch_limit))) 320 pdf_error("font expansion", 321 "font has been expanded with different stretch limit"); 322 323 if (((font_max_shrink(f) == 0) && (shrink_limit != 0)) || 324 ((font_max_shrink(f) > 0) 325 && (font_max_shrink(f) != shrink_limit))) 326 pdf_error("font expansion", 327 "font has been expanded with different shrink limit"); 328 329 if (font_auto_expand(f) != auto_expand) 330 pdf_error("font expansion", 331 "font has been expanded with different auto expansion value"); 332 } else { 333 if (font_used(f)) 334 pdf_warning("font expansion", 335 "font should be expanded before its first use", true, 336 true); 337 set_expand_params(f, auto_expand, stretch_limit, shrink_limit, 338 font_step); 339 } 340} 341 342@ @c 343void new_letterspaced_font(small_number a) 344{ /* letter-space a font by creating a virtual font */ 345 pointer u; /* user's font identifier */ 346 str_number t; /* name for the frozen font identifier */ 347 internal_font_number f, k; 348 boolean nolig = false; 349 get_r_token(); 350 u = cur_cs; 351 if (u >= hash_base) 352 t = cs_text(u); 353 else 354 t = maketexstring("FONT"); 355 define(u, set_font_cmd, null_font); 356 scan_optional_equals(); 357 scan_font_ident(); 358 k = cur_val; 359 scan_int(); 360 if (scan_keyword("nolig")) 361 nolig=true; 362 f = letter_space_font(k, fix_int(cur_val, -1000, 1000), nolig); 363 equiv(u) = f; 364 eqtb[font_id_base + f] = eqtb[u]; 365 font_id_text(f) = t; 366} 367 368@ @c 369void make_font_copy(small_number a) 370{ /* make a font copy for further use with font expansion */ 371 pointer u; /* user's font identifier */ 372 str_number t; /* name for the frozen font identifier */ 373 internal_font_number f, k; 374 get_r_token(); 375 u = cur_cs; 376 if (u >= hash_base) 377 t = cs_text(u); 378 else 379 t = maketexstring("FONT"); 380 define(u, set_font_cmd, null_font); 381 scan_optional_equals(); 382 scan_font_ident(); 383 k = cur_val; 384 f = copy_font_info(k); 385 equiv(u) = f; 386 eqtb[font_id_base + f] = eqtb[u]; 387 font_id_text(f) = t; 388} 389 390@ @c 391void pdf_include_chars(PDF pdf) 392{ 393 str_number s; 394 unsigned char *k, *j; /* running index */ 395 internal_font_number f; 396 scan_font_ident(); 397 f = cur_val; 398 if (f == null_font) 399 pdf_error("font", "invalid font identifier"); 400 pdf_check_vf(cur_val); 401 if (!font_used(f)) 402 pdf_init_font(pdf, f); 403 scan_pdf_ext_toks(); 404 s = tokens_to_string(def_ref); 405 delete_token_ref(def_ref); 406 j = str_string(s) + str_length(s); 407 for (k = str_string(s); k < j; k++) { 408 pdf_mark_char(f, *k); 409 } 410 flush_str(s); 411} 412 413@ @c 414void glyph_to_unicode(void) 415{ 416 str_number s1, s2; 417 scan_pdf_ext_toks(); 418 s1 = tokens_to_string(def_ref); 419 delete_token_ref(def_ref); 420 scan_pdf_ext_toks(); 421 s2 = tokens_to_string(def_ref); 422 delete_token_ref(def_ref); 423 def_tounicode(s1, s2); 424 flush_str(s2); 425 flush_str(s1); 426} 427