#include "xetex-core.h"
#include "xetex-xetexd.h"
#include <algorithm>
#include "tectonic_xetex_layout.h"
#include "xetex-XeTeXOTMath.h"
int
get_ot_math_constant(int f, int n)
{
hb_ot_math_constant_t constant = (hb_ot_math_constant_t) n;
hb_position_t rval = 0;
if (font_area[f] == OTGR_FONT_FLAG) {
XeTeXFont font = getFont((XeTeXLayoutEngine) font_layout_engine[f]);
hb_font_t *hbFont = ttxl_get_hb_font((XeTeXLayoutEngine) font_layout_engine[f]);
rval = hb_ot_math_get_constant(hbFont, constant);
switch (constant) {
case HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN:
case HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN:
case HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT:
break;
default:
rval = D2Fix(ttxl_font_units_to_points(font, rval));
break;
}
}
return rval;
}
#define unknown ((hb_ot_math_constant_t) -1)
#define math_x_height 5
#define math_quad 6
#define num1 8
#define num2 9
#define num3 10
#define denom1 11
#define denom2 12
#define sup1 13
#define sup2 14
#define sup3 15
#define sub1 16
#define sub2 17
#define sup_drop 18
#define sub_drop 19
#define delim1 20
#define delim2 21
#define axis_height 22
const hb_ot_math_constant_t TeX_sym_to_OT_map[] = {
unknown,
unknown,
unknown,
unknown,
unknown,
HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT, unknown, unknown,
HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP,
HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP,
HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP,
HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN,
HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN,
HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP, HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP, HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED,
HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN, HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX, HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN, HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT,
unknown, HB_OT_MATH_CONSTANT_AXIS_HEIGHT
};
int
get_native_mathsy_param(int f, int n)
{
int rval = 0;
if (n == math_quad) {
rval = font_size[f];
}
else if (n == delim2) { rval = std::min<int>(1.5 * font_size[f], get_native_mathsy_param(f, delim1));
}
else {
if (n < (int) (sizeof(TeX_sym_to_OT_map) / sizeof(hb_ot_math_constant_t))) {
hb_ot_math_constant_t ot_index = TeX_sym_to_OT_map[n];
if (ot_index != unknown)
rval = get_ot_math_constant(f, (int)ot_index);
}
}
return rval;
}
#define default_rule_thickness 8
#define big_op_spacing1 9
#define big_op_spacing2 10
#define big_op_spacing3 11
#define big_op_spacing4 12
#define big_op_spacing5 13
const hb_ot_math_constant_t TeX_ext_to_OT_map[] = {
unknown,
unknown,
unknown,
unknown,
unknown,
HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT, unknown, unknown,
HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS, HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN, HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN, HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN, HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN, HB_OT_MATH_CONSTANT_STACK_GAP_MIN };
int
get_native_mathex_param(int f, int n)
{
int rval = 0;
if (n == math_quad)
rval = font_size[f];
else {
if (n < (int) (sizeof(TeX_ext_to_OT_map) / sizeof(hb_ot_math_constant_t))) {
hb_ot_math_constant_t ot_index = TeX_ext_to_OT_map[n];
if (ot_index != unknown)
rval = get_ot_math_constant(f, (int)ot_index);
}
}
return rval;
}
int
get_ot_math_variant(int f, int g, int v, int32_t* adv, int horiz)
{
hb_codepoint_t rval = g;
*adv = -1;
if (font_area[f] == OTGR_FONT_FLAG) {
XeTeXFont font = getFont((XeTeXLayoutEngine) font_layout_engine[f]);
hb_font_t *hbFont = ttxl_get_hb_font((XeTeXLayoutEngine) font_layout_engine[f]);
hb_ot_math_glyph_variant_t variant[1];
unsigned int count = 1;
hb_ot_math_get_glyph_variants(hbFont, g, horiz ? HB_DIRECTION_RTL : HB_DIRECTION_TTB, v, &count, variant);
if (count > 0) {
rval = variant->glyph;
*adv = D2Fix(ttxl_font_units_to_points(font, variant->advance));
}
}
return rval;
}
void *
get_ot_assembly_ptr(int f, int g, int horiz)
{
void *rval = NULL;
if (font_area[f] == OTGR_FONT_FLAG) {
hb_font_t *hbFont = ttxl_get_hb_font((XeTeXLayoutEngine) font_layout_engine[f]);
unsigned int count = hb_ot_math_get_glyph_assembly(hbFont, g,
horiz ? HB_DIRECTION_RTL : HB_DIRECTION_TTB,
0, NULL, NULL, NULL);
if (count > 0) {
GlyphAssembly *a = (GlyphAssembly *) xmalloc(sizeof(GlyphAssembly));
a->count = count;
a->parts = (hb_ot_math_glyph_part_t *) xmalloc(count * sizeof(hb_ot_math_glyph_part_t));
hb_ot_math_get_glyph_assembly(hbFont, g,
horiz ? HB_DIRECTION_RTL : HB_DIRECTION_TTB,
0, &a->count, a->parts, NULL);
rval = (void *) a;
}
}
return rval;
}
void
free_ot_assembly(GlyphAssembly* a)
{
if (!a)
return;
free(a->parts);
free(a);
}
int
get_ot_math_ital_corr(int f, int g)
{
hb_position_t rval = 0;
if (font_area[f] == OTGR_FONT_FLAG) {
XeTeXFont font = getFont((XeTeXLayoutEngine) font_layout_engine[f]);
hb_font_t *hbFont = ttxl_get_hb_font((XeTeXLayoutEngine) font_layout_engine[f]);
rval = hb_ot_math_get_glyph_italics_correction(hbFont, g);
rval = D2Fix(ttxl_font_units_to_points(font, rval));
}
return rval;
}
int
get_ot_math_accent_pos(int f, int g)
{
hb_position_t rval = 0x7fffffffUL;
if (font_area[f] == OTGR_FONT_FLAG) {
XeTeXFont font = getFont((XeTeXLayoutEngine) font_layout_engine[f]);
hb_font_t *hbFont = ttxl_get_hb_font((XeTeXLayoutEngine) font_layout_engine[f]);
rval = hb_ot_math_get_glyph_top_accent_attachment(hbFont, g);
rval = D2Fix(ttxl_font_units_to_points(font, rval));
}
return rval;
}
int
ot_min_connector_overlap(int f)
{
hb_position_t rval = 0;
if (font_area[f] == OTGR_FONT_FLAG) {
XeTeXFont font = getFont((XeTeXLayoutEngine) font_layout_engine[f]);
hb_font_t *hbFont = ttxl_get_hb_font((XeTeXLayoutEngine) font_layout_engine[f]);
rval = hb_ot_math_get_min_connector_overlap(hbFont, HB_DIRECTION_RTL);
rval = D2Fix(ttxl_font_units_to_points(font, rval));
}
return rval;
}
static int
getMathKernAt(int f, int g, int height, hb_ot_math_kern_t side)
{
hb_position_t rval = 0;
if (font_area[f] == OTGR_FONT_FLAG) {
hb_font_t *hbFont = ttxl_get_hb_font((XeTeXLayoutEngine) font_layout_engine[f]);
rval = hb_ot_math_get_glyph_kerning(hbFont, g, side, height);
}
return rval;
}
static float
glyph_height(int f, int g)
{
float rval = 0.0;
if (font_area[f] == OTGR_FONT_FLAG) {
XeTeXLayoutEngine engine = (XeTeXLayoutEngine)font_layout_engine[f];
getGlyphHeightDepth(engine, g, &rval, NULL);
}
return rval;
}
static float
glyph_depth(int f, int g)
{
float rval = 0.0;
if (font_area[f] == OTGR_FONT_FLAG) {
XeTeXLayoutEngine engine = (XeTeXLayoutEngine)font_layout_engine[f];
getGlyphHeightDepth(engine, g, NULL, &rval);
}
return rval;
}
#define sup_cmd 0
#define sub_cmd 1
int
get_ot_math_kern(int f, int g, int sf, int sg, int cmd, int shift_scaled )
{
int rval = 0;
if (font_area[f] == OTGR_FONT_FLAG && font_area[sf] == OTGR_FONT_FLAG) {
XeTeXFont font = getFont((XeTeXLayoutEngine)font_layout_engine[f]);
XeTeXFont sfont = getFont((XeTeXLayoutEngine)font_layout_engine[sf]);
int g_height = ttxl_font_points_to_units(font, glyph_height(f, g));
int g_depth = ttxl_font_points_to_units(font, glyph_depth(f, g));
int sg_height = ttxl_font_points_to_units(sfont, glyph_height(sf, sg));
int sg_depth = ttxl_font_points_to_units(sfont, glyph_depth(sf, sg));
int shift = ttxl_font_points_to_units(font, Fix2D(shift_scaled));
float f_size = ttxl_font_get_point_size(font);
float sf_size = ttxl_font_get_point_size(sfont);
assert(f_size != 0.0);
float scale_factor = sf_size / f_size;
if (cmd == sup_cmd) {
int kern = getMathKernAt(f, g, shift - scale_factor * sg_depth,
HB_OT_MATH_KERN_TOP_RIGHT);
int skern = getMathKernAt(sf, sg, -sg_depth,
HB_OT_MATH_KERN_BOTTOM_LEFT);
int top_kern = kern + scale_factor * skern;
kern = getMathKernAt(f, g, g_height, HB_OT_MATH_KERN_TOP_RIGHT);
skern = getMathKernAt(sf, sg, (g_height - shift) / scale_factor,
HB_OT_MATH_KERN_BOTTOM_LEFT);
int bot_kern = kern + scale_factor * skern;
rval = (top_kern > bot_kern) ? top_kern : bot_kern;
} else if (cmd == sub_cmd) {
int kern = getMathKernAt(f, g, scale_factor * sg_height - shift,
HB_OT_MATH_KERN_BOTTOM_RIGHT);
int skern = getMathKernAt(sf, sg, sg_height,
HB_OT_MATH_KERN_TOP_LEFT);
int top_kern = kern + scale_factor * skern;
kern = getMathKernAt(f, g, -g_depth,
HB_OT_MATH_KERN_BOTTOM_RIGHT);
skern = getMathKernAt(sf, sg, (shift - g_depth) / scale_factor,
HB_OT_MATH_KERN_TOP_LEFT);
int bot_kern = kern + scale_factor * skern;
rval = (top_kern > bot_kern) ? top_kern : bot_kern;
} else {
assert(0); }
rval = D2Fix(ttxl_font_units_to_points(font, rval));
}
return rval;
}
int
ot_part_count(const GlyphAssembly* a)
{
return a->count;
}
int
ot_part_glyph(const GlyphAssembly* a, int i)
{
return a->parts[i].glyph;
}
bool
ot_part_is_extender(const GlyphAssembly* a, int i)
{
return (a->parts[i].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER) != 0;
}
int
ot_part_start_connector(int f, const GlyphAssembly* a, int i)
{
int rval = 0;
if (font_area[f] == OTGR_FONT_FLAG) {
XeTeXFont font = getFont((XeTeXLayoutEngine) font_layout_engine[f]);
rval = D2Fix(ttxl_font_units_to_points(font, a->parts[i].start_connector_length));
}
return rval;
}
int
ot_part_end_connector(int f, const GlyphAssembly* a, int i)
{
int rval = 0;
if (font_area[f] == OTGR_FONT_FLAG) {
XeTeXFont font = getFont((XeTeXLayoutEngine) font_layout_engine[f]);
rval = D2Fix(ttxl_font_units_to_points(font, a->parts[i].end_connector_length));
}
return rval;
}
int
ot_part_full_advance(int f, const GlyphAssembly* a, int i)
{
int rval = 0;
if (font_area[f] == OTGR_FONT_FLAG) {
XeTeXFont font = getFont((XeTeXLayoutEngine) font_layout_engine[f]);
rval = D2Fix(ttxl_font_units_to_points(font, a->parts[i].full_advance));
}
return rval;
}