beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / font / texfont.w
blob06926a2f5a1899734ac52acbbc2d992637bea438
1 % texfont.w
3 % Copyright 2006-2013 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 @* Main font API implementation for the original pascal parts.
22 Stuff to watch out for:
24 \item{} Knuth had a |'null_character'| that was used when a character could
25 not be found by the |fetch()| routine, to signal an error. This has
26 been deleted, but it may mean that the output of luatex is
27 incompatible with TeX after |fetch()| has detected an error condition.
29 \item{} Knuth also had a |font_glue()| optimization. I've removed that
30 because it was a bit of dirty programming and it also was
31 problematic |if 0 != null|.
35 #include "ptexlib.h"
36 #include "lua/luatex-api.h"
38 @ @c
39 #define noDEBUG
41 #define proper_char_index(c) (c<=font_ec(f) && c>=font_bc(f))
42 #define do_realloc(a,b,d) a = xrealloc(a,(unsigned)((unsigned)(b)*sizeof(d)))
44 texfont **font_tables = NULL;
46 static int font_arr_max = 0;
47 static int font_id_maxval = 0;
49 @ @c
50 static void grow_font_table(int id)
52 int j;
53 if (id >= font_arr_max) {
54 font_bytes +=
55 (int) (((id + 8 - font_arr_max) * (int) sizeof(texfont *)));
56 font_tables =
57 xrealloc(font_tables,
58 (unsigned) (((unsigned) id + 8) * sizeof(texfont *)));
59 j = 8;
60 while (j--) {
61 font_tables[id + j] = NULL;
63 font_arr_max = id + 8;
67 int new_font_id(void)
69 int i;
70 for (i = 0; i < font_arr_max; i++) {
71 if (font_tables[i] == NULL) {
72 break;
75 if (i >= font_arr_max)
76 grow_font_table(i);
77 if (i > font_id_maxval)
78 font_id_maxval = i;
79 return i;
82 int max_font_id(void)
84 return font_id_maxval;
87 void set_max_font_id(int i)
89 font_id_maxval = i;
92 @ @c
93 int new_font(void)
95 int k;
96 int id;
97 charinfo *ci;
98 sa_tree_item sa_value = { 0 };
99 id = new_font_id();
100 font_bytes += (int) sizeof(texfont);
101 /* most stuff is zero */
102 font_tables[id] = xcalloc(1, sizeof(texfont));
103 font_tables[id]->_font_name = NULL;
104 font_tables[id]->_font_area = NULL;
105 font_tables[id]->_font_filename = NULL;
106 font_tables[id]->_font_fullname = NULL;
107 font_tables[id]->_font_psname = NULL;
108 font_tables[id]->_font_encodingname = NULL;
109 font_tables[id]->_font_cidregistry = NULL;
110 font_tables[id]->_font_cidordering = NULL;
111 font_tables[id]->_left_boundary = NULL;
112 font_tables[id]->_right_boundary = NULL;
113 font_tables[id]->_param_base = NULL;
114 font_tables[id]->_math_param_base = NULL;
116 set_font_bc(id, 1); /* ec = 0 */
117 set_hyphen_char(id, '-');
118 set_skew_char(id, -1);
119 font_slant(id) = 0; /* vertical */
120 font_extend(id) = 1000; /* normal width */
122 /* allocate eight values including 0 */
123 set_font_params(id, 7);
124 for (k = 0; k <= 7; k++) {
125 set_font_param(id, k, 0);
127 /* character info zero is reserved for notdef */
128 font_tables[id]->characters = new_sa_tree(1, 1, sa_value); /* stack size 1, default item value 0 */
129 ci = xcalloc(1, sizeof(charinfo));
130 set_charinfo_name(ci, xstrdup(".notdef"));
131 font_tables[id]->charinfo = ci;
132 font_tables[id]->charinfo_size = 1;
133 font_tables[id]->charinfo_cache = NULL;
135 return id;
138 @ @c
139 void font_malloc_charinfo(internal_font_number f, int num)
141 int glyph = font_tables[f]->charinfo_size;
142 font_bytes += (int) (num * (int) sizeof(charinfo));
143 do_realloc(font_tables[f]->charinfo, (unsigned) (glyph + num), charinfo);
144 memset(&(font_tables[f]->charinfo[glyph]), 0,
145 (size_t) (num * (int) sizeof(charinfo)));
146 font_tables[f]->charinfo_size += num;
149 @ @c
150 #define find_charinfo_id(f,c) (get_sa_item(font_tables[f]->characters,c).int_value)
152 charinfo *get_charinfo(internal_font_number f, int c)
154 int glyph;
155 charinfo *ci;
156 if (proper_char_index(c)) {
157 glyph = get_sa_item(font_tables[f]->characters, c).int_value;
158 if (!glyph) {
159 sa_tree_item sa_value = { 0 };
160 int tglyph = ++font_tables[f]->charinfo_count;
161 if (tglyph >= font_tables[f]->charinfo_size) {
162 font_malloc_charinfo(f, 256);
164 font_tables[f]->charinfo[tglyph].ef = 1000; /* init */
165 sa_value.int_value = tglyph;
166 set_sa_item(font_tables[f]->characters, c, sa_value, 1); /* 1 = global */
167 glyph = tglyph;
169 return &(font_tables[f]->charinfo[glyph]);
170 } else if (c == left_boundarychar) {
171 if (left_boundary(f) == NULL) {
172 ci = xcalloc(1, sizeof(charinfo));
173 font_bytes += (int) sizeof(charinfo);
174 set_left_boundary(f, ci);
176 return left_boundary(f);
177 } else if (c == right_boundarychar) {
178 if (right_boundary(f) == NULL) {
179 ci = xcalloc(1, sizeof(charinfo));
180 font_bytes += (int) sizeof(charinfo);
181 set_right_boundary(f, ci);
183 return right_boundary(f);
185 return &(font_tables[f]->charinfo[0]);
188 @ @c
189 static void set_charinfo(internal_font_number f, int c, charinfo * ci)
191 int glyph;
192 if (proper_char_index(c)) {
193 glyph = get_sa_item(font_tables[f]->characters, c).int_value;
194 if (glyph) {
195 font_tables[f]->charinfo[glyph] = *ci;
196 } else {
197 normal_error("font","character insertion failed");
199 } else if (c == left_boundarychar) {
200 set_left_boundary(f, ci);
201 } else if (c == right_boundarychar) {
202 set_right_boundary(f, ci);
206 @ @c
207 charinfo *copy_charinfo(charinfo * ci)
209 int x, k;
210 kerninfo *kern;
211 liginfo *lig;
212 eight_bits *packet;
213 charinfo *co = NULL;
214 if (ci == NULL)
215 return NULL;
216 co = xmalloc(sizeof(charinfo));
217 memcpy(co, ci, sizeof(charinfo));
218 set_charinfo_used(co, false);
219 co->name = NULL;
220 co->tounicode = NULL;
221 co->packets = NULL;
222 co->ligatures = NULL;
223 co->kerns = NULL;
224 co->vert_variants = NULL;
225 co->hor_variants = NULL;
226 if (ci->name != NULL) {
227 co->name = xstrdup(ci->name);
229 if (ci->tounicode != NULL) {
230 co->tounicode = xstrdup(ci->tounicode);
232 /* kerns */
233 if ((kern = get_charinfo_kerns(ci)) != NULL) {
234 x = 0;
235 while (!kern_end(kern[x])) {
236 x++;
238 x++;
239 co->kerns = xmalloc((unsigned) (x * (int) sizeof(kerninfo)));
240 memcpy(co->kerns, ci->kerns, (size_t) (x * (int) sizeof(kerninfo)));
242 /* ligs */
243 if ((lig = get_charinfo_ligatures(ci)) != NULL) {
244 x = 0;
245 while (!lig_end(lig[x])) {
246 x++;
248 x++;
249 co->ligatures = xmalloc((unsigned) (x * (int) sizeof(liginfo)));
250 memcpy(co->ligatures, ci->ligatures,
251 (size_t) (x * (int) sizeof(liginfo)));
253 /* packets */
254 if ((packet = get_charinfo_packets(ci)) != NULL) {
255 x = vf_packet_bytes(ci);
256 co->packets = xmalloc((unsigned) x);
257 memcpy(co->packets, ci->packets, (size_t) x);
260 /* horizontal and vertical extenders */
261 if (get_charinfo_vert_variants(ci) != NULL) {
262 set_charinfo_vert_variants(co, copy_variants(get_charinfo_vert_variants(ci)));
264 if (get_charinfo_hor_variants(ci) != NULL) {
265 set_charinfo_hor_variants(co, copy_variants(get_charinfo_hor_variants(ci)));
267 x = ci->top_left_math_kerns;
268 co->top_left_math_kerns = x;
269 if (x > 0) {
270 co->top_left_math_kern_array =
271 xmalloc((unsigned) (2 * (int) sizeof(scaled) * x));
272 for (k = 0; k < co->top_left_math_kerns; k++) {
273 co->top_left_math_kern_array[(2 * k)] = ci->top_left_math_kern_array[(2 * k)];
274 co->top_left_math_kern_array[(2 * k) + 1] = ci->top_left_math_kern_array[(2 * k) + 1];
277 x = ci->top_right_math_kerns;
278 co->top_right_math_kerns = x;
279 if (x > 0) {
280 co->top_right_math_kern_array =
281 xmalloc((unsigned) (2 * (int) sizeof(scaled) * x));
282 for (k = 0; k < co->top_right_math_kerns; k++) {
283 co->top_right_math_kern_array[(2 * k)] = ci->top_right_math_kern_array[(2 * k)];
284 co->top_right_math_kern_array[(2 * k) + 1] = ci->top_right_math_kern_array[(2 * k) + 1];
287 x = ci->bottom_right_math_kerns;
288 co->bottom_right_math_kerns = x;
289 if (x > 0) {
290 co->bottom_right_math_kern_array =
291 xmalloc((unsigned) (2 * (int) sizeof(scaled) * x));
292 for (k = 0; k < co->bottom_right_math_kerns; k++) {
293 co->bottom_right_math_kern_array[(2 * k)] = ci->bottom_right_math_kern_array[(2 * k)];
294 co->bottom_right_math_kern_array[(2 * k) + 1] = ci->bottom_right_math_kern_array[(2 * k) + 1];
297 x = ci->bottom_left_math_kerns;
298 co->bottom_left_math_kerns = x;
299 if (x > 0) {
300 co->bottom_left_math_kern_array =
301 xmalloc((unsigned) (2 * (int) sizeof(scaled) * x));
302 for (k = 0; k < co->bottom_left_math_kerns; k++) {
303 co->bottom_left_math_kern_array[(2 * k)] = ci->bottom_left_math_kern_array[(2 * k)];
304 co->bottom_left_math_kern_array[(2 * k) + 1] = ci->bottom_left_math_kern_array[(2 * k) + 1];
307 return co;
310 charinfo *char_info(internal_font_number f, int c)
312 if (f > font_id_maxval)
313 return 0;
314 if (proper_char_index(c)) {
315 register int glyph = (int) find_charinfo_id(f, c);
316 return &(font_tables[f]->charinfo[glyph]);
317 } else if (c == left_boundarychar && left_boundary(f) != NULL) {
318 return left_boundary(f);
319 } else if (c == right_boundarychar && right_boundary(f) != NULL) {
320 return right_boundary(f);
322 return &(font_tables[f]->charinfo[0]);
325 @ @c
326 scaled_whd get_charinfo_whd(internal_font_number f, int c)
328 scaled_whd s;
329 charinfo *i;
330 i = char_info(f, c);
331 s.wd = i->width;
332 s.dp = i->depth;
333 s.ht = i->height;
334 return s;
337 @ @c
338 int char_exists(internal_font_number f, int c)
340 if (f > font_id_maxval)
341 return 0;
342 if (proper_char_index(c)) {
343 return (int) find_charinfo_id(f, c);
344 } else if ((c == left_boundarychar) && has_left_boundary(f)) {
345 return 1;
346 } else if ((c == right_boundarychar) && has_right_boundary(f)) {
347 return 1;
349 return 0;
352 @ @c
353 #if 0
354 static int lua_char_exists_callback(internal_font_number f, int c)
356 int callback_id;
357 lua_State *L = Luas;
358 int ret = 0;
359 callback_id = callback_defined(char_exists_callback);
360 if (callback_id != 0) {
361 if (!get_callback(L, callback_id)) {
362 lua_pop(L, 2);
363 return 0;
365 lua_pushinteger(L, f);
366 lua_pushinteger(L, c);
367 if (lua_pcall(L, 2, 1, 0) != 0) { /* two args, 1 result */
368 fprintf(stdout, "error: %s\n", lua_tostring(L, -1));
369 lua_pop(L, 2);
370 error();
371 } else {
372 ret = lua_toboolean(L, -1);
375 return ret;
377 #endif
379 @ @c
380 extinfo *new_variant(int glyph, int startconnect, int endconnect,
381 int advance, int repeater)
383 extinfo *ext;
384 ext = xmalloc(sizeof(extinfo));
385 ext->next = NULL;
386 ext->glyph = glyph;
387 ext->start_overlap = startconnect;
388 ext->end_overlap = endconnect;
389 ext->advance = advance;
390 ext->extender = repeater;
391 return ext;
395 @ @c
396 static extinfo *copy_variant(extinfo * old)
398 extinfo *ext;
399 ext = xmalloc(sizeof(extinfo));
400 ext->next = NULL;
401 ext->glyph = old->glyph;
402 ext->start_overlap = old->start_overlap;
403 ext->end_overlap = old->end_overlap;
404 ext->advance = old->advance;
405 ext->extender = old->extender;
406 return ext;
409 @ @c
410 static void dump_variant(extinfo * ext)
412 dump_int(ext->glyph);
413 dump_int(ext->start_overlap);
414 dump_int(ext->end_overlap);
415 dump_int(ext->advance);
416 dump_int(ext->extender);
417 return;
421 @ @c
422 static extinfo *undump_variant(void)
424 int x;
425 extinfo *ext;
426 undump_int(x);
427 if (x == 0)
428 return NULL;
429 ext = xmalloc(sizeof(extinfo));
430 ext->next = NULL;
431 ext->glyph = x;
432 undump_int(x);
433 ext->start_overlap = x;
434 undump_int(x);
435 ext->end_overlap = x;
436 undump_int(x);
437 ext->advance = x;
438 undump_int(x);
439 ext->extender = x;
440 return ext;
443 @ @c
444 void add_charinfo_vert_variant(charinfo * ci, extinfo * ext)
446 if (ci->vert_variants == NULL) {
447 ci->vert_variants = ext;
448 } else {
449 extinfo *lst = ci->vert_variants;
450 while (lst->next != NULL)
451 lst = lst->next;
452 lst->next = ext;
457 @ @c
458 void add_charinfo_hor_variant(charinfo * ci, extinfo * ext)
460 if (ci->hor_variants == NULL) {
461 ci->hor_variants = ext;
462 } else {
463 extinfo *lst = ci->hor_variants;
464 while (lst->next != NULL)
465 lst = lst->next;
466 lst->next = ext;
471 @ @c
472 extinfo *copy_variants(extinfo * o)
474 extinfo *c, *t = NULL, *h = NULL;
475 while (o != NULL) {
476 c = copy_variant(o);
477 if (h == null)
478 h = c;
479 else
480 t->next = c;
481 t = c;
482 o = o->next;
485 return h;
488 @ @c
489 static void dump_charinfo_variants(extinfo * o)
491 while (o != NULL) {
492 dump_variant(o);
493 o = o->next;
495 dump_int(0);
496 return;
499 @ @c
500 static extinfo *undump_charinfo_variants(void)
502 extinfo *c, *t = NULL, *h = NULL;
503 c = undump_variant();
504 while (c != NULL) {
505 if (h == null)
506 h = c;
507 else
508 t->next = c;
509 t = c;
510 c = undump_variant();
512 return h;
516 @ Note that mant more small things like this are implemented
517 as macros in the header file.
519 void set_charinfo_width(charinfo * ci, scaled val)
521 ci->width = val;
524 void set_charinfo_height(charinfo * ci, scaled val)
526 ci->height = val;
529 void set_charinfo_depth(charinfo * ci, scaled val)
531 ci->depth = val;
534 void set_charinfo_italic(charinfo * ci, scaled val)
536 ci->italic = val;
539 void set_charinfo_vert_italic(charinfo * ci, scaled val)
541 ci->vert_italic = val;
544 void set_charinfo_top_accent(charinfo * ci, scaled val)
546 ci->top_accent = val;
549 void set_charinfo_bot_accent(charinfo * ci, scaled val)
551 ci->bot_accent = val;
554 void set_charinfo_tag(charinfo * ci, scaled val)
556 ci->tag = (char) val;
559 void set_charinfo_remainder(charinfo * ci, scaled val)
561 ci->remainder = val;
564 void set_charinfo_used(charinfo * ci, scaled val)
566 ci->used = (char) val;
569 void set_charinfo_index(charinfo * ci, scaled val)
571 ci->index = (unsigned short) val;
574 void set_charinfo_name(charinfo * ci, char *val)
576 xfree(ci->name);
577 ci->name = val;
580 void set_charinfo_tounicode(charinfo * ci, char *val)
582 xfree(ci->tounicode);
583 ci->tounicode = val;
586 void set_charinfo_ligatures(charinfo * ci, liginfo * val)
588 dxfree(ci->ligatures, val);
591 void set_charinfo_kerns(charinfo * ci, kerninfo * val)
593 dxfree(ci->kerns, val);
596 void set_charinfo_packets(charinfo * ci, eight_bits * val)
598 dxfree(ci->packets, val);
601 void set_charinfo_ef(charinfo * ci, scaled val)
603 ci->ef = val;
606 void set_charinfo_lp(charinfo * ci, scaled val)
608 ci->lp = val;
611 void set_charinfo_rp(charinfo * ci, scaled val)
613 ci->rp = val;
616 @ @c
617 void set_charinfo_vert_variants(charinfo * ci, extinfo * ext)
619 extinfo *c, *lst;
620 if (ci->vert_variants != NULL) {
621 lst = ci->vert_variants;
622 while (lst != NULL) {
623 c = lst->next;
624 free(lst);
625 lst = c;
628 ci->vert_variants = ext;
631 @ @c
632 void set_charinfo_hor_variants(charinfo * ci, extinfo * ext)
634 extinfo *c, *lst;
635 if (ci->hor_variants != NULL) {
636 lst = ci->hor_variants;
637 while (lst != NULL) {
638 c = lst->next;
639 free(lst);
640 lst = c;
643 ci->hor_variants = ext;
647 @ @c
648 int get_charinfo_math_kerns(charinfo * ci, int id)
651 int k = 0; /* all callers check for |result>0| */
652 if (id == top_left_kern) {
653 k = ci->top_left_math_kerns;
654 } else if (id == bottom_left_kern) {
655 k = ci->bottom_left_math_kerns;
656 } else if (id == bottom_right_kern) {
657 k = ci->bottom_right_math_kerns;
658 } else if (id == top_right_kern) {
659 k = ci->top_right_math_kerns;
660 } else {
661 confusion("get_charinfo_math_kerns");
663 return k;
666 @ @c
667 void add_charinfo_math_kern(charinfo * ci, int id, scaled ht, scaled krn)
669 int k;
670 if (id == top_left_kern) {
671 k = ci->top_left_math_kerns;
672 do_realloc(ci->top_left_math_kern_array, ((k + 1) * 2), sizeof(scaled));
673 ci->top_left_math_kern_array[(2 * (k))] = ht;
674 ci->top_left_math_kern_array[((2 * (k)) + 1)] = krn;
675 ci->top_left_math_kerns++;
676 } else if (id == bottom_left_kern) {
677 k = ci->bottom_left_math_kerns;
678 do_realloc(ci->bottom_left_math_kern_array, ((k + 1) * 2),
679 sizeof(scaled));
680 ci->bottom_left_math_kern_array[(2 * (k))] = ht;
681 ci->bottom_left_math_kern_array[(2 * (k)) + 1] = krn;
682 ci->bottom_left_math_kerns++;
683 } else if (id == bottom_right_kern) {
684 k = ci->bottom_right_math_kerns;
685 do_realloc(ci->bottom_right_math_kern_array, ((k + 1) * 2),
686 sizeof(scaled));
687 ci->bottom_right_math_kern_array[(2 * (k))] = ht;
688 ci->bottom_right_math_kern_array[(2 * (k)) + 1] = krn;
689 ci->bottom_right_math_kerns++;
690 } else if (id == top_right_kern) {
691 k = ci->top_right_math_kerns;
692 do_realloc(ci->top_right_math_kern_array, ((k + 1) * 2),
693 sizeof(scaled));
694 ci->top_right_math_kern_array[(2 * (k))] = ht;
695 ci->top_right_math_kern_array[(2 * (k)) + 1] = krn;
696 ci->top_right_math_kerns++;
697 } else {
698 confusion("add_charinfo_math_kern");
703 @ @c
704 static void dump_math_kerns(charinfo * ci)
706 int k, l;
707 l = ci->top_left_math_kerns;
708 dump_int(l);
709 for (k = 0; k < l; k++) {
710 dump_int(ci->top_left_math_kern_array[(2 * k)]);
711 dump_int(ci->top_left_math_kern_array[(2 * k) + 1]);
713 l = ci->bottom_left_math_kerns;
714 dump_int(l);
715 for (k = 0; k < l; k++) {
716 dump_int(ci->bottom_left_math_kern_array[(2 * k)]);
717 dump_int(ci->bottom_left_math_kern_array[(2 * k) + 1]);
719 l = ci->bottom_right_math_kerns;
720 dump_int(l);
721 for (k = 0; k < l; k++) {
722 dump_int(ci->bottom_right_math_kern_array[(2 * k)]);
723 dump_int(ci->bottom_right_math_kern_array[(2 * k) + 1]);
725 l = ci->top_right_math_kerns;
726 dump_int(l);
727 for (k = 0; k < l; k++) {
728 dump_int(ci->bottom_left_math_kern_array[(2 * k)]);
729 dump_int(ci->bottom_left_math_kern_array[(2 * k) + 1]);
733 @ @c
734 static void undump_math_kerns(charinfo * ci)
736 int k;
737 int x;
738 undump_int(x);
739 ci->top_left_math_kerns = x;
740 if (x > 0)
741 ci->top_left_math_kern_array =
742 xmalloc((unsigned) (2 * (int) sizeof(scaled) * x));
743 for (k = 0; k < ci->top_left_math_kerns; k++) {
744 undump_int(x);
745 ci->top_left_math_kern_array[(2 * k)] = (scaled) x;
746 undump_int(x);
747 ci->top_left_math_kern_array[(2 * k) + 1] = (scaled) x;
749 undump_int(x);
750 ci->bottom_left_math_kerns = x;
751 if (x > 0)
752 ci->bottom_left_math_kern_array =
753 xmalloc((unsigned) (2 * (int) sizeof(scaled) * x));
754 for (k = 0; k < ci->bottom_left_math_kerns; k++) {
755 undump_int(x);
756 ci->bottom_left_math_kern_array[(2 * k)] = (scaled) x;
757 undump_int(x);
758 ci->bottom_left_math_kern_array[(2 * k) + 1] = (scaled) x;
760 undump_int(x);
761 ci->bottom_right_math_kerns = x;
762 if (x > 0)
763 ci->bottom_right_math_kern_array =
764 xmalloc((unsigned) (2 * (int) sizeof(scaled) * x));
765 for (k = 0; k < ci->bottom_right_math_kerns; k++) {
766 undump_int(x);
767 ci->bottom_right_math_kern_array[(2 * k)] = (scaled) x;
768 undump_int(x);
769 ci->bottom_right_math_kern_array[(2 * k) + 1] = (scaled) x;
771 undump_int(x);
772 ci->top_right_math_kerns = x;
773 if (x > 0)
774 ci->top_right_math_kern_array =
775 xmalloc((unsigned) (2 * (int) sizeof(scaled) * x));
776 for (k = 0; k < ci->top_right_math_kerns; k++) {
777 undump_int(x);
778 ci->top_right_math_kern_array[(2 * k)] = (scaled) x;
779 undump_int(x);
780 ci->top_right_math_kern_array[(2 * k) + 1] = (scaled) x;
785 @ In TeX, extensibles were fairly simple things.
786 This function squeezes a TFM extensible into the vertical extender structures.
787 |advance==0| is a special case for TFM fonts, because finding the proper
788 advance width during tfm reading can be tricky
791 a small complication arises if |rep| is the only non-zero: it needs to be
792 doubled as a non-repeatable to avoid mayhem */
795 void set_charinfo_extensible(charinfo * ci, int top, int bot, int mid, int rep)
797 extinfo *ext;
798 set_charinfo_vert_variants(ci, NULL); /* clear old */
799 if (bot == 0 && top == 0 && mid == 0 && rep != 0) {
800 ext = new_variant(rep, 0, 0, 0, EXT_NORMAL);
801 add_charinfo_vert_variant(ci, ext);
802 ext = new_variant(rep, 0, 0, 0, EXT_REPEAT);
803 add_charinfo_vert_variant(ci, ext);
804 return;
806 if (bot != 0) {
807 ext = new_variant(bot, 0, 0, 0, EXT_NORMAL);
808 add_charinfo_vert_variant(ci, ext);
810 if (rep != 0) {
811 ext = new_variant(rep, 0, 0, 0, EXT_REPEAT);
812 add_charinfo_vert_variant(ci, ext);
814 if (mid != 0) {
815 ext = new_variant(mid, 0, 0, 0, EXT_NORMAL);
816 add_charinfo_vert_variant(ci, ext);
817 if (rep != 0) {
818 ext = new_variant(rep, 0, 0, 0, EXT_REPEAT);
819 add_charinfo_vert_variant(ci, ext);
822 if (top != 0) {
823 ext = new_variant(top, 0, 0, 0, EXT_NORMAL);
824 add_charinfo_vert_variant(ci, ext);
828 @ Note that many more simple things like this are implemented as macros
829 in the header file.
832 scaled get_charinfo_width(charinfo * ci)
834 return ci->width;
837 scaled get_charinfo_height(charinfo * ci)
839 return ci->height;
842 scaled get_charinfo_depth(charinfo * ci)
844 return ci->depth;
847 scaled get_charinfo_italic(charinfo * ci)
849 return ci->italic;
852 scaled get_charinfo_vert_italic(charinfo * ci)
854 return ci->vert_italic;
857 scaled get_charinfo_top_accent(charinfo * ci)
859 return ci->top_accent;
862 scaled get_charinfo_bot_accent(charinfo * ci)
864 return ci->bot_accent;
867 char get_charinfo_tag(charinfo * ci)
869 return ci->tag;
872 int get_charinfo_remainder(charinfo * ci)
874 return ci->remainder;
877 char get_charinfo_used(charinfo * ci)
879 return ci->used;
882 int get_charinfo_index(charinfo * ci)
884 return ci->index;
887 char *get_charinfo_name(charinfo * ci)
889 return ci->name;
892 char *get_charinfo_tounicode(charinfo * ci)
894 return ci->tounicode;
897 liginfo *get_charinfo_ligatures(charinfo * ci)
899 return ci->ligatures;
902 kerninfo *get_charinfo_kerns(charinfo * ci)
904 return ci->kerns;
907 eight_bits *get_charinfo_packets(charinfo * ci)
909 return ci->packets;
912 int get_charinfo_ef(charinfo * ci)
914 return ci->ef;
917 int get_charinfo_rp(charinfo * ci)
919 return ci->rp;
922 int get_charinfo_lp(charinfo * ci)
924 return ci->lp;
927 extinfo *get_charinfo_vert_variants(charinfo * ci)
929 extinfo *w = NULL;
930 if (ci->vert_variants != NULL)
931 w = ci->vert_variants;
932 return w;
935 extinfo *get_charinfo_hor_variants(charinfo * ci)
937 extinfo *w = NULL;
938 if (ci->hor_variants != NULL)
939 w = ci->hor_variants;
940 return w;
944 scaled char_width(internal_font_number f, int c)
946 charinfo *ci = char_info(f, c);
947 scaled w = get_charinfo_width(ci);
948 return w;
951 scaled calc_char_width(internal_font_number f, int c, int ex)
953 charinfo *ci = char_info(f, c);
954 scaled w = get_charinfo_width(ci);
955 if (ex != 0)
956 w = round_xn_over_d(w, 1000 + ex, 1000);
957 return w;
960 scaled char_depth(internal_font_number f, int c)
962 charinfo *ci = char_info(f, c);
963 scaled d = get_charinfo_depth(ci);
964 return d;
967 scaled char_height(internal_font_number f, int c)
969 charinfo *ci = char_info(f, c);
970 scaled h = get_charinfo_height(ci);
971 return h;
974 scaled char_italic(internal_font_number f, int c)
976 charinfo *ci = char_info(f, c);
977 scaled i = get_charinfo_italic(ci);
978 return i;
981 scaled char_vert_italic(internal_font_number f, int c)
983 charinfo *ci = char_info(f, c);
984 scaled i = get_charinfo_vert_italic(ci);
985 return i;
988 scaled char_top_accent(internal_font_number f, int c)
990 charinfo *ci = char_info(f, c);
991 return get_charinfo_top_accent(ci);
994 scaled char_bot_accent(internal_font_number f, int c)
996 charinfo *ci = char_info(f, c);
997 return get_charinfo_bot_accent(ci);
1001 int char_remainder(internal_font_number f, int c)
1003 charinfo *ci = char_info(f, c);
1004 return get_charinfo_remainder(ci);
1007 char char_tag(internal_font_number f, int c)
1009 charinfo *ci = char_info(f, c);
1010 return get_charinfo_tag(ci);
1013 char char_used(internal_font_number f, int c)
1015 charinfo *ci = char_info(f, c);
1016 return get_charinfo_used(ci);
1019 char *char_name(internal_font_number f, int c)
1021 charinfo *ci = char_info(f, c);
1022 return get_charinfo_name(ci);
1025 int char_index(internal_font_number f, int c)
1027 charinfo *ci = char_info(f, c);
1028 return get_charinfo_index(ci);
1031 liginfo *char_ligatures(internal_font_number f, int c)
1033 charinfo *ci = char_info(f, c);
1034 return get_charinfo_ligatures(ci);
1037 kerninfo *char_kerns(internal_font_number f, int c)
1039 charinfo *ci = char_info(f, c);
1040 return get_charinfo_kerns(ci);
1043 eight_bits *char_packets(internal_font_number f, int c)
1045 charinfo *ci = char_info(f, c);
1046 return get_charinfo_packets(ci);
1049 @ @c
1050 void set_font_params(internal_font_number f, int b)
1052 int i;
1053 i = font_params(f);
1054 if (i != b) {
1055 font_bytes +=
1056 (int) ((b - (int) font_params(f) + 1) * (int) sizeof(scaled));
1057 do_realloc(param_base(f), (b + 2), int);
1058 font_params(f) = b;
1059 if (b > i) {
1060 while (i < b) {
1061 i++;
1062 set_font_param(f, i, 0);
1068 @ @c
1069 void set_font_math_params(internal_font_number f, int b)
1071 int i;
1072 i = font_math_params(f);
1073 if (i != b) {
1074 font_bytes +=
1075 ((b - (int) font_math_params(f) + 1) * (int) sizeof(scaled));
1076 do_realloc(math_param_base(f), (b + 2), int);
1077 font_math_params(f) = b;
1078 if (b > i) {
1079 while (i < b) {
1080 i++;
1081 set_font_math_param(f, i, undefined_math_parameter);
1087 @ @c
1088 int copy_font(int f)
1090 int i, ci_cnt, ci_size;
1091 charinfo *ci;
1092 int k = new_font();
1095 ci = font_tables[k]->charinfo;
1096 ci_cnt = font_tables[k]->charinfo_count;
1097 ci_size = font_tables[k]->charinfo_size;
1098 memcpy(font_tables[k], font_tables[f], sizeof(texfont));
1099 font_tables[k]->charinfo = ci;
1100 font_tables[k]->charinfo_count = ci_cnt;
1101 font_tables[k]->charinfo_size = ci_size;
1104 font_malloc_charinfo(k, font_tables[f]->charinfo_count);
1105 set_font_cache_id(k, 0);
1106 set_font_used(k, 0);
1107 set_font_touched(k, 0);
1109 font_tables[k]->_font_name = NULL;
1110 font_tables[k]->_font_filename = NULL;
1111 font_tables[k]->_font_fullname = NULL;
1112 font_tables[k]->_font_psname = NULL;
1113 font_tables[k]->_font_encodingname = NULL;
1114 font_tables[k]->_font_area = NULL;
1115 font_tables[k]->_font_cidregistry = NULL;
1116 font_tables[k]->_font_cidordering = NULL;
1117 font_tables[k]->_left_boundary = NULL;
1118 font_tables[k]->_right_boundary = NULL;
1120 set_font_name(k, xstrdup(font_name(f)));
1121 if (font_filename(f) != NULL)
1122 set_font_filename(k, xstrdup(font_filename(f)));
1123 if (font_fullname(f) != NULL)
1124 set_font_fullname(k, xstrdup(font_fullname(f)));
1125 if (font_psname(f) != NULL)
1126 set_font_psname(k, xstrdup(font_psname(f)));
1127 if (font_encodingname(f) != NULL)
1128 set_font_encodingname(k, xstrdup(font_encodingname(f)));
1129 if (font_area(f) != NULL)
1130 set_font_area(k, xstrdup(font_area(f)));
1131 if (font_cidregistry(f) != NULL)
1132 set_font_cidregistry(k, xstrdup(font_cidregistry(f)));
1133 if (font_cidordering(f) != NULL)
1134 set_font_cidordering(k, xstrdup(font_cidordering(f)));
1136 i = (int) (sizeof(*param_base(f)) * (unsigned) (font_params(f)+1));
1137 font_bytes += i;
1138 param_base(k) = xmalloc((unsigned) (i+1));
1139 memcpy(param_base(k), param_base(f), (size_t) (i));
1141 if (font_math_params(f) > 0) {
1142 i = (int) (sizeof(*math_param_base(f)) *
1143 (unsigned) font_math_params(f));
1144 font_bytes += i;
1145 math_param_base(k) = xmalloc((unsigned) i);
1146 memcpy(math_param_base(k), math_param_base(f), (size_t) i);
1149 for (i = 0; i <= font_tables[f]->charinfo_count; i++) {
1150 ci = copy_charinfo(&font_tables[f]->charinfo[i]);
1151 font_tables[k]->charinfo[i] = *ci;
1154 if (left_boundary(f) != NULL) {
1155 ci = copy_charinfo(left_boundary(f));
1156 set_charinfo(k, left_boundarychar, ci);
1159 if (right_boundary(f) != NULL) {
1160 ci = copy_charinfo(right_boundary(f));
1161 set_charinfo(k, right_boundarychar, ci);
1163 /* not updated yet: */
1164 font_tables[k]->charinfo_count = font_tables[f]->charinfo_count;
1165 return k;
1168 @ @c
1169 void delete_font(int f)
1171 int i;
1172 charinfo *co;
1173 assert(f > 0);
1174 if (font_tables[f] != NULL) {
1175 set_font_name(f, NULL);
1176 set_font_filename(f, NULL);
1177 set_font_fullname(f, NULL);
1178 set_font_psname(f, NULL);
1179 set_font_encodingname(f, NULL);
1180 set_font_area(f, NULL);
1181 set_font_cidregistry(f, NULL);
1182 set_font_cidordering(f, NULL);
1183 set_left_boundary(f, NULL);
1184 set_right_boundary(f, NULL);
1186 for (i = font_bc(f); i <= font_ec(f); i++) {
1187 if (quick_char_exists(f, i)) {
1188 co = char_info(f, i);
1189 set_charinfo_name(co, NULL);
1190 set_charinfo_tounicode(co, NULL);
1191 set_charinfo_packets(co, NULL);
1192 set_charinfo_ligatures(co, NULL);
1193 set_charinfo_kerns(co, NULL);
1194 set_charinfo_vert_variants(co, NULL);
1195 set_charinfo_hor_variants(co, NULL);
1198 /* free .notdef */
1199 set_charinfo_name(font_tables[f]->charinfo + 0, NULL);
1200 free(font_tables[f]->charinfo);
1201 destroy_sa_tree(font_tables[f]->characters);
1203 free(param_base(f));
1204 if (math_param_base(f) != NULL)
1205 free(math_param_base(f));
1206 free(font_tables[f]);
1207 font_tables[f] = NULL;
1209 if (font_id_maxval == f) {
1210 font_id_maxval--;
1215 @ @c
1216 void create_null_font(void)
1218 int i = new_font();
1219 assert(i == 0);
1220 set_font_name(i, xstrdup("nullfont"));
1221 set_font_area(i, xstrdup(""));
1222 set_font_touched(i, 1);
1225 @ @c
1226 boolean is_valid_font(int id)
1228 int ret = 0;
1229 if (id >= 0 && id <= font_id_maxval && font_tables[id] != NULL)
1230 ret = 1;
1231 return ret;
1234 @ @c
1235 boolean cmp_font_area(int id, str_number t)
1237 char *tt = NULL;
1238 char *tid = font_area(id);
1239 if (t == 0) {
1240 if (tid == NULL || strlen(tid) == 0)
1241 return 1;
1242 else
1243 return 0;
1245 tt = makecstring(t);
1246 if ((tt == NULL || strlen(tt) == 0) && (tid == NULL || strlen(tid) == 0))
1247 return 1;
1248 if (tt == NULL || strcmp(tid, tt) != 0)
1249 return 0;
1250 free(tt);
1251 return 1;
1254 @ Here come some subroutines to deal with expanded fonts for HZ-algorithm.
1255 return 1 == identical
1257 static boolean cmp_font_name(int id, char *tt)
1259 char *tid;
1260 if (!is_valid_font(id))
1261 return 0;
1262 tid = font_name(id);
1263 if (tt == NULL && tid == NULL)
1264 return 1;
1265 if (tt == NULL || tid == NULL || strcmp(tid, tt) != 0)
1266 return 0;
1267 return 1;
1270 @ @c
1271 int test_no_ligatures(internal_font_number f)
1273 int c;
1274 for (c = font_bc(f); c <= font_ec(f); c++) {
1275 if (has_lig(f, c)) /* |char_exists(f,c)| */
1276 return 0;
1278 return 1;
1281 @ @c
1282 int get_tag_code(internal_font_number f, int c)
1284 small_number i;
1285 if (char_exists(f, c)) {
1286 i = char_tag(f, c);
1287 if (i == lig_tag)
1288 return 1;
1289 else if (i == list_tag)
1290 return 2;
1291 else if (i == ext_tag)
1292 return 4;
1293 else
1294 return 0;
1296 return -1;
1299 @ @c
1300 int get_lp_code(internal_font_number f, int c)
1302 charinfo *ci = char_info(f, c);
1303 return get_charinfo_lp(ci);
1306 int get_rp_code(internal_font_number f, int c)
1308 charinfo *ci = char_info(f, c);
1309 return get_charinfo_rp(ci);
1312 int get_ef_code(internal_font_number f, int c)
1314 charinfo *ci = char_info(f, c);
1315 return get_charinfo_ef(ci);
1318 @ @c
1319 void set_tag_code(internal_font_number f, int c, int i)
1321 int fixedi;
1322 charinfo *co;
1323 if (char_exists(f, c)) {
1324 /* |abs(fix_int(i-7,0))| */
1325 fixedi = -(i < -7 ? -7 : (i > 0 ? 0 : i));
1326 co = char_info(f, c);
1327 if (fixedi >= 4) {
1328 if (char_tag(f, c) == ext_tag)
1329 set_charinfo_tag(co, (char_tag(f, c) - ext_tag));
1330 fixedi = fixedi - 4;
1332 if (fixedi >= 2) {
1333 if (char_tag(f, c) == list_tag)
1334 set_charinfo_tag(co, (char_tag(f, c) - list_tag));
1335 fixedi = fixedi - 2;
1337 if (fixedi >= 1) {
1338 if (has_lig(f, c))
1339 set_charinfo_ligatures(co, NULL);
1340 if (has_kern(f, c))
1341 set_charinfo_kerns(co, NULL);
1346 @ @c
1347 void set_lp_code(internal_font_number f, int c, int i)
1349 charinfo *co;
1350 if (char_exists(f, c)) {
1351 co = char_info(f, c);
1352 set_charinfo_lp(co, i);
1356 void set_rp_code(internal_font_number f, int c, int i)
1358 charinfo *co;
1359 if (char_exists(f, c)) {
1360 co = char_info(f, c);
1361 set_charinfo_rp(co, i);
1365 void set_ef_code(internal_font_number f, int c, int i)
1367 charinfo *co;
1368 if (char_exists(f, c)) {
1369 co = char_info(f, c);
1370 set_charinfo_ef(co, i);
1374 @ @c
1375 void set_no_ligatures(internal_font_number f)
1377 int c;
1378 charinfo *co;
1379 if (font_tables[f]->ligatures_disabled)
1380 return;
1381 co = char_info(f, left_boundarychar);
1382 set_charinfo_ligatures(co, NULL);
1383 co = char_info(f, right_boundarychar); /* this is weird */
1384 set_charinfo_ligatures(co, NULL);
1385 for (c = 0; c < font_tables[f]->charinfo_count; c++) {
1386 co = font_tables[f]->charinfo + c;
1387 set_charinfo_ligatures(co, NULL);
1389 font_tables[f]->ligatures_disabled = 1;
1392 @ @c
1393 liginfo get_ligature(internal_font_number f, int lc, int rc)
1395 int k = 0;
1396 liginfo t, u;
1397 charinfo *co;
1398 t.lig = 0;
1399 t.type = 0;
1400 t.adj = 0;
1401 if (lc == non_boundarychar || rc == non_boundarychar || (!has_lig(f, lc)))
1402 return t;
1403 co = char_info(f, lc);
1404 while (1) {
1405 u = charinfo_ligature(co, k);
1406 if (lig_end(u))
1407 break;
1408 if (lig_char(u) == rc) {
1409 if (lig_disabled(u)) {
1410 return t;
1411 } else {
1412 return u;
1415 k++;
1417 return t;
1420 @ @c
1421 scaled raw_get_kern(internal_font_number f, int lc, int rc)
1423 int k = 0;
1424 kerninfo u;
1425 charinfo *co;
1426 if (lc == non_boundarychar || rc == non_boundarychar)
1427 return 0;
1428 co = char_info(f, lc);
1429 while (1) {
1430 u = charinfo_kern(co, k);
1431 if (kern_end(u))
1432 break;
1433 if (kern_char(u) == rc) {
1434 if (kern_disabled(u))
1435 return 0;
1436 else
1437 return kern_kern(u);
1439 k++;
1441 return 0;
1444 @ @c
1445 scaled get_kern(internal_font_number f, int lc, int rc)
1447 if (lc == non_boundarychar || rc == non_boundarychar || (!has_kern(f, lc)))
1448 return 0;
1449 return raw_get_kern(f, lc, rc);
1453 @ dumping and undumping fonts
1456 #define dump_string(a) \
1457 if (a!=NULL) { \
1458 x = (int)(strlen(a)+1); \
1459 dump_int(x); dump_things(*a, x); \
1460 } else { \
1461 x = 0; dump_int(x); \
1464 static void dump_charinfo(int f, int c)
1466 charinfo *co;
1467 int x;
1468 liginfo *lig;
1469 kerninfo *kern;
1470 dump_int(c);
1471 co = char_info(f, c);
1472 set_charinfo_used(co, 0);
1473 dump_int(get_charinfo_width(co));
1474 dump_int(get_charinfo_height(co));
1475 dump_int(get_charinfo_depth(co));
1476 dump_int(get_charinfo_italic(co));
1477 dump_int(get_charinfo_vert_italic(co));
1478 dump_int(get_charinfo_top_accent(co));
1479 dump_int(get_charinfo_bot_accent(co));
1480 dump_int(get_charinfo_tag(co));
1481 dump_int(get_charinfo_ef(co));
1482 dump_int(get_charinfo_rp(co));
1483 dump_int(get_charinfo_lp(co));
1484 dump_int(get_charinfo_remainder(co));
1485 dump_int(get_charinfo_used(co));
1486 dump_int(get_charinfo_index(co));
1487 dump_string(get_charinfo_name(co));
1488 dump_string(get_charinfo_tounicode(co));
1490 /* ligatures */
1491 x = 0;
1492 if ((lig = get_charinfo_ligatures(co)) != NULL) {
1493 while (!lig_end(lig[x])) {
1494 x++;
1496 x++;
1497 dump_int(x);
1498 dump_things(*lig, x);
1499 } else {
1500 dump_int(x);
1502 /* kerns */
1503 x = 0;
1504 if ((kern = get_charinfo_kerns(co)) != NULL) {
1505 while (!kern_end(kern[x])) {
1506 x++;
1508 x++;
1509 dump_int(x);
1510 dump_things(*kern, x);
1511 } else {
1512 dump_int(x);
1514 /* packets */
1515 x = vf_packet_bytes(co);
1516 dump_int(x);
1517 if (x > 0) {
1518 dump_things(*get_charinfo_packets(co), x);
1521 if (get_charinfo_tag(co) == ext_tag) {
1522 dump_charinfo_variants(get_charinfo_vert_variants(co));
1523 dump_charinfo_variants(get_charinfo_hor_variants(co));
1525 dump_math_kerns(co);
1528 static void dump_font_entry(texfont * f)
1530 int x;
1531 dump_int(f->_font_size);
1532 dump_int(f->_font_dsize);
1533 dump_int(f->_font_cidversion);
1534 dump_int(f->_font_cidsupplement);
1535 dump_int(f->_font_ec);
1536 x = (int) f->_font_checksum;
1537 dump_int(x);
1538 dump_int(f->_font_used);
1539 dump_int(f->_font_touched);
1540 dump_int(f->_font_cache_id);
1541 dump_int(f->_font_encodingbytes);
1542 dump_int(f->_font_oldmath);
1543 dump_int(f->_font_slant);
1544 dump_int(f->_font_extend);
1545 dump_int(f->font_max_shrink);
1546 dump_int(f->font_max_stretch);
1547 dump_int(f->_font_step);
1548 dump_int(f->_font_auto_expand);
1549 dump_int(f->_font_tounicode);
1550 dump_int(f->_font_type);
1551 dump_int(f->_font_format);
1552 dump_int(f->_font_embedding);
1553 dump_int(f->_font_bc);
1554 dump_int(f->_hyphen_char);
1555 dump_int(f->_skew_char);
1556 dump_int(f->_font_natural_dir);
1557 dump_int(f->_font_params);
1558 dump_int(f->_font_math_params);
1559 dump_int(f->ligatures_disabled);
1560 dump_int(f->_pdf_font_num);
1561 dump_int(f->_pdf_font_attr);
1564 void dump_font(int f)
1566 int i, x;
1568 set_font_used(f, 0);
1569 font_tables[f]->charinfo_cache = NULL;
1570 dump_font_entry(font_tables[f]);
1571 dump_string(font_name(f));
1572 dump_string(font_area(f));
1573 dump_string(font_filename(f));
1574 dump_string(font_fullname(f));
1575 dump_string(font_psname(f));
1576 dump_string(font_encodingname(f));
1577 dump_string(font_cidregistry(f));
1578 dump_string(font_cidordering(f));
1580 dump_things(*param_base(f), (font_params(f) + 1));
1582 if (font_math_params(f) > 0) {
1583 dump_things(*math_param_base(f), (font_math_params(f) + 1 ));
1585 if (has_left_boundary(f)) {
1586 dump_int(1);
1587 dump_charinfo(f, left_boundarychar);
1588 } else {
1589 dump_int(0);
1591 if (has_right_boundary(f)) {
1592 dump_int(1);
1593 dump_charinfo(f, right_boundarychar);
1594 } else {
1595 dump_int(0);
1598 for (i = font_bc(f); i <= font_ec(f); i++) {
1599 if (quick_char_exists(f, i)) {
1600 dump_charinfo(f, i);
1605 @ @c
1606 static int undump_charinfo(int f)
1608 charinfo *co;
1609 int x, i;
1610 char *s = NULL;
1611 liginfo *lig = NULL;
1612 kerninfo *kern = NULL;
1613 eight_bits *packet = NULL;
1615 undump_int(i);
1616 co = get_charinfo(f, i);
1617 undump_int(x);
1618 set_charinfo_width(co, x);
1619 undump_int(x);
1620 set_charinfo_height(co, x);
1621 undump_int(x);
1622 set_charinfo_depth(co, x);
1623 undump_int(x);
1624 set_charinfo_italic(co, x);
1625 undump_int(x);
1626 set_charinfo_vert_italic(co, x);
1627 undump_int(x);
1628 set_charinfo_top_accent(co, x);
1629 undump_int(x);
1630 set_charinfo_bot_accent(co, x);
1631 undump_int(x);
1632 set_charinfo_tag(co, x);
1633 undump_int(x);
1634 set_charinfo_ef(co, x);
1635 undump_int(x);
1636 set_charinfo_rp(co, x);
1637 undump_int(x);
1638 set_charinfo_lp(co, x);
1639 undump_int(x);
1640 set_charinfo_remainder(co, x);
1641 undump_int(x);
1642 set_charinfo_used(co, x);
1643 undump_int(x);
1644 set_charinfo_index(co, x);
1646 /* name */
1647 undump_int(x);
1648 if (x > 0) {
1649 font_bytes += x;
1650 s = xmalloc((unsigned) x);
1651 undump_things(*s, x);
1653 set_charinfo_name(co, s);
1654 /* tounicode */
1655 undump_int(x);
1656 if (x > 0) {
1657 font_bytes += x;
1658 s = xmalloc((unsigned) x);
1659 undump_things(*s, x);
1661 set_charinfo_tounicode(co, s);
1662 /* ligatures */
1663 undump_int(x);
1664 if (x > 0) {
1665 font_bytes += (int) ((unsigned) x * sizeof(liginfo));
1666 lig = xmalloc((unsigned) ((unsigned) x * sizeof(liginfo)));
1667 undump_things(*lig, x);
1669 set_charinfo_ligatures(co, lig);
1670 /* kerns */
1671 undump_int(x);
1672 if (x > 0) {
1673 font_bytes += (int) ((unsigned) x * sizeof(kerninfo));
1674 kern = xmalloc((unsigned) ((unsigned) x * sizeof(kerninfo)));
1675 undump_things(*kern, x);
1677 set_charinfo_kerns(co, kern);
1679 /* packets */
1680 undump_int(x);
1681 if (x > 0) {
1682 font_bytes += x;
1683 packet = xmalloc((unsigned) x);
1684 undump_things(*packet, x);
1686 set_charinfo_packets(co, packet);
1688 if (get_charinfo_tag(co) == ext_tag) {
1689 set_charinfo_vert_variants(co, undump_charinfo_variants());
1690 set_charinfo_hor_variants(co, undump_charinfo_variants());
1692 undump_math_kerns(co);
1693 return i;
1696 #define undump_font_string(a) \
1697 undump_int (x); \
1698 if (x>0) { \
1699 font_bytes += x; \
1700 s = xmalloc((unsigned)x); \
1701 undump_things(*s,x); \
1702 a(f,s); \
1705 static void undump_font_entry(texfont * f)
1707 int x = 0;
1708 /* *INDENT-OFF* */
1709 undump_int(x); f->_font_size = x;
1710 undump_int(x); f->_font_dsize = x;
1711 undump_int(x); f->_font_cidversion = x;
1712 undump_int(x); f->_font_cidsupplement = x;
1713 undump_int(x); f->_font_ec = x;
1714 undump_int(x); f->_font_checksum = (unsigned)x;
1715 undump_int(x); f->_font_used = (char)x;
1716 undump_int(x); f->_font_touched = (char)x;
1717 undump_int(x); f->_font_cache_id = x;
1718 undump_int(x); f->_font_encodingbytes = (char)x;
1719 undump_int(x); f->_font_oldmath = x;
1720 undump_int(x); f->_font_slant = x;
1721 undump_int(x); f->_font_extend = x;
1722 undump_int(x); f->font_max_shrink = x;
1723 undump_int(x); f->font_max_stretch = x;
1724 undump_int(x); f->_font_step = x;
1725 undump_int(x); f->_font_auto_expand = x;
1726 undump_int(x); f->_font_tounicode = (char)x;
1727 undump_int(x); f->_font_type = x;
1728 undump_int(x); f->_font_format = x;
1729 undump_int(x); f->_font_embedding = x;
1730 undump_int(x); f->_font_bc = x;
1731 undump_int(x); f->_hyphen_char = x;
1732 undump_int(x); f->_skew_char = x;
1733 undump_int(x); f->_font_natural_dir = x;
1734 undump_int(x); f->_font_params = x;
1735 undump_int(x); f->_font_math_params = x;
1736 undump_int(x); f->ligatures_disabled = x;
1737 undump_int(x); f->_pdf_font_num = x;
1738 undump_int(x); f->_pdf_font_attr = x;
1739 /* *INDENT-ON* */
1742 void undump_font(int f)
1744 int x, i;
1745 texfont *tt;
1746 charinfo *ci;
1747 char *s;
1748 sa_tree_item sa_value = { 0 };
1749 grow_font_table(f);
1750 tt = xmalloc(sizeof(texfont));
1751 memset(tt, 0, sizeof(texfont));
1752 font_bytes += (int) sizeof(texfont);
1753 undump_font_entry(tt);
1754 font_tables[f] = tt;
1756 undump_font_string(set_font_name);
1757 undump_font_string(set_font_area);
1758 undump_font_string(set_font_filename);
1759 undump_font_string(set_font_fullname);
1760 undump_font_string(set_font_psname);
1761 undump_font_string(set_font_encodingname);
1762 undump_font_string(set_font_cidregistry);
1763 undump_font_string(set_font_cidordering);
1765 i = (int) (sizeof(*param_base(f)) * ((unsigned) font_params(f) + 1));
1766 font_bytes += i;
1767 param_base(f) = xmalloc((unsigned) i);
1768 undump_things(*param_base(f), (font_params(f) + 1));
1770 if (font_math_params(f) > 0) {
1771 i = (int) (sizeof(*math_param_base(f)) *
1772 ((unsigned) font_math_params(f) + 1));
1773 font_bytes += i;
1774 math_param_base(f) = xmalloc((unsigned) i);
1775 undump_things(*math_param_base(f), (font_math_params(f) + 1));
1778 /* stack size 1, default item value 0 */
1779 font_tables[f]->characters = new_sa_tree(1, 1, sa_value);
1780 ci = xcalloc(1, sizeof(charinfo));
1781 set_charinfo_name(ci, xstrdup(".notdef"));
1782 font_tables[f]->charinfo = ci;
1783 undump_int(x);
1784 if (x) {
1785 i = undump_charinfo(f); /* left boundary */
1787 undump_int(x);
1788 if (x) {
1789 i = undump_charinfo(f); /* right boundary */
1792 i = font_bc(f);
1793 while (i < font_ec(f)) {
1794 i = undump_charinfo(f);
1798 /* moved from pdffont.w */
1800 @ @c
1801 #define font_id_text(A) cs_text(font_id_base+(A)) /* a frozen font identifier's name */
1803 int pk_dpi; /* PK pixel density value from \.{texmf.cnf} */
1805 @ @c
1806 internal_font_number tfm_lookup(char *s, scaled fs)
1807 { /* looks up for a TFM with name |s| loaded at |fs| size; if found then flushes |s| */
1808 internal_font_number k;
1809 if (fs != 0) {
1810 for (k = 1; k <= max_font_id(); k++) {
1811 if (cmp_font_name(k, s) && font_size(k) == fs) {
1812 return k;
1815 } else {
1816 for (k = 1; k <= max_font_id(); k++) {
1817 if (cmp_font_name(k, s)) {
1818 return k;
1822 return null_font;
1825 @ @c
1826 int fix_expand_value(internal_font_number f, int e)
1827 { /* return the multiple of |font_step(f)| that is nearest to |e| */
1828 int step;
1829 int max_expand;
1830 boolean neg;
1831 if (e == 0)
1832 return 0;
1833 if (e < 0) {
1834 e = -e;
1835 neg = true;
1836 max_expand = font_max_shrink(f);
1837 } else {
1838 neg = false;
1839 max_expand = font_max_stretch(f);
1841 if (e > max_expand) {
1842 e = max_expand;
1843 } else {
1844 step = font_step(f);
1845 if (e % step > 0)
1846 e = step * round_xn_over_d(e, 1, step);
1848 if (neg)
1849 e = -e;
1850 return e;
1853 @ @c
1854 void set_expand_params(internal_font_number f, boolean auto_expand,
1855 int stretch_limit, int shrink_limit, int font_step)
1856 { /* expand a font with given parameters */
1857 set_font_step(f, font_step);
1858 set_font_auto_expand(f, auto_expand);
1859 set_font_max_shrink(f, shrink_limit);
1860 set_font_max_stretch(f, stretch_limit);
1863 @ @c
1864 void read_expand_font(void)
1865 { /* read font expansion spec and load expanded font */
1866 int shrink_limit, stretch_limit, font_step;
1867 internal_font_number f;
1868 boolean auto_expand;
1869 /* read font expansion parameters */
1870 scan_font_ident();
1871 f = cur_val;
1872 if (f == null_font)
1873 normal_error("font expansion", "invalid font identifier");
1874 /*if (pdf_font_blink(f) != null_font)*/
1875 /* normal_error("font expansion",*/
1876 /* "\\fontexpand cannot be used this way (the base font has been expanded)");*/
1877 scan_optional_equals();
1878 scan_int();
1879 stretch_limit = fix_int(cur_val, 0, 1000);
1880 scan_int();
1881 shrink_limit = fix_int(cur_val, 0, 500);
1882 scan_int();
1883 font_step = fix_int(cur_val, 0, 100);
1884 if (font_step == 0)
1885 normal_error("font expansion", "invalid step");
1886 stretch_limit = stretch_limit - stretch_limit % font_step;
1887 if (stretch_limit < 0)
1888 stretch_limit = 0;
1889 shrink_limit = shrink_limit - shrink_limit % font_step;
1890 if (shrink_limit < 0)
1891 shrink_limit = 0;
1892 if ((stretch_limit == 0) && (shrink_limit == 0))
1893 normal_error("font expansion", "invalid limit(s)");
1894 auto_expand = false;
1895 if (scan_keyword("autoexpand")) {
1896 auto_expand = true;
1897 /* Scan an optional space */
1898 get_x_token();
1899 if (cur_cmd != spacer_cmd)
1900 back_input();
1903 if (font_step(f) != 0) {
1904 /* this font has been expanded, ensure the expansion parameters are identical */
1905 if (font_step(f) != font_step)
1906 normal_error("font expansion","font has been expanded with different expansion step");
1908 if (((font_max_stretch(f) == 0) && (stretch_limit != 0)) ||
1909 ((font_max_stretch(f) > 0)
1910 && (font_max_stretch(f) != stretch_limit)))
1911 normal_error("font expansion","font has been expanded with different stretch limit");
1913 if (((font_max_shrink(f) == 0) && (shrink_limit != 0)) ||
1914 ((font_max_shrink(f) > 0)
1915 && (font_max_shrink(f) != shrink_limit)))
1916 normal_error("font expansion","font has been expanded with different shrink limit");
1918 if (font_auto_expand(f) != auto_expand)
1919 normal_error("font expansion","font has been expanded with different auto expansion value");
1920 } else {
1921 if (font_used(f))
1922 normal_warning("font expansion", "font should be expanded before its first use");
1923 set_expand_params(f, auto_expand, stretch_limit, shrink_limit,
1924 font_step);
1928 @ @c
1929 void new_letterspaced_font(small_number a)
1930 { /* letter-space a font by creating a virtual font */
1931 pointer u; /* user's font identifier */
1932 str_number t; /* name for the frozen font identifier */
1933 internal_font_number f, k;
1934 boolean nolig = false;
1935 get_r_token();
1936 u = cur_cs;
1937 if (u >= hash_base)
1938 t = cs_text(u);
1939 else
1940 t = maketexstring("FONT");
1941 define(u, set_font_cmd, null_font);
1942 scan_optional_equals();
1943 scan_font_ident();
1944 k = cur_val;
1945 scan_int();
1946 if (scan_keyword("nolig"))
1947 nolig=true;
1948 f = letter_space_font(k, fix_int(cur_val, -1000, 1000), nolig);
1949 equiv(u) = f;
1950 eqtb[font_id_base + f] = eqtb[u];
1951 font_id_text(f) = t;
1954 @ @c
1955 void make_font_copy(small_number a)
1956 { /* make a font copy for further use with font expansion */
1957 pointer u; /* user's font identifier */
1958 str_number t; /* name for the frozen font identifier */
1959 internal_font_number f, k;
1960 get_r_token();
1961 u = cur_cs;
1962 if (u >= hash_base)
1963 t = cs_text(u);
1964 else
1965 t = maketexstring("FONT");
1966 define(u, set_font_cmd, null_font);
1967 scan_optional_equals();
1968 scan_font_ident();
1969 k = cur_val;
1970 f = copy_font_info(k);
1971 equiv(u) = f;
1972 eqtb[font_id_base + f] = eqtb[u];
1973 font_id_text(f) = t;
1976 @ @c
1977 void glyph_to_unicode(void)
1979 str_number s1, s2;
1980 scan_toks(false, true);
1981 s1 = tokens_to_string(def_ref);
1982 delete_token_ref(def_ref);
1983 scan_toks(false, true);
1984 s2 = tokens_to_string(def_ref);
1985 delete_token_ref(def_ref);
1986 def_tounicode(s1, s2);
1987 flush_str(s2);
1988 flush_str(s1);