tor-browser

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

cffgload.c (25855B)


      1 /****************************************************************************
      2 *
      3 * cffgload.c
      4 *
      5 *   OpenType Glyph Loader (body).
      6 *
      7 * Copyright (C) 1996-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/ftstream.h>
     21 #include <freetype/internal/sfnt.h>
     22 #include <freetype/internal/ftcalc.h>
     23 #include <freetype/internal/psaux.h>
     24 #include <freetype/ftoutln.h>
     25 #include <freetype/ftdriver.h>
     26 
     27 #include "cffload.h"
     28 #include "cffgload.h"
     29 
     30 #include "cfferrs.h"
     31 
     32 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
     33 #define IS_DEFAULT_INSTANCE( _face )             \
     34          ( !( FT_IS_NAMED_INSTANCE( _face ) ||  \
     35               FT_IS_VARIATION( _face )      ) )
     36 #else
     37 #define IS_DEFAULT_INSTANCE( _face )  1
     38 #endif
     39 
     40 
     41  /**************************************************************************
     42   *
     43   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
     44   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
     45   * messages during execution.
     46   */
     47 #undef  FT_COMPONENT
     48 #define FT_COMPONENT  cffgload
     49 
     50 
     51  FT_LOCAL_DEF( FT_Error )
     52  cff_get_glyph_data( TT_Face    face,
     53                      FT_UInt    glyph_index,
     54                      FT_Byte**  pointer,
     55                      FT_ULong*  length )
     56  {
     57 #ifdef FT_CONFIG_OPTION_INCREMENTAL
     58    /* For incremental fonts get the character data using the */
     59    /* callback function.                                     */
     60    if ( face->root.internal->incremental_interface )
     61    {
     62      FT_Data   data;
     63      FT_Error  error =
     64                  face->root.internal->incremental_interface->funcs->get_glyph_data(
     65                    face->root.internal->incremental_interface->object,
     66                    glyph_index, &data );
     67 
     68 
     69      *pointer = (FT_Byte*)data.pointer;
     70      *length  = data.length;
     71 
     72      return error;
     73    }
     74    else
     75 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
     76 
     77    {
     78      CFF_Font  cff = (CFF_Font)( face->extra.data );
     79 
     80 
     81      return cff_index_access_element( &cff->charstrings_index, glyph_index,
     82                                       pointer, length );
     83    }
     84  }
     85 
     86 
     87  FT_LOCAL_DEF( void )
     88  cff_free_glyph_data( TT_Face    face,
     89                       FT_Byte**  pointer,
     90                       FT_ULong   length )
     91  {
     92 #ifndef FT_CONFIG_OPTION_INCREMENTAL
     93    FT_UNUSED( length );
     94 #endif
     95 
     96 #ifdef FT_CONFIG_OPTION_INCREMENTAL
     97    /* For incremental fonts get the character data using the */
     98    /* callback function.                                     */
     99    if ( face->root.internal->incremental_interface )
    100    {
    101      FT_Data  data;
    102 
    103 
    104      data.pointer = *pointer;
    105      data.length  = (FT_UInt)length;
    106 
    107      face->root.internal->incremental_interface->funcs->free_glyph_data(
    108        face->root.internal->incremental_interface->object, &data );
    109    }
    110    else
    111 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
    112 
    113    {
    114      CFF_Font  cff = (CFF_Font)( face->extra.data );
    115 
    116 
    117      cff_index_forget_element( &cff->charstrings_index, pointer );
    118    }
    119  }
    120 
    121 
    122  /*************************************************************************/
    123  /*************************************************************************/
    124  /*************************************************************************/
    125  /**********                                                      *********/
    126  /**********                                                      *********/
    127  /**********            COMPUTE THE MAXIMUM ADVANCE WIDTH         *********/
    128  /**********                                                      *********/
    129  /**********    The following code is in charge of computing      *********/
    130  /**********    the maximum advance width of the font.  It        *********/
    131  /**********    quickly processes each glyph charstring to        *********/
    132  /**********    extract the value from either a `sbw' or `seac'   *********/
    133  /**********    operator.                                         *********/
    134  /**********                                                      *********/
    135  /*************************************************************************/
    136  /*************************************************************************/
    137  /*************************************************************************/
    138 
    139 
    140 #if 0 /* unused until we support pure CFF fonts */
    141 
    142 
    143  FT_LOCAL_DEF( FT_Error )
    144  cff_compute_max_advance( TT_Face  face,
    145                           FT_Int*  max_advance )
    146  {
    147    FT_Error     error = FT_Err_Ok;
    148    CFF_Decoder  decoder;
    149    FT_Int       glyph_index;
    150    CFF_Font     cff = (CFF_Font)face->other;
    151 
    152    PSAux_Service            psaux         = (PSAux_Service)face->psaux;
    153    const CFF_Decoder_Funcs  decoder_funcs = psaux->cff_decoder_funcs;
    154 
    155 
    156    *max_advance = 0;
    157 
    158    /* Initialize load decoder */
    159    decoder_funcs->init( &decoder, face, 0, 0, 0, 0, 0, 0 );
    160 
    161    decoder.builder.metrics_only = 1;
    162    decoder.builder.load_points  = 0;
    163 
    164    /* For each glyph, parse the glyph charstring and extract */
    165    /* the advance width.                                     */
    166    for ( glyph_index = 0; glyph_index < face->root.num_glyphs;
    167          glyph_index++ )
    168    {
    169      FT_Byte*  charstring;
    170      FT_ULong  charstring_len;
    171 
    172 
    173      /* now get load the unscaled outline */
    174      error = cff_get_glyph_data( face, glyph_index,
    175                                  &charstring, &charstring_len );
    176      if ( !error )
    177      {
    178        error = decoder_funcs->prepare( &decoder, size, glyph_index );
    179        if ( !error )
    180          error = decoder_funcs->parse_charstrings_old( &decoder,
    181                                                        charstring,
    182                                                        charstring_len,
    183                                                        0 );
    184 
    185        cff_free_glyph_data( face, &charstring, &charstring_len );
    186      }
    187 
    188      /* ignore the error if one has occurred -- skip to next glyph */
    189      error = FT_Err_Ok;
    190    }
    191 
    192    *max_advance = decoder.builder.advance.x;
    193 
    194    return FT_Err_Ok;
    195  }
    196 
    197 
    198 #endif /* 0 */
    199 
    200 
    201  FT_LOCAL_DEF( FT_Error )
    202  cff_slot_load( CFF_GlyphSlot  glyph,
    203                 CFF_Size       size,
    204                 FT_UInt        glyph_index,
    205                 FT_Int32       load_flags )
    206  {
    207    FT_Error     error;
    208    CFF_Decoder  decoder;
    209    PS_Decoder   psdecoder;
    210    TT_Face      face = (TT_Face)glyph->root.face;
    211    FT_Bool      hinting, scaled, force_scaling;
    212    CFF_Font     cff  = (CFF_Font)face->extra.data;
    213 
    214    PSAux_Service            psaux         = (PSAux_Service)face->psaux;
    215    const CFF_Decoder_Funcs  decoder_funcs = psaux->cff_decoder_funcs;
    216 
    217    FT_Matrix  font_matrix;
    218    FT_Vector  font_offset;
    219 
    220 
    221    force_scaling = FALSE;
    222 
    223    /* in a CID-keyed font, consider `glyph_index' as a CID and map */
    224    /* it immediately to the real glyph_index -- if it isn't a      */
    225    /* subsetted font, glyph_indices and CIDs are identical, though */
    226    if ( cff->top_font.font_dict.cid_registry != 0xFFFFU &&
    227         cff->charset.cids                               )
    228    {
    229      /* don't handle CID 0 (.notdef) which is directly mapped to GID 0 */
    230      if ( glyph_index != 0 )
    231      {
    232        glyph_index = cff_charset_cid_to_gindex( &cff->charset,
    233                                                 glyph_index );
    234        if ( glyph_index == 0 )
    235          return FT_THROW( Invalid_Argument );
    236      }
    237    }
    238    else if ( glyph_index >= cff->num_glyphs )
    239      return FT_THROW( Invalid_Argument );
    240 
    241 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
    242 
    243    /* try to load embedded bitmap if any              */
    244    /*                                                 */
    245    /* XXX: The convention should be emphasized in     */
    246    /*      the documents because it can be confusing. */
    247    {
    248      CFF_Face      cff_face = (CFF_Face)size->root.face;
    249      SFNT_Service  sfnt     = (SFNT_Service)cff_face->sfnt;
    250      FT_Stream     stream   = cff_face->root.stream;
    251 
    252 
    253      if ( size->strike_index != 0xFFFFFFFFUL      &&
    254           ( load_flags & FT_LOAD_NO_BITMAP ) == 0 &&
    255           IS_DEFAULT_INSTANCE( size->root.face )  )
    256      {
    257        TT_SBit_MetricsRec  metrics;
    258 
    259 
    260        error = sfnt->load_sbit_image( face,
    261                                       size->strike_index,
    262                                       glyph_index,
    263                                       (FT_UInt)load_flags,
    264                                       stream,
    265                                       &glyph->root.bitmap,
    266                                       &metrics );
    267 
    268        if ( !error )
    269        {
    270          FT_Bool    has_vertical_info;
    271          FT_UShort  advance;
    272          FT_Short   dummy;
    273 
    274 
    275          glyph->root.metrics.width  = (FT_Pos)metrics.width  * 64;
    276          glyph->root.metrics.height = (FT_Pos)metrics.height * 64;
    277 
    278          glyph->root.metrics.horiBearingX = (FT_Pos)metrics.horiBearingX * 64;
    279          glyph->root.metrics.horiBearingY = (FT_Pos)metrics.horiBearingY * 64;
    280          glyph->root.metrics.horiAdvance  = (FT_Pos)metrics.horiAdvance  * 64;
    281 
    282          glyph->root.metrics.vertBearingX = (FT_Pos)metrics.vertBearingX * 64;
    283          glyph->root.metrics.vertBearingY = (FT_Pos)metrics.vertBearingY * 64;
    284          glyph->root.metrics.vertAdvance  = (FT_Pos)metrics.vertAdvance  * 64;
    285 
    286          glyph->root.format = FT_GLYPH_FORMAT_BITMAP;
    287 
    288          if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
    289          {
    290            glyph->root.bitmap_left = metrics.vertBearingX;
    291            glyph->root.bitmap_top  = metrics.vertBearingY;
    292          }
    293          else
    294          {
    295            glyph->root.bitmap_left = metrics.horiBearingX;
    296            glyph->root.bitmap_top  = metrics.horiBearingY;
    297          }
    298 
    299          /* compute linear advance widths */
    300 
    301          (void)( (SFNT_Service)face->sfnt )->get_metrics( face, 0,
    302                                                           glyph_index,
    303                                                           &dummy,
    304                                                           &advance );
    305          glyph->root.linearHoriAdvance = advance;
    306 
    307          has_vertical_info = FT_BOOL(
    308                                face->vertical_info                   &&
    309                                face->vertical.number_Of_VMetrics > 0 );
    310 
    311          /* get the vertical metrics from the vmtx table if we have one */
    312          if ( has_vertical_info )
    313          {
    314            (void)( (SFNT_Service)face->sfnt )->get_metrics( face, 1,
    315                                                             glyph_index,
    316                                                             &dummy,
    317                                                             &advance );
    318            glyph->root.linearVertAdvance = advance;
    319          }
    320          else
    321          {
    322            /* make up vertical ones */
    323            if ( face->os2.version != 0xFFFFU )
    324              glyph->root.linearVertAdvance = (FT_Pos)
    325                ( face->os2.sTypoAscender - face->os2.sTypoDescender );
    326            else
    327              glyph->root.linearVertAdvance = (FT_Pos)
    328                ( face->horizontal.Ascender - face->horizontal.Descender );
    329          }
    330 
    331          return error;
    332        }
    333      }
    334    }
    335 
    336 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
    337 
    338    /* return immediately if we only want the embedded bitmaps */
    339    if ( load_flags & FT_LOAD_SBITS_ONLY )
    340      return FT_THROW( Invalid_Argument );
    341 
    342 #ifdef FT_CONFIG_OPTION_SVG
    343    /* check for OT-SVG */
    344    if ( ( load_flags & FT_LOAD_NO_SVG ) == 0 &&
    345         ( load_flags & FT_LOAD_COLOR )       &&
    346         face->svg                            )
    347    {
    348      /*
    349       * We load the SVG document and try to grab the advances from the
    350       * table.  For the bearings we rely on the presetting hook to do that.
    351       */
    352 
    353      SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
    354 
    355 
    356      if ( size && (size->root.metrics.x_ppem < 1 ||
    357                    size->root.metrics.y_ppem < 1 ) )
    358      {
    359        error = FT_THROW( Invalid_Size_Handle );
    360        return error;
    361      }
    362 
    363      FT_TRACE3(( "Trying to load SVG glyph\n" ));
    364 
    365      error = sfnt->load_svg_doc( (FT_GlyphSlot)glyph, glyph_index );
    366      if ( !error )
    367      {
    368        FT_Fixed  x_scale = size->root.metrics.x_scale;
    369        FT_Fixed  y_scale = size->root.metrics.y_scale;
    370 
    371        FT_Short   dummy;
    372        FT_UShort  advanceX;
    373        FT_UShort  advanceY;
    374 
    375 
    376        FT_TRACE3(( "Successfully loaded SVG glyph\n" ));
    377 
    378        glyph->root.format = FT_GLYPH_FORMAT_SVG;
    379 
    380        /*
    381         * If horizontal or vertical advances are not present in the table,
    382         * this is a problem with the font since the standard requires them.
    383         * However, we are graceful and calculate the values by ourselves
    384         * for the vertical case.
    385         */
    386        sfnt->get_metrics( face,
    387                           FALSE,
    388                           glyph_index,
    389                           &dummy,
    390                           &advanceX );
    391        sfnt->get_metrics( face,
    392                           TRUE,
    393                           glyph_index,
    394                           &dummy,
    395                           &advanceY );
    396 
    397        glyph->root.linearHoriAdvance = advanceX;
    398        glyph->root.linearVertAdvance = advanceY;
    399 
    400        glyph->root.metrics.horiAdvance = FT_MulFix( advanceX, x_scale );
    401        glyph->root.metrics.vertAdvance = FT_MulFix( advanceY, y_scale );
    402 
    403        return error;
    404      }
    405 
    406      FT_TRACE3(( "Failed to load SVG glyph\n" ));
    407    }
    408 
    409 #endif /* FT_CONFIG_OPTION_SVG */
    410 
    411    /* top-level code ensures that FT_LOAD_NO_HINTING is set */
    412    /* if FT_LOAD_NO_SCALE is active                         */
    413    hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
    414    scaled  = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE   ) == 0 );
    415 
    416    glyph->hint        = hinting;
    417    glyph->scaled      = scaled;
    418 
    419    if ( scaled )
    420    {
    421      glyph->x_scale = size->root.metrics.x_scale;
    422      glyph->y_scale = size->root.metrics.y_scale;
    423    }
    424    else
    425    {
    426      glyph->x_scale = 0x10000L;
    427      glyph->y_scale = 0x10000L;
    428    }
    429 
    430    /* if we have a CID subfont, use its matrix (which has already */
    431    /* been multiplied with the root matrix)                       */
    432 
    433    /* this scaling is only relevant if the PS hinter isn't active */
    434    if ( cff->num_subfonts )
    435    {
    436      FT_Long  top_upm, sub_upm;
    437      FT_Byte  fd_index = cff_fd_select_get( &cff->fd_select,
    438                                             glyph_index );
    439 
    440 
    441      if ( fd_index >= cff->num_subfonts )
    442        fd_index = (FT_Byte)( cff->num_subfonts - 1 );
    443 
    444      top_upm = (FT_Long)cff->top_font.font_dict.units_per_em;
    445      sub_upm = (FT_Long)cff->subfonts[fd_index]->font_dict.units_per_em;
    446 
    447      font_matrix = cff->subfonts[fd_index]->font_dict.font_matrix;
    448      font_offset = cff->subfonts[fd_index]->font_dict.font_offset;
    449 
    450      if ( top_upm != sub_upm )
    451      {
    452        glyph->x_scale = FT_MulDiv( glyph->x_scale, top_upm, sub_upm );
    453        glyph->y_scale = FT_MulDiv( glyph->y_scale, top_upm, sub_upm );
    454 
    455        force_scaling = TRUE;
    456      }
    457    }
    458    else
    459    {
    460      font_matrix = cff->top_font.font_dict.font_matrix;
    461      font_offset = cff->top_font.font_dict.font_offset;
    462    }
    463 
    464    {
    465 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
    466      PS_Driver  driver = (PS_Driver)FT_FACE_DRIVER( face );
    467 #endif
    468 
    469      FT_Byte*  charstring;
    470      FT_ULong  charstring_len;
    471 
    472 
    473      decoder_funcs->init( &decoder, face, size, glyph, hinting,
    474                           FT_LOAD_TARGET_MODE( load_flags ),
    475                           cff_get_glyph_data,
    476                           cff_free_glyph_data );
    477 
    478      /* this is for pure CFFs */
    479      if ( load_flags & FT_LOAD_ADVANCE_ONLY )
    480        decoder.width_only = TRUE;
    481 
    482      decoder.builder.no_recurse =
    483        FT_BOOL( load_flags & FT_LOAD_NO_RECURSE );
    484 
    485      /* this function also checks for a valid subfont index */
    486      error = decoder_funcs->prepare( &decoder, size, glyph_index );
    487      if ( error )
    488        goto Glyph_Build_Finished;
    489 
    490      /* now load the unscaled outline */
    491      error = cff_get_glyph_data( face, glyph_index,
    492                                  &charstring, &charstring_len );
    493      if ( error )
    494        goto Glyph_Build_Finished;
    495 
    496 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
    497      /* choose which CFF renderer to use */
    498      if ( driver->hinting_engine == FT_HINTING_FREETYPE )
    499        error = decoder_funcs->parse_charstrings_old( &decoder,
    500                                                      charstring,
    501                                                      charstring_len,
    502                                                      0 );
    503      else
    504 #endif
    505      {
    506        psaux->ps_decoder_init( &psdecoder, &decoder, FALSE );
    507 
    508        error = decoder_funcs->parse_charstrings( &psdecoder,
    509                                                  charstring,
    510                                                  charstring_len );
    511 
    512        /* Adobe's engine uses 16.16 numbers everywhere;              */
    513        /* as a consequence, glyphs larger than 2000ppem get rejected */
    514        if ( FT_ERR_EQ( error, Glyph_Too_Big ) )
    515        {
    516          /* this time, we retry unhinted and scale up the glyph later on */
    517          /* (the engine uses and sets the hardcoded value 0x10000 / 64 = */
    518          /* 0x400 for both `x_scale' and `y_scale' in this case)         */
    519          hinting       = FALSE;
    520          force_scaling = TRUE;
    521          glyph->hint   = hinting;
    522 
    523          error = decoder_funcs->parse_charstrings( &psdecoder,
    524                                                    charstring,
    525                                                    charstring_len );
    526        }
    527      }
    528 
    529      cff_free_glyph_data( face, &charstring, charstring_len );
    530 
    531      if ( error )
    532        goto Glyph_Build_Finished;
    533 
    534 #ifdef FT_CONFIG_OPTION_INCREMENTAL
    535      /* Control data and length may not be available for incremental */
    536      /* fonts.                                                       */
    537      if ( face->root.internal->incremental_interface )
    538      {
    539        glyph->root.control_data = NULL;
    540        glyph->root.control_len = 0;
    541      }
    542      else
    543 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
    544 
    545      /* We set control_data and control_len if charstrings is loaded. */
    546      /* See how charstring loads at cff_index_access_element() in     */
    547      /* cffload.c.                                                    */
    548      {
    549        CFF_Index  csindex = &cff->charstrings_index;
    550 
    551 
    552        if ( csindex->offsets )
    553        {
    554          glyph->root.control_data = csindex->bytes +
    555                                     csindex->offsets[glyph_index] - 1;
    556          glyph->root.control_len  = (FT_Long)charstring_len;
    557        }
    558      }
    559 
    560  Glyph_Build_Finished:
    561      /* save new glyph tables, if no error */
    562      if ( !error )
    563        decoder.builder.funcs.done( &decoder.builder );
    564      /* XXX: anything to do for broken glyph entry? */
    565    }
    566 
    567 #ifdef FT_CONFIG_OPTION_INCREMENTAL
    568 
    569    /* Incremental fonts can optionally override the metrics. */
    570    if ( !error                                                               &&
    571         face->root.internal->incremental_interface                           &&
    572         face->root.internal->incremental_interface->funcs->get_glyph_metrics )
    573    {
    574      FT_Incremental_MetricsRec  metrics;
    575 
    576 
    577      metrics.bearing_x = decoder.builder.left_bearing.x;
    578      metrics.bearing_y = 0;
    579      metrics.advance   = decoder.builder.advance.x;
    580      metrics.advance_v = decoder.builder.advance.y;
    581 
    582      error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
    583                face->root.internal->incremental_interface->object,
    584                glyph_index, FALSE, &metrics );
    585 
    586      decoder.builder.left_bearing.x = metrics.bearing_x;
    587      decoder.builder.advance.x      = metrics.advance;
    588      decoder.builder.advance.y      = metrics.advance_v;
    589    }
    590 
    591 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
    592 
    593    if ( !error )
    594    {
    595      /* Now, set the metrics -- this is rather simple, as   */
    596      /* the left side bearing is the xMin, and the top side */
    597      /* bearing the yMax. For composite glyphs, return only */
    598      /* left side bearing and advance width.                */
    599      if ( load_flags & FT_LOAD_NO_RECURSE )
    600      {
    601        FT_Slot_Internal  internal = glyph->root.internal;
    602 
    603 
    604        glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
    605        glyph->root.metrics.horiAdvance  = decoder.glyph_width;
    606        internal->glyph_matrix           = font_matrix;
    607        internal->glyph_delta            = font_offset;
    608        internal->glyph_transformed      = 1;
    609      }
    610      else
    611      {
    612        FT_BBox            cbox;
    613        FT_Glyph_Metrics*  metrics = &glyph->root.metrics;
    614        FT_Bool            has_vertical_info;
    615 
    616 
    617        glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;
    618 
    619        glyph->root.outline.flags = FT_OUTLINE_REVERSE_FILL;
    620        if ( size && size->root.metrics.y_ppem < 24 )
    621          glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION;
    622 
    623        if ( face->horizontal.number_Of_HMetrics )
    624        {
    625          FT_Short   horiBearingX = 0;
    626          FT_UShort  horiAdvance  = 0;
    627 
    628 
    629          ( (SFNT_Service)face->sfnt )->get_metrics( face, 0,
    630                                                     glyph_index,
    631                                                     &horiBearingX,
    632                                                     &horiAdvance );
    633          metrics->horiAdvance          = horiAdvance;
    634          metrics->horiBearingX         = horiBearingX;
    635          glyph->root.linearHoriAdvance = horiAdvance;
    636        }
    637        else
    638        {
    639          /* copy the _unscaled_ advance width */
    640          metrics->horiAdvance          = decoder.glyph_width;
    641          glyph->root.linearHoriAdvance = decoder.glyph_width;
    642        }
    643 
    644        glyph->root.internal->glyph_transformed = 0;
    645 
    646        has_vertical_info = FT_BOOL( face->vertical_info                   &&
    647                                     face->vertical.number_Of_VMetrics > 0 );
    648 
    649        /* get the vertical metrics from the vmtx table if we have one */
    650        if ( has_vertical_info )
    651        {
    652          FT_Short   vertBearingY = 0;
    653          FT_UShort  vertAdvance  = 0;
    654 
    655 
    656          ( (SFNT_Service)face->sfnt )->get_metrics( face, 1,
    657                                                     glyph_index,
    658                                                     &vertBearingY,
    659                                                     &vertAdvance );
    660          metrics->vertBearingY = vertBearingY;
    661          metrics->vertAdvance  = vertAdvance;
    662        }
    663        else
    664        {
    665          /* make up vertical ones */
    666          if ( face->os2.version != 0xFFFFU )
    667            metrics->vertAdvance = (FT_Pos)( face->os2.sTypoAscender -
    668                                             face->os2.sTypoDescender );
    669          else
    670            metrics->vertAdvance = (FT_Pos)( face->horizontal.Ascender -
    671                                             face->horizontal.Descender );
    672        }
    673 
    674        glyph->root.linearVertAdvance = metrics->vertAdvance;
    675 
    676        /* apply the font matrix, if any */
    677        if ( font_matrix.xx != 0x10000L || font_matrix.yy != 0x10000L ||
    678             font_matrix.xy != 0        || font_matrix.yx != 0        )
    679        {
    680          FT_Outline_Transform( &glyph->root.outline, &font_matrix );
    681 
    682          metrics->horiAdvance = FT_MulFix( metrics->horiAdvance,
    683                                            font_matrix.xx );
    684          metrics->vertAdvance = FT_MulFix( metrics->vertAdvance,
    685                                            font_matrix.yy );
    686        }
    687 
    688        if ( font_offset.x || font_offset.y )
    689        {
    690          FT_Outline_Translate( &glyph->root.outline,
    691                                font_offset.x,
    692                                font_offset.y );
    693 
    694          metrics->horiAdvance += font_offset.x;
    695          metrics->vertAdvance += font_offset.y;
    696        }
    697 
    698        if ( scaled || force_scaling )
    699        {
    700          /* scale the outline and the metrics */
    701          FT_Int       n;
    702          FT_Outline*  cur     = &glyph->root.outline;
    703          FT_Vector*   vec     = cur->points;
    704          FT_Fixed     x_scale = glyph->x_scale;
    705          FT_Fixed     y_scale = glyph->y_scale;
    706 
    707 
    708          /* First of all, scale the points */
    709          if ( !hinting || !decoder.builder.hints_funcs )
    710            for ( n = cur->n_points; n > 0; n--, vec++ )
    711            {
    712              vec->x = FT_MulFix( vec->x, x_scale );
    713              vec->y = FT_MulFix( vec->y, y_scale );
    714            }
    715 
    716          /* Then scale the metrics */
    717          metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
    718          metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
    719        }
    720 
    721        /* compute the other metrics */
    722        FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
    723 
    724        metrics->width  = cbox.xMax - cbox.xMin;
    725        metrics->height = cbox.yMax - cbox.yMin;
    726 
    727        metrics->horiBearingX = cbox.xMin;
    728        metrics->horiBearingY = cbox.yMax;
    729 
    730        if ( has_vertical_info )
    731        {
    732          metrics->vertBearingX = metrics->horiBearingX -
    733                                    metrics->horiAdvance / 2;
    734          metrics->vertBearingY = FT_MulFix( metrics->vertBearingY,
    735                                             glyph->y_scale );
    736        }
    737        else
    738        {
    739          if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
    740            ft_synthesize_vertical_metrics( metrics,
    741                                            metrics->vertAdvance );
    742        }
    743      }
    744    }
    745 
    746    return error;
    747  }
    748 
    749 
    750 /* END */