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

Last change on this file since 251 was 251, checked in by Eugene Romanenko, 13 years ago

PDF plugin: freetype library updated to version 2.3.5

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