ttsbit.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  ttsbit.c                                                               */
00004 /*                                                                         */
00005 /*    TrueType and OpenType embedded bitmap support (body).                */
00006 /*                                                                         */
00007 /*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */
00008 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00009 /*                                                                         */
00010 /*  This file is part of the FreeType project, and may only be used,       */
00011 /*  modified, and distributed under the terms of the FreeType project      */
00012 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00013 /*  this file you indicate that you have read the license and              */
00014 /*  understand and accept it fully.                                        */
00015 /*                                                                         */
00016 /***************************************************************************/
00017 
00018 #include <ft2build.h>
00019 #include FT_INTERNAL_DEBUG_H
00020 #include FT_INTERNAL_STREAM_H
00021 #include FT_TRUETYPE_TAGS_H
00022 
00023   /*
00024    *  Alas, the memory-optimized sbit loader can't be used when implementing
00025    *  the `old internals' hack
00026    */
00027 #ifndef FT_CONFIG_OPTION_OLD_INTERNALS
00028 
00029 #include "ttsbit0.c"
00030 
00031 #else /* FT_CONFIG_OPTION_OLD_INTERNALS */
00032 
00033 #include <ft2build.h>
00034 #include FT_INTERNAL_DEBUG_H
00035 #include FT_INTERNAL_STREAM_H
00036 #include FT_TRUETYPE_TAGS_H
00037 #include "ttsbit.h"
00038 
00039 #include "sferrors.h"
00040 
00041 
00042   /*************************************************************************/
00043   /*                                                                       */
00044   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
00045   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
00046   /* messages during execution.                                            */
00047   /*                                                                       */
00048 #undef  FT_COMPONENT
00049 #define FT_COMPONENT  trace_ttsbit
00050 
00051 
00052   /*************************************************************************/
00053   /*                                                                       */
00054   /* <Function>                                                            */
00055   /*    blit_sbit                                                          */
00056   /*                                                                       */
00057   /* <Description>                                                         */
00058   /*    Blits a bitmap from an input stream into a given target.  Supports */
00059   /*    x and y offsets as well as byte padded lines.                      */
00060   /*                                                                       */
00061   /* <Input>                                                               */
00062   /*    target      :: The target bitmap/pixmap.                           */
00063   /*                                                                       */
00064   /*    source      :: The input packed bitmap data.                       */
00065   /*                                                                       */
00066   /*    line_bits   :: The number of bits per line.                        */
00067   /*                                                                       */
00068   /*    byte_padded :: A flag which is true if lines are byte-padded.      */
00069   /*                                                                       */
00070   /*    x_offset    :: The horizontal offset.                              */
00071   /*                                                                       */
00072   /*    y_offset    :: The vertical offset.                                */
00073   /*                                                                       */
00074   /* <Note>                                                                */
00075   /*    IMPORTANT: The x and y offsets are relative to the top corner of   */
00076   /*               the target bitmap (unlike the normal TrueType           */
00077   /*               convention).  A positive y offset indicates a downwards */
00078   /*               direction!                                              */
00079   /*                                                                       */
00080   static void
00081   blit_sbit( FT_Bitmap*  target,
00082              FT_Byte*    source,
00083              FT_Int      line_bits,
00084              FT_Bool     byte_padded,
00085              FT_Int      x_offset,
00086              FT_Int      y_offset,
00087              FT_Int      source_height )
00088   {
00089     FT_Byte*   line_buff;
00090     FT_Int     line_incr;
00091     FT_Int     height;
00092 
00093     FT_UShort  acc;
00094     FT_UInt    loaded;
00095 
00096 
00097     /* first of all, compute starting write position */
00098     line_incr = target->pitch;
00099     line_buff = target->buffer;
00100 
00101     if ( line_incr < 0 )
00102       line_buff -= line_incr * ( target->rows - 1 );
00103 
00104     line_buff += ( x_offset >> 3 ) + y_offset * line_incr;
00105 
00106     /***********************************************************************/
00107     /*                                                                     */
00108     /* We use the extra-classic `accumulator' trick to extract the bits    */
00109     /* from the source byte stream.                                        */
00110     /*                                                                     */
00111     /* Namely, the variable `acc' is a 16-bit accumulator containing the   */
00112     /* last `loaded' bits from the input stream.  The bits are shifted to  */
00113     /* the upmost position in `acc'.                                       */
00114     /*                                                                     */
00115     /***********************************************************************/
00116 
00117     acc    = 0;  /* clear accumulator   */
00118     loaded = 0;  /* no bits were loaded */
00119 
00120     for ( height = source_height; height > 0; height-- )
00121     {
00122       FT_Byte*  cur   = line_buff;        /* current write cursor          */
00123       FT_Int    count = line_bits;        /* # of bits to extract per line */
00124       FT_Byte   shift = (FT_Byte)( x_offset & 7 ); /* current write shift  */
00125       FT_Byte   space = (FT_Byte)( 8 - shift );
00126 
00127 
00128       /* first of all, read individual source bytes */
00129       if ( count >= 8 )
00130       {
00131         count -= 8;
00132         {
00133           do
00134           {
00135             FT_Byte  val;
00136 
00137 
00138             /* ensure that there are at least 8 bits in the accumulator */
00139             if ( loaded < 8 )
00140             {
00141               acc    |= (FT_UShort)((FT_UShort)*source++ << ( 8 - loaded ));
00142               loaded += 8;
00143             }
00144 
00145             /* now write one byte */
00146             val = (FT_Byte)( acc >> 8 );
00147             if ( shift )
00148             {
00149               cur[0] |= (FT_Byte)( val >> shift );
00150               cur[1] |= (FT_Byte)( val << space );
00151             }
00152             else
00153               cur[0] |= val;
00154 
00155             cur++;
00156             acc   <<= 8;  /* remove bits from accumulator */
00157             loaded -= 8;
00158             count  -= 8;
00159 
00160           } while ( count >= 0 );
00161         }
00162 
00163         /* restore `count' to correct value */
00164         count += 8;
00165       }
00166 
00167       /* now write remaining bits (count < 8) */
00168       if ( count > 0 )
00169       {
00170         FT_Byte  val;
00171 
00172 
00173         /* ensure that there are at least `count' bits in the accumulator */
00174         if ( (FT_Int)loaded < count )
00175         {
00176           acc    |= (FT_UShort)((FT_UShort)*source++ << ( 8 - loaded ));
00177           loaded += 8;
00178         }
00179 
00180         /* now write remaining bits */
00181         val     = (FT_Byte)( ( (FT_Byte)( acc >> 8 ) ) & ~( 0xFF >> count ) );
00182         cur[0] |= (FT_Byte)( val >> shift );
00183 
00184         if ( count > space )
00185           cur[1] |= (FT_Byte)( val << space );
00186 
00187         acc   <<= count;
00188         loaded -= count;
00189       }
00190 
00191       /* now, skip to next line */
00192       if ( byte_padded )
00193       {
00194         acc    = 0;
00195         loaded = 0;   /* clear accumulator on byte-padded lines */
00196       }
00197 
00198       line_buff += line_incr;
00199     }
00200   }
00201 
00202 
00203   static const FT_Frame_Field  sbit_metrics_fields[] =
00204   {
00205 #undef  FT_STRUCTURE
00206 #define FT_STRUCTURE  TT_SBit_MetricsRec
00207 
00208     FT_FRAME_START( 8 ),
00209       FT_FRAME_BYTE( height ),
00210       FT_FRAME_BYTE( width ),
00211 
00212       FT_FRAME_CHAR( horiBearingX ),
00213       FT_FRAME_CHAR( horiBearingY ),
00214       FT_FRAME_BYTE( horiAdvance ),
00215 
00216       FT_FRAME_CHAR( vertBearingX ),
00217       FT_FRAME_CHAR( vertBearingY ),
00218       FT_FRAME_BYTE( vertAdvance ),
00219     FT_FRAME_END
00220   };
00221 
00222 
00223   /*************************************************************************/
00224   /*                                                                       */
00225   /* <Function>                                                            */
00226   /*    Load_SBit_Const_Metrics                                            */
00227   /*                                                                       */
00228   /* <Description>                                                         */
00229   /*    Loads the metrics for `EBLC' index tables format 2 and 5.          */
00230   /*                                                                       */
00231   /* <Input>                                                               */
00232   /*    range  :: The target range.                                        */
00233   /*                                                                       */
00234   /*    stream :: The input stream.                                        */
00235   /*                                                                       */
00236   /* <Return>                                                              */
00237   /*    FreeType error code.  0 means success.                             */
00238   /*                                                                       */
00239   static FT_Error
00240   Load_SBit_Const_Metrics( TT_SBit_Range  range,
00241                            FT_Stream      stream )
00242   {
00243     FT_Error  error;
00244 
00245 
00246     if ( FT_READ_ULONG( range->image_size ) )
00247       return error;
00248 
00249     return FT_STREAM_READ_FIELDS( sbit_metrics_fields, &range->metrics );
00250   }
00251 
00252 
00253   /*************************************************************************/
00254   /*                                                                       */
00255   /* <Function>                                                            */
00256   /*    Load_SBit_Range_Codes                                              */
00257   /*                                                                       */
00258   /* <Description>                                                         */
00259   /*    Loads the range codes for `EBLC' index tables format 4 and 5.      */
00260   /*                                                                       */
00261   /* <Input>                                                               */
00262   /*    range        :: The target range.                                  */
00263   /*                                                                       */
00264   /*    stream       :: The input stream.                                  */
00265   /*                                                                       */
00266   /*    load_offsets :: A flag whether to load the glyph offset table.     */
00267   /*                                                                       */
00268   /* <Return>                                                              */
00269   /*    FreeType error code.  0 means success.                             */
00270   /*                                                                       */
00271   static FT_Error
00272   Load_SBit_Range_Codes( TT_SBit_Range  range,
00273                          FT_Stream      stream,
00274                          FT_Bool        load_offsets )
00275   {
00276     FT_Error   error;
00277     FT_ULong   count, n, size;
00278     FT_Memory  memory = stream->memory;
00279 
00280 
00281     if ( FT_READ_ULONG( count ) )
00282       goto Exit;
00283 
00284     range->num_glyphs = count;
00285 
00286     /* Allocate glyph offsets table if needed */
00287     if ( load_offsets )
00288     {
00289       if ( FT_NEW_ARRAY( range->glyph_offsets, count ) )
00290         goto Exit;
00291 
00292       size = count * 4L;
00293     }
00294     else
00295       size = count * 2L;
00296 
00297     /* Allocate glyph codes table and access frame */
00298     if ( FT_NEW_ARRAY ( range->glyph_codes, count ) ||
00299          FT_FRAME_ENTER( size )                     )
00300       goto Exit;
00301 
00302     for ( n = 0; n < count; n++ )
00303     {
00304       range->glyph_codes[n] = FT_GET_USHORT();
00305 
00306       if ( load_offsets )
00307         range->glyph_offsets[n] = (FT_ULong)range->image_offset +
00308                                   FT_GET_USHORT();
00309     }
00310 
00311     FT_FRAME_EXIT();
00312 
00313   Exit:
00314     return error;
00315   }
00316 
00317 
00318   /*************************************************************************/
00319   /*                                                                       */
00320   /* <Function>                                                            */
00321   /*    Load_SBit_Range                                                    */
00322   /*                                                                       */
00323   /* <Description>                                                         */
00324   /*    Loads a given `EBLC' index/range table.                            */
00325   /*                                                                       */
00326   /* <Input>                                                               */
00327   /*    range  :: The target range.                                        */
00328   /*                                                                       */
00329   /*    stream :: The input stream.                                        */
00330   /*                                                                       */
00331   /* <Return>                                                              */
00332   /*    FreeType error code.  0 means success.                             */
00333   /*                                                                       */
00334   static FT_Error
00335   Load_SBit_Range( TT_SBit_Range  range,
00336                    FT_Stream      stream )
00337   {
00338     FT_Error   error;
00339     FT_Memory  memory = stream->memory;
00340 
00341 
00342     switch( range->index_format )
00343     {
00344     case 1:   /* variable metrics with 4-byte offsets */
00345     case 3:   /* variable metrics with 2-byte offsets */
00346       {
00347         FT_ULong  num_glyphs, n;
00348         FT_Int    size_elem;
00349         FT_Bool   large = FT_BOOL( range->index_format == 1 );
00350 
00351 
00352 
00353         if ( range->last_glyph < range->first_glyph )
00354         {
00355           error = SFNT_Err_Invalid_File_Format;
00356           goto Exit;
00357         }
00358 
00359         num_glyphs        = range->last_glyph - range->first_glyph + 1L;
00360         range->num_glyphs = num_glyphs;
00361         num_glyphs++;                       /* XXX: BEWARE - see spec */
00362 
00363         size_elem = large ? 4 : 2;
00364 
00365         if ( FT_NEW_ARRAY( range->glyph_offsets, num_glyphs ) ||
00366              FT_FRAME_ENTER( num_glyphs * size_elem )         )
00367           goto Exit;
00368 
00369         for ( n = 0; n < num_glyphs; n++ )
00370           range->glyph_offsets[n] = (FT_ULong)( range->image_offset +
00371                                                 ( large ? FT_GET_ULONG()
00372                                                         : FT_GET_USHORT() ) );
00373         FT_FRAME_EXIT();
00374       }
00375       break;
00376 
00377     case 2:   /* all glyphs have identical metrics */
00378       error = Load_SBit_Const_Metrics( range, stream );
00379       break;
00380 
00381     case 4:
00382       error = Load_SBit_Range_Codes( range, stream, 1 );
00383       break;
00384 
00385     case 5:
00386       error = Load_SBit_Const_Metrics( range, stream );
00387       if ( !error )
00388         error = Load_SBit_Range_Codes( range, stream, 0 );
00389       break;
00390 
00391     default:
00392       error = SFNT_Err_Invalid_File_Format;
00393     }
00394 
00395   Exit:
00396     return error;
00397   }
00398 
00399 
00400   /*************************************************************************/
00401   /*                                                                       */
00402   /* <Function>                                                            */
00403   /*    tt_face_load_eblc                                                  */
00404   /*                                                                       */
00405   /* <Description>                                                         */
00406   /*    Loads the table of embedded bitmap sizes for this face.            */
00407   /*                                                                       */
00408   /* <Input>                                                               */
00409   /*    face   :: The target face object.                                  */
00410   /*                                                                       */
00411   /*    stream :: The input stream.                                        */
00412   /*                                                                       */
00413   /* <Return>                                                              */
00414   /*    FreeType error code.  0 means success.                             */
00415   /*                                                                       */
00416   FT_LOCAL_DEF( FT_Error )
00417   tt_face_load_eblc( TT_Face    face,
00418                      FT_Stream  stream )
00419   {
00420     FT_Error   error  = 0;
00421     FT_Memory  memory = stream->memory;
00422     FT_Fixed   version;
00423     FT_ULong   num_strikes;
00424     FT_ULong   table_base;
00425 
00426     static const FT_Frame_Field  sbit_line_metrics_fields[] =
00427     {
00428 #undef  FT_STRUCTURE
00429 #define FT_STRUCTURE  TT_SBit_LineMetricsRec
00430 
00431       /* no FT_FRAME_START */
00432         FT_FRAME_CHAR( ascender ),
00433         FT_FRAME_CHAR( descender ),
00434         FT_FRAME_BYTE( max_width ),
00435 
00436         FT_FRAME_CHAR( caret_slope_numerator ),
00437         FT_FRAME_CHAR( caret_slope_denominator ),
00438         FT_FRAME_CHAR( caret_offset ),
00439 
00440         FT_FRAME_CHAR( min_origin_SB ),
00441         FT_FRAME_CHAR( min_advance_SB ),
00442         FT_FRAME_CHAR( max_before_BL ),
00443         FT_FRAME_CHAR( min_after_BL ),
00444         FT_FRAME_CHAR( pads[0] ),
00445         FT_FRAME_CHAR( pads[1] ),
00446       FT_FRAME_END
00447     };
00448 
00449     static const FT_Frame_Field  strike_start_fields[] =
00450     {
00451 #undef  FT_STRUCTURE
00452 #define FT_STRUCTURE  TT_SBit_StrikeRec
00453 
00454       /* no FT_FRAME_START */
00455         FT_FRAME_ULONG( ranges_offset ),
00456         FT_FRAME_SKIP_LONG,
00457         FT_FRAME_ULONG( num_ranges ),
00458         FT_FRAME_ULONG( color_ref ),
00459       FT_FRAME_END
00460     };
00461 
00462     static const FT_Frame_Field  strike_end_fields[] =
00463     {
00464       /* no FT_FRAME_START */
00465         FT_FRAME_USHORT( start_glyph ),
00466         FT_FRAME_USHORT( end_glyph ),
00467         FT_FRAME_BYTE  ( x_ppem ),
00468         FT_FRAME_BYTE  ( y_ppem ),
00469         FT_FRAME_BYTE  ( bit_depth ),
00470         FT_FRAME_CHAR  ( flags ),
00471       FT_FRAME_END
00472     };
00473 
00474 
00475     face->num_sbit_strikes = 0;
00476 
00477     /* this table is optional */
00478     error = face->goto_table( face, TTAG_EBLC, stream, 0 );
00479     if ( error )
00480       error = face->goto_table( face, TTAG_bloc, stream, 0 );
00481     if ( error )
00482       goto Exit;
00483 
00484     table_base = FT_STREAM_POS();
00485     if ( FT_FRAME_ENTER( 8L ) )
00486       goto Exit;
00487 
00488     version     = FT_GET_LONG();
00489     num_strikes = FT_GET_ULONG();
00490 
00491     FT_FRAME_EXIT();
00492 
00493     /* check version number and strike count */
00494     if ( version     != 0x00020000L ||
00495          num_strikes >= 0x10000L    )
00496     {
00497       FT_ERROR(( "tt_face_load_sbit_strikes: invalid table version\n" ));
00498       error = SFNT_Err_Invalid_File_Format;
00499 
00500       goto Exit;
00501     }
00502 
00503     /* allocate the strikes table */
00504     if ( FT_NEW_ARRAY( face->sbit_strikes, num_strikes ) )
00505       goto Exit;
00506 
00507     face->num_sbit_strikes = num_strikes;
00508 
00509     /* now read each strike table separately */
00510     {
00511       TT_SBit_Strike  strike = face->sbit_strikes;
00512       FT_ULong        count  = num_strikes;
00513 
00514 
00515       if ( FT_FRAME_ENTER( 48L * num_strikes ) )
00516         goto Exit;
00517 
00518       while ( count > 0 )
00519       {
00520         if ( FT_STREAM_READ_FIELDS( strike_start_fields, strike )             ||
00521              FT_STREAM_READ_FIELDS( sbit_line_metrics_fields, &strike->hori ) ||
00522              FT_STREAM_READ_FIELDS( sbit_line_metrics_fields, &strike->vert ) ||
00523              FT_STREAM_READ_FIELDS( strike_end_fields, strike )               )
00524           break;
00525 
00526         count--;
00527         strike++;
00528       }
00529 
00530       FT_FRAME_EXIT();
00531     }
00532 
00533     /* allocate the index ranges for each strike table */
00534     {
00535       TT_SBit_Strike  strike = face->sbit_strikes;
00536       FT_ULong        count  = num_strikes;
00537 
00538 
00539       while ( count > 0 )
00540       {
00541         TT_SBit_Range  range;
00542         FT_ULong       count2 = strike->num_ranges;
00543 
00544 
00545         /* read each range */
00546         if ( FT_STREAM_SEEK( table_base + strike->ranges_offset ) ||
00547              FT_FRAME_ENTER( strike->num_ranges * 8L )            )
00548           goto Exit;
00549 
00550         if ( FT_NEW_ARRAY( strike->sbit_ranges, strike->num_ranges ) )
00551           goto Exit;
00552 
00553         range = strike->sbit_ranges;
00554         while ( count2 > 0 )
00555         {
00556           range->first_glyph  = FT_GET_USHORT();
00557           range->last_glyph   = FT_GET_USHORT();
00558           range->table_offset = table_base + strike->ranges_offset +
00559                                   FT_GET_ULONG();
00560           count2--;
00561           range++;
00562         }
00563 
00564         FT_FRAME_EXIT();
00565 
00566         /* Now, read each index table */
00567         count2 = strike->num_ranges;
00568         range  = strike->sbit_ranges;
00569         while ( count2 > 0 )
00570         {
00571           /* Read the header */
00572           if ( FT_STREAM_SEEK( range->table_offset ) ||
00573                FT_FRAME_ENTER( 8L )                  )
00574             goto Exit;
00575 
00576           range->index_format = FT_GET_USHORT();
00577           range->image_format = FT_GET_USHORT();
00578           range->image_offset = FT_GET_ULONG();
00579 
00580           FT_FRAME_EXIT();
00581 
00582           error = Load_SBit_Range( range, stream );
00583           if ( error )
00584             goto Exit;
00585 
00586           count2--;
00587           range++;
00588         }
00589 
00590         count--;
00591         strike++;
00592       }
00593     }
00594 
00595   Exit:
00596     return error;
00597   }
00598 
00599 
00600   /*************************************************************************/
00601   /*                                                                       */
00602   /* <Function>                                                            */
00603   /*    tt_face_free_eblc                                                  */
00604   /*                                                                       */
00605   /* <Description>                                                         */
00606   /*    Releases the embedded bitmap tables.                               */
00607   /*                                                                       */
00608   /* <Input>                                                               */
00609   /*    face :: The target face object.                                    */
00610   /*                                                                       */
00611   FT_LOCAL_DEF( void )
00612   tt_face_free_eblc( TT_Face  face )
00613   {
00614     FT_Memory       memory       = face->root.memory;
00615     TT_SBit_Strike  strike       = face->sbit_strikes;
00616     TT_SBit_Strike  strike_limit = strike + face->num_sbit_strikes;
00617 
00618 
00619     if ( strike )
00620     {
00621       for ( ; strike < strike_limit; strike++ )
00622       {
00623         TT_SBit_Range  range       = strike->sbit_ranges;
00624         TT_SBit_Range  range_limit = range + strike->num_ranges;
00625 
00626 
00627         if ( range )
00628         {
00629           for ( ; range < range_limit; range++ )
00630           {
00631             /* release the glyph offsets and codes tables */
00632             /* where appropriate                          */
00633             FT_FREE( range->glyph_offsets );
00634             FT_FREE( range->glyph_codes );
00635           }
00636         }
00637         FT_FREE( strike->sbit_ranges );
00638         strike->num_ranges = 0;
00639       }
00640       FT_FREE( face->sbit_strikes );
00641     }
00642     face->num_sbit_strikes = 0;
00643   }
00644 
00645 
00646   FT_LOCAL_DEF( FT_Error )
00647   tt_face_set_sbit_strike( TT_Face          face,
00648                            FT_Size_Request  req,
00649                            FT_ULong*        astrike_index )
00650   {
00651     return FT_Match_Size( (FT_Face)face, req, 0, astrike_index );
00652   }
00653 
00654 
00655   FT_LOCAL_DEF( FT_Error )
00656   tt_face_load_strike_metrics( TT_Face           face,
00657                                FT_ULong          strike_index,
00658                                FT_Size_Metrics*  metrics )
00659   {
00660     TT_SBit_Strike  strike;
00661 
00662 
00663     if ( strike_index >= face->num_sbit_strikes )
00664       return SFNT_Err_Invalid_Argument;
00665 
00666     strike = face->sbit_strikes + strike_index;
00667 
00668     metrics->x_ppem = strike->x_ppem;
00669     metrics->y_ppem = strike->y_ppem;
00670 
00671     metrics->ascender  = strike->hori.ascender << 6;
00672     metrics->descender = strike->hori.descender << 6;
00673 
00674     /* XXX: Is this correct? */
00675     metrics->max_advance = ( strike->hori.min_origin_SB  +
00676                              strike->hori.max_width      +
00677                              strike->hori.min_advance_SB ) << 6;
00678 
00679     metrics->height = metrics->ascender - metrics->descender;
00680 
00681     return SFNT_Err_Ok;
00682   }
00683 
00684 
00685   /*************************************************************************/
00686   /*                                                                       */
00687   /* <Function>                                                            */
00688   /*    find_sbit_range                                                    */
00689   /*                                                                       */
00690   /* <Description>                                                         */
00691   /*    Scans a given strike's ranges and return, for a given glyph        */
00692   /*    index, the corresponding sbit range, and `EBDT' offset.            */
00693   /*                                                                       */
00694   /* <Input>                                                               */
00695   /*    glyph_index   :: The glyph index.                                  */
00696   /*                                                                       */
00697   /*    strike        :: The source/current sbit strike.                   */
00698   /*                                                                       */
00699   /* <Output>                                                              */
00700   /*    arange        :: The sbit range containing the glyph index.        */
00701   /*                                                                       */
00702   /*    aglyph_offset :: The offset of the glyph data in `EBDT' table.     */
00703   /*                                                                       */
00704   /* <Return>                                                              */
00705   /*    FreeType error code.  0 means the glyph index was found.           */
00706   /*                                                                       */
00707   static FT_Error
00708   find_sbit_range( FT_UInt          glyph_index,
00709                    TT_SBit_Strike   strike,
00710                    TT_SBit_Range   *arange,
00711                    FT_ULong        *aglyph_offset )
00712   {
00713     TT_SBit_RangeRec  *range, *range_limit;
00714 
00715 
00716     /* check whether the glyph index is within this strike's */
00717     /* glyph range                                           */
00718     if ( glyph_index < (FT_UInt)strike->start_glyph ||
00719          glyph_index > (FT_UInt)strike->end_glyph   )
00720       goto Fail;
00721 
00722     /* scan all ranges in strike */
00723     range       = strike->sbit_ranges;
00724     range_limit = range + strike->num_ranges;
00725     if ( !range )
00726       goto Fail;
00727 
00728     for ( ; range < range_limit; range++ )
00729     {
00730       if ( glyph_index >= (FT_UInt)range->first_glyph &&
00731            glyph_index <= (FT_UInt)range->last_glyph  )
00732       {
00733         FT_UShort  delta = (FT_UShort)( glyph_index - range->first_glyph );
00734 
00735 
00736         switch ( range->index_format )
00737         {
00738         case 1:
00739         case 3:
00740           *aglyph_offset = range->glyph_offsets[delta];
00741           break;
00742 
00743         case 2:
00744           *aglyph_offset = range->image_offset +
00745                            range->image_size * delta;
00746           break;
00747 
00748         case 4:
00749         case 5:
00750           {
00751             FT_ULong  n;
00752 
00753 
00754             for ( n = 0; n < range->num_glyphs; n++ )
00755             {
00756               if ( (FT_UInt)range->glyph_codes[n] == glyph_index )
00757               {
00758                 if ( range->index_format == 4 )
00759                   *aglyph_offset = range->glyph_offsets[n];
00760                 else
00761                   *aglyph_offset = range->image_offset +
00762                                    n * range->image_size;
00763                 goto Found;
00764               }
00765             }
00766           }
00767 
00768         /* fall-through */
00769         default:
00770           goto Fail;
00771         }
00772 
00773       Found:
00774         /* return successfully! */
00775         *arange  = range;
00776         return SFNT_Err_Ok;
00777       }
00778     }
00779 
00780   Fail:
00781     *arange        = 0;
00782     *aglyph_offset = 0;
00783 
00784     return SFNT_Err_Invalid_Argument;
00785   }
00786 
00787 
00788   /*************************************************************************/
00789   /*                                                                       */
00790   /* <Function>                                                            */
00791   /*    tt_find_sbit_image                                                 */
00792   /*                                                                       */
00793   /* <Description>                                                         */
00794   /*    Checks whether an embedded bitmap (an `sbit') exists for a given   */
00795   /*    glyph, at a given strike.                                          */
00796   /*                                                                       */
00797   /* <Input>                                                               */
00798   /*    face          :: The target face object.                           */
00799   /*                                                                       */
00800   /*    glyph_index   :: The glyph index.                                  */
00801   /*                                                                       */
00802   /*    strike_index  :: The current strike index.                         */
00803   /*                                                                       */
00804   /* <Output>                                                              */
00805   /*    arange        :: The SBit range containing the glyph index.        */
00806   /*                                                                       */
00807   /*    astrike       :: The SBit strike containing the glyph index.       */
00808   /*                                                                       */
00809   /*    aglyph_offset :: The offset of the glyph data in `EBDT' table.     */
00810   /*                                                                       */
00811   /* <Return>                                                              */
00812   /*    FreeType error code.  0 means success.  Returns                    */
00813   /*    SFNT_Err_Invalid_Argument if no sbit exists for the requested      */
00814   /*    glyph.                                                             */
00815   /*                                                                       */
00816   FT_LOCAL( FT_Error )
00817   tt_find_sbit_image( TT_Face          face,
00818                       FT_UInt          glyph_index,
00819                       FT_ULong         strike_index,
00820                       TT_SBit_Range   *arange,
00821                       TT_SBit_Strike  *astrike,
00822                       FT_ULong        *aglyph_offset )
00823   {
00824     FT_Error        error;
00825     TT_SBit_Strike  strike;
00826 
00827 
00828     if ( !face->sbit_strikes                        ||
00829          ( face->num_sbit_strikes <= strike_index ) )
00830       goto Fail;
00831 
00832     strike = &face->sbit_strikes[strike_index];
00833 
00834     error = find_sbit_range( glyph_index, strike,
00835                              arange, aglyph_offset );
00836     if ( error )
00837       goto Fail;
00838 
00839     *astrike = strike;
00840 
00841     return SFNT_Err_Ok;
00842 
00843   Fail:
00844     /* no embedded bitmap for this glyph in face */
00845     *arange        = 0;
00846     *astrike       = 0;
00847     *aglyph_offset = 0;
00848 
00849     return SFNT_Err_Invalid_Argument;
00850   }
00851 
00852 
00853   /*************************************************************************/
00854   /*                                                                       */
00855   /* <Function>                                                            */
00856   /*    tt_load_sbit_metrics                                               */
00857   /*                                                                       */
00858   /* <Description>                                                         */
00859   /*    Gets the big metrics for a given SBit.                             */
00860   /*                                                                       */
00861   /* <Input>                                                               */
00862   /*    stream      :: The input stream.                                   */
00863   /*                                                                       */
00864   /*    range       :: The SBit range containing the glyph.                */
00865   /*                                                                       */
00866   /* <Output>                                                              */
00867   /*    big_metrics :: A big SBit metrics structure for the glyph.         */
00868   /*                                                                       */
00869   /* <Return>                                                              */
00870   /*    FreeType error code.  0 means success.                             */
00871   /*                                                                       */
00872   /* <Note>                                                                */
00873   /*    The stream cursor must be positioned at the glyph's offset within  */
00874   /*    the `EBDT' table before the call.                                  */
00875   /*                                                                       */
00876   /*    If the image format uses variable metrics, the stream cursor is    */
00877   /*    positioned just after the metrics header in the `EBDT' table on    */
00878   /*    function exit.                                                     */
00879   /*                                                                       */
00880   FT_LOCAL( FT_Error )
00881   tt_load_sbit_metrics( FT_Stream        stream,
00882                         TT_SBit_Range    range,
00883                         TT_SBit_Metrics  metrics )
00884   {
00885     FT_Error  error = SFNT_Err_Ok;
00886 
00887 
00888     switch ( range->image_format )
00889     {
00890     case 1:
00891     case 2:
00892     case 8:
00893       /* variable small metrics */
00894       {
00895         TT_SBit_SmallMetricsRec  smetrics;
00896 
00897         static const FT_Frame_Field  sbit_small_metrics_fields[] =
00898         {
00899 #undef  FT_STRUCTURE
00900 #define FT_STRUCTURE  TT_SBit_SmallMetricsRec
00901 
00902           FT_FRAME_START( 5 ),
00903             FT_FRAME_BYTE( height ),
00904             FT_FRAME_BYTE( width ),
00905             FT_FRAME_CHAR( bearingX ),
00906             FT_FRAME_CHAR( bearingY ),
00907             FT_FRAME_BYTE( advance ),
00908           FT_FRAME_END
00909         };
00910 
00911 
00912         /* read small metrics */
00913         if ( FT_STREAM_READ_FIELDS( sbit_small_metrics_fields, &smetrics ) )
00914           goto Exit;
00915 
00916         /* convert it to a big metrics */
00917         metrics->height       = smetrics.height;
00918         metrics->width        = smetrics.width;
00919         metrics->horiBearingX = smetrics.bearingX;
00920         metrics->horiBearingY = smetrics.bearingY;
00921         metrics->horiAdvance  = smetrics.advance;
00922 
00923         /* these metrics are made up at a higher level when */
00924         /* needed.                                          */
00925         metrics->vertBearingX = 0;
00926         metrics->vertBearingY = 0;
00927         metrics->vertAdvance  = 0;
00928       }
00929       break;
00930 
00931     case 6:
00932     case 7:
00933     case 9:
00934       /* variable big metrics */
00935       if ( FT_STREAM_READ_FIELDS( sbit_metrics_fields, metrics ) )
00936         goto Exit;
00937       break;
00938 
00939     case 5:
00940     default:  /* constant metrics */
00941       if ( range->index_format == 2 || range->index_format == 5 )
00942         *metrics = range->metrics;
00943       else
00944         return SFNT_Err_Invalid_File_Format;
00945    }
00946 
00947   Exit:
00948     return error;
00949   }
00950 
00951 
00952   /*************************************************************************/
00953   /*                                                                       */
00954   /* <Function>                                                            */
00955   /*    crop_bitmap                                                        */
00956   /*                                                                       */
00957   /* <Description>                                                         */
00958   /*    Crops a bitmap to its tightest bounding box, and adjusts its       */
00959   /*    metrics.                                                           */
00960   /*                                                                       */
00961   /* <InOut>                                                               */
00962   /*    map     :: The bitmap.                                             */
00963   /*                                                                       */
00964   /*    metrics :: The corresponding metrics structure.                    */
00965   /*                                                                       */
00966   static void
00967   crop_bitmap( FT_Bitmap*       map,
00968                TT_SBit_Metrics  metrics )
00969   {
00970     /***********************************************************************/
00971     /*                                                                     */
00972     /* In this situation, some bounding boxes of embedded bitmaps are too  */
00973     /* large.  We need to crop it to a reasonable size.                    */
00974     /*                                                                     */
00975     /*      ---------                                                      */
00976     /*      |       |                -----                                 */
00977     /*      |  ***  |                |***|                                 */
00978     /*      |   *   |                | * |                                 */
00979     /*      |   *   |    ------>     | * |                                 */
00980     /*      |   *   |                | * |                                 */
00981     /*      |   *   |                | * |                                 */
00982     /*      |  ***  |                |***|                                 */
00983     /*      ---------                -----                                 */
00984     /*                                                                     */
00985     /***********************************************************************/
00986 
00987     FT_Int    rows, count;
00988     FT_Long   line_len;
00989     FT_Byte*  line;
00990 
00991 
00992     /***********************************************************************/
00993     /*                                                                     */
00994     /* first of all, check the top-most lines of the bitmap, and remove    */
00995     /* them if they're empty.                                              */
00996     /*                                                                     */
00997     {
00998       line     = (FT_Byte*)map->buffer;
00999       rows     = map->rows;
01000       line_len = map->pitch;
01001 
01002 
01003       for ( count = 0; count < rows; count++ )
01004       {
01005         FT_Byte*  cur   = line;
01006         FT_Byte*  limit = line + line_len;
01007 
01008 
01009         for ( ; cur < limit; cur++ )
01010           if ( cur[0] )
01011             goto Found_Top;
01012 
01013         /* the current line was empty - skip to next one */
01014         line  = limit;
01015       }
01016 
01017     Found_Top:
01018       /* check that we have at least one filled line */
01019       if ( count >= rows )
01020         goto Empty_Bitmap;
01021 
01022       /* now, crop the empty upper lines */
01023       if ( count > 0 )
01024       {
01025         line = (FT_Byte*)map->buffer;
01026 
01027         FT_MEM_MOVE( line, line + count * line_len,
01028                      ( rows - count ) * line_len );
01029 
01030         metrics->height       = (FT_Byte)( metrics->height - count );
01031         metrics->horiBearingY = (FT_Char)( metrics->horiBearingY - count );
01032         metrics->vertBearingY = (FT_Char)( metrics->vertBearingY - count );
01033 
01034         map->rows -= count;
01035         rows      -= count;
01036       }
01037     }
01038 
01039     /***********************************************************************/
01040     /*                                                                     */
01041     /* second, crop the lower lines                                        */
01042     /*                                                                     */
01043     {
01044       line = (FT_Byte*)map->buffer + ( rows - 1 ) * line_len;
01045 
01046       for ( count = 0; count < rows; count++ )
01047       {
01048         FT_Byte*  cur   = line;
01049         FT_Byte*  limit = line + line_len;
01050 
01051 
01052         for ( ; cur < limit; cur++ )
01053           if ( cur[0] )
01054             goto Found_Bottom;
01055 
01056         /* the current line was empty - skip to previous one */
01057         line -= line_len;
01058       }
01059 
01060     Found_Bottom:
01061       if ( count > 0 )
01062       {
01063         metrics->height  = (FT_Byte)( metrics->height - count );
01064         rows            -= count;
01065         map->rows       -= count;
01066       }
01067     }
01068 
01069     /***********************************************************************/
01070     /*                                                                     */
01071     /* third, get rid of the space on the left side of the glyph           */
01072     /*                                                                     */
01073     do
01074     {
01075       FT_Byte*  limit;
01076 
01077 
01078       line  = (FT_Byte*)map->buffer;
01079       limit = line + rows * line_len;
01080 
01081       for ( ; line < limit; line += line_len )
01082         if ( line[0] & 0x80 )
01083           goto Found_Left;
01084 
01085       /* shift the whole glyph one pixel to the left */
01086       line  = (FT_Byte*)map->buffer;
01087       limit = line + rows * line_len;
01088 
01089       for ( ; line < limit; line += line_len )
01090       {
01091         FT_Int    n, width = map->width;
01092         FT_Byte   old;
01093         FT_Byte*  cur = line;
01094 
01095 
01096         old = (FT_Byte)(cur[0] << 1);
01097         for ( n = 8; n < width; n += 8 )
01098         {
01099           FT_Byte  val;
01100 
01101 
01102           val    = cur[1];
01103           cur[0] = (FT_Byte)( old | ( val >> 7 ) );
01104           old    = (FT_Byte)( val << 1 );
01105           cur++;
01106         }
01107         cur[0] = old;
01108       }
01109 
01110       map->width--;
01111       metrics->horiBearingX++;
01112       metrics->vertBearingX++;
01113       metrics->width--;
01114 
01115     } while ( map->width > 0 );
01116 
01117   Found_Left:
01118 
01119     /***********************************************************************/
01120     /*                                                                     */
01121     /* finally, crop the bitmap width to get rid of the space on the right */
01122     /* side of the glyph.                                                  */
01123     /*                                                                     */
01124     do
01125     {
01126       FT_Int    right = map->width - 1;
01127       FT_Byte*  limit;
01128       FT_Byte   mask;
01129 
01130 
01131       line  = (FT_Byte*)map->buffer + ( right >> 3 );
01132       limit = line + rows * line_len;
01133       mask  = (FT_Byte)( 0x80 >> ( right & 7 ) );
01134 
01135       for ( ; line < limit; line += line_len )
01136         if ( line[0] & mask )
01137           goto Found_Right;
01138 
01139       /* crop the whole glyph to the right */
01140       map->width--;
01141       metrics->width--;
01142 
01143     } while ( map->width > 0 );
01144 
01145   Found_Right:
01146     /* all right, the bitmap was cropped */
01147     return;
01148 
01149   Empty_Bitmap:
01150     map->width      = 0;
01151     map->rows       = 0;
01152     map->pitch      = 0;
01153     map->pixel_mode = FT_PIXEL_MODE_MONO;
01154   }
01155 
01156 
01157   static FT_Error
01158   Load_SBit_Single( FT_Bitmap*       map,
01159                     FT_Int           x_offset,
01160                     FT_Int           y_offset,
01161                     FT_Int           pix_bits,
01162                     FT_UShort        image_format,
01163                     TT_SBit_Metrics  metrics,
01164                     FT_Stream        stream )
01165   {
01166     FT_Error  error;
01167 
01168 
01169     /* check that the source bitmap fits into the target pixmap */
01170     if ( x_offset < 0 || x_offset + metrics->width  > map->width ||
01171          y_offset < 0 || y_offset + metrics->height > map->rows  )
01172     {
01173       error = SFNT_Err_Invalid_Argument;
01174 
01175       goto Exit;
01176     }
01177 
01178     {
01179       FT_Int   glyph_width  = metrics->width;
01180       FT_Int   glyph_height = metrics->height;
01181       FT_Int   glyph_size;
01182       FT_Int   line_bits    = pix_bits * glyph_width;
01183       FT_Bool  pad_bytes    = 0;
01184 
01185 
01186       /* compute size of glyph image */
01187       switch ( image_format )
01188       {
01189       case 1:  /* byte-padded formats */
01190       case 6:
01191         {
01192           FT_Int  line_length;
01193 
01194 
01195           switch ( pix_bits )
01196           {
01197           case 1:
01198             line_length = ( glyph_width + 7 ) >> 3;
01199             break;
01200           case 2:
01201             line_length = ( glyph_width + 3 ) >> 2;
01202             break;
01203           case 4:
01204             line_length = ( glyph_width + 1 ) >> 1;
01205             break;
01206           default:
01207             line_length =   glyph_width;
01208           }
01209 
01210           glyph_size = glyph_height * line_length;
01211           pad_bytes  = 1;
01212         }
01213         break;
01214 
01215       case 2:
01216       case 5:
01217       case 7:
01218         line_bits  =   glyph_width  * pix_bits;
01219         glyph_size = ( glyph_height * line_bits + 7 ) >> 3;
01220         break;
01221 
01222       default:  /* invalid format */
01223         return SFNT_Err_Invalid_File_Format;
01224       }
01225 
01226       /* Now read data and draw glyph into target pixmap       */
01227       if ( FT_FRAME_ENTER( glyph_size ) )
01228         goto Exit;
01229 
01230       /* don't forget to multiply `x_offset' by `map->pix_bits' as */
01231       /* the sbit blitter doesn't make a difference between pixmap */
01232       /* depths.                                                   */
01233       blit_sbit( map, (FT_Byte*)stream->cursor, line_bits, pad_bytes,
01234                  x_offset * pix_bits, y_offset, metrics->height );
01235 
01236       FT_FRAME_EXIT();
01237     }
01238 
01239   Exit:
01240     return error;
01241   }
01242 
01243 
01244   static FT_Error
01245   Load_SBit_Image( TT_SBit_Strike   strike,
01246                    TT_SBit_Range    range,
01247                    FT_ULong         ebdt_pos,
01248                    FT_ULong         glyph_offset,
01249                    FT_GlyphSlot     slot,
01250                    FT_Int           x_offset,
01251                    FT_Int           y_offset,
01252                    FT_Stream        stream,
01253                    TT_SBit_Metrics  metrics,
01254                    FT_Int           depth )
01255   {
01256     FT_Memory   memory = stream->memory;
01257     FT_Bitmap*  map    = &slot->bitmap;
01258     FT_Error    error;
01259 
01260 
01261     /* place stream at beginning of glyph data and read metrics */
01262     if ( FT_STREAM_SEEK( ebdt_pos + glyph_offset ) )
01263       goto Exit;
01264 
01265     error = tt_load_sbit_metrics( stream, range, metrics );
01266     if ( error )
01267       goto Exit;
01268 
01269     /* This function is recursive.  At the top-level call, we  */
01270     /* compute the dimensions of the higher-level glyph to     */
01271     /* allocate the final pixmap buffer.                       */
01272     if ( depth == 0 )
01273     {
01274       FT_Long  size;
01275 
01276 
01277       map->width = metrics->width;
01278       map->rows  = metrics->height;
01279 
01280       switch ( strike->bit_depth )
01281       {
01282       case 1:
01283         map->pixel_mode = FT_PIXEL_MODE_MONO;
01284         map->pitch      = ( map->width + 7 ) >> 3;
01285         break;
01286 
01287       case 2:
01288         map->pixel_mode = FT_PIXEL_MODE_GRAY2;
01289         map->pitch      = ( map->width + 3 ) >> 2;
01290         break;
01291 
01292       case 4:
01293         map->pixel_mode = FT_PIXEL_MODE_GRAY4;
01294         map->pitch      = ( map->width + 1 ) >> 1;
01295         break;
01296 
01297       case 8:
01298         map->pixel_mode = FT_PIXEL_MODE_GRAY;
01299         map->pitch      = map->width;
01300         break;
01301 
01302       default:
01303         return SFNT_Err_Invalid_File_Format;
01304       }
01305 
01306       size = map->rows * map->pitch;
01307 
01308       /* check that there is no empty image */
01309       if ( size == 0 )
01310         goto Exit;     /* exit successfully! */
01311 
01312       error = ft_glyphslot_alloc_bitmap( slot, size );
01313       if (error)
01314         goto Exit;
01315     }
01316 
01317     switch ( range->image_format )
01318     {
01319     case 1:  /* single sbit image - load it */
01320     case 2:
01321     case 5:
01322     case 6:
01323     case 7:
01324       return Load_SBit_Single( map, x_offset, y_offset, strike->bit_depth,
01325                                range->image_format, metrics, stream );
01326 
01327     case 8:  /* compound format */
01328       if ( FT_STREAM_SKIP( 1L ) )
01329       {
01330         error = SFNT_Err_Invalid_Stream_Skip;
01331         goto Exit;
01332       }
01333       /* fallthrough */
01334 
01335     case 9:
01336       break;
01337 
01338     default: /* invalid image format */
01339       return SFNT_Err_Invalid_File_Format;
01340     }
01341 
01342     /* All right, we have a compound format.  First of all, read */
01343     /* the array of elements.                                    */
01344     {
01345       TT_SBit_Component  components;
01346       TT_SBit_Component  comp;
01347       FT_UShort          num_components, count;
01348 
01349 
01350       if ( FT_READ_USHORT( num_components )           ||
01351            FT_NEW_ARRAY( components, num_components ) )
01352         goto Exit;
01353 
01354       count = num_components;
01355 
01356       if ( FT_FRAME_ENTER( 4L * num_components ) )
01357         goto Fail_Memory;
01358 
01359       for ( comp = components; count > 0; count--, comp++ )
01360       {
01361         comp->glyph_code = FT_GET_USHORT();
01362         comp->x_offset   = FT_GET_CHAR();
01363         comp->y_offset   = FT_GET_CHAR();
01364       }
01365 
01366       FT_FRAME_EXIT();
01367 
01368       /* Now recursively load each element glyph */
01369       count = num_components;
01370       comp  = components;
01371       for ( ; count > 0; count--, comp++ )
01372       {
01373         TT_SBit_Range       elem_range;
01374         TT_SBit_MetricsRec  elem_metrics;
01375         FT_ULong            elem_offset;
01376 
01377 
01378         /* find the range for this element */
01379         error = find_sbit_range( comp->glyph_code,
01380                                  strike,
01381                                  &elem_range,
01382                                  &elem_offset );
01383         if ( error )
01384           goto Fail_Memory;
01385 
01386         /* now load the element, recursively */
01387         error = Load_SBit_Image( strike,
01388                                  elem_range,
01389                                  ebdt_pos,
01390                                  elem_offset,
01391                                  slot,
01392                                  x_offset + comp->x_offset,
01393                                  y_offset + comp->y_offset,
01394                                  stream,
01395                                  &elem_metrics,
01396                                  depth + 1 );
01397         if ( error )
01398           goto Fail_Memory;
01399       }
01400 
01401     Fail_Memory:
01402       FT_FREE( components );
01403     }
01404 
01405   Exit:
01406     return error;
01407   }
01408 
01409 
01410   /*************************************************************************/
01411   /*                                                                       */
01412   /* <Function>                                                            */
01413   /*    tt_face_load_sbit_image                                            */
01414   /*                                                                       */
01415   /* <Description>                                                         */
01416   /*    Loads a given glyph sbit image from the font resource.  This also  */
01417   /*    returns its metrics.                                               */
01418   /*                                                                       */
01419   /* <Input>                                                               */
01420   /*    face         :: The target face object.                            */
01421   /*                                                                       */
01422   /*    strike_index :: The current strike index.                          */
01423   /*                                                                       */
01424   /*    glyph_index  :: The current glyph index.                           */
01425   /*                                                                       */
01426   /*    load_flags   :: The glyph load flags (the code checks for the flag */
01427   /*                    FT_LOAD_CROP_BITMAP).                              */
01428   /*                                                                       */
01429   /*    stream       :: The input stream.                                  */
01430   /*                                                                       */
01431   /* <Output>                                                              */
01432   /*    map          :: The target pixmap.                                 */
01433   /*                                                                       */
01434   /*    metrics      :: A big sbit metrics structure for the glyph image.  */
01435   /*                                                                       */
01436   /* <Return>                                                              */
01437   /*    FreeType error code.  0 means success.  Returns an error if no     */
01438   /*    glyph sbit exists for the index.                                   */
01439   /*                                                                       */
01440   /*  <Note>                                                               */
01441   /*    The `map.buffer' field is always freed before the glyph is loaded. */
01442   /*                                                                       */
01443   FT_LOCAL_DEF( FT_Error )
01444   tt_face_load_sbit_image( TT_Face              face,
01445                            FT_ULong             strike_index,
01446                            FT_UInt              glyph_index,
01447                            FT_UInt              load_flags,
01448                            FT_Stream            stream,
01449                            FT_Bitmap           *map,
01450                            TT_SBit_MetricsRec  *metrics )
01451   {
01452     FT_Error        error;
01453     FT_ULong        ebdt_pos, glyph_offset;
01454 
01455     TT_SBit_Strike  strike;
01456     TT_SBit_Range   range;
01457 
01458 
01459     /* Check whether there is a glyph sbit for the current index */
01460     error = tt_find_sbit_image( face, glyph_index, strike_index,
01461                                 &range, &strike, &glyph_offset );
01462     if ( error )
01463       goto Exit;
01464 
01465     /* now, find the location of the `EBDT' table in */
01466     /* the font file                                 */
01467     error = face->goto_table( face, TTAG_EBDT, stream, 0 );
01468     if ( error )
01469       error = face->goto_table( face, TTAG_bdat, stream, 0 );
01470     if ( error )
01471       goto Exit;
01472 
01473     ebdt_pos = FT_STREAM_POS();
01474 
01475     error = Load_SBit_Image( strike, range, ebdt_pos, glyph_offset,
01476                              face->root.glyph, 0, 0, stream, metrics, 0 );
01477     if ( error )
01478       goto Exit;
01479 
01480     /* setup vertical metrics if needed */
01481     if ( strike->flags & 1 )
01482     {
01483       /* in case of a horizontal strike only */
01484       FT_Int  advance;
01485 
01486 
01487       advance = strike->hori.ascender - strike->hori.descender;
01488 
01489       /* some heuristic values */
01490 
01491       metrics->vertBearingX = (FT_Char)(-metrics->width / 2 );
01492       metrics->vertBearingY = (FT_Char)( ( advance - metrics->height ) / 2 );
01493       metrics->vertAdvance  = (FT_Char)( advance * 12 / 10 );
01494     }
01495 
01496     /* Crop the bitmap now, unless specified otherwise */
01497     if ( load_flags & FT_LOAD_CROP_BITMAP )
01498       crop_bitmap( map, metrics );
01499 
01500   Exit:
01501     return error;
01502   }
01503 
01504 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
01505 
01506 
01507 /* END */

Generated on Tue Jul 5 14:13:51 2011 for ROOT_528-00b_version by  doxygen 1.5.1