The BIG graph update
[rrdtool.git] / libraries / freetype-2.0.5 / ttsbit.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  ttsbit.c                                                               */
4 /*                                                                         */
5 /*    TrueType and OpenType embedded bitmap support (body).                */
6 /*                                                                         */
7 /*  Copyright 1996-2001 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)*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] |= val >> shift;
135               cur[1] |= 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)*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] |= val >> shift;
168
169         if ( count > space )
170           cur[1] |= 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_Metrics
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 ( READ_ULong( range->image_size ) )
232       return error;
233
234     return 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 ( 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 ( ALLOC_ARRAY( range->glyph_offsets, count, FT_ULong ) )
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 ( ALLOC_ARRAY ( range->glyph_codes, count, FT_UShort ) ||
284          ACCESS_Frame( size )                                 )
285       goto Exit;
286
287     for ( n = 0; n < count; n++ )
288     {
289       range->glyph_codes[n] = GET_UShort();
290
291       if ( load_offsets )
292         range->glyph_offsets[n] = (FT_ULong)range->image_offset +
293                                   GET_UShort();
294     }
295
296     FORGET_Frame();
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 ( ALLOC_ARRAY( range->glyph_offsets,
344                           num_glyphs, FT_ULong )    ||
345              ACCESS_Frame( num_glyphs * size_elem ) )
346           goto Exit;
347
348         for ( n = 0; n < num_glyphs; n++ )
349           range->glyph_offsets[n] = (FT_ULong)( range->image_offset +
350                                                   ( large ? GET_ULong()
351                                                           : GET_UShort() ) );
352         FORGET_Frame();
353       }
354       break;
355
356     case 2:   /* all glyphs have identical metrics */
357       error = Load_SBit_Const_Metrics( range, stream );
358       break;
359
360     case 4:
361       error = Load_SBit_Range_Codes( range, stream, 1 );
362       break;
363
364     case 5:
365       error = Load_SBit_Const_Metrics( range, stream ) ||
366               Load_SBit_Range_Codes( range, stream, 0  );
367       break;
368
369     default:
370       error = SFNT_Err_Invalid_File_Format;
371     }
372
373   Exit:
374     return error;
375   }
376
377
378   /*************************************************************************/
379   /*                                                                       */
380   /* <Function>                                                            */
381   /*    TT_Load_SBit_Strikes                                               */
382   /*                                                                       */
383   /* <Description>                                                         */
384   /*    Loads the table of embedded bitmap sizes for this face.            */
385   /*                                                                       */
386   /* <Input>                                                               */
387   /*    face   :: The target face object.                                  */
388   /*                                                                       */
389   /*    stream :: The input stream.                                        */
390   /*                                                                       */
391   /* <Return>                                                              */
392   /*    FreeType error code.  0 means success.                             */
393   /*                                                                       */
394   FT_LOCAL_DEF FT_Error
395   TT_Load_SBit_Strikes( TT_Face    face,
396                         FT_Stream  stream )
397   {
398     FT_Error   error  = 0;
399     FT_Memory  memory = stream->memory;
400     FT_Fixed   version;
401     FT_ULong   num_strikes;
402     FT_ULong   table_base;
403
404     const FT_Frame_Field  sbit_line_metrics_fields[] =
405     {
406 #undef  FT_STRUCTURE
407 #define FT_STRUCTURE  TT_SBit_Line_Metrics
408
409       /* no FT_FRAME_START */
410         FT_FRAME_CHAR( ascender ),
411         FT_FRAME_CHAR( descender ),
412         FT_FRAME_BYTE( max_width ),
413
414         FT_FRAME_CHAR( caret_slope_numerator ),
415         FT_FRAME_CHAR( caret_slope_denominator ),
416         FT_FRAME_CHAR( caret_offset ),
417
418         FT_FRAME_CHAR( min_origin_SB ),
419         FT_FRAME_CHAR( min_advance_SB ),
420         FT_FRAME_CHAR( max_before_BL ),
421         FT_FRAME_CHAR( min_after_BL ),
422         FT_FRAME_CHAR( pads[0] ),
423         FT_FRAME_CHAR( pads[1] ),
424       FT_FRAME_END
425     };
426
427     const FT_Frame_Field  strike_start_fields[] =
428     {
429 #undef  FT_STRUCTURE
430 #define FT_STRUCTURE  TT_SBit_Strike
431
432       /* no FT_FRAME_START */
433         FT_FRAME_ULONG( ranges_offset ),
434         FT_FRAME_SKIP_LONG,
435         FT_FRAME_ULONG( num_ranges ),
436         FT_FRAME_ULONG( color_ref ),
437       FT_FRAME_END
438     };
439
440     const FT_Frame_Field  strike_end_fields[] =
441     {
442       /* no FT_FRAME_START */
443         FT_FRAME_USHORT( start_glyph ),
444         FT_FRAME_USHORT( end_glyph ),
445         FT_FRAME_BYTE  ( x_ppem ),
446         FT_FRAME_BYTE  ( y_ppem ),
447         FT_FRAME_BYTE  ( bit_depth ),
448         FT_FRAME_CHAR  ( flags ),
449       FT_FRAME_END
450     };
451
452
453     face->num_sbit_strikes = 0;
454
455     /* this table is optional */
456     error = face->goto_table( face, TTAG_EBLC, stream, 0 );
457     if ( error )
458       error = face->goto_table( face, TTAG_bloc, stream, 0 );
459     if ( error )
460       goto Exit;
461
462     table_base = FILE_Pos();
463     if ( ACCESS_Frame( 8L ) )
464       goto Exit;
465
466     version     = GET_Long();
467     num_strikes = GET_ULong();
468
469     FORGET_Frame();
470
471     /* check version number and strike count */
472     if ( version     != 0x00020000L ||
473          num_strikes >= 0x10000L    )
474     {
475       FT_ERROR(( "TT_Load_SBit_Strikes: invalid table version!\n" ));
476       error = SFNT_Err_Invalid_File_Format;
477
478       goto Exit;
479     }
480
481     /* allocate the strikes table */
482     if ( ALLOC_ARRAY( face->sbit_strikes, num_strikes, TT_SBit_Strike ) )
483       goto Exit;
484
485     face->num_sbit_strikes = num_strikes;
486
487     /* now read each strike table separately */
488     {
489       TT_SBit_Strike*  strike = face->sbit_strikes;
490       FT_ULong         count  = num_strikes;
491
492
493       if ( ACCESS_Frame( 48L * num_strikes ) )
494         goto Exit;
495
496       while ( count > 0 )
497       {
498         if ( READ_Fields( strike_start_fields, strike )             ||
499              READ_Fields( sbit_line_metrics_fields, &strike->hori ) ||
500              READ_Fields( sbit_line_metrics_fields, &strike->vert ) ||
501              READ_Fields( strike_end_fields, strike )               )
502           break;
503
504         count--;
505         strike++;
506       }
507
508       FORGET_Frame();
509     }
510
511     /* allocate the index ranges for each strike table */
512     {
513       TT_SBit_Strike*  strike = face->sbit_strikes;
514       FT_ULong         count  = num_strikes;
515
516
517       while ( count > 0 )
518       {
519         TT_SBit_Range*  range;
520         FT_ULong        count2 = strike->num_ranges;
521
522
523         if ( ALLOC_ARRAY( strike->sbit_ranges,
524                           strike->num_ranges,
525                           TT_SBit_Range ) )
526           goto Exit;
527
528         /* read each range */
529         if ( FILE_Seek( table_base + strike->ranges_offset ) ||
530              ACCESS_Frame( strike->num_ranges * 8L )         )
531           goto Exit;
532
533         range = strike->sbit_ranges;
534         while ( count2 > 0 )
535         {
536           range->first_glyph  = GET_UShort();
537           range->last_glyph   = GET_UShort();
538           range->table_offset = table_base + strike->ranges_offset
539                                  + GET_ULong();
540           count2--;
541           range++;
542         }
543
544         FORGET_Frame();
545
546         /* Now, read each index table */
547         count2 = strike->num_ranges;
548         range  = strike->sbit_ranges;
549         while ( count2 > 0 )
550         {
551           /* Read the header */
552           if ( FILE_Seek( range->table_offset ) ||
553                ACCESS_Frame( 8L )               )
554             goto Exit;
555
556           range->index_format = GET_UShort();
557           range->image_format = GET_UShort();
558           range->image_offset = GET_ULong();
559
560           FORGET_Frame();
561
562           error = Load_SBit_Range( range, stream );
563           if ( error )
564             goto Exit;
565
566           count2--;
567           range++;
568         }
569
570         count--;
571         strike++;
572       }
573     }
574
575   Exit:
576     return error;
577   }
578
579
580   /*************************************************************************/
581   /*                                                                       */
582   /* <Function>                                                            */
583   /*    TT_Free_SBit_Strikes                                               */
584   /*                                                                       */
585   /* <Description>                                                         */
586   /*    Releases the embedded bitmap tables.                               */
587   /*                                                                       */
588   /* <Input>                                                               */
589   /*    face :: The target face object.                                    */
590   /*                                                                       */
591   FT_LOCAL_DEF void
592   TT_Free_SBit_Strikes( TT_Face  face )
593   {
594     FT_Memory        memory       = face->root.memory;
595     TT_SBit_Strike*  strike       = face->sbit_strikes;
596     TT_SBit_Strike*  strike_limit = strike + face->num_sbit_strikes;
597
598
599     if ( strike )
600     {
601       for ( ; strike < strike_limit; strike++ )
602       {
603         TT_SBit_Range*  range       = strike->sbit_ranges;
604         TT_SBit_Range*  range_limit = range + strike->num_ranges;
605
606
607         if ( range )
608         {
609           for ( ; range < range_limit; range++ )
610           {
611             /* release the glyph offsets and codes tables */
612             /* where appropriate                          */
613             FREE( range->glyph_offsets );
614             FREE( range->glyph_codes );
615           }
616         }
617         FREE( strike->sbit_ranges );
618         strike->num_ranges = 0;
619       }
620       FREE( face->sbit_strikes );
621     }
622     face->num_sbit_strikes = 0;
623   }
624
625
626   FT_LOCAL_DEF FT_Error
627   TT_Set_SBit_Strike( TT_Face    face,
628                       FT_Int     x_ppem,
629                       FT_Int     y_ppem,
630                       FT_ULong  *astrike_index )
631   {
632     FT_Int  i;
633
634
635     if ( x_ppem < 0 || x_ppem > 255 ||
636          y_ppem < 1 || y_ppem > 255 )
637       return SFNT_Err_Invalid_PPem;
638
639     for ( i = 0; i < face->num_sbit_strikes; i++ )
640     {
641       if ( ( face->sbit_strikes[i].y_ppem  == y_ppem )  &&
642            ( ( x_ppem == 0 ) ||
643              ( face->sbit_strikes[i].x_ppem == x_ppem ) ) )
644       {
645         *astrike_index = i;
646         return SFNT_Err_Ok;
647       }
648     }
649
650     return SFNT_Err_Invalid_PPem;
651   }
652
653
654   /*************************************************************************/
655   /*                                                                       */
656   /* <Function>                                                            */
657   /*    Find_SBit_Range                                                    */
658   /*                                                                       */
659   /* <Description>                                                         */
660   /*    Scans a given strike's ranges and return, for a given glyph        */
661   /*    index, the corresponding sbit range, and `EBDT' offset.            */
662   /*                                                                       */
663   /* <Input>                                                               */
664   /*    glyph_index   :: The glyph index.                                  */
665   /*                                                                       */
666   /*    strike        :: The source/current sbit strike.                   */
667   /*                                                                       */
668   /* <Output>                                                              */
669   /*    arange        :: The sbit range containing the glyph index.        */
670   /*                                                                       */
671   /*    aglyph_offset :: The offset of the glyph data in `EBDT' table.     */
672   /*                                                                       */
673   /* <Return>                                                              */
674   /*    FreeType error code.  0 means the glyph index was found.           */
675   /*                                                                       */
676   static FT_Error
677   Find_SBit_Range( FT_UInt          glyph_index,
678                    TT_SBit_Strike*  strike,
679                    TT_SBit_Range**  arange,
680                    FT_ULong*        aglyph_offset )
681   {
682     TT_SBit_Range  *range, *range_limit;
683
684
685     /* check whether the glyph index is within this strike's */
686     /* glyph range                                           */
687     if ( glyph_index < (FT_UInt)strike->start_glyph ||
688          glyph_index > (FT_UInt)strike->end_glyph   )
689       goto Fail;
690
691     /* scan all ranges in strike */
692     range       = strike->sbit_ranges;
693     range_limit = range + strike->num_ranges;
694     if ( !range )
695       goto Fail;
696
697     for ( ; range < range_limit; range++ )
698     {
699       if ( glyph_index >= (FT_UInt)range->first_glyph &&
700            glyph_index <= (FT_UInt)range->last_glyph  )
701       {
702         FT_UShort  delta = (FT_UShort)( glyph_index - range->first_glyph );
703
704
705         switch ( range->index_format )
706         {
707         case 1:
708         case 3:
709           *aglyph_offset = range->glyph_offsets[delta];
710           break;
711
712         case 2:
713           *aglyph_offset = range->image_offset +
714                            range->image_size * delta;
715           break;
716
717         case 4:
718         case 5:
719           {
720             FT_ULong  n;
721
722
723             for ( n = 0; n < range->num_glyphs; n++ )
724             {
725               if ( (FT_UInt)range->glyph_codes[n] == glyph_index )
726               {
727                 if ( range->index_format == 4 )
728                   *aglyph_offset = range->glyph_offsets[n];
729                 else
730                   *aglyph_offset = range->image_offset +
731                                    n * range->image_size;
732                 goto Found;
733               }
734             }
735           }
736
737           /* fall-through */
738           default:
739             goto Fail;
740         }
741
742     Found:
743         /* return successfully! */
744         *arange  = range;
745         return 0;
746       }
747     }
748
749   Fail:
750     *arange        = 0;
751     *aglyph_offset = 0;
752
753     return SFNT_Err_Invalid_Argument;
754   }
755
756
757   /*************************************************************************/
758   /*                                                                       */
759   /* <Function>                                                            */
760   /*    Find_SBit_Image                                                    */
761   /*                                                                       */
762   /* <Description>                                                         */
763   /*    Checks whether an embedded bitmap (an `sbit') exists for a given   */
764   /*    glyph, at a given strike.                                          */
765   /*                                                                       */
766   /* <Input>                                                               */
767   /*    face          :: The target face object.                           */
768   /*                                                                       */
769   /*    glyph_index   :: The glyph index.                                  */
770   /*                                                                       */
771   /*    strike_index  :: The current strike index.                         */
772   /*                                                                       */
773   /* <Output>                                                              */
774   /*    arange        :: The SBit range containing the glyph index.        */
775   /*                                                                       */
776   /*    astrike       :: The SBit strike containing the glyph index.       */
777   /*                                                                       */
778   /*    aglyph_offset :: The offset of the glyph data in `EBDT' table.     */
779   /*                                                                       */
780   /* <Return>                                                              */
781   /*    FreeType error code.  0 means success.  Returns                    */
782   /*    SFNT_Err_Invalid_Argument if no sbit exists for the requested      */
783   /*    glyph.                                                             */
784   /*                                                                       */
785   static FT_Error
786   Find_SBit_Image( TT_Face           face,
787                    FT_UInt           glyph_index,
788                    FT_ULong          strike_index,
789                    TT_SBit_Range*   *arange,
790                    TT_SBit_Strike*  *astrike,
791                    FT_ULong         *aglyph_offset )
792   {
793     FT_Error         error;
794     TT_SBit_Strike*  strike;
795
796
797     if ( !face->sbit_strikes                              ||
798          ( face->num_sbit_strikes <= (FT_Int)strike_index ) )
799       goto Fail;
800
801     strike = &face->sbit_strikes[strike_index];
802
803     error = Find_SBit_Range( glyph_index, strike,
804                              arange, aglyph_offset );
805     if ( error )
806       goto Fail;
807
808     *astrike = strike;
809
810     return SFNT_Err_Ok;
811
812   Fail:
813     /* no embedded bitmap for this glyph in face */
814     *arange        = 0;
815     *astrike       = 0;
816     *aglyph_offset = 0;
817
818     return SFNT_Err_Invalid_Argument;
819   }
820
821
822   /*************************************************************************/
823   /*                                                                       */
824   /* <Function>                                                            */
825   /*    Load_SBit_Metrics                                                  */
826   /*                                                                       */
827   /* <Description>                                                         */
828   /*    Gets the big metrics for a given SBit.                             */
829   /*                                                                       */
830   /* <Input>                                                               */
831   /*    stream      :: The input stream.                                   */
832   /*                                                                       */
833   /*    range       :: The SBit range containing the glyph.                */
834   /*                                                                       */
835   /* <Output>                                                              */
836   /*    big_metrics :: A big SBit metrics structure for the glyph.         */
837   /*                                                                       */
838   /* <Return>                                                              */
839   /*    FreeType error code.  0 means success.                             */
840   /*                                                                       */
841   /* <Note>                                                                */
842   /*    The stream cursor must be positioned at the glyph's offset within  */
843   /*    the `EBDT' table before the call.                                  */
844   /*                                                                       */
845   /*    If the image format uses variable metrics, the stream cursor is    */
846   /*    positioned just after the metrics header in the `EBDT' table on    */
847   /*    function exit.                                                     */
848   /*                                                                       */
849   static FT_Error
850   Load_SBit_Metrics( FT_Stream         stream,
851                      TT_SBit_Range*    range,
852                      TT_SBit_Metrics*  metrics )
853   {
854     FT_Error  error = SFNT_Err_Ok;
855
856
857     switch ( range->image_format )
858     {
859     case 1:
860     case 2:
861     case 8:
862       /* variable small metrics */
863       {
864         TT_SBit_Small_Metrics  smetrics;
865
866         const FT_Frame_Field  sbit_small_metrics_fields[] =
867         {
868 #undef  FT_STRUCTURE
869 #define FT_STRUCTURE  TT_SBit_Small_Metrics
870
871           FT_FRAME_START( 5 ),
872             FT_FRAME_BYTE( height ),
873             FT_FRAME_BYTE( width ),
874             FT_FRAME_CHAR( bearingX ),
875             FT_FRAME_CHAR( bearingY ),
876             FT_FRAME_BYTE( advance ),
877           FT_FRAME_END
878         };
879
880
881         /* read small metrics */
882         if ( READ_Fields( sbit_small_metrics_fields, &smetrics ) )
883           goto Exit;
884
885         /* convert it to a big metrics */
886         metrics->height       = smetrics.height;
887         metrics->width        = smetrics.width;
888         metrics->horiBearingX = smetrics.bearingX;
889         metrics->horiBearingY = smetrics.bearingY;
890         metrics->horiAdvance  = smetrics.advance;
891
892         /* these metrics are made up at a higher level when */
893         /* needed.                                          */
894         metrics->vertBearingX = 0;
895         metrics->vertBearingY = 0;
896         metrics->vertAdvance  = 0;
897       }
898       break;
899
900     case 6:
901     case 7:
902     case 9:
903       /* variable big metrics */
904       if ( READ_Fields( sbit_metrics_fields, metrics ) )
905         goto Exit;
906       break;
907
908     case 5:
909     default:  /* constant metrics */
910       if ( range->index_format == 2 || range->index_format == 5 )
911         *metrics = range->metrics;
912       else
913         return SFNT_Err_Invalid_File_Format;
914    }
915
916   Exit:
917     return error;
918   }
919
920
921   /*************************************************************************/
922   /*                                                                       */
923   /* <Function>                                                            */
924   /*    Crop_Bitmap                                                        */
925   /*                                                                       */
926   /* <Description>                                                         */
927   /*    Crops a bitmap to its tightest bounding box, and adjusts its       */
928   /*    metrics.                                                           */
929   /*                                                                       */
930   /* <InOut>                                                               */
931   /*    map     :: The bitmap.                                             */
932   /*                                                                       */
933   /*    metrics :: The corresponding metrics structure.                    */
934   /*                                                                       */
935   static void
936   Crop_Bitmap( FT_Bitmap*        map,
937                TT_SBit_Metrics*  metrics )
938   {
939     /***********************************************************************/
940     /*                                                                     */
941     /* In this situation, some bounding boxes of embedded bitmaps are too  */
942     /* large.  We need to crop it to a reasonable size.                    */
943     /*                                                                     */
944     /*      ---------                                                      */
945     /*      |       |                -----                                 */
946     /*      |  ***  |                |***|                                 */
947     /*      |   *   |                | * |                                 */
948     /*      |   *   |    ------>     | * |                                 */
949     /*      |   *   |                | * |                                 */
950     /*      |   *   |                | * |                                 */
951     /*      |  ***  |                |***|                                 */
952     /*      ---------                -----                                 */
953     /*                                                                     */
954     /***********************************************************************/
955
956     FT_Int    rows, count;
957     FT_Long   line_len;
958     FT_Byte*  line;
959
960
961     /***********************************************************************/
962     /*                                                                     */
963     /* first of all, check the top-most lines of the bitmap, and remove    */
964     /* them if they're empty.                                              */
965     /*                                                                     */
966     {
967       line     = (FT_Byte*)map->buffer;
968       rows     = map->rows;
969       line_len = map->pitch;
970
971
972       for ( count = 0; count < rows; count++ )
973       {
974         FT_Byte*  cur   = line;
975         FT_Byte*  limit = line + line_len;
976
977
978         for ( ; cur < limit; cur++ )
979           if ( cur[0] )
980             goto Found_Top;
981
982         /* the current line was empty - skip to next one */
983         line  = limit;
984       }
985
986     Found_Top:
987       /* check that we have at least one filled line */
988       if ( count >= rows )
989         goto Empty_Bitmap;
990
991       /* now, crop the empty upper lines */
992       if ( count > 0 )
993       {
994         line = (FT_Byte*)map->buffer;
995
996         MEM_Move( line, line + count * line_len,
997                   ( rows - count ) * line_len );
998
999         metrics->height       = (FT_Byte)( metrics->height - count );
1000         metrics->horiBearingY = (FT_Char)( metrics->horiBearingY - count );
1001         metrics->vertBearingY = (FT_Char)( metrics->vertBearingY - count );
1002
1003         map->rows -= count;
1004         rows      -= count;
1005       }
1006     }
1007
1008     /***********************************************************************/
1009     /*                                                                     */
1010     /* second, crop the lower lines                                        */
1011     /*                                                                     */
1012     {
1013       line = (FT_Byte*)map->buffer + ( rows - 1 ) * line_len;
1014
1015       for ( count = 0; count < rows; count++ )
1016       {
1017         FT_Byte*  cur   = line;
1018         FT_Byte*  limit = line + line_len;
1019
1020
1021         for ( ; cur < limit; cur++ )
1022           if ( cur[0] )
1023             goto Found_Bottom;
1024
1025         /* the current line was empty - skip to previous one */
1026         line -= line_len;
1027       }
1028
1029     Found_Bottom:
1030       if ( count > 0 )
1031       {
1032         metrics->height  = (FT_Byte)( metrics->height - count );
1033         rows            -= count;
1034         map->rows       -= count;
1035       }
1036     }
1037
1038     /***********************************************************************/
1039     /*                                                                     */
1040     /* third, get rid of the space on the left side of the glyph           */
1041     /*                                                                     */
1042     do
1043     {
1044       FT_Byte*  limit;
1045
1046
1047       line  = (FT_Byte*)map->buffer;
1048       limit = line + rows * line_len;
1049
1050       for ( ; line < limit; line += line_len )
1051         if ( line[0] & 0x80 )
1052           goto Found_Left;
1053
1054       /* shift the whole glyph one pixel to the left */
1055       line  = (FT_Byte*)map->buffer;
1056       limit = line + rows * line_len;
1057
1058       for ( ; line < limit; line += line_len )
1059       {
1060         FT_Int    n, width = map->width;
1061         FT_Byte   old;
1062         FT_Byte*  cur = line;
1063
1064
1065         old = (FT_Byte)(cur[0] << 1);
1066         for ( n = 8; n < width; n += 8 )
1067         {
1068           FT_Byte  val;
1069
1070
1071           val    = cur[1];
1072           cur[0] = (FT_Byte)( old | ( val >> 7 ) );
1073           old    = (FT_Byte)( val << 1 );
1074           cur++;
1075         }
1076         cur[0] = old;
1077       }
1078
1079       map->width--;
1080       metrics->horiBearingX++;
1081       metrics->vertBearingX++;
1082       metrics->width--;
1083
1084     } while ( map->width > 0 );
1085
1086   Found_Left:
1087
1088     /***********************************************************************/
1089     /*                                                                     */
1090     /* finally, crop the bitmap width to get rid of the space on the right */
1091     /* side of the glyph.                                                  */
1092     /*                                                                     */
1093     do
1094     {
1095       FT_Int    right = map->width - 1;
1096       FT_Byte*  limit;
1097       FT_Byte   mask;
1098
1099
1100       line  = (FT_Byte*)map->buffer + ( right >> 3 );
1101       limit = line + rows * line_len;
1102       mask  = (FT_Byte)( 0x80 >> ( right & 7 ) );
1103
1104       for ( ; line < limit; line += line_len )
1105         if ( line[0] & mask )
1106           goto Found_Right;
1107
1108       /* crop the whole glyph to the right */
1109       map->width--;
1110       metrics->width--;
1111
1112     } while ( map->width > 0 );
1113
1114   Found_Right:
1115     /* all right, the bitmap was cropped */
1116     return;
1117
1118   Empty_Bitmap:
1119     map->width      = 0;
1120     map->rows       = 0;
1121     map->pitch      = 0;
1122     map->pixel_mode = ft_pixel_mode_mono;
1123   }
1124
1125
1126   static FT_Error
1127   Load_SBit_Single( FT_Bitmap*        map,
1128                     FT_Int            x_offset,
1129                     FT_Int            y_offset,
1130                     FT_Int            pix_bits,
1131                     FT_UShort         image_format,
1132                     TT_SBit_Metrics*  metrics,
1133                     FT_Stream         stream )
1134   {
1135     FT_Error  error;
1136
1137
1138     /* check that the source bitmap fits into the target pixmap */
1139     if ( x_offset < 0 || x_offset + metrics->width  > map->width ||
1140          y_offset < 0 || y_offset + metrics->height > map->rows  )
1141     {
1142       error = SFNT_Err_Invalid_Argument;
1143
1144       goto Exit;
1145     }
1146
1147     {
1148       FT_Int  glyph_width  = metrics->width;
1149       FT_Int  glyph_height = metrics->height;
1150       FT_Int  glyph_size;
1151       FT_Int  line_bits    = pix_bits * glyph_width;
1152       FT_Bool pad_bytes    = 0;
1153
1154
1155       /* compute size of glyph image */
1156       switch ( image_format )
1157       {
1158       case 1:  /* byte-padded formats */
1159       case 6:
1160         {
1161           FT_Int  line_length;
1162
1163
1164           switch ( pix_bits )
1165           {
1166           case 1:  line_length = ( glyph_width + 7 ) >> 3;   break;
1167           case 2:  line_length = ( glyph_width + 3 ) >> 2;   break;
1168           case 4:  line_length = ( glyph_width + 1 ) >> 1;   break;
1169           default: line_length =   glyph_width;
1170           }
1171
1172           glyph_size = glyph_height * line_length;
1173           pad_bytes  = 1;
1174         }
1175         break;
1176
1177       case 2:
1178       case 5:
1179       case 7:
1180         line_bits  =   glyph_width  * pix_bits;
1181         glyph_size = ( glyph_height * line_bits + 7 ) >> 3;
1182         break;
1183
1184       default:  /* invalid format */
1185         return SFNT_Err_Invalid_File_Format;
1186       }
1187
1188       /* Now read data and draw glyph into target pixmap       */
1189       if ( ACCESS_Frame( glyph_size ) )
1190         goto Exit;
1191
1192       /* don't forget to multiply `x_offset' by `map->pix_bits' as */
1193       /* the sbit blitter doesn't make a difference between pixmap */
1194       /* depths.                                                   */
1195       blit_sbit( map, (FT_Byte*)stream->cursor, line_bits, pad_bytes,
1196                  x_offset * pix_bits, y_offset );
1197
1198       FORGET_Frame();
1199     }
1200
1201   Exit:
1202     return error;
1203   }
1204
1205
1206   static FT_Error
1207   Load_SBit_Image( TT_SBit_Strike*   strike,
1208                    TT_SBit_Range*    range,
1209                    FT_ULong          ebdt_pos,
1210                    FT_ULong          glyph_offset,
1211                    FT_Bitmap*        map,
1212                    FT_Int            x_offset,
1213                    FT_Int            y_offset,
1214                    FT_Stream         stream,
1215                    TT_SBit_Metrics*  metrics )
1216   {
1217     FT_Memory  memory = stream->memory;
1218     FT_Error   error;
1219
1220
1221     /* place stream at beginning of glyph data and read metrics */
1222     if ( FILE_Seek( ebdt_pos + glyph_offset ) )
1223       goto Exit;
1224
1225     error = Load_SBit_Metrics( stream, range, metrics );
1226     if ( error )
1227       goto Exit;
1228
1229     /* this function is recursive.  At the top-level call, the */
1230     /* field map.buffer is NULL.  We thus begin by finding the */
1231     /* dimensions of the higher-level glyph to allocate the    */
1232     /* final pixmap buffer                                     */
1233     if ( map->buffer == 0 )
1234     {
1235       FT_Long  size;
1236
1237
1238       map->width = metrics->width;
1239       map->rows  = metrics->height;
1240
1241       switch ( strike->bit_depth )
1242       {
1243       case 1:
1244         map->pixel_mode = ft_pixel_mode_mono;
1245         map->pitch      = ( map->width + 7 ) >> 3;
1246         break;
1247
1248       case 2:
1249         map->pixel_mode = ft_pixel_mode_pal2;
1250         map->pitch      = ( map->width + 3 ) >> 2;
1251         break;
1252
1253       case 4:
1254         map->pixel_mode = ft_pixel_mode_pal4;
1255         map->pitch      = ( map->width + 1 ) >> 1;
1256         break;
1257
1258       case 8:
1259         map->pixel_mode = ft_pixel_mode_grays;
1260         map->pitch      = map->width;
1261         break;
1262
1263       default:
1264         return SFNT_Err_Invalid_File_Format;
1265       }
1266
1267       size = map->rows * map->pitch;
1268
1269       /* check that there is no empty image */
1270       if ( size == 0 )
1271         goto Exit;     /* exit successfully! */
1272
1273       if ( ALLOC( map->buffer, size ) )
1274         goto Exit;
1275     }
1276
1277     switch ( range->image_format )
1278     {
1279     case 1:  /* single sbit image - load it */
1280     case 2:
1281     case 5:
1282     case 6:
1283     case 7:
1284       return Load_SBit_Single( map, x_offset, y_offset, strike->bit_depth,
1285                                range->image_format, metrics, stream );
1286
1287     case 8:  /* compound format */
1288       FT_Skip_Stream( stream, 1L );
1289       /* fallthrough */
1290
1291     case 9:
1292       break;
1293
1294     default: /* invalid image format */
1295       return SFNT_Err_Invalid_File_Format;
1296     }
1297
1298     /* All right, we have a compound format.  First of all, read */
1299     /* the array of elements.                                    */
1300     {
1301       TT_SBit_Component*  components;
1302       TT_SBit_Component*  comp;
1303       FT_UShort           num_components, count;
1304
1305
1306       if ( READ_UShort( num_components )                                ||
1307            ALLOC_ARRAY( components, num_components, TT_SBit_Component ) )
1308         goto Exit;
1309
1310       count = num_components;
1311
1312       if ( ACCESS_Frame( 4L * num_components ) )
1313         goto Fail_Memory;
1314
1315       for ( comp = components; count > 0; count--, comp++ )
1316       {
1317         comp->glyph_code = GET_UShort();
1318         comp->x_offset   = GET_Char();
1319         comp->y_offset   = GET_Char();
1320       }
1321
1322       FORGET_Frame();
1323
1324       /* Now recursively load each element glyph */
1325       count = num_components;
1326       comp  = components;
1327       for ( ; count > 0; count--, comp++ )
1328       {
1329         TT_SBit_Range*   elem_range;
1330         TT_SBit_Metrics  elem_metrics;
1331         FT_ULong         elem_offset;
1332
1333
1334         /* find the range for this element */
1335         error = Find_SBit_Range( comp->glyph_code,
1336                                  strike,
1337                                  &elem_range,
1338                                  &elem_offset );
1339         if ( error )
1340           goto Fail_Memory;
1341
1342         /* now load the element, recursively */
1343         error = Load_SBit_Image( strike,
1344                                  elem_range,
1345                                  ebdt_pos,
1346                                  elem_offset,
1347                                  map,
1348                                  x_offset + comp->x_offset,
1349                                  y_offset + comp->y_offset,
1350                                  stream,
1351                                  &elem_metrics );
1352         if ( error )
1353           goto Fail_Memory;
1354       }
1355
1356     Fail_Memory:
1357       FREE( components );
1358     }
1359
1360   Exit:
1361     return error;
1362   }
1363
1364
1365   /*************************************************************************/
1366   /*                                                                       */
1367   /* <Function>                                                            */
1368   /*    TT_Load_SBit_Image                                                 */
1369   /*                                                                       */
1370   /* <Description>                                                         */
1371   /*    Loads a given glyph sbit image from the font resource.  This also  */
1372   /*    returns its metrics.                                               */
1373   /*                                                                       */
1374   /* <Input>                                                               */
1375   /*    face         :: The target face object.                            */
1376   /*                                                                       */
1377   /*    strike_index :: The current strike index.                          */
1378   /*                                                                       */
1379   /*    glyph_index  :: The current glyph index.                           */
1380   /*                                                                       */
1381   /*    load_flags   :: The glyph load flags (the code checks for the flag */
1382   /*                    FT_LOAD_CROP_BITMAP).                              */
1383   /*                                                                       */
1384   /*    stream       :: The input stream.                                  */
1385   /*                                                                       */
1386   /* <Output>                                                              */
1387   /*    map          :: The target pixmap.                                 */
1388   /*                                                                       */
1389   /*    metrics      :: A big sbit metrics structure for the glyph image.  */
1390   /*                                                                       */
1391   /* <Return>                                                              */
1392   /*    FreeType error code.  0 means success.  Returns an error if no     */
1393   /*    glyph sbit exists for the index.                                   */
1394   /*                                                                       */
1395   /*  <Note>                                                               */
1396   /*    The `map.buffer' field is always freed before the glyph is loaded. */
1397   /*                                                                       */
1398   FT_LOCAL_DEF FT_Error
1399   TT_Load_SBit_Image( TT_Face           face,
1400                       FT_ULong          strike_index,
1401                       FT_UInt           glyph_index,
1402                       FT_UInt           load_flags,
1403                       FT_Stream         stream,
1404                       FT_Bitmap        *map,
1405                       TT_SBit_Metrics  *metrics )
1406   {
1407     FT_Error         error;
1408     FT_Memory        memory = stream->memory;
1409     FT_ULong         ebdt_pos, glyph_offset;
1410
1411     TT_SBit_Strike*  strike;
1412     TT_SBit_Range*   range;
1413
1414
1415     /* Check whether there is a glyph sbit for the current index */
1416     error = Find_SBit_Image( face, glyph_index, strike_index,
1417                              &range, &strike, &glyph_offset );
1418     if ( error )
1419       goto Exit;
1420
1421     /* now, find the location of the `EBDT' table in */
1422     /* the font file                                 */
1423     error = face->goto_table( face, TTAG_EBDT, stream, 0 );
1424     if ( error )
1425       error = face->goto_table( face, TTAG_bdat, stream, 0 );
1426     if (error)
1427       goto Exit;
1428
1429     ebdt_pos = FILE_Pos();
1430
1431     /* clear the bitmap & load the bitmap */
1432     if ( face->root.glyph->flags & ft_glyph_own_bitmap )
1433       FREE( map->buffer );
1434
1435     map->rows = map->pitch = map->width = 0;
1436
1437     error = Load_SBit_Image( strike, range, ebdt_pos, glyph_offset,
1438                              map, 0, 0, stream, metrics );
1439     if ( error )
1440       goto Exit;
1441
1442     /* the glyph slot owns this bitmap buffer */
1443     face->root.glyph->flags |= ft_glyph_own_bitmap;
1444
1445     /* setup vertical metrics if needed */
1446     if ( strike->flags & 1 )
1447     {
1448       /* in case of a horizontal strike only */
1449       FT_Int  advance;
1450
1451
1452       advance = strike->hori.ascender - strike->hori.descender;
1453
1454       /* some heuristic values */
1455
1456       metrics->vertBearingX = (FT_Char)(-metrics->width / 2 );
1457       metrics->vertBearingY = (FT_Char)( advance / 10 );
1458       metrics->vertAdvance  = (FT_Char)( advance * 12 / 10 );
1459     }
1460
1461     /* Crop the bitmap now, unless specified otherwise */
1462     if ( load_flags & FT_LOAD_CROP_BITMAP )
1463       Crop_Bitmap( map, metrics );
1464
1465   Exit:
1466     return error;
1467   }
1468
1469
1470 /* END */