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