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