[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[freetype2] gsoc-craig-2023-final b9095238d: [autofit] add functions for
From: |
Werner Lemberg |
Subject: |
[freetype2] gsoc-craig-2023-final b9095238d: [autofit] add functions for creating and using reverse character maps |
Date: |
Tue, 31 Oct 2023 23:35:10 -0400 (EDT) |
branch: gsoc-craig-2023-final
commit b9095238d21f778e1d87d10e704c8347faf42b92
Author: Craig White <gerzytet@gmail.com>
Commit: Craig White <gerzytet@gmail.com>
[autofit] add functions for creating and using reverse character maps
as well as looking up entries in the adjustment database.
* include/freetype/internal/ftobjs.h (find_unicode_charmap) Move
documentation
and function prototype from ftobjs.c to this file so that it can be called
from afadjust.c
* src/base/ftobjs.c (find_unicode_charmap) make this function non-static
* src/autofit/afadjust.c Add functions for looking up vertical adjustment
type, tilde correction type, creating and deleting reverse character maps
* src/autofit/afadjust.h Add headers for the above functions. Correct
definition of AF_AdjustmentDatabaseEntry_ to include tilde correction
type
* src/autofit/aftypes.h Add prototype of AF_ReverseCharacterMap
* src/autofit/autofit.c Add include of afadjust.c
---
include/freetype/internal/ftobjs.h | 20 ++++
src/autofit/afadjust.c | 219 +++++++++++++++++++++++++++++++++++++
src/autofit/afadjust.h | 28 ++++-
src/autofit/aftypes.h | 6 +
src/autofit/autofit.c | 1 +
src/base/ftobjs.c | 17 +--
6 files changed, 271 insertions(+), 20 deletions(-)
diff --git a/include/freetype/internal/ftobjs.h
b/include/freetype/internal/ftobjs.h
index 28bc9b65f..ceb4251df 100644
--- a/include/freetype/internal/ftobjs.h
+++ b/include/freetype/internal/ftobjs.h
@@ -275,6 +275,26 @@ FT_BEGIN_HEADER
FT_GlyphSlot slot,
FT_Render_Mode mode );
+ /**************************************************************************
+ *
+ * @Function:
+ * find_unicode_charmap
+ *
+ * @Description:
+ * This function finds a Unicode charmap, if there is one.
+ * And if there is more than one, it tries to favour the more
+ * extensive one, i.e., one that supports UCS-4 against those which
+ * are limited to the BMP ( UCS-2 encoding.)
+ *
+ * If a unicode charmap is found, face->charmap is set to it.
+ *
+ * This function is called from open_face(),
+ * from FT_Select_Charmap( ..., FT_ENCODING_UNICODE ),
+ * and also from afadjust.c in the autofit module.
+ */
+ FT_BASE( FT_Error )
+ find_unicode_charmap( FT_Face face );
+
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
typedef void (*FT_Bitmap_LcdFilterFunc)( FT_Bitmap* bitmap,
diff --git a/src/autofit/afadjust.c b/src/autofit/afadjust.c
index d48e06883..5ebffa470 100644
--- a/src/autofit/afadjust.c
+++ b/src/autofit/afadjust.c
@@ -136,3 +136,222 @@ adjustment_database[] =
{0x17D, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 0},
{0x17E, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 0}
};
+
+/*Helper function: get the adjustment database entry for a codepoint*/
+FT_LOCAL_DEF( const AF_AdjustmentDatabaseEntry* )
+af_adjustment_database_lookup( FT_UInt32 codepoint ) {
+ /* Binary search for database entry */
+ FT_Int low = 0;
+ FT_Int high = AF_ADJUSTMENT_DATABASE_LENGTH - 1;
+ while ( high >= low )
+ {
+ FT_Int mid = ( low + high ) / 2;
+ FT_UInt32 mid_codepoint = adjustment_database[mid].codepoint;
+ if ( mid_codepoint < codepoint )
+ {
+ low = mid + 1;
+ }
+ else if ( mid_codepoint > codepoint )
+ {
+ high = mid - 1;
+ }
+ else
+ {
+ return &adjustment_database[mid];
+ }
+ }
+
+ 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;
+}
+
+/*1 if tilde correction should be applied to the topmost contour
+else 0*/
+FT_LOCAL_DEF( FT_Bool )
+af_lookup_tilde_correction_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 0;
+ }
+ return entry->apply_tilde;
+}
+
+typedef struct AF_ReverseMapEntry_
+{
+ FT_Int glyph_index;
+ FT_UInt32 codepoint;
+} AF_ReverseMapEntry;
+
+typedef struct AF_ReverseCharacterMap_
+{
+ FT_Long length;
+ AF_ReverseMapEntry *entries;
+} AF_ReverseCharacterMap_Rec;
+
+/* qsort compare function for reverse character map */
+FT_LOCAL_DEF( FT_Int )
+af_reverse_character_map_entry_compare( const void *a, const void *b ) {
+ const AF_ReverseMapEntry entry_a = *((const AF_ReverseMapEntry *)a);
+ const AF_ReverseMapEntry entry_b = *((const AF_ReverseMapEntry *)b);
+ return entry_a.glyph_index < entry_b.glyph_index ? -1 :
entry_a.glyph_index > entry_b.glyph_index ? 1 : 0;
+}
+
+FT_LOCAL_DEF( FT_UInt32 )
+af_reverse_character_map_lookup_( AF_ReverseCharacterMap map, FT_Int
glyph_index, FT_Long length )
+{
+ if ( map == NULL )
+ {
+ return 0;
+ }
+ /* Binary search for reverse character map entry */
+ FT_Int low = 0;
+ FT_Int high = length - 1;
+ while ( high >= low )
+ {
+ FT_Int mid = ( high + low ) / 2;
+ FT_Int mid_glyph_index = map->entries[mid].glyph_index;
+ if ( glyph_index < mid_glyph_index )
+ {
+ high = mid - 1;
+ }
+ else if ( glyph_index > mid_glyph_index )
+ {
+ low = mid + 1;
+ }
+ else
+ {
+ return map->entries[mid].codepoint;
+ }
+ }
+
+ return 0;
+}
+
+FT_LOCAL_DEF( FT_UInt32 )
+af_reverse_character_map_lookup( AF_ReverseCharacterMap map, FT_Int
glyph_index )
+{
+ return af_reverse_character_map_lookup_( map, glyph_index, map->length );
+}
+
+/*prepare to add one more entry to the reverse character map
+ this is a helper for af_reverse_character_map_new*/
+FT_LOCAL_DEF( FT_Error )
+af_reverse_character_map_expand( AF_ReverseCharacterMap map, FT_Long
*capacity, FT_Memory memory )
+{
+ FT_Error error;
+ if ( map->length < *capacity )
+ {
+ return FT_Err_Ok;
+ }
+
+ if ( map->length == *capacity )
+ {
+ FT_Long new_capacity = *capacity + *capacity / 2;
+ if ( FT_RENEW_ARRAY( map->entries, map->length, new_capacity ) ) {
+ return error;
+ }
+ *capacity = new_capacity;
+ }
+
+ return FT_Err_Ok;
+}
+
+FT_LOCAL_DEF( FT_Error )
+af_reverse_character_map_new( AF_ReverseCharacterMap *map, AF_FaceGlobals
globals )
+{
+ FT_Face face = globals->face;
+ FT_Memory memory = face->memory;
+ /* Search for a unicode charmap */
+ /* If there isn't one, create a blank map */
+
+ FT_TRACE4(( "af_reverse_character_map_new: building reverse character
map\n" ));
+
+ FT_Error error;
+ /* backup face->charmap because find_unicode_charmap sets it */
+ FT_CharMap old_charmap = face->charmap;
+ if ( ( error = find_unicode_charmap( face ) ) )
+ {
+ *map = NULL;
+ goto Exit;
+ }
+
+ if ( FT_NEW( *map ) )
+ {
+ goto Exit;
+ }
+
+ FT_Long capacity = 10;
+ ( *map )->length = 0;
+
+ if ( FT_NEW_ARRAY( ( *map )->entries, capacity) )
+ {
+ goto Exit;
+ }
+
+#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 = FT_Get_Char_Index( face, codepoint );
+ if ( glyph == 0 )
+ {
+#ifdef FT_DEBUG_LEVEL_TRACE
+ failed_lookups++;
+#endif
+ continue;
+ }
+ error = af_reverse_character_map_expand( *map, &capacity, memory );
+ if ( error ) {
+ goto Exit;
+ }
+
+ ( *map )->length++;
+ ( *map )->entries[i].glyph_index = glyph;
+ ( *map )->entries[i].codepoint = codepoint;
+ }
+
+ ft_qsort(
+ ( *map )->entries,
+ ( *map )->length,
+ sizeof( AF_ReverseMapEntry ),
+ af_reverse_character_map_entry_compare
+ );
+
+ FT_TRACE4(( " reverse character map built successfully"\
+ " with %d entries\n", (*map)->length ));
+
+Exit:
+ face->charmap = old_charmap;
+ 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;
+ }
+
+ 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;
+}
diff --git a/src/autofit/afadjust.h b/src/autofit/afadjust.h
index 6b67703d0..5f9c01ed1 100644
--- a/src/autofit/afadjust.h
+++ b/src/autofit/afadjust.h
@@ -2,6 +2,7 @@
#define AFADJUST_H_
#include <freetype/fttypes.h>
+#include "afglobal.h"
FT_BEGIN_HEADER
@@ -20,10 +21,29 @@ typedef enum AF_VerticalSeparationAdjustmentType_
AF_VERTICAL_ADJUSTMENT_NONE
} 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;
+ FT_Bool apply_tilde;
+} AF_AdjustmentDatabaseEntry;
+
+FT_LOCAL(AF_VerticalSeparationAdjustmentType)
+af_lookup_vertical_seperation_type( AF_ReverseCharacterMap map, FT_Int
glyph_index );
+
+FT_LOCAL( FT_Bool )
+af_lookup_tilde_correction_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( AF_ReverseCharacterMap *map, AF_FaceGlobals
globals );
+
+/*free the reverse character map*/
+FT_LOCAL( FT_Error )
+af_reverse_character_map_done( AF_ReverseCharacterMap map, FT_Memory memory );
struct AF_ReverseCharacterMap_;
diff --git a/src/autofit/aftypes.h b/src/autofit/aftypes.h
index 661519449..dd96f47c3 100644
--- a/src/autofit/aftypes.h
+++ b/src/autofit/aftypes.h
@@ -406,6 +406,12 @@ extern void* af_debug_hints_;
typedef struct AF_FaceGlobalsRec_* AF_FaceGlobals;
+ /*stores a mapping from glyphs to unicode codepoints
+ see afadjust.c for details */
+ struct AF_ReverseCharacterMap_;
+
+ typedef struct AF_ReverseCharacterMap_ *AF_ReverseCharacterMap;
+
/* This is the main structure that combines everything. Autofit modules */
/* specific to writing systems derive their structures from it, for */
/* example `AF_LatinMetrics'. */
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 759b95c73..1a642140d 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -1358,22 +1358,7 @@
driver );
}
-
- /**************************************************************************
- *
- * @Function:
- * find_unicode_charmap
- *
- * @Description:
- * This function finds a Unicode charmap, if there is one.
- * And if there is more than one, it tries to favour the more
- * extensive one, i.e., one that supports UCS-4 against those which
- * are limited to the BMP (said UCS-2 encoding.)
- *
- * This function is called from open_face() (just below), and also
- * from FT_Select_Charmap( ..., FT_ENCODING_UNICODE ).
- */
- static FT_Error
+ FT_Error
find_unicode_charmap( FT_Face face )
{
FT_CharMap* first;
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [freetype2] gsoc-craig-2023-final b9095238d: [autofit] add functions for creating and using reverse character maps,
Werner Lemberg <=