[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[freetype2] gsoc-craig-2023 62378cca3 1/2: * Add trace output
From: |
Werner Lemberg |
Subject: |
[freetype2] gsoc-craig-2023 62378cca3 1/2: * Add trace output |
Date: |
Sun, 25 Jun 2023 23:47:17 -0400 (EDT) |
branch: gsoc-craig-2023
commit 62378cca3a8f222aa96c3584d7738144a77270d2
Author: Craig White <gerzytet@gmail.com>
Commit: Craig White <gerzytet@gmail.com>
* Add trace output
* Remove assumption of exactly 2 contours
* Adjustment database lookups use binary search now
---
include/freetype/internal/fttrace.h | 1 +
src/autofit/afadjust.c | 138 ++++++++++++++++++++++++------------
src/autofit/afadjust.h | 23 +++---
src/autofit/aflatin.c | 74 +++++++++++++------
4 files changed, 159 insertions(+), 77 deletions(-)
diff --git a/include/freetype/internal/fttrace.h
b/include/freetype/internal/fttrace.h
index 319fe56fd..156fb21dc 100644
--- a/include/freetype/internal/fttrace.h
+++ b/include/freetype/internal/fttrace.h
@@ -164,6 +164,7 @@ FT_TRACE_DEF( afhints )
FT_TRACE_DEF( afmodule )
FT_TRACE_DEF( aflatin )
FT_TRACE_DEF( afshaper )
+FT_TRACE_DEF( afadjust )
/* SDF components */
FT_TRACE_DEF( sdf ) /* signed distance raster for outlines (ftsdf.c) */
diff --git a/src/autofit/afadjust.c b/src/autofit/afadjust.c
index 00a21a447..cf2a59671 100644
--- a/src/autofit/afadjust.c
+++ b/src/autofit/afadjust.c
@@ -2,34 +2,52 @@
#include <freetype/freetype.h>
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/ftmemory.h>
+#include <freetype/internal/ftdebug.h>
-#define AF_ADJUSTMENT_DATABASE_LENGTH 12
+#define AF_ADJUSTMENT_DATABASE_LENGTH
(sizeof(adjustment_database)/sizeof(adjustment_database[0]))
+#undef FT_COMPONENT
+#define FT_COMPONENT afadjust
/*TODO: find out whether capital u/U with accent entries are needed*/
/*the accent won't merge with the rest of the glyph because the accent mark is
sitting above empty space*/
FT_LOCAL_ARRAY_DEF( AF_AdjustmentDatabaseEntry )
-adjustment_database[AF_ADJUSTMENT_DATABASE_LENGTH] = {
- {'i', AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE},
- {'j', AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE},
- {0xC8, AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*E with grave*/
- {0xCC, AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*I with grave*/
- {0xD9, AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*U with grave*/
- {0xE0, AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*a with grave*/
- {0xEC, AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*i with grave*/
- {0x114, AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*E with macron*/
- {0x12A, AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*I with macron*/
- {0x12B, AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*i with macron*/
- {0x16A, AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*U with macron*/
- {0x16B, AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE} /*u with macron*/
- /*TODO: find out why E won't work, even though it appears to be
one-on-one*/
+adjustment_database[] =
+{
+ {0x21, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /* ! */
+ {0x69, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /* i */
+ {0x6A, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /* j */
+ {0xA1, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*Inverted Exclamation
Mark*/
+ {0xBF, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*Inverted Question Mark*/
+ {0xC0, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*A with grave*/
+ {0xC1, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*A with acute*/
+ {0xC2, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*A with circumflex*/
+ {0xC3, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*A with tilde*/
+ {0xC8, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*E with grave*/
+ {0xCC, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*I with grave*/
+ {0xD9, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*U with grave*/
+ {0xE0, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*a with grave*/
+ {0xEC, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*i with grave*/
+ {0x114, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*E with macron*/
+ {0x12A, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*I with macron*/
+ {0x12B, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*i with macron*/
+ {0x16A, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*U with macron*/
+ {0x16B, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP} /*u with macron*/
};
/*Helper function: get the adjustment database entry for a codepoint*/
FT_LOCAL_DEF( const AF_AdjustmentDatabaseEntry* )
af_adjustment_database_lookup( FT_UInt32 codepoint ) {
- for ( FT_Int entry = 0; entry < AF_ADJUSTMENT_DATABASE_LENGTH; entry++ ) {
- if ( adjustment_database[entry].codepoint == codepoint ) {
- return &adjustment_database[entry];
+ /* Binary search for database entry */
+ FT_UInt low = 0;
+ FT_UInt high = AF_ADJUSTMENT_DATABASE_LENGTH - 1;
+ while (high > low) {
+ FT_UInt mid = (low + high) / 2;
+ if (adjustment_database[mid].codepoint < codepoint) {
+ low = mid + 1;
+ } else if (adjustment_database[mid].codepoint > codepoint) {
+ high = mid - 1;
+ } else {
+ return &adjustment_database[mid];
}
}
@@ -40,30 +58,37 @@ FT_LOCAL_DEF( AF_VerticalSeparationAdjustmentType )
af_lookup_vertical_seperation_type( AF_ReverseCharacterMap map, FT_Int
glyph_index ) {
FT_UInt32 codepoint = af_reverse_character_map_lookup( map, glyph_index );
const AF_AdjustmentDatabaseEntry *entry = af_adjustment_database_lookup(
codepoint );
- if ( entry == NULL ) {
+ if ( entry == NULL )
+ {
return AF_VERTICAL_ADJUSTMENT_NONE;
}
return entry->vertical_separation_adjustment_type;
}
-typedef struct AF_ReverseMapEntry_ {
+typedef struct AF_ReverseMapEntry_
+{
FT_Int glyph_index;
FT_UInt32 codepoint;
} AF_ReverseMapEntry;
-typedef struct AF_ReverseCharacterMap_ {
+typedef struct AF_ReverseCharacterMap_
+{
FT_UInt length;
AF_ReverseMapEntry *entries;
} AF_ReverseCharacterMap_Rec;
FT_LOCAL_DEF(FT_UInt32)
-af_reverse_character_map_lookup( AF_ReverseCharacterMap map, FT_Int
glyph_index ) {
- if ( map == NULL ) {
+af_reverse_character_map_lookup( AF_ReverseCharacterMap map, FT_Int
glyph_index )
+{
+ if ( map == NULL )
+ {
return 0;
}
- for ( FT_UInt entry = 0; entry < map->length; entry++ ) {
- if ( map->entries[entry].glyph_index == glyph_index ) {
+ for ( FT_UInt entry = 0; entry < map->length; entry++ )
+ {
+ if ( map->entries[entry].glyph_index == glyph_index )
+ {
return map->entries[entry].codepoint;
}
}
@@ -72,64 +97,87 @@ af_reverse_character_map_lookup( AF_ReverseCharacterMap
map, FT_Int glyph_index
}
FT_LOCAL_DEF( FT_Error )
-af_reverse_character_map_new( FT_Face face, AF_ReverseCharacterMap *map,
FT_Memory memory ) {
+af_reverse_character_map_new( FT_Face face, AF_ReverseCharacterMap *map,
FT_Memory memory )
+{
/* Search for a unicode charmap */
/* If there isn't one, create a blank map */
-
+
/*TODO: change this to logic that searches for a "preferred" unicode
charmap that maps the most codepoints*/
/*see find_unicode_charmap*/
/*TODO: use GSUB lookups */
+ FT_TRACE4(( "af_reverse_character_map_new: building reverse character
map\n" ));
FT_CMap unicode_charmap = NULL;
- for ( FT_UInt i = 0; i < face->num_charmaps; i++ ) {
- if ( face->charmaps[i]->encoding == FT_ENCODING_UNICODE ) {
+ for ( FT_UInt i = 0; i < face->num_charmaps; i++ )
+ {
+ if ( face->charmaps[i]->encoding == FT_ENCODING_UNICODE )
+ {
unicode_charmap = FT_CMAP( face->charmaps[i] );
}
}
-
- if ( unicode_charmap == NULL ) {
+
+ if ( unicode_charmap == NULL )
+ {
*map = NULL;
return FT_Err_Ok;
}
FT_Error error;
- if ( FT_NEW( *map ) ) {
+ if ( FT_NEW( *map ) )
+ {
goto Exit;
}
FT_Int capacity = 10;
FT_Int size = 0;
-
- if ( FT_NEW_ARRAY((*map)->entries, capacity) ) {
+
+ if ( FT_NEW_ARRAY((*map)->entries, capacity) )
+ {
goto Exit;
}
- for ( FT_Int i = 0; i < AF_ADJUSTMENT_DATABASE_LENGTH; i++ ) {
+#ifdef FT_DEBUG_LEVEL_TRACE
+ int failed_lookups = 0;
+#endif
+ for ( FT_Int i = 0; i < AF_ADJUSTMENT_DATABASE_LENGTH; i++ )
+ {
FT_UInt32 codepoint = adjustment_database[i].codepoint;
FT_Int glyph = unicode_charmap->clazz->char_index(unicode_charmap,
codepoint);
- if ( glyph == 0 ) {
+ if ( glyph == 0 )
+ {
+#ifdef FT_DEBUG_LEVEL_TRACE
+ failed_lookups++;
+#endif
continue;
}
- if (size == capacity) {
+ if ( size == capacity )
+ {
capacity += capacity / 2;
- if ( FT_RENEW_ARRAY((*map)->entries, size, capacity) ) {
+ if ( FT_RENEW_ARRAY((*map)->entries, size, capacity) )
+ {
goto Exit;
}
}
size++;
- (*map)->entries[i].glyph_index = glyph;
- (*map)->entries[i].codepoint = codepoint;
+ ( *map )->entries[i].glyph_index = glyph;
+ ( *map )->entries[i].codepoint = codepoint;
}
- (*map)->length = size;
+ ( *map )->length = size;
Exit:
- if ( error ) {
- if ( *map ) {
+ if ( error )
+ {
+ FT_TRACE4(( " error while building reverse character map. Using
blank map.\n" ));
+ if ( *map )
+ {
FT_FREE( ( *map )->entries );
}
FT_FREE( *map );
return error;
}
-
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_TRACE4(( " reverse character map built successfully"\
+ " with %d entries and %d failed lookups.\n", size,
failed_lookups ));
+#endif
return FT_Err_Ok;
}
@@ -137,4 +185,4 @@ FT_LOCAL_DEF( FT_Error )
af_reverse_character_map_done( AF_ReverseCharacterMap map, FT_Memory memory ) {
FT_FREE( map->entries );
return FT_Err_Ok;
-}
\ No newline at end of file
+}
diff --git a/src/autofit/afadjust.h b/src/autofit/afadjust.h
index f1c8c47d3..65cdfaa66 100644
--- a/src/autofit/afadjust.h
+++ b/src/autofit/afadjust.h
@@ -7,11 +7,11 @@ FT_BEGIN_HEADER
/*The type of adjustment that should be done to prevent cases where 2 parts of
a character*/
/*stacked vertically merge, even though they should be separate*/
-typedef enum AF_VerticalSeparationAdjustmentType_ {
- AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE,
- /*"One on one" means that the character is expected to be one contour on
top of another, where the contours should not touch*/
- /*the hinter will force the contours to have a gap of at least 1 pixel
between them*/
- /*by moving the top contour up */
+typedef enum AF_VerticalSeparationAdjustmentType_
+{
+ AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP,
+ /*This means that the hinter should find the topmost contour and push it
up until its lowest point is 1 pixel*/
+ /*above the highest point not part of that contour.*/
AF_VERTICAL_ADJUSTMENT_NONE
/*others will be needed, such as the case where the lower contour should
be moved in the adjustment instead of the upper one*/
@@ -19,10 +19,11 @@ typedef enum AF_VerticalSeparationAdjustmentType_ {
/*and a way of handling A and O, where the letter consists of 2 contours*/
} AF_VerticalSeparationAdjustmentType;
-typedef struct AF_AdjustmentDatabaseEntry_ {
- FT_UInt32 codepoint;
- AF_VerticalSeparationAdjustmentType vertical_separation_adjustment_type;
- } AF_AdjustmentDatabaseEntry;
+typedef struct AF_AdjustmentDatabaseEntry_
+{
+ FT_UInt32 codepoint;
+ AF_VerticalSeparationAdjustmentType vertical_separation_adjustment_type;
+} AF_AdjustmentDatabaseEntry;
struct AF_ReverseCharacterMap_;
@@ -37,11 +38,11 @@ af_reverse_character_map_lookup( AF_ReverseCharacterMap
map, FT_Int glyph_index
/*allocate and populate the reverse character map, using the character map
within the face*/
FT_LOCAL( FT_Error )
af_reverse_character_map_new( FT_Face face, AF_ReverseCharacterMap *map,
FT_Memory memory );
-
+
/*free the reverse character map*/
FT_LOCAL( FT_Error )
af_reverse_character_map_done( AF_ReverseCharacterMap map, FT_Memory memory );
FT_END_HEADER
-#endif
\ No newline at end of file
+#endif
diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c
index 8177c66f1..2e870f59e 100644
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -1153,7 +1153,7 @@
goto Exit;
}
af_latin_metrics_check_digits( metrics, face );
-
+
af_reverse_character_map_new( face, &metrics->root.reverse_charmap,
face->memory );
}
@@ -2745,13 +2745,25 @@
}
-void af_glyph_hints_apply_adjustments(AF_GlyphHints hints, AF_Dimension dim,
FT_Int glyph_index, AF_ReverseCharacterMap reverse_charmap) {
- if ( dim != AF_DIMENSION_VERT ) {
+#undef FT_COMPONENT
+#define FT_COMPONENT afadjust
+
+void
+af_glyph_hints_apply_vertical_separation_adjustments( AF_GlyphHints hints,
+ AF_Dimension dim,
+ FT_Int glyph_index,
+ AF_ReverseCharacterMap
reverse_charmap )
+{
+ if ( dim != AF_DIMENSION_VERT )
+ {
return;
}
- if ( af_lookup_vertical_seperation_type( reverse_charmap, glyph_index ) ==
AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE &&
- hints->num_contours == 2 ) {
-
+
+ if ( af_lookup_vertical_seperation_type( reverse_charmap, glyph_index ) ==
AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP
+ && hints->num_contours >= 2 )
+ {
+ FT_TRACE4(( "af_glyph_hints_apply_vertical_separation_adjustments:
Applying vertical adjustment: AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP\n" ));
+
/* Figure out which contout is the higher one by finding the one */
/* with the highest minimum y value */
@@ -2759,22 +2771,27 @@ void af_glyph_hints_apply_adjustments(AF_GlyphHints
hints, AF_Dimension dim, FT_
FT_Pos highest_min_y = 0;
FT_Pos current_min_y = 0;
- for ( FT_Int contour = 0; contour < hints->num_contours; contour++ ) {
+ for ( FT_Int contour = 0; contour < hints->num_contours; contour++ )
+ {
AF_Point point = hints->contours[contour];
AF_Point first_point = point;
- if ( point == NULL ) { /*TODO: is this necessary?*/
+ if ( point == NULL )
+ { /*TODO: is this necessary?*/
continue;
}
current_min_y = point->y;
- do {
- if ( point->y < current_min_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 ) {
+ if ( highest_contour == -1 || current_min_y > highest_min_y )
+ {
highest_min_y = current_min_y;
highest_contour = contour;
}
@@ -2785,42 +2802,57 @@ void af_glyph_hints_apply_adjustments(AF_GlyphHints
hints, AF_Dimension dim, FT_
/* contour, bump the high contour up until the distance is one pixel */
FT_Int adjustment_amount = 0;
- for ( FT_Int contour = 0; contour < hints->num_contours; contour++ ) {
- if (contour == highest_contour) {
+ for ( FT_Int contour = 0; contour < hints->num_contours; contour++ )
+ {
+ if ( contour == highest_contour )
+ {
continue;
}
AF_Point point = hints->contours[contour];
AF_Point first_point = point;
- if ( point == NULL ) {
+ if ( point == NULL )
+ {
continue;
}
FT_Pos max_y = point->y;
- do {
- if ( point->y > max_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 ( max_y >= highest_min_y - 64 )
+ {
+ adjustment_amount = 64 - ( highest_min_y - max_y );
}
}
+ FT_TRACE4(( " Pushing top contour %d units up\n", adjustment_amount ));
if ( adjustment_amount > 0 ) {
AF_Point point = hints->contours[highest_contour];
AF_Point first_point = point;
- if ( point != NULL ) {
- do {
+ if ( point != NULL )
+ {
+ do
+ {
point->y += adjustment_amount;
point = point->next;
} while ( point != first_point );
}
}
+ } else {
+ FT_TRACE4(( "af_glyph_hints_apply_vertical_separation_adjustments: No
vertical adjustment needed\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 */
@@ -3689,7 +3721,7 @@ void af_glyph_hints_apply_adjustments(AF_GlyphHints
hints, AF_Dimension dim, FT_
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_adjustments(hints, (AF_Dimension) dim,
glyph_index, metrics->root.reverse_charmap);
+ af_glyph_hints_apply_vertical_separation_adjustments(hints,
(AF_Dimension) dim, glyph_index, metrics->root.reverse_charmap);
}
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [freetype2] gsoc-craig-2023 62378cca3 1/2: * Add trace output,
Werner Lemberg <=