Home | History | Annotate | Download | only in sfnt
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  ttsbit.c                                                               */
      4 /*                                                                         */
      5 /*    TrueType and OpenType embedded bitmap support (body).                */
      6 /*                                                                         */
      7 /*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
      8 /*            2010 by                                                      */
      9 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
     10 /*                                                                         */
     11 /*  This file is part of the FreeType project, and may only be used,       */
     12 /*  modified, and distributed under the terms of the FreeType project      */
     13 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
     14 /*  this file you indicate that you have read the license and              */
     15 /*  understand and accept it fully.                                        */
     16 /*                                                                         */
     17 /***************************************************************************/
     18 
     19 #include <ft2build.h>
     20 #include FT_INTERNAL_DEBUG_H
     21 #include FT_INTERNAL_STREAM_H
     22 #include FT_TRUETYPE_TAGS_H
     23 
     24   /*
     25    *  Alas, the memory-optimized sbit loader can't be used when implementing
     26    *  the `old internals' hack
     27    */
     28 #ifndef FT_CONFIG_OPTION_OLD_INTERNALS
     29 
     30 #include "ttsbit0.c"
     31 
     32 #else /* FT_CONFIG_OPTION_OLD_INTERNALS */
     33 
     34 #include <ft2build.h>
     35 #include FT_INTERNAL_DEBUG_H
     36 #include FT_INTERNAL_STREAM_H
     37 #include FT_TRUETYPE_TAGS_H
     38 #include "ttsbit.h"
     39 
     40 #include "sferrors.h"
     41 
     42 
     43   /*************************************************************************/
     44   /*                                                                       */
     45   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
     46   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
     47   /* messages during execution.                                            */
     48   /*                                                                       */
     49 #undef  FT_COMPONENT
     50 #define FT_COMPONENT  trace_ttsbit
     51 
     52 
     53   /*************************************************************************/
     54   /*                                                                       */
     55   /* <Function>                                                            */
     56   /*    blit_sbit                                                          */
     57   /*                                                                       */
     58   /* <Description>                                                         */
     59   /*    Blits a bitmap from an input stream into a given target.  Supports */
     60   /*    x and y offsets as well as byte padded lines.                      */
     61   /*                                                                       */
     62   /* <Input>                                                               */
     63   /*    target      :: The target bitmap/pixmap.                           */
     64   /*                                                                       */
     65   /*    source      :: The input packed bitmap data.                       */
     66   /*                                                                       */
     67   /*    line_bits   :: The number of bits per line.                        */
     68   /*                                                                       */
     69   /*    byte_padded :: A flag which is true if lines are byte-padded.      */
     70   /*                                                                       */
     71   /*    x_offset    :: The horizontal offset.                              */
     72   /*                                                                       */
     73   /*    y_offset    :: The vertical offset.                                */
     74   /*                                                                       */
     75   /* <Note>                                                                */
     76   /*    IMPORTANT: The x and y offsets are relative to the top corner of   */
     77   /*               the target bitmap (unlike the normal TrueType           */
     78   /*               convention).  A positive y offset indicates a downwards */
     79   /*               direction!                                              */
     80   /*                                                                       */
     81   static void
     82   blit_sbit( FT_Bitmap*  target,
     83              FT_Byte*    source,
     84              FT_Int      line_bits,
     85              FT_Bool     byte_padded,
     86              FT_Int      x_offset,
     87              FT_Int      y_offset,
     88              FT_Int      source_height )
     89   {
     90     FT_Byte*   line_buff;
     91     FT_Int     line_incr;
     92     FT_Int     height;
     93 
     94     FT_UShort  acc;
     95     FT_UInt    loaded;
     96 
     97 
     98     /* first of all, compute starting write position */
     99     line_incr = target->pitch;
    100     line_buff = target->buffer;
    101 
    102     if ( line_incr < 0 )
    103       line_buff -= line_incr * ( target->rows - 1 );
    104 
    105     line_buff += ( x_offset >> 3 ) + y_offset * line_incr;
    106 
    107     /***********************************************************************/
    108     /*                                                                     */
    109     /* We use the extra-classic `accumulator' trick to extract the bits    */
    110     /* from the source byte stream.                                        */
    111     /*                                                                     */
    112     /* Namely, the variable `acc' is a 16-bit accumulator containing the   */
    113     /* last `loaded' bits from the input stream.  The bits are shifted to  */
    114     /* the upmost position in `acc'.                                       */
    115     /*                                                                     */
    116     /***********************************************************************/
    117 
    118     acc    = 0;  /* clear accumulator   */
    119     loaded = 0;  /* no bits were loaded */
    120 
    121     for ( height = source_height; height > 0; height-- )
    122     {
    123       FT_Byte*  cur   = line_buff;        /* current write cursor          */
    124       FT_Int    count = line_bits;        /* # of bits to extract per line */
    125       FT_Byte   shift = (FT_Byte)( x_offset & 7 ); /* current write shift  */
    126       FT_Byte   space = (FT_Byte)( 8 - shift );
    127 
    128 
    129       /* first of all, read individual source bytes */
    130       if ( count >= 8 )
    131       {
    132         count -= 8;
    133         {
    134           do
    135           {
    136             FT_Byte  val;
    137 
    138 
    139             /* ensure that there are at least 8 bits in the accumulator */
    140             if ( loaded < 8 )
    141             {
    142               acc    |= (FT_UShort)((FT_UShort)*source++ << ( 8 - loaded ));
    143               loaded += 8;
    144             }
    145 
    146             /* now write one byte */
    147             val = (FT_Byte)( acc >> 8 );
    148             if ( shift )
    149             {
    150               cur[0] |= (FT_Byte)( val >> shift );
    151               cur[1] |= (FT_Byte)( val << space );
    152             }
    153             else
    154               cur[0] |= val;
    155 
    156             cur++;
    157             acc   <<= 8;  /* remove bits from accumulator */
    158             loaded -= 8;
    159             count  -= 8;
    160 
    161           } while ( count >= 0 );
    162         }
    163 
    164         /* restore `count' to correct value */
    165         count += 8;
    166       }
    167 
    168       /* now write remaining bits (count < 8) */
    169       if ( count > 0 )
    170       {
    171         FT_Byte  val;
    172 
    173 
    174         /* ensure that there are at least `count' bits in the accumulator */
    175         if ( (FT_Int)loaded < count )
    176         {
    177           acc    |= (FT_UShort)((FT_UShort)*source++ << ( 8 - loaded ));
    178           loaded += 8;
    179         }
    180 
    181         /* now write remaining bits */
    182         val     = (FT_Byte)( ( (FT_Byte)( acc >> 8 ) ) & ~( 0xFF >> count ) );
    183         cur[0] |= (FT_Byte)( val >> shift );
    184 
    185         if ( count > space )
    186           cur[1] |= (FT_Byte)( val << space );
    187 
    188         acc   <<= count;
    189         loaded -= count;
    190       }
    191 
    192       /* now, skip to next line */
    193       if ( byte_padded )
    194       {
    195         acc    = 0;
    196         loaded = 0;   /* clear accumulator on byte-padded lines */
    197       }
    198 
    199       line_buff += line_incr;
    200     }
    201   }
    202 
    203 
    204   static const FT_Frame_Field  sbit_metrics_fields[] =
    205   {
    206 #undef  FT_STRUCTURE
    207 #define FT_STRUCTURE  TT_SBit_MetricsRec
    208 
    209     FT_FRAME_START( 8 ),
    210       FT_FRAME_BYTE( height ),
    211       FT_FRAME_BYTE( width ),
    212 
    213       FT_FRAME_CHAR( horiBearingX ),
    214       FT_FRAME_CHAR( horiBearingY ),
    215       FT_FRAME_BYTE( horiAdvance ),
    216 
    217       FT_FRAME_CHAR( vertBearingX ),
    218       FT_FRAME_CHAR( vertBearingY ),
    219       FT_FRAME_BYTE( vertAdvance ),
    220     FT_FRAME_END
    221   };
    222 
    223 
    224   /*************************************************************************/
    225   /*                                                                       */
    226   /* <Function>                                                            */
    227   /*    Load_SBit_Const_Metrics                                            */
    228   /*                                                                       */
    229   /* <Description>                                                         */
    230   /*    Loads the metrics for `EBLC' index tables format 2 and 5.          */
    231   /*                                                                       */
    232   /* <Input>                                                               */
    233   /*    range  :: The target range.                                        */
    234   /*                                                                       */
    235   /*    stream :: The input stream.                                        */
    236   /*                                                                       */
    237   /* <Return>                                                              */
    238   /*    FreeType error code.  0 means success.                             */
    239   /*                                                                       */
    240   static FT_Error
    241   Load_SBit_Const_Metrics( TT_SBit_Range  range,
    242                            FT_Stream      stream )
    243   {
    244     FT_Error  error;
    245 
    246 
    247     if ( FT_READ_ULONG( range->image_size ) )
    248       return error;
    249 
    250     return FT_STREAM_READ_FIELDS( sbit_metrics_fields, &range->metrics );
    251   }
    252 
    253 
    254   /*************************************************************************/
    255   /*                                                                       */
    256   /* <Function>                                                            */
    257   /*    Load_SBit_Range_Codes                                              */
    258   /*                                                                       */
    259   /* <Description>                                                         */
    260   /*    Loads the range codes for `EBLC' index tables format 4 and 5.      */
    261   /*                                                                       */
    262   /* <Input>                                                               */
    263   /*    range        :: The target range.                                  */
    264   /*                                                                       */
    265   /*    stream       :: The input stream.                                  */
    266   /*                                                                       */
    267   /*    load_offsets :: A flag whether to load the glyph offset table.     */
    268   /*                                                                       */
    269   /* <Return>                                                              */
    270   /*    FreeType error code.  0 means success.                             */
    271   /*                                                                       */
    272   static FT_Error
    273   Load_SBit_Range_Codes( TT_SBit_Range  range,
    274                          FT_Stream      stream,
    275                          FT_Bool        load_offsets )
    276   {
    277     FT_Error   error;
    278     FT_ULong   count, n, size;
    279     FT_Memory  memory = stream->memory;
    280 
    281 
    282     if ( FT_READ_ULONG( count ) )
    283       goto Exit;
    284 
    285     range->num_glyphs = count;
    286 
    287     /* Allocate glyph offsets table if needed */
    288     if ( load_offsets )
    289     {
    290       if ( FT_NEW_ARRAY( range->glyph_offsets, count ) )
    291         goto Exit;
    292 
    293       size = count * 4L;
    294     }
    295     else
    296       size = count * 2L;
    297 
    298     /* Allocate glyph codes table and access frame */
    299     if ( FT_NEW_ARRAY ( range->glyph_codes, count ) ||
    300          FT_FRAME_ENTER( size )                     )
    301       goto Exit;
    302 
    303     for ( n = 0; n < count; n++ )
    304     {
    305       range->glyph_codes[n] = FT_GET_USHORT();
    306 
    307       if ( load_offsets )
    308         range->glyph_offsets[n] = (FT_ULong)range->image_offset +
    309                                   FT_GET_USHORT();
    310     }
    311 
    312     FT_FRAME_EXIT();
    313 
    314   Exit:
    315     return error;
    316   }
    317 
    318 
    319   /*************************************************************************/
    320   /*                                                                       */
    321   /* <Function>                                                            */
    322   /*    Load_SBit_Range                                                    */
    323   /*                                                                       */
    324   /* <Description>                                                         */
    325   /*    Loads a given `EBLC' index/range table.                            */
    326   /*                                                                       */
    327   /* <Input>                                                               */
    328   /*    range  :: The target range.                                        */
    329   /*                                                                       */
    330   /*    stream :: The input stream.                                        */
    331   /*                                                                       */
    332   /* <Return>                                                              */
    333   /*    FreeType error code.  0 means success.                             */
    334   /*                                                                       */
    335   static FT_Error
    336   Load_SBit_Range( TT_SBit_Range  range,
    337                    FT_Stream      stream )
    338   {
    339     FT_Error   error;
    340     FT_Memory  memory = stream->memory;
    341 
    342 
    343     switch( range->index_format )
    344     {
    345     case 1:   /* variable metrics with 4-byte offsets */
    346     case 3:   /* variable metrics with 2-byte offsets */
    347       {
    348         FT_ULong  num_glyphs, n;
    349         FT_Int    size_elem;
    350         FT_Bool   large = FT_BOOL( range->index_format == 1 );
    351 
    352 
    353 
    354         if ( range->last_glyph < range->first_glyph )
    355         {
    356           error = SFNT_Err_Invalid_File_Format;
    357           goto Exit;
    358         }
    359 
    360         num_glyphs        = range->last_glyph - range->first_glyph + 1L;
    361         range->num_glyphs = num_glyphs;
    362         num_glyphs++;                       /* XXX: BEWARE - see spec */
    363 
    364         size_elem = large ? 4 : 2;
    365 
    366         if ( FT_NEW_ARRAY( range->glyph_offsets, num_glyphs ) ||
    367              FT_FRAME_ENTER( num_glyphs * size_elem )         )
    368           goto Exit;
    369 
    370         for ( n = 0; n < num_glyphs; n++ )
    371           range->glyph_offsets[n] = (FT_ULong)( range->image_offset +
    372                                                 ( large ? FT_GET_ULONG()
    373                                                         : FT_GET_USHORT() ) );
    374         FT_FRAME_EXIT();
    375       }
    376       break;
    377 
    378     case 2:   /* all glyphs have identical metrics */
    379       error = Load_SBit_Const_Metrics( range, stream );
    380       break;
    381 
    382     case 4:
    383       error = Load_SBit_Range_Codes( range, stream, 1 );
    384       break;
    385 
    386     case 5:
    387       error = Load_SBit_Const_Metrics( range, stream );
    388       if ( !error )
    389         error = Load_SBit_Range_Codes( range, stream, 0 );
    390       break;
    391 
    392     default:
    393       error = SFNT_Err_Invalid_File_Format;
    394     }
    395 
    396   Exit:
    397     return error;
    398   }
    399 
    400 
    401   /*************************************************************************/
    402   /*                                                                       */
    403   /* <Function>                                                            */
    404   /*    tt_face_load_eblc                                                  */
    405   /*                                                                       */
    406   /* <Description>                                                         */
    407   /*    Loads the table of embedded bitmap sizes for this face.            */
    408   /*                                                                       */
    409   /* <Input>                                                               */
    410   /*    face   :: The target face object.                                  */
    411   /*                                                                       */
    412   /*    stream :: The input stream.                                        */
    413   /*                                                                       */
    414   /* <Return>                                                              */
    415   /*    FreeType error code.  0 means success.                             */
    416   /*                                                                       */
    417   FT_LOCAL_DEF( FT_Error )
    418   tt_face_load_eblc( TT_Face    face,
    419                      FT_Stream  stream )
    420   {
    421     FT_Error   error  = SFNT_Err_Ok;
    422     FT_Memory  memory = stream->memory;
    423     FT_Fixed   version;
    424     FT_ULong   num_strikes;
    425     FT_ULong   table_base;
    426 
    427     static const FT_Frame_Field  sbit_line_metrics_fields[] =
    428     {
    429 #undef  FT_STRUCTURE
    430 #define FT_STRUCTURE  TT_SBit_LineMetricsRec
    431 
    432       /* no FT_FRAME_START */
    433         FT_FRAME_CHAR( ascender ),
    434         FT_FRAME_CHAR( descender ),
    435         FT_FRAME_BYTE( max_width ),
    436 
    437         FT_FRAME_CHAR( caret_slope_numerator ),
    438         FT_FRAME_CHAR( caret_slope_denominator ),
    439         FT_FRAME_CHAR( caret_offset ),
    440 
    441         FT_FRAME_CHAR( min_origin_SB ),
    442         FT_FRAME_CHAR( min_advance_SB ),
    443         FT_FRAME_CHAR( max_before_BL ),
    444         FT_FRAME_CHAR( min_after_BL ),
    445         FT_FRAME_CHAR( pads[0] ),
    446         FT_FRAME_CHAR( pads[1] ),
    447       FT_FRAME_END
    448     };
    449 
    450     static const FT_Frame_Field  strike_start_fields[] =
    451     {
    452 #undef  FT_STRUCTURE
    453 #define FT_STRUCTURE  TT_SBit_StrikeRec
    454 
    455       /* no FT_FRAME_START */
    456         FT_FRAME_ULONG( ranges_offset ),
    457         FT_FRAME_SKIP_LONG,
    458         FT_FRAME_ULONG( num_ranges ),
    459         FT_FRAME_ULONG( color_ref ),
    460       FT_FRAME_END
    461     };
    462 
    463     static const FT_Frame_Field  strike_end_fields[] =
    464     {
    465       /* no FT_FRAME_START */
    466         FT_FRAME_USHORT( start_glyph ),
    467         FT_FRAME_USHORT( end_glyph ),
    468         FT_FRAME_BYTE  ( x_ppem ),
    469         FT_FRAME_BYTE  ( y_ppem ),
    470         FT_FRAME_BYTE  ( bit_depth ),
    471         FT_FRAME_CHAR  ( flags ),
    472       FT_FRAME_END
    473     };
    474 
    475 
    476     face->num_sbit_strikes = 0;
    477 
    478     /* this table is optional */
    479     error = face->goto_table( face, TTAG_EBLC, stream, 0 );
    480     if ( error )
    481       error = face->goto_table( face, TTAG_bloc, stream, 0 );
    482     if ( error )
    483       goto Exit;
    484 
    485     table_base = FT_STREAM_POS();
    486     if ( FT_FRAME_ENTER( 8L ) )
    487       goto Exit;
    488 
    489     version     = FT_GET_LONG();
    490     num_strikes = FT_GET_ULONG();
    491 
    492     FT_FRAME_EXIT();
    493 
    494     /* check version number and strike count */
    495     if ( version     != 0x00020000L ||
    496          num_strikes >= 0x10000L    )
    497     {
    498       FT_ERROR(( "tt_face_load_sbit_strikes: invalid table version\n" ));
    499       error = SFNT_Err_Invalid_File_Format;
    500 
    501       goto Exit;
    502     }
    503 
    504     /* allocate the strikes table */
    505     if ( FT_NEW_ARRAY( face->sbit_strikes, num_strikes ) )
    506       goto Exit;
    507 
    508     face->num_sbit_strikes = num_strikes;
    509 
    510     /* now read each strike table separately */
    511     {
    512       TT_SBit_Strike  strike = face->sbit_strikes;
    513       FT_ULong        count  = num_strikes;
    514 
    515 
    516       if ( FT_FRAME_ENTER( 48L * num_strikes ) )
    517         goto Exit;
    518 
    519       while ( count > 0 )
    520       {
    521         if ( FT_STREAM_READ_FIELDS( strike_start_fields, strike )             ||
    522              FT_STREAM_READ_FIELDS( sbit_line_metrics_fields, &strike->hori ) ||
    523              FT_STREAM_READ_FIELDS( sbit_line_metrics_fields, &strike->vert ) ||
    524              FT_STREAM_READ_FIELDS( strike_end_fields, strike )               )
    525           break;
    526 
    527         count--;
    528         strike++;
    529       }
    530 
    531       FT_FRAME_EXIT();
    532     }
    533 
    534     /* allocate the index ranges for each strike table */
    535     {
    536       TT_SBit_Strike  strike = face->sbit_strikes;
    537       FT_ULong        count  = num_strikes;
    538 
    539 
    540       while ( count > 0 )
    541       {
    542         TT_SBit_Range  range;
    543         FT_ULong       count2 = strike->num_ranges;
    544 
    545 
    546         /* read each range */
    547         if ( FT_STREAM_SEEK( table_base + strike->ranges_offset ) ||
    548              FT_FRAME_ENTER( strike->num_ranges * 8L )            )
    549           goto Exit;
    550 
    551         if ( FT_NEW_ARRAY( strike->sbit_ranges, strike->num_ranges ) )
    552           goto Exit;
    553 
    554         range = strike->sbit_ranges;
    555         while ( count2 > 0 )
    556         {
    557           range->first_glyph  = FT_GET_USHORT();
    558           range->last_glyph   = FT_GET_USHORT();
    559           range->table_offset = table_base + strike->ranges_offset +
    560                                   FT_GET_ULONG();
    561           count2--;
    562           range++;
    563         }
    564 
    565         FT_FRAME_EXIT();
    566 
    567         /* Now, read each index table */
    568         count2 = strike->num_ranges;
    569         range  = strike->sbit_ranges;
    570         while ( count2 > 0 )
    571         {
    572           /* Read the header */
    573           if ( FT_STREAM_SEEK( range->table_offset ) ||
    574                FT_FRAME_ENTER( 8L )                  )
    575             goto Exit;
    576 
    577           range->index_format = FT_GET_USHORT();
    578           range->image_format = FT_GET_USHORT();
    579           range->image_offset = FT_GET_ULONG();
    580 
    581           FT_FRAME_EXIT();
    582 
    583           error = Load_SBit_Range( range, stream );
    584           if ( error )
    585             goto Exit;
    586 
    587           count2--;
    588           range++;
    589         }
    590 
    591         count--;
    592         strike++;
    593       }
    594     }
    595 
    596   Exit:
    597     return error;
    598   }
    599 
    600 
    601   /*************************************************************************/
    602   /*                                                                       */
    603   /* <Function>                                                            */
    604   /*    tt_face_free_eblc                                                  */
    605   /*                                                                       */
    606   /* <Description>                                                         */
    607   /*    Releases the embedded bitmap tables.                               */
    608   /*                                                                       */
    609   /* <Input>                                                               */
    610   /*    face :: The target face object.                                    */
    611   /*                                                                       */
    612   FT_LOCAL_DEF( void )
    613   tt_face_free_eblc( TT_Face  face )
    614   {
    615     FT_Memory       memory       = face->root.memory;
    616     TT_SBit_Strike  strike       = face->sbit_strikes;
    617     TT_SBit_Strike  strike_limit = strike + face->num_sbit_strikes;
    618 
    619 
    620     if ( strike )
    621     {
    622       for ( ; strike < strike_limit; strike++ )
    623       {
    624         TT_SBit_Range  range       = strike->sbit_ranges;
    625         TT_SBit_Range  range_limit = range + strike->num_ranges;
    626 
    627 
    628         if ( range )
    629         {
    630           for ( ; range < range_limit; range++ )
    631           {
    632             /* release the glyph offsets and codes tables */
    633             /* where appropriate                          */
    634             FT_FREE( range->glyph_offsets );
    635             FT_FREE( range->glyph_codes );
    636           }
    637         }
    638         FT_FREE( strike->sbit_ranges );
    639         strike->num_ranges = 0;
    640       }
    641       FT_FREE( face->sbit_strikes );
    642     }
    643     face->num_sbit_strikes = 0;
    644   }
    645 
    646 
    647   FT_LOCAL_DEF( FT_Error )
    648   tt_face_set_sbit_strike( TT_Face          face,
    649                            FT_Size_Request  req,
    650                            FT_ULong*        astrike_index )
    651   {
    652     return FT_Match_Size( (FT_Face)face, req, 0, astrike_index );
    653   }
    654 
    655 
    656   FT_LOCAL_DEF( FT_Error )
    657   tt_face_load_strike_metrics( TT_Face           face,
    658                                FT_ULong          strike_index,
    659                                FT_Size_Metrics*  metrics )
    660   {
    661     TT_SBit_Strike  strike;
    662 
    663 
    664     if ( strike_index >= face->num_sbit_strikes )
    665       return SFNT_Err_Invalid_Argument;
    666 
    667     strike = face->sbit_strikes + strike_index;
    668 
    669     metrics->x_ppem = strike->x_ppem;
    670     metrics->y_ppem = strike->y_ppem;
    671 
    672     metrics->ascender  = strike->hori.ascender << 6;
    673     metrics->descender = strike->hori.descender << 6;
    674 
    675     /* XXX: Is this correct? */
    676     metrics->max_advance = ( strike->hori.min_origin_SB  +
    677                              strike->hori.max_width      +
    678                              strike->hori.min_advance_SB ) << 6;
    679 
    680     metrics->height = metrics->ascender - metrics->descender;
    681 
    682     return SFNT_Err_Ok;
    683   }
    684 
    685 
    686   /*************************************************************************/
    687   /*                                                                       */
    688   /* <Function>                                                            */
    689   /*    find_sbit_range                                                    */
    690   /*                                                                       */
    691   /* <Description>                                                         */
    692   /*    Scans a given strike's ranges and return, for a given glyph        */
    693   /*    index, the corresponding sbit range, and `EBDT' offset.            */
    694   /*                                                                       */
    695   /* <Input>                                                               */
    696   /*    glyph_index   :: The glyph index.                                  */
    697   /*                                                                       */
    698   /*    strike        :: The source/current sbit strike.                   */
    699   /*                                                                       */
    700   /* <Output>                                                              */
    701   /*    arange        :: The sbit range containing the glyph index.        */
    702   /*                                                                       */
    703   /*    aglyph_offset :: The offset of the glyph data in `EBDT' table.     */
    704   /*                                                                       */
    705   /* <Return>                                                              */
    706   /*    FreeType error code.  0 means the glyph index was found.           */
    707   /*                                                                       */
    708   static FT_Error
    709   find_sbit_range( FT_UInt          glyph_index,
    710                    TT_SBit_Strike   strike,
    711                    TT_SBit_Range   *arange,
    712                    FT_ULong        *aglyph_offset )
    713   {
    714     TT_SBit_RangeRec  *range, *range_limit;
    715 
    716 
    717     /* check whether the glyph index is within this strike's */
    718     /* glyph range                                           */
    719     if ( glyph_index < (FT_UInt)strike->start_glyph ||
    720          glyph_index > (FT_UInt)strike->end_glyph   )
    721       goto Fail;
    722 
    723     /* scan all ranges in strike */
    724     range       = strike->sbit_ranges;
    725     range_limit = range + strike->num_ranges;
    726     if ( !range )
    727       goto Fail;
    728 
    729     for ( ; range < range_limit; range++ )
    730     {
    731       if ( glyph_index >= (FT_UInt)range->first_glyph &&
    732            glyph_index <= (FT_UInt)range->last_glyph  )
    733       {
    734         FT_UShort  delta = (FT_UShort)( glyph_index - range->first_glyph );
    735 
    736 
    737         switch ( range->index_format )
    738         {
    739         case 1:
    740         case 3:
    741           *aglyph_offset = range->glyph_offsets[delta];
    742           break;
    743 
    744         case 2:
    745           *aglyph_offset = range->image_offset +
    746                            range->image_size * delta;
    747           break;
    748 
    749         case 4:
    750         case 5:
    751           {
    752             FT_ULong  n;
    753 
    754 
    755             for ( n = 0; n < range->num_glyphs; n++ )
    756             {
    757               if ( (FT_UInt)range->glyph_codes[n] == glyph_index )
    758               {
    759                 if ( range->index_format == 4 )
    760                   *aglyph_offset = range->glyph_offsets[n];
    761                 else
    762                   *aglyph_offset = range->image_offset +
    763                                    n * range->image_size;
    764                 goto Found;
    765               }
    766             }
    767           }
    768 
    769         /* fall-through */
    770         default:
    771           goto Fail;
    772         }
    773 
    774       Found:
    775         /* return successfully! */
    776         *arange  = range;
    777         return SFNT_Err_Ok;
    778       }
    779     }
    780 
    781   Fail:
    782     *arange        = 0;
    783     *aglyph_offset = 0;
    784 
    785     return SFNT_Err_Invalid_Argument;
    786   }
    787 
    788 
    789   /*************************************************************************/
    790   /*                                                                       */
    791   /* <Function>                                                            */
    792   /*    tt_find_sbit_image                                                 */
    793   /*                                                                       */
    794   /* <Description>                                                         */
    795   /*    Checks whether an embedded bitmap (an `sbit') exists for a given   */
    796   /*    glyph, at a given strike.                                          */
    797   /*                                                                       */
    798   /* <Input>                                                               */
    799   /*    face          :: The target face object.                           */
    800   /*                                                                       */
    801   /*    glyph_index   :: The glyph index.                                  */
    802   /*                                                                       */
    803   /*    strike_index  :: The current strike index.                         */
    804   /*                                                                       */
    805   /* <Output>                                                              */
    806   /*    arange        :: The SBit range containing the glyph index.        */
    807   /*                                                                       */
    808   /*    astrike       :: The SBit strike containing the glyph index.       */
    809   /*                                                                       */
    810   /*    aglyph_offset :: The offset of the glyph data in `EBDT' table.     */
    811   /*                                                                       */
    812   /* <Return>                                                              */
    813   /*    FreeType error code.  0 means success.  Returns                    */
    814   /*    SFNT_Err_Invalid_Argument if no sbit exists for the requested      */
    815   /*    glyph.                                                             */
    816   /*                                                                       */
    817   FT_LOCAL( FT_Error )
    818   tt_find_sbit_image( TT_Face          face,
    819                       FT_UInt          glyph_index,
    820                       FT_ULong         strike_index,
    821                       TT_SBit_Range   *arange,
    822                       TT_SBit_Strike  *astrike,
    823                       FT_ULong        *aglyph_offset )
    824   {
    825     FT_Error        error;
    826     TT_SBit_Strike  strike;
    827 
    828 
    829     if ( !face->sbit_strikes                        ||
    830          ( face->num_sbit_strikes <= strike_index ) )
    831       goto Fail;
    832 
    833     strike = &face->sbit_strikes[strike_index];
    834 
    835     error = find_sbit_range( glyph_index, strike,
    836                              arange, aglyph_offset );
    837     if ( error )
    838       goto Fail;
    839 
    840     *astrike = strike;
    841 
    842     return SFNT_Err_Ok;
    843 
    844   Fail:
    845     /* no embedded bitmap for this glyph in face */
    846     *arange        = 0;
    847     *astrike       = 0;
    848     *aglyph_offset = 0;
    849 
    850     return SFNT_Err_Invalid_Argument;
    851   }
    852 
    853 
    854   /*************************************************************************/
    855   /*                                                                       */
    856   /* <Function>                                                            */
    857   /*    tt_load_sbit_metrics                                               */
    858   /*                                                                       */
    859   /* <Description>                                                         */
    860   /*    Gets the big metrics for a given SBit.                             */
    861   /*                                                                       */
    862   /* <Input>                                                               */
    863   /*    stream      :: The input stream.                                   */
    864   /*                                                                       */
    865   /*    range       :: The SBit range containing the glyph.                */
    866   /*                                                                       */
    867   /* <Output>                                                              */
    868   /*    big_metrics :: A big SBit metrics structure for the glyph.         */
    869   /*                                                                       */
    870   /* <Return>                                                              */
    871   /*    FreeType error code.  0 means success.                             */
    872   /*                                                                       */
    873   /* <Note>                                                                */
    874   /*    The stream cursor must be positioned at the glyph's offset within  */
    875   /*    the `EBDT' table before the call.                                  */
    876   /*                                                                       */
    877   /*    If the image format uses variable metrics, the stream cursor is    */
    878   /*    positioned just after the metrics header in the `EBDT' table on    */
    879   /*    function exit.                                                     */
    880   /*                                                                       */
    881   FT_LOCAL( FT_Error )
    882   tt_load_sbit_metrics( FT_Stream        stream,
    883                         TT_SBit_Range    range,
    884                         TT_SBit_Metrics  metrics )
    885   {
    886     FT_Error  error = SFNT_Err_Ok;
    887 
    888 
    889     switch ( range->image_format )
    890     {
    891     case 1:
    892     case 2:
    893     case 8:
    894       /* variable small metrics */
    895       {
    896         TT_SBit_SmallMetricsRec  smetrics;
    897 
    898         static const FT_Frame_Field  sbit_small_metrics_fields[] =
    899         {
    900 #undef  FT_STRUCTURE
    901 #define FT_STRUCTURE  TT_SBit_SmallMetricsRec
    902 
    903           FT_FRAME_START( 5 ),
    904             FT_FRAME_BYTE( height ),
    905             FT_FRAME_BYTE( width ),
    906             FT_FRAME_CHAR( bearingX ),
    907             FT_FRAME_CHAR( bearingY ),
    908             FT_FRAME_BYTE( advance ),
    909           FT_FRAME_END
    910         };
    911 
    912 
    913         /* read small metrics */
    914         if ( FT_STREAM_READ_FIELDS( sbit_small_metrics_fields, &smetrics ) )
    915           goto Exit;
    916 
    917         /* convert it to a big metrics */
    918         metrics->height       = smetrics.height;
    919         metrics->width        = smetrics.width;
    920         metrics->horiBearingX = smetrics.bearingX;
    921         metrics->horiBearingY = smetrics.bearingY;
    922         metrics->horiAdvance  = smetrics.advance;
    923 
    924         /* these metrics are made up at a higher level when */
    925         /* needed.                                          */
    926         metrics->vertBearingX = 0;
    927         metrics->vertBearingY = 0;
    928         metrics->vertAdvance  = 0;
    929       }
    930       break;
    931 
    932     case 6:
    933     case 7:
    934     case 9:
    935       /* variable big metrics */
    936       if ( FT_STREAM_READ_FIELDS( sbit_metrics_fields, metrics ) )
    937         goto Exit;
    938       break;
    939 
    940     case 5:
    941     default:  /* constant metrics */
    942       if ( range->index_format == 2 || range->index_format == 5 )
    943         *metrics = range->metrics;
    944       else
    945         return SFNT_Err_Invalid_File_Format;
    946    }
    947 
    948   Exit:
    949     return error;
    950   }
    951 
    952 
    953   /*************************************************************************/
    954   /*                                                                       */
    955   /* <Function>                                                            */
    956   /*    crop_bitmap                                                        */
    957   /*                                                                       */
    958   /* <Description>                                                         */
    959   /*    Crops a bitmap to its tightest bounding box, and adjusts its       */
    960   /*    metrics.                                                           */
    961   /*                                                                       */
    962   /* <InOut>                                                               */
    963   /*    map     :: The bitmap.                                             */
    964   /*                                                                       */
    965   /*    metrics :: The corresponding metrics structure.                    */
    966   /*                                                                       */
    967   static void
    968   crop_bitmap( FT_Bitmap*       map,
    969                TT_SBit_Metrics  metrics )
    970   {
    971     /***********************************************************************/
    972     /*                                                                     */
    973     /* In this situation, some bounding boxes of embedded bitmaps are too  */
    974     /* large.  We need to crop it to a reasonable size.                    */
    975     /*                                                                     */
    976     /*      ---------                                                      */
    977     /*      |       |                -----                                 */
    978     /*      |  ***  |                |***|                                 */
    979     /*      |   *   |                | * |                                 */
    980     /*      |   *   |    ------>     | * |                                 */
    981     /*      |   *   |                | * |                                 */
    982     /*      |   *   |                | * |                                 */
    983     /*      |  ***  |                |***|                                 */
    984     /*      ---------                -----                                 */
    985     /*                                                                     */
    986     /***********************************************************************/
    987 
    988     FT_Int    rows, count;
    989     FT_Long   line_len;
    990     FT_Byte*  line;
    991 
    992 
    993     /***********************************************************************/
    994     /*                                                                     */
    995     /* first of all, check the top-most lines of the bitmap, and remove    */
    996     /* them if they're empty.                                              */
    997     /*                                                                     */
    998     {
    999       line     = (FT_Byte*)map->buffer;
   1000       rows     = map->rows;
   1001       line_len = map->pitch;
   1002 
   1003 
   1004       for ( count = 0; count < rows; count++ )
   1005       {
   1006         FT_Byte*  cur   = line;
   1007         FT_Byte*  limit = line + line_len;
   1008 
   1009 
   1010         for ( ; cur < limit; cur++ )
   1011           if ( cur[0] )
   1012             goto Found_Top;
   1013 
   1014         /* the current line was empty - skip to next one */
   1015         line  = limit;
   1016       }
   1017 
   1018     Found_Top:
   1019       /* check that we have at least one filled line */
   1020       if ( count >= rows )
   1021         goto Empty_Bitmap;
   1022 
   1023       /* now, crop the empty upper lines */
   1024       if ( count > 0 )
   1025       {
   1026         line = (FT_Byte*)map->buffer;
   1027 
   1028         FT_MEM_MOVE( line, line + count * line_len,
   1029                      ( rows - count ) * line_len );
   1030 
   1031         metrics->height       = (FT_Byte)( metrics->height - count );
   1032         metrics->horiBearingY = (FT_Char)( metrics->horiBearingY - count );
   1033         metrics->vertBearingY = (FT_Char)( metrics->vertBearingY - count );
   1034 
   1035         map->rows -= count;
   1036         rows      -= count;
   1037       }
   1038     }
   1039 
   1040     /***********************************************************************/
   1041     /*                                                                     */
   1042     /* second, crop the lower lines                                        */
   1043     /*                                                                     */
   1044     {
   1045       line = (FT_Byte*)map->buffer + ( rows - 1 ) * line_len;
   1046 
   1047       for ( count = 0; count < rows; count++ )
   1048       {
   1049         FT_Byte*  cur   = line;
   1050         FT_Byte*  limit = line + line_len;
   1051 
   1052 
   1053         for ( ; cur < limit; cur++ )
   1054           if ( cur[0] )
   1055             goto Found_Bottom;
   1056 
   1057         /* the current line was empty - skip to previous one */
   1058         line -= line_len;
   1059       }
   1060 
   1061     Found_Bottom:
   1062       if ( count > 0 )
   1063       {
   1064         metrics->height  = (FT_Byte)( metrics->height - count );
   1065         rows            -= count;
   1066         map->rows       -= count;
   1067       }
   1068     }
   1069 
   1070     /***********************************************************************/
   1071     /*                                                                     */
   1072     /* third, get rid of the space on the left side of the glyph           */
   1073     /*                                                                     */
   1074     do
   1075     {
   1076       FT_Byte*  limit;
   1077 
   1078 
   1079       line  = (FT_Byte*)map->buffer;
   1080       limit = line + rows * line_len;
   1081 
   1082       for ( ; line < limit; line += line_len )
   1083         if ( line[0] & 0x80 )
   1084           goto Found_Left;
   1085 
   1086       /* shift the whole glyph one pixel to the left */
   1087       line  = (FT_Byte*)map->buffer;
   1088       limit = line + rows * line_len;
   1089 
   1090       for ( ; line < limit; line += line_len )
   1091       {
   1092         FT_Int    n, width = map->width;
   1093         FT_Byte   old;
   1094         FT_Byte*  cur = line;
   1095 
   1096 
   1097         old = (FT_Byte)(cur[0] << 1);
   1098         for ( n = 8; n < width; n += 8 )
   1099         {
   1100           FT_Byte  val;
   1101 
   1102 
   1103           val    = cur[1];
   1104           cur[0] = (FT_Byte)( old | ( val >> 7 ) );
   1105           old    = (FT_Byte)( val << 1 );
   1106           cur++;
   1107         }
   1108         cur[0] = old;
   1109       }
   1110 
   1111       map->width--;
   1112       metrics->horiBearingX++;
   1113       metrics->vertBearingX++;
   1114       metrics->width--;
   1115 
   1116     } while ( map->width > 0 );
   1117 
   1118   Found_Left:
   1119 
   1120     /***********************************************************************/
   1121     /*                                                                     */
   1122     /* finally, crop the bitmap width to get rid of the space on the right */
   1123     /* side of the glyph.                                                  */
   1124     /*                                                                     */
   1125     do
   1126     {
   1127       FT_Int    right = map->width - 1;
   1128       FT_Byte*  limit;
   1129       FT_Byte   mask;
   1130 
   1131 
   1132       line  = (FT_Byte*)map->buffer + ( right >> 3 );
   1133       limit = line + rows * line_len;
   1134       mask  = (FT_Byte)( 0x80 >> ( right & 7 ) );
   1135 
   1136       for ( ; line < limit; line += line_len )
   1137         if ( line[0] & mask )
   1138           goto Found_Right;
   1139 
   1140       /* crop the whole glyph to the right */
   1141       map->width--;
   1142       metrics->width--;
   1143 
   1144     } while ( map->width > 0 );
   1145 
   1146   Found_Right:
   1147     /* all right, the bitmap was cropped */
   1148     return;
   1149 
   1150   Empty_Bitmap:
   1151     map->width      = 0;
   1152     map->rows       = 0;
   1153     map->pitch      = 0;
   1154     map->pixel_mode = FT_PIXEL_MODE_MONO;
   1155   }
   1156 
   1157 
   1158   static FT_Error
   1159   Load_SBit_Single( FT_Bitmap*       map,
   1160                     FT_Int           x_offset,
   1161                     FT_Int           y_offset,
   1162                     FT_Int           pix_bits,
   1163                     FT_UShort        image_format,
   1164                     TT_SBit_Metrics  metrics,
   1165                     FT_Stream        stream )
   1166   {
   1167     FT_Error  error;
   1168 
   1169 
   1170     /* check that the source bitmap fits into the target pixmap */
   1171     if ( x_offset < 0 || x_offset + metrics->width  > map->width ||
   1172          y_offset < 0 || y_offset + metrics->height > map->rows  )
   1173     {
   1174       error = SFNT_Err_Invalid_Argument;
   1175 
   1176       goto Exit;
   1177     }
   1178 
   1179     {
   1180       FT_Int   glyph_width  = metrics->width;
   1181       FT_Int   glyph_height = metrics->height;
   1182       FT_Int   glyph_size;
   1183       FT_Int   line_bits    = pix_bits * glyph_width;
   1184       FT_Bool  pad_bytes    = 0;
   1185 
   1186 
   1187       /* compute size of glyph image */
   1188       switch ( image_format )
   1189       {
   1190       case 1:  /* byte-padded formats */
   1191       case 6:
   1192         {
   1193           FT_Int  line_length;
   1194 
   1195 
   1196           switch ( pix_bits )
   1197           {
   1198           case 1:
   1199             line_length = ( glyph_width + 7 ) >> 3;
   1200             break;
   1201           case 2:
   1202             line_length = ( glyph_width + 3 ) >> 2;
   1203             break;
   1204           case 4:
   1205             line_length = ( glyph_width + 1 ) >> 1;
   1206             break;
   1207           default:
   1208             line_length =   glyph_width;
   1209           }
   1210 
   1211           glyph_size = glyph_height * line_length;
   1212           pad_bytes  = 1;
   1213         }
   1214         break;
   1215 
   1216       case 2:
   1217       case 5:
   1218       case 7:
   1219         line_bits  =   glyph_width  * pix_bits;
   1220         glyph_size = ( glyph_height * line_bits + 7 ) >> 3;
   1221         break;
   1222 
   1223       default:  /* invalid format */
   1224         return SFNT_Err_Invalid_File_Format;
   1225       }
   1226 
   1227       /* Now read data and draw glyph into target pixmap       */
   1228       if ( FT_FRAME_ENTER( glyph_size ) )
   1229         goto Exit;
   1230 
   1231       /* don't forget to multiply `x_offset' by `map->pix_bits' as */
   1232       /* the sbit blitter doesn't make a difference between pixmap */
   1233       /* depths.                                                   */
   1234       blit_sbit( map, (FT_Byte*)stream->cursor, line_bits, pad_bytes,
   1235                  x_offset * pix_bits, y_offset, metrics->height );
   1236 
   1237       FT_FRAME_EXIT();
   1238     }
   1239 
   1240   Exit:
   1241     return error;
   1242   }
   1243 
   1244 
   1245   static FT_Error
   1246   Load_SBit_Image( TT_SBit_Strike   strike,
   1247                    TT_SBit_Range    range,
   1248                    FT_ULong         ebdt_pos,
   1249                    FT_ULong         glyph_offset,
   1250                    FT_GlyphSlot     slot,
   1251                    FT_Int           x_offset,
   1252                    FT_Int           y_offset,
   1253                    FT_Stream        stream,
   1254                    TT_SBit_Metrics  metrics,
   1255                    FT_Int           depth )
   1256   {
   1257     FT_Memory   memory = stream->memory;
   1258     FT_Bitmap*  map    = &slot->bitmap;
   1259     FT_Error    error;
   1260 
   1261 
   1262     /* place stream at beginning of glyph data and read metrics */
   1263     if ( FT_STREAM_SEEK( ebdt_pos + glyph_offset ) )
   1264       goto Exit;
   1265 
   1266     error = tt_load_sbit_metrics( stream, range, metrics );
   1267     if ( error )
   1268       goto Exit;
   1269 
   1270     /* This function is recursive.  At the top-level call, we  */
   1271     /* compute the dimensions of the higher-level glyph to     */
   1272     /* allocate the final pixmap buffer.                       */
   1273     if ( depth == 0 )
   1274     {
   1275       FT_Long  size;
   1276 
   1277 
   1278       map->width = metrics->width;
   1279       map->rows  = metrics->height;
   1280 
   1281       switch ( strike->bit_depth )
   1282       {
   1283       case 1:
   1284         map->pixel_mode = FT_PIXEL_MODE_MONO;
   1285         map->pitch      = ( map->width + 7 ) >> 3;
   1286         break;
   1287 
   1288       case 2:
   1289         map->pixel_mode = FT_PIXEL_MODE_GRAY2;
   1290         map->pitch      = ( map->width + 3 ) >> 2;
   1291         break;
   1292 
   1293       case 4:
   1294         map->pixel_mode = FT_PIXEL_MODE_GRAY4;
   1295         map->pitch      = ( map->width + 1 ) >> 1;
   1296         break;
   1297 
   1298       case 8:
   1299         map->pixel_mode = FT_PIXEL_MODE_GRAY;
   1300         map->pitch      = map->width;
   1301         break;
   1302 
   1303       default:
   1304         return SFNT_Err_Invalid_File_Format;
   1305       }
   1306 
   1307       size = map->rows * map->pitch;
   1308 
   1309       /* check that there is no empty image */
   1310       if ( size == 0 )
   1311         goto Exit;     /* exit successfully! */
   1312 
   1313       error = ft_glyphslot_alloc_bitmap( slot, size );
   1314       if (error)
   1315         goto Exit;
   1316     }
   1317 
   1318     switch ( range->image_format )
   1319     {
   1320     case 1:  /* single sbit image - load it */
   1321     case 2:
   1322     case 5:
   1323     case 6:
   1324     case 7:
   1325       return Load_SBit_Single( map, x_offset, y_offset, strike->bit_depth,
   1326                                range->image_format, metrics, stream );
   1327 
   1328     case 8:  /* compound format */
   1329       if ( FT_STREAM_SKIP( 1L ) )
   1330       {
   1331         error = SFNT_Err_Invalid_Stream_Skip;
   1332         goto Exit;
   1333       }
   1334       /* fallthrough */
   1335 
   1336     case 9:
   1337       break;
   1338 
   1339     default: /* invalid image format */
   1340       return SFNT_Err_Invalid_File_Format;
   1341     }
   1342 
   1343     /* All right, we have a compound format.  First of all, read */
   1344     /* the array of elements.                                    */
   1345     {
   1346       TT_SBit_Component  components = NULL;
   1347       TT_SBit_Component  comp;
   1348       FT_UShort          num_components, count;
   1349 
   1350 
   1351       if ( FT_READ_USHORT( num_components )           ||
   1352            FT_NEW_ARRAY( components, num_components ) )
   1353         goto Exit;
   1354 
   1355       count = num_components;
   1356 
   1357       if ( FT_FRAME_ENTER( 4L * num_components ) )
   1358         goto Fail_Memory;
   1359 
   1360       for ( comp = components; count > 0; count--, comp++ )
   1361       {
   1362         comp->glyph_code = FT_GET_USHORT();
   1363         comp->x_offset   = FT_GET_CHAR();
   1364         comp->y_offset   = FT_GET_CHAR();
   1365       }
   1366 
   1367       FT_FRAME_EXIT();
   1368 
   1369       /* Now recursively load each element glyph */
   1370       count = num_components;
   1371       comp  = components;
   1372       for ( ; count > 0; count--, comp++ )
   1373       {
   1374         TT_SBit_Range       elem_range;
   1375         TT_SBit_MetricsRec  elem_metrics;
   1376         FT_ULong            elem_offset;
   1377 
   1378 
   1379         /* find the range for this element */
   1380         error = find_sbit_range( comp->glyph_code,
   1381                                  strike,
   1382                                  &elem_range,
   1383                                  &elem_offset );
   1384         if ( error )
   1385           goto Fail_Memory;
   1386 
   1387         /* now load the element, recursively */
   1388         error = Load_SBit_Image( strike,
   1389                                  elem_range,
   1390                                  ebdt_pos,
   1391                                  elem_offset,
   1392                                  slot,
   1393                                  x_offset + comp->x_offset,
   1394                                  y_offset + comp->y_offset,
   1395                                  stream,
   1396                                  &elem_metrics,
   1397                                  depth + 1 );
   1398         if ( error )
   1399           goto Fail_Memory;
   1400       }
   1401 
   1402     Fail_Memory:
   1403       FT_FREE( components );
   1404     }
   1405 
   1406   Exit:
   1407     return error;
   1408   }
   1409 
   1410 
   1411   /*************************************************************************/
   1412   /*                                                                       */
   1413   /* <Function>                                                            */
   1414   /*    tt_face_load_sbit_image                                            */
   1415   /*                                                                       */
   1416   /* <Description>                                                         */
   1417   /*    Loads a given glyph sbit image from the font resource.  This also  */
   1418   /*    returns its metrics.                                               */
   1419   /*                                                                       */
   1420   /* <Input>                                                               */
   1421   /*    face         :: The target face object.                            */
   1422   /*                                                                       */
   1423   /*    strike_index :: The current strike index.                          */
   1424   /*                                                                       */
   1425   /*    glyph_index  :: The current glyph index.                           */
   1426   /*                                                                       */
   1427   /*    load_flags   :: The glyph load flags (the code checks for the flag */
   1428   /*                    FT_LOAD_CROP_BITMAP).                              */
   1429   /*                                                                       */
   1430   /*    stream       :: The input stream.                                  */
   1431   /*                                                                       */
   1432   /* <Output>                                                              */
   1433   /*    map          :: The target pixmap.                                 */
   1434   /*                                                                       */
   1435   /*    metrics      :: A big sbit metrics structure for the glyph image.  */
   1436   /*                                                                       */
   1437   /* <Return>                                                              */
   1438   /*    FreeType error code.  0 means success.  Returns an error if no     */
   1439   /*    glyph sbit exists for the index.                                   */
   1440   /*                                                                       */
   1441   /*  <Note>                                                               */
   1442   /*    The `map.buffer' field is always freed before the glyph is loaded. */
   1443   /*                                                                       */
   1444   FT_LOCAL_DEF( FT_Error )
   1445   tt_face_load_sbit_image( TT_Face              face,
   1446                            FT_ULong             strike_index,
   1447                            FT_UInt              glyph_index,
   1448                            FT_UInt              load_flags,
   1449                            FT_Stream            stream,
   1450                            FT_Bitmap           *map,
   1451                            TT_SBit_MetricsRec  *metrics )
   1452   {
   1453     FT_Error        error;
   1454     FT_ULong        ebdt_pos, glyph_offset;
   1455 
   1456     TT_SBit_Strike  strike;
   1457     TT_SBit_Range   range;
   1458 
   1459 
   1460     /* Check whether there is a glyph sbit for the current index */
   1461     error = tt_find_sbit_image( face, glyph_index, strike_index,
   1462                                 &range, &strike, &glyph_offset );
   1463     if ( error )
   1464       goto Exit;
   1465 
   1466     /* now, find the location of the `EBDT' table in */
   1467     /* the font file                                 */
   1468     error = face->goto_table( face, TTAG_EBDT, stream, 0 );
   1469     if ( error )
   1470       error = face->goto_table( face, TTAG_bdat, stream, 0 );
   1471     if ( error )
   1472       goto Exit;
   1473 
   1474     ebdt_pos = FT_STREAM_POS();
   1475 
   1476     error = Load_SBit_Image( strike, range, ebdt_pos, glyph_offset,
   1477                              face->root.glyph, 0, 0, stream, metrics, 0 );
   1478     if ( error )
   1479       goto Exit;
   1480 
   1481     /* setup vertical metrics if needed */
   1482     if ( strike->flags & 1 )
   1483     {
   1484       /* in case of a horizontal strike only */
   1485       FT_Int  advance;
   1486 
   1487 
   1488       advance = strike->hori.ascender - strike->hori.descender;
   1489 
   1490       /* some heuristic values */
   1491 
   1492       metrics->vertBearingX = (FT_Char)(-metrics->width / 2 );
   1493       metrics->vertBearingY = (FT_Char)( ( advance - metrics->height ) / 2 );
   1494       metrics->vertAdvance  = (FT_Char)( advance * 12 / 10 );
   1495     }
   1496 
   1497     /* Crop the bitmap now, unless specified otherwise */
   1498     if ( load_flags & FT_LOAD_CROP_BITMAP )
   1499       crop_bitmap( map, metrics );
   1500 
   1501   Exit:
   1502     return error;
   1503   }
   1504 
   1505 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
   1506 
   1507 
   1508 /* END */
   1509