Skip to content

Commit

Permalink
[80_5] Improving Fraction Box Typesetting
Browse files Browse the repository at this point in the history
## What
Improving Fraction Box Typesetting.

## Why
For some OpenType fonts, the heights of the numerator and denominator in
the fraction box environment are not suitable.

## How to test your changes?
Open `devel/80_5.tmu`.

Before (Anasa Math font):

![image](https://github.com/user-attachments/assets/a6f3d3a4-9ecc-491c-958f-ee3c0be8e4b2)

After:

![image](https://github.com/user-attachments/assets/a8bc5314-6d96-44a9-97f9-899b78f53e5b)
  • Loading branch information
KeShih authored Oct 5, 2024
1 parent 06912c2 commit 0cbd691
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 40 deletions.
20 changes: 20 additions & 0 deletions devel/80_5.tmu
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<TMU|<tuple|1.0.3|1.2.9>>

<style|<tuple|generic|chinese>>

<\body>
<math|<frac|1+3|2+4> <frac|1+<frac|1+<frac|1+<frac|1|2>|2+<frac|1|2>>|2+<frac|1+<frac|1|2>|2+<frac|1|2>>>|1+<frac|1+<frac|1+<frac|1|2>|2+<frac|1|2>>|2+<frac|1+<frac|1|2>|2+<frac|1|2>>>> >

<\equation*>
<frac|1|2> <frac|1+<frac|1+<frac|1+<frac|1|2>|2+<frac|1|2>>|2+<frac|1+<frac|1|2>|2+<frac|1|2>>>|1+<frac|1+<frac|1+<frac|1|2>|2+<frac|1|2>>|2+<frac|1+<frac|1|2>|2+<frac|1|2>>>>\
</equation*>
</body>

<\initial>
<\collection>
<associate|font|Asana Math>
<associate|font-family|rm>
<associate|page-medium|paper>
<associate|page-screen-margin|false>
</collection>
</initial>
9 changes: 9 additions & 0 deletions src/Graphics/Fonts/font.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,15 @@ font_rep::copy_math_pars (font fn) {
upper_limit_baseline_rise_min= fn->upper_limit_baseline_rise_min;
lower_limit_gap_min = fn->lower_limit_gap_min;
lower_limit_baseline_drop_min= fn->lower_limit_baseline_drop_min;
frac_rule_thickness = fn->frac_rule_thickness;
frac_num_shift_up = fn->frac_num_shift_up;
frac_num_disp_shift_up = fn->frac_num_disp_shift_up;
frac_num_gap_min = fn->frac_num_gap_min;
frac_num_disp_gap_min = fn->frac_num_disp_gap_min;
frac_denom_shift_down = fn->frac_denom_shift_down;
frac_denom_disp_shift_down = fn->frac_denom_disp_shift_down;
frac_denom_gap_min = fn->frac_denom_gap_min;
frac_denom_disp_gap_min = fn->frac_denom_disp_gap_min;
}

void
Expand Down
9 changes: 9 additions & 0 deletions src/Graphics/Fonts/font.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,15 @@ struct font_rep : rep<font> {
SI upper_limit_baseline_rise_min;
SI lower_limit_gap_min;
SI lower_limit_baseline_drop_min;
SI frac_rule_thickness;
SI frac_num_shift_up;
SI frac_num_disp_shift_up;
SI frac_num_gap_min;
SI frac_num_disp_gap_min;
SI frac_denom_shift_down;
SI frac_denom_disp_shift_down;
SI frac_denom_gap_min;
SI frac_denom_disp_gap_min;

SI wpt; // width of one point in font
SI hpt; // height of one point in font (usually wpt)
Expand Down
78 changes: 47 additions & 31 deletions src/Plugins/Freetype/unicode_font.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,11 @@ struct unicode_font_rep : font_rep {
SI get_rsup_correction (string s);
SI get_wide_correction (string s, int mode);

SI design_unit_to_metric (int du);
int metric_to_design_unit (SI m);
double design_unit_to_metric_factor;
double metric_to_design_unit_factor;
void init_design_unit_factor ();
SI design_unit_to_metric (int du);
int metric_to_design_unit (SI m);
};

/******************************************************************************
Expand Down Expand Up @@ -444,6 +447,8 @@ unicode_font_rep::unicode_font_rep (string name, string family2, int size2,
this->math_face = math_face2;
this->math_table= math_face2->math_table;
math_type = MATH_TYPE_OPENTYPE;
init_design_unit_factor ();
// limit boxes
upper_limit_gap_min=
design_unit_to_metric (math_table->constants_table[upperLimitGapMin]);
upper_limit_baseline_rise_min= design_unit_to_metric (
Expand All @@ -452,6 +457,26 @@ unicode_font_rep::unicode_font_rep (string name, string family2, int size2,
design_unit_to_metric (math_table->constants_table[lowerLimitGapMin]);
lower_limit_baseline_drop_min= design_unit_to_metric (
math_table->constants_table[lowerLimitBaselineDropMin]);
// frac boxes
frac_rule_thickness= design_unit_to_metric (
math_table->constants_table[fractionRuleThickness]);
frac_num_shift_up= design_unit_to_metric (
math_table->constants_table[fractionNumeratorShiftUp]);
frac_num_disp_shift_up= design_unit_to_metric (
math_table->constants_table[fractionNumeratorDisplayStyleShiftUp]);
frac_num_gap_min= design_unit_to_metric (
math_table->constants_table[fractionNumeratorGapMin]);
frac_num_disp_gap_min= design_unit_to_metric (
math_table->constants_table[fractionNumDisplayStyleGapMin]);
frac_denom_shift_down= design_unit_to_metric (
math_table->constants_table[fractionDenominatorShiftDown]);
frac_denom_disp_shift_down= design_unit_to_metric (
math_table
->constants_table[fractionDenominatorDisplayStyleShiftDown]);
frac_denom_gap_min= design_unit_to_metric (
math_table->constants_table[fractionDenominatorGapMin]);
frac_denom_disp_gap_min= design_unit_to_metric (
math_table->constants_table[fractionDenominatorGapMin]);
}
}
}
Expand Down Expand Up @@ -1003,41 +1028,32 @@ unicode_font (string family, int size, int hdpi, int vdpi) {
* OpenType
******************************************************************************/

inline void
unicode_font_rep::init_design_unit_factor () {
int units_of_m= 0;
SI em = 0;
// get the design units of the width of 'm'
FT_UInt glyph_index= FT_Get_Char_Index (math_face->ft_face, 'm');
FT_Load_Glyph (math_face->ft_face, glyph_index, FT_LOAD_NO_SCALE);
units_of_m= math_face->ft_face->glyph->metrics.horiAdvance;

// get the width of the character 'm'
metric ex;
get_extents ("m", ex);
em= ex->x2 - ex->x1;

metric_to_design_unit_factor= (double) units_of_m / (double) em;
design_unit_to_metric_factor= (double) em / (double) units_of_m;
}

inline SI
unicode_font_rep::design_unit_to_metric (int du) {
// use 'm' as a reference character
static int units_of_m= 0;
static SI em = 0;
if (units_of_m == 0) {
// get the design units of the width of 'm'
FT_UInt glyph_index= FT_Get_Char_Index (math_face->ft_face, 'm');
FT_Load_Glyph (math_face->ft_face, glyph_index, FT_LOAD_NO_SCALE);
units_of_m= math_face->ft_face->glyph->metrics.horiAdvance;

// get the width of the character 'm'
metric ex;
get_extents ("m", ex);
em= ex->x2 - ex->x1;
}
return (SI) ((du * em) / units_of_m);
return (SI) design_unit_to_metric_factor * du;
}

inline int
unicode_font_rep::metric_to_design_unit (SI m) {
static int units_of_m= 0;
static SI em = 0;
if (units_of_m == 0) {
// get the units of the character 'm'
FT_UInt glyph_index= FT_Get_Char_Index (math_face->ft_face, 'm');
FT_Load_Glyph (math_face->ft_face, glyph_index, FT_LOAD_NO_SCALE);
units_of_m= math_face->ft_face->glyph->metrics.horiAdvance;

// get the width of the character 'm'
metric ex;
get_extents ("m", ex);
em= ex->x2 - ex->x1;
}
return (int) ((m * units_of_m) / em);
return (int) metric_to_design_unit_factor * m;
}

font
Expand Down
41 changes: 34 additions & 7 deletions src/Typeset/Boxes/Composite/math_boxes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "Boxes/composite.hpp"
#include "Boxes/construct.hpp"
#include "analyze.hpp"
#include "font.hpp"

/******************************************************************************
* Miscellaneous routines
Expand Down Expand Up @@ -62,15 +63,16 @@ italic_correction (box L, box R) {
struct frac_box_rep : public composite_box_rep {
font fn, sfn;
pencil pen;
frac_box_rep (path ip, box b1, box b2, font fn, font sfn, pencil pen);
frac_box_rep (path ip, box b1, box b2, font fn, font sfn, pencil pen,
bool opentype_disp);
operator tree () { return tree (TUPLE, "frac", bs[0], bs[1]); }
box adjust_kerning (int mode, double factor);
box expand_glyphs (int mode, double factor);
int find_child (SI x, SI y, SI delta, bool force);
};

frac_box_rep::frac_box_rep (path ip, box b1, box b2, font fn2, font sfn2,
pencil pen2)
pencil pen2, bool opentype_disp)
: composite_box_rep (ip), fn (fn2), sfn (sfn2), pen (pen2) {
// Italic correction does not lead to nicer results,
// because right correction is not equilibrated w.r.t. left correction
Expand All @@ -84,10 +86,34 @@ frac_box_rep::frac_box_rep (path ip, box b1, box b2, font fn2, font sfn2,
SI d = sep >> 1;

pencil bar_pen= pen->set_width (bar_w);
insert (b1, (w >> 1) - (b1->x2 >> 1), bar_y + sep + (bar_w >> 1) - b1_y);
insert (b2, (w >> 1) - (b2->x2 >> 1), bar_y - sep - (bar_w >> 1) - b2_y);
insert (line_box (decorate_middle (ip), d, 0, w - d, 0, bar_pen), 0, bar_y);

bool use_opentype=
(fn->math_type == MATH_TYPE_OPENTYPE) && (fn->frac_num_gap_min > 0);

if (use_opentype) {
SI num_gap_min = fn->frac_num_gap_min;
SI den_gap_min = fn->frac_denom_gap_min;
SI num_shift_up = fn->frac_num_shift_up;
SI den_shift_down= fn->frac_denom_shift_down;

if (opentype_disp) {
num_gap_min = fn->frac_num_disp_gap_min;
den_gap_min = fn->frac_denom_disp_gap_min;
num_shift_up = fn->frac_num_disp_shift_up;
den_shift_down= fn->frac_denom_disp_shift_down;
}

insert (b1, (w >> 1) - (b1->x2 >> 1),
max (num_shift_up, bar_y + num_gap_min + (bar_w >> 1) - b1->y1));
insert (b2, (w >> 1) - (b2->x2 >> 1),
min (-den_shift_down, bar_y - den_gap_min - (bar_w >> 1) - b2->y2));
insert (line_box (decorate_middle (ip), d, 0, w - d, 0, bar_pen), 0, bar_y);
}
else {
insert (b1, (w >> 1) - (b1->x2 >> 1), bar_y + sep + (bar_w >> 1) - b1_y);
insert (b2, (w >> 1) - (b2->x2 >> 1), bar_y - sep - (bar_w >> 1) - b2_y);
insert (line_box (decorate_middle (ip), d, 0, w - d, 0, bar_pen), 0, bar_y);
}
italic_correct (b1);
italic_correct (b2);
position ();
Expand Down Expand Up @@ -698,8 +724,9 @@ wide_box_rep::get_bracket_extents (SI& lo, SI& hi) {
******************************************************************************/

box
frac_box (path ip, box b1, box b2, font fn, font sfn, pencil pen) {
return tm_new<frac_box_rep> (ip, b1, b2, fn, sfn, pen);
frac_box (path ip, box b1, box b2, font fn, font sfn, pencil pen,
bool opentype_disp) {
return tm_new<frac_box_rep> (ip, b1, b2, fn, sfn, pen, opentype_disp);
}

box
Expand Down
3 changes: 2 additions & 1 deletion src/Typeset/Boxes/construct.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,8 @@ box highlight_box (path ip, box b, box xb, ornament_parameters ps);
box highlight_box (path ip, box b, SI w, brush col, brush sunc, brush shad);
box art_box (path ip, box b, art_box_parameters ps);

box frac_box (path ip, box b1, box b2, font fn, font sfn, pencil pen);
box frac_box (path ip, box b1, box b2, font fn, font sfn, pencil pen,
bool opentype_disp= false);
box sqrt_box (path ip, box b1, box b2, box sqrtb, font fn, pencil pen);
box neg_box (path ip, box b, font fn, pencil pen);
box tree_box (path ip, array<box> bs, font fn, pencil pen);
Expand Down
2 changes: 1 addition & 1 deletion src/Typeset/Concat/concat_math.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ concater_rep::typeset_frac (tree t, path ip) {
if (disp) env->local_end (MATH_DISPLAY, old);
else env->local_end_script (old);
if (num->w () <= env->frac_max && den->w () <= env->frac_max)
print (frac_box (ip, num, den, env->fn, sfn, env->pen));
print (frac_box (ip, num, den, env->fn, sfn, env->pen, disp));
else typeset_wide_frac (t, ip);
}

Expand Down

0 comments on commit 0cbd691

Please sign in to comment.