ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

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

Generated on Sun May 27 2012 04:34:02 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.