1049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
2049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
3049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  ttpload.c                                                              */
4049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
5049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*    TrueType-specific tables loader (body).                              */
6049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
7a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  Copyright 1996-2002, 2004-2013 by                                      */
8049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
10049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  This file is part of the FreeType project, and may only be used,       */
11049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  modified, and distributed under the terms of the FreeType project      */
12049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  this file you indicate that you have read the license and              */
14049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  understand and accept it fully.                                        */
15049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
16049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
17049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
18049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
19049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include <ft2build.h>
20049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_DEBUG_H
21049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_OBJECTS_H
22049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_STREAM_H
23049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_TRUETYPE_TAGS_H
24049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
25049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "ttpload.h"
26049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
27049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
28049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "ttgxvar.h"
29049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
30049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
31049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "tterrors.h"
32049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
33049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
34049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
35049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
36049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
37049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
38049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* messages during execution.                                            */
39049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
40049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#undef  FT_COMPONENT
41049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_COMPONENT  trace_ttpload
42049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
43049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
44049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
45049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
46049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
47049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    tt_face_load_loca                                                  */
48049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
49049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
50049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Load the locations table.                                          */
51049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
52049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <InOut>                                                               */
53049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    face   :: A handle to the target face object.                      */
54049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
55049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Input>                                                               */
56049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    stream :: The input stream.                                        */
57049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
58049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Return>                                                              */
59049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    FreeType error code.  0 means success.                             */
60049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
61049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
62049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_face_load_loca( TT_Face    face,
63049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Stream  stream )
64049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
65049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error  error;
66049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  table_len;
670a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    FT_Int    shift;
68049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
69049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
70049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* we need the size of the `glyf' table for malformed `loca' tables */
71049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = face->goto_table( face, TTAG_glyf, stream, &face->glyf_len );
720a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
730a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    /* it is possible that a font doesn't have a glyf table at all */
740a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    /* or its size is zero                                         */
75a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( FT_ERR_EQ( error, Table_Missing ) )
760a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      face->glyf_len = 0;
770a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    else if ( error )
78049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
79049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
80049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_TRACE2(( "Locations " ));
81049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = face->goto_table( face, TTAG_loca, stream, &table_len );
82049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( error )
83049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
84a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      error = FT_THROW( Locations_Missing );
85049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
86049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
87049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
88049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( face->header.Index_To_Loc_Format != 0 )
89049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
900a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      shift = 2;
910a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
92049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( table_len >= 0x40000L )
93049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
94295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        FT_TRACE2(( "table too large\n" ));
95a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        error = FT_THROW( Invalid_Table );
96049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
97049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
98295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      face->num_locations = table_len >> shift;
99049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1020a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      shift = 1;
1030a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( table_len >= 0x20000L )
105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
106295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        FT_TRACE2(( "table too large\n" ));
107a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        error = FT_THROW( Invalid_Table );
108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
110295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      face->num_locations = table_len >> shift;
1110a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    }
1120a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
113c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    if ( face->num_locations != (FT_ULong)face->root.num_glyphs + 1 )
1140a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    {
1150a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      FT_TRACE2(( "glyph count mismatch!  loca: %d, maxp: %d\n",
116c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                  face->num_locations - 1, face->root.num_glyphs ));
1170a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1180a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      /* we only handle the case where `maxp' gives a larger value */
119c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner      if ( face->num_locations <= (FT_ULong)face->root.num_glyphs )
1200a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      {
121c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner        FT_Long   new_loca_len =
122c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner                    ( (FT_Long)( face->root.num_glyphs ) + 1 ) << shift;
1230a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1240a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project        TT_Table  entry = face->dir_tables;
1250a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project        TT_Table  limit = entry + face->num_tables;
1260a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1270a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project        FT_Long   pos  = FT_Stream_Pos( stream );
1280a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project        FT_Long   dist = 0x7FFFFFFFL;
1290a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1300a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1310a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project        /* compute the distance to next table in font file */
1320a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project        for ( ; entry < limit; entry++ )
1330a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project        {
1340a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project          FT_Long  diff = entry->Offset - pos;
1350a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1360a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1370a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project          if ( diff > 0 && diff < dist )
1380a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            dist = diff;
1390a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project        }
1400a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1418583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        if ( entry == limit )
1428583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        {
1438583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner          /* `loca' is the last table */
1448583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner          dist = stream->size - pos;
1458583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        }
1468583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner
1470a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project        if ( new_loca_len <= dist )
1480a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project        {
149c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner          face->num_locations = face->root.num_glyphs + 1;
1500a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project          table_len           = new_loca_len;
1510a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1520a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project          FT_TRACE2(( "adjusting num_locations to %d\n",
1530a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                      face->num_locations ));
1540a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project        }
1550a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      }
156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*
159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * Extract the frame.  We don't need to decompress it since
160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * we are able to parse it directly.
161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_FRAME_EXTRACT( table_len, face->glyph_locations ) )
163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_TRACE2(( "loaded\n" ));
166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_ULong )
173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_face_get_location( TT_Face   face,
174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        FT_UInt   gindex,
175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        FT_UInt  *asize )
176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  pos1, pos2;
178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p;
179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p_limit;
180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    pos1 = pos2 = 0;
183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( gindex < face->num_locations )
185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( face->header.Index_To_Loc_Format != 0 )
187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p       = face->glyph_locations + gindex * 4;
189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p_limit = face->glyph_locations + face->num_locations * 4;
190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        pos1 = FT_NEXT_ULONG( p );
192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        pos2 = pos1;
193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( p + 4 <= p_limit )
195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          pos2 = FT_NEXT_ULONG( p );
196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p       = face->glyph_locations + gindex * 2;
200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p_limit = face->glyph_locations + face->num_locations * 2;
201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        pos1 = FT_NEXT_USHORT( p );
203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        pos2 = pos1;
204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( p + 2 <= p_limit )
206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          pos2 = FT_NEXT_USHORT( p );
207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        pos1 <<= 1;
209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        pos2 <<= 1;
210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2138583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner    /* Check broken location data */
214e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    if ( pos1 > face->glyf_len )
2158583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner    {
2168583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner      FT_TRACE1(( "tt_face_get_location:"
217e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang                  " too large offset=0x%08lx found for gid=0x%04lx,"
218e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang                  " exceeding the end of glyf table (0x%08lx)\n",
219e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang                  pos1, gindex, face->glyf_len ));
2208583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner      *asize = 0;
2218583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner      return 0;
2228583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner    }
2238583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner
224e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    if ( pos2 > face->glyf_len )
2258583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner    {
2268583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner      FT_TRACE1(( "tt_face_get_location:"
227e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang                  " too large offset=0x%08lx found for gid=0x%04lx,"
228e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang                  " truncate at the end of glyf table (0x%08lx)\n",
229e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang                  pos2, gindex + 1, face->glyf_len ));
2308583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner      pos2 = face->glyf_len;
2318583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner    }
2328583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner
233295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* The `loca' table must be ordered; it refers to the length of */
234295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* an entry as the difference between the current and the next  */
235295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* position.  However, there do exist (malformed) fonts which   */
236295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* don't obey this rule, so we are only able to provide an      */
237295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* upper bound for the size.                                    */
2380a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    /*                                                              */
2390a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    /* We get (intentionally) a wrong, non-zero result in case the  */
2400a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    /* `glyf' table is missing.                                     */
241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( pos2 >= pos1 )
242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      *asize = (FT_UInt)( pos2 - pos1 );
243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      *asize = (FT_UInt)( face->glyf_len - pos1 );
245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return pos1;
247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_face_done_loca( TT_Face  face )
252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Stream  stream = face->root.stream;
254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FRAME_RELEASE( face->glyph_locations );
257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    face->num_locations = 0;
258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    tt_face_load_cvt                                                   */
266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Load the control value table into a face object.                   */
269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <InOut>                                                               */
271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    face   :: A handle to the target face object.                      */
272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Input>                                                               */
274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    stream :: A handle to the input stream.                            */
275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Return>                                                              */
277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    FreeType error code.  0 means success.                             */
278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_face_load_cvt( TT_Face    face,
281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    FT_Stream  stream )
282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_USE_BYTECODE_INTERPRETER
284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error   error;
286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory  memory = stream->memory;
287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong   table_len;
288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_TRACE2(( "CVT " ));
291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = face->goto_table( face, TTAG_cvt, stream, &table_len );
293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( error )
294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
295295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_TRACE2(( "is missing\n" ));
296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      face->cvt_size = 0;
298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      face->cvt      = NULL;
299a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      error          = FT_Err_Ok;
300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    face->cvt_size = table_len / 2;
305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_NEW_ARRAY( face->cvt, face->cvt_size ) )
307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_FRAME_ENTER( face->cvt_size * 2L ) )
310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Short*  cur   = face->cvt;
314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Short*  limit = cur + face->cvt_size;
315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3178583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner      for ( ; cur < limit; cur++ )
318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *cur = FT_GET_SHORT();
319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FRAME_EXIT();
322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_TRACE2(( "loaded\n" ));
323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( face->doblend )
326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = tt_face_vary_cvt( face, stream );
327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else /* !TT_USE_BYTECODE_INTERPRETER */
333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( face   );
335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( stream );
336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
337a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    tt_face_load_fpgm                                                  */
347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Load the font program.                                             */
350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <InOut>                                                               */
352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    face   :: A handle to the target face object.                      */
353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Input>                                                               */
355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    stream :: A handle to the input stream.                            */
356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Return>                                                              */
358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    FreeType error code.  0 means success.                             */
359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_face_load_fpgm( TT_Face    face,
362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Stream  stream )
363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_USE_BYTECODE_INTERPRETER
365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error  error;
367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  table_len;
368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_TRACE2(( "Font program " ));
371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* The font program is optional */
373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = face->goto_table( face, TTAG_fpgm, stream, &table_len );
374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( error )
375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      face->font_program      = NULL;
377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      face->font_program_size = 0;
378a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      error                   = FT_Err_Ok;
379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
380295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_TRACE2(( "is missing\n" ));
381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      face->font_program_size = table_len;
385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_FRAME_EXTRACT( table_len, face->font_program ) )
386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_TRACE2(( "loaded, %12d bytes\n", face->font_program_size ));
389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else /* !TT_USE_BYTECODE_INTERPRETER */
395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( face   );
397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( stream );
398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
399a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    tt_face_load_prep                                                  */
409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Load the cvt program.                                              */
412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <InOut>                                                               */
414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    face   :: A handle to the target face object.                      */
415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Input>                                                               */
417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    stream :: A handle to the input stream.                            */
418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Return>                                                              */
420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    FreeType error code.  0 means success.                             */
421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_face_load_prep( TT_Face    face,
424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Stream  stream )
425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_USE_BYTECODE_INTERPRETER
427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error  error;
429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  table_len;
430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_TRACE2(( "Prep program " ));
433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = face->goto_table( face, TTAG_prep, stream, &table_len );
435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( error )
436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      face->cvt_program      = NULL;
438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      face->cvt_program_size = 0;
439a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      error                  = FT_Err_Ok;
440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
441295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_TRACE2(( "is missing\n" ));
442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      face->cvt_program_size = table_len;
446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_FRAME_EXTRACT( table_len, face->cvt_program ) )
447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_TRACE2(( "loaded, %12d bytes\n", face->cvt_program_size ));
450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else /* !TT_USE_BYTECODE_INTERPRETER */
456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( face   );
458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( stream );
459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
460a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
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  /*                                                                       */
468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    tt_face_load_hdmx                                                  */
470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Load the `hdmx' table into the face object.                        */
473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Input>                                                               */
475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    face   :: A handle to the target face object.                      */
476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    stream :: A handle to the input stream.                            */
478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Return>                                                              */
480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    FreeType error code.  0 means success.                             */
481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_face_load_hdmx( TT_Face    face,
485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Stream  stream )
486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error   error;
488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory  memory = stream->memory;
489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    version, nn, num_records;
490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong   table_size, record_size;
491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p;
492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   limit;
493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* this table is optional */
496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = face->goto_table( face, TTAG_hdmx, stream, &table_size );
497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( error || table_size < 8 )
498a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_Err_Ok;
499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_FRAME_EXTRACT( table_size, face->hdmx_table ) )
501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p     = face->hdmx_table;
504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    limit = p + table_size;
505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    version     = FT_NEXT_USHORT( p );
507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_records = FT_NEXT_USHORT( p );
508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    record_size = FT_NEXT_ULONG( p );
509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* The maximum number of bytes in an hdmx device record is the */
511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* maximum number of glyphs + 2; this is 0xFFFF + 2; this is   */
512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* the reason why `record_size' is a long (which we read as    */
513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* unsigned long for convenience).  In practice, two bytes     */
514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* sufficient to hold the size value.                          */
515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                             */
516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* There are at least two fonts, HANNOM-A and HANNOM-B version */
517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* 2.0 (2005), which get this wrong: The upper two bytes of    */
518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* the size value are set to 0xFF instead of 0x00.  We catch   */
519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* and fix this.                                               */
520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( record_size >= 0xFFFF0000UL )
522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      record_size &= 0xFFFFU;
523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* The limit for `num_records' is a heuristic value. */
525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( version != 0 || num_records > 255 || record_size > 0x10001L )
527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
528a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      error = FT_THROW( Invalid_File_Format );
529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Fail;
530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_NEW_ARRAY( face->hdmx_record_sizes, num_records ) )
533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Fail;
534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( nn = 0; nn < num_records; nn++ )
536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( p + record_size > limit )
538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      face->hdmx_record_sizes[nn] = p[0];
541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p                          += record_size;
542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    face->hdmx_record_count = nn;
545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    face->hdmx_table_size   = table_size;
546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    face->hdmx_record_size  = record_size;
547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Fail:
552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FRAME_RELEASE( face->hdmx_table );
553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    face->hdmx_table_size = 0;
554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    goto Exit;
555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_face_free_hdmx( TT_Face  face )
560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Stream  stream = face->root.stream;
562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory  memory = stream->memory;
563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FREE( face->hdmx_record_sizes );
566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FRAME_RELEASE( face->hdmx_table );
567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Return the advance width table for a given pixel size if it is found  */
573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* in the font's `hdmx' table (if any).                                  */
574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Byte* )
576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_face_get_device_metrics( TT_Face  face,
577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              FT_UInt  ppem,
578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              FT_UInt  gindex )
579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   nn;
581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  result      = NULL;
582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  record_size = face->hdmx_record_size;
583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  record      = face->hdmx_table + 8;
584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( nn = 0; nn < face->hdmx_record_count; nn++ )
587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( face->hdmx_record_sizes[nn] == ppem )
588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gindex += 2;
590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( gindex < record_size )
591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          result = record + nn * record_size + gindex;
592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return result;
596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* END */
600