3 % Copyright
2006-2011 Taco Hoekwater
<taco@@luatex.org
>
5 % This file is part of LuaTeX.
7 % LuaTeX is free software
; you can redistribute it and
/or modify it under
8 % the terms of the GNU General Public License as published by the Free
9 % Software Foundation
; either version
2 of the License
, or
(at your
10 % option
) any later version.
12 % LuaTeX is distributed in the hope that it will be useful
, but WITHOUT
13 % ANY WARRANTY
; without even the implied warranty of MERCHANTABILITY or
14 % FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 % License for more details.
17 % You should have received a copy of the GNU General Public License along
18 % with LuaTeX
; if not
, see
<http
://www.gnu.org
/licenses
/>.
22 #include
"lua/luatex-api.h"
28 const char
*font_type_strings
[] = {
29 "unknown", "virtual", "real", NULL
32 const char
*font_format_strings
[] = {
33 "unknown", "type1", "type3", "truetype", "opentype", NULL
36 const char
*font_embedding_strings
[] = {
37 "unknown", "no", "subset", "full", NULL
40 const char
*ligature_type_strings
[] = {
41 "=:", "=:|", "|=:", "|=:|", "", "=:|>", "|=:>", "|=:|>", "", "", "", "|=:|>>", NULL
44 const char
*MATH_param_names
[] = {
46 "ScriptPercentScaleDown",
47 "ScriptScriptPercentScaleDown",
48 "DelimitedSubFormulaMinHeight",
49 "DisplayOperatorMinHeight",
53 "FlattenedAccentBaseHeight",
56 "SubscriptBaselineDropMin",
58 "SuperscriptShiftUpCramped",
59 "SuperscriptBottomMin",
60 "SuperscriptBaselineDropMax",
61 "SubSuperscriptGapMin",
62 "SuperscriptBottomMaxWithSubscript",
65 "UpperLimitBaselineRiseMin",
67 "LowerLimitBaselineDropMin",
69 "StackTopDisplayStyleShiftUp",
70 "StackBottomShiftDown",
71 "StackBottomDisplayStyleShiftDown",
73 "StackDisplayStyleGapMin",
74 "StretchStackTopShiftUp",
75 "StretchStackBottomShiftDown",
76 "StretchStackGapAboveMin",
77 "StretchStackGapBelowMin",
78 "FractionNumeratorShiftUp",
79 "FractionNumeratorDisplayStyleShiftUp",
80 "FractionDenominatorShiftDown",
81 "FractionDenominatorDisplayStyleShiftDown",
82 "FractionNumeratorGapMin",
83 "FractionNumeratorDisplayStyleGapMin",
84 "FractionRuleThickness",
85 "FractionDenominatorGapMin",
86 "FractionDenominatorDisplayStyleGapMin",
87 "SkewedFractionHorizontalGap",
88 "SkewedFractionVerticalGap",
90 "OverbarRuleThickness",
91 "OverbarExtraAscender",
92 "UnderbarVerticalGap",
93 "UnderbarRuleThickness",
94 "UnderbarExtraDescender",
96 "RadicalDisplayStyleVerticalGap",
97 "RadicalRuleThickness",
98 "RadicalExtraAscender",
99 "RadicalKernBeforeDegree",
100 "RadicalKernAfterDegree",
101 "RadicalDegreeBottomRaisePercent",
102 "MinConnectorOverlap",
103 "SubscriptShiftDownWithSuperscript",
104 "FractionDelimiterSize",
105 "FractionDelimiterDisplayStyleSize",
109 /* here for now
, may be useful elsewhere
*/
111 int ff_checkoption
(lua_State
*L
, int narg
, const char
*def
, const char
*const lst
[]);
113 int ff_checkoption
(lua_State
*L
, int narg
, const char
*def
, const char
*const lst
[]) {
114 const char
*name
= (def
) ? luaL_optstring
(L
, narg
, def
) : luaL_checkstring
(L
, narg
);
116 for
(i
=0; lst
[i
]; i
++)
117 if
(strcmp
(lst
[i
], name
) == 0)
122 #define dump_intfield
(L
,n
,c
) \
123 lua_push_string_by_name
(L
,n
); \
124 lua_pushinteger
(L
, c
); \
127 #define dump_stringfield
(L
,n
,c
) \
128 lua_push_string_by_name
(L
,n
); \
129 lua_pushstring
(L
, c
); \
132 #define dump_booleanfield
(L
,n
,c
) \
133 lua_push_string_by_name
(L
,n
); \
134 lua_pushboolean
(L
, c
); \
137 static void dump_math_kerns
(lua_State
* L
, charinfo
* co
, int l
, int id
)
140 for
(i
= 0; i
< l
; i
++) {
142 if
(id
==top_left_kern
) {
143 dump_intfield
(L
, height
, co-
>top_left_math_kern_array
[(2*i
)]);
144 dump_intfield
(L
, kern
, co-
>top_left_math_kern_array
[(2*i
)+1]);
145 } else if
(id
==top_right_kern
) {
146 dump_intfield
(L
, height
, co-
>top_right_math_kern_array
[(2*i
)]);
147 dump_intfield
(L
, kern
, co-
>top_right_math_kern_array
[(2*i
)+1]);
148 } else if
(id
==bottom_right_kern
) {
149 dump_intfield
(L
, height
, co-
>bottom_right_math_kern_array
[(2*i
)]);
150 dump_intfield
(L
, kern
, co-
>bottom_right_math_kern_array
[(2*i
)+1]);
151 } else if
(id
==bottom_left_kern
) {
152 dump_intfield
(L
, height
, co-
>bottom_left_math_kern_array
[(2*i
)]);
153 dump_intfield
(L
, kern
, co-
>bottom_left_math_kern_array
[(2*i
)+1]);
155 lua_rawseti
(L
, -2, (i
+ 1));
159 static void font_char_to_lua
(lua_State
* L
, internal_font_number f
, charinfo
* co
)
164 lua_createtable
(L
, 0, 10);
166 dump_intfield
(L
,width
,get_charinfo_width
(co
));
167 dump_intfield
(L
,height
,get_charinfo_height
(co
));
168 dump_intfield
(L
,depth
,get_charinfo_depth
(co
));
170 if
(get_charinfo_italic
(co
) != 0) {
171 dump_intfield
(L
,italic
,get_charinfo_italic
(co
));
173 if
(get_charinfo_vert_italic
(co
) != 0) {
174 dump_intfield
(L
,vert_italic
,get_charinfo_vert_italic
(co
));
176 if
(get_charinfo_top_accent
(co
) !=0 && get_charinfo_top_accent(co) != INT_MIN) {
177 dump_intfield
(L
,top_accent
,get_charinfo_top_accent
(co
));
179 if
(get_charinfo_bot_accent
(co
) != 0 && get_charinfo_bot_accent(co) != INT_MIN) {
180 dump_intfield
(L
,bot_accent
,get_charinfo_bot_accent
(co
));
182 if
(get_charinfo_ef
(co
) != 1000) {
183 dump_intfield
(L
,expansion_factor
,get_charinfo_ef
(co
));
185 if
(get_charinfo_lp
(co
) != 0) {
186 dump_intfield
(L
,left_protruding
,get_charinfo_lp
(co
));
188 if
(get_charinfo_rp
(co
) != 0) {
189 dump_intfield
(L
,right_protruding
,get_charinfo_rp
(co
));
191 if
(font_encodingbytes
(f
) == 2) {
192 dump_intfield
(L
,index
,get_charinfo_index
(co
));
194 if
(get_charinfo_name
(co
) != NULL) {
195 dump_stringfield
(L
,name
,get_charinfo_name
(co
));
197 if
(get_charinfo_tounicode
(co
) != NULL) {
198 dump_stringfield
(L
,tounicode
,get_charinfo_tounicode
(co
));
200 if
(get_charinfo_tag
(co
) == list_tag
) {
201 dump_intfield
(L
,next
,get_charinfo_remainder
(co
));
203 if
(get_charinfo_used
(co
)) {
204 dump_booleanfield
(L
,used
,(get_charinfo_used
(co
) ? true
: false
));
206 if
(get_charinfo_tag
(co
) == ext_tag
) {
208 h
= get_charinfo_hor_variants
(co
);
211 lua_push_string_by_name
(L
,horiz_variants
);
214 lua_createtable
(L
, 0, 5);
215 dump_intfield
(L
, glyph
, h-
>glyph
);
216 dump_intfield
(L
, extender
, h-
>extender
);
217 dump_intfield
(L
, start
, h-
>start_overlap
);
218 dump_intfield
(L
, end
, h-
>end_overlap
);
219 dump_intfield
(L
, advance
, h-
>advance
);
220 lua_rawseti
(L
, -2, i
);
226 h
= get_charinfo_vert_variants
(co
);
229 lua_push_string_by_name
(L
,vert_variants
);
232 lua_createtable
(L
, 0, 5);
233 dump_intfield
(L
, glyph
, h-
>glyph
);
234 dump_intfield
(L
, extender
, h-
>extender
);
235 dump_intfield
(L
, start
, h-
>start_overlap
);
236 dump_intfield
(L
, end
, h-
>end_overlap
);
237 dump_intfield
(L
, advance
, h-
>advance
);
238 lua_rawseti
(L
, -2, i
);
245 ki
= get_charinfo_kerns
(co
);
248 lua_push_string_by_name
(L
,kerns
);
249 lua_createtable
(L
, 10, 1);
250 for
(i
= 0; !kern_end
(ki
[i
]); i
++) {
251 if
(kern_disabled
(ki
[i
])) {
252 /* skip like in lookup
*/
254 lua_rawgeti
(L
, -1, kern_char
(ki
[i
]));
255 if
(lua_type
(L
,-1) == LUA_TNIL
) {
257 if
(kern_char
(ki
[i
]) == right_boundarychar
) {
258 lua_push_string_by_name
(L
,right_boundary
);
260 lua_pushinteger
(L
, kern_char
(ki
[i
]));
262 lua_pushinteger
(L
, kern_kern
(ki
[i
]));
272 l
= get_charinfo_ligatures
(co
);
275 lua_push_string_by_name
(L
,ligatures
);
276 lua_createtable
(L
, 10, 1);
277 for
(i
= 0; !lig_end
(l
[i
]); i
++) {
278 if
(lig_char
(l
[i
]) == right_boundarychar
) {
279 lua_push_string_by_name
(L
,right_boundary
);
281 lua_pushinteger
(L
, lig_char
(l
[i
]));
283 lua_createtable
(L
, 0, 2);
284 lua_push_string_by_name
(L
,type
);
285 lua_pushinteger
(L
, lig_type
(l
[i
]));
287 lua_push_string_by_name
(L
,char
);
288 lua_pushinteger
(L
, lig_replacement
(l
[i
]));
295 lua_push_string_by_name
(L
,mathkern
);
299 i
= get_charinfo_math_kerns
(co
, top_right_kern
);
303 lua_push_string_by_name
(L
,top_right
);
305 dump_math_kerns
(L
, co
, i
, top_right_kern
);
308 i
= get_charinfo_math_kerns
(co
, top_left_kern
);
311 lua_push_string_by_name
(L
,top_left
);
313 dump_math_kerns
(L
, co
, i
, top_left_kern
);
316 i
= get_charinfo_math_kerns
(co
, bottom_right_kern
);
319 lua_push_string_by_name
(L
,bottom_right
);
321 dump_math_kerns
(L
, co
, i
, bottom_right_kern
);
324 i
= get_charinfo_math_kerns
(co
, bottom_left_kern
);
327 lua_push_string_by_name
(L
,bottom_left
);
329 dump_math_kerns
(L
, co
, i
, bottom_left_kern
);
339 static void write_lua_parameters
(lua_State
* L
, int f
)
342 lua_push_string_by_name
(L
,parameters
);
344 for
(k
= 1; k
<= font_params
(f
); k
++) {
347 dump_intfield
(L
,slant
,font_param
(f
, k
));
350 dump_intfield
(L
,space
,font_param
(f
, k
));
352 case space_stretch_code
:
353 dump_intfield
(L
,space_stretch
,font_param
(f
, k
));
355 case space_shrink_code
:
356 dump_intfield
(L
,space_shrink
,font_param
(f
, k
));
359 dump_intfield
(L
,x_height
,font_param
(f
, k
));
362 dump_intfield
(L
,quad
,font_param
(f
, k
));
364 case extra_space_code
:
365 dump_intfield
(L
,extra_space
,font_param
(f
, k
));
368 lua_pushinteger
(L
, font_param
(f
, k
));
369 lua_rawseti
(L
, -2, k
);
376 static void write_lua_math_parameters
(lua_State
* L
, int f
)
379 lua_push_string_by_name
(L
,MathConstants
);
381 for
(k
= 1; k
<= font_math_params
(f
); k
++) {
382 lua_pushinteger
(L
, font_math_param
(f
, k
));
383 if
(k
<= MATH_param_max
) {
384 lua_setfield
(L
, -2, MATH_param_names
[k
]);
386 lua_rawseti
(L
, -2, k
);
392 int font_to_lua
(lua_State
* L
, int f
)
396 if
(font_cache_id
(f
) > 0) {
397 /* fetch the table from the registry if it was
398 saved there by |font_from_lua
()|
*/
399 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, font_cache_id
(f
));
400 /* fontdimens can be changed from tex code
*/
401 write_lua_parameters
(L
, f
);
406 lua_push_string_by_name
(L
,name
);
407 lua_pushstring
(L
, font_name
(f
));
409 if
(font_area
(f
) != NULL) {
410 dump_stringfield
(L
,area
,font_area
(f
));
412 if
(font_filename
(f
) != NULL) {
413 dump_stringfield
(L
,filename
,font_filename
(f
));
415 if
(font_fullname
(f
) != NULL) {
416 dump_stringfield
(L
,fullname
,font_fullname
(f
));
418 if
(font_psname
(f
) != NULL) {
419 dump_stringfield
(L
,psname
,font_psname
(f
));
421 if
(font_encodingname
(f
) != NULL) {
422 dump_stringfield
(L
,encodingname
,font_encodingname
(f
));
425 dump_booleanfield
(L
,used
,(font_used
(f
) ? true
: false
));
426 dump_stringfield
(L
,type
,font_type_strings
[font_type
(f
)]);
427 dump_stringfield
(L
,format
,font_format_strings
[font_format
(f
)]);
428 dump_stringfield
(L
,embedding
,font_embedding_strings
[font_embedding
(f
)]);
430 dump_intfield
(L
,units_per_em
,font_units_per_em
(f
));
431 dump_intfield
(L
,size
,font_size
(f
));
432 dump_intfield
(L
,designsize
,font_dsize
(f
));
433 dump_intfield
(L
,checksum
,font_checksum
(f
));
434 dump_intfield
(L
,slant
,font_slant
(f
));
435 dump_intfield
(L
,extend
,font_extend
(f
));
436 dump_intfield
(L
,direction
,font_natural_dir
(f
));
437 dump_intfield
(L
,encodingbytes
,font_encodingbytes
(f
));
438 dump_booleanfield
(L
,oldmath
,font_oldmath
(f
));
439 dump_intfield
(L
,tounicode
,font_tounicode
(f
));
441 /* the next one is read only
*/
442 if
(font_max_shrink
(f
) != 0) {
443 dump_intfield
(L
,shrink
,font_max_shrink
(f
));
445 if
(font_max_stretch
(f
) != 0) {
446 dump_intfield
(L
,stretch
,font_max_stretch
(f
));
448 if
(font_step
(f
) != 0) {
449 dump_intfield
(L
,step
,font_step
(f
));
451 if
(font_auto_expand
(f
) != 0) {
452 dump_booleanfield
(L
,auto_expand
,font_auto_expand
(f
));
454 if
(pdf_font_attr
(f
) != 0) {
455 char
*s
= makecstring
(pdf_font_attr
(f
));
456 dump_stringfield
(L
,attributes
,s
);
461 write_lua_parameters
(L
, f
);
462 write_lua_math_parameters
(L
, f
);
465 lua_push_string_by_name
(L
,characters
);
466 lua_createtable
(L
, font_tables
[f
]->charinfo_size
, 0); /* all characters
*/
467 if
(has_left_boundary
(f
)) {
468 co
= get_charinfo
(f
, left_boundarychar
);
469 lua_push_string_by_name
(L
,left_boundary
);
470 font_char_to_lua
(L
, f
, co
);
473 if
(has_right_boundary
(f
)) {
474 co
= get_charinfo
(f
, right_boundarychar
);
475 lua_push_string_by_name
(L
,right_boundary
);
476 font_char_to_lua
(L
, f
, co
);
479 for
(k
= font_bc
(f
); k
<= font_ec
(f
); k
++) {
480 if
(quick_char_exists
(f
, k
)) {
481 lua_pushinteger
(L
, k
);
482 co
= get_charinfo
(f
, k
);
483 font_char_to_lua
(L
, f
, co
);
489 if
(font_cache_id
(f
) == 0) { /* renew
*/
491 lua_pushvalue
(L
, -1);
492 r
= luaL_ref
(L
, LUA_REGISTRYINDEX
); /* pops the table
*/
493 set_font_cache_id
(f
, r
);
498 #define count_hash_items
(L
,name_index
,n
) \
500 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, name_index
); \
502 if
(lua_type
(L
, -1) == LUA_TTABLE
) { \
504 while
(lua_next
(L
, -2) != 0) { \
510 /* keep table on stack
*/ \
516 #define streq
(a
,b
) (strcmp
(a
,b
)==0)
518 #define append_packet
(k
) { *(cp
++) = (eight_bits
) (k
); }
520 #define do_store_four
(l
) { \
521 append_packet
((l
& 0xFF000000) >> 24); \
522 append_packet
((l
& 0x00FF0000) >> 16); \
523 append_packet
((l
& 0x0000FF00) >> 8); \
524 append_packet
((l
& 0x000000FF)); \
528 static void append_float
(eight_bits
** cpp
, float a
)
531 eight_bits
*cp
= *cpp
;
534 eight_bits b
[sizeof
(float
)];
537 for
(i
= 0; i
< sizeof
(float
); i
++)
538 append_packet
(u.b
[i
]);
542 static int n_enum_field
(lua_State
* L
, int name_index
, int dflt
, const char
**values
)
547 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, name_index
); /* fetch the stringptr
*/
550 if
(t
== LUA_TNUMBER
) {
551 i
= (int
) lua_tointeger
(L
, -1);
552 } else if
(t
== LUA_TSTRING
) {
553 s
= lua_tostring
(L
, -1);
555 while
(values
[k
] != NULL) {
556 if
(strcmp
(values
[k
], s
) == 0) {
567 static int n_boolean_field
(lua_State
* L
, int name_index
, int dflt
)
570 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, name_index
); /* fetch the stringptr
*/
572 if
(lua_isboolean
(L
, -1)) {
573 i
= lua_toboolean
(L
, -1);
579 static char
*n_string_field_copy
(lua_State
* L
, int name_index
, const char
*dflt
)
582 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, name_index
); /* fetch the stringptr
*/
584 if
(lua_type
(L
,-1) == LUA_TSTRING
) {
585 i
= xstrdup
(lua_tostring
(L
, -1));
586 } else if
(dflt
== NULL) {
595 static const char
*n_string_field
(lua_State
* L
, int name_index
)
597 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, name_index
); /* fetch the stringptr
*/
599 return lua_tostring
(L
,-1);
602 static int n_some_field
(lua_State
* L
, int name_index
)
604 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, name_index
); /* fetch the stringptr
*/
606 return lua_type
(L
,-1);
609 /*static void init_font_string_pointers
(lua_State
* L
){}*/
611 static int count_char_packet_bytes
(lua_State
* L
)
616 for
(i
= 1; i
<= (int
) lua_rawlen
(L
, -1); i
++) {
617 lua_rawgeti
(L
, -1, i
);
618 if
(lua_istable
(L
, -1)) {
619 lua_rawgeti
(L
, -1, 1);
620 if
(lua_type
(L
,-1) == LUA_TSTRING
) {
621 const char
*s
= lua_tostring
(L
, -1);
622 if
(lua_key_eq
(s
, font
)) {
625 } else if
(lua_key_eq
(s
, char
)) {
631 } else if
(lua_key_eq
(s
, slot
)) {
634 } else if
(lua_key_eq
(s
, comment
) || lua_key_eq
(s
, nop
)) {
636 } else if
(lua_key_eq
(s
, push
) || lua_key_eq
(s
, pop
)) {
638 } else if
(lua_key_eq
(s
, rule
)) {
640 } else if
(lua_key_eq
(s
, right
) || lua_key_eq
(s
, node
)
641 || lua_key_eq
(s
, down
) || lua_key_eq
(s
, image
)) {
643 } else if
(lua_key_eq
(s
, scale
)) {
644 l
+= sizeof
(float
) + 1;
645 } else if
(lua_key_eq
(s
, special
) || lua_key_eq
(s
, lua
)) {
647 lua_rawgeti
(L
, -2, 2);
648 if
(lua_type
(L
,-1) == LUA_TSTRING
) {
649 (void
) lua_tolstring
(L
, -1, &len);
652 l
= (int
) (l
+ 5 + (int
) len
);
656 normal_error
("vf command","invalid packet special");
657 /* fprintf
(stdout
, "invalid packet special!\n"); */
660 normal_error
("vf command","unknown packet command");
661 /* fprintf
(stdout
, "unknown packet command %s!\n", s
); */
664 normal_error
("vf command","no packet command");
665 /* fprintf
(stdout
, "no packet command!\n"); */
667 lua_pop
(L
, 1); /* command name
*/
669 lua_pop
(L
, 1); /* item
*/
674 static scaled sp_to_dvi
(halfword sp
, halfword atsize
)
677 mult
= (double
) (atsize
/ 65536.0);
678 result
= (double
) (sp
* 16.0);
679 return floor
(result
/ mult
);
683 static void read_char_packets
(lua_State
* L
, int
*l_fonts
, charinfo
* co
, internal_font_number f
, int atsize
)
689 eight_bits
*cpackets
, *cp
;
692 int pc
= count_char_packet_bytes
(L
);
695 while
(l_fonts
[(max_f
+ 1)] != 0)
697 cp
= cpackets
= xmalloc
((unsigned
) (pc
+ 1));
698 for
(i
= 1; i
<= (int
) lua_rawlen
(L
, -1); i
++) {
699 lua_rawgeti
(L
, -1, i
);
700 if
(lua_istable
(L
, -1)) {
701 /* fetch the command code
*/
702 lua_rawgeti
(L
, -1, 1);
703 if
(lua_type
(L
,-1) == LUA_TSTRING
) {
704 s
= lua_tostring
(L
, -1);
706 if
(lua_key_eq
(s
, font
)) {
707 cmd
= packet_font_code
;
708 } else if
(lua_key_eq
(s
, char
)) {
709 cmd
= packet_char_code
;
711 append_packet
(packet_font_code
);
715 } else if
(lua_key_eq
(s
, slot
)) {
716 cmd
= packet_nop_code
;
717 lua_rawgeti
(L
, -2, 2);
718 n
= (int
) luaL_checkinteger
(L
, -1);
722 ff
= (n
> max_f ? l_fonts
[1] : l_fonts
[n
]);
724 lua_rawgeti
(L
, -3, 3);
725 n
= (int
) luaL_checkinteger
(L
, -1);
727 append_packet
(packet_font_code
);
729 append_packet
(packet_char_code
);
731 } else if
(lua_key_eq
(s
, comment
) || lua_key_eq
(s
, nop
)) {
732 cmd
= packet_nop_code
;
733 } else if
(lua_key_eq
(s
, node
)) {
734 cmd
= packet_node_code
;
735 } else if
(lua_key_eq
(s
, push
)) {
736 cmd
= packet_push_code
;
737 } else if
(lua_key_eq
(s
, pop
)) {
738 cmd
= packet_pop_code
;
739 } else if
(lua_key_eq
(s
, rule
)) {
740 cmd
= packet_rule_code
;
741 } else if
(lua_key_eq
(s
, right
)) {
742 cmd
= packet_right_code
;
743 } else if
(lua_key_eq
(s
, down
)) {
744 cmd
= packet_down_code
;
745 } else if
(lua_key_eq
(s
, special
)) {
746 cmd
= packet_special_code
;
747 } else if
(lua_key_eq
(s
, image
)) {
748 cmd
= packet_image_code
;
749 } else if
(lua_key_eq
(s
, scale
)) {
750 cmd
= packet_scale_code
;
751 } else if
(lua_key_eq
(s
, lua
)) {
752 cmd
= packet_lua_code
;
755 case packet_push_code
:
756 case packet_pop_code
:
759 case packet_font_code
:
761 lua_rawgeti
(L
, -2, 2);
762 n
= (int
) luaL_checkinteger
(L
, -1);
766 ff
= (n
> max_f ? l_fonts
[1] : l_fonts
[n
]);
771 case packet_node_code
:
773 lua_rawgeti
(L
, -2, 2);
774 n
= copy_node_list
(nodelist_from_lua
(L
));
778 case packet_char_code
:
780 lua_rawgeti
(L
, -2, 2);
781 n
= (int
) luaL_checkinteger
(L
, -1);
785 case packet_right_code
:
786 case packet_down_code
:
788 lua_rawgeti
(L
, -2, 2);
789 n
= (int
) luaL_checkinteger
(L
, -1);
790 do_store_four
(sp_to_dvi
(n
, atsize
));
793 case packet_rule_code
:
795 lua_rawgeti
(L
, -2, 2);
796 n
= (int
) luaL_checkinteger
(L
, -1);
797 do_store_four
(sp_to_dvi
(n
, atsize
));
798 lua_rawgeti
(L
, -3, 3);
799 n
= (int
) luaL_checkinteger
(L
, -1);
800 do_store_four
(sp_to_dvi
(n
, atsize
));
803 case packet_special_code
:
804 case packet_lua_code
:
806 lua_rawgeti
(L
, -2, 2);
807 s
= luaL_checklstring
(L
, -1, &l);
819 case packet_image_code
:
821 lua_rawgeti
(L
, -2, 2); /* img
/imgtable? ...
*/
822 if
(lua_istable
(L
, -1)) { /* imgtable ...
*/
823 lua_getglobal
(L
, "img"); /* imglib imgtable ...
*/
824 lua_pushstring
(L
, "new"); /* `new' imglib imgtable ...
*/
825 lua_gettable
(L
, -2); /* f imglib imgtable ...
*/
826 lua_insert
(L
, -3); /* imglib imgtable f ...
*/
827 lua_pop
(L
, 1); /* imgtable f ...
*/
830 luaL_checkudata
(L
, -1, TYPE_IMG
); /* img ...
--- just typecheck
*/
831 n
= luaL_ref
(L
, LUA_REGISTRYINDEX
); /* ...
*/
834 case packet_nop_code
:
836 case packet_scale_code
:
838 lua_rawgeti
(L
, -2, 2);
839 append_float
(&cp, (float) luaL_checknumber(L, -1));
843 normal_error
("vf command","invalid packet code");
844 /* fprintf
(stdout
, "Unknown char packet code %s\n", s
); */
847 lua_pop
(L
, 1); /* command code
*/
849 normal_error
("vf command","commands has to be a tbale");
850 /* fprintf
(stdout
, "Found a `commands' item that is not a table\n"); */
852 lua_pop
(L
, 1); /* command table
*/
854 append_packet
(packet_end_code
);
855 set_charinfo_packets
(co
, cpackets
);
860 static void read_lua_cidinfo
(lua_State
* L
, int f
)
864 /*lua_getfield
(L
, -1, "cidinfo");*/
865 lua_key_rawgeti
(cidinfo
);
866 if
(lua_istable
(L
, -1)) {
867 i
= lua_numeric_field_by_index
(L
,lua_key_index
(version
), 0);
868 set_font_cidversion
(f
, i
);
869 i
= lua_numeric_field_by_index
(L
,lua_key_index
(supplement
), 0);
870 set_font_cidsupplement
(f
, i
);
871 s
= n_string_field_copy
(L
, lua_key_index
(registry
), "Adobe"); /* Adobe-Identity-0
*/
872 set_font_cidregistry
(f
, s
);
873 s
= n_string_field_copy
(L
, lua_key_index
(ordering
), "Identity");
874 set_font_cidordering
(f
, s
);
881 static void read_lua_parameters
(lua_State
* L
, int f
)
885 /*lua_getfield
(L
, -1, "parameters");*/
886 lua_key_rawgeti
(parameters
);
887 if
(lua_istable
(L
, -1)) {
888 /* the number of parameters is the max
(IntegerKeys
(L
)),7) */
890 lua_pushnil
(L
); /* first key
*/
891 while
(lua_next
(L
, -2) != 0) {
892 if
(lua_type
(L
, -2) == LUA_TNUMBER
) {
893 i
= (int
) lua_tointeger
(L
, -2);
897 lua_pop
(L
, 1); /* pop value
*/
900 set_font_params
(f
, n
);
901 /* sometimes it is handy to have all integer keys
*/
902 for
(i
= 1; i
<= 7; i
++) {
903 lua_rawgeti
(L
, -1, i
);
904 if
(lua_type
(L
, -1) == LUA_TNUMBER
) {
905 n
= lua_roundnumber
(L
, -1); /* round ?
*/
906 set_font_param
(f
, i
, n
);
910 lua_pushnil
(L
); /* first key
*/
911 while
(lua_next
(L
, -2) != 0) {
913 if
(t
== LUA_TNUMBER
) {
914 i
= (int
) lua_tointeger
(L
, -2);
916 if
(lua_type
(L
,-1) == LUA_TNUMBER
) {
917 n
= lua_roundnumber
(L
, -1);
921 set_font_param
(f
, i
, n
);
923 } else if
(t
== LUA_TSTRING
) {
924 s
= lua_tostring
(L
, -2);
925 if
(lua_type
(L
,-1) == LUA_TNUMBER
) {
926 n
= lua_roundnumber
(L
, -1);
930 if
(lua_key_eq
(s
, slant
)) {
931 set_font_param
(f
, slant_code
, n
);
932 } else if
(lua_key_eq
(s
, space
)) {
933 set_font_param
(f
, space_code
, n
);
934 } else if
(lua_key_eq
(s
, space_stretch
)) {
935 set_font_param
(f
, space_stretch_code
, n
);
936 } else if
(lua_key_eq
(s
, space_shrink
)) {
937 set_font_param
(f
, space_shrink_code
, n
);
938 } else if
(lua_key_eq
(s
, x_height
)) {
939 set_font_param
(f
, x_height_code
, n
);
940 } else if
(lua_key_eq
(s
, quad
)) {
941 set_font_param
(f
, quad_code
, n
);
942 } else if
(lua_key_eq
(s
, extra_space
)) {
943 set_font_param
(f
, extra_space_code
, n
);
954 static void read_lua_math_parameters
(lua_State
* L
, int f
)
957 /*lua_getfield
(L
, -1, "MathConstants");*/
958 lua_key_rawgeti
(MathConstants
);
959 if
(lua_istable
(L
, -1)) {
961 while
(lua_next
(L
, -2) != 0) {
963 if
(t
== LUA_TNUMBER
) {
964 i
= (int
) lua_tointeger
(L
, -2);
965 } else if
(t
== LUA_TSTRING
) {
966 i
= ff_checkoption
(L
, -2, NULL, MATH_param_names
);
968 n
= (int
) lua_tointeger
(L
, -1);
970 set_font_math_param
(f
, i
, n
);
972 lua_pop
(L
, 1); /* pop value
*/
974 set_font_oldmath
(f
,false
);
976 set_font_oldmath
(f
,true
);
982 #define MIN_INF
-0x7FFFFFFF
984 static void store_math_kerns
(lua_State
* L
, int index
, charinfo
* co
, int id
)
988 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, index
);
990 if
(lua_istable
(L
, -1) && ((k = (int) lua_rawlen(L, -1)) > 0)) {
991 for
(l
= 0; l
< k
; l
++) {
992 lua_rawgeti
(L
, -1, (l
+ 1));
993 if
(lua_istable
(L
, -1)) {
994 ht
= (scaled
) lua_numeric_field_by_index
(L
, lua_key_index
(height
), MIN_INF
);
995 krn
= (scaled
) lua_numeric_field_by_index
(L
, lua_key_index
(kern
), MIN_INF
);
996 if
(krn
> MIN_INF
&& ht > MIN_INF)
997 add_charinfo_math_kern
(co
, id
, ht
, krn
);
1006 static void font_char_from_lua
(lua_State
* L
, internal_font_number f
, int i
, int
*l_fonts
, boolean has_math
)
1008 int k
, r
, t
, lt
, u
, n
;
1014 int nl
= 0; /* number of ligature table items
*/
1015 int nk
= 0; /* number of kern table items
*/
1017 int atsize
= font_size
(f
);
1018 if
(lua_istable
(L
, -1)) {
1019 co
= get_charinfo
(f
, i
);
1020 set_charinfo_tag
(co
, 0);
1021 j
= lua_numeric_field_by_index
(L
, lua_key_index
(width
), 0);
1022 set_charinfo_width
(co
, j
);
1023 j
= lua_numeric_field_by_index
(L
, lua_key_index
(height
), 0);
1024 set_charinfo_height
(co
, j
);
1025 j
= lua_numeric_field_by_index
(L
, lua_key_index
(depth
), 0);
1026 set_charinfo_depth
(co
, j
);
1027 j
= lua_numeric_field_by_index
(L
, lua_key_index
(italic
), 0);
1028 set_charinfo_italic
(co
, j
);
1029 j
= lua_numeric_field_by_index
(L
, lua_key_index
(vert_italic
), 0);
1030 set_charinfo_vert_italic
(co
, j
);
1031 j
= lua_numeric_field_by_index
(L
, lua_key_index
(index
), 0);
1032 set_charinfo_index
(co
, j
);
1033 j
= lua_numeric_field_by_index
(L
, lua_key_index
(expansion_factor
), 1000);
1034 set_charinfo_ef
(co
, j
);
1035 j
= lua_numeric_field_by_index
(L
, lua_key_index
(left_protruding
), 0);
1036 set_charinfo_lp
(co
, j
);
1037 j
= lua_numeric_field_by_index
(L
, lua_key_index
(right_protruding
), 0);
1038 set_charinfo_rp
(co
, j
);
1039 k
= n_boolean_field
(L
, lua_key_index
(used
), 0);
1040 set_charinfo_used
(co
, k
);
1041 s
= n_string_field
(L
, lua_key_index
(name
));
1043 set_charinfo_name
(co
, xstrdup
(s
));
1045 set_charinfo_name
(co
, NULL);
1046 /* n_string_field leaves a value on stack
*/
1048 u
= n_some_field
(L
,lua_key_index
(tounicode
));
1049 if
(u
== LUA_TNUMBER
) {
1050 u
= lua_tointeger
(L
,-1);
1052 set_charinfo_tounicode
(co
, NULL);
1053 } else if
(u
< 0xD7FF ||
(u
> 0xDFFF && u <= 0xFFFF)) {
1054 char
*s
= malloc
(5);
1055 sprintf
(s
,"%04X",(unsigned int
) u
);
1056 set_charinfo_tounicode
(co
,s
);
1058 char
*s
= malloc
(9);
1060 sprintf
(s
,"%04X%04X",(unsigned int
) (floor
(u
/1024)+0xD800),(unsigned int
) (u
%1024+0xDC00));
1061 set_charinfo_tounicode
(co
,s
);
1063 } else if
(u
== LUA_TTABLE
) {
1064 n
= lua_rawlen
(L
,-1);
1066 for
(k
= 1; k
<= n
; k
++) {
1067 lua_rawgeti
(L
, -1, k
);
1068 if
(lua_type
(L
,-1) == LUA_TNUMBER
) {
1069 u
= lua_tointeger
(L
,-1);
1078 } else if
(u
< 0xD7FF ||
(u
> 0xDFFF && u <= 0xFFFF)) {
1086 char
*s
= malloc
(u
+1);
1088 for
(k
= 1; k
<= n
; k
++) {
1089 lua_rawgeti
(L
, -1, k
);
1090 u
= lua_tointeger
(L
,-1);
1091 if
(u
< 0xD7FF ||
(u
> 0xDFFF && u <= 0xFFFF)) {
1092 sprintf
(t
,"%04X",(unsigned int
) u
);
1096 sprintf
(t
,"%04X%04X",(unsigned int
) (floor
(u
/1024)+0xD800),(unsigned int
) (u
%1024+0xDC00));
1101 set_charinfo_tounicode
(co
,s
);
1103 set_charinfo_tounicode
(co
, NULL);
1105 } else if
(u
== LUA_TSTRING
) {
1106 s
= lua_tostring
(L
,-1);
1107 set_charinfo_tounicode
(co
, xstrdup
(s
));
1109 set_charinfo_tounicode
(co
, NULL);
1111 /* ... leaves a value on stack
*/
1115 j
= lua_numeric_field_by_index
(L
, lua_key_index
(top_accent
), INT_MIN
);
1116 set_charinfo_top_accent
(co
, j
);
1117 j
= lua_numeric_field_by_index
(L
, lua_key_index
(bot_accent
), INT_MIN
);
1118 set_charinfo_bot_accent
(co
, j
);
1119 k
= lua_numeric_field_by_index
(L
, lua_key_index
(next
), -1);
1121 set_charinfo_tag
(co
, list_tag
);
1122 set_charinfo_remainder
(co
, k
);
1125 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, lua_key_index
(extensible
));
1127 if
(lua_istable
(L
, -1)) {
1128 int top
, bot
, mid
, rep
;
1129 top
= lua_numeric_field_by_index
(L
, lua_key_index
(top
), 0);
1130 bot
= lua_numeric_field_by_index
(L
, lua_key_index
(bot
), 0);
1131 mid
= lua_numeric_field_by_index
(L
, lua_key_index
(mid
), 0);
1132 rep
= lua_numeric_field_by_index
(L
, lua_key_index
(rep
), 0);
1133 if
(top
!= 0 || bot
!= 0 || mid
!= 0 || rep
!= 0) {
1134 set_charinfo_tag
(co
, ext_tag
);
1135 set_charinfo_extensible
(co
, top
, bot
, mid
, rep
);
1137 formatted_warning
("font", "lua-loaded font %s char U+%X has an invalid extensible field",
1138 font_name
(f
), (int
) i
);
1143 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, lua_key_index
(horiz_variants
));
1145 if
(lua_istable
(L
, -1)) {
1146 int glyph
, startconnect
, endconnect
, advance
, extender
;
1148 set_charinfo_tag
(co
, ext_tag
);
1149 set_charinfo_hor_variants
(co
, NULL);
1151 lua_rawgeti
(L
, -1, k
);
1152 if
(lua_istable
(L
, -1)) {
1153 glyph
= lua_numeric_field_by_index
(L
, lua_key_index
(glyph
), 0);
1154 extender
= lua_numeric_field_by_index
(L
, lua_key_index
(extender
), 0);
1155 startconnect
= lua_numeric_field_by_index
(L
, lua_key_index
(start
), 0);
1156 endconnect
= lua_numeric_field_by_index
(L
, lua_key_index
(end
), 0);
1157 advance
= lua_numeric_field_by_index
(L
, lua_key_index
(advance
), 0);
1158 h
= new_variant
(glyph
, startconnect
, endconnect
, advance
, extender
);
1159 add_charinfo_hor_variant
(co
, h
);
1169 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, lua_key_index
(vert_variants
));
1171 if
(lua_istable
(L
, -1)) {
1172 int glyph
, startconnect
, endconnect
, advance
, extender
;
1174 set_charinfo_tag
(co
, ext_tag
);
1175 set_charinfo_vert_variants
(co
, NULL);
1177 lua_rawgeti
(L
, -1, k
);
1178 if
(lua_istable
(L
, -1)) {
1179 glyph
= lua_numeric_field_by_index
(L
, lua_key_index
(glyph
), 0);
1180 extender
= lua_numeric_field_by_index
(L
, lua_key_index
(extender
), 0);
1181 startconnect
= lua_numeric_field_by_index
(L
, lua_key_index
(start
), 0);
1182 endconnect
= lua_numeric_field_by_index
(L
, lua_key_index
(end
), 0);
1183 advance
= lua_numeric_field_by_index
(L
, lua_key_index
(advance
), 0);
1184 h
= new_variant
(glyph
, startconnect
, endconnect
, advance
, extender
);
1185 add_charinfo_vert_variant
(co
, h
);
1196 Here is a complete example
:
1199 | bottom_left
= { { height
= 420, kern
= 80 }, { height
= 520, kern
= 4 } },|
1200 | bottom_right
= { { height
= 0, kern
= 48 } },|
1201 | top_left
= { { height
= 620, kern
= 0 }, { height
= 720, kern
= -80 } },|
1202 | top_right
= { { height
= 676, kern
= 115 }, { height
= 776, kern
= 45 } },|
1207 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, lua_key_index
(mathkern
));
1209 if
(lua_istable
(L
, -1)) {
1210 store_math_kerns
(L
,lua_key_index
(top_left
), co
, top_left_kern
);
1211 store_math_kerns
(L
,lua_key_index
(top_right
), co
, top_right_kern
);
1212 store_math_kerns
(L
,lua_key_index
(bottom_right
), co
, bottom_right_kern
);
1213 store_math_kerns
(L
,lua_key_index
(bottom_left
), co
, bottom_left_kern
);
1217 /* end of |has_math|
*/
1218 count_hash_items
(L
, lua_key_index
(kerns
), nk
);
1220 /* kerns table still on stack
*/
1221 ckerns
= xcalloc
((unsigned
) (nk
+ 1), sizeof
(kerninfo
));
1223 lua_pushnil
(L
); /* traverse hash
*/
1224 while
(lua_next
(L
, -2) != 0) {
1225 k
= non_boundarychar
;
1226 lt
= lua_type
(L
,-2);
1227 if
(lt
== LUA_TNUMBER
) {
1228 k
= (int
) lua_tointeger
(L
, -2); /* adjacent char
*/
1230 k
= non_boundarychar
;
1231 } else if
(lt
== LUA_TSTRING
) {
1232 s
= lua_tostring
(L
, -2);
1233 if
(lua_key_eq
(s
, right_boundary
)) {
1234 k
= right_boundarychar
;
1235 if
(!has_right_boundary
(f
))
1236 set_right_boundary
(f
, get_charinfo
(f
, right_boundarychar
));
1239 j
= lua_roundnumber
(L
, -1); /* movement
*/
1240 if
(k
!= non_boundarychar
) {
1241 set_kern_item
(ckerns
[ctr
], k
, j
);
1244 formatted_warning
("font", "lua-loaded font %s char U+%X has an invalid kern field",
1245 font_name
(f
), (int
) i
);
1249 /* guard against empty tables
*/
1251 set_kern_item
(ckerns
[ctr
], end_kern
, 0);
1252 set_charinfo_kerns
(co
, ckerns
);
1254 formatted_warning
("font", "lua-loaded font %s char U+%X has an invalid kerns field",
1255 font_name
(f
), (int
) i
);
1260 /* packet commands
*/
1261 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, lua_key_index
(commands
));
1263 if
(lua_istable
(L
, -1)) {
1264 lua_pushnil
(L
); /* first key
*/
1265 if
(lua_next
(L
, -2) != 0) {
1267 read_char_packets
(L
, (int
*) l_fonts
, co
, f
, atsize
);
1273 count_hash_items
(L
, lua_key_index
(ligatures
),nl
);
1275 /* ligatures table still on stack
*/
1276 cligs
= xcalloc
((unsigned
) (nl
+ 1), sizeof
(liginfo
));
1278 lua_pushnil
(L
); /* traverse hash
*/
1279 while
(lua_next
(L
, -2) != 0) {
1280 k
= non_boundarychar
;
1281 lt
= lua_type
(L
,-2);
1282 if
(lt
== LUA_TNUMBER
) {
1283 k
= (int
) lua_tointeger
(L
, -2); /* adjacent char
*/
1285 k
= non_boundarychar
;
1287 } else if
(lt
== LUA_TSTRING
) {
1288 s
= lua_tostring
(L
, -2);
1289 if
(lua_key_eq
(s
, right_boundary
)) {
1290 k
= right_boundarychar
;
1291 if
(!has_right_boundary
(f
))
1292 set_right_boundary
(f
, get_charinfo
(f
, right_boundarychar
));
1296 if
(lua_istable
(L
, -1)) {
1297 r
= lua_numeric_field_by_index
(L
, lua_key_index
(char
), -1); /* ligature
*/
1299 if
(r
!= -1 && k != non_boundarychar) {
1300 t
= n_enum_field
(L
, lua_key_index
(type
), 0, ligature_type_strings
);
1301 set_ligature_item
(cligs
[ctr
], (char
) ((t
* 2) + 1), k
, r
);
1304 formatted_warning
("font", "lua-loaded font %s char U+%X has an invalid ligature field",
1305 font_name
(f
), (int
) i
);
1307 lua_pop
(L
, 1); /* iterator value
*/
1309 /* guard against empty tables
*/
1311 set_ligature_item
(cligs
[ctr
], 0, end_ligature
, 0);
1312 set_charinfo_ligatures
(co
, cligs
);
1314 formatted_warning
("font", "lua-loaded font %s char U+%X has an invalid ligatures field",
1315 font_name
(f
), (int
) i
);
1317 lua_pop
(L
, 1); /* ligatures table
*/
1322 @ The caller has to fix the state of the lua stack when there is an error
!
1325 int font_from_lua
(lua_State
* L
, int f
)
1328 int s_top
; /* lua stack top
*/
1329 int bc
; /* first char index
*/
1330 int ec
; /* last char index
*/
1333 int
*l_fonts
= NULL;
1335 boolean no_math
= false
;
1337 /* will we save a cache of the luat table?
*/
1339 save_ref
= 1; /* we start with ss
= "yes" */
1341 ss
= n_string_field
(L
, lua_key_index
(cache
));
1342 if
(lua_key_eq
(ss
, no
))
1344 else if
(lua_key_eq
(ss
, renew
))
1346 /* n_string_field leaves a value on stack
*/
1349 /* the table is at stack index
-1 */
1351 s
= n_string_field_copy
(L
,lua_key_index
(area
), "");
1352 set_font_area
(f
, s
);
1353 s
= n_string_field_copy
(L
, lua_key_index
(filename
), NULL);
1354 set_font_filename
(f
, s
);
1355 s
= n_string_field_copy
(L
, lua_key_index
(encodingname
), NULL);
1356 set_font_encodingname
(f
, s
);
1358 s
= n_string_field_copy
(L
, lua_key_index
(name
), NULL);
1359 set_font_name
(f
, s
);
1360 s
= n_string_field_copy
(L
, lua_key_index
(fullname
), font_name
(f
));
1361 set_font_fullname
(f
, s
);
1364 formatted_error
("font","lua-loaded font '%d' has no name!", f
);
1367 s
= n_string_field_copy
(L
, lua_key_index
(psname
), NULL);
1368 set_font_psname
(f
, s
);
1370 i
= lua_numeric_field_by_index
(L
,lua_key_index
(units_per_em
), 0);
1371 set_font_units_per_em
(f
, i
);
1372 i
= lua_numeric_field_by_index
(L
,lua_key_index
(designsize
), 655360);
1373 set_font_dsize
(f
, i
);
1374 i
= lua_numeric_field_by_index
(L
,lua_key_index
(size
), font_dsize
(f
));
1375 set_font_size
(f
, i
);
1376 set_font_checksum
(f
, (unsigned
)(lua_unsigned_numeric_field_by_index
(L
,lua_key_index
(checksum
), 0))) ;
1377 i
= lua_numeric_field_by_index
(L
,lua_key_index
(direction
), 0);
1378 set_font_natural_dir
(f
, i
);
1379 i
= lua_numeric_field_by_index
(L
,lua_key_index
(encodingbytes
), 0);
1380 set_font_encodingbytes
(f
, (char
) i
);
1381 i
= n_boolean_field
(L
,lua_key_index
(oldmath
), 0);
1382 set_font_oldmath
(f
, i
);
1383 i
= lua_numeric_field_by_index
(L
,lua_key_index
(tounicode
), 0);
1384 set_font_tounicode
(f
, (char
) i
);
1386 i
= lua_numeric_field_by_index
(L
,lua_key_index
(extend
), 1000);
1387 if
(i
< FONT_EXTEND_MIN
)
1388 i
= FONT_EXTEND_MIN
;
1389 if
(i
> FONT_EXTEND_MAX
)
1390 i
= FONT_EXTEND_MAX
;
1391 set_font_extend
(f
, i
);
1392 i
= lua_numeric_field_by_index
(L
,lua_key_index
(slant
), 0);
1393 if
(i
< FONT_SLANT_MIN
)
1395 if
(i
> FONT_SLANT_MAX
)
1397 set_font_slant
(f
, i
);
1399 i
= lua_numeric_field_by_index
(L
,lua_key_index
(hyphenchar
), int_par
(default_hyphen_char_code
));
1400 set_hyphen_char
(f
, i
);
1401 i
= lua_numeric_field_by_index
(L
,lua_key_index
(skewchar
), int_par
(default_skew_char_code
));
1402 set_skew_char
(f
, i
);
1403 i
= n_boolean_field
(L
, lua_key_index
(used
), 0);
1404 set_font_used
(f
, (char
) i
);
1406 s
= n_string_field_copy
(L
, lua_key_index
(attributes
), NULL);
1407 if
(s
!= NULL && strlen(s) > 0) {
1408 i
= maketexstring
(s
);
1409 set_pdf_font_attr
(f
, i
);
1413 i
= n_enum_field
(L
, lua_key_index
(type
), unknown_font_type
, font_type_strings
);
1414 set_font_type
(f
, i
);
1415 i
= n_enum_field
(L
, lua_key_index
(format
), unknown_format
, font_format_strings
);
1416 set_font_format
(f
, i
);
1417 i
= n_enum_field
(L
, lua_key_index
(embedding
), unknown_embedding
, font_embedding_strings
);
1418 set_font_embedding
(f
, i
);
1419 if
(font_encodingbytes
(f
) == 0 && (font_format(f) == opentype_format || font_format(f) == truetype_format)) {
1420 set_font_encodingbytes
(f
, 2);
1423 /* now fetch the base fonts
, if needed
*/
1424 count_hash_items
(L
, lua_key_index
(fonts
), n
);
1426 /* font table still on stack
*/
1427 l_fonts
= xmalloc
((unsigned
) ((unsigned
) (n
+ 2) * sizeof
(int
)));
1428 memset
(l_fonts
, 0, (size_t
) ((unsigned
) (n
+ 2) * sizeof
(int
)));
1429 for
(i
= 1; i
<= n
; i
++) {
1430 lua_rawgeti
(L
, -1, i
);
1431 if
(lua_istable
(L
, -1)) {
1432 lua_key_rawgeti
(id
);
1433 if
(lua_isnumber
(L
, -1)) {
1434 l_fonts
[i
] = (int
) lua_tointeger
(L
, -1);
1435 if
(l_fonts
[i
] == 0) {
1436 l_fonts
[i
] = (int
) f
;
1438 lua_pop
(L
, 2); /* pop id and entry
*/
1441 lua_pop
(L
, 1); /* pop id
*/
1444 if
(lua_istable
(L
, -1)) {
1445 ss
= n_string_field
(L
, lua_key_index
(name
));
1446 /* string is anchored
*/
1450 t
= lua_numeric_field_by_index
(L
, lua_key_index
(size
), -1000);
1451 /* TODO
: the stack is messed up
, otherwise this explicit resizing would not be needed
*/
1452 s_top
= lua_gettop
(L
);
1453 if
(strcmp
(font_name
(f
), ss
) == 0)
1456 l_fonts
[i
] = find_font_id
(ss
, t
);
1457 lua_settop
(L
, s_top
);
1459 formatted_error
("font","invalid local font in lua-loaded font '%s'", font_name
(f
));
1461 lua_pop
(L
, 1); /* pop list entry
*/
1463 lua_pop
(L
, 1); /* pop font table
*/
1464 } else if
(font_type
(f
) == virtual_font_type
) {
1465 formatted_error
("font","invalid local fonts in lua-loaded font '%s'", font_name
(f
));
1467 l_fonts
= xmalloc
(3 * sizeof
(int
));
1474 no_math
= n_boolean_field
(L
, lua_key_index
(nomath
), 0);
1475 read_lua_parameters
(L
, f
);
1477 read_lua_math_parameters
(L
, f
);
1478 if
(n_boolean_field
(L
, lua_key_index
(oldmath
), 0)) {
1479 set_font_oldmath
(f
,true
);
1483 set_font_oldmath
(f
,true
);
1485 read_lua_cidinfo
(L
, f
);
1488 /*lua_rawgeti
(L
, LUA_REGISTRYINDEX
, lua_key_index
(characters
));lua_rawget
(L
, -2);*/
1489 lua_key_rawgeti
(characters
);
1490 /*lua_getfield
(L
, -1, "characters");*/
1491 if
(lua_istable
(L
, -1)) {
1492 /* find the array size values
*/
1493 int num
= 0; /* number of charinfo's to add
*/
1496 lua_pushnil
(L
); /* first key
*/
1497 while
(lua_next
(L
, -2) != 0) {
1498 if
(lua_isnumber
(L
, -2)) {
1499 i
= (int
) lua_tointeger
(L
, -2);
1501 if
(lua_istable
(L
, -1)) {
1507 if
(bc
>= 0 && i < bc)
1515 font_malloc_charinfo
(f
, num
);
1518 lua_pushnil
(L
); /* first key
*/
1519 while
(lua_next
(L
, -2) != 0) {
1520 lt
= lua_type
(L
,-2);
1521 if
(lt
== LUA_TNUMBER
) {
1522 i
= (int
) lua_tointeger
(L
, -2);
1524 font_char_from_lua
(L
, f
, i
, l_fonts
, !no_math
);
1526 } else if
(lt
== LUA_TSTRING
) {
1527 const char
*ss1
= lua_tostring
(L
, -2);
1528 if
(lua_key_eq
(ss1
, left_boundary
)) {
1529 font_char_from_lua
(L
, f
, left_boundarychar
, l_fonts
,
1531 } else if
(lua_key_eq
(ss1
, right_boundary
)) {
1532 font_char_from_lua
(L
, f
, right_boundarychar
, l_fonts
,
1541 Handle font expansion last
: the |copy_font| routine is called eventually
,
1542 and that needs to know |bc| and |ec|.
1545 if
(font_type
(f
) != virtual_font_type
) {
1546 int fstep
= lua_numeric_field_by_index
(L
, lua_key_index
(step
), 0);
1552 int fshrink
= lua_numeric_field_by_index
(L
, lua_key_index
(shrink
), 0);
1553 int fstretch
=lua_numeric_field_by_index
(L
, lua_key_index
(stretch
), 0);
1554 int fexpand
= n_boolean_field
(L
, lua_key_index
(auto_expand
), 0);
1559 fshrink
-= (fshrink
% fstep
);
1564 if
(fstretch
> 1000)
1566 fstretch
-= (fstretch
% fstep
);
1569 set_expand_params
(f
, fexpand
, fstretch
, fshrink
, fstep
);
1574 /* jikes
, no characters
*/
1575 formatted_warning
("font","lua-loaded font '%d' with name '%s' has no characters", f
, font_name
(f
));
1579 r
= luaL_ref
(L
, LUA_REGISTRYINDEX
); /* pops the table
*/
1580 set_font_cache_id
(f
, r
);
1583 set_font_cache_id
(f
, save_ref
);
1586 /* jikes
, no characters
*/
1587 formatted_warning
("font","lua-loaded font '%d' with name '%s' has no character table", f
, font_name
(f
));
1589 if
(l_fonts
!= NULL)
1597 static void nesting_append
(halfword nest1
, halfword newn
)
1599 halfword tail
= tlink
(nest1
);
1601 couple_nodes
(nest1
, newn
);
1603 couple_nodes
(tail
, newn
);
1605 tlink
(nest1
) = newn
;
1608 static void nesting_prepend
(halfword nest1
, halfword newn
)
1610 halfword head
= vlink
(nest1
);
1611 couple_nodes
(nest1
, newn
);
1613 tlink
(nest1
) = newn
;
1615 couple_nodes
(newn
, head
);
1619 static void nesting_prepend_list
(halfword nest1
, halfword newn
)
1621 halfword head
= vlink
(nest1
);
1622 couple_nodes
(nest1
, newn
);
1624 tlink
(nest1
) = tail_of_list
(newn
);
1626 halfword tail
= tail_of_list
(newn
);
1627 couple_nodes
(tail
, head
);
1631 static int test_ligature
(liginfo
* lig
, halfword left
, halfword right
)
1633 if
(type
(left
) != glyph_node
)
1635 if
(font
(left
) != font
(right
))
1637 if
(is_ghost
(left
) || is_ghost
(right
))
1639 *lig
= get_ligature
(font
(left
), character
(left
), character
(right
));
1640 if
(is_valid_ligature
(*lig
)) {
1646 static int try_ligature
(halfword
* frst
, halfword fwd
)
1648 halfword cur
= *frst
;
1650 if
(test_ligature
(&lig, cur, fwd)) {
1651 int move_after
= (lig_type
(lig
) & 0x0C) >> 2;
1652 int keep_right
= ((lig_type
(lig
) & 0x01) != 0);
1653 int keep_left
= ((lig_type
(lig
) & 0x02) != 0);
1654 halfword newgl
= raw_glyph_node
();
1655 font
(newgl
) = font
(cur
);
1656 character
(newgl
) = lig_replacement
(lig
);
1657 set_is_ligature
(newgl
);
1659 below might not be correct in contrived border case.
1660 but we use it only for debugging
, so ...
1662 if
(character
(cur
) < 0) {
1663 set_is_leftboundary
(newgl
);
1665 if
(character
(fwd
) < 0) {
1666 set_is_rightboundary
(newgl
);
1668 if
(character
(cur
) < 0) {
1669 if
(character
(fwd
) < 0) {
1670 build_attribute_list
(newgl
);
1672 add_node_attr_ref
(node_attr
(fwd
));
1673 node_attr
(newgl
) = node_attr
(fwd
);
1676 add_node_attr_ref
(node_attr
(cur
));
1677 node_attr
(newgl
) = node_attr
(cur
);
1681 TODO
/FIXME if this ligature is consists of another ligature
1682 we should add it's |lig_ptr| to the new glyphs |lig_ptr|
(and
1683 cleanup the no longer needed node
) LOW PRIORITY
1687 halfword new_first
= copy_node
(cur
);
1688 lig_ptr
(newgl
) = new_first
;
1689 couple_nodes
(cur
, newgl
);
1695 halfword prev
= alink
(cur
);
1697 lig_ptr
(newgl
) = cur
;
1698 couple_nodes
(prev
, newgl
);
1699 cur
= newgl
; /* as cur has disappeared
*/
1703 halfword new_second
= copy_node
(fwd
);
1704 /* correct
, because we
{\it know\
/} |lig_ptr| points to
{\it one\
/} node
*/
1705 couple_nodes
(lig_ptr
(newgl
), new_second
);
1706 couple_nodes
(newgl
, fwd
);
1712 halfword next
= vlink
(fwd
);
1714 /* correct
, because we
{\it know\
/} |lig_ptr| points to
{\it one\
/} node
*/
1715 couple_nodes
(lig_ptr
(newgl
), fwd
);
1717 couple_nodes
(newgl
, next
);
1720 /* check and return
*/
1727 @ there shouldn't be any ligatures here
- we only add them at the end of
1728 |xxx_break| in a \.
{DISC-1
- DISC-2
} situation and we stop processing \.
{DISC-1
}
1729 (we continue with \.
{DISC-1
}'s |post_| and |no_break|.
1732 static halfword handle_lig_nest
(halfword root
, halfword cur
)
1736 while
(vlink
(cur
) != null
) {
1737 halfword fwd
= vlink
(cur
);
1738 if
(type
(cur
) == glyph_node
&& type(fwd) == glyph_node &&
1739 font
(cur
) == font
(fwd
) && try_ligature(&cur, fwd)) {
1748 static halfword handle_lig_word
(halfword cur
)
1750 halfword right
= null
;
1751 if
(type
(cur
) == boundary_node
) {
1752 halfword prev
= alink
(cur
);
1753 halfword fwd
= vlink
(cur
);
1754 /* no need to uncouple |cur|
, it is freed
*/
1760 couple_nodes
(prev
, fwd
);
1761 if
(type
(fwd
) != glyph_node
)
1764 } else if
(has_left_boundary
(font
(cur
))) {
1765 halfword prev
= alink
(cur
);
1766 halfword p
= new_glyph
(font
(cur
), left_boundarychar
);
1767 couple_nodes
(prev
, p
);
1768 couple_nodes
(p
, cur
);
1771 if
(has_right_boundary
(font
(cur
))) {
1772 right
= new_glyph
(font
(cur
), right_boundarychar
);
1775 /* A glyph followed by ...
*/
1776 if
(type
(cur
) == glyph_node
) {
1777 halfword fwd
= vlink
(cur
);
1778 if
(fwd
== null
) { /* last character of paragraph
*/
1781 /* \.
{--\\par
} prohibits use of |couple_nodes| here
*/
1782 try_couple_nodes
(cur
, right
);
1786 if
(type
(fwd
) == glyph_node
) { /* |GLYPH
- GLYPH|
*/
1787 if
(font
(cur
) != font
(fwd
))
1789 if
(try_ligature
(&cur, fwd))
1791 } else if
(type
(fwd
) == disc_node
) { /* |GLYPH
- DISC|
*/
1793 /* if \.
{a
{bx
}{}{y
}} and \.
{a
+b
=>B
} convert to \.
{{Bx
}{}{ay
}} */
1794 halfword pre
= vlink_pre_break
(fwd
);
1795 halfword nob
= vlink_no_break
(fwd
);
1796 halfword next
, tail
;
1798 /* Check on
: a
{b?
}{?
}{?
} and a
+b
=>B
: {B?
}{?
}{a?
} */
1799 /* Check on
: a
{?
}{?
}{b?
} and a
+b
=>B
: {a?
}{?
}{B?
} */
1800 if
((pre
!= null
&& type(pre) == glyph_node
1801 && test_ligature(&lig, cur, pre))
1802 ||
(nob
!= null
&& type(nob) == glyph_node
1803 && test_ligature(&lig, cur, nob))) {
1804 /* move cur from before disc
, to skipped part
*/
1805 halfword prev
= alink
(cur
);
1807 couple_nodes
(prev
, fwd
);
1808 nesting_prepend
(no_break
(fwd
), cur
);
1809 /* now ligature the |pre_break|
*/
1810 nesting_prepend
(pre_break
(fwd
), copy_node
(cur
));
1811 /* As we have removed cur
, we need to start again ...
*/
1814 /* Check on
: a
{?
}{?
}{}b and a
+b
=>B
: {a?
}{?b
}{B
} */
1816 if
(nob
== null
&& next != null && type(next) == glyph_node
1817 && test_ligature(&lig, cur, next)) {
1818 /* move |cur| from before |disc| to |no_break| part
*/
1819 halfword prev
= alink
(cur
);
1821 couple_nodes
(prev
, fwd
);
1822 couple_nodes
(no_break
(fwd
), cur
); /* we
{\it know\
/} it's empty
*/
1823 /* now copy cur the |pre_break|
*/
1824 nesting_prepend
(pre_break
(fwd
), copy_node
(cur
));
1825 /* move next from after disc to |no_break| part
*/
1827 uncouple_node
(next
);
1828 try_couple_nodes
(fwd
, tail
);
1829 couple_nodes
(cur
, next
); /* we
{\it know\
/} this works
*/
1830 tlink
(no_break
(fwd
)) = next
; /* and make sure the list is correct
*/
1831 /* now copy next to the |post_break|
*/
1832 nesting_append
(post_break
(fwd
), copy_node
(next
));
1833 /* As we have removed cur
, we need to start again ...
*/
1836 /* we are finished with the |pre_break|
*/
1837 handle_lig_nest
(pre_break
(fwd
), vlink_pre_break
(fwd
));
1838 } else if
(type
(fwd
) == boundary_node
) {
1839 halfword next
= vlink
(fwd
);
1840 try_couple_nodes
(cur
, next
);
1842 if
(right
!= null
) {
1843 flush_node
(right
); /* Shame
, didn't need it
*/
1844 /* no need to reset |right|
, we're going to leave the loop anyway
*/
1848 /* fwd is something unknown
*/
1851 couple_nodes
(cur
, right
);
1852 couple_nodes
(right
, fwd
);
1856 /* A discretionary followed by ...
*/
1857 } else if
(type
(cur
) == disc_node
) {
1858 /* If \.
{{?
}{x
}{?
}} or \.
{{?
}{?
}{y
}} then ...
*/
1859 if
(vlink_no_break
(cur
) != null || vlink_post_break
(cur
) != null
) {
1863 if
(subtype
(cur
) == select_disc
) {
1865 if
(vlink_post_break
(cur
) != null
)
1866 handle_lig_nest
(post_break
(prev
), vlink_post_break
(prev
));
1867 if
(vlink_no_break
(cur
) != null
)
1868 handle_lig_nest
(no_break
(prev
), vlink_no_break
(prev
));
1870 if
(vlink_post_break
(cur
) != null
)
1871 handle_lig_nest
(post_break
(cur
), vlink_post_break
(cur
));
1872 if
(vlink_no_break
(cur
) != null
)
1873 handle_lig_nest
(no_break
(cur
), vlink_no_break
(cur
));
1874 while
((fwd
= vlink
(cur
)) != null
) {
1875 halfword nob
, pst
, next
;
1876 if
(type
(fwd
) != glyph_node
)
1878 if
(subtype
(cur
) != select_disc
) {
1879 nob
= tlink_no_break
(cur
);
1880 pst
= tlink_post_break
(cur
);
1881 if
((nob
== null ||
!test_ligature
(&lig, nob, fwd)) &&
1882 (pst
== null ||
!test_ligature
(&lig, pst, fwd)))
1884 nesting_append
(no_break
(cur
), copy_node
(fwd
));
1885 handle_lig_nest
(no_break
(cur
), nob
);
1888 nob
= tlink_no_break
(prev
);
1889 pst
= tlink_post_break
(prev
);
1890 if
((nob
== null ||
!test_ligature
(&lig, nob, fwd)) &&
1891 (pst
== null ||
!test_ligature
(&lig, pst, fwd)))
1894 nesting_append
(no_break
(prev
), copy_node
(fwd
));
1895 handle_lig_nest
(no_break
(prev
), nob
);
1896 nesting_append
(post_break
(prev
), copy_node
(fwd
));
1897 handle_lig_nest
(post_break
(prev
), pst
);
1900 nob
= tlink_no_break
(cur
);
1901 pst
= tlink_post_break
(cur
);
1902 if
((nob
== null ||
!test_ligature
(&lig, nob, fwd)) &&
1903 (pst
== null ||
!test_ligature
(&lig, pst, fwd)))
1906 nesting_append
(no_break
(cur
), copy_node
(fwd
));
1907 handle_lig_nest
(no_break
(cur
), nob
);
1914 try_couple_nodes
(cur
, next
);
1915 nesting_append
(post_break
(cur
), fwd
);
1916 handle_lig_nest
(post_break
(cur
), pst
);
1918 if
(fwd
!= null
&& type(fwd) == disc_node) {
1919 halfword next
= vlink
(fwd
);
1920 if
(vlink_no_break
(fwd
) == null
1921 && vlink_post_break(fwd) == null
1923 && type(next) == glyph_node
1924 && ((tlink_post_break(cur) != null && test_ligature(&lig, tlink_post_break(cur), next)) ||
1925 (tlink_no_break
(cur
) != null
&& test_ligature(&lig, tlink_no_break (cur), next)))) {
1926 /* Building an |init_disc| followed by a |select_disc|
1927 \.
{{a-
}{b
}{AB
} {-}{}{}} 'c'
1929 /* is it tail necessary ?
*/
1930 halfword last1
= vlink
(next
), tail
;
1931 uncouple_node
(next
);
1932 try_couple_nodes
(fwd
, last1
);
1933 /* \.
{{a-
}{b
}{AB
} {-}{c
}{}} */
1934 nesting_append
(post_break
(fwd
), copy_node
(next
));
1935 /* \.
{{a-
}{b
}{AB
} {-}{c
}{-}} */
1936 if
(vlink_no_break
(cur
) != null
) {
1937 nesting_prepend
(no_break
(fwd
), copy_node
(vlink_pre_break
(fwd
)));
1939 /* \.
{{a-
}{b
}{AB
} {b-
}{c
}{-}} */
1940 if
(vlink_post_break
(cur
) != null
)
1941 nesting_prepend_list
(pre_break
(fwd
), copy_node_list
(vlink_post_break
(cur
)));
1942 /* \.
{{a-
}{b
}{AB
} {b-
}{c
}{AB-
}} */
1943 if
(vlink_no_break
(cur
) != null
) {
1944 nesting_prepend_list
(no_break
(fwd
), copy_node_list
(vlink_no_break
(cur
)));
1946 /* \.
{{a-
}{b
}{ABC
} {b-
}{c
}{AB-
}} */
1947 tail
= tlink_no_break
(cur
);
1948 nesting_append
(no_break
(cur
), copy_node
(next
));
1949 handle_lig_nest
(no_break
(cur
), tail
);
1950 /* \.
{{a-
}{BC
}{ABC
} {b-
}{c
}{AB-
}} */
1951 tail
= tlink_post_break
(cur
);
1952 nesting_append
(post_break
(cur
), next
);
1953 handle_lig_nest
(post_break
(cur
), tail
);
1954 /* and set the subtypes
*/
1955 subtype
(cur
) = init_disc
;
1956 subtype
(fwd
) = select_disc
;
1962 /* NO GLYPH NOR DISC
*/
1965 /* step-to-next-node
*/
1966 /* \.
{--\\par
} allows |vlink
(cur
)| to be null
*/
1973 @ Return value is the new tail
, head should be a dummy
1976 halfword handle_ligaturing
(halfword head
, halfword tail
)
1978 halfword save_tail1
; /* trick to allow explicit |node
==null| tests
*/
1981 if
(vlink
(head
) == null
)
1983 save_tail1
= vlink
(tail
);
1986 /* |if
(fix_node_lists
)|
*/
1987 fix_node_list
(head
);
1992 while
(cur
!= null
) {
1993 if
(type
(cur
) == glyph_node ||
(type
(cur
) == boundary_node
)) {
1994 cur
= handle_lig_word
(cur
);
2002 if
(valid_node
(save_tail1
)) {
2003 try_couple_nodes
(prev
, save_tail1
);
2012 static void add_kern_before
(halfword left
, halfword right
)
2014 if
((!is_rightghost
(right
)) &&
2015 font
(left
) == font
(right
) && has_kern(font(left), character(left))) {
2016 int k
= raw_get_kern
(font
(left
), character
(left
), character
(right
));
2018 halfword kern
= new_kern
(k
);
2019 halfword prev
= alink
(right
);
2020 couple_nodes
(prev
, kern
);
2021 couple_nodes
(kern
, right
);
2022 /* update the attribute list
(inherit from left
) */
2023 delete_attribute_ref
(node_attr
(kern
));
2024 add_node_attr_ref
(node_attr
(left
));
2025 node_attr
(kern
) = node_attr
(left
);
2030 static void add_kern_after
(halfword left
, halfword right
, halfword aft
)
2032 if
((!is_rightghost
(right
)) &&
2033 font
(left
) == font
(right
) && has_kern(font(left), character(left))) {
2034 int k
= raw_get_kern
(font
(left
), character
(left
), character
(right
));
2036 halfword kern
= new_kern
(k
);
2037 halfword next
= vlink
(aft
);
2038 couple_nodes
(aft
, kern
);
2039 try_couple_nodes
(kern
, next
);
2040 /* update the attribute list
(inherit from left
== aft
) */
2041 delete_attribute_ref
(node_attr
(kern
));
2042 add_node_attr_ref
(node_attr
(aft
));
2043 node_attr
(kern
) = node_attr
(aft
);
2048 static void do_handle_kerning
(halfword root
, halfword init_left
, halfword init_right
)
2050 halfword cur
= vlink
(root
);
2051 halfword left
= null
;
2053 if
(init_left
!= null
&& init_right != null) {
2054 add_kern_after
(init_left
, init_right
, root
);
2055 tlink
(root
) = vlink
(root
);
2059 if
(type
(cur
) == glyph_node
) {
2061 if
(init_left
!= null
)
2062 add_kern_before
(init_left
, cur
);
2065 while
((cur
= vlink
(cur
)) != null
) {
2066 if
(type
(cur
) == glyph_node
) {
2069 add_kern_before
(left
, cur
);
2070 if
(character
(left
) < 0 || is_ghost
(left
)) {
2071 halfword prev
= alink
(left
);
2072 couple_nodes
(prev
, cur
);
2078 if
(type
(cur
) == disc_node
) {
2079 halfword right
= type
(vlink
(cur
)) == glyph_node ? vlink
(cur
) : null
;
2080 do_handle_kerning
(pre_break
(cur
), left
, null
);
2081 do_handle_kerning
(post_break
(cur
), null
, right
);
2082 if
(vlink_post_break
(cur
) != null
)
2083 tlink_post_break
(cur
) = tail_of_list
(vlink_post_break
(cur
));
2084 do_handle_kerning
(no_break
(cur
), left
, right
);
2085 if
(vlink_no_break
(cur
) != null
)
2086 tlink_no_break
(cur
) = tail_of_list
(vlink_no_break
(cur
)); /* needed?
*/
2089 if
(character
(left
) < 0 || is_ghost
(left
)) {
2090 halfword prev
= alink
(left
);
2091 couple_nodes
(prev
, cur
);
2099 if
(init_right
!= null
)
2100 add_kern_after
(left
, init_right
, left
);
2101 if
(character
(left
) < 0 || is_ghost
(left
)) {
2102 halfword prev
= alink
(left
);
2103 halfword next
= vlink
(left
);
2105 couple_nodes
(prev
, next
);
2107 } else if
(prev
!= root
) {
2119 halfword handle_kerning
(halfword head
, halfword tail
)
2122 save_link
= vlink
(tail
);
2125 do_handle_kerning
(head
, null
, null
);
2127 if
(valid_node
(save_link
)) {
2128 try_couple_nodes
(tail
, save_link
);
2133 @
* ligaturing and kerning
: lua-interface.
2136 static halfword run_lua_ligkern_callback
(halfword head
, halfword tail
, int callback_id
)
2138 lua_State
*L
= Luas
;
2140 int top
= lua_gettop
(L
);
2141 if
(!get_callback
(L
, callback_id
)) {
2145 nodelist_to_lua
(L
, head
);
2146 nodelist_to_lua
(L
, tail
);
2147 if
((i
=lua_pcall
(L
, 2, 0, 0)) != 0) {
2148 luatex_error
(L
, (i
== LUA_ERRRUN ?
0 : 1));
2151 fix_node_list
(head
);
2156 halfword new_ligkern
(halfword head
, halfword tail
)
2158 int callback_id
= 0;
2159 if
(vlink
(head
) == null
)
2161 callback_id
= callback_defined
(ligaturing_callback
);
2162 if
(callback_id
> 0) {
2163 tail
= run_lua_ligkern_callback
(head
, tail
, callback_id
);
2165 tail
= tail_of_list
(head
);
2166 } else if
(callback_id
== 0) {
2167 tail
= handle_ligaturing
(head
, tail
);
2169 callback_id
= callback_defined
(kerning_callback
);
2170 if
(callback_id
> 0) {
2171 tail
= run_lua_ligkern_callback
(head
, tail
, callback_id
);
2173 tail
= tail_of_list
(head
);
2175 } else if
(callback_id
== 0) {
2176 halfword nest1
= new_node
(nesting_node
, 1);
2177 halfword cur
= vlink
(head
);
2178 halfword aft
= vlink
(tail
);
2179 couple_nodes
(nest1
, cur
);
2180 tlink
(nest1
) = tail
;
2182 do_handle_kerning
(nest1
, null
, null
);
2183 couple_nodes
(head
, vlink
(nest1
));
2184 tail
= tlink
(nest1
);
2185 try_couple_nodes
(tail
, aft
);