summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/font/texfont.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/font/texfont.c')
-rw-r--r--Build/source/texk/web2c/luatexdir/font/texfont.c1954
1 files changed, 1954 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/font/texfont.c b/Build/source/texk/web2c/luatexdir/font/texfont.c
new file mode 100644
index 00000000000..0134243d929
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/texfont.c
@@ -0,0 +1,1954 @@
+/*
+
+Copyright 2006-2013 Taco Hoekwater <taco@luatex.org>
+
+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/>.
+
+*/
+
+/*tex
+
+ Here is the main font API implementation for the original pascal parts. Stuff
+ to watch out for:
+
+ \startitemize
+
+ \startitem
+ Knuth had a |'null_character'| that was used when a character could
+ not be found by the |fetch()| routine, to signal an error. This has
+ been deleted, but it may mean that the output of luatex is
+ incompatible with TeX after |fetch()| has detected an error
+ condition.
+ \stopitem
+
+ \startitem
+ Knuth also had a |font_glue()| optimization. I've removed that
+ because it was a bit of dirty programming and it also was problematic
+ |if 0 != null|.
+ \stopitem
+
+ \stopitemize
+
+*/
+
+#include "ptexlib.h"
+#include "lua/luatex-api.h"
+
+#define noDEBUG
+
+#define proper_char_index(c) (c<=font_ec(f) && c>=font_bc(f))
+#define do_realloc(a,b,d) a = xrealloc(a,(unsigned)((unsigned)(b)*sizeof(d)))
+
+texfont **font_tables = NULL;
+
+static int font_arr_max = 0;
+static int font_id_maxval = 0;
+
+static void grow_font_table(int id)
+{
+ int j;
+ if (id >= font_arr_max) {
+ font_bytes +=
+ (int) (((id + 8 - font_arr_max) * (int) sizeof(texfont *)));
+ font_tables =
+ xrealloc(font_tables,
+ (unsigned) (((unsigned) id + 8) * sizeof(texfont *)));
+ j = 8;
+ while (j--) {
+ font_tables[id + j] = NULL;
+ }
+ font_arr_max = id + 8;
+ }
+}
+
+int new_font_id(void)
+{
+ int i;
+ for (i = 0; i < font_arr_max; i++) {
+ if (font_tables[i] == NULL) {
+ break;
+ }
+ }
+ if (i >= font_arr_max)
+ grow_font_table(i);
+ if (i > font_id_maxval)
+ font_id_maxval = i;
+ return i;
+}
+
+int max_font_id(void)
+{
+ return font_id_maxval;
+}
+
+void set_max_font_id(int i)
+{
+ font_id_maxval = i;
+}
+
+int new_font(void)
+{
+ int k;
+ int id;
+ charinfo *ci;
+ sa_tree_item sa_value = { 0 };
+ id = new_font_id();
+ font_bytes += (int) sizeof(texfont);
+ /*tex Most stuff is zero */
+ font_tables[id] = xcalloc(1, sizeof(texfont));
+ font_tables[id]->_font_name = NULL;
+ font_tables[id]->_font_area = NULL;
+ font_tables[id]->_font_filename = NULL;
+ font_tables[id]->_font_fullname = NULL;
+ font_tables[id]->_font_psname = NULL;
+ font_tables[id]->_font_encodingname = NULL;
+ font_tables[id]->_font_cidregistry = NULL;
+ font_tables[id]->_font_cidordering = NULL;
+ font_tables[id]->_left_boundary = NULL;
+ font_tables[id]->_right_boundary = NULL;
+ font_tables[id]->_param_base = NULL;
+ font_tables[id]->_math_param_base = NULL;
+ /*tex |ec = 0| */
+ set_font_bc(id, 1);
+ set_font_writingmode(id, 0);
+ set_font_identity(id, 0);
+ /* set_font_encoding_bytes(id,1) */ /* ? */
+ set_font_subfont(id, 0);
+ set_hyphen_char(id, '-');
+ set_skew_char(id, -1);
+ /*tex vertical */
+ font_slant(id) = 0;
+ /*tex normal width */
+ font_extend(id) = 1000;
+ /*tex normal height */
+ font_squeeze(id) = 1000;
+ font_width(id) = 0;
+ font_mode(id) = 0;
+ /*tex allocate eight values including 0 */
+ set_font_params(id, 7);
+ for (k = 0; k <= 7; k++) {
+ set_font_param(id, k, 0);
+ }
+ /*tex character info zero is reserved for |notdef|. The stack size 1, default item value 0. */
+ font_tables[id]->_characters = new_sa_tree(1, 1, sa_value);
+ ci = xcalloc(1, sizeof(charinfo));
+ set_charinfo_name(ci, xstrdup(".notdef"));
+ font_tables[id]->_charinfo = ci;
+ font_tables[id]->_charinfo_size = 1;
+ return id;
+}
+
+void font_malloc_charinfo(internal_font_number f, int num)
+{
+ int glyph = font_tables[f]->_charinfo_size;
+ font_bytes += (int) (num * (int) sizeof(charinfo));
+ do_realloc(font_tables[f]->_charinfo, (unsigned) (glyph + num), charinfo);
+ memset(&(font_tables[f]->_charinfo[glyph]), 0, (size_t) (num * (int) sizeof(charinfo)));
+ font_tables[f]->_charinfo_size += num;
+}
+
+#define find_charinfo_id(f,c) (get_sa_item(font_tables[f]->_characters,c).int_value)
+
+charinfo *get_charinfo(internal_font_number f, int c)
+{
+ int glyph;
+ charinfo *ci;
+ if (proper_char_index(c)) {
+ glyph = get_sa_item(font_tables[f]->_characters, c).int_value;
+ if (!glyph) {
+ sa_tree_item sa_value = { 0 };
+ int tglyph = ++font_tables[f]->_charinfo_count;
+ if (tglyph >= font_tables[f]->_charinfo_size) {
+ font_malloc_charinfo(f, 256);
+ }
+ font_tables[f]->_charinfo[tglyph].ef = 1000;
+ sa_value.int_value = tglyph;
+ /*tex 1 means global */
+ set_sa_item(font_tables[f]->_characters, c, sa_value, 1);
+ glyph = tglyph;
+ }
+ return &(font_tables[f]->_charinfo[glyph]);
+ } else if (c == left_boundarychar) {
+ if (left_boundary(f) == NULL) {
+ ci = xcalloc(1, sizeof(charinfo));
+ font_bytes += (int) sizeof(charinfo);
+ set_left_boundary(f, ci);
+ }
+ return left_boundary(f);
+ } else if (c == right_boundarychar) {
+ if (right_boundary(f) == NULL) {
+ ci = xcalloc(1, sizeof(charinfo));
+ font_bytes += (int) sizeof(charinfo);
+ set_right_boundary(f, ci);
+ }
+ return right_boundary(f);
+ }
+ return &(font_tables[f]->_charinfo[0]);
+}
+
+static void set_charinfo(internal_font_number f, int c, charinfo * ci)
+{
+ int glyph;
+ if (proper_char_index(c)) {
+ glyph = get_sa_item(font_tables[f]->_characters, c).int_value;
+ if (glyph) {
+ font_tables[f]->_charinfo[glyph] = *ci;
+ } else {
+ normal_error("font","character insertion failed");
+ }
+ } else if (c == left_boundarychar) {
+ set_left_boundary(f, ci);
+ } else if (c == right_boundarychar) {
+ set_right_boundary(f, ci);
+ }
+}
+
+charinfo *copy_charinfo(charinfo * ci)
+{
+ int x, k;
+ kerninfo *kern;
+ liginfo *lig;
+ eight_bits *packet;
+ charinfo *co = NULL;
+ if (ci == NULL)
+ return NULL;
+ co = xmalloc(sizeof(charinfo));
+ memcpy(co, ci, sizeof(charinfo));
+ set_charinfo_used(co, false);
+ co->name = NULL;
+ co->tounicode = NULL;
+ co->packets = NULL;
+ co->ligatures = NULL;
+ co->kerns = NULL;
+ co->vert_variants = NULL;
+ co->hor_variants = NULL;
+ if (ci->name != NULL) {
+ co->name = xstrdup(ci->name);
+ }
+ if (ci->tounicode != NULL) {
+ co->tounicode = xstrdup(ci->tounicode);
+ }
+ /*tex Kerns */
+ if ((kern = get_charinfo_kerns(ci)) != NULL) {
+ x = 0;
+ while (!kern_end(kern[x])) {
+ x++;
+ }
+ x++;
+ co->kerns = xmalloc((unsigned) (x * (int) sizeof(kerninfo)));
+ memcpy(co->kerns, ci->kerns, (size_t) (x * (int) sizeof(kerninfo)));
+ }
+ /*tex Ligatures */
+ if ((lig = get_charinfo_ligatures(ci)) != NULL) {
+ x = 0;
+ while (!lig_end(lig[x])) {
+ x++;
+ }
+ x++;
+ co->ligatures = xmalloc((unsigned) (x * (int) sizeof(liginfo)));
+ memcpy(co->ligatures, ci->ligatures,
+ (size_t) (x * (int) sizeof(liginfo)));
+ }
+ /*tex Packets */
+ if ((packet = get_charinfo_packets(ci)) != NULL) {
+ x = vf_packet_bytes(ci);
+ co->packets = xmalloc((unsigned) x);
+ memcpy(co->packets, ci->packets, (size_t) x);
+ }
+ /*tex Horizontal and vertical extenders */
+ if (get_charinfo_vert_variants(ci) != NULL) {
+ set_charinfo_vert_variants(co, copy_variants(get_charinfo_vert_variants(ci)));
+ }
+ if (get_charinfo_hor_variants(ci) != NULL) {
+ set_charinfo_hor_variants(co, copy_variants(get_charinfo_hor_variants(ci)));
+ }
+ x = ci->top_left_math_kerns;
+ co->top_left_math_kerns = x;
+ if (x > 0) {
+ co->top_left_math_kern_array = xmalloc((unsigned) (2 * (int) sizeof(scaled) * x));
+ for (k = 0; k < co->top_left_math_kerns; k++) {
+ co->top_left_math_kern_array[(2 * k)] = ci->top_left_math_kern_array[(2 * k)];
+ co->top_left_math_kern_array[(2 * k) + 1] = ci->top_left_math_kern_array[(2 * k) + 1];
+ }
+ }
+ x = ci->bottom_left_math_kerns;
+ co->bottom_left_math_kerns = x;
+ if (x > 0) {
+ co->bottom_left_math_kern_array = xmalloc((unsigned) (2 * (int) sizeof(scaled) * x));
+ for (k = 0; k < co->bottom_left_math_kerns; k++) {
+ co->bottom_left_math_kern_array[(2 * k)] = ci->bottom_left_math_kern_array[(2 * k)];
+ co->bottom_left_math_kern_array[(2 * k) + 1] = ci->bottom_left_math_kern_array[(2 * k) + 1];
+ }
+ }
+ x = ci->top_right_math_kerns;
+ co->top_right_math_kerns = x;
+ if (x > 0) {
+ co->top_right_math_kern_array = xmalloc((unsigned) (2 * (int) sizeof(scaled) * x));
+ for (k = 0; k < co->top_right_math_kerns; k++) {
+ co->top_right_math_kern_array[(2 * k)] = ci->top_right_math_kern_array[(2 * k)];
+ co->top_right_math_kern_array[(2 * k) + 1] = ci->top_right_math_kern_array[(2 * k) + 1];
+ }
+ }
+ x = ci->bottom_right_math_kerns;
+ co->bottom_right_math_kerns = x;
+ if (x > 0) {
+ co->bottom_right_math_kern_array = xmalloc((unsigned) (2 * (int) sizeof(scaled) * x));
+ for (k = 0; k < co->bottom_right_math_kerns; k++) {
+ co->bottom_right_math_kern_array[(2 * k)] = ci->bottom_right_math_kern_array[(2 * k)];
+ co->bottom_right_math_kern_array[(2 * k) + 1] = ci->bottom_right_math_kern_array[(2 * k) + 1];
+ }
+ }
+ return co;
+}
+
+charinfo *char_info(internal_font_number f, int c)
+{
+ if (f > font_id_maxval)
+ return 0;
+ if (proper_char_index(c)) {
+ register int glyph = (int) find_charinfo_id(f, c);
+ return &(font_tables[f]->_charinfo[glyph]);
+ } else if (c == left_boundarychar && left_boundary(f) != NULL) {
+ return left_boundary(f);
+ } else if (c == right_boundarychar && right_boundary(f) != NULL) {
+ return right_boundary(f);
+ }
+ return &(font_tables[f]->_charinfo[0]);
+}
+
+scaled_whd get_charinfo_whd(internal_font_number f, int c)
+{
+ scaled_whd s;
+ charinfo *i;
+ i = char_info(f, c);
+ s.wd = i->width;
+ s.dp = i->depth;
+ s.ht = i->height;
+ return s;
+}
+
+int char_exists(internal_font_number f, int c)
+{
+ if (f > font_id_maxval)
+ return 0;
+ if (proper_char_index(c)) {
+ return (int) find_charinfo_id(f, c);
+ } else if ((c == left_boundarychar) && has_left_boundary(f)) {
+ return 1;
+ } else if ((c == right_boundarychar) && has_right_boundary(f)) {
+ return 1;
+ }
+ return 0;
+}
+
+int lua_glyph_not_found_callback(internal_font_number f, int c)
+{
+ int callback_id;
+ int ret = 0;
+ int top, i;
+ callback_id = callback_defined(glyph_not_found_callback);
+ if (callback_id != 0) {
+ top = lua_gettop(Luas);
+ if (!get_callback(Luas, callback_id)) {
+ lua_settop(Luas, top);
+ return 0;
+ }
+ lua_pushinteger(Luas, f);
+ lua_pushinteger(Luas, c);
+ if ((i=lua_pcall(Luas, 2, 1, 0)) != 0) {
+ formatted_warning ("glyph not found", "error: %s", lua_tostring(Luas, -1));
+ lua_settop(Luas, top);
+ luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1));
+ } else {
+ ret = lua_toboolean(Luas, -1);
+ }
+ lua_settop(Luas, top);
+ } else {
+ char_warning(f,c);
+ }
+ return ret;
+}
+
+extinfo *new_variant(int glyph, int startconnect, int endconnect, int advance, int repeater)
+{
+ extinfo *ext;
+ ext = xmalloc(sizeof(extinfo));
+ ext->next = NULL;
+ ext->glyph = glyph;
+ ext->start_overlap = startconnect;
+ ext->end_overlap = endconnect;
+ ext->advance = advance;
+ ext->extender = repeater;
+ return ext;
+}
+
+static extinfo *copy_variant(extinfo * old)
+{
+ extinfo *ext;
+ ext = xmalloc(sizeof(extinfo));
+ ext->next = NULL;
+ ext->glyph = old->glyph;
+ ext->start_overlap = old->start_overlap;
+ ext->end_overlap = old->end_overlap;
+ ext->advance = old->advance;
+ ext->extender = old->extender;
+ return ext;
+}
+
+static void dump_variant(extinfo * ext)
+{
+ dump_int(ext->glyph);
+ dump_int(ext->start_overlap);
+ dump_int(ext->end_overlap);
+ dump_int(ext->advance);
+ dump_int(ext->extender);
+ return;
+}
+
+static extinfo *undump_variant(void)
+{
+ int x;
+ extinfo *ext;
+ undump_int(x);
+ if (x == 0)
+ return NULL;
+ ext = xmalloc(sizeof(extinfo));
+ ext->next = NULL;
+ ext->glyph = x;
+ undump_int(x);
+ ext->start_overlap = x;
+ undump_int(x);
+ ext->end_overlap = x;
+ undump_int(x);
+ ext->advance = x;
+ undump_int(x);
+ ext->extender = x;
+ return ext;
+}
+
+void add_charinfo_vert_variant(charinfo * ci, extinfo * ext)
+{
+ if (ci->vert_variants == NULL) {
+ ci->vert_variants = ext;
+ } else {
+ extinfo *lst = ci->vert_variants;
+ while (lst->next != NULL)
+ lst = lst->next;
+ lst->next = ext;
+ }
+
+}
+
+void add_charinfo_hor_variant(charinfo * ci, extinfo * ext)
+{
+ if (ci->hor_variants == NULL) {
+ ci->hor_variants = ext;
+ } else {
+ extinfo *lst = ci->hor_variants;
+ while (lst->next != NULL)
+ lst = lst->next;
+ lst->next = ext;
+ }
+
+}
+
+extinfo *copy_variants(extinfo * o)
+{
+ extinfo *c, *t = NULL, *h = NULL;
+ while (o != NULL) {
+ c = copy_variant(o);
+ if (h == null)
+ h = c;
+ else
+ t->next = c;
+ t = c;
+ o = o->next;
+ }
+
+ return h;
+}
+
+static void dump_charinfo_variants(extinfo * o)
+{
+ while (o != NULL) {
+ dump_variant(o);
+ o = o->next;
+ }
+ dump_int(0);
+ return;
+}
+
+static extinfo *undump_charinfo_variants(void)
+{
+ extinfo *c, *t = NULL, *h = NULL;
+ c = undump_variant();
+ while (c != NULL) {
+ if (h == null)
+ h = c;
+ else
+ t->next = c;
+ t = c;
+ c = undump_variant();
+ }
+ return h;
+}
+
+
+/*tex
+
+ Note that many more small things like this are implemented as macros in the
+ header file.
+*/
+
+void set_charinfo_width(charinfo * ci, scaled val)
+{
+ ci->width = val;
+}
+
+void set_charinfo_height(charinfo * ci, scaled val)
+{
+ ci->height = val;
+}
+
+void set_charinfo_depth(charinfo * ci, scaled val)
+{
+ ci->depth = val;
+}
+
+void set_charinfo_italic(charinfo * ci, scaled val)
+{
+ ci->italic = val;
+}
+
+void set_charinfo_vert_italic(charinfo * ci, scaled val)
+{
+ ci->vert_italic = val;
+}
+
+void set_charinfo_top_accent(charinfo * ci, scaled val)
+{
+ ci->top_accent = val;
+}
+
+void set_charinfo_bot_accent(charinfo * ci, scaled val)
+{
+ ci->bot_accent = val;
+}
+
+void set_charinfo_tag(charinfo * ci, scaled val)
+{
+ ci->tag = (char) val;
+}
+
+void set_charinfo_remainder(charinfo * ci, scaled val)
+{
+ ci->remainder = val;
+}
+
+void set_charinfo_used(charinfo * ci, scaled val)
+{
+ ci->used = (char) val;
+}
+
+void set_charinfo_index(charinfo * ci, scaled val)
+{
+ ci->index = (unsigned short) val;
+}
+
+void set_charinfo_name(charinfo * ci, char *val)
+{
+ xfree(ci->name);
+ ci->name = val;
+}
+
+void set_charinfo_tounicode(charinfo * ci, char *val)
+{
+ xfree(ci->tounicode);
+ ci->tounicode = val;
+}
+
+void set_charinfo_ligatures(charinfo * ci, liginfo * val)
+{
+ dxfree(ci->ligatures, val);
+}
+
+void set_charinfo_kerns(charinfo * ci, kerninfo * val)
+{
+ dxfree(ci->kerns, val);
+}
+
+void set_charinfo_packets(charinfo * ci, eight_bits * val)
+{
+ dxfree(ci->packets, val);
+}
+
+void set_charinfo_ef(charinfo * ci, scaled val)
+{
+ ci->ef = val;
+}
+
+void set_charinfo_lp(charinfo * ci, scaled val)
+{
+ ci->lp = val;
+}
+
+void set_charinfo_rp(charinfo * ci, scaled val)
+{
+ ci->rp = val;
+}
+
+void set_charinfo_vert_variants(charinfo * ci, extinfo * ext)
+{
+ extinfo *c, *lst;
+ if (ci->vert_variants != NULL) {
+ lst = ci->vert_variants;
+ while (lst != NULL) {
+ c = lst->next;
+ free(lst);
+ lst = c;
+ }
+ }
+ ci->vert_variants = ext;
+}
+
+void set_charinfo_hor_variants(charinfo * ci, extinfo * ext)
+{
+ extinfo *c, *lst;
+ if (ci->hor_variants != NULL) {
+ lst = ci->hor_variants;
+ while (lst != NULL) {
+ c = lst->next;
+ free(lst);
+ lst = c;
+ }
+ }
+ ci->hor_variants = ext;
+
+}
+
+int get_charinfo_math_kerns(charinfo * ci, int id)
+{
+ /*tex All callers check for |result>0|. */
+ int k = 0;
+ if (id == top_left_kern) {
+ k = ci->top_left_math_kerns;
+ } else if (id == bottom_left_kern) {
+ k = ci->bottom_left_math_kerns;
+ } else if (id == top_right_kern) {
+ k = ci->top_right_math_kerns;
+ } else if (id == bottom_right_kern) {
+ k = ci->bottom_right_math_kerns;
+ } else {
+ confusion("get_charinfo_math_kerns");
+ }
+ return k;
+}
+
+void add_charinfo_math_kern(charinfo * ci, int id, scaled ht, scaled krn)
+{
+ int k;
+ if (id == top_left_kern) {
+ k = ci->top_left_math_kerns;
+ do_realloc(ci->top_left_math_kern_array, ((k + 1) * 2), sizeof(scaled));
+ ci->top_left_math_kern_array[(2 * (k))] = ht;
+ ci->top_left_math_kern_array[((2 * (k)) + 1)] = krn;
+ ci->top_left_math_kerns++;
+ } else if (id == bottom_left_kern) {
+ k = ci->bottom_left_math_kerns;
+ do_realloc(ci->bottom_left_math_kern_array, ((k + 1) * 2), sizeof(scaled));
+ ci->bottom_left_math_kern_array[(2 * (k))] = ht;
+ ci->bottom_left_math_kern_array[(2 * (k)) + 1] = krn;
+ ci->bottom_left_math_kerns++;
+ } else if (id == top_right_kern) {
+ k = ci->top_right_math_kerns;
+ do_realloc(ci->top_right_math_kern_array, ((k + 1) * 2), sizeof(scaled));
+ ci->top_right_math_kern_array[(2 * (k))] = ht;
+ ci->top_right_math_kern_array[(2 * (k)) + 1] = krn;
+ ci->top_right_math_kerns++;
+ } else if (id == bottom_right_kern) {
+ k = ci->bottom_right_math_kerns;
+ do_realloc(ci->bottom_right_math_kern_array, ((k + 1) * 2), sizeof(scaled));
+ ci->bottom_right_math_kern_array[(2 * (k))] = ht;
+ ci->bottom_right_math_kern_array[(2 * (k)) + 1] = krn;
+ ci->bottom_right_math_kerns++;
+ } else {
+ confusion("add_charinfo_math_kern");
+ }
+}
+
+static void dump_math_kerns(charinfo * ci)
+{
+ int k, l;
+ l = ci->top_left_math_kerns;
+ dump_int(l);
+ for (k = 0; k < l; k++) {
+ dump_int(ci->top_left_math_kern_array[(2 * k)]);
+ dump_int(ci->top_left_math_kern_array[(2 * k) + 1]);
+ }
+ l = ci->bottom_left_math_kerns;
+ dump_int(l);
+ for (k = 0; k < l; k++) {
+ dump_int(ci->bottom_left_math_kern_array[(2 * k)]);
+ dump_int(ci->bottom_left_math_kern_array[(2 * k) + 1]);
+ }
+ l = ci->top_right_math_kerns;
+ dump_int(l);
+ for (k = 0; k < l; k++) {
+ dump_int(ci->top_right_math_kern_array[(2 * k)]);
+ dump_int(ci->top_right_math_kern_array[(2 * k) + 1]);
+ }
+ l = ci->bottom_right_math_kerns;
+ dump_int(l);
+ for (k = 0; k < l; k++) {
+ dump_int(ci->bottom_right_math_kern_array[(2 * k)]);
+ dump_int(ci->bottom_right_math_kern_array[(2 * k) + 1]);
+ }
+}
+
+static void undump_math_kerns(charinfo * ci)
+{
+ int k, x;
+ undump_int(x);
+ ci->top_left_math_kerns = x;
+ if (x > 0)
+ ci->top_left_math_kern_array = xmalloc((unsigned) (2 * (int) sizeof(scaled) * x));
+ for (k = 0; k < ci->top_left_math_kerns; k++) {
+ undump_int(x);
+ ci->top_left_math_kern_array[(2 * k)] = (scaled) x;
+ undump_int(x);
+ ci->top_left_math_kern_array[(2 * k) + 1] = (scaled) x;
+ }
+ undump_int(x);
+ ci->bottom_left_math_kerns = x;
+ if (x > 0)
+ ci->bottom_left_math_kern_array = xmalloc((unsigned) (2 * (int) sizeof(scaled) * x));
+ for (k = 0; k < ci->bottom_left_math_kerns; k++) {
+ undump_int(x);
+ ci->bottom_left_math_kern_array[(2 * k)] = (scaled) x;
+ undump_int(x);
+ ci->bottom_left_math_kern_array[(2 * k) + 1] = (scaled) x;
+ }
+ undump_int(x);
+ ci->top_right_math_kerns = x;
+ if (x > 0)
+ ci->top_right_math_kern_array = xmalloc((unsigned) (2 * (int) sizeof(scaled) * x));
+ for (k = 0; k < ci->top_right_math_kerns; k++) {
+ undump_int(x);
+ ci->top_right_math_kern_array[(2 * k)] = (scaled) x;
+ undump_int(x);
+ ci->top_right_math_kern_array[(2 * k) + 1] = (scaled) x;
+ }
+ undump_int(x);
+ ci->bottom_right_math_kerns = x;
+ if (x > 0)
+ ci->bottom_right_math_kern_array = xmalloc((unsigned) (2 * (int) sizeof(scaled) * x));
+ for (k = 0; k < ci->bottom_right_math_kerns; k++) {
+ undump_int(x);
+ ci->bottom_right_math_kern_array[(2 * k)] = (scaled) x;
+ undump_int(x);
+ ci->bottom_right_math_kern_array[(2 * k) + 1] = (scaled) x;
+ }
+}
+
+/*tex
+
+ In TeX, extensibles were fairly simple things. This function squeezes a TFM
+ extensible into the vertical extender structures. |advance==0| is a special
+ case for TFM fonts, because finding the proper advance width during tfm
+ reading can be tricky.
+
+ A small complication arises if |rep| is the only non-zero: it needs to be
+ doubled as a non-repeatable to avoid mayhem.
+
+*/
+
+void set_charinfo_extensible(charinfo * ci, int top, int bot, int mid, int rep)
+{
+ extinfo *ext;
+ /*tex Clear old data: */
+ set_charinfo_vert_variants(ci, NULL);
+ if (bot == 0 && top == 0 && mid == 0 && rep != 0) {
+ ext = new_variant(rep, 0, 0, 0, EXT_NORMAL);
+ add_charinfo_vert_variant(ci, ext);
+ ext = new_variant(rep, 0, 0, 0, EXT_REPEAT);
+ add_charinfo_vert_variant(ci, ext);
+ return;
+ }
+ if (bot != 0) {
+ ext = new_variant(bot, 0, 0, 0, EXT_NORMAL);
+ add_charinfo_vert_variant(ci, ext);
+ }
+ if (rep != 0) {
+ ext = new_variant(rep, 0, 0, 0, EXT_REPEAT);
+ add_charinfo_vert_variant(ci, ext);
+ }
+ if (mid != 0) {
+ ext = new_variant(mid, 0, 0, 0, EXT_NORMAL);
+ add_charinfo_vert_variant(ci, ext);
+ if (rep != 0) {
+ ext = new_variant(rep, 0, 0, 0, EXT_REPEAT);
+ add_charinfo_vert_variant(ci, ext);
+ }
+ }
+ if (top != 0) {
+ ext = new_variant(top, 0, 0, 0, EXT_NORMAL);
+ add_charinfo_vert_variant(ci, ext);
+ }
+}
+
+/*tex
+
+ Note that many more simple things like this are implemented as macros in the
+ header file.
+
+*/
+
+scaled get_charinfo_width(charinfo * ci)
+{
+ return ci->width;
+}
+
+scaled get_charinfo_height(charinfo * ci)
+{
+ return ci->height;
+}
+
+scaled get_charinfo_depth(charinfo * ci)
+{
+ return ci->depth;
+}
+
+scaled get_charinfo_italic(charinfo * ci)
+{
+ return ci->italic;
+}
+
+scaled get_charinfo_vert_italic(charinfo * ci)
+{
+ return ci->vert_italic;
+}
+
+scaled get_charinfo_top_accent(charinfo * ci)
+{
+ return ci->top_accent;
+}
+
+scaled get_charinfo_bot_accent(charinfo * ci)
+{
+ return ci->bot_accent;
+}
+
+char get_charinfo_tag(charinfo * ci)
+{
+ return ci->tag;
+}
+
+int get_charinfo_remainder(charinfo * ci)
+{
+ return ci->remainder;
+}
+
+char get_charinfo_used(charinfo * ci)
+{
+ return ci->used;
+}
+
+int get_charinfo_index(charinfo * ci)
+{
+ return ci->index;
+}
+
+char *get_charinfo_name(charinfo * ci)
+{
+ return ci->name;
+}
+
+char *get_charinfo_tounicode(charinfo * ci)
+{
+ return ci->tounicode;
+}
+
+liginfo *get_charinfo_ligatures(charinfo * ci)
+{
+ return ci->ligatures;
+}
+
+kerninfo *get_charinfo_kerns(charinfo * ci)
+{
+ return ci->kerns;
+}
+
+eight_bits *get_charinfo_packets(charinfo * ci)
+{
+ return ci->packets;
+}
+
+int get_charinfo_ef(charinfo * ci)
+{
+ return ci->ef;
+}
+
+int get_charinfo_rp(charinfo * ci)
+{
+ return ci->rp;
+}
+
+int get_charinfo_lp(charinfo * ci)
+{
+ return ci->lp;
+}
+
+extinfo *get_charinfo_vert_variants(charinfo * ci)
+{
+ extinfo *w = NULL;
+ if (ci->vert_variants != NULL)
+ w = ci->vert_variants;
+ return w;
+}
+
+extinfo *get_charinfo_hor_variants(charinfo * ci)
+{
+ extinfo *w = NULL;
+ if (ci->hor_variants != NULL)
+ w = ci->hor_variants;
+ return w;
+}
+
+
+scaled char_width(internal_font_number f, int c)
+{
+ charinfo *ci = char_info(f, c);
+ scaled w = get_charinfo_width(ci);
+ return w;
+}
+
+scaled calc_char_width(internal_font_number f, int c, int ex)
+{
+ charinfo *ci = char_info(f, c);
+ scaled w = get_charinfo_width(ci);
+ if (ex != 0)
+ w = round_xn_over_d(w, 1000 + ex, 1000);
+ return w;
+}
+
+scaled char_depth(internal_font_number f, int c)
+{
+ charinfo *ci = char_info(f, c);
+ scaled d = get_charinfo_depth(ci);
+ return d;
+}
+
+scaled char_height(internal_font_number f, int c)
+{
+ charinfo *ci = char_info(f, c);
+ scaled h = get_charinfo_height(ci);
+ return h;
+}
+
+scaled char_italic(internal_font_number f, int c)
+{
+ charinfo *ci = char_info(f, c);
+ scaled i = get_charinfo_italic(ci);
+ return i;
+}
+
+scaled char_vert_italic(internal_font_number f, int c)
+{
+ charinfo *ci = char_info(f, c);
+ scaled i = get_charinfo_vert_italic(ci);
+ return i;
+}
+
+scaled char_top_accent(internal_font_number f, int c)
+{
+ charinfo *ci = char_info(f, c);
+ return get_charinfo_top_accent(ci);
+}
+
+scaled char_bot_accent(internal_font_number f, int c)
+{
+ charinfo *ci = char_info(f, c);
+ return get_charinfo_bot_accent(ci);
+}
+
+int char_remainder(internal_font_number f, int c)
+{
+ charinfo *ci = char_info(f, c);
+ return get_charinfo_remainder(ci);
+}
+
+char char_tag(internal_font_number f, int c)
+{
+ charinfo *ci = char_info(f, c);
+ return get_charinfo_tag(ci);
+}
+
+char char_used(internal_font_number f, int c)
+{
+ charinfo *ci = char_info(f, c);
+ return get_charinfo_used(ci);
+}
+
+char *char_name(internal_font_number f, int c)
+{
+ charinfo *ci = char_info(f, c);
+ return get_charinfo_name(ci);
+}
+
+int char_index(internal_font_number f, int c)
+{
+ charinfo *ci = char_info(f, c);
+ return get_charinfo_index(ci);
+}
+
+liginfo *char_ligatures(internal_font_number f, int c)
+{
+ charinfo *ci = char_info(f, c);
+ return get_charinfo_ligatures(ci);
+}
+
+kerninfo *char_kerns(internal_font_number f, int c)
+{
+ charinfo *ci = char_info(f, c);
+ return get_charinfo_kerns(ci);
+}
+
+eight_bits *char_packets(internal_font_number f, int c)
+{
+ charinfo *ci = char_info(f, c);
+ return get_charinfo_packets(ci);
+}
+
+void set_font_params(internal_font_number f, int b)
+{
+ int i;
+ i = font_params(f);
+ if (i != b) {
+ font_bytes +=
+ (int) ((b - (int) font_params(f) + 1) * (int) sizeof(scaled));
+ do_realloc(param_base(f), (b + 2), int);
+ font_params(f) = b;
+ if (b > i) {
+ while (i < b) {
+ i++;
+ set_font_param(f, i, 0);
+ }
+ }
+ }
+}
+
+void set_font_math_params(internal_font_number f, int b)
+{
+ int i;
+ i = font_math_params(f);
+ if (i != b) {
+ font_bytes +=
+ ((b - (int) font_math_params(f) + 1) * (int) sizeof(scaled));
+ do_realloc(math_param_base(f), (b + 2), int);
+ font_math_params(f) = b;
+ if (b > i) {
+ while (i < b) {
+ i++;
+ set_font_math_param(f, i, undefined_math_parameter);
+ }
+ }
+ }
+}
+
+int copy_font(int f)
+{
+ int i, ci_cnt, ci_size;
+ charinfo *ci;
+ int k = new_font();
+ {
+ ci = font_tables[k]->_charinfo;
+ ci_cnt = font_tables[k]->_charinfo_count;
+ ci_size = font_tables[k]->_charinfo_size;
+ memcpy(font_tables[k], font_tables[f], sizeof(texfont));
+ font_tables[k]->_charinfo = ci;
+ font_tables[k]->_charinfo_count = ci_cnt;
+ font_tables[k]->_charinfo_size = ci_size;
+ }
+ font_malloc_charinfo(k, font_tables[f]->_charinfo_count);
+ set_font_cache_id(k, 0);
+ set_font_used(k, 0);
+ set_font_touched(k, 0);
+ font_tables[k]->_font_name = NULL;
+ font_tables[k]->_font_filename = NULL;
+ font_tables[k]->_font_fullname = NULL;
+ font_tables[k]->_font_psname = NULL;
+ font_tables[k]->_font_encodingname = NULL;
+ font_tables[k]->_font_area = NULL;
+ font_tables[k]->_font_cidregistry = NULL;
+ font_tables[k]->_font_cidordering = NULL;
+ font_tables[k]->_left_boundary = NULL;
+ font_tables[k]->_right_boundary = NULL;
+ set_font_name(k, xstrdup(font_name(f)));
+ if (font_filename(f) != NULL)
+ set_font_filename(k, xstrdup(font_filename(f)));
+ if (font_fullname(f) != NULL)
+ set_font_fullname(k, xstrdup(font_fullname(f)));
+ if (font_psname(f) != NULL)
+ set_font_psname(k, xstrdup(font_psname(f)));
+ if (font_encodingname(f) != NULL)
+ set_font_encodingname(k, xstrdup(font_encodingname(f)));
+ if (font_area(f) != NULL)
+ set_font_area(k, xstrdup(font_area(f)));
+ if (font_cidregistry(f) != NULL)
+ set_font_cidregistry(k, xstrdup(font_cidregistry(f)));
+ if (font_cidordering(f) != NULL)
+ set_font_cidordering(k, xstrdup(font_cidordering(f)));
+ set_font_encodingbytes(k,font_encodingbytes(f));
+ set_font_subfont(k,font_subfont(f));
+ i = (int) (sizeof(*param_base(f)) * (unsigned) (font_params(f)+1));
+ font_bytes += i;
+ param_base(k) = xmalloc((unsigned) (i+1));
+ memcpy(param_base(k), param_base(f), (size_t) (i));
+ if (font_math_params(f) > 0) {
+ i = (int) (sizeof(*math_param_base(f)) *
+ (unsigned) font_math_params(f));
+ font_bytes += i;
+ math_param_base(k) = xmalloc((unsigned) i);
+ memcpy(math_param_base(k), math_param_base(f), (size_t) i);
+ }
+ for (i = 0; i <= font_tables[f]->_charinfo_count; i++) {
+ ci = copy_charinfo(&font_tables[f]->_charinfo[i]);
+ font_tables[k]->_charinfo[i] = *ci;
+ }
+ if (left_boundary(f) != NULL) {
+ ci = copy_charinfo(left_boundary(f));
+ set_charinfo(k, left_boundarychar, ci);
+ }
+ if (right_boundary(f) != NULL) {
+ ci = copy_charinfo(right_boundary(f));
+ set_charinfo(k, right_boundarychar, ci);
+ }
+ /*tex Not updated yet: */
+ font_tables[k]->_charinfo_count = font_tables[f]->_charinfo_count;
+ return k;
+}
+
+void delete_font(int f)
+{
+ int i;
+ charinfo *co;
+ assert(f > 0);
+ if (font_tables[f] != NULL) {
+ set_font_name(f, NULL);
+ set_font_filename(f, NULL);
+ set_font_fullname(f, NULL);
+ set_font_psname(f, NULL);
+ set_font_encodingname(f, NULL);
+ set_font_area(f, NULL);
+ set_font_cidregistry(f, NULL);
+ set_font_cidordering(f, NULL);
+ set_left_boundary(f, NULL);
+ set_right_boundary(f, NULL);
+ for (i = font_bc(f); i <= font_ec(f); i++) {
+ if (quick_char_exists(f, i)) {
+ co = char_info(f, i);
+ set_charinfo_name(co, NULL);
+ set_charinfo_tounicode(co, NULL);
+ set_charinfo_packets(co, NULL);
+ set_charinfo_ligatures(co, NULL);
+ set_charinfo_kerns(co, NULL);
+ set_charinfo_vert_variants(co, NULL);
+ set_charinfo_hor_variants(co, NULL);
+ }
+ }
+ /*tex free |notdef| */
+ set_charinfo_name(font_tables[f]->_charinfo + 0, NULL);
+ free(font_tables[f]->_charinfo);
+ destroy_sa_tree(font_tables[f]->_characters);
+ free(param_base(f));
+ if (math_param_base(f) != NULL)
+ free(math_param_base(f));
+ free(font_tables[f]);
+ font_tables[f] = NULL;
+ if (font_id_maxval == f) {
+ font_id_maxval--;
+ }
+ }
+}
+
+void create_null_font(void)
+{
+ int i = new_font();
+ assert(i == 0);
+ set_font_name(i, xstrdup("nullfont"));
+ set_font_area(i, xstrdup(""));
+ set_font_touched(i, 1);
+}
+
+boolean is_valid_font(int id)
+{
+ int ret = 0;
+ if (id >= 0 && id <= font_id_maxval && font_tables[id] != NULL)
+ ret = 1;
+ return ret;
+}
+
+boolean cmp_font_area(int id, str_number t)
+{
+ char *tt = NULL;
+ char *tid = font_area(id);
+ if (t == 0) {
+ if (tid == NULL || strlen(tid) == 0)
+ return 1;
+ else
+ return 0;
+ }
+ tt = makecstring(t);
+ if ((tt == NULL || strlen(tt) == 0) && (tid == NULL || strlen(tid) == 0))
+ return 1;
+ if (tt == NULL || strcmp(tid, tt) != 0)
+ return 0;
+ free(tt);
+ return 1;
+}
+
+/*tex
+
+ Here come some subroutines to deal with expanded fonts for HZ-algorithm.
+ returning 1 means that they are identical.
+
+*/
+
+static boolean cmp_font_name(int id, char *tt)
+{
+ char *tid;
+ if (!is_valid_font(id))
+ return 0;
+ tid = font_name(id);
+ if (tt == NULL && tid == NULL)
+ return 1;
+ if (tt == NULL || tid == NULL || strcmp(tid, tt) != 0)
+ return 0;
+ return 1;
+}
+
+int test_no_ligatures(internal_font_number f)
+{
+ int c;
+ for (c = font_bc(f); c <= font_ec(f); c++) {
+ if (has_lig(f, c))
+ return 0;
+ }
+ return 1;
+}
+
+int get_tag_code(internal_font_number f, int c)
+{
+ small_number i;
+ if (char_exists(f, c)) {
+ i = char_tag(f, c);
+ if (i == lig_tag)
+ return 1;
+ else if (i == list_tag)
+ return 2;
+ else if (i == ext_tag)
+ return 4;
+ else
+ return 0;
+ }
+ return -1;
+}
+
+int get_lp_code(internal_font_number f, int c)
+{
+ charinfo *ci = char_info(f, c);
+ return get_charinfo_lp(ci);
+}
+
+int get_rp_code(internal_font_number f, int c)
+{
+ charinfo *ci = char_info(f, c);
+ return get_charinfo_rp(ci);
+}
+
+int get_ef_code(internal_font_number f, int c)
+{
+ charinfo *ci = char_info(f, c);
+ return get_charinfo_ef(ci);
+}
+
+void set_tag_code(internal_font_number f, int c, int i)
+{
+ int fixedi;
+ charinfo *co;
+ if (char_exists(f, c)) {
+ fixedi = -(i < -7 ? -7 : (i > 0 ? 0 : i));
+ co = char_info(f, c);
+ if (fixedi >= 4) {
+ if (char_tag(f, c) == ext_tag)
+ set_charinfo_tag(co, (char_tag(f, c) - ext_tag));
+ fixedi = fixedi - 4;
+ }
+ if (fixedi >= 2) {
+ if (char_tag(f, c) == list_tag)
+ set_charinfo_tag(co, (char_tag(f, c) - list_tag));
+ fixedi = fixedi - 2;
+ };
+ if (fixedi >= 1) {
+ if (has_lig(f, c))
+ set_charinfo_ligatures(co, NULL);
+ if (has_kern(f, c))
+ set_charinfo_kerns(co, NULL);
+ }
+ }
+}
+
+void set_lp_code(internal_font_number f, int c, int i)
+{
+ charinfo *co;
+ if (char_exists(f, c)) {
+ co = char_info(f, c);
+ set_charinfo_lp(co, i);
+ }
+}
+
+void set_rp_code(internal_font_number f, int c, int i)
+{
+ charinfo *co;
+ if (char_exists(f, c)) {
+ co = char_info(f, c);
+ set_charinfo_rp(co, i);
+ }
+}
+
+void set_ef_code(internal_font_number f, int c, int i)
+{
+ charinfo *co;
+ if (char_exists(f, c)) {
+ co = char_info(f, c);
+ set_charinfo_ef(co, i);
+ }
+}
+
+void set_no_ligatures(internal_font_number f)
+{
+ int c;
+ charinfo *co;
+ if (font_tables[f]->_ligatures_disabled)
+ return;
+ co = char_info(f, left_boundarychar);
+ set_charinfo_ligatures(co, NULL);
+ co = char_info(f, right_boundarychar);
+ set_charinfo_ligatures(co, NULL);
+ for (c = 0; c < font_tables[f]->_charinfo_count; c++) {
+ co = font_tables[f]->_charinfo + c;
+ set_charinfo_ligatures(co, NULL);
+ }
+ font_tables[f]->_ligatures_disabled = 1;
+}
+
+liginfo get_ligature(internal_font_number f, int lc, int rc)
+{
+ int k = 0;
+ liginfo t, u;
+ charinfo *co;
+ t.lig = 0;
+ t.type = 0;
+ t.adj = 0;
+ if (lc == non_boundarychar || rc == non_boundarychar || (!has_lig(f, lc)))
+ return t;
+ co = char_info(f, lc);
+ while (1) {
+ u = charinfo_ligature(co, k);
+ if (lig_end(u))
+ break;
+ if (lig_char(u) == rc) {
+ if (lig_disabled(u)) {
+ return t;
+ } else {
+ return u;
+ }
+ }
+ k++;
+ }
+ return t;
+}
+
+scaled raw_get_kern(internal_font_number f, int lc, int rc)
+{
+ int k = 0;
+ kerninfo u;
+ charinfo *co;
+ if (lc == non_boundarychar || rc == non_boundarychar)
+ return 0;
+ co = char_info(f, lc);
+ while (1) {
+ u = charinfo_kern(co, k);
+ if (kern_end(u))
+ break;
+ if (kern_char(u) == rc) {
+ if (kern_disabled(u))
+ return 0;
+ else
+ return kern_kern(u);
+ }
+ k++;
+ }
+ return 0;
+}
+
+scaled get_kern(internal_font_number f, int lc, int rc)
+{
+ if (lc == non_boundarychar || rc == non_boundarychar || (!has_kern(f, lc)))
+ return 0;
+ return raw_get_kern(f, lc, rc);
+}
+
+
+/*tex Dumping and undumping fonts. */
+
+#define dump_string(a) \
+ if (a!=NULL) { \
+ x = (int)(strlen(a)+1); \
+ dump_int(x); dump_things(*a, x); \
+ } else { \
+ x = 0; dump_int(x); \
+ }
+
+static void dump_charinfo(int f, int c)
+{
+ charinfo *co;
+ int x;
+ liginfo *lig;
+ kerninfo *kern;
+ dump_int(c);
+ co = char_info(f, c);
+ set_charinfo_used(co, 0);
+ dump_int(get_charinfo_width(co));
+ dump_int(get_charinfo_height(co));
+ dump_int(get_charinfo_depth(co));
+ dump_int(get_charinfo_italic(co));
+ dump_int(get_charinfo_vert_italic(co));
+ dump_int(get_charinfo_top_accent(co));
+ dump_int(get_charinfo_bot_accent(co));
+ dump_int(get_charinfo_tag(co));
+ dump_int(get_charinfo_ef(co));
+ dump_int(get_charinfo_rp(co));
+ dump_int(get_charinfo_lp(co));
+ dump_int(get_charinfo_remainder(co));
+ dump_int(get_charinfo_used(co));
+ dump_int(get_charinfo_index(co));
+ dump_string(get_charinfo_name(co));
+ dump_string(get_charinfo_tounicode(co));
+ /*tex Ligatures */
+ x = 0;
+ if ((lig = get_charinfo_ligatures(co)) != NULL) {
+ while (!lig_end(lig[x])) {
+ x++;
+ }
+ x++;
+ dump_int(x);
+ dump_things(*lig, x);
+ } else {
+ dump_int(x);
+ }
+ /*tex Kerns */
+ x = 0;
+ if ((kern = get_charinfo_kerns(co)) != NULL) {
+ while (!kern_end(kern[x])) {
+ x++;
+ }
+ x++;
+ dump_int(x);
+ dump_things(*kern, x);
+ } else {
+ dump_int(x);
+ }
+ /*tex Packets */
+ x = vf_packet_bytes(co);
+ dump_int(x);
+ if (x > 0) {
+ dump_things(*get_charinfo_packets(co), x);
+ }
+ if (get_charinfo_tag(co) == ext_tag) {
+ dump_charinfo_variants(get_charinfo_vert_variants(co));
+ dump_charinfo_variants(get_charinfo_hor_variants(co));
+ }
+ dump_math_kerns(co);
+}
+
+static void dump_font_entry(texfont * f)
+{
+ int x;
+ dump_int(f->_font_size);
+ dump_int(f->_font_dsize);
+ dump_int(f->_font_cidversion);
+ dump_int(f->_font_cidsupplement);
+ dump_int(f->_font_ec);
+ x = (int) f->_font_checksum;
+ dump_int(x);
+ dump_int(f->_font_used);
+ dump_int(f->_font_touched);
+ dump_int(f->_font_cache_id);
+ dump_int(f->_font_encodingbytes);
+ dump_int(f->_font_subfont);
+ dump_int(f->_font_oldmath);
+ dump_int(f->_font_slant);
+ dump_int(f->_font_extend);
+ dump_int(f->_font_squeeze);
+ dump_int(f->_font_mode);
+ dump_int(f->_font_width);
+ dump_int(f->_font_max_shrink);
+ dump_int(f->_font_max_stretch);
+ dump_int(f->_font_step);
+ dump_int(f->_font_tounicode);
+ dump_int(f->_font_type);
+ dump_int(f->_font_format);
+ dump_int(f->_font_writingmode);
+ dump_int(f->_font_identity);
+ dump_int(f->_font_embedding);
+ dump_int(f->_font_streamprovider);
+ dump_int(f->_font_bc);
+ dump_int(f->_hyphen_char);
+ dump_int(f->_skew_char);
+ dump_int(f->_font_natural_dir);
+ dump_int(f->_font_params);
+ dump_int(f->_font_math_params);
+ dump_int(f->_ligatures_disabled);
+ dump_int(f->_pdf_font_num);
+ dump_int(f->_pdf_font_attr);
+}
+
+void dump_font(int f)
+{
+ int i, x;
+ set_font_used(f, 0);
+ dump_font_entry(font_tables[f]);
+ dump_string(font_name(f));
+ dump_string(font_area(f));
+ dump_string(font_filename(f));
+ dump_string(font_fullname(f));
+ dump_string(font_psname(f));
+ dump_string(font_encodingname(f));
+ dump_string(font_cidregistry(f));
+ dump_string(font_cidordering(f));
+ dump_things(*param_base(f), (font_params(f) + 1));
+ if (font_math_params(f) > 0) {
+ dump_things(*math_param_base(f), (font_math_params(f) + 1 ));
+ }
+ if (has_left_boundary(f)) {
+ dump_int(1);
+ dump_charinfo(f, left_boundarychar);
+ } else {
+ dump_int(0);
+ }
+ if (has_right_boundary(f)) {
+ dump_int(1);
+ dump_charinfo(f, right_boundarychar);
+ } else {
+ dump_int(0);
+ }
+ for (i = font_bc(f); i <= font_ec(f); i++) {
+ if (quick_char_exists(f, i)) {
+ dump_charinfo(f, i);
+ }
+ }
+}
+
+static int undump_charinfo(int f)
+{
+ charinfo *co;
+ int x, i;
+ char *s = NULL;
+ liginfo *lig = NULL;
+ kerninfo *kern = NULL;
+ eight_bits *packet = NULL;
+ undump_int(i);
+ co = get_charinfo(f, i);
+ undump_int(x);
+ set_charinfo_width(co, x);
+ undump_int(x);
+ set_charinfo_height(co, x);
+ undump_int(x);
+ set_charinfo_depth(co, x);
+ undump_int(x);
+ set_charinfo_italic(co, x);
+ undump_int(x);
+ set_charinfo_vert_italic(co, x);
+ undump_int(x);
+ set_charinfo_top_accent(co, x);
+ undump_int(x);
+ set_charinfo_bot_accent(co, x);
+ undump_int(x);
+ set_charinfo_tag(co, x);
+ undump_int(x);
+ set_charinfo_ef(co, x);
+ undump_int(x);
+ set_charinfo_rp(co, x);
+ undump_int(x);
+ set_charinfo_lp(co, x);
+ undump_int(x);
+ set_charinfo_remainder(co, x);
+ undump_int(x);
+ set_charinfo_used(co, x);
+ undump_int(x);
+ set_charinfo_index(co, x);
+ /*tex Name */
+ undump_int(x);
+ if (x > 0) {
+ font_bytes += x;
+ s = xmalloc((unsigned) x);
+ undump_things(*s, x);
+ }
+ set_charinfo_name(co, s);
+ /*tex Tounicode */
+ undump_int(x);
+ if (x > 0) {
+ font_bytes += x;
+ s = xmalloc((unsigned) x);
+ undump_things(*s, x);
+ }
+ set_charinfo_tounicode(co, s);
+ /*tex Ligatures */
+ undump_int(x);
+ if (x > 0) {
+ font_bytes += (int) ((unsigned) x * sizeof(liginfo));
+ lig = xmalloc((unsigned) ((unsigned) x * sizeof(liginfo)));
+ undump_things(*lig, x);
+ }
+ set_charinfo_ligatures(co, lig);
+ /*tex Kerns */
+ undump_int(x);
+ if (x > 0) {
+ font_bytes += (int) ((unsigned) x * sizeof(kerninfo));
+ kern = xmalloc((unsigned) ((unsigned) x * sizeof(kerninfo)));
+ undump_things(*kern, x);
+ }
+ set_charinfo_kerns(co, kern);
+
+ /*tex Packets */
+ undump_int(x);
+ if (x > 0) {
+ font_bytes += x;
+ packet = xmalloc((unsigned) x);
+ undump_things(*packet, x);
+ }
+ set_charinfo_packets(co, packet);
+ if (get_charinfo_tag(co) == ext_tag) {
+ set_charinfo_vert_variants(co, undump_charinfo_variants());
+ set_charinfo_hor_variants(co, undump_charinfo_variants());
+ }
+ undump_math_kerns(co);
+ return i;
+}
+
+#define undump_font_string(a) \
+ undump_int (x); \
+ if (x>0) { \
+ font_bytes += x; \
+ s = xmalloc((unsigned)x); \
+ undump_things(*s,x); \
+ a(f,s); \
+ }
+
+static void undump_font_entry(texfont * f)
+{
+ int x = 0;
+ undump_int(x); f->_font_size = x;
+ undump_int(x); f->_font_dsize = x;
+ undump_int(x); f->_font_cidversion = x;
+ undump_int(x); f->_font_cidsupplement = x;
+ undump_int(x); f->_font_ec = x;
+ undump_int(x); f->_font_checksum = (unsigned)x;
+ undump_int(x); f->_font_used = (char)x;
+ undump_int(x); f->_font_touched = (char)x;
+ undump_int(x); f->_font_cache_id = x;
+ undump_int(x); f->_font_encodingbytes = (char)x;
+ undump_int(x); f->_font_subfont = x;
+ undump_int(x); f->_font_oldmath = x;
+ undump_int(x); f->_font_slant = x;
+ undump_int(x); f->_font_extend = x;
+ undump_int(x); f->_font_squeeze = x;
+ undump_int(x); f->_font_mode = x;
+ undump_int(x); f->_font_width = x;
+ undump_int(x); f->_font_max_shrink = x;
+ undump_int(x); f->_font_max_stretch = x;
+ undump_int(x); f->_font_step = x;
+ undump_int(x); f->_font_tounicode = (char)x;
+ undump_int(x); f->_font_type = x;
+ undump_int(x); f->_font_format = x;
+ undump_int(x); f->_font_writingmode = x;
+ undump_int(x); f->_font_identity = x;
+ undump_int(x); f->_font_embedding = x;
+ undump_int(x); f->_font_streamprovider = x;
+ undump_int(x); f->_font_bc = x;
+ undump_int(x); f->_hyphen_char = x;
+ undump_int(x); f->_skew_char = x;
+ undump_int(x); f->_font_natural_dir = x;
+ undump_int(x); f->_font_params = x;
+ undump_int(x); f->_font_math_params = x;
+ undump_int(x); f->_ligatures_disabled = x;
+ undump_int(x); f->_pdf_font_num = x;
+ undump_int(x); f->_pdf_font_attr = x;
+}
+
+void undump_font(int f)
+{
+ int x, i;
+ texfont *tt;
+ charinfo *ci;
+ char *s;
+ sa_tree_item sa_value = { 0 };
+ grow_font_table(f);
+ tt = xmalloc(sizeof(texfont));
+ memset(tt, 0, sizeof(texfont));
+ font_bytes += (int) sizeof(texfont);
+ undump_font_entry(tt);
+ font_tables[f] = tt;
+ undump_font_string(set_font_name);
+ undump_font_string(set_font_area);
+ undump_font_string(set_font_filename);
+ undump_font_string(set_font_fullname);
+ undump_font_string(set_font_psname);
+ undump_font_string(set_font_encodingname);
+ undump_font_string(set_font_cidregistry);
+ undump_font_string(set_font_cidordering);
+ i = (int) (sizeof(*param_base(f)) * ((unsigned) font_params(f) + 1));
+ font_bytes += i;
+ param_base(f) = xmalloc((unsigned) i);
+ undump_things(*param_base(f), (font_params(f) + 1));
+ if (font_math_params(f) > 0) {
+ i = (int) (sizeof(*math_param_base(f)) *
+ ((unsigned) font_math_params(f) + 1));
+ font_bytes += i;
+ math_param_base(f) = xmalloc((unsigned) i);
+ undump_things(*math_param_base(f), (font_math_params(f) + 1));
+ }
+ /*tex stack size 1, default item value 0 */
+ font_tables[f]->_characters = new_sa_tree(1, 1, sa_value);
+ ci = xcalloc(1, sizeof(charinfo));
+ set_charinfo_name(ci, xstrdup(".notdef"));
+ font_tables[f]->_charinfo = ci;
+ undump_int(x);
+ if (x) {
+ /*tex left boundary */
+ i = undump_charinfo(f);
+ }
+ undump_int(x);
+ if (x) {
+ /*tex right boundary */
+ i = undump_charinfo(f);
+ }
+ i = font_bc(f);
+ while (i < font_ec(f)) {
+ i = undump_charinfo(f);
+ }
+}
+
+/* The \PK\ pixel density value from |texmf.cnf| */
+
+int pk_dpi;
+
+/*tex
+
+ This one looks up the font for a \TFM\ with name |s| loaded at |fs| size and
+ if found then flushes |s|.
+
+*/
+
+internal_font_number tfm_lookup(char *s, scaled fs)
+{
+ internal_font_number k;
+ if (fs != 0) {
+ for (k = 1; k <= max_font_id(); k++) {
+ if (cmp_font_name(k, s) && font_size(k) == fs) {
+ return k;
+ }
+ }
+ } else {
+ for (k = 1; k <= max_font_id(); k++) {
+ if (cmp_font_name(k, s)) {
+ return k;
+ }
+ }
+ }
+ return null_font;
+}
+
+/*tex
+
+ This returns the multiple of |font_step(f)| that is nearest to |e|.
+
+*/
+
+int fix_expand_value(internal_font_number f, int e)
+{
+ int step;
+ int max_expand;
+ boolean neg;
+ if (e == 0)
+ return 0;
+ if (e < 0) {
+ e = -e;
+ neg = true;
+ max_expand = font_max_shrink(f);
+ } else {
+ neg = false;
+ max_expand = font_max_stretch(f);
+ }
+ if (e > max_expand) {
+ e = max_expand;
+ } else {
+ step = font_step(f);
+ if (e % step > 0)
+ e = step * round_xn_over_d(e, 1, step);
+ }
+ if (neg)
+ e = -e;
+ return e;
+}
+
+void set_expand_params(internal_font_number f, int stretch_limit, int shrink_limit, int font_step)
+{
+ set_font_step(f, font_step);
+ set_font_max_shrink(f, shrink_limit);
+ set_font_max_stretch(f, stretch_limit);
+}
+
+/*tex
+
+ This reads font expansion spec and load expanded font.
+
+*/
+
+void read_expand_font(void)
+{
+ int shrink_limit, stretch_limit, font_step;
+ internal_font_number f;
+ scan_font_ident();
+ f = cur_val;
+ if (f == null_font)
+ normal_error("font expansion", "invalid font identifier");
+ scan_optional_equals();
+ scan_int();
+ stretch_limit = fix_int(cur_val, 0, 1000);
+ scan_int();
+ shrink_limit = fix_int(cur_val, 0, 500);
+ scan_int();
+ font_step = fix_int(cur_val, 0, 100);
+ if (font_step == 0)
+ normal_error("font expansion", "invalid step");
+ stretch_limit = stretch_limit - stretch_limit % font_step;
+ if (stretch_limit < 0)
+ stretch_limit = 0;
+ shrink_limit = shrink_limit - shrink_limit % font_step;
+ if (shrink_limit < 0)
+ shrink_limit = 0;
+ if ((stretch_limit == 0) && (shrink_limit == 0))
+ normal_error("font expansion", "invalid limit(s)");
+ if (scan_keyword("autoexpand")) {
+ normal_warning("font expansion", "autoexpand not supported");
+ /*tex scan an optional space */
+ get_x_token();
+ if (cur_cmd != spacer_cmd)
+ back_input();
+ }
+ if (font_step(f) != 0) {
+ /*tex This font has been expanded, ensure the expansion parameters are identical. */
+ if (font_step(f) != font_step)
+ normal_error("font expansion","font has been expanded with different expansion step");
+ if (((font_max_stretch(f) == 0) && (stretch_limit != 0)) ||
+ ((font_max_stretch(f) > 0) && (font_max_stretch(f) != stretch_limit)))
+ normal_error("font expansion","font has been expanded with different stretch limit");
+
+ if (((font_max_shrink(f) == 0) && (shrink_limit != 0)) ||
+ ((font_max_shrink(f) > 0) && (font_max_shrink(f) != shrink_limit)))
+ normal_error("font expansion","font has been expanded with different shrink limit");
+ } else {
+ if (font_used(f))
+ normal_warning("font expansion", "font should be expanded before its first use");
+ set_expand_params(f, stretch_limit, shrink_limit, font_step);
+ }
+}
+
+/*tex
+
+ Here's an old (sort of obsolete) letterspace-a-font helper. It does so by by
+ creating a virtual font.
+
+*/
+
+void new_letterspaced_font(small_number a)
+{
+ pointer u;
+ str_number t;
+ internal_font_number f, k;
+ boolean nolig = false;
+ get_r_token();
+ u = cur_cs;
+ if (u >= hash_base)
+ t = cs_text(u);
+ else
+ t = maketexstring("FONT");
+ define(u, set_font_cmd, null_font);
+ scan_optional_equals();
+ scan_font_ident();
+ k = cur_val;
+ scan_int();
+ if (scan_keyword("nolig"))
+ nolig=true;
+ f = letter_space_font(k, fix_int(cur_val, -1000, 1000), nolig);
+ equiv(u) = f;
+ eqtb[font_id_base + f] = eqtb[u];
+ font_id_text(f) = t;
+}
+
+/*tex
+
+ This makes a font copy for further use with font expansion. Again a
+ traditional font related helper.
+
+*/
+
+void make_font_copy(small_number a)
+{
+ pointer u;
+ str_number t;
+ internal_font_number f, k;
+ get_r_token();
+ u = cur_cs;
+ if (u >= hash_base)
+ t = cs_text(u);
+ else
+ t = maketexstring("FONT");
+ define(u, set_font_cmd, null_font);
+ scan_optional_equals();
+ scan_font_ident();
+ k = cur_val;
+ f = copy_font_info(k);
+ equiv(u) = f;
+ eqtb[font_id_base + f] = eqtb[u];
+ font_id_text(f) = t;
+}
+
+void glyph_to_unicode(void)
+{
+ str_number s1, s2;
+ scan_toks(false, true);
+ s1 = tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ scan_toks(false, true);
+ s2 = tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ def_tounicode(s1, s2);
+ flush_str(s2);
+ flush_str(s1);
+}