1 /* lfontlib.c
2
3 Copyright 2006-2014 Taco Hoekwater <taco@luatex.org>
4
5 This file is part of LuaTeX.
6
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.
11
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.
16
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/>. */
19
20
21 #include "ptexlib.h"
22 #include "lua/luatex-api.h"
23
24 #define TIMERS 0
25
26 #if TIMERS
27 # include <sys/time.h>
28 #endif
29
get_fontid(void)30 static int get_fontid(void)
31 {
32 if (font_tables == NULL || font_tables[0] == NULL) {
33 create_null_font();
34 }
35 return new_font();
36 }
37
font_read_tfm(lua_State * L)38 static int font_read_tfm(lua_State * L)
39 {
40 internal_font_number f;
41 scaled s;
42 int k;
43 const char *cnom;
44 if (lua_isstring(L, 1)) {
45 cnom = lua_tostring(L, 1);
46 if (lua_isnumber(L, 2)) {
47 s = (int) lua_tonumber(L, 2);
48 if (strlen(cnom)) {
49 f = get_fontid();
50 if (read_tfm_info(f, cnom, s)) {
51 k = font_to_lua(L, f);
52 delete_font(f);
53 return k;
54 } else {
55 delete_font(f);
56 luaL_error(L, "font loading failed");
57 }
58 } else {
59 luaL_error(L, "expected tfm name as first argument");
60 }
61 } else {
62 luaL_error(L, "expected an integer size as second argument");
63 }
64 } else {
65 luaL_error(L, "expected tfm name as first argument");
66 }
67 return 2; /* not reached */
68 }
69
70
font_read_vf(lua_State * L)71 static int font_read_vf(lua_State * L)
72 {
73 int i;
74 const char *cnom;
75 if (lua_isstring(L, 1)) {
76 cnom = lua_tostring(L, 1);
77 if (strlen(cnom)) {
78 if (lua_isnumber(L, 2)) {
79 i = (int) lua_tonumber(L, 2);
80 return make_vf_table(L, cnom, (scaled) i);
81 } else {
82 luaL_error(L, "expected an integer size as second argument");
83 return 2;
84 }
85 }
86 }
87 luaL_error(L, "expected vf name as first argument");
88 return 2; /* not reached */
89 }
90
tex_current_font(lua_State * L)91 static int tex_current_font(lua_State * L)
92 {
93 int i;
94 i = (int) luaL_optinteger(L, 1, 0);
95 if (i > 0) {
96 if (is_valid_font(i)) {
97 zset_cur_font(i);
98 return 0;
99 } else {
100 luaL_error(L, "expected a valid font id");
101 return 2; /* not reached */
102 }
103 } else {
104 lua_pushnumber(L, get_cur_font());
105 return 1;
106 }
107 }
108
tex_max_font(lua_State * L)109 static int tex_max_font(lua_State * L)
110 {
111 lua_pushnumber(L, max_font_id());
112 return 1;
113 }
114
115
tex_each_font_next(lua_State * L)116 static int tex_each_font_next(lua_State * L)
117 {
118 int i, m; /* id */
119 m = (int) lua_tonumber(L, 1);
120 i = (int) lua_tonumber(L, 2);
121 i++;
122 while (i <= m && !is_valid_font(i))
123 i++;
124 if (i > m) {
125 lua_pushnil(L);
126 return 1;
127 } else {
128 lua_pushnumber(L, i);
129 if (!font_to_lua(L, i))
130 lua_pushnil(L);
131 return 2;
132 }
133 }
134
tex_each_font(lua_State * L)135 static int tex_each_font(lua_State * L)
136 {
137 lua_pushcclosure(L, tex_each_font_next, 0);
138 lua_pushnumber(L, max_font_id());
139 lua_pushnumber(L, 0);
140 return 3;
141 }
142
frozenfont(lua_State * L)143 static int frozenfont(lua_State * L)
144 {
145 int i;
146 i = (int) luaL_checkinteger(L, 1);
147 if (i) {
148 if (is_valid_font(i)) {
149 if (font_touched(i) || font_used(i)) {
150 lua_pushboolean(L, 1);
151 } else {
152 lua_pushboolean(L, 0);
153 }
154 } else {
155 lua_pushnil(L);
156 }
157 return 1;
158 } else {
159 luaL_error(L, "expected an integer argument");
160 }
161 return 0; /* not reached */
162 }
163
164
setfont(lua_State * L)165 static int setfont(lua_State * L)
166 {
167 int i;
168 i = (int) luaL_checkinteger(L, -2);
169 if (i) {
170 luaL_checktype(L, -1, LUA_TTABLE);
171 if (is_valid_font(i)) {
172 if (!(font_touched(i) || font_used(i))) {
173 font_from_lua(L, i);
174 } else {
175 luaL_error(L,
176 "that font has been accessed already, changing it is forbidden");
177 }
178 } else {
179 luaL_error(L, "that integer id is not a valid font");
180 }
181 }
182 return 0;
183 }
184
185
deffont(lua_State * L)186 static int deffont(lua_State * L)
187 {
188 int i;
189 #if TIMERS
190 struct timeval tva;
191 struct timeval tvb;
192 double tvdiff;
193 #endif
194 luaL_checktype(L, -1, LUA_TTABLE);
195 i = get_fontid();
196 #if TIMERS
197 gettimeofday(&tva, NULL);
198 #endif
199 if (font_from_lua(L, i)) {
200 #if TIMERS
201 gettimeofday(&tvb, NULL);
202 tvdiff = tvb.tv_sec * 1000000.0;
203 tvdiff += (double) tvb.tv_usec;
204 tvdiff -= (tva.tv_sec * 1000000.0);
205 tvdiff -= (double) tva.tv_usec;
206 tvdiff /= 1000000;
207 fprintf(stdout, "font.define(%s,%i): %f seconds\n",
208 font_fullname(i), i, tvdiff);
209 #endif
210 lua_pushnumber(L, i);
211 return 1;
212 } else {
213 lua_pop(L, 1); /* pop the broken table */
214 delete_font(i);
215 luaL_error(L, "font creation failed");
216 }
217 return 0; /* not reached */
218 }
219
220 /* this returns the expected (!) next fontid. */
nextfontid(lua_State * L)221 static int nextfontid(lua_State * L)
222 {
223 int i = get_fontid();
224 lua_pushnumber(L, i);
225 delete_font(i);
226 return 1;
227 }
228
229
getfont(lua_State * L)230 static int getfont(lua_State * L)
231 {
232 int i;
233 i = (int) luaL_checkinteger(L, -1);
234 if (i && is_valid_font(i) && font_to_lua(L, i))
235 return 1;
236 lua_pushnil(L);
237 return 1;
238 }
239
240
getfontid(lua_State * L)241 static int getfontid(lua_State * L)
242 {
243 const char *s;
244 size_t ff;
245 int cs;
246 int f;
247 if (lua_type(L, 1) == LUA_TSTRING) {
248 s = lua_tolstring(L, 1, &ff);
249 cs = string_lookup(s, ff);
250 if (cs == undefined_control_sequence || cs == undefined_cs_cmd
251 || eq_type(cs) != set_font_cmd) {
252 lua_pushstring(L, "not a valid font csname");
253 f = -1;
254 } else {
255 f = equiv(cs);
256 }
257 lua_pushnumber(L, f);
258 } else {
259 luaL_error(L, "expected font csname string as argument");
260 }
261 return 1;
262 }
263
264
265 static const struct luaL_Reg fontlib[] = {
266 {"read_tfm", font_read_tfm},
267 {"read_vf", font_read_vf},
268 {"current", tex_current_font},
269 {"max", tex_max_font},
270 {"each", tex_each_font},
271 {"getfont", getfont},
272 {"setfont", setfont},
273 {"define", deffont},
274 {"nextid", nextfontid},
275 {"id", getfontid},
276 {"frozen", frozenfont},
277 {NULL, NULL} /* sentinel */
278 };
279
luaopen_font(lua_State * L)280 int luaopen_font(lua_State * L)
281 {
282 luaL_register(L, "font", fontlib);
283 make_table(L, "fonts", "tex.fonts", "getfont", "setfont");
284 return 1;
285 }
286
287 /**********************************************************************/
288 /* "vf" library: Lua functions within virtual fonts */
289
l_vf_char(lua_State * L)290 static int l_vf_char(lua_State * L)
291 {
292 int k, w;
293 /*int ex = 0;*/ /* Wrong! TODO */
294 vf_struct *vsp = static_pdf->vfstruct;
295 packet_stack_record *mat_p;
296 internal_font_number lf = vsp->lf;
297 int ex_glyph = vsp->ex_glyph/1000;
298 if (!vsp->vflua)
299 pdf_error("vf", "vf.char() outside virtual font");
300 k = (int) luaL_checkinteger(L, 1);
301 if (!char_exists(lf, (int) k)) {
302 char_warning(lf, (int) k);
303 } else {
304 if (has_packet(lf, (int) k))
305 do_vf_packet(static_pdf, lf, (int) k, ex_glyph);
306 else
307 backend_out[glyph_node] (static_pdf, lf, (int) k, ex_glyph);
308 }
309 mat_p = &(vsp->packet_stack[vsp->packet_stack_level]);
310 w = char_width(lf, (int) k);
311 mat_p->pos.h += round_xn_over_d(w, 1000 + ex_glyph, 1000);
312 synch_pos_with_cur(static_pdf->posstruct, vsp->refpos, mat_p->pos);
313 return 0;
314 }
315
l_vf_down(lua_State * L)316 static int l_vf_down(lua_State * L)
317 {
318 scaled i;
319 vf_struct *vsp = static_pdf->vfstruct;
320 packet_stack_record *mat_p;
321 if (!vsp->vflua)
322 pdf_error("vf", "vf.down() outside virtual font");
323 i = (scaled) luaL_checkinteger(L, 1);
324 i = store_scaled_f(i, vsp->fs_f);
325 mat_p = &(vsp->packet_stack[vsp->packet_stack_level]);
326 mat_p->pos.v += i;
327 synch_pos_with_cur(static_pdf->posstruct, vsp->refpos, mat_p->pos);
328 return 0;
329 }
330
l_vf_fontid(lua_State * L)331 static int l_vf_fontid(lua_State * L)
332 {
333 vf_struct *vsp = static_pdf->vfstruct;
334 if (!vsp->vflua)
335 pdf_error("vf", "vf.fontid() outside virtual font");
336 vsp->lf = (int) luaL_checkinteger(L, 1);
337 return 0;
338 }
339
l_vf_image(lua_State * L)340 static int l_vf_image(lua_State * L)
341 {
342 int k;
343 vf_struct *vsp = static_pdf->vfstruct;
344 if (!vsp->vflua)
345 pdf_error("vf", "vf.image() outside virtual font");
346 k = (int) luaL_checkinteger(L, 1);
347 vf_out_image(static_pdf, k);
348 return 0;
349 }
350
l_vf_node(lua_State * L)351 static int l_vf_node(lua_State * L)
352 {
353 int k;
354 vf_struct *vsp = static_pdf->vfstruct;
355 if (!vsp->vflua)
356 pdf_error("vf", "vf.node() outside virtual font");
357 k = (int) luaL_checkinteger(L, 1);
358 hlist_out(static_pdf, (halfword) k);
359 return 0;
360 }
361
l_vf_nop(lua_State * L)362 static int l_vf_nop(lua_State * L)
363 {
364 vf_struct *vsp = static_pdf->vfstruct;
365 if (!vsp->vflua)
366 pdf_error("vf", "vf.nop() outside virtual font");
367 return 0;
368 }
369
l_vf_pop(lua_State * L)370 static int l_vf_pop(lua_State * L)
371 {
372 vf_struct *vsp = static_pdf->vfstruct;
373 packet_stack_record *mat_p;
374 if (!vsp->vflua)
375 pdf_error("vf", "vf.pop() outside virtual font");
376 if (vsp->packet_stack_level == vsp->packet_stack_minlevel)
377 pdf_error("vf", "packet_stack_level underflow");
378 vsp->packet_stack_level--;
379 mat_p = &(vsp->packet_stack[vsp->packet_stack_level]);
380 synch_pos_with_cur(static_pdf->posstruct, vsp->refpos, mat_p->pos);
381 return 0;
382 }
383
l_vf_push(lua_State * L)384 static int l_vf_push(lua_State * L)
385 {
386 vf_struct *vsp = static_pdf->vfstruct;
387 packet_stack_record *mat_p;
388 if (!vsp->vflua)
389 pdf_error("vf", "vf.push() outside virtual font");
390 mat_p = &(vsp->packet_stack[vsp->packet_stack_level]);
391 vsp->packet_stack_level++;
392 if (vsp->packet_stack_level == packet_stack_size)
393 pdf_error("vf", "packet_stack_level overflow");
394 vsp->packet_stack[vsp->packet_stack_level] = *mat_p;
395 mat_p = &(vsp->packet_stack[vsp->packet_stack_level]);
396 return 0;
397 }
398
l_vf_right(lua_State * L)399 static int l_vf_right(lua_State * L)
400 {
401 scaled i;
402 vf_struct *vsp = static_pdf->vfstruct;
403 packet_stack_record *mat_p;
404 if (!vsp->vflua)
405 pdf_error("vf", "vf.right() outside virtual font");
406 mat_p = &(vsp->packet_stack[vsp->packet_stack_level]);
407 i = (scaled) luaL_checkinteger(L, 1);
408 i = store_scaled_f(i, vsp->fs_f);
409 mat_p->pos.h += i;
410 synch_pos_with_cur(static_pdf->posstruct, vsp->refpos, mat_p->pos);
411 return 0;
412 }
413
l_vf_rule(lua_State * L)414 static int l_vf_rule(lua_State * L)
415 {
416 scaledpos size;
417 vf_struct *vsp = static_pdf->vfstruct;
418 packet_stack_record *mat_p;
419 if (!vsp->vflua)
420 pdf_error("vf", "vf.rule() outside virtual font");
421 size.h = (scaled) luaL_checkinteger(L, 1);
422 size.v = (scaled) luaL_checkinteger(L, 2);
423 size.h = store_scaled_f(size.h, vsp->fs_f);
424 size.v = store_scaled_f(size.v, vsp->fs_f);
425 if (size.h > 0 && size.v > 0)
426 pdf_place_rule(static_pdf, 0, size); /* the 0 is unused */
427 mat_p = &(vsp->packet_stack[vsp->packet_stack_level]);
428 mat_p->pos.h += size.h;
429 synch_pos_with_cur(static_pdf->posstruct, vsp->refpos, mat_p->pos);
430 return 0;
431 }
432
l_vf_special(lua_State * L)433 static int l_vf_special(lua_State * L)
434 {
435 const_lstring st;
436 int texstr;
437 vf_struct *vsp = static_pdf->vfstruct;
438 if (!vsp->vflua)
439 pdf_error("vf", "vf.special() outside virtual font");
440 st.s = lua_tolstring(L, 1, &(st.l));
441 texstr = maketexlstring(st.s, st.l);
442 pdf_literal(static_pdf, texstr, scan_special, false);
443 flush_str(texstr);
444 return 0;
445 }
446
447 static const struct luaL_Reg vflib[] = {
448 {"char", l_vf_char},
449 {"down", l_vf_down},
450 /* {"font", l_vf_font}, */
451 {"fontid", l_vf_fontid},
452 {"image", l_vf_image},
453 /* {"lua", l_vf_lua}, */
454 {"node", l_vf_node},
455 {"nop", l_vf_nop},
456 {"pop", l_vf_pop},
457 {"push", l_vf_push},
458 {"right", l_vf_right},
459 {"rule", l_vf_rule},
460 /* {"scale", l_vf_scale}, */
461 /* {"slot", l_vf_slot}, */
462 {"special", l_vf_special},
463 {NULL, NULL} /* sentinel */
464 };
465
luaopen_vf(lua_State * L)466 int luaopen_vf(lua_State * L)
467 {
468 luaL_register(L, "vf", vflib);
469 return 1;
470 }
471