[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[freetype2] adjust 34c1acfca 4/7: [autofit] Implement vertical separatio
From: |
Werner Lemberg |
Subject: |
[freetype2] adjust 34c1acfca 4/7: [autofit] Implement vertical separation adjustment. |
Date: |
Sun, 14 Apr 2024 10:04:04 -0400 (EDT) |
branch: adjust
commit 34c1acfca3697b8e55701141d0cf6e4c99ad3f8e
Author: Craig White <gerzytet@gmail.com>
Commit: Werner Lemberg <wl@gnu.org>
[autofit] Implement vertical separation adjustment.
* src/autofit/aflatin.c: Include `afadjust.h`.
(af_latin_metrics_init): Call `af_reverse_character_map_new`.
(af_latin_metrics_done): New function.
(af_move_contour_vertically, af_check_contour_horizontal_overlap,
af_glyph_hints_apply_vertical_separation_adjustments): New functions.
(af_latin_hints_apply): Call
`af_glyph_hints_apply_vertical_separation_adjustments`.
(af_latin_writing_system_class): Updated.
* src/autofit/aftypes.h (AF_StyleMetricsRec): Add `reverse_charmap` field.
---
src/autofit/aflatin.c | 320 +++++++++++++++++++++++++++++++++++++++++++++++++-
src/autofit/aftypes.h | 2 +
2 files changed, 321 insertions(+), 1 deletion(-)
diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c
index 316e7c676..91d369f40 100644
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -22,6 +22,7 @@
#include "afglobal.h"
#include "aflatin.h"
#include "aferrors.h"
+#include "afadjust.h"
/**************************************************************************
@@ -1155,6 +1156,9 @@
af_latin_metrics_check_digits( metrics, face );
}
+ af_reverse_character_map_new( &metrics->root.reverse_charmap,
+ metrics->root.globals );
+
Exit:
face->charmap = oldmap;
return error;
@@ -1485,6 +1489,17 @@
}
+ FT_CALLBACK_DEF( void )
+ af_latin_metrics_done( AF_StyleMetrics metrics_ )
+ {
+ AF_LatinMetrics metrics = (AF_LatinMetrics)metrics_;
+
+
+ af_reverse_character_map_done( metrics->root.reverse_charmap,
+ metrics->root.globals->face->memory );
+ }
+
+
/* Scale global values in both directions. */
FT_LOCAL_DEF( void )
@@ -2738,6 +2753,304 @@
}
+#undef FT_COMPONENT
+#define FT_COMPONENT afadjust
+
+
+ static void
+ af_move_contour_vertically( AF_Point contour,
+ FT_Int movement )
+ {
+ AF_Point point = contour;
+ AF_Point first_point = point;
+
+
+ if ( point )
+ {
+ do
+ {
+ point->y += movement;
+ point = point->next;
+
+ } while ( point != first_point );
+ }
+ }
+
+
+ /* Return 1 if the given contour overlaps horizontally with the bounding */
+ /* box of all other contours combined. This is a helper for function */
+ /* `af_glyph_hints_apply_vertical_separation_adjustments`. */
+ static FT_Bool
+ af_check_contour_horizontal_overlap( AF_GlyphHints hints,
+ FT_Int contour_index )
+ {
+ FT_Pos contour_max_x = -32000;
+ FT_Pos contour_min_x = 32000;
+ FT_Pos others_max_x = -32000;
+ FT_Pos others_min_x = 32000;
+
+ FT_Int contour;
+
+ FT_Bool horizontal_overlap;
+
+
+ for ( contour = 0; contour < hints->num_contours; contour++ )
+ {
+ AF_Point first_point = hints->contours[contour];
+ AF_Point p = first_point;
+
+
+ do
+ {
+ p = p->next;
+
+ if ( contour == contour_index )
+ {
+ if ( p->x < contour_min_x )
+ contour_min_x = p->x;
+ if ( p->x > contour_max_x )
+ contour_max_x = p->x;
+ }
+ else
+ {
+ if ( p->x < others_min_x )
+ others_min_x = p->x;
+ if ( p->x > others_max_x )
+ others_max_x = p->x;
+ }
+ } while ( p != first_point );
+ }
+
+ horizontal_overlap =
+ ( others_min_x <= contour_max_x && contour_max_x <= others_max_x ) ||
+ ( others_min_x <= contour_min_x && contour_min_x <= others_max_x ) ||
+ ( contour_max_x >= others_max_x && contour_min_x <= others_min_x );
+
+ return horizontal_overlap;
+ }
+
+
+ static void
+ af_glyph_hints_apply_vertical_separation_adjustments(
+ AF_GlyphHints hints,
+ AF_Dimension dim,
+ FT_Int glyph_index,
+ AF_ReverseCharacterMap reverse_charmap )
+ {
+ FT_TRACE4(( "Entering"
+ " af_glyph_hints_apply_vertical_separation_adjustments\n" ));
+
+ if ( dim != AF_DIMENSION_VERT )
+ return;
+
+ if ( af_lookup_vertical_separation_type( reverse_charmap,
+ glyph_index ) ==
+ AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP &&
+ hints->num_contours >= 2 )
+ {
+ FT_Int highest_contour = -1;
+ FT_Pos highest_min_y = 0;
+ FT_Pos current_min_y = 0;
+
+ FT_Int contour;
+ FT_Bool horizontal_overlap;
+ FT_Int adjustment_amount;
+
+ FT_TRACE4(( "af_glyph_hints_apply_vertical_separation_adjustments:\n"
+ " Applying vertical adjustment:"
+ " AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP\n" ));
+
+ /* Figure out which contour is the higher one by finding the one */
+ /* with the highest minimum y value. */
+ for ( contour = 0; contour < hints->num_contours; contour++ )
+ {
+ AF_Point point = hints->contours[contour];
+ AF_Point first_point = point;
+
+
+ if ( !point )
+ continue;
+
+ current_min_y = point->y;
+
+ do
+ {
+ if ( point->y < current_min_y )
+ current_min_y = point->y;
+ point = point->next;
+
+ } while ( point != first_point );
+
+ if ( highest_contour == -1 || current_min_y > highest_min_y )
+ {
+ highest_min_y = current_min_y;
+ highest_contour = contour;
+ }
+ }
+
+ /* Check for a horizontal overlap between the top contour and the */
+ /* rest. If there is no overlap, do not adjust. */
+ horizontal_overlap =
+ af_check_contour_horizontal_overlap( hints, highest_contour );
+ if ( !horizontal_overlap )
+ {
+ FT_TRACE4(( " Top contour does not horizontally overlap"
+ " with other contours.\n"
+ " Skipping adjustment.\n" ));
+ return;
+ }
+
+ /* If there are any contours that have a maximum y coordinate */
+ /* greater than or equal to the minimum y coordinate of the */
+ /* previously found highest contour, bump the high contour up until */
+ /* the distance is one pixel. */
+ adjustment_amount = 0;
+
+ for ( contour = 0; contour < hints->num_contours; contour++ )
+ {
+ AF_Point point;
+ AF_Point first_point;
+
+ FT_Pos max_y;
+
+
+ if ( contour == highest_contour )
+ continue;
+
+ point = hints->contours[contour];
+ first_point = point;
+ if ( !point )
+ continue;
+
+ max_y = point->y;
+ do
+ {
+ if ( point->y > max_y )
+ max_y = point->y;
+ point = point->next;
+
+ } while ( point != first_point );
+
+ if ( max_y >= highest_min_y - 64 )
+ adjustment_amount = 64 - ( highest_min_y - max_y );
+ }
+
+ if ( adjustment_amount > 64 )
+ FT_TRACE4(( " Calculated adjustment amount %d"
+ " was more than threshold of 64. Not adjusting\n",
+ adjustment_amount ));
+ else if ( adjustment_amount > 0 )
+ {
+ FT_TRACE4(( " Pushing top contour %d units up\n",
+ adjustment_amount ));
+
+ af_move_contour_vertically( hints->contours[highest_contour],
+ adjustment_amount );
+ }
+ }
+
+ else if ( af_lookup_vertical_separation_type( reverse_charmap,
+ glyph_index ) ==
+ AF_VERTICAL_ADJUSTMENT_BOTTOM_CONTOUR_DOWN &&
+ hints->num_contours >= 2 )
+ {
+ FT_Int lowest_contour = -1;
+ FT_Pos lowest_max_y = 0;
+ FT_Pos current_max_y = 0;
+
+ FT_Int contour;
+ FT_Int adjustment_amount;
+
+
+ FT_TRACE4(( "af_glyph_hints_apply_vertical_separation_adjustments:\n"
+ " Applying vertical adjustment:"
+ " AF_VERTICAL_ADJUSTMENT_BOTTOM_CONTOUR_DOWN\n" ));
+
+ /* Find lowest contour. */
+ for ( contour = 0; contour < hints->num_contours; contour++ )
+ {
+ AF_Point point = hints->contours[contour];
+ AF_Point first_point = point;
+
+
+ if ( !point )
+ continue;
+
+ current_max_y = point->y;
+
+ do
+ {
+ if ( point->y > current_max_y )
+ current_max_y = point->y;
+ point = point->next;
+
+ } while ( point != first_point );
+
+ if ( lowest_contour == -1 || current_max_y < lowest_max_y )
+ {
+ lowest_max_y = current_max_y;
+ lowest_contour = contour;
+ }
+ }
+
+ adjustment_amount = 0;
+
+ for ( contour = 0; contour < hints->num_contours; contour++ )
+ {
+ AF_Point point;
+ AF_Point first_point;
+
+ FT_Pos min_y;
+
+
+ if ( contour == lowest_contour )
+ continue;
+
+ point = hints->contours[contour];
+ first_point = point;
+ if ( !point )
+ continue;
+
+ min_y = point->y;
+ do
+ {
+ if ( point->y < min_y )
+ min_y = point->y;
+ point = point->next;
+
+ } while ( point != first_point );
+
+ if ( min_y <= lowest_max_y - 64 )
+ adjustment_amount = 64 - ( min_y - lowest_max_y );
+ }
+
+ if ( adjustment_amount > 64 )
+ FT_TRACE4(( " Calculated adjustment amount %d"
+ " was more than threshold of 64. Not adjusting\n",
+ adjustment_amount ));
+ else if ( adjustment_amount > 0 )
+ {
+ FT_TRACE4(( " Pushing bottom contour %d units down\n",
+ adjustment_amount ));
+
+ af_move_contour_vertically( hints->contours[lowest_contour],
+ -adjustment_amount );
+ }
+ }
+
+ else
+ FT_TRACE4(( "af_glyph_hints_apply_vertical_separation_adjustments:\n"
+ " No vertical adjustment needed\n" ));
+
+ FT_TRACE4(( "Exiting"
+ " af_glyph_hints_apply_vertical_separation_adjustments\n" ));
+ }
+
+
+#undef FT_COMPONENT
+#define FT_COMPONENT aflatin
+
+
/* Compute the snapped width of a given stem, ignoring very thin ones. */
/* There is a lot of voodoo in this function; changing the hard-coded */
/* parameters influence the whole hinting process. */
@@ -3605,6 +3918,11 @@
af_glyph_hints_align_edge_points( hints, (AF_Dimension)dim );
af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim );
af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim );
+ af_glyph_hints_apply_vertical_separation_adjustments(
+ hints,
+ (AF_Dimension)dim,
+ glyph_index,
+ metrics->root.reverse_charmap );
}
}
@@ -3633,7 +3951,7 @@
(AF_WritingSystem_InitMetricsFunc) af_latin_metrics_init, /*
style_metrics_init */
(AF_WritingSystem_ScaleMetricsFunc)af_latin_metrics_scale, /*
style_metrics_scale */
- (AF_WritingSystem_DoneMetricsFunc) NULL, /*
style_metrics_done */
+ (AF_WritingSystem_DoneMetricsFunc) af_latin_metrics_done, /*
style_metrics_done */
(AF_WritingSystem_GetStdWidthsFunc)af_latin_get_standard_widths, /*
style_metrics_getstdw */
(AF_WritingSystem_InitHintsFunc) af_latin_hints_init, /*
style_hints_init */
diff --git a/src/autofit/aftypes.h b/src/autofit/aftypes.h
index 5d4aaa9ba..259b555be 100644
--- a/src/autofit/aftypes.h
+++ b/src/autofit/aftypes.h
@@ -439,6 +439,8 @@ extern void* af_debug_hints_;
AF_FaceGlobals globals; /* to access properties */
+ AF_ReverseCharacterMap reverse_charmap;
+
} AF_StyleMetricsRec;
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [freetype2] adjust 34c1acfca 4/7: [autofit] Implement vertical separation adjustment.,
Werner Lemberg <=