tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ftgloadr.c (11115B)


      1 /****************************************************************************
      2 *
      3 * ftgloadr.c
      4 *
      5 *   The FreeType glyph loader (body).
      6 *
      7 * Copyright (C) 2002-2025 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 <freetype/internal/ftdebug.h>
     20 #include <freetype/internal/ftgloadr.h>
     21 #include <freetype/internal/ftmemory.h>
     22 #include <freetype/internal/ftobjs.h>
     23 
     24 #undef  FT_COMPONENT
     25 #define FT_COMPONENT  gloader
     26 
     27 
     28  /*************************************************************************/
     29  /*************************************************************************/
     30  /*************************************************************************/
     31  /*****                                                               *****/
     32  /*****                                                               *****/
     33  /*****                    G L Y P H   L O A D E R                    *****/
     34  /*****                                                               *****/
     35  /*****                                                               *****/
     36  /*************************************************************************/
     37  /*************************************************************************/
     38  /*************************************************************************/
     39 
     40  /**************************************************************************
     41   *
     42   * The glyph loader is a simple object which is used to load a set of
     43   * glyphs easily.  It is critical for the correct loading of composites.
     44   *
     45   * Ideally, one can see it as a stack of abstract `glyph' objects.
     46   *
     47   *   loader.base     Is really the bottom of the stack.  It describes a
     48   *                   single glyph image made of the juxtaposition of
     49   *                   several glyphs (those `in the stack').
     50   *
     51   *   loader.current  Describes the top of the stack, on which a new
     52   *                   glyph can be loaded.
     53   *
     54   *   Rewind          Clears the stack.
     55   *   Prepare         Set up `loader.current' for addition of a new glyph
     56   *                   image.
     57   *   Add             Add the `current' glyph image to the `base' one,
     58   *                   and prepare for another one.
     59   *
     60   * The glyph loader is now a base object.  Each driver used to
     61   * re-implement it in one way or the other, which wasted code and
     62   * energy.
     63   *
     64   */
     65 
     66 
     67  /* create a new glyph loader */
     68  FT_BASE_DEF( FT_Error )
     69  FT_GlyphLoader_New( FT_Memory        memory,
     70                      FT_GlyphLoader  *aloader )
     71  {
     72    FT_GlyphLoader  loader = NULL;
     73    FT_Error        error;
     74 
     75 
     76    if ( !FT_NEW( loader ) )
     77    {
     78      loader->memory = memory;
     79      *aloader       = loader;
     80    }
     81    return error;
     82  }
     83 
     84 
     85  /* rewind the glyph loader - reset counters to 0 */
     86  FT_BASE_DEF( void )
     87  FT_GlyphLoader_Rewind( FT_GlyphLoader  loader )
     88  {
     89    FT_GlyphLoad  base    = &loader->base;
     90    FT_GlyphLoad  current = &loader->current;
     91 
     92 
     93    base->outline.n_points   = 0;
     94    base->outline.n_contours = 0;
     95    base->outline.flags      = 0;
     96    base->num_subglyphs      = 0;
     97 
     98    *current = *base;
     99  }
    100 
    101 
    102  /* reset glyph loader, free all allocated tables, */
    103  /* and start from zero                            */
    104  FT_BASE_DEF( void )
    105  FT_GlyphLoader_Reset( FT_GlyphLoader  loader )
    106  {
    107    FT_Memory  memory = loader->memory;
    108 
    109 
    110    FT_FREE( loader->base.outline.points );
    111    FT_FREE( loader->base.outline.tags );
    112    FT_FREE( loader->base.outline.contours );
    113    FT_FREE( loader->base.extra_points );
    114    FT_FREE( loader->base.subglyphs );
    115 
    116    loader->base.extra_points2 = NULL;
    117 
    118    loader->max_points    = 0;
    119    loader->max_contours  = 0;
    120    loader->max_subglyphs = 0;
    121 
    122    FT_GlyphLoader_Rewind( loader );
    123  }
    124 
    125 
    126  /* delete a glyph loader */
    127  FT_BASE_DEF( void )
    128  FT_GlyphLoader_Done( FT_GlyphLoader  loader )
    129  {
    130    if ( loader )
    131    {
    132      FT_Memory  memory = loader->memory;
    133 
    134 
    135      FT_GlyphLoader_Reset( loader );
    136      FT_FREE( loader );
    137    }
    138  }
    139 
    140 
    141  /* re-adjust the `current' outline fields */
    142  static void
    143  FT_GlyphLoader_Adjust_Points( FT_GlyphLoader  loader )
    144  {
    145    FT_Outline*  base    = &loader->base.outline;
    146    FT_Outline*  current = &loader->current.outline;
    147 
    148 
    149    current->points   = FT_OFFSET( base->points,   base->n_points );
    150    current->tags     = FT_OFFSET( base->tags,     base->n_points );
    151    current->contours = FT_OFFSET( base->contours, base->n_contours );
    152 
    153    /* handle extra points table - if any */
    154    if ( loader->use_extra )
    155    {
    156      loader->current.extra_points  = loader->base.extra_points +
    157                                      base->n_points;
    158 
    159      loader->current.extra_points2 = loader->base.extra_points2 +
    160                                      base->n_points;
    161    }
    162  }
    163 
    164 
    165  FT_BASE_DEF( FT_Error )
    166  FT_GlyphLoader_CreateExtra( FT_GlyphLoader  loader )
    167  {
    168    FT_Error   error;
    169    FT_Memory  memory = loader->memory;
    170 
    171 
    172    if ( loader->max_points == 0           ||
    173         loader->base.extra_points != NULL )
    174      return FT_Err_Ok;
    175 
    176    if ( !FT_NEW_ARRAY( loader->base.extra_points, 2 * loader->max_points ) )
    177    {
    178      loader->use_extra          = 1;
    179      loader->base.extra_points2 = loader->base.extra_points +
    180                                   loader->max_points;
    181 
    182      FT_GlyphLoader_Adjust_Points( loader );
    183    }
    184    return error;
    185  }
    186 
    187 
    188  /* re-adjust the `current' subglyphs field */
    189  static void
    190  FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader  loader )
    191  {
    192    FT_GlyphLoad  base    = &loader->base;
    193    FT_GlyphLoad  current = &loader->current;
    194 
    195 
    196    current->subglyphs = FT_OFFSET( base->subglyphs, base->num_subglyphs );
    197  }
    198 
    199 
    200  /* Ensure that we can add `n_points' and `n_contours' to our glyph.      */
    201  /* This function reallocates its outline tables if necessary.  Note that */
    202  /* it DOESN'T change the number of points within the loader!             */
    203  /*                                                                       */
    204  FT_BASE_DEF( FT_Error )
    205  FT_GlyphLoader_CheckPoints( FT_GlyphLoader  loader,
    206                              FT_UInt         n_points,
    207                              FT_UInt         n_contours )
    208  {
    209    FT_Memory    memory  = loader->memory;
    210    FT_Error     error   = FT_Err_Ok;
    211    FT_Outline*  base    = &loader->base.outline;
    212    FT_Outline*  current = &loader->current.outline;
    213    FT_Bool      adjust  = 0;
    214 
    215    FT_UInt  new_max, old_max, min_new_max;
    216 
    217 
    218    error = FT_GlyphLoader_CreateExtra( loader );
    219    if ( error )
    220      goto Exit;
    221 
    222    /* check points & tags */
    223    new_max = (FT_UInt)base->n_points + (FT_UInt)current->n_points +
    224              n_points;
    225    old_max = loader->max_points;
    226 
    227    if ( new_max > old_max )
    228    {
    229      if ( new_max > FT_OUTLINE_POINTS_MAX )
    230      {
    231        error = FT_THROW( Array_Too_Large );
    232        goto Exit;
    233      }
    234 
    235      min_new_max = old_max + ( old_max >> 1 );
    236      if ( new_max < min_new_max )
    237        new_max = min_new_max;
    238      new_max = FT_PAD_CEIL( new_max, 8 );
    239      if ( new_max > FT_OUTLINE_POINTS_MAX )
    240        new_max = FT_OUTLINE_POINTS_MAX;
    241 
    242      if ( FT_RENEW_ARRAY( base->points, old_max, new_max ) ||
    243           FT_RENEW_ARRAY( base->tags,   old_max, new_max ) )
    244        goto Exit;
    245 
    246      if ( loader->use_extra )
    247      {
    248        if ( FT_RENEW_ARRAY( loader->base.extra_points,
    249                             old_max * 2, new_max * 2 ) )
    250          goto Exit;
    251 
    252        FT_ARRAY_MOVE( loader->base.extra_points + new_max,
    253                       loader->base.extra_points + old_max,
    254                       old_max );
    255 
    256        loader->base.extra_points2 = loader->base.extra_points + new_max;
    257      }
    258 
    259      adjust = 1;
    260      loader->max_points = new_max;
    261    }
    262 
    263    error = FT_GlyphLoader_CreateExtra( loader );
    264    if ( error )
    265      goto Exit;
    266 
    267    /* check contours */
    268    old_max = loader->max_contours;
    269    new_max = (FT_UInt)base->n_contours + (FT_UInt)current->n_contours +
    270              n_contours;
    271    if ( new_max > old_max )
    272    {
    273      if ( new_max > FT_OUTLINE_CONTOURS_MAX )
    274      {
    275        error = FT_THROW( Array_Too_Large );
    276        goto Exit;
    277      }
    278 
    279      min_new_max = old_max + ( old_max >> 1 );
    280      if ( new_max < min_new_max )
    281        new_max = min_new_max;
    282      new_max = FT_PAD_CEIL( new_max, 4 );
    283      if ( new_max > FT_OUTLINE_CONTOURS_MAX )
    284        new_max = FT_OUTLINE_CONTOURS_MAX;
    285 
    286      if ( FT_RENEW_ARRAY( base->contours, old_max, new_max ) )
    287        goto Exit;
    288 
    289      adjust = 1;
    290      loader->max_contours = new_max;
    291    }
    292 
    293    if ( adjust )
    294      FT_GlyphLoader_Adjust_Points( loader );
    295 
    296  Exit:
    297    if ( error )
    298      FT_GlyphLoader_Reset( loader );
    299 
    300    return error;
    301  }
    302 
    303 
    304  /* Ensure that we can add `n_subglyphs' to our glyph. this function */
    305  /* reallocates its subglyphs table if necessary.  Note that it DOES */
    306  /* NOT change the number of subglyphs within the loader!            */
    307  /*                                                                  */
    308  FT_BASE_DEF( FT_Error )
    309  FT_GlyphLoader_CheckSubGlyphs( FT_GlyphLoader  loader,
    310                                 FT_UInt         n_subs )
    311  {
    312    FT_Memory     memory = loader->memory;
    313    FT_Error      error  = FT_Err_Ok;
    314    FT_UInt       new_max, old_max;
    315 
    316    FT_GlyphLoad  base    = &loader->base;
    317    FT_GlyphLoad  current = &loader->current;
    318 
    319 
    320    new_max = base->num_subglyphs + current->num_subglyphs + n_subs;
    321    old_max = loader->max_subglyphs;
    322    if ( new_max > old_max )
    323    {
    324      new_max = FT_PAD_CEIL( new_max, 2 );
    325      if ( FT_RENEW_ARRAY( base->subglyphs, old_max, new_max ) )
    326        goto Exit;
    327 
    328      loader->max_subglyphs = new_max;
    329 
    330      FT_GlyphLoader_Adjust_Subglyphs( loader );
    331    }
    332 
    333  Exit:
    334    return error;
    335  }
    336 
    337 
    338  /* prepare loader for the addition of a new glyph on top of the base one */
    339  FT_BASE_DEF( void )
    340  FT_GlyphLoader_Prepare( FT_GlyphLoader  loader )
    341  {
    342    FT_GlyphLoad  current = &loader->current;
    343 
    344 
    345    current->outline.n_points   = 0;
    346    current->outline.n_contours = 0;
    347    current->num_subglyphs      = 0;
    348 
    349    FT_GlyphLoader_Adjust_Points   ( loader );
    350    FT_GlyphLoader_Adjust_Subglyphs( loader );
    351  }
    352 
    353 
    354  /* add current glyph to the base image -- and prepare for another */
    355  FT_BASE_DEF( void )
    356  FT_GlyphLoader_Add( FT_GlyphLoader  loader )
    357  {
    358    FT_Outline*  base;
    359    FT_Outline*  current;
    360    FT_Int       n;
    361 
    362 
    363    if ( !loader )
    364      return;
    365 
    366    base    = &loader->base.outline;
    367    current = &loader->current.outline;
    368 
    369    /* adjust contours count in newest outline */
    370    for ( n = 0; n < current->n_contours; n++ )
    371      current->contours[n] += base->n_points;
    372 
    373    base->n_points   += current->n_points;
    374    base->n_contours += current->n_contours;
    375 
    376    loader->base.num_subglyphs += loader->current.num_subglyphs;
    377 
    378    /* prepare for another new glyph image */
    379    FT_GlyphLoader_Prepare( loader );
    380  }
    381 
    382 
    383 /* END */