1
4
5
26
27# include "luametatex.h"
28
29
38
39static inline halfword tex_aux_discretionary_node(halfword target, int location)
40{
41 switch (location) {
42 case pre_break_code : return disc_pre_break_node(target);
43 case post_break_code: return disc_post_break_node(target);
44 case no_break_code : return disc_no_break_node(target);
45 default : return null;
46 }
47}
48
49static inline int tex_aux_same_font_properties(halfword a, halfword b)
50{
51 return node_type(a) == glyph_node && node_type(b) == glyph_node
52 && glyph_font(a) == glyph_font(b)
53 && glyph_x_scale(a) == glyph_x_scale(b)
54 && glyph_y_scale(a) == glyph_y_scale(b)
55 && glyph_scale(a) == glyph_scale(b);
56}
57
58static inline int tex_aux_apply_base_kerning(halfword n)
59{
60 if (glyph_protected(n)) {
61 return 0;
62 } else {
63 halfword f = glyph_font(n);
64 if (f >= 0 && f <= lmt_font_state.font_data.ptr && lmt_font_state.fonts[f]) {
65 return has_font_text_control(f, text_control_base_kerning);
66 } else {
67 return 0;
68 }
69 }
70}
71
72static inline int tex_aux_apply_base_ligaturing(halfword n)
73{
74 if (glyph_protected(n)) {
75 return 0;
76 } else {
77 halfword f = glyph_font(n);
78 if (f >= 0 && f <= lmt_font_state.font_data.ptr && lmt_font_state.fonts[f]) {
79 return has_font_text_control(f, text_control_base_ligaturing);
80 } else {
81 return 0;
82 }
83 }
84}
85
86
87
88static inline scaled tex_aux_font_x_scaled(scaled v)
89{
90 return v ? scaledround(0.000001 * (glyph_scale_par ? glyph_scale_par : 1000) * (glyph_x_scale_par ? glyph_x_scale_par : 1000) * v) : 0;
91}
92
93static inline scaled tex_aux_font_y_scaled(scaled v)
94{
95 return v ? scaledround(0.000001 * (glyph_scale_par ? glyph_scale_par : 1000) * (glyph_y_scale_par ? glyph_y_scale_par : 1000) * v) : 0;
96}
97
98static inline scaled tex_aux_glyph_x_scaled(halfword g, scaled v)
99{
100 return v ? scaledround(0.000001 * (glyph_scale(g) ? glyph_scale(g) : 1000) * (glyph_x_scale(g) ? glyph_x_scale(g) : 1000) * v) : 0;
101}
102
103static inline scaled tex_aux_glyph_y_scaled(halfword g, scaled v)
104{
105 return v ? scaledround(0.000001 * (glyph_scale(g) ? glyph_scale(g) : 1000) * (glyph_y_scale(g) ? glyph_y_scale(g) : 1000) * v) : 0;
106}
107
108font_state_info lmt_font_state = {
109 .fonts = NULL,
110 .adjust_stretch = 0,
111 .adjust_shrink = 0,
112 .adjust_step = 0,
113 .padding = 0,
114 .font_data = {
115 .minimum = min_font_size,
116 .maximum = max_font_size,
117 .size = memory_data_unset,
118 .step = stp_font_size,
119 .allocated = 0,
120 .itemsize = sizeof(texfont *),
121 .top = 0,
122 .ptr = 0,
123 .initial = memory_data_unset,
124 .offset = 0,
125 .extra = 0,
126 },
127};
128
129
133
134void tex_initialize_fonts(void)
135{
136 texfont **tmp = aux_allocate_clear_array(sizeof(texfont *), lmt_font_state.font_data.minimum, 0);
137 if (tmp) {
138 for (int i = 0; i < lmt_font_state.font_data.minimum; i++) {
139 tmp[i] = NULL;
140 }
141 lmt_font_state.fonts = tmp;
142 lmt_font_state.font_data.allocated = lmt_font_state.font_data.minimum;
143 lmt_font_state.font_data.top = lmt_font_state.font_data.minimum;
144 lmt_font_state.font_data.ptr = -1;
145 tex_create_null_font();
146 } else {
147 tex_overflow_error("fonts", lmt_font_state.font_data.minimum);
148 }
149}
150
151
152
153int tex_new_font_id(void)
154{
155 if (lmt_font_state.font_data.ptr < lmt_font_state.font_data.top) {
156 ++lmt_font_state.font_data.ptr;
157 return lmt_font_state.font_data.ptr;
158 } else if (lmt_font_state.font_data.top < lmt_font_state.font_data.maximum) {
159 texfont **tmp ;
160 int top = lmt_font_state.font_data.top + lmt_font_state.font_data.step;
161 if (top > lmt_font_state.font_data.maximum) {
162 top = lmt_font_state.font_data.maximum;
163 }
164 tmp = aux_reallocate_array(lmt_font_state.fonts, sizeof(texfont *), top, 0);
165 if (tmp) {
166 for (int i = lmt_font_state.font_data.top + 1; i < top; i++) {
167 tmp[i] = NULL;
168 }
169 lmt_font_state.fonts = tmp;
170 lmt_font_state.font_data.allocated = top;
171 lmt_font_state.font_data.top = top;
172 lmt_font_state.font_data.ptr += 1;
173 return lmt_font_state.font_data.ptr;
174 }
175 }
176 tex_overflow_error("fonts", lmt_font_state.font_data.maximum);
177 return 0;
178}
179
180int tex_get_font_max_id(void)
181{
182 return lmt_font_state.font_data.ptr;
183}
184
185void tex_dump_font_data(dumpstream f) {
186 dump_int(f, lmt_font_state.font_data.ptr);
187}
188
189void tex_undump_font_data(dumpstream f) {
190 int x;
191 undump_int(f, x);
192 lmt_font_state.font_data.ptr = 0;
193}
194
195void tex_set_charinfo_extensible_recipe(charinfo *ci, extinfo *ext)
196{
197 if (ci->math) {
198 extinfo *list = ci->math->extensible_recipe;
199 if (list) {
200 while (list) {
201 extinfo *c = list->next;
202 lmt_memory_free(list);
203 list = c;
204 }
205 }
206 ci->math->extensible_recipe = ext;
207 }
208}
209
210void tex_set_font_parameters(halfword f, int index)
211{
212 int i = font_parameter_count(f);
213 if (index > i) {
214
215 int size = (index + 2) * (int) sizeof(int);
216 int *list = lmt_memory_realloc(font_parameter_base(f), (size_t) size);
217 if (list) {
218 lmt_font_state.font_data.extra += (index - i + 1) * (int) sizeof(scaled);
219 font_parameter_base(f) = list;
220 font_parameter_count(f) = index;
221 while (i < index) {
222 font_parameter(f, ++i) = 0;
223 }
224 } else {
225 tex_overflow_error("font", size);
226 }
227 }
228}
229
230
231
232int tex_new_font(void)
233{
234 int size = sizeof(charinfo);
235 charinfo *ci = lmt_memory_calloc(1, (size_t) size);
236 if (ci) {
237 texfont *tf = NULL;
238 size = sizeof(texfont);
239 tf = lmt_memory_calloc(1, (size_t) size);
240 if (tf) {
241 sa_tree_item sa_value = { 0 };
242 int id = tex_new_font_id();
243 lmt_font_state.font_data.extra += size;
244 lmt_font_state.fonts[id] = tf;
245 set_font_name(id, NULL);
246 set_font_original(id, NULL);
247 set_font_left_boundary(id, NULL);
248 set_font_right_boundary(id, NULL);
249 set_font_parameter_base(id, NULL);
250 set_font_math_parameter_base(id, NULL);
251
252 set_font_first_character(id, 1);
253 set_font_hyphen_char(id, '-');
254 set_font_skew_char(id, -1);
255
256 tex_set_font_parameters(id, 7);
257 for (int i = 0; i <= 7; i++) {
258 tex_set_font_parameter(id, i, 0);
259 }
260
261 tf->characters = sa_new_tree(fontchar_sparse_identifier, 1, 1, 4, sa_value);
262 tf->chardata = ci;
263 tf->chardata_size = 1;
264 tf->weight = 1.0;
265 return id;
266 }
267 }
268 tex_overflow_error("font", size);
269 return 0;
270}
271
272void tex_font_malloc_charinfo(halfword f, int index)
273{
274 int glyph = lmt_font_state.fonts[f]->chardata_size;
275 int size = (glyph + index) * sizeof(charinfo);
276 charinfo *data = lmt_memory_realloc(lmt_font_state.fonts[f]->chardata , (size_t) size);
277 if (data) {
278 lmt_font_state.font_data.extra += index * sizeof(charinfo);
279 lmt_font_state.fonts[f]->chardata = data;
280 memset(&data[glyph], 0, (size_t) index * sizeof(charinfo));
281 lmt_font_state.fonts[f]->chardata_size += index;
282 } else {
283 tex_overflow_error("font", size);
284 }
285}
286
287void tex_char_malloc_mathinfo(charinfo *ci)
288{
289 int size = sizeof(mathinfo);
290 mathinfo *mi = lmt_memory_calloc(1, (size_t) size);
291 if (mi) {
292 mi->extensible_recipe = NULL;
293
294 mi->top_left_math_kern_array = NULL;
295 mi->top_right_math_kern_array = NULL;
296 mi->bottom_right_math_kern_array = NULL;
297 mi->bottom_left_math_kern_array = NULL;
298
299 mi->top_left_kern = 0;
300 mi->top_right_kern = 0;
301 mi->bottom_left_kern = 0;
302 mi->bottom_right_kern = 0;
303
304 mi->left_margin = 0;
305 mi->right_margin = 0;
306 mi->top_margin = 0;
307 mi->bottom_margin = 0;
308
309 mi->top_overshoot = INT_MIN;
310 mi->bottom_overshoot = INT_MIN;
311 if (ci->math) {
312
313 tex_set_charinfo_extensible_recipe(ci, NULL);
314 set_charinfo_top_left_math_kern_array(ci, NULL);
315 set_charinfo_top_right_math_kern_array(ci, NULL);
316 set_charinfo_bottom_right_math_kern_array(ci, NULL);
317 set_charinfo_bottom_left_math_kern_array(ci, NULL);
318 lmt_memory_free(ci->math);
319 } else {
320 lmt_font_state.font_data.extra += size;
321 }
322 ci->math = mi;
323 } else {
324 tex_overflow_error("font", size);
325 }
326}
327
328static inline int aux_find_charinfo_id(halfword f, int c)
329{
330 sa_tree_item item;
331 sa_get_item_4(lmt_font_state.fonts[f]->characters, c, &item);
332 return (int) item.int_value;
333}
334
335charinfo *tex_get_charinfo(halfword f, int c)
336{
337 if (proper_char_index(f, c)) {
338 sa_tree_item item;
339 int glyph;
340 sa_get_item_4(lmt_font_state.fonts[f]->characters, c, &item);
341 glyph = (int) item.int_value;
342 if (! glyph) {
343 sa_tree_item sa_value = { 0 };
344 int tglyph = ++lmt_font_state.fonts[f]->chardata_count;
345 if (tglyph >= lmt_font_state.fonts[f]->chardata_size) {
346 tex_font_malloc_charinfo(f, 256);
347 }
348 lmt_font_state.fonts[f]->chardata[tglyph].expansion = scaling_factor;
349 sa_value.int_value = tglyph;
350
351 sa_set_item_4(lmt_font_state.fonts[f]->characters, c, sa_value, 1);
352 glyph = tglyph;
353 }
354 return &(lmt_font_state.fonts[f]->chardata[glyph]);
355 } else if (c == left_boundary_char) {
356 if (! font_has_left_boundary(f)) {
357 int size = sizeof(charinfo);
358 charinfo *ci = lmt_memory_calloc(1, (size_t) size);
359 if (ci) {
360 lmt_font_state.font_data.extra += size;
361 set_font_left_boundary(f, ci);
362 } else {
363 tex_overflow_error("font", size);
364 }
365 }
366 return font_left_boundary(f);
367 } else if (c == right_boundary_char) {
368 if (! font_has_right_boundary(f)) {
369 int size = sizeof(charinfo);
370 charinfo *ci = lmt_memory_calloc(1, (size_t) size);
371 if (ci) {
372 lmt_font_state.font_data.extra += size;
373 set_font_right_boundary(f, ci);
374 } else {
375 tex_overflow_error("font", size);
376 }
377 }
378 return font_right_boundary(f);
379 } else {
380 return &(lmt_font_state.fonts[f]->chardata[0]);
381 }
382}
383
384static charinfo *tex_aux_char_info(halfword f, int c)
385{
386 if (f > lmt_font_state.font_data.ptr) {
387 return NULL;
388 } else if (proper_char_index(f, c)) {
389 return &(lmt_font_state.fonts[f]->chardata[(int) aux_find_charinfo_id(f, c)]);
390 } else if (c == left_boundary_char) {
391 if (font_left_boundary(f)) {
392 return font_left_boundary(f);
393 }
394 } else if (c == right_boundary_char) {
395 if (font_right_boundary(f)) {
396 return font_right_boundary(f);
397 }
398 }
399 return &(lmt_font_state.fonts[f]->chardata[0]);
400}
401
402
403
404
405
406
407
408static scaled tex_aux_glyph_weight_done(halfword g)
409{
410 return glyph_weight(g) && tex_has_glyph_option(g, glyph_option_weight_less)
411 ? 0 : lround(glyph_weight(g) * lmt_font_state.fonts[glyph_font(g)]->weight);
412}
413
414void tex_char_process(halfword f, int c)
415{
416 if (tex_char_has_tag_from_font(f, c, callback_tag)) {
417 int callback_id = lmt_callback_defined(process_character_callback);
418 if (callback_id > 0) {
419 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "dd->", f, c);
420 }
421 tex_char_reset_tag_from_font(f, c, callback_tag);
422 }
423}
424
425int tex_char_exists(halfword f, int c)
426{
427 if (f > lmt_font_state.font_data.ptr) {
428 return 0;
429 } else if (proper_char_index(f, c)) {
430 return (int) aux_find_charinfo_id(f, c);
431 } else if (c == left_boundary_char) {
432 if (font_has_left_boundary(f)) {
433 return 1;
434 }
435 } else if (c == right_boundary_char) {
436 if (font_has_right_boundary(f)) {
437 return 1;
438 }
439 }
440 return 0;
441}
442
443
458
459int tex_math_char_exists(halfword f, int c, int size)
460{
461 (void) size;
462 return (f > 0 && f <= lmt_font_state.font_data.ptr && proper_char_index(f, c));
463}
464
465
469
470int tex_get_math_char(halfword f, int c, int size, scaled *scale, scaled *xscale, scaled *yscale, scaled *weight, int direction)
471{
472 int id = aux_find_charinfo_id(f, c);
473 texfont *tf = lmt_font_state.fonts[f];
474 if (id) {
475
476 if (direction) {
477 charinfo *ci = &tf->chardata[id];
478 int m = ci->math->mirror;
479 if (m && proper_char_index(f, m)) {
480 int mid = aux_find_charinfo_id(f, m);
481 if (mid) {
482 id = mid;
483 c = m;
484 }
485 }
486 }
487
488 if (size && tf->compactmath) {
489 for (int i=1;i<=size;i++) {
490 charinfo *ci = &tf->chardata[id];
491 if (ci->math) {
492 int s = ci->math->smaller;
493 if (s && proper_char_index(f, s)) {
494 id = aux_find_charinfo_id(f, s);
495 if (id) {
496
497 c = s;
498 } else {
499 break;
500 }
501 } else {
502 break;
503 }
504 } else {
505 break;
506 }
507 }
508 }
509 }
510 if (scale) {
511 *scale = tex_get_math_font_scale(f, size);
512 *xscale = tex_get_math_font_x_scale(f, size);
513 *yscale = tex_get_math_font_y_scale(f, size);
514 *weight = tex_get_math_font_weight(f, size);
515 if (! *scale) {
516 *scale = scaling_factor;
517 }
518 if (! *xscale) {
519 *xscale = scaling_factor;
520 }
521 if (! *yscale) {
522 *yscale = scaling_factor;
523 }
524 }
525 return c;
526}
527
528void tex_append_charinfo_extensible_recipe(charinfo *ci, int glyph, int startconnect, int endconnect, int advance, int extender)
529{
530 if (ci->math) {
531 int size = sizeof(extinfo);
532 extinfo *ext = lmt_memory_malloc((size_t) size);
533 if (ext) {
534 extinfo *lst = ci->math->extensible_recipe;
535 ext->next = NULL;
536 ext->glyph = glyph;
537 ext->start_overlap = startconnect;
538 ext->end_overlap = endconnect;
539 ext->advance = advance;
540 ext->extender = extender;
541 if (lst) {
542 while (lst->next) {
543 lst = lst->next;
544 }
545 lst->next = ext;
546 } else {
547 ci->math->extensible_recipe = ext;
548 }
549 } else {
550 tex_overflow_error("font", size);
551 }
552 }
553}
554
555int tex_get_charinfo_math_kerns(charinfo *ci, int id)
556{
557
558 if (ci->math) {
559 switch (id) {
560 case top_left_kern:
561 return ci->math->top_left_math_kerns;
562 case bottom_left_kern:
563 return ci->math->bottom_left_math_kerns;
564 case top_right_kern:
565 return ci->math->top_right_math_kerns;
566 case bottom_right_kern:
567 return ci->math->bottom_right_math_kerns;
568 default:
569 tex_confusion("weird math kern");
570 break;
571 }
572 }
573 return 0;
574}
575
576void tex_add_charinfo_math_kern(charinfo *ci, int id, scaled ht, scaled krn)
577{
578 if (ci->math) {
579 int k = 0;
580 int s = 0;
581 scaled *a = NULL;
582 switch (id) {
583 case top_right_kern:
584 {
585 k = ci->math->top_right_math_kerns;
586 s = 2 * (k + 1) * (int) sizeof(scaled);
587 a = lmt_memory_realloc(ci->math->top_right_math_kern_array, (size_t) s);
588 if (a) {
589 ci->math->top_right_math_kern_array = a;
590 ci->math->top_right_math_kerns++;
591 }
592 break;
593 }
594 case bottom_right_kern:
595 {
596 k = ci->math->bottom_right_math_kerns;
597 s = 2 * (k + 1) * (int) sizeof(scaled);
598 a = lmt_memory_realloc(ci->math->bottom_right_math_kern_array, (size_t) s);
599 if (a) {
600 ci->math->bottom_right_math_kern_array = a;
601 ci->math->bottom_right_math_kerns++;
602 }
603 break;
604 }
605 case bottom_left_kern:
606 {
607 k = ci->math->bottom_left_math_kerns;
608 s = 2 * (k + 1) * (int) sizeof(scaled);
609 a = lmt_memory_realloc(ci->math->bottom_left_math_kern_array, (size_t) s);
610 if (a) {
611 ci->math->bottom_left_math_kern_array = a;
612 ci->math->bottom_left_math_kerns++;
613 }
614 break;
615 }
616 case top_left_kern:
617 {
618 k = ci->math->top_left_math_kerns;
619 s = 2 * (k + 1) * (int) sizeof(scaled);
620 a = lmt_memory_realloc(ci->math->top_left_math_kern_array, (size_t) s);
621 if (a) {
622 ci->math->top_left_math_kern_array = a;
623 ci->math->top_left_math_kerns++;
624 }
625 break;
626 }
627 default:
628 tex_confusion("add math kern");
629 return;
630 }
631 if (a) {
632 a[2 * k] = ht;
633 a[(2 * k) + 1] = krn;
634 } else {
635 tex_overflow_error("font", s);
636 }
637 }
638}
639
640
686
687
688
689void tex_set_font_math_parameters(halfword f, int b)
690{
691 int i = font_math_parameter_count(f);
692 if (i < b) {
693 size_t size = ((size_t) b + 2) * sizeof(scaled);
694 scaled *data = lmt_memory_realloc(font_math_parameter_base(f), size);
695 if (data) {
696 lmt_font_state.font_data.extra += (int) (((size_t) b - i + 1) * sizeof(scaled));
697 font_math_parameter_base(f) = data;
698 font_math_parameter_count(f) = b;
699 while (i < b) {
700 ++i;
701
702 font_math_parameter(f, i) = undefined_math_parameter;
703 }
704 } else {
705 tex_overflow_error("font", (int) size);
706 }
707 }
708}
709
710void tex_delete_font(int f)
711{
712 if (lmt_font_state.fonts[f]) {
713 tex_set_font_name(f, NULL);
714 tex_set_font_original(f, NULL);
715 set_font_left_boundary(f, NULL);
716 set_font_right_boundary(f, NULL);
717 for (int i = font_first_character(f); i <= font_last_character(f); i++) {
718 if (tex_char_exists(f, i)) {
719 charinfo *co = tex_aux_char_info(f, i);
720 set_charinfo_kerns(co, NULL);
721 set_charinfo_ligatures(co, NULL);
722 if (co->math) {
723 tex_set_charinfo_extensible_recipe(co, NULL);
724 set_charinfo_top_left_math_kern_array(co, NULL);
725 set_charinfo_top_right_math_kern_array(co, NULL);
726 set_charinfo_bottom_right_math_kern_array(co, NULL);
727 set_charinfo_bottom_left_math_kern_array(co, NULL);
728 set_charinfo_math(co, NULL);
729 }
730 }
731 }
732
733 lmt_memory_free(lmt_font_state.fonts[f]->chardata);
734 sa_destroy_tree(lmt_font_state.fonts[f]->characters);
735 lmt_memory_free(font_parameter_base(f));
736 if (font_math_parameter_base(f)) {
737 lmt_memory_free(font_math_parameter_base(f));
738 }
739 lmt_memory_free(lmt_font_state.fonts[f]);
740 lmt_font_state.fonts[f] = NULL;
741 if (lmt_font_state.font_data.ptr == f) {
742 lmt_font_state.font_data.ptr--;
743 }
744 }
745}
746
747void tex_create_null_font(void)
748{
749 int id = tex_new_font();
750 tex_set_font_name(id, "nullfont");
751 tex_set_font_original(id, "nullfont");
752}
753
754int tex_is_valid_font(halfword f)
755{
756 return (f >= 0 && f <= lmt_font_state.font_data.ptr && lmt_font_state.fonts[f]);
757}
758
759int tex_checked_font(halfword f)
760{
761 return (f >= 0 && f <= lmt_font_state.font_data.ptr && lmt_font_state.fonts[f]) ? f : null_font;
762}
763
764halfword tex_get_font_identifier(halfword fontspec)
765{
766 if (fontspec) {
767 halfword fnt = font_spec_identifier(fontspec);
768 if ((fnt >= 0 && fnt <= lmt_font_state.font_data.ptr && lmt_font_state.fonts[fnt])) {
769 return fnt;
770 }
771 }
772 return null_font;
773}
774
775
779
780ligatureinfo tex_get_ligature(halfword f, int lc, int rc)
781{
782 ligatureinfo t = { 0, 0, 0, 0 };
783 if (lc != non_boundary_char && rc != non_boundary_char && tex_has_ligature(f, lc)) {
784 int k = 0;
785 charinfo *co = tex_aux_char_info(f, lc);
786 while (1) {
787 ligatureinfo u = charinfo_ligature(co, k);
788 if (ligature_end(u)) {
789 break;
790 } else if (ligature_char(u) == rc) {
791 return ligature_disabled(u) ? t : u;
792 }
793 k++;
794 }
795 }
796 return t;
797}
798
799int tex_raw_get_kern(halfword f, int lc, int rc)
800{
801 if (lc != non_boundary_char && rc != non_boundary_char) {
802 int k = 0;
803 charinfo *co = tex_aux_char_info(f, lc);
804 while (1) {
805 kerninfo u = charinfo_kern(co, k);
806 if (kern_end(u)) {
807 break;
808 } else if (kern_char(u) == rc) {
809 return kern_disabled(u) ? 0 : kern_kern(u);
810 }
811 k++;
812 }
813 }
814 return 0;
815}
816
817int tex_get_kern(halfword f, int lc, int rc)
818{
819 if (lc == non_boundary_char || rc == non_boundary_char || (! tex_has_kern(f, lc))) {
820 return 0;
821 } else {
822 return tex_raw_get_kern(f, lc, rc);
823 }
824}
825
826scaled tex_valid_kern(halfword left, halfword right)
827{
828 if (node_type(left) == glyph_node && node_type(right) == glyph_node) {
829 halfword fl = glyph_font(left);
830 halfword fr = glyph_font(right);
831 halfword cl = glyph_character(left);
832 halfword cr = glyph_character(right);
833 if (fl == fr && cl != non_boundary_char && cr != non_boundary_char && tex_has_kern(fl, cl) && ! tex_has_glyph_option(left, glyph_option_no_right_kern) && ! tex_has_glyph_option(right, glyph_option_no_left_kern)) {
834 return tex_raw_get_kern(fl, cl, cr);
835 }
836 }
837 return 0;
838}
839
840
845
846halfword tex_checked_font_adjust(halfword adjust_spacing, halfword adjust_spacing_step, halfword adjust_spacing_shrink, halfword adjust_spacing_stretch)
847{
848 if (adjust_spacing >= adjust_spacing_full) {
849 if (adjust_spacing_step > 0) {
850 lmt_font_state.adjust_step = adjust_spacing_step;
851 lmt_font_state.adjust_shrink = adjust_spacing_shrink;
852 lmt_font_state.adjust_stretch = adjust_spacing_stretch;
853 if (lmt_font_state.adjust_step > max_font_adjust_step) {
854 lmt_font_state.adjust_step = max_font_adjust_step;
855 }
856 if (lmt_font_state.adjust_shrink < 0) {
857 lmt_font_state.adjust_shrink = 0;
858 } else if (lmt_font_state.adjust_shrink > max_font_adjust_shrink_factor) {
859 lmt_font_state.adjust_shrink = max_font_adjust_shrink_factor;
860 }
861 if (lmt_font_state.adjust_stretch < 0) {
862 lmt_font_state.adjust_stretch = 0;
863 } else if (lmt_font_state.adjust_stretch > max_font_adjust_stretch_factor) {
864 lmt_font_state.adjust_stretch = max_font_adjust_stretch_factor;
865 }
866 return adjust_spacing;
867 }
868 } else {
869 adjust_spacing = adjust_spacing_off;
870 }
871 lmt_font_state.adjust_step = 0;
872 lmt_font_state.adjust_shrink = 0;
873 lmt_font_state.adjust_stretch = 0;
874 return adjust_spacing;
875}
876
877int tex_read_font_info(char *cnom, scaled s)
878{
879 int callback_id = lmt_callback_defined(define_font_callback);
880 if (callback_id > 0) {
881 int f = 0;
882 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "Sd->d", cnom, s, &f);
883 if (tex_is_valid_font(f)) {
884 tex_set_font_original(f, (char *) cnom);
885 return f;
886 } else {
887 return 0;
888 }
889 } else {
890 tex_normal_warning("fonts","no font has been read, you need to enable or fix the callback");
891 return 0;
892 }
893}
894
895
896
897halfword tex_get_font_parameter(halfword f, halfword code)
898{
899 if (font_parameter_count(f) < code) {
900 tex_set_font_parameters(f, code);
901 }
902 return font_parameter(f, code);
903}
904
905void tex_set_font_parameter(halfword f, halfword code, scaled v)
906{
907 if (font_parameter_count(f) < code) {
908 tex_set_font_parameters(f, code);
909 }
910 font_parameter(f, code) = v;
911}
912
913scaled tex_get_font_slant (halfword f) { return font_parameter(f, slant_code); }
914scaled tex_get_font_space (halfword f) { return font_parameter(f, space_code); }
915scaled tex_get_font_space_stretch (halfword f) { return font_parameter(f, space_stretch_code); }
916scaled tex_get_font_space_shrink (halfword f) { return font_parameter(f, space_shrink_code); }
917scaled tex_get_font_ex_height (halfword f) { return font_parameter(f, ex_height_code); }
918scaled tex_get_font_em_width (halfword f) { return font_parameter(f, em_width_code); }
919scaled tex_get_font_extra_space (halfword f) { return font_parameter(f, extra_space_code); }
920
921scaled tex_get_scaled_slant (halfword f) { return font_parameter(f, slant_code); }
922scaled tex_get_scaled_space (halfword f) { return tex_aux_font_x_scaled(font_parameter(f, space_code)); }
923scaled tex_get_scaled_space_stretch (halfword f) { return tex_aux_font_x_scaled(font_parameter(f, space_stretch_code)); }
924scaled tex_get_scaled_space_shrink (halfword f) { return tex_aux_font_x_scaled(font_parameter(f, space_shrink_code)); }
925scaled tex_get_scaled_ex_height (halfword f) { return tex_aux_font_y_scaled(font_parameter(f, ex_height_code)); }
926scaled tex_get_scaled_em_width (halfword f) { return tex_aux_font_x_scaled(font_parameter(f, em_width_code)); }
927scaled tex_get_scaled_extra_space (halfword f) { return tex_aux_font_x_scaled(font_parameter(f, extra_space_code)); }
928
929scaled tex_font_x_scaled (scaled v) { return tex_aux_font_x_scaled(v); }
930scaled tex_font_y_scaled (scaled v) { return tex_aux_font_y_scaled(v); }
931
932halfword tex_get_scaled_parameter(halfword f, halfword code)
933{
934 if (font_parameter_count(f) < code) {
935 tex_set_font_parameters(f, code);
936 }
937 switch (code) {
938 case slant_code:
939 return font_parameter(f, code);
940 case ex_height_code:
941 return tex_aux_font_y_scaled(font_parameter(f, code));
942 default:
943 return tex_aux_font_x_scaled(font_parameter(f, code));
944 }
945}
946
947void tex_set_scaled_parameter(halfword f, halfword code, scaled v)
948{
949 if (font_parameter_count(f) < code) {
950 tex_set_font_parameters(f, code);
951 }
952 font_parameter(f, code) = tex_aux_font_x_scaled(v);
953}
954
955halfword tex_get_scaled_glue(halfword f)
956{
957 halfword p = tex_new_glue_node(zero_glue, space_skip_glue);
958 glue_amount(p) = tex_aux_font_x_scaled(font_parameter(f, space_code));
959 glue_stretch(p) = tex_aux_font_x_scaled(font_parameter(f, space_stretch_code));
960 glue_shrink(p) = tex_aux_font_x_scaled(font_parameter(f, space_shrink_code));
961 glue_font(p) = f;
962 return p;
963}
964
965halfword tex_get_scaled_parameter_glue(quarterword p, quarterword s)
966{
967 halfword n = tex_new_glue_node(zero_glue, s);
968 halfword g = glue_parameter(p);
969
970
971
972 glue_amount(n) = tex_aux_font_x_scaled(glue_amount(g));
973 glue_stretch(n) = tex_aux_font_x_scaled(glue_stretch(g));
974 glue_shrink(n) = tex_aux_font_x_scaled(glue_shrink(g));
975 return n;
976}
977
978halfword tex_get_parameter_glue(quarterword p, quarterword s)
979{
980 halfword n = tex_new_glue_node(zero_glue, s);
981 halfword g = glue_parameter(p);
982 if (g) {
983 memcpy((void *) (lmt_node_memory_state.nodes + n + 2), (void *) (lmt_node_memory_state.nodes + g + 2), (glue_spec_size - 2) * (sizeof(memoryword)));
984 }
985 return n;
986}
987
988
989
990static void tex_aux_discretionary_append(halfword target, int location, halfword n)
991{
992 halfword node = tex_aux_discretionary_node(target, location);
993 if (node_tail(node)) {
994 tex_couple_nodes(node_tail(node), n);
995 } else {
996 node_head(node) = n;
997 }
998 node_tail(node) = n;
999}
1000
1001static void tex_aux_discretionary_prepend(halfword target, int location, halfword n)
1002{
1003 halfword node = tex_aux_discretionary_node(target, location);
1004 if (node_head(node)) {
1005 tex_couple_nodes(n, node_head(node));
1006 } else {
1007 node_tail(node) = n;
1008 }
1009 node_head(node) = n;
1010}
1011
1012static void tex_aux_nesting_prepend_list(halfword target, int location, halfword n)
1013{
1014 halfword node = tex_aux_discretionary_node(target, location);
1015 halfword copy = tex_copy_node_list(n, null);
1016 halfword tail = tex_tail_of_node_list(copy);
1017 if (node_head(node)) {
1018 tex_couple_nodes(tail, node_head(node));
1019 } else {
1020 node_tail(node) = tail;
1021 }
1022 node_head(node) = copy;
1023}
1024
1025int tex_valid_ligature(halfword left, halfword right, int *slot)
1026{
1027 if (node_type(left) != glyph_node) {
1028 return -1;
1029 } else if (glyph_font(left) != glyph_font(right)) {
1030 return -1;
1031 } else if (tex_has_glyph_option(left, glyph_option_no_right_ligature) || tex_has_glyph_option(right, glyph_option_no_left_ligature)) {
1032 return -1;
1033 } else {
1034 ligatureinfo lig = tex_get_ligature(glyph_font(left), glyph_character(left), glyph_character(right));
1035 if (ligature_is_valid(lig)) {
1036 *slot = ligature_replacement(lig);
1037 return ligature_type(lig);
1038 } else {
1039 return -1;
1040 }
1041 }
1042}
1043
1044static int tex_aux_found_ligature(halfword left, halfword right)
1045{
1046 if (! left || ! right) {
1047 return 0;
1048 } else if (node_type(left) != glyph_node || node_type(right) != glyph_node) {
1049 return 0;
1050 } else if (glyph_font(left) != glyph_font(right)) {
1051 return 0;
1052 } else if (tex_has_glyph_option(left, glyph_option_no_right_ligature) || tex_has_glyph_option(right, glyph_option_no_left_ligature)) {
1053 return 0;
1054 } else {
1055 return ligature_is_valid(tex_get_ligature(glyph_font(left), glyph_character(left), glyph_character(right)));
1056 }
1057}
1058
1059
1064
1065static int tex_aux_try_ligature(halfword *first, halfword second, halfword *nextone)
1066{
1067 halfword current = *first;
1068 halfword slot;
1069 halfword type = tex_valid_ligature(current, second, &slot);
1070 if (type >= 0) {
1071 int move_after = (type & 0x0C) >> 2;
1072 int keep_right = (type & 0x01) != 0;
1073 int keep_left = (type & 0x02) != 0;
1074 halfword next = node_next(second);
1075 if (keep_left && keep_right) {
1076 halfword ligature = tex_copy_node(current);
1077 glyph_character(ligature) = slot;
1078 tex_couple_nodes(*first, ligature);
1079 tex_couple_nodes(ligature, second);
1080 if (nextone) {
1081 *nextone = second;
1082 }
1083 } else if (keep_right) {
1084 glyph_character(*first) = slot;
1085 if (nextone) {
1086 *nextone = second;
1087 }
1088 } else if (keep_left) {
1089 glyph_character(second) = slot;
1090 if (nextone) {
1091 *nextone = second;
1092 }
1093 } else {
1094 glyph_character(*first) = slot;
1095 tex_uncouple_node(second);
1096 tex_flush_node(second);
1097 tex_try_couple_nodes(*first, next);
1098 if (nextone) {
1099 *nextone = *first;
1100 }
1101 }
1102
1103 if (nextone) {
1104 while (move_after-- > 0 && *nextone) {
1105 *nextone = node_next(*nextone);
1106 }
1107 }
1108 return 1;
1109 } else {
1110 return 0;
1111 }
1112}
1113
1114static void tex_aux_handle_ligature_list(halfword target, int location)
1115{
1116 halfword node = tex_aux_discretionary_node(target, location);
1117 halfword head = node_head(node);
1118 halfword tail = node_tail(node);
1119 if (head && head != tail) {
1120 halfword current = head;
1121 while (node_next(current)) {
1122 halfword next = node_next(current);
1123 int ishead = current == head;
1124 halfword nextone = next;
1125 if (tex_aux_same_font_properties(current, next) && tex_aux_try_ligature(¤t, next, &nextone)) {
1126 if (ishead) {
1127 head = current;
1128 node_head(node) = current;
1129 }
1130 current = nextone;
1131 } else {
1132 current = next;
1133 }
1134 }
1135 node_tail(node) = current;
1136 }
1137}
1138
1139static void tex_aux_handle_ligature_pair(halfword target, int location)
1140{
1141 halfword node = tex_aux_discretionary_node(target, location);
1142 halfword head = node_head(node);
1143 halfword tail = node_tail(node);
1144 if (head && head != tail) {
1145 halfword previous = node_prev(tail);
1146 int ishead = previous == head;
1147 if (tex_aux_same_font_properties(previous, tail) && tex_aux_try_ligature(&previous, tail, NULL)) {
1148 if (ishead) {
1149 head = previous;
1150 node_head(node) = previous;
1151 }
1152 node_tail(node) = previous;
1153 }
1154 }
1155}
1156
1157
1172
1173static halfword tex_aux_handle_ligature_word(halfword current)
1174{
1175 halfword right = null;
1176 halfword last = null;
1177 if (node_type(current) == boundary_node) {
1178 halfword previous = node_prev(current);
1179 halfword next = node_next(current);
1180
1181 tex_flush_node(current);
1182 if (next) {
1183 tex_couple_nodes(previous, next);
1184 if (node_type(next) != glyph_node) {
1185 return previous;
1186 } else {
1187 current = next;
1188 }
1189 } else {
1190 node_next(previous) = next;
1191 return previous;
1192 }
1193 } else if (node_type(current) == glyph_node && font_has_left_boundary(glyph_font(current))) {
1194 halfword previous = node_prev(current);
1195 halfword glyph = tex_new_glyph_node(glyph_unset_subtype, glyph_font(current), left_boundary_char, current);
1196 tex_couple_nodes(previous, glyph);
1197 tex_couple_nodes(glyph, current);
1198 current = glyph;
1199 }
1200 if (node_type(current) == glyph_node && font_has_right_boundary(glyph_font(current))) {
1201 right = tex_new_glyph_node(glyph_unset_subtype, glyph_font(current), right_boundary_char, current);
1202 }
1203
1204 while (1) {
1205 halfword currenttype = node_type(current);
1206
1207 if (currenttype == glyph_node) {
1208 if (tex_aux_apply_base_ligaturing(current)) {
1209 halfword forward = node_next(current);
1210 if (forward) {
1211 halfword forwardtype = node_type(forward);
1212 if (forwardtype == glyph_node) {
1213 if (! tex_aux_apply_base_ligaturing(forward)) {
1214
1215 } else if (! tex_aux_same_font_properties(current, forward)) {
1216
1217 } else {
1218 halfword nextone = current;
1219 if (tex_aux_try_ligature(¤t, forward, &nextone)) {
1220 current = nextone;
1221 continue;
1222 }
1223 }
1224 } else if (forwardtype == disc_node) {
1225
1226 halfword pre = disc_pre_break_head(forward);
1227 halfword replace = disc_no_break_head(forward);
1228 halfword next;
1229
1230
1231 if (tex_aux_found_ligature(current, pre) || tex_aux_found_ligature(current, replace)) {
1232
1233 halfword previous = node_prev(current);
1234 tex_uncouple_node(current);
1235 tex_couple_nodes(previous, forward);
1236 tex_aux_discretionary_prepend(forward, no_break_code, current);
1237 tex_aux_discretionary_prepend(forward, pre_break_code, tex_copy_node(current));
1238
1239 current = previous;
1240 }
1241
1242 next = node_next(forward);
1243 if (! replace && tex_aux_found_ligature(current, next)) {
1244
1245 halfword previous = node_prev(current);
1246 halfword tail = node_next(next);
1247 tex_uncouple_node(current);
1248 tex_couple_nodes(previous, forward);
1249 tex_aux_discretionary_prepend(forward, pre_break_code, tex_copy_node(current));
1250
1251 tex_uncouple_node(next);
1252 tex_try_couple_nodes(forward, tail);
1253
1254 tex_couple_nodes(current, next);
1255
1256 tex_aux_discretionary_append(forward, post_break_code, tex_copy_node(next));
1257
1258 current = previous;
1259 }
1260
1261 tex_aux_handle_ligature_list(forward, pre_break_code);
1262 } else if (forwardtype == boundary_node) {
1263 halfword next = node_next(forward);
1264 tex_try_couple_nodes(current, next);
1265 tex_flush_node(forward);
1266 if (right) {
1267
1268 tex_flush_node(right);
1269
1270 }
1271 break;
1272 } else if (right) {
1273 tex_couple_nodes(current, right);
1274 tex_couple_nodes(right, forward);
1275 right = null;
1276 continue;
1277 } else {
1278 break;
1279 }
1280 } else {
1281
1282 if (right) {
1283
1284 tex_try_couple_nodes(current, right);
1285 right = null;
1286 continue;
1287 } else {
1288 break;
1289 }
1290 }
1291
1292 }
1293 } else if (currenttype == disc_node) {
1294
1295 if (disc_no_break_head(current) || disc_post_break_head(current)) {
1296
1297 halfword forward;
1298 if (disc_post_break_head(current)) {
1299 tex_aux_handle_ligature_list(current, post_break_code);
1300 }
1301 if (disc_no_break_head(current)) {
1302 tex_aux_handle_ligature_list(current, no_break_code);
1303 }
1304 forward = node_next(current);
1305 while (forward && node_type(forward) == glyph_node && tex_aux_apply_base_ligaturing(forward)) {
1306 halfword replace = disc_no_break_tail(current);
1307 halfword post = disc_post_break_tail(current);
1308 if (tex_aux_found_ligature(replace, forward) || tex_aux_found_ligature(post, forward)) {
1309 tex_try_couple_nodes(current, node_next(forward));
1310 tex_uncouple_node(forward);
1311 tex_aux_discretionary_append(current, no_break_code, tex_copy_node(forward));
1312 tex_aux_handle_ligature_pair(current, no_break_code);
1313 tex_aux_handle_ligature_pair(current, post_break_code);
1314 forward = node_next(current);
1315 } else {
1316 break;
1317 }
1318 }
1319 if (forward && node_type(forward) == disc_node) {
1320
1321 halfword next = node_next(forward);
1322 if (next
1323 && ! disc_no_break_head(forward)
1324 && ! disc_post_break_head(forward)
1325 && node_type(next) == glyph_node
1326 && tex_aux_apply_base_ligaturing(next)
1327 && ((disc_post_break_tail(current) && tex_aux_found_ligature(disc_post_break_tail(current), next)) ||
1328 (disc_no_break_tail (current) && tex_aux_found_ligature(disc_no_break_tail (current), next)))) {
1329 halfword last = node_next(next);
1330 tex_uncouple_node(next);
1331 tex_try_couple_nodes(forward, last);
1332
1333 if (hyphenation_permitted(hyphenation_mode_par, lazy_ligatures_hyphenation_mode)) {
1334
1335 tex_aux_discretionary_append(current, no_break_code, tex_copy_node(next));
1336 tex_aux_handle_ligature_pair(current,no_break_code);
1337 tex_aux_discretionary_append(current, post_break_code, next);
1338 tex_aux_handle_ligature_pair(current,post_break_code);
1339 tex_try_couple_nodes(node_prev(forward), node_next(forward));
1340 tex_flush_node(forward);
1341 } else {
1342
1343 tex_aux_discretionary_append(forward, post_break_code, tex_copy_node(next));
1344 if (disc_no_break_head(current)) {
1345 tex_aux_nesting_prepend_list(forward, no_break_code, disc_no_break_head(current));
1346 tex_aux_discretionary_append(forward, no_break_code, next);
1347 tex_aux_handle_ligature_pair(forward, no_break_code);
1348 tex_aux_nesting_prepend_list(forward, pre_break_code, disc_no_break_head(current));
1349 }
1350 tex_try_couple_nodes(node_prev(current), node_next(current));
1351 tex_flush_node(current);
1352 current = forward;
1353 }
1354 }
1355 }
1356 }
1357 } else {
1358
1359 return last;
1360 }
1361
1362 last = current;
1363 current = node_next(current);
1364 }
1365 return current;
1366}
1367
1368
1369
1370halfword tex_handle_ligaturing(halfword head, halfword tail)
1371{
1372 if (node_next(head)) {
1373
1374 halfword save_tail = null;
1375 halfword current, previous;
1376 if (tail) {
1377 save_tail = node_next(tail);
1378 node_next(tail) = null;
1379 }
1380 previous = head;
1381 current = node_next(previous);
1382 while (current) {
1383 switch(node_type(current)) {
1384 case glyph_node:
1385 if (tex_aux_apply_base_ligaturing(current)) {
1386 current = tex_aux_handle_ligature_word(current);
1387 }
1388 break;
1389 case disc_node:
1390 case boundary_node:
1391 current = tex_aux_handle_ligature_word(current);
1392 break;
1393 }
1394 previous = current;
1395 if (current) {
1396 current = node_next(current);
1397 }
1398 }
1399 if (! previous) {
1400 previous = tex_tail_of_node_list(head);
1401 }
1402 tex_try_couple_nodes(previous, save_tail);
1403 return previous;
1404 } else {
1405 return tail;
1406 }
1407}
1408
1409
1410
1411static halfword tex_aux_add_kern_before(halfword left, halfword right)
1412{
1413 if (tex_aux_same_font_properties(left, right) &&
1414 ! tex_has_glyph_option(left, glyph_option_no_right_kern) &&
1415 ! tex_has_glyph_option(right, glyph_option_no_left_kern) &&
1416 tex_has_kern(glyph_font(left), glyph_character(left))
1417 ) {
1418 scaled k = tex_raw_get_kern(glyph_font(left), glyph_character(left), glyph_character(right));
1419 if (k) {
1420 scaled kern = tex_new_kern_node(k, font_kern_subtype);
1421 halfword previous = node_prev(right);
1422 tex_couple_nodes(previous, kern);
1423 tex_couple_nodes(kern, right);
1424 tex_attach_attribute_list_copy(kern, left);
1425 return kern;
1426 }
1427 }
1428 return null;
1429}
1430
1431static halfword tex_aux_add_kern_after(halfword left, halfword right, halfword after)
1432{
1433 if (tex_aux_same_font_properties(left, right) &&
1434 ! tex_has_glyph_option(left, glyph_option_no_right_kern) &&
1435 ! tex_has_glyph_option(right, glyph_option_no_left_kern) &&
1436 tex_has_kern(glyph_font(left), glyph_character(left))
1437 ) {
1438 scaled k = tex_raw_get_kern(glyph_font(left), glyph_character(left), glyph_character(right));
1439 if (k) {
1440 scaled kern = tex_new_kern_node(k, font_kern_subtype);
1441 halfword next = node_next(after);
1442 tex_couple_nodes(after, kern);
1443 tex_try_couple_nodes(kern, next);
1444 tex_attach_attribute_list_copy(kern, after);
1445 return kern;
1446 }
1447 }
1448 return null;
1449}
1450
1451static halfword tex_aux_do_handle_kerning(halfword root, halfword init_left, halfword init_right);
1452
1453static void tex_aux_handle_discretionary_kerning(halfword target, int location, halfword left, halfword right)
1454{
1455 halfword node = tex_aux_discretionary_node(target, location);
1456 if (node_head(node)) {
1457 halfword kern = tex_aux_do_handle_kerning(node_head(node), left, right);
1458 if (kern) {
1459 node_head(node) = kern;
1460 node_tail(node) = tex_tail_of_node_list(node_head(node));
1461 }
1462 }
1463}
1464
1465static halfword tex_aux_do_handle_kerning(halfword root, halfword init_left, halfword init_right)
1466{
1467
1468 halfword head = root;
1469 halfword current = head;
1470 halfword initial = null;
1471 if (current) {
1472 halfword left = null;
1473 if (node_type(current) == glyph_node && tex_aux_apply_base_kerning(current)) {
1474 if (init_left) {
1475 halfword kern = tex_aux_add_kern_before(init_left, current);
1476 if (current == head) {
1477 initial = kern;
1478 }
1479 }
1480 left = current;
1481 }
1482 current = node_next(current);
1483 while (current) {
1484 halfword currenttype = node_type(current);
1485 if (currenttype == glyph_node) {
1486 if (tex_aux_apply_base_kerning(current)) {
1487 if (left) {
1488 tex_aux_add_kern_before(left, current);
1489 if (glyph_character(left) < 0) {
1490 halfword previous = node_prev(left);
1491 tex_couple_nodes(previous, current);
1492 tex_flush_node(left);
1493 }
1494 }
1495 left = current;
1496 } else {
1497 left = null;
1498 }
1499 } else {
1500 if (currenttype == disc_node) {
1501 halfword next = node_next(current);
1502 halfword right = node_type(next) == glyph_node && tex_aux_apply_base_kerning(next) ? next : null;
1503 tex_aux_handle_discretionary_kerning(current, pre_break_code, left, null);
1504 tex_aux_handle_discretionary_kerning(current, post_break_code, null, right);
1505 tex_aux_handle_discretionary_kerning(current, no_break_code, left, right);
1506 }
1507 if (left) {
1508 if (glyph_character(left) < 0) {
1509 halfword previous = node_prev(left);
1510 tex_couple_nodes(previous, current);
1511 tex_flush_node(left);
1512 }
1513 left = null;
1514 }
1515 }
1516 current = node_next(current);
1517 }
1518 if (left) {
1519 if (init_right) {
1520 tex_aux_add_kern_after(left, init_right, left);
1521 }
1522 if (glyph_character(left) < 0) {
1523 halfword previous = node_prev(left);
1524 halfword next = node_next(left);
1525 if (next) {
1526 tex_couple_nodes(previous, next);
1527 node_tail(root) = next;
1528 } else if (previous != root) {
1529 node_next(previous) = null;
1530 node_tail(root) = previous;
1531 } else {
1532 node_next(root) = null;
1533 node_tail(root) = null;
1534 }
1535 tex_flush_node(left);
1536 }
1537 }
1538 } else if (init_left && init_right ) {
1539 tex_aux_add_kern_after(init_left, init_right, root);
1540 node_tail(root) = node_next(root);
1541 }
1542 return initial;
1543}
1544
1545halfword tex_handle_kerning(halfword head, halfword tail)
1546{
1547 halfword save_link = null;
1548 if (tail) {
1549 save_link = node_next(tail);
1550 node_next(tail) = null;
1551 node_tail(head) = tail;
1552 tex_aux_do_handle_kerning(node_next(head), null, null);
1553 tail = node_tail(head);
1554 if (tex_valid_node(save_link)) {
1555
1556 tex_try_couple_nodes(tail, save_link);
1557 }
1558 } else {
1559 node_tail(head) = null;
1560 tex_aux_do_handle_kerning(node_next(head), null, null);
1561 }
1562 return tail;
1563}
1564
1565
1566
1567static halfword tex_aux_run_lua_ligkern_callback(lua_State *L, halfword head, halfword group, halfword direction, int callback_id)
1568{
1569 int top = 0;
1570 if (lmt_callback_okay(L, callback_id, &top)) {
1571 int i;
1572 lmt_node_list_to_lua(L, head);
1573 lmt_push_group_code(L, group);
1574 lua_pushinteger(L, direction);
1575 i = lmt_callback_call(L, 3, 1, top);
1576 if (i) {
1577 lmt_callback_error(L, top, i);
1578 } else {
1579 head = lmt_node_list_from_lua(L, -1);
1580 lmt_callback_wrapup(L, top);
1581 }
1582 }
1583 return head;
1584}
1585
1586halfword tex_handle_glyphrun(halfword head, halfword group, halfword direction)
1587{
1588 if (head) {
1589 int callback_id = lmt_callback_defined(glyph_run_callback);
1590 if (callback_id) {
1591 return tex_aux_run_lua_ligkern_callback(lmt_lua_state.lua_instance, head, group, direction, callback_id);
1592 } else {
1593 callback_id = lmt_callback_defined(ligaturing_callback);
1594 if (callback_id) {
1595 head = tex_aux_run_lua_ligkern_callback(lmt_lua_state.lua_instance, head, group, direction, callback_id);
1596 } else {
1597
1598 tex_handle_ligaturing(head, null);
1599 }
1600 callback_id = lmt_callback_defined(kerning_callback);
1601 if (callback_id) {
1602 head = tex_aux_run_lua_ligkern_callback(lmt_lua_state.lua_instance, head, group, direction, callback_id);
1603 } else {
1604 halfword kern = tex_aux_do_handle_kerning(head, null, null);
1605 if (kern) {
1606 head = kern;
1607 }
1608 }
1609 }
1610 }
1611 return head;
1612}
1613
1614
1628
1629void tex_set_cur_font(halfword g, halfword f)
1630{
1631 update_tex_font(g, f);
1632}
1633
1634
1638
1639int tex_tex_def_font(int a)
1640{
1641 if (! lmt_fileio_state.job_name) {
1642
1643 tex_open_log_file();
1644 }
1645 tex_get_r_token();
1646 if (tex_define_permitted(cur_cs, a)) {
1647
1648 halfword u = cur_cs;
1649
1650 halfword f;
1651
1652 scaled s = -scaling_factor;
1653 char *fn;
1654
1655 if (is_global(a)) {
1656 update_tex_font_global(u, null_font);
1657 } else {
1658 update_tex_font_local(u, null_font);
1659 }
1660 fn = tex_read_file_name(1, NULL, NULL);
1661
1662 lmt_fileio_state.name_in_progress = 1;
1663 if (tex_scan_keyword("at")) {
1664
1665 s = tex_scan_dimension(0, 0, 0, 0, NULL, NULL);
1666 if ((s <= 0) || (s >= 0x8000000)) {
1667 tex_handle_error(
1668 normal_error_type,
1669 "Improper 'at' size (%p), replaced by 10pt",
1670 s,
1671 "I can only handle fonts at positive sizes that are less than 2048pt, so I've\n"
1672 "changed what you said to 10pt."
1673 );
1674 s = 10 * unity;
1675 }
1676 } else if (tex_scan_keyword("scaled")) {
1677 s = tex_scan_integer(0, NULL, NULL);
1678 if ((s <= 0) || (s > 0x8000)) {
1679 tex_handle_error(
1680 normal_error_type,
1681 "Illegal magnification has been changed to 1000 (%i)",
1682 s,
1683 "The magnification ratio must be between 1 and 32768."
1684 );
1685 s = -scaling_factor;
1686 } else {
1687 s = -s;
1688 }
1689 }
1690 lmt_fileio_state.name_in_progress = 0;
1691 f = tex_read_font_info(fn, s);
1692 eq_value(u) = f;
1693 lmt_memory_free(fn);
1694 return 1;
1695 } else {
1696 return 0;
1697 }
1698}
1699
1700
1711
1712void tex_missing_character(halfword n, halfword f, halfword c, halfword where)
1713{
1714 int callback_id = lmt_callback_defined(missing_character_callback);
1715 if (callback_id > 0) {
1716 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "dNdd->", where, n, f, c);
1717 } else if (tracing_lost_chars_par > 0) {
1718 int old_setting = tracing_online_par;
1719 if (tracing_lost_chars_par > 1) {
1720 tracing_online_par = 1;
1721 }
1722 tex_begin_diagnostic();
1723 tex_print_format("[font: missing character, character %c (%U), font '%s', location %i]", c, c, font_name(f), where);
1724 tex_end_diagnostic();
1725 tracing_online_par = old_setting;
1726 }
1727}
1728
1729
1730
1731scaled tex_char_width_from_font(halfword f, halfword c)
1732{
1733 return tex_aux_char_info(f, c)->width;
1734}
1735
1736scaled tex_char_height_from_font(halfword f, halfword c)
1737{
1738 return tex_aux_char_info(f, c)->height;
1739}
1740
1741scaled tex_char_depth_from_font(halfword f, halfword c)
1742{
1743 return tex_aux_char_info(f, c)->depth;
1744}
1745
1746scaled tex_char_total_from_font(halfword f, halfword c)
1747{
1748 charinfo *ci = tex_aux_char_info(f, c);
1749 return ci->height + ci->depth;
1750}
1751
1752scaled tex_char_italic_from_font(halfword f, halfword c)
1753{
1754 return tex_aux_char_info(f, c)->italic;
1755}
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769scaledwhd tex_char_whd_from_font(halfword f, halfword c)
1770{
1771 charinfo *ci = tex_aux_char_info(f, c);
1772 return (scaledwhd) {
1773 .wd = ci->width,
1774 .ht = ci->height,
1775 .dp = ci->depth,
1776 .ic = ci->italic
1777 };
1778}
1779
1780static charinfo *tex_aux_quality_char_info(halfword f, int c)
1781{
1782 if (f > lmt_font_state.font_data.ptr) {
1783 return NULL;
1784 } else if (proper_char_index(f, c)) {
1785 if (! has_font_text_control(f, text_control_quality_set)) {
1786 int callback_id = lmt_callback_defined(quality_font_callback);
1787 if (callback_id > 0) {
1788 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "d->", f);
1789 set_font_text_control(f, text_control_quality_set);
1790 }
1791 }
1792 return &(lmt_font_state.fonts[f]->chardata[(int) aux_find_charinfo_id(f, c)]);
1793 } else {
1794 return NULL;
1795 }
1796}
1797
1798scaled tex_char_ef_from_font(halfword f, halfword c)
1799{
1800 charinfo *co = tex_aux_quality_char_info(f, c);
1801 return co ? co->expansion : 0;
1802}
1803
1804scaled tex_char_cf_from_font(halfword f, halfword c)
1805{
1806 charinfo *co = tex_aux_quality_char_info(f, c);
1807 return co ? co->compression : 0;
1808}
1809
1810scaled tex_char_lp_from_font(halfword f, halfword c)
1811{
1812 charinfo *co = tex_aux_quality_char_info(f, c);
1813 return co ? co->leftprotrusion : 0;
1814}
1815
1816scaled tex_char_rp_from_font(halfword f, halfword c)
1817{
1818 charinfo *co = tex_aux_quality_char_info(f, c);
1819 return co ? co->rightprotrusion : 0;
1820}
1821
1822halfword tex_char_has_tag_from_font(halfword f, halfword c, halfword tag)
1823{
1824 return (tex_aux_char_info(f, c)->tag & tag) == tag;
1825}
1826
1827void tex_char_reset_tag_from_font(halfword f, halfword c, halfword tag)
1828{
1829 charinfo *ci = tex_aux_char_info(f, c);
1830 ci->tag = ci->tag & ~(tag);
1831}
1832
1833halfword tex_char_tag_from_font(halfword f, halfword c)
1834{
1835 return tex_aux_char_info(f, c)->tag;
1836}
1837
1838int tex_char_checked_tag(halfword tag)
1839{
1840 return tag & (
1841 horizontal_tag | vertical_tag
1842 | extend_last_tag | italic_tag | n_ary_tag | radical_tag | punctuation_tag
1843 | above_baseline_tag | below_baseline_tag | force_extensible_tag
1844 );
1845}
1846
1847halfword tex_char_next_from_font(halfword f, halfword c)
1848{
1849 charinfo *ci = tex_aux_char_info(f, c);
1850 return ci->math ? ci->math->next : -1;
1851}
1852
1853halfword tex_char_extensible_italic_from_font(halfword f, halfword c)
1854{
1855 charinfo *ci = tex_aux_char_info(f, c);
1856 return ci->math ? ci->math->extensible_italic : INT_MIN;
1857}
1858
1859halfword tex_char_unchecked_top_anchor_from_font(halfword f, halfword c)
1860{
1861 charinfo *ci = tex_aux_char_info(f, c);
1862 return ci->math ? ci->math->top_anchor : INT_MIN;
1863}
1864
1865halfword tex_char_top_anchor_from_font(halfword f, halfword c)
1866{
1867 scaled n = tex_char_unchecked_top_anchor_from_font(f, c);
1868 return n == INT_MIN ? 0 : n;
1869}
1870
1871halfword tex_char_unchecked_bottom_anchor_from_font(halfword f, halfword c)
1872{
1873 charinfo *ci = tex_aux_char_info(f, c);
1874 return ci->math ? ci->math->bottom_anchor : INT_MIN;
1875}
1876
1877halfword tex_char_bottom_anchor_from_font(halfword f, halfword c)
1878{
1879 scaled n = tex_char_unchecked_bottom_anchor_from_font(f, c);
1880 return n == INT_MIN ? 0 : n;
1881}
1882
1883halfword tex_char_flat_accent_from_font(halfword f, halfword c)
1884{
1885 charinfo *ci = tex_aux_char_info(f, c);
1886 return ci->math ? ci->math->flat_accent : INT_MIN;
1887}
1888
1889scaled tex_char_top_left_kern_from_font(halfword f, halfword c)
1890{
1891 charinfo *ci = tex_aux_char_info(f, c);
1892 return ci->math ? ci->math->top_left_kern : 0;
1893}
1894
1895scaled tex_char_top_right_kern_from_font(halfword f, halfword c)
1896{
1897 charinfo *ci = tex_aux_char_info(f, c);
1898 return ci->math ? ci->math->top_right_kern : 0;
1899}
1900
1901scaled tex_char_bottom_left_kern_from_font(halfword f, halfword c)
1902{
1903 charinfo *ci = tex_aux_char_info(f, c);
1904 return ci->math ? ci->math->bottom_left_kern : 0;
1905}
1906
1907scaled tex_char_bottom_right_kern_from_font(halfword f, halfword c)
1908{
1909 charinfo *ci = tex_aux_char_info(f, c);
1910 return ci->math ? ci->math->bottom_right_kern : 0;
1911}
1912
1913extinfo *tex_char_extensible_recipe_from_font(halfword f, halfword c)
1914{
1915 charinfo *ci = tex_aux_char_info(f, c);
1916 return ci->math ? ci->math->extensible_recipe : NULL;
1917}
1918
1919extinfo *tex_char_extensible_recipe_front_last(halfword f, halfword c)
1920{
1921 charinfo *ci = tex_aux_char_info(f, c);
1922 while (ci) {
1923 halfword next = ci->math ? ci->math->next : -1;
1924 if (next > 0) {
1925 ci = tex_aux_char_info(f, c);
1926 } else {
1927 return ci->math ? ci->math->extensible_recipe : NULL;
1928 }
1929 }
1930 return NULL;
1931}
1932
1933scaled tex_char_left_margin_from_font(halfword f, halfword c)
1934{
1935 charinfo *ci = tex_aux_char_info(f, c);
1936 return ci->math ? ci->math->left_margin : 0;
1937}
1938
1939scaled tex_char_right_margin_from_font(halfword f, halfword c)
1940{
1941 charinfo *ci = tex_aux_char_info(f, c);
1942 return ci->math ? ci->math->right_margin : 0;
1943}
1944
1945scaled tex_char_top_margin_from_font(halfword f, halfword c)
1946{
1947 charinfo *ci = tex_aux_char_info(f, c);
1948 return ci->math ? ci->math->top_margin : 0;
1949}
1950
1951scaled tex_char_bottom_margin_from_font(halfword f, halfword c)
1952{
1953 charinfo *ci = tex_aux_char_info(f, c);
1954 return ci->math ? ci->math->bottom_margin : 0;
1955}
1956
1957scaled tex_char_top_overshoot_from_font(halfword f, halfword c)
1958{
1959 charinfo *ci = tex_aux_char_info(f, c);
1960 return ci->math ? ci->math->top_overshoot : 0;
1961}
1962
1963scaled tex_char_bottom_overshoot_from_font(halfword f, halfword c)
1964{
1965 charinfo *ci = tex_aux_char_info(f, c);
1966 return ci->math ? ci->math->bottom_overshoot : 0;
1967}
1968
1969scaled tex_char_inner_x_offset_from_font(halfword f, halfword c)
1970{
1971 charinfo *ci = tex_aux_char_info(f, c);
1972 return ci->math ? ci->math->inner_x_offset : 0;
1973}
1974
1975scaled tex_char_inner_y_offset_from_font(halfword f, halfword c)
1976{
1977 charinfo *ci = tex_aux_char_info(f, c);
1978 return ci->math ? ci->math->inner_y_offset : 0;
1979}
1980
1981
1982
1983scaled tex_char_width_from_glyph(halfword g)
1984{
1985 charinfo *ci = tex_aux_char_info(glyph_font(g), glyph_character(g));
1986 return tex_aux_glyph_x_scaled(g, ci->width + 2 * tex_aux_glyph_weight_done(g));
1987}
1988
1989scaled tex_char_height_from_glyph(halfword g)
1990{
1991 charinfo *ci = tex_aux_char_info(glyph_font(g), glyph_character(g));
1992 return tex_aux_glyph_y_scaled(g, ci->height + (has_charinfo_tag(ci,below_baseline_tag) ? 0 : tex_aux_glyph_weight_done(g)));
1993}
1994
1995scaled tex_char_depth_from_glyph(halfword g)
1996{
1997 charinfo *ci = tex_aux_char_info(glyph_font(g), glyph_character(g));
1998 return tex_aux_glyph_y_scaled(g, ci->depth + (has_charinfo_tag(ci,above_baseline_tag) ? 0 : tex_aux_glyph_weight_done(g)));
1999}
2000
2001scaled tex_char_total_from_glyph(halfword g)
2002{
2003 charinfo *ci = tex_aux_char_info(glyph_font(g), glyph_character(g));
2004 scaled ht = ci->height + (has_charinfo_tag(ci,below_baseline_tag) ? 0 : tex_aux_glyph_weight_done(g));
2005 scaled dp = ci->depth + (has_charinfo_tag(ci,above_baseline_tag) ? 0 : tex_aux_glyph_weight_done(g));
2006 return tex_aux_glyph_y_scaled(g, (ht > 0 ? ht : 0) + (dp > 0 ? dp : 0));
2007}
2008
2009scaled tex_char_italic_from_glyph(halfword g)
2010{
2011 charinfo *ci = tex_aux_char_info(glyph_font(g), glyph_character(g));
2012
2013 return tex_aux_glyph_x_scaled(g, ci->italic);
2014}
2015
2016scaledkrn tex_char_corner_kerns_from_glyph(halfword g)
2017{
2018 charinfo *ci = tex_aux_char_info(glyph_font(g), glyph_character(g));
2019 if (ci->math) {
2020 scaled w = tex_aux_glyph_weight_done(g);
2021 return (scaledkrn) {
2022 .bl = ci->math->bottom_left_kern ? tex_aux_glyph_y_scaled(g, ci->math->bottom_left_kern + w) : 0,
2023 .br = ci->math->bottom_right_kern ? tex_aux_glyph_y_scaled(g, ci->math->bottom_right_kern + w) : 0,
2024 .tr = ci->math->top_right_kern ? tex_aux_glyph_y_scaled(g, ci->math->top_right_kern + w) : 0,
2025 .tl = ci->math->top_left_kern ? tex_aux_glyph_y_scaled(g, ci->math->top_left_kern + w) : 0,
2026 };
2027 } else {
2028 return (scaledkrn) { 0, 0, 0, 0 };
2029 }
2030}
2031
2032scaled tex_char_left_protrusion_from_glyph(halfword g)
2033{
2034 charinfo *ci = tex_aux_quality_char_info(glyph_font(g), glyph_character(g));
2035 return ci ? tex_aux_glyph_x_scaled(g, ci->leftprotrusion + tex_aux_glyph_weight_done(g)) : 0;
2036}
2037
2038scaled tex_char_right_protrusion_from_glyph(halfword g)
2039{
2040 charinfo *ci = tex_aux_quality_char_info(glyph_font(g), glyph_character(g));
2041 return ci ? tex_aux_glyph_x_scaled(g, ci->rightprotrusion + tex_aux_glyph_weight_done(g)) : 0;
2042}
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060scaledwhd tex_char_whd_from_glyph(halfword g)
2061{
2062 charinfo *ci = tex_aux_char_info(glyph_font(g), glyph_character(g));
2063 scaled w = tex_aux_glyph_weight_done(g);
2064 return (scaledwhd) {
2065 .wd = tex_aux_glyph_x_scaled(g, ci->width + w * 2),
2066 .ht = tex_aux_glyph_y_scaled(g, ci->height + (has_charinfo_tag(ci,below_baseline_tag) ? 0 : w)),
2067 .dp = tex_aux_glyph_y_scaled(g, ci->depth + (has_charinfo_tag(ci,above_baseline_tag) ? 0 : w)),
2068
2069 .ic = tex_aux_glyph_x_scaled(g, ci->italic),
2070 };
2071}
2072
2073scaled tex_char_width_italic_from_glyph(halfword g)
2074{
2075 charinfo *ci = tex_aux_char_info(glyph_font(g), glyph_character(g));
2076
2077 return tex_aux_glyph_x_scaled(g, ci->width + ci->italic);
2078}
2079
2080
2081
2082scaled tex_calculated_char_width(halfword f, halfword c, halfword ex)
2083{
2084 scaled wd = tex_aux_char_info(f, c)->width;
2085 return ex ? tex_round_xn_over_d(wd, scaling_factor + ex, scaling_factor) : wd;
2086}
2087
2088scaled tex_calculated_glyph_width(halfword g, halfword ex)
2089{
2090 charinfo *ci = tex_aux_char_info(glyph_font(g), glyph_character(g));
2091 scaled wd = tex_aux_glyph_x_scaled(g, ci->width + 2 * tex_aux_glyph_weight_done(g));
2092 return ex ? tex_round_xn_over_d(wd, scaling_factor + ex, scaling_factor) : wd;
2093}
2094
2095
2096
2097int tex_has_ligature(halfword f, halfword c)
2098{
2099 charinfo *ci = tex_aux_char_info(f, c);
2100 return ci ? ci->ligatures != NULL : 0;
2101}
2102
2103int tex_has_kern(halfword f, halfword c)
2104{
2105 charinfo *ci = tex_aux_char_info(f, c);
2106 return ci ? ci->kerns != NULL : 0;
2107}
2108
2109int tex_char_has_math(halfword f, halfword c)
2110{
2111 charinfo *ci = tex_aux_char_info(f, c);
2112 return ci ? ci->math != NULL : 0;
2113}
2114
2115
2116
2117void tex_set_lpcode_in_font(halfword f, halfword c, halfword i)
2118{
2119 charinfo *ci = tex_aux_char_info(f, c);
2120 if (ci) {
2121 ci->leftprotrusion = i;
2122 }
2123}
2124
2125void tex_set_rpcode_in_font(halfword f, halfword c, halfword i)
2126{
2127 charinfo *ci = tex_aux_char_info(f, c);
2128 if (ci) {
2129 ci->rightprotrusion = i;
2130 }
2131}
2132
2133void tex_set_efcode_in_font(halfword f, halfword c, halfword i) {
2134 charinfo *ci = tex_aux_char_info(f, c);
2135 if (ci) {
2136 ci->expansion = i;
2137 }
2138}
2139
2140void tex_set_cfcode_in_font(halfword f, halfword c, halfword i) {
2141 charinfo *ci = tex_aux_char_info(f, c);
2142 if (ci) {
2143 ci->compression = i;
2144 }
2145}
2146
2147void tex_set_font_name(halfword f, const char *s)
2148{
2149 if (font_name(f)) {
2150 lmt_memory_free(font_name(f));
2151 }
2152 set_font_name(f, s ? lmt_memory_strdup(s) : NULL);
2153}
2154
2155void tex_set_font_original(halfword f, const char *s)
2156{
2157 if (font_original(f)) {
2158 lmt_memory_free(font_original(f));
2159 }
2160 set_font_original(f, s ? lmt_memory_strdup(s) : NULL);
2161}
2162
2163scaled tex_get_math_font_scale(halfword f, halfword size)
2164{
2165 scaled scale;
2166 switch (size) {
2167 case 2: scale = (lmt_font_state.fonts[f]->mathscales[2] ? lmt_font_state.fonts[f]->mathscales[2] : scaling_factor) * glyph_scriptscript_scale_par; break;
2168 case 1: scale = (lmt_font_state.fonts[f]->mathscales[1] ? lmt_font_state.fonts[f]->mathscales[1] : scaling_factor) * glyph_script_scale_par; break;
2169 default: scale = (lmt_font_state.fonts[f]->mathscales[0] ? lmt_font_state.fonts[f]->mathscales[0] : scaling_factor) * glyph_text_scale_par; break;
2170 }
2171 scale = scaledround(0.001 * (double) scale);
2172 return scale ? scale : scaling_factor;
2173}
2174
2175scaled tex_get_math_font_x_scale(halfword f, halfword size)
2176{
2177 scaled scale;
2178 switch (size) {
2179 case 2: scale = (lmt_font_state.fonts[f]->mathxscales[2] ? lmt_font_state.fonts[f]->mathxscales[2] : scaling_factor) * glyph_scriptscript_scale_par; break;
2180 case 1: scale = (lmt_font_state.fonts[f]->mathxscales[1] ? lmt_font_state.fonts[f]->mathxscales[1] : scaling_factor) * glyph_script_scale_par; break;
2181 default: scale = (lmt_font_state.fonts[f]->mathxscales[0] ? lmt_font_state.fonts[f]->mathxscales[0] : scaling_factor) * glyph_text_scale_par; break;
2182 }
2183 scale = scaledround(0.001 * (double) scale);
2184 return scale ? scale : scaling_factor;
2185}
2186
2187scaled tex_get_math_font_y_scale(halfword f, halfword size)
2188{
2189 scaled scale;
2190 switch (size) {
2191 case 2: scale = (lmt_font_state.fonts[f]->mathyscales[2] ? lmt_font_state.fonts[f]->mathyscales[2] : scaling_factor) * glyph_scriptscript_scale_par; break;
2192 case 1: scale = (lmt_font_state.fonts[f]->mathyscales[1] ? lmt_font_state.fonts[f]->mathyscales[1] : scaling_factor) * glyph_script_scale_par; break;
2193 default: scale = (lmt_font_state.fonts[f]->mathyscales[0] ? lmt_font_state.fonts[f]->mathyscales[0] : scaling_factor) * glyph_text_scale_par; break;
2194 }
2195 scale = scaledround(0.001 * (double) scale);
2196 return scale ? scale : scaling_factor;
2197}
2198
2199scaled tex_get_math_font_weight(halfword f, halfword size)
2200{
2201 switch (size) {
2202 case 2: return lmt_font_state.fonts[f]->mathweights[2];
2203 case 1: return lmt_font_state.fonts[f]->mathweights[1];
2204 default: return lmt_font_state.fonts[f]->mathweights[0];
2205 }
2206}
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241scaled tex_get_math_font_factor(halfword size)
2242{
2243 switch (size) {
2244 case 2: return glyph_scriptscript_scale_par;
2245 case 1: return glyph_script_scale_par;
2246 default: return glyph_text_scale_par;
2247 }
2248}
2249
2250
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274void tex_run_font_spec(void)
2275{
2276 update_tex_font_identifier(font_spec_identifier(cur_chr));
2277if (font_spec_property_is_set(cur_chr,font_spec_scale_set)) {
2278 if (font_spec_scale(cur_chr) != glyph_scale_par) {
2279 update_tex_glyph_scale(font_spec_scale(cur_chr));
2280 }
2281}
2282if (font_spec_property_is_set(cur_chr,font_spec_x_scale_set)) {
2283 if (font_spec_x_scale(cur_chr) != glyph_x_scale_par) {
2284 update_tex_glyph_x_scale(font_spec_x_scale(cur_chr));
2285 }
2286}
2287if (font_spec_property_is_set(cur_chr,font_spec_y_scale_set)) {
2288 if (font_spec_y_scale(cur_chr) != glyph_y_scale_par) {
2289 update_tex_glyph_y_scale(font_spec_y_scale(cur_chr));
2290 }
2291}
2292if (font_spec_property_is_set(cur_chr,font_spec_slant_set)) {
2293 if (font_spec_y_scale(cur_chr) != glyph_slant_par) {
2294 update_tex_glyph_slant(font_spec_slant(cur_chr));
2295 }
2296}
2297if (font_spec_property_is_set(cur_chr,font_spec_weight_set)) {
2298 if (font_spec_weight(cur_chr) != glyph_weight_par) {
2299 update_tex_glyph_weight(font_spec_weight(cur_chr));
2300 }
2301}
2302}
2303 |