Edit

kc3-lang/freetype/src/autofit/afglobal.c

Branch :

  • Show log

    Commit

  • Author : David Turner
    Date : 2004-02-23 21:08:37
    Hash : 9bfbf79c
    Message : adding support for dummy script, i.e. no-hinting for non latin glyphs

  • src/autofit/afglobal.c
  • #include "afglobal.h"
    #include "afdummy.h"
    #include "aflatin.h"
    
     /* populate this list when you add new scripts
      */
      static AF_ScriptClass const   af_script_classes[] =
      {
        & af_dummy_script_class,
        & af_latin_script_class,
    
        NULL  /* do not remove */
      };
    
    #define AF_SCRIPT_LIST_DEFAULT   0    /* index of default script in 'af_script_classes' */
    #define AF_SCRIPT_LIST_NONE      255  /* indicates an uncovered glyph                      */
    
     /*
      *  note that glyph_scripts[] is used to map each glyph into
      *  an index into the 'af_script_classes' array.
      *
      */
      typedef struct AF_FaceGlobalsRec_
      {
        FT_Face            face;
        FT_UInt            glyph_count;    /* same as face->num_glyphs     */
        FT_Byte*           glyph_scripts;
    
        AF_ScriptMetrics   metrics[ AF_SCRIPT_MAX ];
    
      } AF_FaceGlobalsRec;
    
    
    
    
     /* this function is used to compute the script index of each glyph
      * within a given face
      */
      static FT_Error
      af_face_globals_compute_script_coverage( AF_FaceGlobals  globals )
      {
        FT_Error    error       = 0;
        FT_Face     face        = globals->face;
        FT_CharMap  old_charmap = face->charmap;
        FT_Byte*    gscripts    = globals->glyph_scripts;
        FT_UInt     ss;
    
       /* the value 255 means "uncovered glyph"
        */
        FT_MEM_SET( globals->glyph_scripts,
                    AF_SCRIPT_LIST_NONE,
                    globals->glyph_count );
    
        error = FT_Select_Charmap( face, FT_ENCODING_UNICODE );
        if ( error )
        {
         /* ignore this error, we'll simply use Latin as the standard
          * script. XXX: Shouldn't we rather disable hinting ??
          */
          error = 0;
          goto Exit;
        }
    
       /* scan each script in a Unicode charmap
        */
        for ( ss = 0; af_script_classes[ss]; ss++ )
        {
          AF_ScriptClass      clazz = af_script_classes[ss];
          AF_Script_UniRange  range;
    
          if ( clazz->script_uni_ranges == NULL )
            continue;
    
         /* scan all unicode points in the range, and set the corresponding
          * glyph script index
          */
          for ( range = clazz->script_uni_ranges; range->first != 0; range++ )
          {
            FT_ULong  charcode = range->first;
            FT_UInt   gindex;
    
            gindex = FT_Get_Char_Index( face, charcode );
    
            if ( gindex != 0                               &&
                 gindex < globals->glyph_count             &&
                 gscripts[ gindex ] == AF_SCRIPT_LIST_NONE )
            {
              gscripts[ gindex ] = (FT_Byte) ss;
            }
            for (;;)
            {
              charcode = FT_Get_Next_Char( face, charcode, &gindex );
    
              if ( gindex == 0 || charcode > range->last )
                break;
    
              if ( gindex < globals->glyph_count       &&
                   gscripts[ gindex ] == AF_SCRIPT_LIST_NONE )
              {
                gscripts[ gindex ] = (FT_Byte) ss;
              }
            }
          }
        }
    
      Exit:
       /* by default, all uncovered glyphs are set to the latin script
        * XXX: shouldnt' we disable hinting or do something similar ?
        */
        {
          FT_UInt  nn;
    
          for ( nn = 0; nn < globals->glyph_count; nn++ )
          {
            if ( gscripts[ nn ] == AF_SCRIPT_LIST_NONE )
              gscripts[ nn ] = AF_SCRIPT_LIST_DEFAULT;
          }
        }
    
        FT_Set_Charmap( face, old_charmap );
        return error;
      }
    
    
    
      FT_LOCAL_DEF( FT_Error )
      af_face_globals_new( FT_Face          face,
                           AF_FaceGlobals  *aglobals )
      {
        FT_Error        error;
        FT_Memory       memory;
        AF_FaceGlobals  globals;
    
        memory = face->memory;
    
        if ( !FT_ALLOC( globals, sizeof(*globals) +
                                 face->num_glyphs*sizeof(FT_Byte) ) )
        {
          globals->face          = face;
          globals->glyph_count   = face->num_glyphs;
          globals->glyph_scripts = (FT_Byte*)( globals+1 );
    
          error = af_face_globals_compute_script_coverage( globals );
          if ( error )
          {
            af_face_globals_free( globals );
            globals = NULL;
          }
        }
    
        *aglobals = globals;
        return error;
      }
    
    
      FT_LOCAL_DEF( void )
      af_face_globals_free( AF_FaceGlobals  globals )
      {
        if ( globals )
        {
          FT_Memory  memory = globals->face->memory;
          FT_UInt    nn;
    
          for ( nn = 0; nn < AF_SCRIPT_MAX; nn++ )
          {
            if ( globals->metrics[nn] )
            {
              AF_ScriptClass  clazz = af_script_classes[nn];
    
              FT_ASSERT( globals->metrics[nn]->clazz == clazz );
    
              if ( clazz->script_metrics_done )
                clazz->script_metrics_done( globals->metrics[nn] );
    
              FT_FREE( globals->metrics[nn] );
            }
          }
    
          globals->glyph_count   = 0;
          globals->glyph_scripts = NULL;  /* no need to free this one !! */
          globals->face          = NULL;
          FT_FREE( globals );
        }
      }
    
    
      FT_LOCAL_DEF( FT_Error )
      af_face_globals_get_metrics( AF_FaceGlobals     globals,
                                   FT_UInt            gindex,
                                   AF_ScriptMetrics  *ametrics )
      {
        AF_ScriptMetrics  metrics = NULL;
        FT_UInt           index;
        AF_ScriptClass    clazz;
        FT_Error          error = 0;
    
        if ( gindex >= globals->glyph_count )
        {
          error = FT_Err_Invalid_Argument;
          goto Exit;
        }
    
        index   = globals->glyph_scripts[ gindex ];
        clazz   = af_script_classes[ index ];
        metrics = globals->metrics[ clazz->script ];
        if ( metrics == NULL )
        {
         /* create the global metrics object when needed
          */
          FT_Memory  memory = globals->face->memory;
    
          if ( FT_ALLOC( metrics, clazz->script_metrics_size ) )
            goto Exit;
    
          metrics->clazz = clazz;
    
          if ( clazz->script_metrics_init )
          {
            error = clazz->script_metrics_init( metrics, globals->face );
            if ( error )
            {
              if ( clazz->script_metrics_done )
                clazz->script_metrics_done( metrics );
    
              FT_FREE( metrics );
              goto Exit;
            }
          }
    
          globals->metrics[ clazz->script ] = metrics;
        }
    
      Exit:
        *ametrics = metrics;
        return error;
      }