"Fossies" - the Fresh Open Source Software Archive

Member "SDL2_ttf-2.20.2/external/freetype/src/autofit/afglobal.c" (25 May 2022, 13819 Bytes) of package /linux/misc/SDL2_ttf-2.20.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "afglobal.c" see the Fossies "Dox" file reference documentation.

    1 /****************************************************************************
    2  *
    3  * afglobal.c
    4  *
    5  *   Auto-fitter routines to compute global hinting values (body).
    6  *
    7  * Copyright (C) 2003-2022 by
    8  * David Turner, Robert Wilhelm, and Werner Lemberg.
    9  *
   10  * This file is part of the FreeType project, and may only be used,
   11  * modified, and distributed under the terms of the FreeType project
   12  * license, LICENSE.TXT.  By continuing to use, modify, or distribute
   13  * this file you indicate that you have read the license and
   14  * understand and accept it fully.
   15  *
   16  */
   17 
   18 
   19 #include "afglobal.h"
   20 #include "afranges.h"
   21 #include "afshaper.h"
   22 #include "afws-decl.h"
   23 #include <freetype/internal/ftdebug.h>
   24 
   25 
   26   /**************************************************************************
   27    *
   28    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
   29    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
   30    * messages during execution.
   31    */
   32 #undef  FT_COMPONENT
   33 #define FT_COMPONENT  afglobal
   34 
   35 
   36 #include "aferrors.h"
   37 
   38 
   39 #undef  SCRIPT
   40 #define SCRIPT( s, S, d, h, H, ss )         \
   41           AF_DEFINE_SCRIPT_CLASS(           \
   42             af_ ## s ## _script_class,      \
   43             AF_SCRIPT_ ## S,                \
   44             af_ ## s ## _uniranges,         \
   45             af_ ## s ## _nonbase_uniranges, \
   46             AF_ ## H,                       \
   47             ss )
   48 
   49 #include "afscript.h"
   50 
   51 
   52 #undef  STYLE
   53 #define STYLE( s, S, d, ws, sc, ss, c )  \
   54           AF_DEFINE_STYLE_CLASS(         \
   55             af_ ## s ## _style_class,    \
   56             AF_STYLE_ ## S,              \
   57             ws,                          \
   58             sc,                          \
   59             ss,                          \
   60             c )
   61 
   62 #include "afstyles.h"
   63 
   64 
   65 #undef  WRITING_SYSTEM
   66 #define WRITING_SYSTEM( ws, WS )               \
   67           &af_ ## ws ## _writing_system_class,
   68 
   69   FT_LOCAL_ARRAY_DEF( AF_WritingSystemClass )
   70   af_writing_system_classes[] =
   71   {
   72 
   73 #include "afws-iter.h"
   74 
   75     NULL  /* do not remove */
   76   };
   77 
   78 
   79 #undef  SCRIPT
   80 #define SCRIPT( s, S, d, h, H, ss )   \
   81           &af_ ## s ## _script_class,
   82 
   83   FT_LOCAL_ARRAY_DEF( AF_ScriptClass )
   84   af_script_classes[] =
   85   {
   86 
   87 #include "afscript.h"
   88 
   89     NULL  /* do not remove */
   90   };
   91 
   92 
   93 #undef  STYLE
   94 #define STYLE( s, S, d, ws, sc, ss, c ) \
   95           &af_ ## s ## _style_class,
   96 
   97   FT_LOCAL_ARRAY_DEF( AF_StyleClass )
   98   af_style_classes[] =
   99   {
  100 
  101 #include "afstyles.h"
  102 
  103     NULL  /* do not remove */
  104   };
  105 
  106 
  107 #ifdef FT_DEBUG_LEVEL_TRACE
  108 
  109 #undef  STYLE
  110 #define STYLE( s, S, d, ws, sc, ss, c )  #s,
  111 
  112   FT_LOCAL_ARRAY_DEF( char* )
  113   af_style_names[] =
  114   {
  115 
  116 #include "afstyles.h"
  117 
  118   };
  119 
  120 #endif /* FT_DEBUG_LEVEL_TRACE */
  121 
  122 
  123   /* Compute the style index of each glyph within a given face. */
  124 
  125   static FT_Error
  126   af_face_globals_compute_style_coverage( AF_FaceGlobals  globals )
  127   {
  128     FT_Error    error;
  129     FT_Face     face        = globals->face;
  130     FT_CharMap  old_charmap = face->charmap;
  131     FT_UShort*  gstyles     = globals->glyph_styles;
  132     FT_UInt     ss;
  133     FT_UInt     i;
  134     FT_UInt     dflt        = ~0U; /* a non-valid value */
  135 
  136 
  137     /* the value AF_STYLE_UNASSIGNED means `uncovered glyph' */
  138     for ( i = 0; i < (FT_UInt)globals->glyph_count; i++ )
  139       gstyles[i] = AF_STYLE_UNASSIGNED;
  140 
  141     error = FT_Select_Charmap( face, FT_ENCODING_UNICODE );
  142     if ( error )
  143     {
  144       /*
  145        * Ignore this error; we simply use the fallback style.
  146        * XXX: Shouldn't we rather disable hinting?
  147        */
  148       error = FT_Err_Ok;
  149       goto Exit;
  150     }
  151 
  152     /* scan each style in a Unicode charmap */
  153     for ( ss = 0; af_style_classes[ss]; ss++ )
  154     {
  155       AF_StyleClass       style_class =
  156                             af_style_classes[ss];
  157       AF_ScriptClass      script_class =
  158                             af_script_classes[style_class->script];
  159       AF_Script_UniRange  range;
  160 
  161 
  162       if ( !script_class->script_uni_ranges )
  163         continue;
  164 
  165       /*
  166        * Scan all Unicode points in the range and set the corresponding
  167        * glyph style index.
  168        */
  169       if ( style_class->coverage == AF_COVERAGE_DEFAULT )
  170       {
  171         if ( (FT_UInt)style_class->script ==
  172              globals->module->default_script )
  173           dflt = ss;
  174 
  175         for ( range = script_class->script_uni_ranges;
  176               range->first != 0;
  177               range++ )
  178         {
  179           FT_ULong  charcode = range->first;
  180           FT_UInt   gindex;
  181 
  182 
  183           gindex = FT_Get_Char_Index( face, charcode );
  184 
  185           if ( gindex != 0                                                &&
  186                gindex < (FT_ULong)globals->glyph_count                    &&
  187                ( gstyles[gindex] & AF_STYLE_MASK ) == AF_STYLE_UNASSIGNED )
  188             gstyles[gindex] = (FT_UShort)ss;
  189 
  190           for (;;)
  191           {
  192             charcode = FT_Get_Next_Char( face, charcode, &gindex );
  193 
  194             if ( gindex == 0 || charcode > range->last )
  195               break;
  196 
  197             if ( gindex < (FT_ULong)globals->glyph_count                    &&
  198                  ( gstyles[gindex] & AF_STYLE_MASK ) == AF_STYLE_UNASSIGNED )
  199               gstyles[gindex] = (FT_UShort)ss;
  200           }
  201         }
  202 
  203         /* do the same for the script's non-base characters */
  204         for ( range = script_class->script_uni_nonbase_ranges;
  205               range->first != 0;
  206               range++ )
  207         {
  208           FT_ULong  charcode = range->first;
  209           FT_UInt   gindex;
  210 
  211 
  212           gindex = FT_Get_Char_Index( face, charcode );
  213 
  214           if ( gindex != 0                                          &&
  215                gindex < (FT_ULong)globals->glyph_count              &&
  216                ( gstyles[gindex] & AF_STYLE_MASK ) == (FT_UShort)ss )
  217             gstyles[gindex] |= AF_NONBASE;
  218 
  219           for (;;)
  220           {
  221             charcode = FT_Get_Next_Char( face, charcode, &gindex );
  222 
  223             if ( gindex == 0 || charcode > range->last )
  224               break;
  225 
  226             if ( gindex < (FT_ULong)globals->glyph_count              &&
  227                  ( gstyles[gindex] & AF_STYLE_MASK ) == (FT_UShort)ss )
  228               gstyles[gindex] |= AF_NONBASE;
  229           }
  230         }
  231       }
  232       else
  233       {
  234         /* get glyphs not directly addressable by cmap */
  235         af_shaper_get_coverage( globals, style_class, gstyles, 0 );
  236       }
  237     }
  238 
  239     /* handle the remaining default OpenType features ... */
  240     for ( ss = 0; af_style_classes[ss]; ss++ )
  241     {
  242       AF_StyleClass  style_class = af_style_classes[ss];
  243 
  244 
  245       if ( style_class->coverage == AF_COVERAGE_DEFAULT )
  246         af_shaper_get_coverage( globals, style_class, gstyles, 0 );
  247     }
  248 
  249     /* ... and finally the default OpenType features of the default script */
  250     af_shaper_get_coverage( globals, af_style_classes[dflt], gstyles, 1 );
  251 
  252     /* mark ASCII digits */
  253     for ( i = 0x30; i <= 0x39; i++ )
  254     {
  255       FT_UInt  gindex = FT_Get_Char_Index( face, i );
  256 
  257 
  258       if ( gindex != 0 && gindex < (FT_ULong)globals->glyph_count )
  259         gstyles[gindex] |= AF_DIGIT;
  260     }
  261 
  262   Exit:
  263     /*
  264      * By default, all uncovered glyphs are set to the fallback style.
  265      * XXX: Shouldn't we disable hinting or do something similar?
  266      */
  267     if ( globals->module->fallback_style != AF_STYLE_UNASSIGNED )
  268     {
  269       FT_Long  nn;
  270 
  271 
  272       for ( nn = 0; nn < globals->glyph_count; nn++ )
  273       {
  274         if ( ( gstyles[nn] & AF_STYLE_MASK ) == AF_STYLE_UNASSIGNED )
  275         {
  276           gstyles[nn] &= ~AF_STYLE_MASK;
  277           gstyles[nn] |= globals->module->fallback_style;
  278         }
  279       }
  280     }
  281 
  282 #ifdef FT_DEBUG_LEVEL_TRACE
  283 
  284     FT_TRACE4(( "\n" ));
  285     FT_TRACE4(( "style coverage\n" ));
  286     FT_TRACE4(( "==============\n" ));
  287     FT_TRACE4(( "\n" ));
  288 
  289     for ( ss = 0; af_style_classes[ss]; ss++ )
  290     {
  291       AF_StyleClass  style_class = af_style_classes[ss];
  292       FT_UInt        count       = 0;
  293       FT_Long        idx;
  294 
  295 
  296       FT_TRACE4(( "%s:\n", af_style_names[style_class->style] ));
  297 
  298       for ( idx = 0; idx < globals->glyph_count; idx++ )
  299       {
  300         if ( ( gstyles[idx] & AF_STYLE_MASK ) == style_class->style )
  301         {
  302           if ( !( count % 10 ) )
  303             FT_TRACE4(( " " ));
  304 
  305           FT_TRACE4(( " %ld", idx ));
  306           count++;
  307 
  308           if ( !( count % 10 ) )
  309             FT_TRACE4(( "\n" ));
  310         }
  311       }
  312 
  313       if ( !count )
  314         FT_TRACE4(( "  (none)\n" ));
  315       if ( count % 10 )
  316         FT_TRACE4(( "\n" ));
  317     }
  318 
  319 #endif /* FT_DEBUG_LEVEL_TRACE */
  320 
  321     FT_Set_Charmap( face, old_charmap );
  322     return error;
  323   }
  324 
  325 
  326   FT_LOCAL_DEF( FT_Error )
  327   af_face_globals_new( FT_Face          face,
  328                        AF_FaceGlobals  *aglobals,
  329                        AF_Module        module )
  330   {
  331     FT_Error        error;
  332     FT_Memory       memory;
  333     AF_FaceGlobals  globals = NULL;
  334 
  335 
  336     memory = face->memory;
  337 
  338     /* we allocate an AF_FaceGlobals structure together */
  339     /* with the glyph_styles array                      */
  340     if ( FT_QALLOC( globals,
  341                     sizeof ( *globals ) +
  342                       (FT_ULong)face->num_glyphs * sizeof ( FT_UShort ) ) )
  343       goto Exit;
  344 
  345     FT_ZERO( &globals->metrics );
  346 
  347     globals->face                      = face;
  348     globals->glyph_count               = face->num_glyphs;
  349     /* right after the globals structure come the glyph styles */
  350     globals->glyph_styles              = (FT_UShort*)( globals + 1 );
  351     globals->module                    = module;
  352     globals->stem_darkening_for_ppem   = 0;
  353     globals->darken_x                  = 0;
  354     globals->darken_y                  = 0;
  355     globals->standard_vertical_width   = 0;
  356     globals->standard_horizontal_width = 0;
  357     globals->scale_down_factor         = 0;
  358 
  359 #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
  360     globals->hb_font = hb_ft_font_create( face, NULL );
  361     globals->hb_buf  = hb_buffer_create();
  362 #endif
  363 
  364     error = af_face_globals_compute_style_coverage( globals );
  365     if ( error )
  366     {
  367       af_face_globals_free( globals );
  368       globals = NULL;
  369     }
  370     else
  371       globals->increase_x_height = AF_PROP_INCREASE_X_HEIGHT_MAX;
  372 
  373   Exit:
  374     *aglobals = globals;
  375     return error;
  376   }
  377 
  378 
  379   FT_LOCAL_DEF( void )
  380   af_face_globals_free( AF_FaceGlobals  globals )
  381   {
  382     if ( globals )
  383     {
  384       FT_Memory  memory = globals->face->memory;
  385       FT_UInt    nn;
  386 
  387 
  388       for ( nn = 0; nn < AF_STYLE_MAX; nn++ )
  389       {
  390         if ( globals->metrics[nn] )
  391         {
  392           AF_StyleClass          style_class =
  393             af_style_classes[nn];
  394           AF_WritingSystemClass  writing_system_class =
  395             af_writing_system_classes[style_class->writing_system];
  396 
  397 
  398           if ( writing_system_class->style_metrics_done )
  399             writing_system_class->style_metrics_done( globals->metrics[nn] );
  400 
  401           FT_FREE( globals->metrics[nn] );
  402         }
  403       }
  404 
  405 #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
  406       hb_font_destroy( globals->hb_font );
  407       hb_buffer_destroy( globals->hb_buf );
  408 #endif
  409 
  410       /* no need to free `globals->glyph_styles'; */
  411       /* it is part of the `globals' array        */
  412       FT_FREE( globals );
  413     }
  414   }
  415 
  416 
  417   FT_LOCAL_DEF( FT_Error )
  418   af_face_globals_get_metrics( AF_FaceGlobals    globals,
  419                                FT_UInt           gindex,
  420                                FT_UInt           options,
  421                                AF_StyleMetrics  *ametrics )
  422   {
  423     AF_StyleMetrics  metrics = NULL;
  424 
  425     AF_Style               style = (AF_Style)options;
  426     AF_WritingSystemClass  writing_system_class;
  427     AF_StyleClass          style_class;
  428 
  429     FT_Error  error = FT_Err_Ok;
  430 
  431 
  432     if ( gindex >= (FT_ULong)globals->glyph_count )
  433     {
  434       error = FT_THROW( Invalid_Argument );
  435       goto Exit;
  436     }
  437 
  438     /* if we have a forced style (via `options'), use it, */
  439     /* otherwise look into `glyph_styles' array           */
  440     if ( style == AF_STYLE_NONE_DFLT || style + 1 >= AF_STYLE_MAX )
  441       style = (AF_Style)( globals->glyph_styles[gindex] &
  442                           AF_STYLE_UNASSIGNED           );
  443 
  444   Again:
  445     style_class          = af_style_classes[style];
  446     writing_system_class = af_writing_system_classes
  447                              [style_class->writing_system];
  448 
  449     metrics = globals->metrics[style];
  450     if ( !metrics )
  451     {
  452       /* create the global metrics object if necessary */
  453       FT_Memory  memory = globals->face->memory;
  454 
  455 
  456       if ( FT_ALLOC( metrics, writing_system_class->style_metrics_size ) )
  457         goto Exit;
  458 
  459       metrics->style_class = style_class;
  460       metrics->globals     = globals;
  461 
  462       if ( writing_system_class->style_metrics_init )
  463       {
  464         error = writing_system_class->style_metrics_init( metrics,
  465                                                           globals->face );
  466         if ( error )
  467         {
  468           if ( writing_system_class->style_metrics_done )
  469             writing_system_class->style_metrics_done( metrics );
  470 
  471           FT_FREE( metrics );
  472 
  473           /* internal error code -1 indicates   */
  474           /* that no blue zones have been found */
  475           if ( error == -1 )
  476           {
  477             style = (AF_Style)( globals->glyph_styles[gindex] &
  478                                 AF_STYLE_UNASSIGNED           );
  479             /* IMPORTANT: Clear the error code, see
  480              * https://gitlab.freedesktop.org/freetype/freetype/-/issues/1063
  481              */
  482             error = FT_Err_Ok;
  483             goto Again;
  484           }
  485 
  486           goto Exit;
  487         }
  488       }
  489 
  490       globals->metrics[style] = metrics;
  491     }
  492 
  493   Exit:
  494     *ametrics = metrics;
  495 
  496     return error;
  497   }
  498 
  499 
  500   FT_LOCAL_DEF( FT_Bool )
  501   af_face_globals_is_digit( AF_FaceGlobals  globals,
  502                             FT_UInt         gindex )
  503   {
  504     if ( gindex < (FT_ULong)globals->glyph_count )
  505       return FT_BOOL( globals->glyph_styles[gindex] & AF_DIGIT );
  506 
  507     return FT_BOOL( 0 );
  508   }
  509 
  510 
  511 /* END */