[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[freetype2] gsoc-craig-2023 f8e996bfb: Prototype adjustment database, re
From: |
Werner Lemberg |
Subject: |
[freetype2] gsoc-craig-2023 f8e996bfb: Prototype adjustment database, reverse character lookup, and fixes for a few characters |
Date: |
Sun, 4 Jun 2023 15:32:22 -0400 (EDT) |
branch: gsoc-craig-2023
commit f8e996bfb1f79056715e0f68c2ab0f741e86c308
Author: Craig White <gerzytet@gmail.com>
Commit: Craig White <gerzytet@gmail.com>
Prototype adjustment database, reverse character lookup, and fixes for a
few characters
---
src/autofit/afadjust.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++
src/autofit/afadjust.h | 47 +++++++++++++++++
src/autofit/aflatin.c | 90 +++++++++++++++++++++++++++++--
src/autofit/aftypes.h | 2 +
src/autofit/autofit.c | 1 +
src/base/ftobjs.c | 1 -
6 files changed, 277 insertions(+), 4 deletions(-)
diff --git a/src/autofit/afadjust.c b/src/autofit/afadjust.c
new file mode 100644
index 000000000..00a21a447
--- /dev/null
+++ b/src/autofit/afadjust.c
@@ -0,0 +1,140 @@
+#include "afadjust.h"
+#include <freetype/freetype.h>
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftmemory.h>
+
+#define AF_ADJUSTMENT_DATABASE_LENGTH 12
+
+/*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*/
+};
+
+/*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];
+ }
+ }
+
+ return NULL;
+}
+
+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 ) {
+ return AF_VERTICAL_ADJUSTMENT_NONE;
+ }
+ return entry->vertical_separation_adjustment_type;
+}
+
+typedef struct AF_ReverseMapEntry_ {
+ FT_Int glyph_index;
+ FT_UInt32 codepoint;
+} AF_ReverseMapEntry;
+
+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 ) {
+ return 0;
+ }
+
+ for ( FT_UInt entry = 0; entry < map->length; entry++ ) {
+ if ( map->entries[entry].glyph_index == glyph_index ) {
+ return map->entries[entry].codepoint;
+ }
+ }
+
+ return 0;
+}
+
+FT_LOCAL_DEF( FT_Error )
+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_CMap unicode_charmap = NULL;
+ 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 ) {
+ *map = NULL;
+ return FT_Err_Ok;
+ }
+
+ FT_Error error;
+
+ if ( FT_NEW( *map ) ) {
+ goto Exit;
+ }
+
+ FT_Int capacity = 10;
+ FT_Int size = 0;
+
+ if ( FT_NEW_ARRAY((*map)->entries, capacity) ) {
+ goto Exit;
+ }
+ 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 ) {
+ continue;
+ }
+ if (size == capacity) {
+ capacity += capacity / 2;
+ if ( FT_RENEW_ARRAY((*map)->entries, size, capacity) ) {
+ goto Exit;
+ }
+ }
+ size++;
+ (*map)->entries[i].glyph_index = glyph;
+ (*map)->entries[i].codepoint = codepoint;
+ }
+ (*map)->length = size;
+
+Exit:
+ if ( error ) {
+ if ( *map ) {
+ FT_FREE( ( *map )->entries );
+ }
+ FT_FREE( *map );
+ return error;
+ }
+
+ return FT_Err_Ok;
+}
+
+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
new file mode 100644
index 000000000..f1c8c47d3
--- /dev/null
+++ b/src/autofit/afadjust.h
@@ -0,0 +1,47 @@
+#ifndef AFADJUST_H_
+#define AFADJUST_H_
+
+#include <freetype/fttypes.h>
+
+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 */
+ 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*/
+ /*or umlats, where there are 2 contours which should be moved together*/
+ /*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;
+
+struct AF_ReverseCharacterMap_;
+
+typedef struct AF_ReverseCharacterMap_ *AF_ReverseCharacterMap;
+
+FT_LOCAL(AF_VerticalSeparationAdjustmentType)
+af_lookup_vertical_seperation_type( AF_ReverseCharacterMap map, FT_Int
glyph_index );
+
+FT_LOCAL( FT_UInt32 )
+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
diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c
index 6f672d593..8177c66f1 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"
/**************************************************************************
@@ -227,7 +228,6 @@
dummy->units_per_em / 100 );
axis->width_count = num_widths;
}
-
Exit:
for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
{
@@ -1153,6 +1153,8 @@
goto Exit;
}
af_latin_metrics_check_digits( metrics, face );
+
+ af_reverse_character_map_new( face, &metrics->root.reverse_charmap,
face->memory );
}
Exit:
@@ -1502,6 +1504,11 @@
af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT );
}
+ 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 );
+ }
/* Extract standard_width from writing system/script specific */
/* metrics class. */
@@ -2738,6 +2745,83 @@
}
+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 ) {
+ return;
+ }
+ if ( af_lookup_vertical_seperation_type( reverse_charmap, glyph_index ) ==
AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE &&
+ hints->num_contours == 2 ) {
+
+ /* Figure out which contout is the higher one by finding the one */
+ /* with the highest minimum y value */
+
+ FT_Int highest_contour = -1;
+ FT_Pos highest_min_y = 0;
+ FT_Pos current_min_y = 0;
+
+ 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?*/
+ 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;
+ }
+ }
+
+ /* If there are any contours that have a maximum y coordinate */
+ /* greater or equal to the minimum y coordinate of the previously found
highest*/
+ /* 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) {
+ continue;
+ }
+ AF_Point point = hints->contours[contour];
+ AF_Point first_point = point;
+ if ( point == NULL ) {
+ continue;
+ }
+ FT_Pos 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 > 0 ) {
+ AF_Point point = hints->contours[highest_contour];
+ AF_Point first_point = point;
+ if ( point != NULL ) {
+ do {
+ point->y += adjustment_amount;
+ point = point->next;
+ } while ( point != first_point );
+ }
+ }
+ }
+}
+
+
/* 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 +3689,7 @@
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);
}
}
@@ -3633,12 +3718,11 @@
(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 */
(AF_WritingSystem_ApplyHintsFunc) af_latin_hints_apply /*
style_hints_apply */
)
-
/* END */
diff --git a/src/autofit/aftypes.h b/src/autofit/aftypes.h
index 661519449..aca173567 100644
--- a/src/autofit/aftypes.h
+++ b/src/autofit/aftypes.h
@@ -39,6 +39,7 @@
#include <freetype/internal/ftdebug.h>
#include "afblue.h"
+#include "afadjust.h"
#ifdef FT_DEBUG_AUTOFIT
#include FT_CONFIG_STANDARD_LIBRARY_H
@@ -417,6 +418,7 @@ extern void* af_debug_hints_;
FT_Bool digits_have_same_width;
AF_FaceGlobals globals; /* to access properties */
+ AF_ReverseCharacterMap reverse_charmap;
} AF_StyleMetricsRec;
diff --git a/src/autofit/autofit.c b/src/autofit/autofit.c
index 8bd609b5e..55017186d 100644
--- a/src/autofit/autofit.c
+++ b/src/autofit/autofit.c
@@ -30,6 +30,7 @@
#include "afmodule.c"
#include "afranges.c"
#include "afshaper.c"
+#include "afadjust.c"
/* END */
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index abfa3ab0e..b379868ba 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -1358,7 +1358,6 @@
driver );
}
-
/**************************************************************************
*
* @Function:
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [freetype2] gsoc-craig-2023 f8e996bfb: Prototype adjustment database, reverse character lookup, and fixes for a few characters,
Werner Lemberg <=