diff options
Diffstat (limited to 'source/luametatex/source/tex/texrules.c')
-rw-r--r-- | source/luametatex/source/tex/texrules.c | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/source/luametatex/source/tex/texrules.c b/source/luametatex/source/tex/texrules.c new file mode 100644 index 000000000..1a3040585 --- /dev/null +++ b/source/luametatex/source/tex/texrules.c @@ -0,0 +1,248 @@ +/* + See license.txt in the root of this project. +*/ + +# include "luametatex.h" + +halfword tex_aux_scan_rule_spec(rule_types t, halfword s) +{ + /*tex |width|, |depth|, and |height| all equal |null_flag| now */ + halfword rule = tex_new_rule_node((quarterword) s); + halfword attr = node_attr(rule); + switch (t) { + case h_rule_type: + rule_height(rule) = default_rule; + rule_depth(rule) = 0; + break; + case v_rule_type: + case m_rule_type: + if (s == strut_rule_code) { + rule_width(rule) = 0; + node_subtype(rule) = strut_rule_subtype; + rule_height(rule) = null_flag; + rule_depth(rule) = null_flag; + } else { + rule_width(rule) = default_rule; + } + break; + } + while (1) { + /*tex + Maybe: + + h : "whdxylrWHDXYLR" + v : "whdxytbWHDXYTB" + m : "whdxylrtbWHDXYLRTB" + + but for now we are tolerant because internally it's left/right anyway. + + */ + switch (tex_scan_character("awhdxylrtbcfAWHDXYLRTBCF", 0, 1, 0)) { + case 0: + goto DONE; + case 'a': case 'A': + if (tex_scan_mandate_keyword("attr", 1)) { + halfword i = tex_scan_attribute_register_number(); + halfword v = tex_scan_int(1, NULL); + if (eq_value(register_attribute_location(i)) != v) { + if (attr) { + attr = tex_patch_attribute_list(attr, i, v); + } else { + attr = tex_copy_attribute_list_set(tex_current_attribute_list(), i, v); + } + } + } + break; + case 'w': case 'W': + if (tex_scan_mandate_keyword("width", 1)) { + rule_width(rule) = tex_scan_dimen(0, 0, 0, 0, NULL); + } + break; + case 'h': case 'H': + if (tex_scan_mandate_keyword("height", 1)) { + rule_height(rule) = tex_scan_dimen(0, 0, 0, 0, NULL); + } + break; + case 'd': case 'D': + if (tex_scan_mandate_keyword("depth", 1)) { + rule_depth(rule) = tex_scan_dimen(0, 0, 0, 0, NULL); + } + break; + case 'l': case 'L': + if (tex_scan_mandate_keyword("left", 1)) { + rule_left(rule) = tex_scan_dimen(0, 0, 0, 0, NULL); + } + break; + case 'r': case 'R': + if (tex_scan_mandate_keyword("right", 1)) { + rule_right(rule) = tex_scan_dimen(0, 0, 0, 0, NULL); + } + break; + case 't': case 'T': /* just because it's nicer */ + if (tex_scan_mandate_keyword("top", 1)) { + rule_left(rule) = tex_scan_dimen(0, 0, 0, 0, NULL); + } + break; + case 'b': case 'B': /* just because it's nicer */ + if (tex_scan_mandate_keyword("bottom", 1)) { + rule_right(rule) = tex_scan_dimen(0, 0, 0, 0, NULL); + } + break; + case 'x': case 'X': + if (tex_scan_mandate_keyword("xoffset", 1)) { + rule_x_offset(rule) = tex_scan_dimen(0, 0, 0, 0, NULL); + } + break; + case 'y': case 'Y': + if (tex_scan_mandate_keyword("yoffset", 1)) { + rule_y_offset(rule) = tex_scan_dimen(0, 0, 0, 0, NULL); + } + break; + case 'f': case 'F': + switch (tex_scan_character("aoAO", 0, 0, 0)) { + case 'o': case 'O': + if (tex_scan_mandate_keyword("font", 2)) { + tex_set_rule_font(rule, tex_scan_font_identifier(NULL)); + } + break; + case 'a': case 'A': + if (tex_scan_mandate_keyword("fam", 2)) { + tex_set_rule_family(rule, tex_scan_math_family_number()); + } + break; + default: + tex_aux_show_keyword_error("font|fam"); + goto DONE; + } + break; + case 'c': case 'C': + if (tex_scan_mandate_keyword("char", 1)) { + rule_character(rule) = tex_scan_char_number(0); + } + break; + default: + goto DONE; + } + } + DONE: + node_attr(rule) = attr; + if (t == v_rule_type && s == strut_rule_code) { + tex_aux_check_text_strut_rule(rule, text_style); + } + return rule; +} + +void tex_aux_run_vrule(void) +{ + tex_tail_append(tex_aux_scan_rule_spec(v_rule_type, cur_chr)); + cur_list.space_factor = 1000; +} + +void tex_aux_run_hrule(void) +{ + tex_tail_append(tex_aux_scan_rule_spec(h_rule_type, cur_chr)); + cur_list.prev_depth = ignore_depth; +} + +void tex_aux_run_mrule(void) +{ + tex_tail_append(tex_aux_scan_rule_spec(m_rule_type, cur_chr)); +} + +void tex_aux_check_math_strut_rule(halfword rule, halfword style) +{ + if (node_subtype(rule) == strut_rule_subtype) { + scaled ht = rule_height(rule); + scaled dp = rule_depth(rule); + if (ht == null_flag || dp == null_flag) { + halfword fnt = tex_get_rule_font(rule, style); + halfword chr = rule_character(rule); + if (fnt > 0 && chr && tex_char_exists(fnt, chr)) { + if (ht == null_flag) { + ht = tex_math_font_char_ht(fnt, chr, style); + } + if (dp == null_flag) { + dp = tex_math_font_char_dp(fnt, chr, style); + } + } else { + if (ht == null_flag) { + ht = tex_get_math_y_parameter(style, math_parameter_rule_height); + } + if (dp == null_flag) { + dp = tex_get_math_y_parameter(style, math_parameter_rule_depth); + } + } + rule_height(rule) = ht; + rule_depth(rule) = dp; + } + } +} + +void tex_aux_check_text_strut_rule(halfword rule, halfword style) +{ + if (node_subtype(rule) == strut_rule_subtype) { + scaled ht = rule_height(rule); + scaled dp = rule_depth(rule); + if (ht == null_flag || dp == null_flag) { + halfword fnt = tex_get_rule_font(rule, style); + halfword chr = rule_character(rule); + if (fnt > 0 && chr && tex_char_exists(fnt, chr)) { + if (ht == null_flag) { + ht = tex_char_height_from_font(fnt, chr); + } + if (dp == null_flag) { + dp = tex_char_depth_from_font(fnt, chr); + } + } + rule_height(rule) = ht; + rule_depth(rule) = dp; + } + } +} + +halfword tex_get_rule_font(halfword n, halfword style) +{ + halfword fnt = rule_font(n); + if (fnt > rule_font_fam_offset) { + halfword fam = fnt - rule_font_fam_offset; + if (fam_par_in_range(fam)) { + fnt = tex_fam_fnt(fam, tex_size_of_style(style)); + } + } + if (fnt < 0 || fnt >= max_n_of_fonts) { + return null_font; + } else { + return fnt; + } +} + +halfword tex_get_rule_family(halfword n) +{ + halfword fnt = rule_font(n); + if (fnt > rule_font_fam_offset) { + halfword fam = fnt - rule_font_fam_offset; + if (fam_par_in_range(fam)) { + return fam; + } + } + return 0; +} + +void tex_set_rule_font(halfword n, halfword fnt) +{ + if (fnt < 0 || fnt >= rule_font_fam_offset) { + rule_font(n) = 0; + } else { + rule_font(n) = fnt; + } +} + +void tex_set_rule_family(halfword n, halfword fam) +{ + if (fam < 0 || fam >= max_n_of_math_families) { + rule_font(n) = rule_font_fam_offset; + } else { + rule_font(n) = rule_font_fam_offset + fam; + } +} + |