source: trunk/poppler/freetype2/src/sfnt/ttsbit.c @ 182

Last change on this file since 182 was 182, checked in by Eugene Romanenko, 15 years ago

freetype update to version 2.3.0

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