tor-browser

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

pfrsbit.c (21398B)


      1 /****************************************************************************
      2 *
      3 * pfrsbit.c
      4 *
      5 *   FreeType PFR bitmap 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 "pfrsbit.h"
     20 #include "pfrload.h"
     21 #include <freetype/internal/ftdebug.h>
     22 #include <freetype/internal/ftstream.h>
     23 
     24 #include "pfrerror.h"
     25 
     26 #undef  FT_COMPONENT
     27 #define FT_COMPONENT  pfr
     28 
     29 
     30  /*************************************************************************/
     31  /*************************************************************************/
     32  /*****                                                               *****/
     33  /*****                      PFR BIT WRITER                           *****/
     34  /*****                                                               *****/
     35  /*************************************************************************/
     36  /*************************************************************************/
     37 
     38  typedef struct  PFR_BitWriter_
     39  {
     40    FT_Byte*  line;      /* current line start               */
     41    FT_Int    pitch;     /* line size in bytes               */
     42    FT_UInt   width;     /* width in pixels/bits             */
     43    FT_UInt   rows;      /* number of remaining rows to scan */
     44    FT_UInt   total;     /* total number of bits to draw     */
     45 
     46  } PFR_BitWriterRec, *PFR_BitWriter;
     47 
     48 
     49  static void
     50  pfr_bitwriter_init( PFR_BitWriter  writer,
     51                      FT_Bitmap*     target,
     52                      FT_Bool        decreasing )
     53  {
     54    writer->line   = target->buffer;
     55    writer->pitch  = target->pitch;
     56    writer->width  = target->width;
     57    writer->rows   = target->rows;
     58    writer->total  = writer->width * writer->rows;
     59 
     60    if ( !decreasing )
     61    {
     62      writer->line += writer->pitch * (FT_Int)( target->rows - 1 );
     63      writer->pitch = -writer->pitch;
     64    }
     65  }
     66 
     67 
     68  static void
     69  pfr_bitwriter_decode_bytes( PFR_BitWriter  writer,
     70                              FT_Byte*       p,
     71                              FT_Byte*       limit )
     72  {
     73    FT_UInt   n, reload;
     74    FT_UInt   left = writer->width;
     75    FT_Byte*  cur  = writer->line;
     76    FT_UInt   mask = 0x80;
     77    FT_UInt   val  = 0;
     78    FT_UInt   c    = 0;
     79 
     80 
     81    n = (FT_UInt)( limit - p ) * 8;
     82    if ( n > writer->total )
     83      n = writer->total;
     84 
     85    reload = n & 7;
     86 
     87    for ( ; n > 0; n-- )
     88    {
     89      if ( ( n & 7 ) == reload )
     90        val = *p++;
     91 
     92      if ( val & 0x80 )
     93        c |= mask;
     94 
     95      val  <<= 1;
     96      mask >>= 1;
     97 
     98      if ( --left <= 0 )
     99      {
    100        cur[0] = (FT_Byte)c;
    101        left   = writer->width;
    102        mask   = 0x80;
    103 
    104        writer->line += writer->pitch;
    105        cur           = writer->line;
    106        c             = 0;
    107      }
    108      else if ( mask == 0 )
    109      {
    110        cur[0] = (FT_Byte)c;
    111        mask   = 0x80;
    112        c      = 0;
    113        cur++;
    114      }
    115    }
    116 
    117    if ( mask != 0x80 )
    118      cur[0] = (FT_Byte)c;
    119  }
    120 
    121 
    122  static void
    123  pfr_bitwriter_decode_rle1( PFR_BitWriter  writer,
    124                             FT_Byte*       p,
    125                             FT_Byte*       limit )
    126  {
    127    FT_Int    phase, count, counts[2];
    128    FT_UInt   n, reload;
    129    FT_UInt   left = writer->width;
    130    FT_Byte*  cur  = writer->line;
    131    FT_UInt   mask = 0x80;
    132    FT_UInt   c    = 0;
    133 
    134 
    135    n = writer->total;
    136 
    137    phase     = 1;
    138    counts[0] = 0;
    139    counts[1] = 0;
    140    count     = 0;
    141    reload    = 1;
    142 
    143    for ( ; n > 0; n-- )
    144    {
    145      if ( reload )
    146      {
    147        do
    148        {
    149          if ( phase )
    150          {
    151            FT_Int  v;
    152 
    153 
    154            if ( p >= limit )
    155              break;
    156 
    157            v         = *p++;
    158            counts[0] = v >> 4;
    159            counts[1] = v & 15;
    160            phase     = 0;
    161            count     = counts[0];
    162          }
    163          else
    164          {
    165            phase = 1;
    166            count = counts[1];
    167          }
    168 
    169        } while ( count == 0 );
    170      }
    171 
    172      if ( phase )
    173        c |= mask;
    174 
    175      mask >>= 1;
    176 
    177      if ( --left <= 0 )
    178      {
    179        cur[0] = (FT_Byte)c;
    180        left   = writer->width;
    181        mask   = 0x80;
    182 
    183        writer->line += writer->pitch;
    184        cur           = writer->line;
    185        c             = 0;
    186      }
    187      else if ( mask == 0 )
    188      {
    189        cur[0] = (FT_Byte)c;
    190        mask   = 0x80;
    191        c      = 0;
    192        cur++;
    193      }
    194 
    195      reload = ( --count <= 0 );
    196    }
    197 
    198    if ( mask != 0x80 )
    199      cur[0] = (FT_Byte) c;
    200  }
    201 
    202 
    203  static void
    204  pfr_bitwriter_decode_rle2( PFR_BitWriter  writer,
    205                             FT_Byte*       p,
    206                             FT_Byte*       limit )
    207  {
    208    FT_Int    phase, count;
    209    FT_UInt   n, reload;
    210    FT_UInt   left = writer->width;
    211    FT_Byte*  cur  = writer->line;
    212    FT_UInt   mask = 0x80;
    213    FT_UInt   c    = 0;
    214 
    215 
    216    n = writer->total;
    217 
    218    phase  = 1;
    219    count  = 0;
    220    reload = 1;
    221 
    222    for ( ; n > 0; n-- )
    223    {
    224      if ( reload )
    225      {
    226        do
    227        {
    228          if ( p >= limit )
    229            break;
    230 
    231          count = *p++;
    232          phase = phase ^ 1;
    233 
    234        } while ( count == 0 );
    235      }
    236 
    237      if ( phase )
    238        c |= mask;
    239 
    240      mask >>= 1;
    241 
    242      if ( --left <= 0 )
    243      {
    244        cur[0] = (FT_Byte)c;
    245        c      = 0;
    246        mask   = 0x80;
    247        left   = writer->width;
    248 
    249        writer->line += writer->pitch;
    250        cur           = writer->line;
    251      }
    252      else if ( mask == 0 )
    253      {
    254        cur[0] = (FT_Byte)c;
    255        c      = 0;
    256        mask   = 0x80;
    257        cur++;
    258      }
    259 
    260      reload = ( --count <= 0 );
    261    }
    262 
    263    if ( mask != 0x80 )
    264      cur[0] = (FT_Byte) c;
    265  }
    266 
    267 
    268  /*************************************************************************/
    269  /*************************************************************************/
    270  /*****                                                               *****/
    271  /*****                  BITMAP DATA DECODING                         *****/
    272  /*****                                                               *****/
    273  /*************************************************************************/
    274  /*************************************************************************/
    275 
    276  static void
    277  pfr_lookup_bitmap_data( FT_Byte*   base,
    278                          FT_Byte*   limit,
    279                          FT_UInt    count,
    280                          FT_UInt*   flags,
    281                          FT_UInt    char_code,
    282                          FT_ULong*  found_offset,
    283                          FT_ULong*  found_size )
    284  {
    285    FT_UInt   min, max, mid, char_len;
    286    FT_Bool   two = FT_BOOL( *flags & PFR_BITMAP_2BYTE_CHARCODE );
    287    FT_Byte*  buff;
    288 
    289 
    290    char_len = 4;
    291    if ( two )
    292      char_len += 1;
    293    if ( *flags & PFR_BITMAP_2BYTE_SIZE )
    294      char_len += 1;
    295    if ( *flags & PFR_BITMAP_3BYTE_OFFSET )
    296      char_len += 1;
    297 
    298    if ( !( *flags & PFR_BITMAP_CHARCODES_VALIDATED ) )
    299    {
    300      FT_Byte*  p;
    301      FT_Byte*  lim;
    302      FT_UInt   code;
    303      FT_Long   prev_code;
    304 
    305 
    306      *flags    |= PFR_BITMAP_VALID_CHARCODES;
    307      prev_code  = -1;
    308      lim        = base + count * char_len;
    309 
    310      if ( lim > limit )
    311      {
    312        FT_TRACE0(( "pfr_lookup_bitmap_data:"
    313                    " number of bitmap records too large,\n" ));
    314        FT_TRACE0(( "                       "
    315                    " thus ignoring all bitmaps in this strike\n" ));
    316        *flags &= ~PFR_BITMAP_VALID_CHARCODES;
    317      }
    318      else
    319      {
    320        /* check whether records are sorted by code */
    321        for ( p = base; p < lim; p += char_len )
    322        {
    323          if ( two )
    324            code = FT_PEEK_USHORT( p );
    325          else
    326            code = *p;
    327 
    328          if ( (FT_Long)code <= prev_code )
    329          {
    330            FT_TRACE0(( "pfr_lookup_bitmap_data:"
    331                        " bitmap records are not sorted,\n" ));
    332            FT_TRACE0(( "                       "
    333                        " thus ignoring all bitmaps in this strike\n" ));
    334            *flags &= ~PFR_BITMAP_VALID_CHARCODES;
    335            break;
    336          }
    337 
    338          prev_code = code;
    339        }
    340      }
    341 
    342      *flags |= PFR_BITMAP_CHARCODES_VALIDATED;
    343    }
    344 
    345    /* ignore bitmaps in case table is not valid     */
    346    /* (this might be sanitized, but PFR is dead...) */
    347    if ( !( *flags & PFR_BITMAP_VALID_CHARCODES ) )
    348      goto Fail;
    349 
    350    min = 0;
    351    max = count;
    352    mid = min + ( max - min ) / 2;
    353 
    354    /* binary search */
    355    while ( min < max )
    356    {
    357      FT_UInt  code;
    358 
    359 
    360      buff = base + mid * char_len;
    361 
    362      if ( two )
    363        code = PFR_NEXT_USHORT( buff );
    364      else
    365        code = PFR_NEXT_BYTE( buff );
    366 
    367      if ( char_code < code )
    368        max = mid;
    369      else if ( char_code > code )
    370        min = mid + 1;
    371      else
    372        goto Found_It;
    373 
    374      /* reasonable prediction in a continuous block */
    375      mid += char_code - code;
    376      if ( mid >= max || mid < min )
    377        mid = min + ( max - min ) / 2;
    378    }
    379 
    380  Fail:
    381    /* Not found */
    382    *found_size   = 0;
    383    *found_offset = 0;
    384    return;
    385 
    386  Found_It:
    387    if ( *flags & PFR_BITMAP_2BYTE_SIZE )
    388      *found_size = PFR_NEXT_USHORT( buff );
    389    else
    390      *found_size = PFR_NEXT_BYTE( buff );
    391 
    392    if ( *flags & PFR_BITMAP_3BYTE_OFFSET )
    393      *found_offset = PFR_NEXT_ULONG( buff );
    394    else
    395      *found_offset = PFR_NEXT_USHORT( buff );
    396  }
    397 
    398 
    399  /* load bitmap metrics.  `*aadvance' must be set to the default value */
    400  /* before calling this function                                       */
    401  /*                                                                    */
    402  static FT_Error
    403  pfr_load_bitmap_metrics( FT_Byte**  pdata,
    404                           FT_Byte*   limit,
    405                           FT_Long    scaled_advance,
    406                           FT_Long   *axpos,
    407                           FT_Long   *aypos,
    408                           FT_UInt   *axsize,
    409                           FT_UInt   *aysize,
    410                           FT_Long   *aadvance,
    411                           FT_UInt   *aformat )
    412  {
    413    FT_Error  error = FT_Err_Ok;
    414    FT_Byte   flags;
    415    FT_Byte   b;
    416    FT_Byte*  p = *pdata;
    417    FT_Long   xpos, ypos, advance;
    418    FT_UInt   xsize, ysize;
    419 
    420 
    421    PFR_CHECK( 1 );
    422    flags = PFR_NEXT_BYTE( p );
    423 
    424    xpos    = 0;
    425    ypos    = 0;
    426    xsize   = 0;
    427    ysize   = 0;
    428    advance = 0;
    429 
    430    switch ( flags & 3 )
    431    {
    432    case 0:
    433      PFR_CHECK( 1 );
    434      b    = PFR_NEXT_BYTE( p );
    435      xpos = (FT_Char)b >> 4;
    436      ypos = ( (FT_Char)( b << 4 ) ) >> 4;
    437      break;
    438 
    439    case 1:
    440      PFR_CHECK( 2 );
    441      xpos = PFR_NEXT_INT8( p );
    442      ypos = PFR_NEXT_INT8( p );
    443      break;
    444 
    445    case 2:
    446      PFR_CHECK( 4 );
    447      xpos = PFR_NEXT_SHORT( p );
    448      ypos = PFR_NEXT_SHORT( p );
    449      break;
    450 
    451    case 3:
    452      PFR_CHECK( 6 );
    453      xpos = PFR_NEXT_LONG( p );
    454      ypos = PFR_NEXT_LONG( p );
    455      break;
    456 
    457    default:
    458      ;
    459    }
    460 
    461    flags >>= 2;
    462    switch ( flags & 3 )
    463    {
    464    case 0:
    465      /* blank image */
    466      xsize = 0;
    467      ysize = 0;
    468      break;
    469 
    470    case 1:
    471      PFR_CHECK( 1 );
    472      b     = PFR_NEXT_BYTE( p );
    473      xsize = ( b >> 4 ) & 0xF;
    474      ysize = b & 0xF;
    475      break;
    476 
    477    case 2:
    478      PFR_CHECK( 2 );
    479      xsize = PFR_NEXT_BYTE( p );
    480      ysize = PFR_NEXT_BYTE( p );
    481      break;
    482 
    483    case 3:
    484      PFR_CHECK( 4 );
    485      xsize = PFR_NEXT_USHORT( p );
    486      ysize = PFR_NEXT_USHORT( p );
    487      break;
    488 
    489    default:
    490      ;
    491    }
    492 
    493    flags >>= 2;
    494    switch ( flags & 3 )
    495    {
    496    case 0:
    497      advance = scaled_advance;
    498      break;
    499 
    500    case 1:
    501      PFR_CHECK( 1 );
    502      advance = PFR_NEXT_INT8( p ) * 256;
    503      break;
    504 
    505    case 2:
    506      PFR_CHECK( 2 );
    507      advance = PFR_NEXT_SHORT( p );
    508      break;
    509 
    510    case 3:
    511      PFR_CHECK( 3 );
    512      advance = PFR_NEXT_LONG( p );
    513      break;
    514 
    515    default:
    516      ;
    517    }
    518 
    519    *axpos    = xpos;
    520    *aypos    = ypos;
    521    *axsize   = xsize;
    522    *aysize   = ysize;
    523    *aadvance = advance;
    524    *aformat  = flags >> 2;
    525    *pdata    = p;
    526 
    527  Exit:
    528    return error;
    529 
    530  Too_Short:
    531    error = FT_THROW( Invalid_Table );
    532    FT_ERROR(( "pfr_load_bitmap_metrics: invalid glyph data\n" ));
    533    goto Exit;
    534  }
    535 
    536 
    537  static FT_Error
    538  pfr_load_bitmap_bits( FT_Byte*    p,
    539                        FT_Byte*    limit,
    540                        FT_UInt     format,
    541                        FT_Bool     decreasing,
    542                        FT_Bitmap*  target )
    543  {
    544    FT_Error          error = FT_Err_Ok;
    545    PFR_BitWriterRec  writer;
    546 
    547 
    548    if ( target->rows > 0 && target->width > 0 )
    549    {
    550      pfr_bitwriter_init( &writer, target, decreasing );
    551 
    552      switch ( format )
    553      {
    554      case 0: /* packed bits */
    555        pfr_bitwriter_decode_bytes( &writer, p, limit );
    556        break;
    557 
    558      case 1: /* RLE1 */
    559        pfr_bitwriter_decode_rle1( &writer, p, limit );
    560        break;
    561 
    562      case 2: /* RLE2 */
    563        pfr_bitwriter_decode_rle2( &writer, p, limit );
    564        break;
    565 
    566      default:
    567        ;
    568      }
    569    }
    570 
    571    return error;
    572  }
    573 
    574 
    575  /*************************************************************************/
    576  /*************************************************************************/
    577  /*****                                                               *****/
    578  /*****                     BITMAP LOADING                            *****/
    579  /*****                                                               *****/
    580  /*************************************************************************/
    581  /*************************************************************************/
    582 
    583  FT_LOCAL_DEF( FT_Error )
    584  pfr_slot_load_bitmap( PFR_Slot  glyph,
    585                        PFR_Size  size,
    586                        FT_UInt   glyph_index,
    587                        FT_Bool   metrics_only )
    588  {
    589    FT_Error     error;
    590    PFR_Face     face   = (PFR_Face) glyph->root.face;
    591    FT_Stream    stream = face->root.stream;
    592    PFR_PhyFont  phys   = &face->phy_font;
    593    FT_ULong     gps_offset;
    594    FT_ULong     gps_size;
    595    PFR_Char     character;
    596    PFR_Strike   strike;
    597 
    598 
    599    character = &phys->chars[glyph_index];
    600 
    601    /* look up a bitmap strike corresponding to the current */
    602    /* character dimensions                                 */
    603    {
    604      FT_UInt  n;
    605 
    606 
    607      strike = phys->strikes;
    608      for ( n = 0; n < phys->num_strikes; n++ )
    609      {
    610        if ( strike->x_ppm == (FT_UInt)size->root.metrics.x_ppem &&
    611             strike->y_ppm == (FT_UInt)size->root.metrics.y_ppem )
    612          goto Found_Strike;
    613 
    614        strike++;
    615      }
    616 
    617      /* couldn't find it */
    618      return FT_THROW( Invalid_Argument );
    619    }
    620 
    621  Found_Strike:
    622 
    623    /* now look up the glyph's position within the file */
    624    {
    625      FT_UInt  char_len;
    626 
    627 
    628      char_len = 4;
    629      if ( strike->flags & PFR_BITMAP_2BYTE_CHARCODE )
    630        char_len += 1;
    631      if ( strike->flags & PFR_BITMAP_2BYTE_SIZE )
    632        char_len += 1;
    633      if ( strike->flags & PFR_BITMAP_3BYTE_OFFSET )
    634        char_len += 1;
    635 
    636      /* access data directly in the frame to speed up lookups */
    637      if ( FT_STREAM_SEEK( phys->bct_offset + strike->bct_offset ) ||
    638           FT_FRAME_ENTER( char_len * strike->num_bitmaps )        )
    639        goto Exit;
    640 
    641      pfr_lookup_bitmap_data( stream->cursor,
    642                              stream->limit,
    643                              strike->num_bitmaps,
    644                              &strike->flags,
    645                              character->char_code,
    646                              &gps_offset,
    647                              &gps_size );
    648 
    649      FT_FRAME_EXIT();
    650 
    651      if ( gps_size == 0 )
    652      {
    653        /* could not find a bitmap program string for this glyph */
    654        error = FT_THROW( Invalid_Argument );
    655        goto Exit;
    656      }
    657    }
    658 
    659    /* get the bitmap metrics */
    660    {
    661      FT_Long   xpos = 0, ypos = 0, advance = 0;
    662      FT_UInt   xsize = 0, ysize = 0, format = 0;
    663      FT_Byte*  p;
    664 
    665 
    666      /* compute linear advance */
    667      advance = character->advance;
    668      if ( phys->metrics_resolution != phys->outline_resolution )
    669        advance = FT_MulDiv( advance,
    670                             (FT_Long)phys->outline_resolution,
    671                             (FT_Long)phys->metrics_resolution );
    672 
    673      glyph->root.linearHoriAdvance = advance;
    674 
    675      /* compute default advance, i.e., scaled advance; this can be */
    676      /* overridden in the bitmap header of certain glyphs          */
    677      advance = FT_MulDiv( (FT_Fixed)size->root.metrics.x_ppem << 8,
    678                           character->advance,
    679                           (FT_Long)phys->metrics_resolution );
    680 
    681      if ( FT_STREAM_SEEK( face->header.gps_section_offset + gps_offset ) ||
    682           FT_FRAME_ENTER( gps_size )                                     )
    683        goto Exit;
    684 
    685      p     = stream->cursor;
    686      error = pfr_load_bitmap_metrics( &p, stream->limit,
    687                                       advance,
    688                                       &xpos, &ypos,
    689                                       &xsize, &ysize,
    690                                       &advance, &format );
    691      if ( error )
    692        goto Exit1;
    693 
    694      /*
    695       * Before allocating the target bitmap, we check whether the given
    696       * bitmap dimensions are valid, depending on the image format.
    697       *
    698       * Format 0: We have a stream of pixels (with 8 pixels per byte).
    699       *
    700       *             (xsize * ysize + 7) / 8 <= gps_size
    701       *
    702       * Format 1: Run-length encoding; the high nibble holds the number of
    703       *           white bits, the low nibble the number of black bits.  In
    704       *           other words, a single byte can represent at most 15
    705       *           pixels.
    706       *
    707       *             xsize * ysize <= 15 * gps_size
    708       *
    709       * Format 2: Run-length encoding; the high byte holds the number of
    710       *           white bits, the low byte the number of black bits.  In
    711       *           other words, two bytes can represent at most 255 pixels.
    712       *
    713       *             xsize * ysize <= 255 * (gps_size + 1) / 2
    714       */
    715      switch ( format )
    716      {
    717      case 0:
    718        if ( ( (FT_ULong)xsize * ysize + 7 ) / 8 > gps_size )
    719          error = FT_THROW( Invalid_Table );
    720        break;
    721      case 1:
    722        if ( (FT_ULong)xsize * ysize > 15 * gps_size )
    723          error = FT_THROW( Invalid_Table );
    724        break;
    725      case 2:
    726        if ( (FT_ULong)xsize * ysize > 255 * ( ( gps_size + 1 ) / 2 ) )
    727          error = FT_THROW( Invalid_Table );
    728        break;
    729      default:
    730        FT_ERROR(( "pfr_slot_load_bitmap: invalid image type\n" ));
    731        error = FT_THROW( Invalid_Table );
    732      }
    733 
    734      if ( error )
    735      {
    736        if ( FT_ERR_EQ( error, Invalid_Table ) )
    737          FT_ERROR(( "pfr_slot_load_bitmap: invalid bitmap dimensions\n" ));
    738        goto Exit1;
    739      }
    740 
    741      /*
    742       * XXX: on 16bit systems we return an error for huge bitmaps
    743       *      that cause size truncation, because truncated
    744       *      size properties make bitmap glyphs broken.
    745       */
    746      if ( xpos > FT_INT_MAX                  ||
    747           xpos < FT_INT_MIN                  ||
    748           ysize > FT_INT_MAX                 ||
    749           ypos > FT_INT_MAX - (FT_Long)ysize ||
    750           ypos + (FT_Long)ysize < FT_INT_MIN )
    751      {
    752        FT_TRACE1(( "pfr_slot_load_bitmap:"
    753                    " huge bitmap glyph %ldx%ld over FT_GlyphSlot\n",
    754                     xpos, ypos ));
    755        error = FT_THROW( Invalid_Pixel_Size );
    756      }
    757 
    758      if ( !error )
    759      {
    760        glyph->root.format = FT_GLYPH_FORMAT_BITMAP;
    761 
    762        /* Set up glyph bitmap and metrics */
    763 
    764        /* XXX: needs casts to fit FT_Bitmap.{width|rows|pitch} */
    765        glyph->root.bitmap.width      = xsize;
    766        glyph->root.bitmap.rows       = ysize;
    767        glyph->root.bitmap.pitch      = (FT_Int)( xsize + 7 ) >> 3;
    768        glyph->root.bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
    769 
    770        /* XXX: needs casts to fit FT_Glyph_Metrics.{width|height} */
    771        glyph->root.metrics.width        = (FT_Pos)xsize << 6;
    772        glyph->root.metrics.height       = (FT_Pos)ysize << 6;
    773        glyph->root.metrics.horiBearingX = xpos * 64;
    774        glyph->root.metrics.horiBearingY = ypos * 64;
    775        glyph->root.metrics.horiAdvance  = FT_PIX_ROUND( ( advance >> 2 ) );
    776        glyph->root.metrics.vertBearingX = - glyph->root.metrics.width >> 1;
    777        glyph->root.metrics.vertBearingY = 0;
    778        glyph->root.metrics.vertAdvance  = size->root.metrics.height;
    779 
    780        /* XXX: needs casts fit FT_GlyphSlotRec.bitmap_{left|top} */
    781        glyph->root.bitmap_left = (FT_Int)xpos;
    782        glyph->root.bitmap_top  = (FT_Int)( ypos + (FT_Long)ysize );
    783 
    784        if ( metrics_only )
    785          goto Exit1;
    786 
    787        /* Allocate and read bitmap data */
    788        {
    789          FT_ULong  len = (FT_ULong)glyph->root.bitmap.pitch * ysize;
    790 
    791 
    792          error = ft_glyphslot_alloc_bitmap( &glyph->root, len );
    793          if ( !error )
    794            error = pfr_load_bitmap_bits(
    795                      p,
    796                      stream->limit,
    797                      format,
    798                      FT_BOOL( face->header.color_flags &
    799                               PFR_FLAG_INVERT_BITMAP   ),
    800                      &glyph->root.bitmap );
    801        }
    802      }
    803 
    804    Exit1:
    805      FT_FRAME_EXIT();
    806    }
    807 
    808  Exit:
    809    return error;
    810  }
    811 
    812 
    813 /* END */