1
4
5# include "luametatex.h"
6
7
29
30
31void lmt_fontlib_initialize(void) {
32
33}
34
35static int valid_math_parameter(lua_State *L, int narg) {
36 const char *s = lua_tostring(L, narg);
37 if (s) {
38 for (int i = 1; lmt_interface.math_font_parameter_values[i].name; i++) {
39 if (lmt_interface.math_font_parameter_values[i].name == s) {
40 return i;
41 }
42 }
43 }
44 return -1;
45}
46
47
52
53static const char *lmt_ligature_type_strings[] = {
54 "=:", "=:|", "|=:", "|=:|", "", "=:|>", "|=:>", "|=:|>", "", "", "", "|=:|>>", NULL
55};
56
57static int fontlib_aux_count_hash_items(lua_State *L)
58{
59 int n = 0;
60 if (lua_type(L, -1) == LUA_TTABLE) {
61 lua_pushnil(L);
62 while (lua_next(L, -2)) {
63 n++;
64 lua_pop(L, 1);
65 }
66 }
67 return n;
68}
69
70
75
76# if (1)
77
78 # define set_numeric_field_by_index(target,name,dflt) \
79 lua_push_key(name); \
80 target = (lua_rawget(L, -2) == LUA_TNUMBER) ? lmt_roundnumber(L, -1) : dflt ; \
81 lua_pop(L, 1);
82
83# else
84
85 # define set_numeric_field_by_index(target,name,dflt) \
86 lua_push_key(name); \
87 if (lua_rawget(L, -2) == LUA_TNUMBER) { \
88 target = lmt_roundnumber(L, -1); \
89 lua_pop(L, 1); \
90 lua_push_key(name); \
91 lua_push_integer(L, target); \
92 lua_rawset(L, -3); \
93 } else { \
94 target = dflt ; \
95 lua_pop(L, 1); \
96 }
97
98# endif
99
100# define set_boolean_field_by_index(target,name,dflt) \
101 lua_push_key(name); \
102 target = (lua_rawget(L, -2) == LUA_TBOOLEAN) ? lua_toboolean(L, -1) : dflt ; \
103 lua_pop(L, 1);
104
105# define set_string_field_by_index(target,name) \
106 lua_push_key(name); \
107 target = (lua_rawget(L, -2) == LUA_TSTRING) ? lua_tostring(L, -1) : NULL ; \
108 lua_pop(L, 1);
109
110# define set_any_field_by_index(target,name) \
111 lua_push_key(name); \
112 target = (lua_rawget(L, -2) != LUA_TNIL); \
113 lua_pop(L, 1);
114
115
121
122static void fontlib_aux_read_lua_parameters(lua_State *L, int f)
123{
124 lua_push_key(parameters);
125 if (lua_rawget(L, -2) == LUA_TTABLE) {
126
127 int maxindex = 7;
128 lua_pushnil(L);
129 while (lua_next(L, -2)) {
130 if (lua_type(L, -2) == LUA_TNUMBER) {
131 int i = (int) lua_tointeger(L, -2);
132 if (i > maxindex) {
133 maxindex = i;
134 }
135 }
136 lua_pop(L, 1);
137 }
138
142 if (maxindex > 7) {
143 tex_set_font_parameters(f, maxindex);
144 }
145
149 for (int i = 1; i <= maxindex; i++) {
150 if (lua_rawgeti(L, -1, i) == LUA_TNUMBER) {
151 halfword value = lmt_roundnumber(L, -1);
152 tex_set_font_parameter(f, i, value);
153 }
154 lua_pop(L, 1);
155 }
156 lua_pushnil(L);
157 while (lua_next(L, -2)) {
158 halfword value = lua_type(L, -1) == LUA_TNUMBER ? lmt_roundnumber(L, -1) : 0;
159 switch (lua_type(L, -2)) {
160 case LUA_TSTRING:
161 {
162
163 const char *s = lua_tostring(L, -2);
164 if (lua_key_eq(s, slant)) {
165 tex_set_font_parameter(f, slant_code, value);
166 } else if (lua_key_eq(s, space)) {
167 tex_set_font_parameter(f, space_code, value);
168 } else if (lua_key_eq(s, spacestretch)) {
169 tex_set_font_parameter(f, space_stretch_code, value);
170 } else if (lua_key_eq(s, spaceshrink)) {
171 tex_set_font_parameter(f, space_shrink_code, value);
172 } else if (lua_key_eq(s, xheight)) {
173 tex_set_font_parameter(f, ex_height_code, value);
174 } else if (lua_key_eq(s, quad)) {
175 tex_set_font_parameter(f, em_width_code, value);
176 } else if (lua_key_eq(s, extraspace)) {
177 tex_set_font_parameter(f, extra_space_code, value);
178 } else {
179 break;
180 }
181
182
183
184
185
186 }
187 break;
188 case LUA_TNUMBER:
189 {
190
191 int index = (int) lua_tointeger(L, -2);
192 if (index >= 8) {
193 tex_set_font_parameter(f, index, value);
194 }
195 }
196 break;
197 }
198 lua_pop(L, 1);
199 }
200 }
201 lua_pop(L, 1);
202
203}
204
205static void fontlib_aux_read_lua_math_parameters(lua_State *L, int f)
206{
207 lua_push_key(MathConstants);
208 if (lua_rawget(L, -2) == LUA_TTABLE) {
209 lua_pushnil(L);
210 while (lua_next(L, -2)) {
211 int n = (int) lmt_roundnumber(L, -1);
212 int i = 0;
213 switch (lua_type(L, -2)) {
214 case LUA_TSTRING:
215 i = valid_math_parameter(L, -2);
216 break;
217 case LUA_TNUMBER:
218 i = (int) lua_tointeger(L, -2);
219 break;
220 }
221 if (i > 0) {
222
223 tex_set_font_math_parameters(f, i);
224
225
226
227 font_math_parameter(f, i) = n;
228 }
229 lua_pop(L, 1);
230 }
231 }
232 lua_pop(L, 1);
233}
234
235
250
251static void fontlib_aux_store_math_kerns(lua_State *L, int index, charinfo *co, int id)
252{
253 lua_push_key_by_index(index);
254 if (lua_rawget(L, -2) == LUA_TTABLE) {
255 lua_Integer k = lua_rawlen(L, -1);
256 if (k > 0) {
257 for (lua_Integer l = 1; l <= k; l++) {
258 if (lua_rawgeti(L, -1, l) == LUA_TTABLE) {
259 scaled ht, krn;
260 set_numeric_field_by_index(ht, height, 0);
261 set_numeric_field_by_index(krn, kern, 0);
262 if (krn || ht) {
263 tex_add_charinfo_math_kern(co, id, ht, krn);
264 }
265 }
266 lua_pop(L, 1);
267 }
268 }
269 }
270 lua_pop(L, 1);
271}
272
273static void fontlib_aux_font_char_from_lua(lua_State *L, halfword f, int i, int has_math)
274{
275 if (lua_istable(L, -1)) {
276
277 int target;
278 const char *starget;
279 charinfo *co = tex_get_charinfo(f, i);
280 set_numeric_field_by_index(target, tag, 0);
281 set_charinfo_tag(co, target ? tex_char_checked_tag(target) : 0);
282 set_any_field_by_index(target, callback);
283 set_charinfo_tag(co, target ? callback_tag : 0);
284 set_numeric_field_by_index(target, width, 0);
285 set_charinfo_width(co, target);
286 set_numeric_field_by_index(target, height, 0);
287 set_charinfo_height(co, target);
288 set_numeric_field_by_index(target, depth, 0);
289 set_charinfo_depth(co, target);
290 set_numeric_field_by_index(target, italic, 0);
291 set_charinfo_italic(co, target);
292 set_numeric_field_by_index(target, expansion, scaling_factor);
293 set_charinfo_expansion(co, target);
294 set_numeric_field_by_index(target, compression, target);
295 set_charinfo_compression(co, target);
296 set_numeric_field_by_index(target, leftprotrusion, 0);
297 if (target) {
298 set_font_text_control(f, text_control_left_protrusion);
299 set_charinfo_leftprotrusion(co, target);
300 }
301 set_numeric_field_by_index(target, rightprotrusion, 0);
302 if (target) {
303 set_font_text_control(f, text_control_right_protrusion);
304 set_charinfo_rightprotrusion(co, target);
305 }
306 if (has_math) {
307 tex_char_malloc_mathinfo(co);
308 set_numeric_field_by_index(target, smaller, 0);
309 set_charinfo_smaller(co, target);
310 set_numeric_field_by_index(target, mirror, 0);
311 set_charinfo_mirror(co, target);
312 set_numeric_field_by_index(target, flataccent, INT_MIN);
313 set_charinfo_flat_accent(co, target);
314
315 set_numeric_field_by_index(target, topleft, 0);
316 set_charinfo_top_left_kern(co, target);
317 set_numeric_field_by_index(target, topright, 0);
318 set_charinfo_top_right_kern(co, target);
319 set_numeric_field_by_index(target, bottomright, 0);
320 set_charinfo_bottom_right_kern(co, target);
321 set_numeric_field_by_index(target, bottomleft, 0);
322 set_charinfo_bottom_left_kern(co, target);
323
324 set_numeric_field_by_index(target, leftmargin, 0);
325 set_charinfo_left_margin(co, target);
326 set_numeric_field_by_index(target, rightmargin, 0);
327 set_charinfo_right_margin(co, target);
328 set_numeric_field_by_index(target, topmargin, 0);
329 set_charinfo_top_margin(co, target);
330 set_numeric_field_by_index(target, bottommargin, 0);
331 set_charinfo_bottom_margin(co, target);
332
333 set_numeric_field_by_index(target, topovershoot, 0);
334 set_charinfo_top_overshoot(co, target);
335 set_numeric_field_by_index(target, bottomovershoot, 0);
336 set_charinfo_bottom_overshoot(co, target);
337
338 set_numeric_field_by_index(target, topanchor, INT_MIN);
339 set_charinfo_top_anchor(co, target);
340 set_numeric_field_by_index(target, bottomanchor, INT_MIN);
341 set_charinfo_bottom_anchor(co, target);
342
343 set_string_field_by_index(starget, innerlocation);
344 if (lua_key_eq(starget, left)) {
345 set_charinfo_tag(co, inner_left_tag);
346 } else if (lua_key_eq(starget, right)) {
347 set_charinfo_tag(co, inner_right_tag);
348 } else if (lua_key_eq(starget, top)) {
349 set_charinfo_tag(co, inner_top_tag);
350 } else if (lua_key_eq(starget, bottom)) {
351 set_charinfo_tag(co, inner_bottom_tag);
352 }
353 set_numeric_field_by_index(target, innerxoffset, INT_MIN);
354 set_charinfo_inner_x_offset(co, target);
355 set_numeric_field_by_index(target, inneryoffset, INT_MIN);
356 set_charinfo_inner_y_offset(co, target);
357
358 set_numeric_field_by_index(target, next, -1);
359 if (target >= 0) {
360 set_charinfo_tag(co, list_tag);
361 set_charinfo_next(co, target);
362 }
363 set_boolean_field_by_index(target, extensible, 0);
364 if (target) {
365 set_charinfo_tag(co, extend_last_tag);
366 }
367 set_boolean_field_by_index(target, keepbase, 0);
368 if (target) {
369 set_charinfo_tag(co, keep_base_tag);
370 }
371 lua_push_key(parts);
372 if (lua_rawget(L, -2) == LUA_TTABLE) {
373 set_charinfo_tag(co, extensible_tag);
374 tex_set_charinfo_extensible_recipe(co, NULL);
375 for (lua_Integer k = 1; ; k++) {
376 if (lua_rawgeti(L, -1, k) == LUA_TTABLE) {
377 int glyph, startconnect, endconnect, advance, extender;
378 set_numeric_field_by_index(glyph, glyph, 0);
379 set_numeric_field_by_index(extender, extender, 0);
380 set_numeric_field_by_index(startconnect, start, 0);
381 set_numeric_field_by_index(endconnect, end, 0);
382 set_numeric_field_by_index(advance, advance, 0);
383 tex_append_charinfo_extensible_recipe(co, glyph, startconnect, endconnect, advance, extender);
384 lua_pop(L, 1);
385 } else {
386 lua_pop(L, 1);
387 break;
388 }
389 }
390 lua_pop(L, 1);
391 set_numeric_field_by_index(target, partsitalic, 0);
392 set_charinfo_extensible_italic(co, target);
393 set_string_field_by_index(starget, partsorientation);
394 if (lua_key_eq(starget, horizontal)) {
395 set_charinfo_tag(co, horizontal_tag);
396 } else if (lua_key_eq(starget, vertical)) {
397 set_charinfo_tag(co, vertical_tag);
398 }
399 } else {
400 lua_pop(L, 1);
401 }
402 lua_push_key(mathkerns);
403 if (lua_rawget(L, -2) == LUA_TTABLE) {
404 fontlib_aux_store_math_kerns(L, lua_key_index(topleft), co, top_left_kern);
405 fontlib_aux_store_math_kerns(L, lua_key_index(topright), co, top_right_kern);
406 fontlib_aux_store_math_kerns(L, lua_key_index(bottomright), co, bottom_right_kern);
407 fontlib_aux_store_math_kerns(L, lua_key_index(bottomleft), co, bottom_left_kern);
408 }
409 lua_pop(L, 1);
410 }
411
412 lua_push_key(kerns);
413 if (lua_rawget(L, -2) == LUA_TTABLE) {
414 int count = fontlib_aux_count_hash_items(L);
415 if (count > 0) {
416
417 kerninfo *ckerns = lmt_memory_calloc((size_t) count + 1, sizeof(kerninfo));
418 if (ckerns) {
419 int ctr = 0;
420 set_charinfo_tag(co, kerns_tag);
421
422 lua_pushnil(L);
423 while (lua_next(L, -2)) {
424 int k = non_boundary_char;
425 switch (lua_type(L, -2)) {
426 case LUA_TNUMBER:
427
428 k = (int) lua_tointeger(L, -2);
429 if (k < 0) {
430 k = non_boundary_char;
431 }
432 break;
433 case LUA_TSTRING:
434 {
435 const char *s = lua_tostring(L, -2);
436 if (lua_key_eq(s, rightboundary)) {
437 k = right_boundary_char;
438 if (! font_has_right_boundary(f)) {
439 set_font_right_boundary(f, tex_get_charinfo(f, right_boundary_char));
440 }
441 }
442 }
443 break;
444 }
445 target = lmt_roundnumber(L, -1);
446 if (k != non_boundary_char) {
447 set_kern_item(ckerns[ctr], k, target);
448 ctr++;
449 } else {
450 tex_formatted_warning("font", "lua-loaded font %s char U+%X has an invalid kern field", font_name(f), (int) i);
451 }
452 lua_pop(L, 1);
453 }
454
455 if (ctr > 0) {
456 set_kern_item(ckerns[ctr], end_kern, 0);
457 set_charinfo_kerns(co, ckerns);
458 } else {
459 tex_formatted_warning("font", "lua-loaded font %s char U+%X has an invalid kerns field", font_name(f), (int) i);
460 }
461 } else {
462 tex_overflow_error("font", (count + 1) * sizeof(kerninfo));
463 }
464 }
465 }
466 lua_pop(L, 1);
467
468 lua_push_key(ligatures);
469 if (lua_rawget(L, -2) == LUA_TTABLE) {
470 int count = fontlib_aux_count_hash_items(L);
471 if (count > 0) {
472
473 ligatureinfo *cligs = lmt_memory_calloc((size_t) count + 1, sizeof(ligatureinfo));
474 if (cligs) {
475 int ctr = 0;
476 set_charinfo_tag(co, ligatures_tag);
477
478 lua_pushnil(L);
479 while (lua_next(L, -2)) {
480 int k = non_boundary_char;
481 int r = -1;
482 switch (lua_type(L, -2)) {
483 case LUA_TNUMBER:
484
485 k = (int) lua_tointeger(L, -2);
486 if (k < 0) {
487 k = non_boundary_char;
488 }
489 break;
490 case LUA_TSTRING:
491 {
492 const char *s = lua_tostring(L, -2);
493 if (lua_key_eq(s, rightboundary)) {
494 k = right_boundary_char;
495 if (! font_has_right_boundary(f)) {
496 set_font_right_boundary(f, tex_get_charinfo(f, right_boundary_char));
497 }
498 }
499 }
500 break;
501 }
502 if (lua_istable(L, -1)) {
503
504 set_numeric_field_by_index(r, char, -1);
505 }
506 if (r != -1 && k != non_boundary_char) {
507 int ligtarget = 0;
508 lua_push_key(type);
509 switch (lua_rawget(L, -2)) {
510 case LUA_TNUMBER:
511 ligtarget = lmt_tointeger(L, -1);
512 break;
513 case LUA_TSTRING:
514 {
515 const char *value = lua_tostring(L, -1);
516 int index = 0;
517 while (lmt_ligature_type_strings[index]) {
518 if (strcmp(lmt_ligature_type_strings[index], value) == 0) {
519 ligtarget = index;
520 break;
521 } else {
522 index++;
523 }
524 }
525 }
526 break;
527 default:
528 break;
529 }
530 lua_pop(L, 1);
531 set_ligature_item(cligs[ctr], (ligtarget * 2) + 1, k, r);
532 ctr++;
533 } else {
534 tex_formatted_warning("font", "lua-loaded font %s char U+%X has an invalid ligature field", font_name(f), (int) i);
535 }
536
537 lua_pop(L, 1);
538 }
539
540 if (ctr > 0) {
541 set_ligature_item(cligs[ctr], 0, end_of_ligature_code, 0);
542 set_charinfo_ligatures(co, cligs);
543 } else {
544 tex_formatted_warning("font", "lua-loaded font %s char U+%X has an invalid ligatures field", font_name(f), (int) i);
545 }
546 } else {
547 tex_overflow_error("font", (count + 1) * sizeof(ligatureinfo));
548 }
549 }
550 }
551 lua_pop(L, 1);
552 }
553}
554
555
560
561static int lmt_font_from_lua(lua_State *L, int f)
562{
563
564 const char *nstr ;
565 set_string_field_by_index(nstr, name);
566 tex_set_font_name(f, nstr);
567 if (nstr) {
568 const char *ostr = NULL;
569 int no_math = 0;
570 int j;
571 set_string_field_by_index(ostr, original);
572 tex_set_font_original(f, ostr ? ostr : nstr);
573 set_numeric_field_by_index(j, designsize, 655360);
574 set_font_design_size(f, j);
575 set_numeric_field_by_index(j, size, font_design_size(f));
576 set_font_size(f, j);
577 set_boolean_field_by_index(j, compactmath, 0);
578 set_font_compactmath(f, j);
579 set_numeric_field_by_index(j, mathcontrol, 0);
580 set_font_mathcontrol(f, j);
581 set_numeric_field_by_index(j, textcontrol, 0);
582 set_font_textcontrol(f, j);
583 set_numeric_field_by_index(j, textscale, 0);
584 set_font_textsize(f, j);
585 set_numeric_field_by_index(j, scriptscale, 0);
586 set_font_scriptsize(f, j);
587 set_numeric_field_by_index(j, scriptscriptscale, 0);
588 set_font_scriptscriptsize(f, j);
589 set_numeric_field_by_index(j, hyphenchar, default_hyphen_char_par);
590 set_font_hyphen_char(f, j);
591 set_numeric_field_by_index(j, skewchar, default_skew_char_par);
592 set_font_skew_char(f, j);
593 set_boolean_field_by_index(no_math, nomath, 0);
594 fontlib_aux_read_lua_parameters(L, f);
595 if (! no_math) {
596 fontlib_aux_read_lua_math_parameters(L, f);
597 }
598 lmt_font_state.fonts[f]->weight = 65.536 * lmt_font_state.fonts[f]->design_size / lmt_font_state.fonts[f]->size;
599
600 lua_push_key(characters);
601 if (lua_rawget(L, -2) == LUA_TTABLE) {
602
603 int num = 0;
604 int last = 0;
605 int first = -1;
606
607 lua_pushnil(L);
608 while (lua_next(L, -2)) {
609 if (lua_isnumber(L, -2)) {
610 int i = (int) lua_tointeger(L, -2);
611 if (i >= 0 && lua_istable(L, -1)) {
612 num++;
613 if (i > last) {
614 last = i;
615 }
616 if (first < 0) {
617 first = i;
618 }
619 if (first >= 0 && i < first) {
620 first = i;
621 }
622 }
623 }
624 lua_pop(L, 1);
625 }
626 if (num > 0) {
627 int fstep = 0;
628 tex_font_malloc_charinfo(f, num);
629 set_font_first_character(f, first);
630 set_font_last_character(f, last);
631
632 lua_pushnil(L);
633 while (lua_next(L, -2)) {
634 switch (lua_type(L, -2)) {
635 case LUA_TNUMBER:
636 {
637 int i = lmt_tointeger(L, -2);
638 if (i >= 0) {
639 fontlib_aux_font_char_from_lua(L, f, i, ! no_math);
640 }
641 }
642 break;
643 case LUA_TSTRING:
644 {
645 const char *b = lua_tostring(L, -2);
646 if (lua_key_eq(b, leftboundary)) {
647 fontlib_aux_font_char_from_lua(L, f, left_boundary_char, ! no_math);
648 } else if (lua_key_eq(b, rightboundary)) {
649 fontlib_aux_font_char_from_lua(L, f, right_boundary_char, ! no_math);
650 }
651 }
652 break;
653 }
654 lua_pop(L, 1);
655 }
656 lua_pop(L, 1);
657
663 set_numeric_field_by_index(fstep, step, 0);
664 if (fstep > 0) {
665 int fstretch = 0;
666 int fshrink = 0;
667 if (fstep > max_font_adjust_step) {
668 fstep = max_font_adjust_step;
669 }
670 set_numeric_field_by_index(fshrink, shrink, 0);
671 set_numeric_field_by_index(fstretch, stretch, 0);
672 if (fshrink < 0) {
673 fshrink = 0;
674 } else if (fshrink > max_font_adjust_shrink_factor) {
675 fshrink = max_font_adjust_shrink_factor;
676 }
677 fshrink -= (fshrink % fstep);
678 if (fshrink < 0) {
679 fshrink = 0;
680 }
681 if (fstretch < 0) {
682 fstretch = 0;
683 } else if (fstretch > max_font_adjust_stretch_factor) {
684 fstretch = max_font_adjust_stretch_factor;
685 }
686 fstretch -= (fstretch % fstep);
687 if (fstretch < 0) {
688 fstretch = 0;
689 }
690 set_font_step(f, fstep);
691 set_font_max_stretch(f, fstretch);
692 set_font_max_shrink(f, fshrink);
693 set_font_text_control(f, text_control_expansion);
694 }
695 } else {
696 tex_formatted_warning("font", "lua-loaded font '%d' with name '%s' has no characters", f, font_name(f));
697 }
698 } else {
699 tex_formatted_warning("font", "lua-loaded font '%d' with name '%s' has no character table", f, font_name(f));
700 }
701 return 1;
702 } else {
703 return tex_formatted_error("font", "lua-loaded font '%d' has no name!", f);
704 }
705}
706
707static int lmt_characters_from_lua(lua_State *L, int f)
708{
709 int no_math;
710
711 set_boolean_field_by_index(no_math, nomath, 0);
712
713 lua_push_key(characters);
714 if (lua_rawget(L, -2) == LUA_TTABLE) {
715
716 int num = 0;
717 int todo = 0;
718 int first = font_first_character(f);
719 int last = font_last_character(f);
720
721 lua_pushnil(L);
722 while (lua_next(L, -2)) {
723 if (lua_isnumber(L, -2)) {
724 int i = lmt_tointeger(L, -2);
725 if (i >= 0 && lua_istable(L, -1)) {
726 todo++;
727
728 if (! proper_char_index(f, i)) {
729 num++;
730 if (i > last) {
731 last = i;
732 }
733 if (first < 0) {
734 first = i;
735 }
736 if (first >= 0 && i < first) {
737 first = i;
738 }
739 }
740 }
741 }
742 lua_pop(L, 1);
743 }
744 if (todo > 0) {
745 if (num > 0) {
746 tex_font_malloc_charinfo(f, num);
747 set_font_first_character(f, first);
748 set_font_last_character(f, last);
749 }
750
751 lua_pushnil(L);
752 while (lua_next(L, -2)) {
753 if (lua_type(L, -2) == LUA_TNUMBER) {
754 int i = lmt_tointeger(L, -2);
755 if (i >= 0) {
756 if (tex_char_exists(f, i)) {
757 charinfo *co = tex_get_charinfo(f, i);
758 set_charinfo_ligatures(co, NULL);
759 set_charinfo_kerns(co, NULL);
760 set_charinfo_math(co, NULL);
761 tex_set_charinfo_extensible_recipe(co, NULL);
762 }
763 fontlib_aux_font_char_from_lua(L, f, i, ! no_math);
764 }
765 }
766 lua_pop(L, 1);
767 }
768 lua_pop(L, 1);
769 }
770 }
771 return 1;
772}
773
774static int lmt_quality_from_lua(lua_State *L, int f)
775{
776 lua_push_key(characters);
777 if (lua_rawget(L, -2) == LUA_TTABLE) {
778 int first = font_first_character(f);
779 int last = font_last_character(f);
780 lua_pushnil(L);
781 while (lua_next(L, -2)) {
782 if (lua_type(L, -2) == LUA_TNUMBER) {
783 int i = lmt_tointeger(L, -2);
784 if ((i >= first && i <= last) && tex_char_exists(f, i) && lua_istable(L, -1)) {
785 int target;
786 charinfo *co = tex_get_charinfo(f, i);
787 if (! has_charinfo_tag(co, expansion_tag)) {
788 set_numeric_field_by_index(target, expansion, scaling_factor);
789 set_charinfo_expansion(co, target);
790 set_numeric_field_by_index(target, compression, target);
791 set_charinfo_compression(co, target);
792 set_charinfo_tag(co, expansion_tag);
793 }
794 if (! has_charinfo_tag(co, protrusion_tag)) {
795 set_numeric_field_by_index(target, leftprotrusion, 0);
796 if (target) {
797 set_font_text_control(f, text_control_left_protrusion);
798 set_charinfo_leftprotrusion(co, target);
799 }
800 set_numeric_field_by_index(target, rightprotrusion, 0);
801 if (target) {
802 set_font_text_control(f, text_control_right_protrusion);
803 set_charinfo_rightprotrusion(co, target);
804 }
805 set_charinfo_tag(co, protrusion_tag);
806 }
807 }
808 }
809 lua_pop(L, 1);
810 }
811 lua_pop(L, 1);
812 }
813 return 1;
814}
815
816
823
824static int fontlib_current(lua_State *L)
825{
826 int i = lmt_optinteger(L, 1, 0);
827 if (i > 0) {
828 if (tex_is_valid_font(i)) {
829 tex_set_cur_font(0, i);
830 } else {
831 luaL_error(L, "expected a valid font id");
832 }
833 }
834 lua_pushinteger(L, cur_font_par);
835 return 1;
836}
837
838static int fontlib_max(lua_State *L)
839{
840 lua_pushinteger(L, tex_get_font_max_id());
841 return 1;
842}
843
844static int fontlib_setfont(lua_State *L)
845{
846 int i = lmt_checkinteger(L, 1);
847 if (i) {
848 luaL_checktype(L, 2, LUA_TTABLE);
849 if (! tex_is_valid_font(i)) {
850 return luaL_error(L, "font with id %d is not a valid font", i);
851 } else {
852 lua_settop(L, 2);
853 lmt_font_from_lua(L, i);
854 }
855 }
856 return 0;
857}
858
859static int fontlib_addcharacters(lua_State *L)
860{
861 int i = lmt_checkinteger(L, 1);
862 if (i) {
863 luaL_checktype(L, 2, LUA_TTABLE);
864 if (tex_is_valid_font(i)) {
865 lua_settop(L, 2);
866 lmt_characters_from_lua(L, i);
867 } else {
868 return luaL_error(L, "invalid font id %d passed", i);
869 }
870 }
871 return 0;
872}
873
874static int fontlib_addquality(lua_State *L)
875{
876 int i = lmt_checkinteger(L, 1);
877 if (i) {
878 if (tex_is_valid_font(i)) {
879 if (! has_font_text_control(i, text_control_quality_set)) {
880 luaL_checktype(L, 2, LUA_TTABLE);
881 lua_settop(L, 2);
882 lmt_quality_from_lua(L, i);
883 set_font_text_control(i, text_control_quality_set);
884 }
885 } else {
886 return luaL_error(L, "invalid font id %d passed", i);
887 }
888 }
889 return 0;
890}
891
892
893
894static int fontlib_define(lua_State *L)
895{
896 if (lua_type(L, 1) == LUA_TTABLE) {
897 int i = lmt_optinteger(L, 2, 0);
898 if (! i) {
899 i = tex_new_font();
900 } else if (! tex_is_valid_font(i)) {
901 return luaL_error(L, "invalid font id %d passed", i);
902 }
903 lua_settop(L, 1);
904 if (lmt_font_from_lua(L, i)) {
905 lua_pushinteger(L, i);
906 return 1;
907 } else {
908 lua_pop(L, 1);
909 tex_delete_font(i);
910 return luaL_error(L, "font creation failed, error in table");
911 }
912 } else {
913 return 0;
914 }
915}
916
917static int fontlib_id(lua_State *L)
918{
919 if (lua_type(L, 1) == LUA_TSTRING) {
920 size_t l;
921 const char *s = lua_tolstring(L, 1, &l);
922 int cs = tex_string_locate_only(s, l);
923 int f = -1;
924 if (cs == undefined_control_sequence || cs == undefined_cs_cmd || eq_type(cs) != set_font_cmd) {
925 lua_pushliteral(L, "not a valid font csname");
926 } else {
927 f = eq_value(cs);
928 }
929 lua_pushinteger(L, f);
930 return 1;
931 } else {
932 return luaL_error(L, "expected font csname string as argument");
933 }
934}
935
936
943
944static int fontlib_nextid(lua_State *L)
945{
946 int keep = lua_toboolean(L, 1);
947 int id = tex_new_font();
948 lua_pushinteger(L, id);
949 if (! keep) {
950 tex_delete_font(id);
951 }
952 return 1;
953}
954
955
963
964static int fontlib_aux_valid_fontdimen(lua_State *L, halfword *fnt, halfword *n)
965{
966 *fnt = lmt_tohalfword(L, 1);
967 *n = lmt_tohalfword(L, 2);
968 if (*n > 0 && *n <= font_parameter_count(*fnt)) {
969 return 1;
970 } else {
971 return luaL_error(L, "font with id %i has only %d fontdimens", fnt, n);
972 }
973}
974
975static int fontlib_setfontdimen(lua_State *L)
976{
977 halfword fnt, n;
978 if (fontlib_aux_valid_fontdimen(L, &fnt, &n)) {
979 tex_set_font_parameter(fnt, n, lmt_tohalfword(L, 3));
980 }
981 return 0;
982}
983
984static int fontlib_getfontdimen(lua_State *L)
985{
986 halfword fnt, n;
987 if (fontlib_aux_valid_fontdimen(L, &fnt, &n)) {
988 lua_pushinteger(L, font_parameter(fnt, n));
989 } else {
990 lua_pushnil(L);
991 }
992 return 1;
993}
994
995static int fontlib_getmathspec(lua_State *L)
996{
997 if (lua_type(L, 1) == LUA_TSTRING) {
998 size_t lname = 0;
999 const char *name = lua_tolstring(L, 1, &lname);
1000 halfword cs = tex_string_locate_only(name, lname);
1001 if (eq_type(cs) == mathspec_cmd) {
1002 halfword ms = eq_value(cs);
1003 if (ms) {
1004 mathcodeval m = tex_get_math_spec(ms);
1005 lua_pushinteger(L, m.class_value);
1006 lua_pushinteger(L, m.family_value);
1007 lua_pushinteger(L, m.character_value);
1008 return 3;
1009 }
1010 }
1011 }
1012 return 0;
1013}
1014
1015static int fontlib_getfontspec(lua_State *L)
1016{
1017 if (lua_type(L, 1) == LUA_TSTRING) {
1018 size_t lname = 0;
1019 const char *name = lua_tolstring(L, 1, &lname);
1020 halfword cs = tex_string_locate_only(name, lname);
1021 if (eq_type(cs) == fontspec_cmd) {
1022 halfword fs = eq_value(cs);
1023 if (fs) {
1024 lua_pushinteger(L, font_spec_identifier(fs));
1025 lua_pushinteger(L, font_spec_scale(fs));
1026 lua_pushinteger(L, font_spec_x_scale(fs));
1027 lua_pushinteger(L, font_spec_y_scale(fs));
1028 lua_pushinteger(L, font_spec_slant(fs));
1029 lua_pushinteger(L, font_spec_weight(fs));
1030 return 6;
1031 }
1032 }
1033 }
1034 return 0;
1035}
1036
1037static int fontlib_getmathindex(lua_State *L) {
1038 halfword index = -1;
1039 switch (lua_type(L, 1)) {
1040 case LUA_TSTRING:
1041 index = valid_math_parameter(L, 1);
1042 break;
1043 case LUA_TNUMBER:
1044 index = lmt_tointeger(L, 1);
1045 break;
1046 }
1047 if (index > 0 && index < math_parameter_last_code) {
1048 lua_pushinteger(L, index);
1049 lua_pushboolean(L, index >= math_parameter_first_engine_code);
1050 } else {
1051 lua_pushinteger(L, 0);
1052 lua_pushboolean(L, 0);
1053 }
1054 return 2;
1055}
1056
1057static int fontlib_xscaled(lua_State *L)
1058{
1059 lua_pushinteger(L, tex_font_x_scaled(lmt_optroundnumber(L, 1, 1)));
1060 return 1;
1061}
1062
1063static int fontlib_yscaled(lua_State *L)
1064{
1065 lua_pushinteger(L, tex_font_y_scaled(lmt_optroundnumber(L, 1, 1)));
1066 return 1;
1067}
1068
1069static const struct luaL_Reg fontlib_function_list[] = {
1070 { "current", fontlib_current },
1071 { "max", fontlib_max },
1072 { "setfont", fontlib_setfont },
1073 { "addcharacters", fontlib_addcharacters },
1074 { "addquality", fontlib_addquality },
1075 { "define", fontlib_define },
1076 { "nextid", fontlib_nextid },
1077 { "id", fontlib_id },
1078 { "getfontdimen", fontlib_getfontdimen },
1079 { "setfontdimen", fontlib_setfontdimen },
1080 { "getfontspec", fontlib_getfontspec },
1081 { "getmathspec", fontlib_getmathspec },
1082 { "getmathindex", fontlib_getmathindex },
1083 { "xscaled", fontlib_xscaled },
1084 { "yscaled", fontlib_yscaled },
1085 { NULL, NULL },
1086};
1087
1088int luaopen_font(lua_State *L)
1089{
1090 lua_newtable(L);
1091 luaL_setfuncs(L, fontlib_function_list, 0);
1092 return 1;
1093}
1094 |