1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/
2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  ttsbit.c                                                               */
4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*    TrueType and OpenType embedded bitmap support (body).                */
6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  Copyright 2005-2009, 2013 by                                           */
8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  Copyright 2013 by Google, Inc.                                         */
11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  Google Author(s): Behdad Esfahbod.                                     */
12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  This file is part of the FreeType project, and may only be used,       */
14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  modified, and distributed under the terms of the FreeType project      */
15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  this file you indicate that you have read the license and              */
17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  understand and accept it fully.                                        */
18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/
20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/ft2build.h"
23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/internal/ftdebug.h"
24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/internal/ftstream.h"
25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/tttags.h"
26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/ftbitmap.h"
27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "ttsbit.h"
28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "sferrors.h"
30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "pngshim.h"
32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*                                                                       */
36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* messages during execution.                                            */
39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*                                                                       */
40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef  FT_COMPONENT
41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_COMPONENT  trace_ttsbit
42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_LOCAL_DEF( FT_Error )
45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  tt_face_load_eblc( TT_Face    face,
46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                     FT_Stream  stream )
47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error  error = FT_Err_Ok;
49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Fixed  version;
50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_ULong  num_strikes, table_size;
51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte*  p;
52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte*  p_limit;
53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt   count;
54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    face->sbit_num_strikes = 0;
57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* this table is optional */
59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    error = face->goto_table( face, TTAG_CBLC, stream, &table_size );
60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( error )
61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = face->goto_table( face, TTAG_EBLC, stream, &table_size );
62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( error )
63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = face->goto_table( face, TTAG_bloc, stream, &table_size );
64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( error )
65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( table_size < 8 )
68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_ERROR(( "tt_face_load_sbit_strikes: table too short\n" ));
70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = FT_THROW( Invalid_File_Format );
71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( FT_FRAME_EXTRACT( table_size, face->sbit_table ) )
75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    face->sbit_table_size = table_size;
78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p       = face->sbit_table;
80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p_limit = p + table_size;
81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    version     = FT_NEXT_ULONG( p );
83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    num_strikes = FT_NEXT_ULONG( p );
84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( version != 0x00020000UL || num_strikes >= 0x10000UL )
86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_ERROR(( "tt_face_load_sbit_strikes: invalid table version\n" ));
88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = FT_THROW( Invalid_File_Format );
89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Fail;
90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /*
93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *  Count the number of strikes available in the table.  We are a bit
94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *  paranoid there and don't trust the data.
95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     */
96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    count = (FT_UInt)num_strikes;
97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( 8 + 48UL * count > table_size )
98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      count = (FT_UInt)( ( p_limit - p ) / 48 );
99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    face->sbit_num_strikes = count;
101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_TRACE3(( "sbit_num_strikes: %u\n", count ));
103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Exit:
104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return error;
105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Fail:
107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_FRAME_RELEASE( face->sbit_table );
108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    face->sbit_table_size = 0;
109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    goto Exit;
110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_LOCAL_DEF( void )
114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  tt_face_free_eblc( TT_Face  face )
115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Stream  stream = face->root.stream;
117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_FRAME_RELEASE( face->sbit_table );
120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    face->sbit_table_size  = 0;
121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    face->sbit_num_strikes = 0;
122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_LOCAL_DEF( FT_Error )
126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  tt_face_set_sbit_strike( TT_Face          face,
127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           FT_Size_Request  req,
128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           FT_ULong*        astrike_index )
129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FT_Match_Size( (FT_Face)face, req, 0, astrike_index );
131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_LOCAL_DEF( FT_Error )
135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  tt_face_load_strike_metrics( TT_Face           face,
136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                               FT_ULong          strike_index,
137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                               FT_Size_Metrics*  metrics )
138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte*  strike;
140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( strike_index >= (FT_ULong)face->sbit_num_strikes )
143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return FT_THROW( Invalid_Argument );
144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    strike = face->sbit_table + 8 + strike_index * 48;
146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    metrics->x_ppem = (FT_UShort)strike[44];
148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    metrics->y_ppem = (FT_UShort)strike[45];
149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    metrics->ascender  = (FT_Char)strike[16] << 6;  /* hori.ascender  */
151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    metrics->descender = (FT_Char)strike[17] << 6;  /* hori.descender */
152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    metrics->height    = metrics->ascender - metrics->descender;
153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* XXX: Is this correct? */
155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    metrics->max_advance = ( (FT_Char)strike[22] + /* min_origin_SB  */
156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                      strike[18] + /* max_width      */
157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                             (FT_Char)strike[23]   /* min_advance_SB */
158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                 ) << 6;
159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FT_Err_Ok;
161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  typedef struct  TT_SBitDecoderRec_
165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    TT_Face          face;
167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Stream        stream;
168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Bitmap*       bitmap;
169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    TT_SBit_Metrics  metrics;
170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Bool          metrics_loaded;
171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Bool          bitmap_allocated;
172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte          bit_depth;
173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_ULong         ebdt_start;
175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_ULong         ebdt_size;
176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_ULong         strike_index_array;
178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_ULong         strike_index_count;
179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte*         eblc_base;
180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte*         eblc_limit;
181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  } TT_SBitDecoderRec, *TT_SBitDecoder;
183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Error
186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  tt_sbit_decoder_init( TT_SBitDecoder       decoder,
187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        TT_Face              face,
188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        FT_ULong             strike_index,
189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        TT_SBit_MetricsRec*  metrics )
190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error   error;
192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Stream  stream = face->root.stream;
193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_ULong   ebdt_size;
194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    error = face->goto_table( face, TTAG_CBDT, stream, &ebdt_size );
197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( error )
198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = face->goto_table( face, TTAG_EBDT, stream, &ebdt_size );
199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( error )
200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = face->goto_table( face, TTAG_bdat, stream, &ebdt_size );
201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( error )
202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    decoder->face    = face;
205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    decoder->stream  = stream;
206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    decoder->bitmap  = &face->root.glyph->bitmap;
207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    decoder->metrics = metrics;
208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    decoder->metrics_loaded   = 0;
210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    decoder->bitmap_allocated = 0;
211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    decoder->ebdt_start = FT_STREAM_POS();
213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    decoder->ebdt_size  = ebdt_size;
214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    decoder->eblc_base  = face->sbit_table;
216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    decoder->eblc_limit = face->sbit_table + face->sbit_table_size;
217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* now find the strike corresponding to the index */
219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Byte*  p;
221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( 8 + 48 * strike_index + 3 * 4 + 34 + 1 > face->sbit_table_size )
224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        error = FT_THROW( Invalid_File_Format );
226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Exit;
227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      p = decoder->eblc_base + 8 + 48 * strike_index;
230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      decoder->strike_index_array = FT_NEXT_ULONG( p );
232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      p                          += 4;
233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      decoder->strike_index_count = FT_NEXT_ULONG( p );
234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      p                          += 34;
235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      decoder->bit_depth          = *p;
236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( decoder->strike_index_array > face->sbit_table_size             ||
238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           decoder->strike_index_array + 8 * decoder->strike_index_count >
239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov             face->sbit_table_size                                         )
240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        error = FT_THROW( Invalid_File_Format );
241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Exit:
244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return error;
245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static void
249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  tt_sbit_decoder_done( TT_SBitDecoder  decoder )
250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UNUSED( decoder );
252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Error
256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  tt_sbit_decoder_alloc_bitmap( TT_SBitDecoder  decoder,
257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                FT_UInt         load_flags )
258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error    error = FT_Err_Ok;
260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt     width, height;
261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Bitmap*  map = decoder->bitmap;
262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Long     size;
263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( !decoder->metrics_loaded )
266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = FT_THROW( Invalid_Argument );
268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    width  = decoder->metrics->width;
272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    height = decoder->metrics->height;
273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    map->width = (int)width;
275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    map->rows  = (int)height;
276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    switch ( decoder->bit_depth )
278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    case 1:
280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      map->pixel_mode = FT_PIXEL_MODE_MONO;
281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      map->pitch      = ( map->width + 7 ) >> 3;
282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      map->num_grays  = 2;
283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      break;
284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    case 2:
286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      map->pixel_mode = FT_PIXEL_MODE_GRAY2;
287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      map->pitch      = ( map->width + 3 ) >> 2;
288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      map->num_grays  = 4;
289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      break;
290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    case 4:
292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      map->pixel_mode = FT_PIXEL_MODE_GRAY4;
293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      map->pitch      = ( map->width + 1 ) >> 1;
294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      map->num_grays  = 16;
295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      break;
296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    case 8:
298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      map->pixel_mode = FT_PIXEL_MODE_GRAY;
299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      map->pitch      = map->width;
300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      map->num_grays  = 256;
301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      break;
302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    case 32:
304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( load_flags & FT_LOAD_COLOR )
305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        map->pixel_mode = FT_PIXEL_MODE_BGRA;
307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        map->pitch      = map->width * 4;
308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        map->num_grays  = 256;
309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        map->pixel_mode = FT_PIXEL_MODE_GRAY;
313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        map->pitch      = map->width;
314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        map->num_grays  = 256;
315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      break;
317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    default:
319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = FT_THROW( Invalid_File_Format );
320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    size = map->rows * map->pitch;
324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* check that there is no empty image */
326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( size == 0 )
327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;     /* exit successfully! */
328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    error = ft_glyphslot_alloc_bitmap( decoder->face->root.glyph, size );
330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( error )
331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    decoder->bitmap_allocated = 1;
334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Exit:
336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return error;
337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Error
341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  tt_sbit_decoder_load_metrics( TT_SBitDecoder  decoder,
342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                FT_Byte*       *pp,
343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                FT_Byte*        limit,
344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                FT_Bool         big )
345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte*         p       = *pp;
347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    TT_SBit_Metrics  metrics = decoder->metrics;
348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( p + 5 > limit )
351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Fail;
352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    metrics->height       = p[0];
354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    metrics->width        = p[1];
355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    metrics->horiBearingX = (FT_Char)p[2];
356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    metrics->horiBearingY = (FT_Char)p[3];
357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    metrics->horiAdvance  = p[4];
358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p += 5;
360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( big )
361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( p + 3 > limit )
363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Fail;
364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      metrics->vertBearingX = (FT_Char)p[0];
366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      metrics->vertBearingY = (FT_Char)p[1];
367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      metrics->vertAdvance  = p[2];
368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      p += 3;
370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    decoder->metrics_loaded = 1;
373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *pp = p;
374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FT_Err_Ok;
375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Fail:
377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_TRACE1(( "tt_sbit_decoder_load_metrics: broken table" ));
378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FT_THROW( Invalid_Argument );
379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* forward declaration */
383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Error
384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  tt_sbit_decoder_load_image( TT_SBitDecoder  decoder,
385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                              FT_UInt         load_flags,
386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                              FT_UInt         glyph_index,
387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                              FT_Int          x_pos,
388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                              FT_Int          y_pos );
389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  typedef FT_Error  (*TT_SBitDecoder_LoadFunc)( TT_SBitDecoder  decoder,
391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                FT_UInt         load_flags,
392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                FT_Byte*        p,
393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                FT_Byte*        plimit,
394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                FT_Int          x_pos,
395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                FT_Int          y_pos );
396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Error
399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  tt_sbit_decoder_load_byte_aligned( TT_SBitDecoder  decoder,
400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                     FT_UInt         load_flags,
401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                     FT_Byte*        p,
402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                     FT_Byte*        limit,
403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                     FT_Int          x_pos,
404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                     FT_Int          y_pos )
405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error    error = FT_Err_Ok;
407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte*    line;
408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Int      bit_height, bit_width, pitch, width, height, line_bits, h;
409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Bitmap*  bitmap;
410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UNUSED( load_flags );
412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* check that we can write the glyph into the bitmap */
415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    bitmap     = decoder->bitmap;
416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    bit_width  = bitmap->width;
417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    bit_height = bitmap->rows;
418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pitch      = bitmap->pitch;
419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    line       = bitmap->buffer;
420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    width  = decoder->metrics->width;
422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    height = decoder->metrics->height;
423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    line_bits = width * decoder->bit_depth;
425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( x_pos < 0 || x_pos + width > bit_width   ||
427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         y_pos < 0 || y_pos + height > bit_height )
428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_TRACE1(( "tt_sbit_decoder_load_byte_aligned:"
430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  " invalid bitmap dimensions\n" ));
431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = FT_THROW( Invalid_File_Format );
432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( p + ( ( line_bits + 7 ) >> 3 ) * height > limit )
436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_TRACE1(( "tt_sbit_decoder_load_byte_aligned: broken bitmap\n" ));
438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = FT_THROW( Invalid_File_Format );
439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* now do the blit */
443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    line  += y_pos * pitch + ( x_pos >> 3 );
444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    x_pos &= 7;
445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( x_pos == 0 )  /* the easy one */
447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      for ( h = height; h > 0; h--, line += pitch )
449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_Byte*  pwrite = line;
451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_Int    w;
452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for ( w = line_bits; w >= 8; w -= 8 )
455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          pwrite[0] = (FT_Byte)( pwrite[0] | *p++ );
457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          pwrite   += 1;
458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( w > 0 )
461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          pwrite[0] = (FT_Byte)( pwrite[0] | ( *p++ & ( 0xFF00U >> w ) ) );
462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else  /* x_pos > 0 */
465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      for ( h = height; h > 0; h--, line += pitch )
467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_Byte*  pwrite = line;
469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_Int    w;
470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_UInt   wval = 0;
471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for ( w = line_bits; w >= 8; w -= 8 )
474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          wval       = (FT_UInt)( wval | *p++ );
476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          pwrite[0]  = (FT_Byte)( pwrite[0] | ( wval >> x_pos ) );
477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          pwrite    += 1;
478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          wval     <<= 8;
479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( w > 0 )
482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          wval = (FT_UInt)( wval | ( *p++ & ( 0xFF00U >> w ) ) );
483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* all bits read and there are `x_pos + w' bits to be written */
485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pwrite[0] = (FT_Byte)( pwrite[0] | ( wval >> x_pos ) );
487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( x_pos + w > 8 )
489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          pwrite++;
491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          wval     <<= 8;
492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          pwrite[0]  = (FT_Byte)( pwrite[0] | ( wval >> x_pos ) );
493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Exit:
498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( !error )
499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_TRACE3(( "tt_sbit_decoder_load_byte_aligned: loaded\n" ));
500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return error;
501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*
505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   * Load a bit-aligned bitmap (with pointer `p') into a line-aligned bitmap
506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   * (with pointer `pwrite').  In the example below, the width is 3 pixel,
507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   * and `x_pos' is 1 pixel.
508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *
509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *       p                               p+1
510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *     |                               |                               |
511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *     | 7   6   5   4   3   2   1   0 | 7   6   5   4   3   2   1   0 |...
512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *     |                               |                               |
513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *       +-------+   +-------+   +-------+ ...
514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *           .           .           .
515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *           .           .           .
516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *           v           .           .
517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *       +-------+       .           .
518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   * |                               | .
519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   * | 7   6   5   4   3   2   1   0 | .
520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   * |                               | .
521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *   pwrite              .           .
522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *                       .           .
523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *                       v           .
524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *                   +-------+       .
525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *             |                               |
526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *             | 7   6   5   4   3   2   1   0 |
527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *             |                               |
528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *               pwrite+1            .
529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *                                   .
530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *                                   v
531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *                               +-------+
532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *                         |                               |
533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *                         | 7   6   5   4   3   2   1   0 |
534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *                         |                               |
535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *                           pwrite+2
536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *
537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   */
538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Error
540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  tt_sbit_decoder_load_bit_aligned( TT_SBitDecoder  decoder,
541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                    FT_UInt         load_flags,
542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                    FT_Byte*        p,
543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                    FT_Byte*        limit,
544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                    FT_Int          x_pos,
545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                    FT_Int          y_pos )
546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error    error = FT_Err_Ok;
548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte*    line;
549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Int      bit_height, bit_width, pitch, width, height, line_bits, h, nbits;
550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Bitmap*  bitmap;
551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UShort   rval;
552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UNUSED( load_flags );
554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* check that we can write the glyph into the bitmap */
557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    bitmap     = decoder->bitmap;
558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    bit_width  = bitmap->width;
559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    bit_height = bitmap->rows;
560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pitch      = bitmap->pitch;
561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    line       = bitmap->buffer;
562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    width  = decoder->metrics->width;
564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    height = decoder->metrics->height;
565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    line_bits = width * decoder->bit_depth;
567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( x_pos < 0 || x_pos + width  > bit_width  ||
569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         y_pos < 0 || y_pos + height > bit_height )
570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_TRACE1(( "tt_sbit_decoder_load_bit_aligned:"
572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  " invalid bitmap dimensions\n" ));
573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = FT_THROW( Invalid_File_Format );
574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( p + ( ( line_bits * height + 7 ) >> 3 ) > limit )
578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_TRACE1(( "tt_sbit_decoder_load_bit_aligned: broken bitmap\n" ));
580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = FT_THROW( Invalid_File_Format );
581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* now do the blit */
585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* adjust `line' to point to the first byte of the bitmap */
587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    line  += y_pos * pitch + ( x_pos >> 3 );
588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    x_pos &= 7;
589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* the higher byte of `rval' is used as a buffer */
591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    rval  = 0;
592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    nbits = 0;
593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for ( h = height; h > 0; h--, line += pitch )
595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Byte*  pwrite = line;
597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Int    w      = line_bits;
598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* handle initial byte (in target bitmap) specially if necessary */
601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( x_pos )
602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        w = ( line_bits < 8 - x_pos ) ? line_bits : 8 - x_pos;
604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( h == height )
606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          rval  = *p++;
608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          nbits = x_pos;
609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else if ( nbits < w )
611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          if ( p < limit )
613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            rval |= *p++;
614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          nbits += 8 - w;
615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else
617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          rval  >>= 8;
619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          nbits  -= w;
620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        *pwrite++ |= ( ( rval >> nbits ) & 0xFF ) &
623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                     ( ~( 0xFF << w ) << ( 8 - w - x_pos ) );
624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        rval     <<= 8;
625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        w = line_bits - w;
627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* handle medial bytes */
630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      for ( ; w >= 8; w -= 8 )
631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        rval      |= *p++;
633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        *pwrite++ |= ( rval >> nbits ) & 0xFF;
634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        rval <<= 8;
636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* handle final byte if necessary */
639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( w > 0 )
640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( nbits < w )
642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          if ( p < limit )
644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            rval |= *p++;
645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          *pwrite |= ( ( rval >> nbits ) & 0xFF ) & ( 0xFF00U >> w );
646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          nbits   += 8 - w;
647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          rval <<= 8;
649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else
651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          *pwrite |= ( ( rval >> nbits ) & 0xFF ) & ( 0xFF00U >> w );
653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          nbits   -= w;
654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Exit:
659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( !error )
660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_TRACE3(( "tt_sbit_decoder_load_bit_aligned: loaded\n" ));
661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return error;
662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Error
666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  tt_sbit_decoder_load_compound( TT_SBitDecoder  decoder,
667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                 FT_UInt         load_flags,
668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                 FT_Byte*        p,
669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                 FT_Byte*        limit,
670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                 FT_Int          x_pos,
671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                 FT_Int          y_pos )
672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error  error = FT_Err_Ok;
674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt   num_components, nn;
675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Char  horiBearingX = decoder->metrics->horiBearingX;
677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Char  horiBearingY = decoder->metrics->horiBearingY;
678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte  horiAdvance  = decoder->metrics->horiAdvance;
679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Char  vertBearingX = decoder->metrics->vertBearingX;
680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Char  vertBearingY = decoder->metrics->vertBearingY;
681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte  vertAdvance  = decoder->metrics->vertAdvance;
682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( p + 2 > limit )
685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Fail;
686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    num_components = FT_NEXT_USHORT( p );
688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( p + 4 * num_components > limit )
689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_TRACE1(( "tt_sbit_decoder_load_compound: broken table\n" ));
691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Fail;
692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_TRACE3(( "tt_sbit_decoder_load_compound: loading %d components\n",
695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                num_components ));
696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for ( nn = 0; nn < num_components; nn++ )
698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_UInt  gindex = FT_NEXT_USHORT( p );
700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Byte  dx     = FT_NEXT_BYTE( p );
701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Byte  dy     = FT_NEXT_BYTE( p );
702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* NB: a recursive call */
705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = tt_sbit_decoder_load_image( decoder, load_flags, gindex,
706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                          x_pos + dx, y_pos + dy );
707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( error )
708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        break;
709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_TRACE3(( "tt_sbit_decoder_load_compound: done\n" ));
712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    decoder->metrics->horiBearingX = horiBearingX;
714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    decoder->metrics->horiBearingY = horiBearingY;
715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    decoder->metrics->horiAdvance  = horiAdvance;
716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    decoder->metrics->vertBearingX = vertBearingX;
717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    decoder->metrics->vertBearingY = vertBearingY;
718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    decoder->metrics->vertAdvance  = vertAdvance;
719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    decoder->metrics->width        = (FT_Byte)decoder->bitmap->width;
720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    decoder->metrics->height       = (FT_Byte)decoder->bitmap->rows;
721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Exit:
723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return error;
724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Fail:
726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    error = FT_THROW( Invalid_File_Format );
727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    goto Exit;
728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_CONFIG_OPTION_USE_PNG
732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Error
734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  tt_sbit_decoder_load_png( TT_SBitDecoder  decoder,
735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            FT_UInt         load_flags,
736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            FT_Byte*        p,
737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            FT_Byte*        limit,
738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            FT_Int          x_pos,
739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            FT_Int          y_pos )
740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error  error = FT_Err_Ok;
742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_ULong  png_len;
743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UNUSED( load_flags );
745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( limit - p < 4 )
748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_TRACE1(( "tt_sbit_decoder_load_png: broken bitmap\n" ));
750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = FT_THROW( Invalid_File_Format );
751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    png_len = FT_NEXT_ULONG( p );
755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( (FT_ULong)( limit - p ) < png_len )
756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_TRACE1(( "tt_sbit_decoder_load_png: broken bitmap\n" ));
758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = FT_THROW( Invalid_File_Format );
759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    error = Load_SBit_Png( decoder->bitmap,
763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           x_pos,
764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           y_pos,
765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           decoder->bit_depth,
766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           decoder->metrics,
767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           decoder->stream->memory,
768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           p,
769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           png_len );
770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Exit:
772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( !error )
773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_TRACE3(( "tt_sbit_decoder_load_png: loaded\n" ));
774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return error;
775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* FT_CONFIG_OPTION_USE_PNG */
778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Error
781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  tt_sbit_decoder_load_bitmap( TT_SBitDecoder  decoder,
782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                               FT_UInt         load_flags,
783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                               FT_UInt         glyph_format,
784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                               FT_ULong        glyph_start,
785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                               FT_ULong        glyph_size,
786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                               FT_Int          x_pos,
787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                               FT_Int          y_pos )
788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error   error;
790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Stream  stream = decoder->stream;
791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte*   p;
792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte*   p_limit;
793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte*   data;
794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* seek into the EBDT table now */
797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( glyph_start + glyph_size > decoder->ebdt_size )
798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = FT_THROW( Invalid_Argument );
800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( FT_STREAM_SEEK( decoder->ebdt_start + glyph_start ) ||
804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         FT_FRAME_EXTRACT( glyph_size, data )                )
805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p       = data;
808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p_limit = p + glyph_size;
809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* read the data, depending on the glyph format */
811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    switch ( glyph_format )
812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    case 1:
814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    case 2:
815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    case 8:
816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    case 17:
817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 0 );
818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      break;
819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    case 6:
821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    case 7:
822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    case 9:
823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    case 18:
824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 );
825ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      break;
826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    default:
828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = FT_Err_Ok;
829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( error )
832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Fail;
833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
834ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      TT_SBitDecoder_LoadFunc  loader;
836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      switch ( glyph_format )
839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      case 1:
841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      case 6:
842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        loader = tt_sbit_decoder_load_byte_aligned;
843ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        break;
844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      case 2:
846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      case 5:
847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      case 7:
848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        loader = tt_sbit_decoder_load_bit_aligned;
849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        break;
850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      case 8:
852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( p + 1 > p_limit )
853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto Fail;
854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        p += 1;  /* skip padding */
856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* fall-through */
857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      case 9:
859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        loader = tt_sbit_decoder_load_compound;
860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        break;
861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_CONFIG_OPTION_USE_PNG
863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      case 17: /* small metrics, PNG image data   */
864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      case 18: /* big metrics, PNG image data     */
865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      case 19: /* metrics in EBLC, PNG image data */
866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        loader = tt_sbit_decoder_load_png;
867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        break;
868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* FT_CONFIG_OPTION_USE_PNG */
869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      default:
871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        error = FT_THROW( Invalid_Table );
872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Fail;
873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( !decoder->bitmap_allocated )
876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        error = tt_sbit_decoder_alloc_bitmap( decoder, load_flags );
878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( error )
879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto Fail;
880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
881ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( decoder->bit_depth == 32                          &&
883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           decoder->bitmap->pixel_mode != FT_PIXEL_MODE_BGRA )
884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* Flatten color bitmaps if color was not requested. */
886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_Library library = decoder->face->root.glyph->library;
888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_Memory  memory  = decoder->stream->memory;
889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_Bitmap color, *orig;
891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( decoder->bitmap->pixel_mode != FT_PIXEL_MODE_GRAY ||
894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov             x_pos != 0 || y_pos != 0                          )
895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          /* Shouldn't happen. */
897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          error = FT_THROW( Invalid_Table );
898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto Fail;
899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_Bitmap_New( &color );
902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        color.rows       = decoder->bitmap->rows;
904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        color.width      = decoder->bitmap->width;
905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        color.pitch      = color.width * 4;
906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        color.pixel_mode = FT_PIXEL_MODE_BGRA;
907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( FT_ALLOC( color.buffer, color.rows * color.pitch ) )
909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto Fail;
910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
911ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        orig            = decoder->bitmap;
912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        decoder->bitmap = &color;
913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        error = loader( decoder, load_flags, p, p_limit, x_pos, y_pos );
915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
916ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        decoder->bitmap = orig;
917ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* explicitly test against FT_Err_Ok to avoid compiler warnings */
919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* (we do an assignment within a conditional)                   */
920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( error                                           ||
921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov             ( error = FT_Bitmap_Convert( library,
922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                          &color,
923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                          decoder->bitmap,
924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                          1 ) ) != FT_Err_Ok )
925ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          FT_Bitmap_Done( library, &color );
927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto Fail;
928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_Bitmap_Done( library, &color );
931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        error = loader( decoder, load_flags, p, p_limit, x_pos, y_pos );
935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Fail:
938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_FRAME_RELEASE( data );
939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Exit:
941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return error;
942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Error
946ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  tt_sbit_decoder_load_image( TT_SBitDecoder  decoder,
947ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                              FT_UInt         load_flags,
948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                              FT_UInt         glyph_index,
949ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                              FT_Int          x_pos,
950ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                              FT_Int          y_pos )
951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
952ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /*
953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *  First, we find the correct strike range that applies to this
954ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *  glyph index.
955ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     */
956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte*  p          = decoder->eblc_base + decoder->strike_index_array;
958ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte*  p_limit    = decoder->eblc_limit;
959ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_ULong  num_ranges = decoder->strike_index_count;
960ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt   start, end, index_format, image_format;
961ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_ULong  image_start = 0, image_end = 0, image_offset;
962ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
963ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
964ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for ( ; num_ranges > 0; num_ranges-- )
965ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
966ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      start = FT_NEXT_USHORT( p );
967ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      end   = FT_NEXT_USHORT( p );
968ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
969ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( glyph_index >= start && glyph_index <= end )
970ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto FoundRange;
971ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
972ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      p += 4;  /* ignore index offset */
973ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
974ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    goto NoBitmap;
975ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
976ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FoundRange:
977ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    image_offset = FT_NEXT_ULONG( p );
978ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
979ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* overflow check */
980ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p = decoder->eblc_base + decoder->strike_index_array;
981ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( image_offset > (FT_ULong)( p_limit - p ) )
982ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Failure;
983ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
984ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p += image_offset;
985ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( p + 8 > p_limit )
986ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto NoBitmap;
987ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
988ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* now find the glyph's location and extend within the ebdt table */
989ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    index_format = FT_NEXT_USHORT( p );
990ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    image_format = FT_NEXT_USHORT( p );
991ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    image_offset = FT_NEXT_ULONG ( p );
992ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
993ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    switch ( index_format )
994ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
995ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    case 1: /* 4-byte offsets relative to `image_offset' */
996ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
997ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        p += 4 * ( glyph_index - start );
998ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( p + 8 > p_limit )
999ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto NoBitmap;
1000ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1001ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        image_start = FT_NEXT_ULONG( p );
1002ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        image_end   = FT_NEXT_ULONG( p );
1003ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1004ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( image_start == image_end )  /* missing glyph */
1005ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto NoBitmap;
1006ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
1007ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      break;
1008ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1009ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    case 2: /* big metrics, constant image size */
1010ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
1011ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_ULong  image_size;
1012ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1013ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1014ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( p + 12 > p_limit )
1015ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto NoBitmap;
1016ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1017ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        image_size = FT_NEXT_ULONG( p );
1018ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1019ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 ) )
1020ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto NoBitmap;
1021ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1022ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        image_start = image_size * ( glyph_index - start );
1023ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        image_end   = image_start + image_size;
1024ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
1025ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      break;
1026ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1027ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    case 3: /* 2-byte offsets relative to 'image_offset' */
1028ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
1029ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        p += 2 * ( glyph_index - start );
1030ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( p + 4 > p_limit )
1031ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto NoBitmap;
1032ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1033ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        image_start = FT_NEXT_USHORT( p );
1034ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        image_end   = FT_NEXT_USHORT( p );
1035ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1036ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( image_start == image_end )  /* missing glyph */
1037ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto NoBitmap;
1038ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
1039ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      break;
1040ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1041ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    case 4: /* sparse glyph array with (glyph,offset) pairs */
1042ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
1043ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_ULong  mm, num_glyphs;
1044ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1045ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1046ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( p + 4 > p_limit )
1047ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto NoBitmap;
1048ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1049ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        num_glyphs = FT_NEXT_ULONG( p );
1050ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1051ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* overflow check for p + ( num_glyphs + 1 ) * 4 */
1052ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( num_glyphs > (FT_ULong)( ( ( p_limit - p ) >> 2 ) - 1 ) )
1053ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto NoBitmap;
1054ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1055ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for ( mm = 0; mm < num_glyphs; mm++ )
1056ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
1057ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          FT_UInt  gindex = FT_NEXT_USHORT( p );
1058ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1059ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1060ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          if ( gindex == glyph_index )
1061ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          {
1062ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            image_start = FT_NEXT_USHORT( p );
1063ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            p          += 2;
1064ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            image_end   = FT_PEEK_USHORT( p );
1065ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            break;
1066ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          }
1067ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          p += 2;
1068ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1069ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1070ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( mm >= num_glyphs )
1071ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto NoBitmap;
1072ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
1073ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      break;
1074ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1075ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    case 5: /* constant metrics with sparse glyph codes */
1076ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    case 19:
1077ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
1078ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_ULong  image_size, mm, num_glyphs;
1079ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1080ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1081ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( p + 16 > p_limit )
1082ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto NoBitmap;
1083ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1084ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        image_size = FT_NEXT_ULONG( p );
1085ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1086ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 ) )
1087ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto NoBitmap;
1088ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1089ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        num_glyphs = FT_NEXT_ULONG( p );
1090ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1091ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* overflow check for p + 2 * num_glyphs */
1092ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( num_glyphs > (FT_ULong)( ( p_limit - p ) >> 1 ) )
1093ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto NoBitmap;
1094ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1095ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for ( mm = 0; mm < num_glyphs; mm++ )
1096ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
1097ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          FT_UInt  gindex = FT_NEXT_USHORT( p );
1098ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1099ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          if ( gindex == glyph_index )
1101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            break;
1102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( mm >= num_glyphs )
1105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto NoBitmap;
1106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        image_start = image_size * mm;
1108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        image_end   = image_start + image_size;
1109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
1110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      break;
1111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    default:
1113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto NoBitmap;
1114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( image_start > image_end )
1117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto NoBitmap;
1118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    image_end  -= image_start;
1120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    image_start = image_offset + image_start;
1121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_TRACE3(( "tt_sbit_decoder_load_image:"
1123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                " found sbit (format %d) for glyph index %d\n",
1124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                image_format, glyph_index ));
1125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return tt_sbit_decoder_load_bitmap( decoder,
1127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                        load_flags,
1128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                        image_format,
1129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                        image_start,
1130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                        image_end,
1131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                        x_pos,
1132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                        y_pos );
1133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Failure:
1135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FT_THROW( Invalid_Table );
1136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  NoBitmap:
1138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_TRACE4(( "tt_sbit_decoder_load_image:"
1139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                " no sbit found for glyph index %d\n", glyph_index ));
1140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FT_THROW( Invalid_Argument );
1142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
1143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_LOCAL( FT_Error )
1146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  tt_face_load_sbit_image( TT_Face              face,
1147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           FT_ULong             strike_index,
1148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           FT_UInt              glyph_index,
1149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           FT_UInt              load_flags,
1150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           FT_Stream            stream,
1151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           FT_Bitmap           *map,
1152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           TT_SBit_MetricsRec  *metrics )
1153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
1154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    TT_SBitDecoderRec  decoder[1];
1155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error           error;
1156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UNUSED( load_flags );
1158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UNUSED( stream );
1159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UNUSED( map );
1160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    error = tt_sbit_decoder_init( decoder, face, strike_index, metrics );
1163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( !error )
1164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
1165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = tt_sbit_decoder_load_image( decoder,
1166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                          load_flags,
1167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                          glyph_index,
1168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                          0,
1169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                          0 );
1170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      tt_sbit_decoder_done( decoder );
1171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return error;
1174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
1175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* EOF */
1178