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