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