1049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
2049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
3049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  ttsbit0.c                                                              */
4049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
5049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*    TrueType and OpenType embedded bitmap support (body).                */
6049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*    This is a heap-optimized version.                                    */
7049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner/*  Copyright 2005, 2006, 2007, 2008, 2009 by                              */
9049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
10049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
11049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  This file is part of the FreeType project, and may only be used,       */
12049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  modified, and distributed under the terms of the FreeType project      */
13049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
14049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  this file you indicate that you have read the license and              */
15049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  understand and accept it fully.                                        */
16049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
17049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
18049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
19049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
20049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* This file is included by ttsbit.c */
21049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
22049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
23049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include <ft2build.h>
24049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_DEBUG_H
25049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_STREAM_H
26049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_TRUETYPE_TAGS_H
27049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "ttsbit.h"
28049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
29049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "sferrors.h"
30049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
31049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
32049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
33049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
34049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
35049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
36049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* messages during execution.                                            */
37049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
38049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#undef  FT_COMPONENT
39049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_COMPONENT  trace_ttsbit
40049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
41049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
42049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
43049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_face_load_eblc( TT_Face    face,
44049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Stream  stream )
45049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
4677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Error  error = SFNT_Err_Ok;
4777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Fixed  version;
4877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_ULong  num_strikes, table_size;
4977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Byte*  p;
5077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Byte*  p_limit;
5177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_UInt   count;
52049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
53049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
54049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    face->sbit_num_strikes = 0;
55049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
56049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* this table is optional */
57049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = face->goto_table( face, TTAG_EBLC, stream, &table_size );
58049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( error )
59049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = face->goto_table( face, TTAG_bloc, stream, &table_size );
60049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( error )
61049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
62049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
63049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table_size < 8 )
64049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
65295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_ERROR(( "tt_face_load_sbit_strikes: table too short\n" ));
66049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = SFNT_Err_Invalid_File_Format;
67049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
68049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
69049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
70049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_FRAME_EXTRACT( table_size, face->sbit_table ) )
71049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
72049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
73049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    face->sbit_table_size = table_size;
74049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
75049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p       = face->sbit_table;
76049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p_limit = p + table_size;
77049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
78049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    version     = FT_NEXT_ULONG( p );
79049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_strikes = FT_NEXT_ULONG( p );
80049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
81049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( version != 0x00020000UL || num_strikes >= 0x10000UL )
82049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
83295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_ERROR(( "tt_face_load_sbit_strikes: invalid table version\n" ));
84049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = SFNT_Err_Invalid_File_Format;
85049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Fail;
86049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
87049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
88049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
89049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  Count the number of strikes available in the table.  We are a bit
90049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  paranoid there and don't trust the data.
91049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
92049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    count = (FT_UInt)num_strikes;
93049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( 8 + 48UL * count > table_size )
94049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      count = (FT_UInt)( ( p_limit - p ) / 48 );
95049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
96049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    face->sbit_num_strikes = count;
97049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
98049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_TRACE3(( "sbit_num_strikes: %u\n", count ));
99049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Fail:
103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FRAME_RELEASE( face->sbit_table );
104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    face->sbit_table_size = 0;
105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    goto Exit;
106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_face_free_eblc( TT_Face  face )
111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Stream  stream = face->root.stream;
113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FRAME_RELEASE( face->sbit_table );
116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    face->sbit_table_size  = 0;
117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    face->sbit_num_strikes = 0;
118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_face_set_sbit_strike( TT_Face          face,
123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_Size_Request  req,
124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_ULong*        astrike_index )
125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return FT_Match_Size( (FT_Face)face, req, 0, astrike_index );
127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_face_load_strike_metrics( TT_Face           face,
132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                               FT_ULong          strike_index,
133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                               FT_Size_Metrics*  metrics )
134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
13577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Byte*  strike;
136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( strike_index >= (FT_ULong)face->sbit_num_strikes )
139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return SFNT_Err_Invalid_Argument;
140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    strike = face->sbit_table + 8 + strike_index * 48;
142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    metrics->x_ppem = (FT_UShort)strike[44];
144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    metrics->y_ppem = (FT_UShort)strike[45];
145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    metrics->ascender  = (FT_Char)strike[16] << 6;  /* hori.ascender  */
147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    metrics->descender = (FT_Char)strike[17] << 6;  /* hori.descender */
148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    metrics->height    = metrics->ascender - metrics->descender;
149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* XXX: Is this correct? */
151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    metrics->max_advance = ( (FT_Char)strike[22] + /* min_origin_SB  */
152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                      strike[18] + /* max_width      */
153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             (FT_Char)strike[23]   /* min_advance_SB */
154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                                 ) << 6;
155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return SFNT_Err_Ok;
157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef struct  TT_SBitDecoderRec_
161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_Face          face;
163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Stream        stream;
164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Bitmap*       bitmap;
165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_SBit_Metrics  metrics;
166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Bool          metrics_loaded;
167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Bool          bitmap_allocated;
168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte          bit_depth;
169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong         ebdt_start;
171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong         ebdt_size;
172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong         strike_index_array;
174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong         strike_index_count;
175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*         eblc_base;
176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*         eblc_limit;
177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  } TT_SBitDecoderRec, *TT_SBitDecoder;
179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_sbit_decoder_init( TT_SBitDecoder       decoder,
183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        TT_Face              face,
184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        FT_ULong             strike_index,
185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        TT_SBit_MetricsRec*  metrics )
186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error   error;
188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Stream  stream = face->root.stream;
189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong   ebdt_size;
190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = face->goto_table( face, TTAG_EBDT, stream, &ebdt_size );
193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( error )
194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = face->goto_table( face, TTAG_bdat, stream, &ebdt_size );
195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( error )
196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    decoder->face    = face;
199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    decoder->stream  = stream;
200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    decoder->bitmap  = &face->root.glyph->bitmap;
201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    decoder->metrics = metrics;
202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    decoder->metrics_loaded   = 0;
204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    decoder->bitmap_allocated = 0;
205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    decoder->ebdt_start = FT_STREAM_POS();
207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    decoder->ebdt_size  = ebdt_size;
208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    decoder->eblc_base  = face->sbit_table;
210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    decoder->eblc_limit = face->sbit_table + face->sbit_table_size;
211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* now find the strike corresponding to the index */
213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  p;
215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( 8 + 48 * strike_index + 3 * 4 + 34 + 1 > face->sbit_table_size )
218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        error = SFNT_Err_Invalid_File_Format;
220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p = decoder->eblc_base + 8 + 48 * strike_index;
224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      decoder->strike_index_array = FT_NEXT_ULONG( p );
226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p                          += 4;
227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      decoder->strike_index_count = FT_NEXT_ULONG( p );
228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p                          += 34;
229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      decoder->bit_depth          = *p;
230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( decoder->strike_index_array > face->sbit_table_size             ||
232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           decoder->strike_index_array + 8 * decoder->strike_index_count >
233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             face->sbit_table_size                                         )
234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        error = SFNT_Err_Invalid_File_Format;
235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_sbit_decoder_done( TT_SBitDecoder  decoder )
244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( decoder );
246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_sbit_decoder_alloc_bitmap( TT_SBitDecoder  decoder )
251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error    error = SFNT_Err_Ok;
253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     width, height;
254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Bitmap*  map = decoder->bitmap;
255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Long     size;
256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !decoder->metrics_loaded )
259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = SFNT_Err_Invalid_Argument;
261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    width  = decoder->metrics->width;
265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    height = decoder->metrics->height;
266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    map->width = (int)width;
268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    map->rows  = (int)height;
269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    switch ( decoder->bit_depth )
271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case 1:
273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      map->pixel_mode = FT_PIXEL_MODE_MONO;
274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      map->pitch      = ( map->width + 7 ) >> 3;
275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case 2:
278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      map->pixel_mode = FT_PIXEL_MODE_GRAY2;
279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      map->pitch      = ( map->width + 3 ) >> 2;
280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case 4:
283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      map->pixel_mode = FT_PIXEL_MODE_GRAY4;
284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      map->pitch      = ( map->width + 1 ) >> 1;
285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case 8:
288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      map->pixel_mode = FT_PIXEL_MODE_GRAY;
289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      map->pitch      = map->width;
290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    default:
293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = SFNT_Err_Invalid_File_Format;
294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    size = map->rows * map->pitch;
298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* check that there is no empty image */
300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( size == 0 )
301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;     /* exit successfully! */
302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = ft_glyphslot_alloc_bitmap( decoder->face->root.glyph, size );
304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( error )
305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    decoder->bitmap_allocated = 1;
308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_sbit_decoder_load_metrics( TT_SBitDecoder  decoder,
316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                FT_Byte*       *pp,
317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                FT_Byte*        limit,
318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                FT_Bool         big )
319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*         p       = *pp;
321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_SBit_Metrics  metrics = decoder->metrics;
322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( p + 5 > limit )
325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Fail;
326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
32777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    metrics->height       = p[0];
32877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    metrics->width        = p[1];
32977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    metrics->horiBearingX = (FT_Char)p[2];
33077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    metrics->horiBearingY = (FT_Char)p[3];
33177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    metrics->horiAdvance  = p[4];
332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p += 5;
334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( big )
335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( p + 3 > limit )
337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Fail;
338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
33977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      metrics->vertBearingX = (FT_Char)p[0];
34077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      metrics->vertBearingY = (FT_Char)p[1];
34177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      metrics->vertAdvance  = p[2];
342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p += 3;
344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    decoder->metrics_loaded = 1;
347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *pp = p;
34877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    return SFNT_Err_Ok;
349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Fail:
351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return SFNT_Err_Invalid_Argument;
352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* forward declaration */
356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_sbit_decoder_load_image( TT_SBitDecoder  decoder,
358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              FT_UInt         glyph_index,
359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              FT_Int          x_pos,
360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              FT_Int          y_pos );
361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef FT_Error  (*TT_SBitDecoder_LoadFunc)( TT_SBitDecoder  decoder,
363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                                FT_Byte*        p,
364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                                FT_Byte*        plimit,
365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                                FT_Int          x_pos,
366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                                FT_Int          y_pos );
367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_sbit_decoder_load_byte_aligned( TT_SBitDecoder  decoder,
371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                     FT_Byte*        p,
372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                     FT_Byte*        limit,
373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                     FT_Int          x_pos,
374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                     FT_Int          y_pos )
375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error    error = SFNT_Err_Ok;
377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*    line;
378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int      bit_height, bit_width, pitch, width, height, h;
379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Bitmap*  bitmap;
380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !decoder->bitmap_allocated )
383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = tt_sbit_decoder_alloc_bitmap( decoder );
385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* check that we can write the glyph into the bitmap */
390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    bitmap     = decoder->bitmap;
391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    bit_width  = bitmap->width;
392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    bit_height = bitmap->rows;
393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    pitch      = bitmap->pitch;
394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    line       = bitmap->buffer;
395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    width  = decoder->metrics->width;
397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    height = decoder->metrics->height;
398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( x_pos < 0 || x_pos + width > bit_width   ||
400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         y_pos < 0 || y_pos + height > bit_height )
401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = SFNT_Err_Invalid_File_Format;
403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( p + ( ( width + 7 ) >> 3 ) * height > limit )
407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = SFNT_Err_Invalid_File_Format;
409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* now do the blit */
413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    line  += y_pos * pitch + ( x_pos >> 3 );
414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    x_pos &= 7;
415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( x_pos == 0 )  /* the easy one */
417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( h = height; h > 0; h--, line += pitch )
419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Byte*  write = line;
421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Int    w;
422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( w = width; w >= 8; w -= 8 )
425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          write[0] = (FT_Byte)( write[0] | *p++ );
427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          write   += 1;
428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( w > 0 )
431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          write[0] = (FT_Byte)( write[0] | ( *p++ & ( 0xFF00U >> w ) ) );
432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else  /* x_pos > 0 */
435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( h = height; h > 0; h--, line += pitch )
437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Byte*  write = line;
439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Int    w;
440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt   wval = 0;
441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( w = width; w >= 8; w -= 8 )
444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          wval      = (FT_UInt)( wval | *p++ );
446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          write[0]  = (FT_Byte)( write[0] | ( wval >> x_pos ) );
447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          write    += 1;
448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          wval    <<= 8;
449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( w > 0 )
452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          wval = (FT_UInt)( wval | ( *p++ & ( 0xFF00U >> w ) ) );
453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
45477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        /* all bits read and there are `x_pos + w' bits to be written */
455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        write[0] = (FT_Byte)( write[0] | ( wval >> x_pos ) );
457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( x_pos + w > 8 )
459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          write++;
461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          wval   <<= 8;
462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          write[0] = (FT_Byte)( write[0] | ( wval >> x_pos ) );
463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
472295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*
473295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   * Load a bit-aligned bitmap (with pointer `p') into a line-aligned bitmap
474295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   * (with pointer `write').  In the example below, the width is 3 pixel,
475295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   * and `x_pos' is 1 pixel.
476295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *
477295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *       p                               p+1
478295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *     |                               |                               |
479295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *     | 7   6   5   4   3   2   1   0 | 7   6   5   4   3   2   1   0 |...
480295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *     |                               |                               |
481295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *       +-------+   +-------+   +-------+ ...
482295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *           .           .           .
483295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *           .           .           .
484295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *           v           .           .
485295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *       +-------+       .           .
486295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   * |                               | .
487295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   * | 7   6   5   4   3   2   1   0 | .
488295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   * |                               | .
489295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *   write               .           .
490295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *                       .           .
491295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *                       v           .
492295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *                   +-------+       .
493295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *             |                               |
494295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *             | 7   6   5   4   3   2   1   0 |
495295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *             |                               |
496295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *               write+1             .
497295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *                                   .
498295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *                                   v
499295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *                               +-------+
500295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *                         |                               |
501295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *                         | 7   6   5   4   3   2   1   0 |
502295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *                         |                               |
503295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *                           write+2
504295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   *
505295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner   */
506295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_sbit_decoder_load_bit_aligned( TT_SBitDecoder  decoder,
509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                    FT_Byte*        p,
510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                    FT_Byte*        limit,
511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                    FT_Int          x_pos,
512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                    FT_Int          y_pos )
513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error    error = SFNT_Err_Ok;
515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*    line;
516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int      bit_height, bit_width, pitch, width, height, h, nbits;
517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Bitmap*  bitmap;
518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort   rval;
519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !decoder->bitmap_allocated )
522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = tt_sbit_decoder_alloc_bitmap( decoder );
524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* check that we can write the glyph into the bitmap */
529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    bitmap     = decoder->bitmap;
530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    bit_width  = bitmap->width;
531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    bit_height = bitmap->rows;
532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    pitch      = bitmap->pitch;
533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    line       = bitmap->buffer;
534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    width  = decoder->metrics->width;
536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    height = decoder->metrics->height;
537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( x_pos < 0 || x_pos + width  > bit_width  ||
539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         y_pos < 0 || y_pos + height > bit_height )
540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = SFNT_Err_Invalid_File_Format;
542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( p + ( ( width * height + 7 ) >> 3 ) > limit )
546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = SFNT_Err_Invalid_File_Format;
548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* now do the blit */
552295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
553295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* adjust `line' to point to the first byte of the bitmap */
554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    line  += y_pos * pitch + ( x_pos >> 3 );
555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    x_pos &= 7;
556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* the higher byte of `rval' is used as a buffer */
558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    rval  = 0;
559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    nbits = 0;
560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( h = height; h > 0; h--, line += pitch )
562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  write = line;
564295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_Int    w     = width;
565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
567295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      /* handle initial byte (in target bitmap) specially if necessary */
568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( x_pos )
569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        w = ( width < 8 - x_pos ) ? width : 8 - x_pos;
571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
57277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        if ( h == height )
57377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        {
574295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          rval  = *p++;
575295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          nbits = x_pos;
57677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        }
57777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        else if ( nbits < w )
578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
579295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          if ( p < limit )
580295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            rval |= *p++;
581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          nbits += 8 - w;
582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          rval  >>= 8;
586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          nbits  -= w;
587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
58977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        *write++ |= ( ( rval >> nbits ) & 0xFF ) &
59077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner                    ( ~( 0xFF << w ) << ( 8 - w - x_pos ) );
591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        rval    <<= 8;
592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        w = width - w;
594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
596295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      /* handle medial bytes */
597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; w >= 8; w -= 8 )
598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        rval     |= *p++;
600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *write++ |= ( rval >> nbits ) & 0xFF;
601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        rval <<= 8;
603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
605295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      /* handle final byte if necessary */
606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( w > 0 )
607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( nbits < w )
609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
610295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          if ( p < limit )
611295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            rval |= *p++;
612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          *write |= ( ( rval >> nbits ) & 0xFF ) & ( 0xFF00U >> w );
613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          nbits  += 8 - w;
614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          rval <<= 8;
616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          *write |= ( ( rval >> nbits ) & 0xFF ) & ( 0xFF00U >> w );
620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          nbits  -= w;
621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_sbit_decoder_load_compound( TT_SBitDecoder  decoder,
632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 FT_Byte*        p,
633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 FT_Byte*        limit,
634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 FT_Int          x_pos,
635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 FT_Int          y_pos )
636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error  error = SFNT_Err_Ok;
638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   num_components, nn;
639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
64077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Char  horiBearingX = decoder->metrics->horiBearingX;
64177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Char  horiBearingY = decoder->metrics->horiBearingY;
64277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Byte  horiAdvance  = decoder->metrics->horiAdvance;
64377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Char  vertBearingX = decoder->metrics->vertBearingX;
64477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Char  vertBearingY = decoder->metrics->vertBearingY;
64577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Byte  vertAdvance  = decoder->metrics->vertAdvance;
64677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( p + 2 > limit )
649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Fail;
650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_components = FT_NEXT_USHORT( p );
652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( p + 4 * num_components > limit )
653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Fail;
654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
65577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    if ( !decoder->bitmap_allocated )
65677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    {
65777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      error = tt_sbit_decoder_alloc_bitmap( decoder );
65877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      if ( error )
65977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        goto Exit;
66077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    }
66177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( nn = 0; nn < num_components; nn++ )
663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  gindex = FT_NEXT_USHORT( p );
665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte  dx     = FT_NEXT_BYTE( p );
666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte  dy     = FT_NEXT_BYTE( p );
667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* NB: a recursive call */
670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = tt_sbit_decoder_load_image( decoder, gindex,
671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          x_pos + dx, y_pos + dy );
672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
67677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    decoder->metrics->horiBearingX = horiBearingX;
67777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    decoder->metrics->horiBearingY = horiBearingY;
67877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    decoder->metrics->horiAdvance  = horiAdvance;
67977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    decoder->metrics->vertBearingX = vertBearingX;
68077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    decoder->metrics->vertBearingY = vertBearingY;
68177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    decoder->metrics->vertAdvance  = vertAdvance;
68277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    decoder->metrics->width        = (FT_UInt)decoder->bitmap->width;
68377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    decoder->metrics->height       = (FT_UInt)decoder->bitmap->rows;
68477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Fail:
689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = SFNT_Err_Invalid_File_Format;
690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    goto Exit;
691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_sbit_decoder_load_bitmap( TT_SBitDecoder  decoder,
696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                               FT_UInt         glyph_format,
697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                               FT_ULong        glyph_start,
698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                               FT_ULong        glyph_size,
699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                               FT_Int          x_pos,
700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                               FT_Int          y_pos )
701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error   error;
703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Stream  stream = decoder->stream;
704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p;
705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p_limit;
706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   data;
707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* seek into the EBDT table now */
710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( glyph_start + glyph_size > decoder->ebdt_size )
711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = SFNT_Err_Invalid_Argument;
713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_STREAM_SEEK( decoder->ebdt_start + glyph_start ) ||
717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         FT_FRAME_EXTRACT( glyph_size, data )                )
718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p       = data;
721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p_limit = p + glyph_size;
722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* read the data, depending on the glyph format */
724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    switch ( glyph_format )
725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case 1:
727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case 2:
728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case 8:
729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 0 );
730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case 6:
733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case 7:
734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case 9:
735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 );
736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    default:
739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = SFNT_Err_Ok;
740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( error )
743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Fail;
744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TT_SBitDecoder_LoadFunc  loader;
747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      switch ( glyph_format )
750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      case 1:
752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      case 6:
753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        loader = tt_sbit_decoder_load_byte_aligned;
754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      case 2:
757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      case 5:
758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      case 7:
759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        loader = tt_sbit_decoder_load_bit_aligned;
760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      case 8:
763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( p + 1 > p_limit )
764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Fail;
765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p += 1;  /* skip padding */
767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* fall-through */
768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      case 9:
770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        loader = tt_sbit_decoder_load_compound;
771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      default:
774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Fail;
775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = loader( decoder, p, p_limit, x_pos, y_pos );
778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Fail:
781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FRAME_RELEASE( data );
782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_sbit_decoder_load_image( TT_SBitDecoder  decoder,
790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              FT_UInt         glyph_index,
791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              FT_Int          x_pos,
792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              FT_Int          y_pos )
793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  First, we find the correct strike range that applies to this
796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     *  glyph index.
797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p          = decoder->eblc_base + decoder->strike_index_array;
800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p_limit    = decoder->eblc_limit;
801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  num_ranges = decoder->strike_index_count;
802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   start, end, index_format, image_format;
803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  image_start = 0, image_end = 0, image_offset;
804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; num_ranges > 0; num_ranges-- )
807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start = FT_NEXT_USHORT( p );
809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      end   = FT_NEXT_USHORT( p );
810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( glyph_index >= start && glyph_index <= end )
812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto FoundRange;
813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p += 4;  /* ignore index offset */
815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    goto NoBitmap;
817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FoundRange:
819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    image_offset = FT_NEXT_ULONG( p );
820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* overflow check */
822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( decoder->eblc_base + decoder->strike_index_array + image_offset <
823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           decoder->eblc_base )
824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Failure;
825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p = decoder->eblc_base + decoder->strike_index_array + image_offset;
827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( p + 8 > p_limit )
828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto NoBitmap;
829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* now find the glyph's location and extend within the ebdt table */
831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    index_format = FT_NEXT_USHORT( p );
832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    image_format = FT_NEXT_USHORT( p );
833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    image_offset = FT_NEXT_ULONG ( p );
834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    switch ( index_format )
836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case 1: /* 4-byte offsets relative to `image_offset' */
838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p += 4 * ( glyph_index - start );
840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( p + 8 > p_limit )
841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto NoBitmap;
842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        image_start = FT_NEXT_ULONG( p );
844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        image_end   = FT_NEXT_ULONG( p );
845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( image_start == image_end )  /* missing glyph */
847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto NoBitmap;
848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case 2: /* big metrics, constant image size */
852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_ULong  image_size;
854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( p + 12 > p_limit )
857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto NoBitmap;
858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        image_size = FT_NEXT_ULONG( p );
860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 ) )
862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto NoBitmap;
863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        image_start = image_size * ( glyph_index - start );
865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        image_end   = image_start + image_size;
866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case 3: /* 2-byte offsets relative to 'image_offset' */
870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p += 2 * ( glyph_index - start );
872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( p + 4 > p_limit )
873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto NoBitmap;
874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        image_start = FT_NEXT_USHORT( p );
876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        image_end   = FT_NEXT_USHORT( p );
877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( image_start == image_end )  /* missing glyph */
879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto NoBitmap;
880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case 4: /* sparse glyph array with (glyph,offset) pairs */
884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_ULong  mm, num_glyphs;
886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( p + 4 > p_limit )
889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto NoBitmap;
890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        num_glyphs = FT_NEXT_ULONG( p );
892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* overflow check */
894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( p + ( num_glyphs + 1 ) * 4 < p )
895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Failure;
896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( p + ( num_glyphs + 1 ) * 4 > p_limit )
898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto NoBitmap;
899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( mm = 0; mm < num_glyphs; mm++ )
901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt  gindex = FT_NEXT_USHORT( p );
903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( gindex == glyph_index )
906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            image_start = FT_NEXT_USHORT( p );
908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p          += 2;
909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            image_end   = FT_PEEK_USHORT( p );
910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p += 2;
913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( mm >= num_glyphs )
916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto NoBitmap;
917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case 5: /* constant metrics with sparse glyph codes */
921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_ULong  image_size, mm, num_glyphs;
923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( p + 16 > p_limit )
926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto NoBitmap;
927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        image_size = FT_NEXT_ULONG( p );
929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 ) )
931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto NoBitmap;
932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        num_glyphs = FT_NEXT_ULONG( p );
934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* overflow check */
936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( p + 2 * num_glyphs < p )
937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Failure;
938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( p + 2 * num_glyphs > p_limit )
940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto NoBitmap;
941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( mm = 0; mm < num_glyphs; mm++ )
943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt  gindex = FT_NEXT_USHORT( p );
945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( gindex == glyph_index )
948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( mm >= num_glyphs )
952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto NoBitmap;
953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        image_start = image_size * mm;
955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        image_end   = image_start + image_size;
956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    default:
960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto NoBitmap;
961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( image_start > image_end )
964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto NoBitmap;
965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    image_end  -= image_start;
967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    image_start = image_offset + image_start;
968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return tt_sbit_decoder_load_bitmap( decoder,
970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                        image_format,
971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                        image_start,
972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                        image_end,
973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                        x_pos,
974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                        y_pos );
975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Failure:
977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return SFNT_Err_Invalid_Table;
978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  NoBitmap:
980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return SFNT_Err_Invalid_Argument;
981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL( FT_Error )
985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_face_load_sbit_image( TT_Face              face,
986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_ULong             strike_index,
987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_UInt              glyph_index,
988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_UInt              load_flags,
989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_Stream            stream,
990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_Bitmap           *map,
991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           TT_SBit_MetricsRec  *metrics )
992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_SBitDecoderRec  decoder[1];
994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error           error;
995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( load_flags );
997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( stream );
998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( map );
999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = tt_sbit_decoder_init( decoder, face, strike_index, metrics );
1002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !error )
1003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = tt_sbit_decoder_load_image( decoder, glyph_index, 0, 0 );
1005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      tt_sbit_decoder_done( decoder );
1006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* EOF */
1012