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