From 2e09812c5121413fa29692a46b310983cb3de3e8 Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Fri, 25 Dec 2015 08:05:30 +0100 Subject: [PATCH] [autofit] Make top-to-bottom hinting work in latin auto-hinter. This improves rendering of scripts like Bengali or Devanagari. * src/autofit/afhints.c (af_axis_hints_new_edge): Add parameter to pass top-to-bottom hinting flag. This makes the function sort edges in descending vertical position. * src/autofit/afhints.c: Updated. * src/autofit/aflatin.c (af_latin_hints_compute_edges, af_latin_hint_edges): Use `top_to_bottom_hinting' flag. * src/autofit/afcjk.c (af_cjk_hints_compute_edges), src/autofit/aflatin2.c (af_latin2_hints_compute_edges): Updated. --- ChangeLog | 18 ++++++++++++++++++ src/autofit/afcjk.c | 2 +- src/autofit/afhints.c | 4 +++- src/autofit/afhints.h | 1 + src/autofit/aflatin.c | 36 ++++++++++++++++++++++++++++++------ src/autofit/aflatin2.c | 2 +- 6 files changed, 54 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 89d03ef2f..7b5178097 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2015-12-25 Werner Lemberg + + [autofit] Make top-to-bottom hinting work in latin auto-hinter. + + This improves rendering of scripts like Bengali or Devanagari. + + * src/autofit/afhints.c (af_axis_hints_new_edge): Add parameter to + pass top-to-bottom hinting flag. This makes the function sort edges + in descending vertical position. + + * src/autofit/afhints.c: Updated. + + * src/autofit/aflatin.c (af_latin_hints_compute_edges, + af_latin_hint_edges): Use `top_to_bottom_hinting' flag. + + * src/autofit/afcjk.c (af_cjk_hints_compute_edges), + src/autofit/aflatin2.c (af_latin2_hints_compute_edges): Updated. + 2015-12-24 Werner Lemberg [autofit] Add hinting direction to `AF_ScriptClassRec'. diff --git a/src/autofit/afcjk.c b/src/autofit/afcjk.c index 73d75ae92..247d44771 100644 --- a/src/autofit/afcjk.c +++ b/src/autofit/afcjk.c @@ -1091,7 +1091,7 @@ /* insert a new edge in the list and */ /* sort according to the position */ error = af_axis_hints_new_edge( axis, seg->pos, - (AF_Direction)seg->dir, + (AF_Direction)seg->dir, 0, memory, &edge ); if ( error ) goto Exit; diff --git a/src/autofit/afhints.c b/src/autofit/afhints.c index 56c822000..b85f4b37c 100644 --- a/src/autofit/afhints.c +++ b/src/autofit/afhints.c @@ -99,6 +99,7 @@ af_axis_hints_new_edge( AF_AxisHints axis, FT_Int fpos, AF_Direction dir, + FT_Bool top_to_bottom_hinting, FT_Memory memory, AF_Edge *anedge ) { @@ -153,7 +154,8 @@ while ( edge > edges ) { - if ( edge[-1].fpos < fpos ) + if ( top_to_bottom_hinting ? ( edge[-1].fpos > fpos ) + : ( edge[-1].fpos < fpos ) ) break; /* we want the edge with same position and minor direction */ diff --git a/src/autofit/afhints.h b/src/autofit/afhints.h index a64c7a4b1..eb593324b 100644 --- a/src/autofit/afhints.h +++ b/src/autofit/afhints.h @@ -419,6 +419,7 @@ FT_BEGIN_HEADER af_axis_hints_new_edge( AF_AxisHints axis, FT_Int fpos, AF_Direction dir, + FT_Bool top_to_bottom_hinting, FT_Memory memory, AF_Edge *edge ); diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c index 9c9f37071..f75bf00e2 100644 --- a/src/autofit/aflatin.c +++ b/src/autofit/aflatin.c @@ -1773,6 +1773,12 @@ FT_Memory memory = hints->memory; AF_LatinAxis laxis = &((AF_LatinMetrics)hints->metrics)->axis[dim]; + AF_StyleClass style_class = hints->metrics->style_class; + AF_ScriptClass script_class = AF_SCRIPT_CLASSES_GET + [style_class->script]; + + FT_Bool top_to_bottom_hinting = 0; + AF_Segment segments = axis->segments; AF_Segment segment_limit = segments + axis->num_segments; AF_Segment seg; @@ -1795,6 +1801,9 @@ : AF_DIR_RIGHT; #endif + if ( dim == AF_DIMENSION_VERT ) + top_to_bottom_hinting = script_class->top_to_bottom_hinting; + /* * We ignore all segments that are less than 1 pixel in length * to avoid many problems with serif fonts. We compute the @@ -1872,6 +1881,7 @@ /* sort according to the position */ error = af_axis_hints_new_edge( axis, seg->pos, (AF_Direction)seg->dir, + top_to_bottom_hinting, memory, &edge ); if ( error ) goto Exit; @@ -2558,8 +2568,14 @@ AF_Edge anchor = NULL; FT_Int has_serifs = 0; + AF_StyleClass style_class = hints->metrics->style_class; + AF_ScriptClass script_class = AF_SCRIPT_CLASSES_GET + [style_class->script]; + + FT_Bool top_to_bottom_hinting = 0; + #ifdef FT_DEBUG_LEVEL_TRACE - FT_UInt num_actions = 0; + FT_UInt num_actions = 0; #endif @@ -2567,6 +2583,9 @@ dim == AF_DIMENSION_VERT ? "horizontal" : "vertical", af_style_names[hints->metrics->style_class->style] )); + if ( dim == AF_DIMENSION_VERT ) + top_to_bottom_hinting = script_class->top_to_bottom_hinting; + /* we begin by aligning all stems relative to the blue zone */ /* if needed -- that's only for horizontal edges */ @@ -2862,7 +2881,9 @@ edge->flags |= AF_EDGE_DONE; edge2->flags |= AF_EDGE_DONE; - if ( edge > edges && edge->pos < edge[-1].pos ) + if ( edge > edges && + ( top_to_bottom_hinting ? ( edge->pos > edge[-1].pos ) + : ( edge->pos < edge[-1].pos ) ) ) { #ifdef FT_DEBUG_LEVEL_TRACE FT_TRACE5(( " BOUND: edge %d (pos=%.2f) moved to %.2f\n", @@ -3023,7 +3044,9 @@ #endif edge->flags |= AF_EDGE_DONE; - if ( edge > edges && edge->pos < edge[-1].pos ) + if ( edge > edges && + ( top_to_bottom_hinting ? ( edge->pos > edge[-1].pos ) + : ( edge->pos < edge[-1].pos ) ) ) { #ifdef FT_DEBUG_LEVEL_TRACE FT_TRACE5(( " BOUND: edge %d (pos=%.2f) moved to %.2f\n", @@ -3034,9 +3057,10 @@ edge->pos = edge[-1].pos; } - if ( edge + 1 < edge_limit && - edge[1].flags & AF_EDGE_DONE && - edge->pos > edge[1].pos ) + if ( edge + 1 < edge_limit && + edge[1].flags & AF_EDGE_DONE && + ( top_to_bottom_hinting ? ( edge->pos < edge[1].pos ) + : ( edge->pos > edge[1].pos ) ) ) { #ifdef FT_DEBUG_LEVEL_TRACE FT_TRACE5(( " BOUND: edge %d (pos=%.2f) moved to %.2f\n", diff --git a/src/autofit/aflatin2.c b/src/autofit/aflatin2.c index 2fb7d1d35..216848a09 100644 --- a/src/autofit/aflatin2.c +++ b/src/autofit/aflatin2.c @@ -1195,7 +1195,7 @@ /* insert a new edge in the list and */ /* sort according to the position */ - error = af_axis_hints_new_edge( axis, seg->pos, seg->dir, + error = af_axis_hints_new_edge( axis, seg->pos, seg->dir, 0, memory, &edge ); if ( error ) goto Exit;