freetype-commit
[Top][All Lists]
Advanced

[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;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]