summaryrefslogtreecommitdiff
path: root/source/luametatex/source/tex/texfont.h
diff options
context:
space:
mode:
Diffstat (limited to 'source/luametatex/source/tex/texfont.h')
-rw-r--r--source/luametatex/source/tex/texfont.h667
1 files changed, 667 insertions, 0 deletions
diff --git a/source/luametatex/source/tex/texfont.h b/source/luametatex/source/tex/texfont.h
new file mode 100644
index 000000000..a13c6e13d
--- /dev/null
+++ b/source/luametatex/source/tex/texfont.h
@@ -0,0 +1,667 @@
+/*
+ See license.txt in the root of this project.
+*/
+
+# ifndef LMT_TEXFONT_H
+# define LMT_TEXFONT_H
+
+# include "tex/textypes.h"
+
+/*tex
+
+ In the \WEBC\ infrastructrure there is code that deals with endianness of the machine but in
+ \LUAMETATEX\ we don't need this. In \LUATEX\ sharing the format file was already dropped, simply
+ because we can also store \LUA\ bytecode in the format. In the other engines font data can end
+ up in the format file and that in turn then also can be endian dependent. But in \LUAMETATEX\
+ we no longer stored font data, and that is yet another reason why there is no endian related
+ code here.
+
+ The ligature and kern structures are for traditional \TEX\ fonts, thise that are handles by the
+ built in reference handlers. Although \OPENTYPE\ is more versatile, we should not forget that
+ for many (latin) scripts these so called base fonts are quite adequate and efficient. We could
+ of course implement base support in \LUA\ but although \LUAMETATEX\ can delegate a lot, we also
+ keep the reference implementation available: it is well documented, was for a long time the best
+ one could get and doesn't take that much code. So, here come the basic structures:
+
+*/
+
+typedef struct ligatureinfo {
+ int type;
+ int ligature;
+ int adjacent;
+ /* alignment */
+ int padding;
+} ligatureinfo;
+
+typedef struct kerninfo {
+ int kern;
+ int adjacent;
+} kerninfo;
+
+/*tex
+
+ In \LUAMETATEX, at runtime, after a font is loaded via a callback, we only store the little
+ information that is needed for basic ligature building and kerning, math rendering (like
+ extensibles), and par building which includes protrusion and expansion. We don't need anything
+ related to the backend because outpout is delegated to \LUA.
+
+ The most extensive data structures are those related to \OPENTYPE\ math. When passing a font we
+ can save memory by using the |hasmath| directive. In \LUAMETATEX\ we can then have a different
+ |struct| with 15 fields less than in \LUATEX\ which, combined with other savings, saves some 60
+ bytes. The disadvantage is that accessors of those fields also need to act upon that flag, which
+ involves more testing. However, because in practice math font access is not that prominent so
+ the gain outweights this potential performance hit. For an average \CJK\ font with 5000
+ characters we saves 300000 bytes. Because a complete Latin font with various features also can
+ have thousands of glyphs, it can save some memory there too. It's changes like this that give
+ \LUAMETATEX\ a much smaller memory footprint than its predecessor.
+
+ The next record relates to math extensibles. It is good to realize that traditional \TEX\ fonts
+ are handled differently in the math subengine than \OPENTYPE\ math fonts. However, we use the
+ more extensive \OPENTYPE\ structure for both type of fonts.
+
+*/
+
+typedef struct extinfo {
+ struct extinfo *next;
+ int glyph;
+ int start_overlap;
+ int end_overlap;
+ int advance;
+ int extender;
+ /* alignment */
+ int padding;
+} extinfo;
+
+// typedef enum math_font_options {
+// math_font_ignore_italic_option = 0x01,
+// } math_font_options;
+//
+// # define math_font_option(options,option) ((options & option) == option)
+
+typedef struct mathinfo {
+ scaled vertical_italic;
+ scaled top_accent;
+ scaled bottom_accent;
+ int smaller;
+ scaled scale;
+ int flat_accent;
+ int top_left_math_kerns;
+ int top_right_math_kerns;
+ int bottom_right_math_kerns;
+ int bottom_left_math_kerns;
+ extinfo *horizontal_parts;
+ extinfo *vertical_parts;
+ scaled *top_left_math_kern_array;
+ scaled *top_right_math_kern_array;
+ scaled *bottom_right_math_kern_array;
+ scaled *bottom_left_math_kern_array;
+ /* these are for specific (script) anchoring */
+ scaled top_left_kern;
+ scaled bottom_left_kern;
+ scaled top_right_kern;
+ scaled bottom_right_kern;
+ scaled left_margin;
+ scaled right_margin;
+ scaled top_margin;
+ scaled bottom_margin;
+} mathinfo;
+
+typedef struct charinfo {
+ /*tex
+ This is what \TEX\ uses when it calculates the dimensions needed for building boxes and
+ breaking paragraphs into lines. The italic correction is part of that as it has a primitive
+ that needs the value.
+ */
+ scaled width;
+ scaled height;
+ scaled depth;
+ scaled italic;
+ /*tex
+ The next three variables relate to expansion and protrusion, properties introduced in the
+ \PDFTEX\ engine. Handling of protrusion and expansion is the only features that we inherit
+ from this important extension to traditional \TEX.
+ */
+ scaled expansion;
+ scaled leftprotrusion;
+ scaled rightprotrusion;
+ /* halfword padding; */ /* when we pack |tag| and |remainder| we can safe 4 bytes */
+ /*tex
+ These two are used in a \TFM\ file for signaling ligatures. They are also used for math
+ extensions in traditional \TEX\ fonts, so we just keep them.
+ */
+ /* halfword tag; */ /* 2 bits is enough (flags) */
+ /* halfword remainder; */ /* 21 bits is enough (unicode) */
+ halfword tagrem; /* just an integer, less (arm) alignment hassle that way */
+ /*tex
+ Traditional \TEX\ fonts use these two lists for ligature building and inter-character
+ kerning and these are now optional (via pointers). By also using an indirect structure for
+ math data we save quite a bit of memory when we have no math font.
+ */
+ ligatureinfo *ligatures;
+ kerninfo *kerns;
+ mathinfo *math;
+} charinfo;
+
+/*tex
+ We can just abuse the token setters and getters here.
+*/
+
+# define charinfo_tag token_cmd
+# define charinfo_rem token_chr
+# define charinfo_tagrem token_val
+
+/*tex
+
+ For a font instance we only store the bits that are used by the engine itself. Of course more
+ data can (and normally will be) be kept at the \TEX\ cq.\ \LUA\ end.
+
+ We could store a scale (/1000) and avoid copying a font but then we also need to multiply
+ width, height, etc. when queried (extra overhead). A bit tricky is then dealing with (virtual)
+ commands. It is not that big a deal in \CONTEXT\ so I might actually add this feature but only
+ very few documents use many font instances so in the end the gain is neglectable (we only save
+ some memory). Also, we then need to adapt the math processing quite a bit which is always kind
+ of tricky.
+
+ Again, compared to \LUATEX\ there is less data stored here because we don't need to control the
+ backend. Of course in \CONTEXT\ we keep plenty of data at the \LUA\ end, but we did that already
+ anyway.
+
+*/
+
+typedef struct texfont {
+ /*tex the range of (allocated) characters */
+ int first_character;
+ int last_character;
+ /*tex the (sparse) character (glyph) array */
+ sa_tree characters;
+ charinfo *chardata;
+ int chardata_count;
+ int chardata_size;
+ /*tex properties used in messages */
+ int size;
+ int design_size;
+ char *name;
+ char *original;
+ /*tex for experimental new thingies */
+ int compactmath;
+ /*tex default to false when MathConstants not seen */
+ int oldmath;
+ /*tex this controls the engine */
+ int mathcontrol;
+ int textcontrol;
+ /*tex expansion */
+ int max_shrink;
+ int max_stretch;
+ int step;
+ /*tex special characters, see \TEX book */
+ int hyphen_char;
+ int skew_char;
+ /*tex all parameters, although only some are used */
+ int parameter_count;
+ scaled *parameter_base;
+ /* */
+ int padding;
+ /*tex also special */
+ charinfo *left_boundary;
+ charinfo *right_boundary;
+ /*tex all math parameters */
+ scaled *math_parameter_base;
+ int math_parameter_count;
+ /* zero is alignment */
+ int mathscales[3];
+} texfont;
+
+/*tex
+
+ Instead of global variables we store some properties that are shared between the different components
+ in a dedicated struct.
+
+*/
+
+typedef struct font_state_info {
+ texfont **fonts;
+ halfword adjust_stretch;
+ halfword adjust_shrink;
+ halfword adjust_step;
+ int padding;
+ memory_data font_data;
+} font_state_info ;
+
+extern font_state_info lmt_font_state;
+
+# define font_size(a) lmt_font_state.fonts[a]->size
+# define font_name(a) lmt_font_state.fonts[a]->name
+# define font_original(a) lmt_font_state.fonts[a]->original
+# define font_design_size(a) lmt_font_state.fonts[a]->design_size
+# define font_first_character(a) lmt_font_state.fonts[a]->first_character
+# define font_last_character(a) lmt_font_state.fonts[a]->last_character
+/*define font_touched(a) font_state.fonts[a]->touched */
+# define font_oldmath(a) lmt_font_state.fonts[a]->oldmath
+# define font_compactmath(a) lmt_font_state.fonts[a]->compactmath
+# define font_mathcontrol(a) lmt_font_state.fonts[a]->mathcontrol
+# define font_textcontrol(a) lmt_font_state.fonts[a]->textcontrol
+# define font_hyphen_char(a) lmt_font_state.fonts[a]->hyphen_char
+# define font_skew_char(a) lmt_font_state.fonts[a]->skew_char
+# define font_max_shrink(a) (lmt_font_state.adjust_step > 0 ? lmt_font_state.adjust_shrink : lmt_font_state.fonts[a]->max_shrink)
+# define font_max_stretch(a) (lmt_font_state.adjust_step > 0 ? lmt_font_state.adjust_stretch : lmt_font_state.fonts[a]->max_stretch)
+# define font_step(a) (lmt_font_state.adjust_step > 0 ? lmt_font_state.adjust_step : lmt_font_state.fonts[a]->step)
+# define font_mathscale(a,b) lmt_font_state.fonts[a]->mathscales[b]
+
+# define set_font_size(a,b) lmt_font_state.fonts[a]->size = b
+# define set_font_name(a,b) lmt_font_state.fonts[a]->name = b
+# define set_font_original(a,b) lmt_font_state.fonts[a]->original = b
+# define set_font_design_size(a,b) lmt_font_state.fonts[a]->design_size = b
+# define set_font_first_character(a,b) lmt_font_state.fonts[a]->first_character = b
+# define set_font_last_character(a,b) lmt_font_state.fonts[a]->last_character = b
+/*define set_font_touched(a,b) font_state.fonts[a]->touched = b */
+# define set_font_oldmath(a,b) lmt_font_state.fonts[a]->oldmath = b
+# define set_font_compactmath(a,b) lmt_font_state.fonts[a]->compactmath = b
+# define set_font_mathcontrol(a,b) lmt_font_state.fonts[a]->mathcontrol = b
+# define set_font_textcontrol(a,b) lmt_font_state.fonts[a]->textcontrol = b
+# define set_font_hyphen_char(a,b) lmt_font_state.fonts[a]->hyphen_char = b
+# define set_font_skew_char(a,b) lmt_font_state.fonts[a]->skew_char = b
+# define set_font_max_shrink(a,b) lmt_font_state.fonts[a]->max_shrink = b
+# define set_font_max_stretch(a,b) lmt_font_state.fonts[a]->max_stretch = b
+# define set_font_step(a,b) lmt_font_state.fonts[a]->step = b
+
+# define set_font_textsize(a,b) lmt_font_state.fonts[a]->mathscales[0] = b
+# define set_font_scriptsize(a,b) lmt_font_state.fonts[a]->mathscales[1] = b
+# define set_font_scriptscriptsize(a,b) lmt_font_state.fonts[a]->mathscales[2] = b
+
+/*tex
+ These are bound to a font. There might be a few more in the future. An example is collapsing
+ hyphens. One can do that using (in context speak) tlig feature but actually it is some very
+ \TEX\ thing, that happened to be implemented using ligatures. In \LUAMETATEX\ it's also a bit
+ special because, although it is not really dependent on a language, hyphen handling in \TEX\
+ is very present in the hyphenator (also sequences of them). So, naturally it moved there. But
+ users who don't want it can disable it per font.
+*/
+
+typedef enum text_control_codes {
+ text_control_collapse_hyphens = 0x00001,
+} text_control_codes;
+
+# define has_font_text_control(f,c) ((font_textcontrol(f) & c) == c)
+
+/*tex
+
+ These are special codes that are used in the traditional ligature builder. In \OPENTYPE\
+ fonts we don't see these.
+
+*/
+
+typedef enum boundarychar_codes {
+ left_boundary_char = -1,
+ right_boundary_char = -2,
+ non_boundary_char = -3,
+} boundarychar_codes;
+
+/*tex These are pointers, so: |NULL| */
+
+# define font_left_boundary(a) lmt_font_state.fonts[a]->left_boundary
+# define font_right_boundary(a) lmt_font_state.fonts[a]->right_boundary
+
+# define font_has_left_boundary(a) (font_left_boundary(a))
+# define font_has_right_boundary(a) (font_right_boundary(a))
+
+# define set_font_left_boundary(a,b) { if (font_left_boundary(a)) { lmt_memory_free(font_left_boundary(a)); } font_left_boundary(a) = b; }
+# define set_font_right_boundary(a,b) { if (font_right_boundary(a)) { lmt_memory_free(font_right_boundary(a)); } font_right_boundary(a) = b; }
+
+/*tex
+
+ In traditional \TEX\ there are just over a handful of font specific parameters for text fonts
+ and some more in math fonts. Actually, these parameters were stored in a way that permitted
+ adding more at runtime, something that made no real sense, but can be abused for creeating
+ more dimensions than the 256 that traditional \TEX\ provides.
+
+*/
+
+# define font_parameter_count(a) lmt_font_state.fonts[a]->parameter_count
+# define font_parameter_base(a) lmt_font_state.fonts[a]->parameter_base
+# define font_parameter(a,b) lmt_font_state.fonts[a]->parameter_base[b]
+
+# define font_math_parameter_count(a) lmt_font_state.fonts[a]->math_parameter_count
+# define font_math_parameter_base(a) lmt_font_state.fonts[a]->math_parameter_base
+# define font_math_parameter(a,b) lmt_font_state.fonts[a]->math_parameter_base[b]
+
+# define set_font_parameter_base(a,b) lmt_font_state.fonts[a]->parameter_base = b;
+# define set_font_math_parameter_base(a,b) lmt_font_state.fonts[a]->math_parameter_base = b;
+
+/*tex
+
+ These font parameters could be adapted at runtime but one should really wonder if that is such
+ a good idea nowadays.
+
+ */
+
+//define set_font_parameter(f,n,b) { if (font_parameter_count(f) < n) { tex_set_font_parameters(f, n); } font_parameter(f, n) = b; }
+// # define set_font_math_parameter(f,n,b) { if (font_math_parameter_count(f) < n) { tex_set_font_math_parameters(f, n); } font_math_parameter(f, n) = b; }
+
+extern void tex_set_font_parameters (halfword f, int b);
+extern void tex_set_font_math_parameters (halfword f, int b);
+extern int tex_get_font_max_id (void);
+extern int tex_get_font_max_id (void);
+
+extern halfword tex_checked_font_adjust (
+ halfword adjust_spacing,
+ halfword adjust_spacing_step,
+ halfword adjust_spacing_shrink,
+ halfword adjust_spacing_stretch
+);
+
+/*tex
+
+ Font parameters are sometimes referred to as |slant(f)|, |space(f)|, etc. These numbers are
+ also the font dimen numbers.
+
+*/
+
+typedef enum font_parameter_codes {
+ slant_code = 1,
+ space_code,
+ space_stretch_code,
+ space_shrink_code,
+ ex_height_code,
+ em_width_code,
+ extra_space_code,
+} font_parameter_codes;
+
+extern scaled tex_get_font_slant (halfword f);
+extern scaled tex_get_font_space (halfword f);
+extern scaled tex_get_font_space_stretch (halfword f);
+extern scaled tex_get_font_space_shrink (halfword f);
+extern scaled tex_get_font_ex_height (halfword f);
+extern scaled tex_get_font_em_width (halfword f);
+extern scaled tex_get_font_extra_space (halfword f);
+extern scaled tex_get_font_parameter (halfword f, halfword code);
+extern void tex_set_font_parameter (halfword f, halfword code, scaled v);
+
+extern scaled tex_get_scaled_space (halfword f);
+extern scaled tex_get_scaled_space_stretch (halfword f);
+extern scaled tex_get_scaled_space_shrink (halfword f);
+extern scaled tex_get_scaled_ex_height (halfword f);
+extern scaled tex_get_scaled_em_width (halfword f);
+extern scaled tex_get_scaled_extra_space (halfword f);
+extern scaled tex_get_scaled_parameter (halfword f, halfword code);
+extern void tex_set_scaled_parameter (halfword f, halfword code, scaled v);
+
+extern halfword tex_get_scaled_glue (halfword f);
+extern halfword tex_get_scaled_parameter_glue (quarterword p, quarterword s);
+extern halfword tex_get_parameter_glue (quarterword p, quarterword s);
+
+extern halfword tex_get_font_identifier (halfword fs);
+
+/*tex
+
+ The \OPENTYPE\ math fonts have four edges and reference points for kerns. Here we go:
+
+*/
+
+typedef enum font_math_kern_codes {
+ top_right_kern = 1,
+ bottom_right_kern,
+ bottom_left_kern,
+ top_left_kern,
+} font_math_kern_codes;
+
+extern charinfo *tex_get_charinfo (halfword f, int c);
+extern int tex_char_exists (halfword f, int c);
+extern void tex_char_process (halfword f, int c);
+extern int tex_math_char_exists (halfword f, int c, int size);
+extern int tex_get_math_char (halfword f, int c, int size, scaled *scale);
+
+/*tex
+
+ Here is a quick way to test if a glyph exists, when you are already certain the font |f| exists,
+ and that the |c| is a regular glyph id, not one of the two special boundary objects. Contrary
+ to traditional \TEX\ we store character information in a hash table instead of an array. Keep
+ in mind that we talk \UNICODE: plenty of characters in the code space, but less so in a font,
+ so we can best be sparse.
+
+*/
+
+# define quick_char_exists(f,c) (sa_get_item_4(lmt_font_state.fonts[f]->characters,c).int_value)
+
+/*tex
+ These low level setters are not publis and used in helpers. They might become functions
+ when I feel the need.
+*/
+
+# define set_charinfo_width(ci,val) ci->width = val;
+# define set_charinfo_height(ci,val) ci->height = val;
+# define set_charinfo_depth(ci,val) ci->depth = val;
+# define set_charinfo_italic(ci,val) ci->italic = val;
+# define set_charinfo_expansion(ci,val) ci->expansion = val;
+# define set_charinfo_leftprotrusion(ci,val) ci->leftprotrusion = val;
+# define set_charinfo_rightprotrusion(ci,val) ci->rightprotrusion = val;
+
+# define set_charinfo_tag(ci,tag) ci->tagrem = charinfo_tagrem(charinfo_tag(ci->tagrem) | tag,charinfo_rem(ci->tagrem));
+# define set_charinfo_remainder(ci,rem) ci->tagrem = charinfo_tagrem(charinfo_tag(ci->tagrem),rem);
+
+# define has_charinfo_tag(ci,p) (charinfo_tag(ci->tagrem) & (p) == (p))
+# define get_charinfo_tag(ci) charinfo_tag(ci->tagrem)
+
+# define set_charinfo_ligatures(ci,val) { lmt_memory_free(ci->ligatures); ci->ligatures = val; }
+# define set_charinfo_kerns(ci,val) { lmt_memory_free(ci->kerns); ci->kerns = val; }
+# define set_charinfo_math(ci,val) { lmt_memory_free(ci->math); ci->math = val; }
+
+# define set_charinfo_top_left_math_kern_array(ci,val) if (ci->math) { lmt_memory_free(ci->math->top_left_math_kern_array); ci->math->top_left_math_kern_array = val; }
+# define set_charinfo_top_right_math_kern_array(ci,val) if (ci->math) { lmt_memory_free(ci->math->top_right_math_kern_array); ci->math->top_left_math_kern_array = val; }
+# define set_charinfo_bottom_right_math_kern_array(ci,val) if (ci->math) { lmt_memory_free(ci->math->bottom_right_math_kern_array); ci->math->top_left_math_kern_array = val; }
+# define set_charinfo_bottom_left_math_kern_array(ci,val) if (ci->math) { lmt_memory_free(ci->math->bottom_left_math_kern_array); ci->math->top_left_math_kern_array = val; }
+
+//define set_charinfo_options(ci,val) if (ci->math) { ci->math->options = val; }
+
+# define set_ligature_item(f,b,c,d) { f.type = b; f.adjacent = c; f.ligature = d; }
+# define set_kern_item(f,b,c) { f.adjacent = b; f.kern = c; }
+
+# define set_charinfo_left_margin(ci,val) if (ci->math) { ci->math->left_margin = val; }
+# define set_charinfo_right_margin(ci,val) if (ci->math) { ci->math->right_margin = val; }
+# define set_charinfo_top_margin(ci,val) if (ci->math) { ci->math->top_margin = val; }
+# define set_charinfo_bottom_margin(ci,val) if (ci->math) { ci->math->bottom_margin = val; }
+
+# define set_charinfo_smaller(ci,val) if (ci->math) { ci->math->smaller = val; }
+# define set_charinfo_vertical_italic(ci,val) if (ci->math) { ci->math->vertical_italic = val; }
+# define set_charinfo_top_accent(ci,val) if (ci->math) { ci->math->top_accent = val; }
+# define set_charinfo_bottom_accent(ci,val) if (ci->math) { ci->math->bottom_accent = val; }
+# define set_charinfo_flat_accent(ci,val) if (ci->math) { ci->math->flat_accent = val; }
+
+# define set_charinfo_top_left_kern(ci,val) if (ci->math) { ci->math->top_left_kern = val; }
+# define set_charinfo_top_right_kern(ci,val) if (ci->math) { ci->math->top_right_kern = val; }
+# define set_charinfo_bottom_left_kern(ci,val) if (ci->math) { ci->math->bottom_left_kern = val; }
+# define set_charinfo_bottom_right_kern(ci,val) if (ci->math) { ci->math->bottom_right_kern = val; }
+
+/*tex Setters: */
+
+void tex_set_lpcode_in_font (halfword f, halfword c, halfword i);
+void tex_set_rpcode_in_font (halfword f, halfword c, halfword i);
+void tex_set_efcode_in_font (halfword f, halfword c, halfword i);
+
+extern void tex_set_charinfo_extensible (charinfo *ci, int top, int bottom, int middle, int extender);
+extern void tex_add_charinfo_math_kern (charinfo *ci, int type, scaled ht, scaled krn);
+extern int tex_get_charinfo_math_kerns (charinfo *ci, int id);
+extern void tex_set_charinfo_horizontal_parts (charinfo *ci, extinfo *ext);
+extern void tex_set_charinfo_vertical_parts (charinfo *ci, extinfo *ext);
+extern void tex_add_charinfo_vertical_part (charinfo *ci, extinfo *ext);
+extern void tex_add_charinfo_horizontal_part (charinfo *ci, extinfo *ext);
+extern extinfo *tex_new_charinfo_part (int glyph, int startconnect, int endconnect, int advance, int repeater);
+
+/*tex Checkers: */
+
+int tex_char_has_math (halfword f, halfword c);
+int tex_has_ligature (halfword f, halfword c);
+int tex_has_kern (halfword f, halfword c);
+
+/*tex Getters: */
+
+# define MATH_KERN_NOT_FOUND 0x7FFFFFFF
+
+extern scaled tex_char_width_from_font (halfword f, halfword c); /* math + maincontrol */
+extern scaled tex_char_height_from_font (halfword f, halfword c); /* math + maincontrol */
+extern scaled tex_char_depth_from_font (halfword f, halfword c); /* math + maincontrol */
+extern scaled tex_char_total_from_font (halfword f, halfword c); /* math */
+extern scaled tex_char_italic_from_font (halfword f, halfword c); /* math + maincontrol */
+// halfword tex_char_options_from_font (halfword f, halfword c);
+extern scaled tex_char_ef_from_font (halfword f, halfword c); /* packaging + maincontrol */
+extern scaled tex_char_lp_from_font (halfword f, halfword c); /* packaging + maincontrol */
+extern scaled tex_char_rp_from_font (halfword f, halfword c); /* packaging + maincontrol */
+extern halfword tex_char_tag_from_font (halfword f, halfword c); /* math */
+extern halfword tex_char_remainder_from_font (halfword f, halfword c); /* math */
+extern halfword tex_char_has_tag_from_font (halfword f, halfword c, halfword tag);
+extern void tex_char_reset_tag_from_font (halfword f, halfword c, halfword tag);
+// int tex_char_has_option_from_font (halfword g, halfword c, int option);
+
+extern scaled tex_char_top_left_kern_from_font (halfword f, halfword c); /* math */
+extern scaled tex_char_top_right_kern_from_font (halfword f, halfword c); /* math */
+extern scaled tex_char_bottom_left_kern_from_font (halfword f, halfword c); /* math */
+extern scaled tex_char_bottom_right_kern_from_font (halfword f, halfword c); /* math */
+
+extern scaledwhd tex_char_whd_from_font (halfword f, halfword c); /* math + maincontrol */
+
+extern scaled tex_font_x_scaled (scaled v);
+extern scaled tex_font_y_scaled (scaled v);
+
+extern scaled tex_char_width_from_glyph (halfword g); /* x/y scaled */
+extern scaled tex_char_height_from_glyph (halfword g); /* x/y scaled */
+extern scaled tex_char_depth_from_glyph (halfword g); /* x/y scaled */
+extern scaled tex_char_total_from_glyph (halfword g); /* x/y scaled */
+extern scaled tex_char_italic_from_glyph (halfword g); /* x/y scaled */
+// int tex_char_options_from_glyph (halfword g);
+extern scaled tex_char_width_italic_from_glyph (halfword g); /* x/y scaled */
+// int tex_char_has_option_from_glyph (halfword g, int option);
+
+extern scaledwhd tex_char_whd_from_glyph (halfword g); /* x/y scaled */
+
+extern halfword tex_char_vertical_italic_from_font (halfword f, halfword c);
+extern halfword tex_char_top_accent_from_font (halfword f, halfword c);
+extern halfword tex_char_bot_accent_from_font (halfword f, halfword c);
+extern halfword tex_char_flat_accent_from_font (halfword f, halfword c);
+
+extern halfword tex_char_top_anchor_from_font (halfword f, halfword c);
+extern halfword tex_char_bot_anchor_from_font (halfword f, halfword c);
+
+extern scaled tex_char_left_margin_from_font (halfword f, halfword c);
+extern scaled tex_char_right_margin_from_font (halfword f, halfword c);
+extern scaled tex_char_top_margin_from_font (halfword f, halfword c);
+extern scaled tex_char_bottom_margin_from_font (halfword f, halfword c);
+
+extern extinfo *tex_char_vertical_parts_from_font (halfword f, halfword c);
+extern extinfo *tex_char_horizontal_parts_from_font (halfword f, halfword c);
+
+/* scaled tex_math_kern_at (halfword f, int c, int side, int v); */
+/* scaled tex_find_math_kern (halfword l_f, int l_c, halfword r_f, int r_c, int cmd, scaled shift); */
+
+extern int tex_valid_kern (halfword left, halfword right); /* returns kern */
+extern int tex_valid_ligature (halfword left, halfword right, int *slot); /* returns type */
+
+extern scaled tex_calculated_char_width (halfword f, halfword c, halfword ex);
+extern scaled tex_calculated_glyph_width (halfword g, halfword ex); /* scale */
+
+/*
+ Kerns: the |otherchar| value signals \quote {stop}. These are not really public and only
+ to be used in the helpers. But we keep them as reference.
+*/
+
+# define end_kern 0x7FFFFF
+
+# define charinfo_kern(b,c) b->kerns[c]
+
+# define kern_char(b) (b).adjacent
+# define kern_kern(b) (b).kern
+# define kern_end(b) ((b).adjacent == end_kern)
+# define kern_disabled(b) ((b).adjacent > end_kern)
+
+/*
+ Ligatures: the |otherchar| value signals \quote {stop}. These are not really public and only
+ to be used in the helpers. But we keep them as reference.
+*/
+
+# define end_of_ligature_code 0x7FFFFF
+
+# define charinfo_ligature(b,c) b->ligatures[c]
+
+# define ligature_is_valid(a) ((a).type != 0)
+# define ligature_type(a) ((a).type >> 1)
+# define ligature_char(a) (a).adjacent
+# define ligature_replacement(a) (a).ligature
+# define ligature_end(a) ((a).adjacent == end_of_ligature_code)
+# define ligature_disabled(a) ((a).adjacent > end_of_ligature_code)
+
+/* Remainders and related flags: */
+
+typedef enum math_extension_modes {
+ math_extension_normal,
+ math_extension_repeat,
+} math_extension_modes;
+
+/* Expansion */
+
+typedef enum adjust_spacing_modes {
+ adjust_spacing_off,
+ adjust_spacing_unused,
+ adjust_spacing_full,
+ adjust_spacing_font,
+} adjust_spacing_modes;
+
+typedef enum protrude_chars_modes {
+ protrude_chars_off,
+ protrude_chars_unused,
+ protrude_chars_normal,
+ protrude_chars_advanced,
+} protrude_chars_modes;
+
+/*
+typedef enum math_extension_locations {
+ extension_top,
+ extension_bottom,
+ extension_middle,
+ extension_repeat,
+} math_extension_locations;
+*/
+
+/* Tags: */
+
+typedef enum tag_codes {
+ no_tag = 0x00, /*tex vanilla character */
+ ligature_tag = 0x01, /*tex character has a ligature/kerning program */
+ list_tag = 0x02, /*tex character has a successor in a charlist */
+ extension_tag = 0x04, /*tex character is extensible */
+ callback_tag = 0x08,
+ extend_last_tag = 0x10,
+} tag_codes;
+
+extern halfword tex_checked_font (halfword f);
+extern int tex_is_valid_font (halfword f);
+extern int tex_raw_get_kern (halfword f, int lc, int rc);
+extern int tex_get_kern (halfword f, int lc, int rc);
+extern ligatureinfo tex_get_ligature (halfword f, int lc, int rc);
+extern int tex_new_font (void);
+extern int tex_new_font_id (void);
+extern void tex_font_malloc_charinfo (halfword f, int num);
+extern void tex_char_malloc_mathinfo (charinfo * ci);
+extern void tex_dump_font_data (dumpstream f);
+extern void tex_undump_font_data (dumpstream f);
+extern void tex_create_null_font (void);
+extern void tex_delete_font (int id);
+extern int tex_read_font_info (char *cnom, scaled s);
+extern int tex_fix_expand_value (halfword f, int e);
+
+extern halfword tex_handle_glyphrun (halfword head, halfword group, halfword direction);
+extern halfword tex_handle_ligaturing (halfword head, halfword tail);
+extern halfword tex_handle_kerning (halfword head, halfword tail);
+
+extern void tex_set_cur_font (halfword g, halfword f);
+extern int tex_tex_def_font (int a);
+
+extern void tex_char_warning (halfword f, int c);
+
+extern void tex_initialize_fonts (void);
+
+extern void tex_set_font_name (halfword f, const char *s);
+extern void tex_set_font_original (halfword f, const char *s);
+
+extern scaled tex_get_math_font_scale (halfword f, halfword size);
+
+extern void tex_run_font_spec (void);
+
+# endif