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