/* lfontlib.c
Copyright 2006-2010 Taco Hoekwater <
[email protected]>
This file is part of LuaTeX.
LuaTeX is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
LuaTeX is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU General Public License along
with LuaTeX; if not, see <
http://www.gnu.org/licenses/>. */
#include "lua/luatex-api.h"
#include "ptexlib.h"
static const char _svn_version[] =
"$Id: lfontlib.c 3551 2010-03-26 14:43:50Z taco $ $URL:
http://foundry.supelec.fr/svn/luatex/tags/beta-0.70.1/source/texk/web2c/luatexdir/lua/lfontlib.c $";
#define TIMERS 0
#if TIMERS
# include <sys/time.h>
#endif
static int get_fontid(void)
{
if (font_tables == NULL || font_tables[0] == NULL) {
create_null_font();
}
return new_font();
}
static int font_read_tfm(lua_State * L)
{
internal_font_number f;
scaled s;
int k;
const char *cnom;
if (lua_isstring(L, 1)) {
cnom = lua_tostring(L, 1);
if (lua_isnumber(L, 2)) {
lua_number2int(s, lua_tonumber(L, 2));
if (strlen(cnom)) {
f = get_fontid();
if (read_tfm_info(f, cnom, s)) {
k = font_to_lua(L, f);
delete_font(f);
return k;
} else {
delete_font(f);
luaL_error(L, "font loading failed");
}
} else {
luaL_error(L, "expected tfm name as first argument");
}
} else {
luaL_error(L, "expected an integer size as second argument");
}
} else {
luaL_error(L, "expected tfm name as first argument");
}
return 2; /* not reached */
}
static int font_read_vf(lua_State * L)
{
int i;
const char *cnom;
if (lua_isstring(L, 1)) {
cnom = lua_tostring(L, 1);
if (strlen(cnom)) {
if (lua_isnumber(L, 2)) {
lua_number2int(i, lua_tonumber(L, 2));
return make_vf_table(L, cnom, (scaled) i);
} else {
luaL_error(L,
"expected an integer size as second argument");
return 2;
}
}
}
luaL_error(L, "expected vf name as first argument");
return 2; /* not reached */
}
static int tex_current_font(lua_State * L)
{
int i;
i = (int) luaL_optinteger(L, 1, 0);
if (i > 0) {
if (is_valid_font(i)) {
zset_cur_font(i);
return 0;
} else {
luaL_error(L, "expected a valid font id");
return 2; /* not reached */
}
} else {
lua_pushnumber(L, get_cur_font());
return 1;
}
}
static int tex_max_font(lua_State * L)
{
lua_pushnumber(L, max_font_id());
return 1;
}
static int tex_each_font_next(lua_State * L)
{
int i, m; /* id */
lua_number2int(m, lua_tonumber(L, 1));
lua_number2int(i, lua_tonumber(L, 2));
i++;
while (i <= m && !is_valid_font(i))
i++;
if (i > m) {
lua_pushnil(L);
return 1;
} else {
lua_pushnumber(L, i);
if (!font_to_lua(L, i))
lua_pushnil(L);
return 2;
}
}
static int tex_each_font(lua_State * L)
{
lua_pushcclosure(L, tex_each_font_next, 0);
lua_pushnumber(L, max_font_id());
lua_pushnumber(L, 0);
return 3;
}
static int frozenfont(lua_State * L)
{
int i;
i = (int) luaL_checkinteger(L, 1);
if (i) {
if (is_valid_font(i)) {
if (font_touched(i) || font_used(i)) {
lua_pushboolean(L, 1);
} else {
lua_pushboolean(L, 0);
}
} else {
lua_pushnil(L);
}
return 1;
} else {
luaL_error(L, "expected an integer argument");
}
return 0; /* not reached */
}
static int setfont(lua_State * L)
{
int i;
i = (int) luaL_checkinteger(L, -2);
if (i) {
luaL_checktype(L, -1, LUA_TTABLE);
if (is_valid_font(i)) {
if (!(font_touched(i) || font_used(i))) {
font_from_lua(L, i);
} else {
luaL_error(L,
"that font has been accessed already, changing it is forbidden");
}
} else {
luaL_error(L, "that integer id is not a valid font");
}
}
return 0;
}
static int deffont(lua_State * L)
{
int i;
#if TIMERS
struct timeval tva;
struct timeval tvb;
double tvdiff;
#endif
luaL_checktype(L, -1, LUA_TTABLE);
i = get_fontid();
#if TIMERS
gettimeofday(&tva, NULL);
#endif
if (font_from_lua(L, i)) {
#if TIMERS
gettimeofday(&tvb, NULL);
tvdiff = tvb.tv_sec * 1000000.0;
tvdiff += (double) tvb.tv_usec;
tvdiff -= (tva.tv_sec * 1000000.0);
tvdiff -= (double) tva.tv_usec;
tvdiff /= 1000000;
fprintf(stdout, "font.define(%s,%i): %f seconds\n",
font_fullname(i), i, tvdiff);
#endif
lua_pushnumber(L, i);
return 1;
} else {
lua_pop(L, 1); /* pop the broken table */
delete_font(i);
luaL_error(L, "font creation failed");
}
return 0; /* not reached */
}
/* this returns the expected (!) next fontid. */
static int nextfontid(lua_State * L)
{
int i = get_fontid();
lua_pushnumber(L, i);
delete_font(i);
return 1;
}
static int getfont(lua_State * L)
{
int i;
i = (int) luaL_checkinteger(L, -1);
if (i && is_valid_font(i) && font_to_lua(L, i))
return 1;
lua_pushnil(L);
return 1;
}
static int getfontid(lua_State * L)
{
const char *s;
size_t ff;
int cur_cs;
int f;
if (lua_type(L, 1) == LUA_TSTRING) {
s = lua_tolstring(L, 1, &ff);
cur_cs = string_lookup(s, ff);
if (cur_cs == undefined_control_sequence || cur_cs == undefined_cs_cmd
|| eq_type(cur_cs) != set_font_cmd) {
lua_pushstring(L, "not a valid font csname");
f = -1;
} else {
f = equiv(cur_cs);
}
lua_pushnumber(L, f);
} else {
luaL_error(L, "expected font csname string as argument");
}
return 1;
}
static const struct luaL_reg fontlib[] = {
{"read_tfm", font_read_tfm},
{"read_vf", font_read_vf},
{"current", tex_current_font},
{"max", tex_max_font},
{"each", tex_each_font},
{"getfont", getfont},
{"setfont", setfont},
{"define", deffont},
{"nextid", nextfontid},
{"id", getfontid},
{"frozen", frozenfont},
{NULL, NULL} /* sentinel */
};
int luaopen_font(lua_State * L)
{
luaL_register(L, "font", fontlib);
make_table(L, "fonts", "getfont", "setfont");
return 1;
}