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