1a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/***************************************************************************/
2a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*                                                                         */
3a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  pfrload.c                                                              */
4a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*                                                                         */
5a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*    FreeType PFR loader (body).                                          */
6a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*                                                                         */
7a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  Copyright 2002-2005, 2007, 2009, 2010, 2013 by                         */
8a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*                                                                         */
10a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  This file is part of the FreeType project, and may only be used,       */
11a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  modified, and distributed under the terms of the FreeType project      */
12a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  this file you indicate that you have read the license and              */
14a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  understand and accept it fully.                                        */
15a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*                                                                         */
16a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/***************************************************************************/
17a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
18a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
19a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#include "pfrload.h"
20a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#include FT_INTERNAL_DEBUG_H
21a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#include FT_INTERNAL_STREAM_H
22a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
23a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#include "pfrerror.h"
24a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
25a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#undef  FT_COMPONENT
26a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#define FT_COMPONENT  trace_pfr
27a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
28a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
29a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /*************************************************************************/
30a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /*************************************************************************/
31a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /*****                                                               *****/
32a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /*****                          EXTRA ITEMS                          *****/
33a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /*****                                                               *****/
34a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /*************************************************************************/
35a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /*************************************************************************/
36a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
37a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
38a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_LOCAL_DEF( FT_Error )
39a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  pfr_extra_items_skip( FT_Byte*  *pp,
40a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                        FT_Byte*   limit )
41a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
42a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return pfr_extra_items_parse( pp, limit, NULL, NULL );
43a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
44a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
45a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
46a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_LOCAL_DEF( FT_Error )
47a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  pfr_extra_items_parse( FT_Byte*       *pp,
48a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                         FT_Byte*        limit,
49a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                         PFR_ExtraItem   item_list,
50a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                         FT_Pointer      item_data )
51a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
52a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Error  error = FT_Err_Ok;
53a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Byte*  p     = *pp;
54a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_UInt   num_items, item_type, item_size;
55a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
56a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
57a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    PFR_CHECK( 1 );
58a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    num_items = PFR_NEXT_BYTE( p );
59a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
60a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    for ( ; num_items > 0; num_items-- )
61a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    {
62a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      PFR_CHECK( 2 );
63a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      item_size = PFR_NEXT_BYTE( p );
64a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      item_type = PFR_NEXT_BYTE( p );
65a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
66a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      PFR_CHECK( item_size );
67a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
68a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( item_list )
69a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      {
70a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        PFR_ExtraItem  extra = item_list;
71a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
72a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
73a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        for ( extra = item_list; extra->parser != NULL; extra++ )
74a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        {
75a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          if ( extra->type == item_type )
76a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          {
77a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            error = extra->parser( p, p + item_size, item_data );
78a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            if ( error ) goto Exit;
79a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
80a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            break;
81a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          }
82a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        }
83a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      }
84a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
85a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      p += item_size;
86a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    }
87a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
88a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  Exit:
89a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    *pp = p;
90a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return error;
91a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
92a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  Too_Short:
93a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_ERROR(( "pfr_extra_items_parse: invalid extra items table\n" ));
94a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    error = FT_THROW( Invalid_Table );
95a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    goto Exit;
96a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
97a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
98a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
99a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /*************************************************************************/
100a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /*************************************************************************/
101a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /*****                                                               *****/
102a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /*****                          PFR HEADER                           *****/
103a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /*****                                                               *****/
104a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /*************************************************************************/
105a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /*************************************************************************/
106a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
107a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   static const FT_Frame_Field  pfr_header_fields[] =
108a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   {
109a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#undef  FT_STRUCTURE
110a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#define FT_STRUCTURE  PFR_HeaderRec
111a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
112a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang     FT_FRAME_START( 58 ),
113a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_ULONG ( signature ),
114a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_USHORT( version ),
115a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_USHORT( signature2 ),
116a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_USHORT( header_size ),
117a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
118a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_USHORT( log_dir_size ),
119a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_USHORT( log_dir_offset ),
120a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
121a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_USHORT( log_font_max_size ),
122a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_UOFF3 ( log_font_section_size ),
123a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_UOFF3 ( log_font_section_offset ),
124a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
125a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_USHORT( phy_font_max_size ),
126a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_UOFF3 ( phy_font_section_size ),
127a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_UOFF3 ( phy_font_section_offset ),
128a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
129a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_USHORT( gps_max_size ),
130a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_UOFF3 ( gps_section_size ),
131a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_UOFF3 ( gps_section_offset ),
132a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
133a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_BYTE  ( max_blue_values ),
134a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_BYTE  ( max_x_orus ),
135a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_BYTE  ( max_y_orus ),
136a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
137a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_BYTE  ( phy_font_max_size_high ),
138a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_BYTE  ( color_flags ),
139a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
140a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_UOFF3 ( bct_max_size ),
141a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_UOFF3 ( bct_set_max_size ),
142a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_UOFF3 ( phy_bct_set_max_size ),
143a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
144a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_USHORT( num_phy_fonts ),
145a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_BYTE  ( max_vert_stem_snap ),
146a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_BYTE  ( max_horz_stem_snap ),
147a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       FT_FRAME_USHORT( max_chars ),
148a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang     FT_FRAME_END
149a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   };
150a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
151a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
152a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_LOCAL_DEF( FT_Error )
153a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  pfr_header_load( PFR_Header  header,
154a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                   FT_Stream   stream )
155a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
156a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Error  error;
157a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
158a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
159a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* read header directly */
160a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( !FT_STREAM_SEEK( 0 )                                &&
161a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang         !FT_STREAM_READ_FIELDS( pfr_header_fields, header ) )
162a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    {
163a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      /* make a few adjustments to the header */
164a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      header->phy_font_max_size +=
165a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        (FT_UInt32)header->phy_font_max_size_high << 16;
166a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    }
167a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
168a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return error;
169a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
170a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
171a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
172a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_LOCAL_DEF( FT_Bool )
173a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  pfr_header_check( PFR_Header  header )
174a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
175a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Bool  result = 1;
176a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
177a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
178a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* check signature and header size */
179a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( header->signature  != 0x50465230L ||   /* "PFR0" */
180a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang         header->version     > 4           ||
181a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang         header->header_size < 58          ||
182a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang         header->signature2 != 0x0d0a      )    /* CR/LF  */
183a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    {
184a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      result = 0;
185a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    }
186a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return  result;
187a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
188a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
189a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
190a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /***********************************************************************/
191a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /***********************************************************************/
192a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /*****                                                             *****/
193a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /*****                    PFR LOGICAL FONTS                        *****/
194a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /*****                                                             *****/
195a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /***********************************************************************/
196a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /***********************************************************************/
197a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
198a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
199a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_LOCAL_DEF( FT_Error )
200a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  pfr_log_font_count( FT_Stream  stream,
201a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                      FT_UInt32  section_offset,
202a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                      FT_UInt   *acount )
203a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
204a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Error  error;
205a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_UInt   count;
206a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_UInt   result = 0;
207a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
208a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
209a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( FT_STREAM_SEEK( section_offset ) || FT_READ_USHORT( count ) )
210a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      goto Exit;
211a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
212a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    result = count;
213a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
214a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  Exit:
215a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    *acount = result;
216a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return error;
217a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
218a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
219a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
220a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_LOCAL_DEF( FT_Error )
221a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  pfr_log_font_load( PFR_LogFont  log_font,
222a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     FT_Stream    stream,
223a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     FT_UInt      idx,
224a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     FT_UInt32    section_offset,
225a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     FT_Bool      size_increment )
226a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
227a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_UInt    num_log_fonts;
228a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_UInt    flags;
229a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_UInt32  offset;
230a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_UInt32  size;
231a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Error   error;
232a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
233a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
234a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( FT_STREAM_SEEK( section_offset ) ||
235a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang         FT_READ_USHORT( num_log_fonts )  )
236a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      goto Exit;
237a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
238a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( idx >= num_log_fonts )
239a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_THROW( Invalid_Argument );
240a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
241a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( FT_STREAM_SKIP( idx * 5 ) ||
242a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang         FT_READ_USHORT( size )    ||
243a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang         FT_READ_UOFF3 ( offset )  )
244a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      goto Exit;
245a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
246a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* save logical font size and offset */
247a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    log_font->size   = size;
248a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    log_font->offset = offset;
249a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
250a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* now, check the rest of the table before loading it */
251a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    {
252a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      FT_Byte*  p;
253a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      FT_Byte*  limit;
254a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      FT_UInt   local;
255a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
256a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
257a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) )
258a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        goto Exit;
259a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
260a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      p     = stream->cursor;
261a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      limit = p + size;
262a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
263a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      PFR_CHECK(13);
264a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
265a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      log_font->matrix[0] = PFR_NEXT_LONG( p );
266a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      log_font->matrix[1] = PFR_NEXT_LONG( p );
267a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      log_font->matrix[2] = PFR_NEXT_LONG( p );
268a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      log_font->matrix[3] = PFR_NEXT_LONG( p );
269a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
270a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      flags = PFR_NEXT_BYTE( p );
271a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
272a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      local = 0;
273a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( flags & PFR_LOG_STROKE )
274a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      {
275a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        local++;
276a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( flags & PFR_LOG_2BYTE_STROKE )
277a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          local++;
278a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
279a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( (flags & PFR_LINE_JOIN_MASK) == PFR_LINE_JOIN_MITER )
280a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          local += 3;
281a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      }
282a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( flags & PFR_LOG_BOLD )
283a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      {
284a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        local++;
285a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( flags & PFR_LOG_2BYTE_BOLD )
286a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          local++;
287a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      }
288a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
289a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      PFR_CHECK( local );
290a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
291a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( flags & PFR_LOG_STROKE )
292a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      {
293a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        log_font->stroke_thickness = ( flags & PFR_LOG_2BYTE_STROKE )
294a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                     ? PFR_NEXT_SHORT( p )
295a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                     : PFR_NEXT_BYTE( p );
296a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
297a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( ( flags & PFR_LINE_JOIN_MASK ) == PFR_LINE_JOIN_MITER )
298a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          log_font->miter_limit = PFR_NEXT_LONG( p );
299a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      }
300a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
301a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( flags & PFR_LOG_BOLD )
302a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      {
303a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        log_font->bold_thickness = ( flags & PFR_LOG_2BYTE_BOLD )
304a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                   ? PFR_NEXT_SHORT( p )
305a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                   : PFR_NEXT_BYTE( p );
306a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      }
307a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
308a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( flags & PFR_LOG_EXTRA_ITEMS )
309a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      {
310a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        error = pfr_extra_items_skip( &p, limit );
311a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if (error) goto Fail;
312a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      }
313a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
314a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      PFR_CHECK(5);
315a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      log_font->phys_size   = PFR_NEXT_USHORT( p );
316a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      log_font->phys_offset = PFR_NEXT_ULONG( p );
317a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( size_increment )
318a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      {
319a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        PFR_CHECK( 1 );
320a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        log_font->phys_size += (FT_UInt32)PFR_NEXT_BYTE( p ) << 16;
321a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      }
322a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    }
323a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
324a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  Fail:
325a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_FRAME_EXIT();
326a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
327a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  Exit:
328a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return error;
329a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
330a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  Too_Short:
331a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_ERROR(( "pfr_log_font_load: invalid logical font table\n" ));
332a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    error = FT_THROW( Invalid_Table );
333a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    goto Fail;
334a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
335a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
336a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
337a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /***********************************************************************/
338a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /***********************************************************************/
339a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /*****                                                             *****/
340a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /*****                    PFR PHYSICAL FONTS                       *****/
341a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /*****                                                             *****/
342a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /***********************************************************************/
343a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /***********************************************************************/
344a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
345a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
346a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /* load bitmap strikes lists */
347a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_CALLBACK_DEF( FT_Error )
348a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  pfr_extra_item_load_bitmap_info( FT_Byte*     p,
349a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                   FT_Byte*     limit,
350a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                   PFR_PhyFont  phy_font )
351a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
352a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Memory   memory = phy_font->memory;
353a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    PFR_Strike  strike;
354a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_UInt     flags0;
355a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_UInt     n, count, size1;
356a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Error    error = FT_Err_Ok;
357a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
358a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
359a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    PFR_CHECK( 5 );
360a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
361a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    p += 3;  /* skip bctSize */
362a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    flags0 = PFR_NEXT_BYTE( p );
363a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    count  = PFR_NEXT_BYTE( p );
364a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
365a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* re-allocate when needed */
366a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( phy_font->num_strikes + count > phy_font->max_strikes )
367a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    {
368a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      FT_UInt  new_max = FT_PAD_CEIL( phy_font->num_strikes + count, 4 );
369a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
370a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
371a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( FT_RENEW_ARRAY( phy_font->strikes,
372a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                           phy_font->num_strikes,
373a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                           new_max ) )
374a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        goto Exit;
375a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
376a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      phy_font->max_strikes = new_max;
377a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    }
378a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
379a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    size1 = 1 + 1 + 1 + 2 + 2 + 1;
380a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( flags0 & PFR_STRIKE_2BYTE_XPPM )
381a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      size1++;
382a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
383a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( flags0 & PFR_STRIKE_2BYTE_YPPM )
384a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      size1++;
385a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
386a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( flags0 & PFR_STRIKE_3BYTE_SIZE )
387a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      size1++;
388a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
389a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( flags0 & PFR_STRIKE_3BYTE_OFFSET )
390a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      size1++;
391a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
392a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( flags0 & PFR_STRIKE_2BYTE_COUNT )
393a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      size1++;
394a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
395a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    strike = phy_font->strikes + phy_font->num_strikes;
396a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
397a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    PFR_CHECK( count * size1 );
398a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
399a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    for ( n = 0; n < count; n++, strike++ )
400a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    {
401a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      strike->x_ppm       = ( flags0 & PFR_STRIKE_2BYTE_XPPM )
402a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                            ? PFR_NEXT_USHORT( p )
403a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                            : PFR_NEXT_BYTE( p );
404a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
405a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      strike->y_ppm       = ( flags0 & PFR_STRIKE_2BYTE_YPPM )
406a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                            ? PFR_NEXT_USHORT( p )
407a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                            : PFR_NEXT_BYTE( p );
408a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
409a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      strike->flags       = PFR_NEXT_BYTE( p );
410a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
411a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      strike->bct_size    = ( flags0 & PFR_STRIKE_3BYTE_SIZE )
412a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                            ? PFR_NEXT_ULONG( p )
413a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                            : PFR_NEXT_USHORT( p );
414a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
415a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      strike->bct_offset  = ( flags0 & PFR_STRIKE_3BYTE_OFFSET )
416a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                            ? PFR_NEXT_ULONG( p )
417a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                            : PFR_NEXT_USHORT( p );
418a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
419a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      strike->num_bitmaps = ( flags0 & PFR_STRIKE_2BYTE_COUNT )
420a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                            ? PFR_NEXT_USHORT( p )
421a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                            : PFR_NEXT_BYTE( p );
422a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    }
423a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
424a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->num_strikes += count;
425a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
426a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  Exit:
427a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return error;
428a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
429a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  Too_Short:
430a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    error = FT_THROW( Invalid_Table );
431a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_ERROR(( "pfr_extra_item_load_bitmap_info:"
432a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang               " invalid bitmap info table\n" ));
433a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    goto Exit;
434a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
435a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
436a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
437a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /* Load font ID.  This is a so-called "unique" name that is rather
438a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   * long and descriptive (like "Tiresias ScreenFont v7.51").
439a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   *
440a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   * Note that a PFR font's family name is contained in an *undocumented*
441a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   * string of the "auxiliary data" portion of a physical font record.  This
442a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   * may also contain the "real" style name!
443a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   *
444a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   * If no family name is present, the font ID is used instead for the
445a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   * family.
446a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   */
447a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_CALLBACK_DEF( FT_Error )
448a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  pfr_extra_item_load_font_id( FT_Byte*     p,
449a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                               FT_Byte*     limit,
450a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                               PFR_PhyFont  phy_font )
451a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
452a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Error    error  = FT_Err_Ok;
453a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Memory   memory = phy_font->memory;
454a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_PtrDist  len    = limit - p;
455a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
456a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
457a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( phy_font->font_id != NULL )
458a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      goto Exit;
459a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
460a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( FT_ALLOC( phy_font->font_id, len + 1 ) )
461a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      goto Exit;
462a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
463a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* copy font ID name, and terminate it for safety */
464a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_MEM_COPY( phy_font->font_id, p, len );
465a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->font_id[len] = 0;
466a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
467a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  Exit:
468a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return error;
469a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
470a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
471a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
472a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /* load stem snap tables */
473a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_CALLBACK_DEF( FT_Error )
474a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  pfr_extra_item_load_stem_snaps( FT_Byte*     p,
475a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                  FT_Byte*     limit,
476a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                  PFR_PhyFont  phy_font )
477a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
478a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_UInt    count, num_vert, num_horz;
479a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Int*    snaps  = NULL;
480a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Error   error  = FT_Err_Ok;
481a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Memory  memory = phy_font->memory;
482a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
483a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
484a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( phy_font->vertical.stem_snaps != NULL )
485a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      goto Exit;
486a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
487a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    PFR_CHECK( 1 );
488a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    count = PFR_NEXT_BYTE( p );
489a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
490a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    num_vert = count & 15;
491a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    num_horz = count >> 4;
492a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    count    = num_vert + num_horz;
493a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
494a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    PFR_CHECK( count * 2 );
495a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
496a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( FT_NEW_ARRAY( snaps, count ) )
497a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      goto Exit;
498a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
499a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->vertical.stem_snaps = snaps;
500a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->horizontal.stem_snaps = snaps + num_vert;
501a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
502a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    for ( ; count > 0; count--, snaps++ )
503a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      *snaps = FT_NEXT_SHORT( p );
504a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
505a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  Exit:
506a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return error;
507a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
508a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  Too_Short:
509a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    error = FT_THROW( Invalid_Table );
510a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_ERROR(( "pfr_exta_item_load_stem_snaps:"
511a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang               " invalid stem snaps table\n" ));
512a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    goto Exit;
513a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
514a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
515a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
516a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
517a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /* load kerning pair data */
518a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_CALLBACK_DEF( FT_Error )
519a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  pfr_extra_item_load_kerning_pairs( FT_Byte*     p,
520a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                     FT_Byte*     limit,
521a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                     PFR_PhyFont  phy_font )
522a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
523a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    PFR_KernItem  item   = NULL;
524a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Error      error  = FT_Err_Ok;
525a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Memory     memory = phy_font->memory;
526a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
527a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
528a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_TRACE2(( "pfr_extra_item_load_kerning_pairs()\n" ));
529a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
530a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( FT_NEW( item ) )
531a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      goto Exit;
532a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
533a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    PFR_CHECK( 4 );
534a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
535a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    item->pair_count = PFR_NEXT_BYTE( p );
536a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    item->base_adj   = PFR_NEXT_SHORT( p );
537a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    item->flags      = PFR_NEXT_BYTE( p );
538a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    item->offset     = phy_font->offset + ( p - phy_font->cursor );
539a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
540a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#ifndef PFR_CONFIG_NO_CHECKS
541a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    item->pair_size = 3;
542a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
543a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( item->flags & PFR_KERN_2BYTE_CHAR )
544a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      item->pair_size += 2;
545a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
546a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( item->flags & PFR_KERN_2BYTE_ADJ )
547a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      item->pair_size += 1;
548a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
549a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    PFR_CHECK( item->pair_count * item->pair_size );
550a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#endif
551a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
552a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* load first and last pairs into the item to speed up */
553a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* lookup later...                                     */
554a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( item->pair_count > 0 )
555a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    {
556a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      FT_UInt   char1, char2;
557a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      FT_Byte*  q;
558a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
559a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
560a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( item->flags & PFR_KERN_2BYTE_CHAR )
561a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      {
562a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        q     = p;
563a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        char1 = PFR_NEXT_USHORT( q );
564a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        char2 = PFR_NEXT_USHORT( q );
565a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
566a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        item->pair1 = PFR_KERN_INDEX( char1, char2 );
567a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
568a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        q = p + item->pair_size * ( item->pair_count - 1 );
569a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        char1 = PFR_NEXT_USHORT( q );
570a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        char2 = PFR_NEXT_USHORT( q );
571a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
572a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        item->pair2 = PFR_KERN_INDEX( char1, char2 );
573a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      }
574a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      else
575a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      {
576a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        q     = p;
577a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        char1 = PFR_NEXT_BYTE( q );
578a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        char2 = PFR_NEXT_BYTE( q );
579a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
580a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        item->pair1 = PFR_KERN_INDEX( char1, char2 );
581a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
582a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        q = p + item->pair_size * ( item->pair_count - 1 );
583a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        char1 = PFR_NEXT_BYTE( q );
584a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        char2 = PFR_NEXT_BYTE( q );
585a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
586a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        item->pair2 = PFR_KERN_INDEX( char1, char2 );
587a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      }
588a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
589a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      /* add new item to the current list */
590a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      item->next                 = NULL;
591a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      *phy_font->kern_items_tail = item;
592a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      phy_font->kern_items_tail  = &item->next;
593a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      phy_font->num_kern_pairs  += item->pair_count;
594a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    }
595a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    else
596a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    {
597a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      /* empty item! */
598a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      FT_FREE( item );
599a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    }
600a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
601a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  Exit:
602a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return error;
603a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
604a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  Too_Short:
605a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_FREE( item );
606a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
607a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    error = FT_THROW( Invalid_Table );
608a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_ERROR(( "pfr_extra_item_load_kerning_pairs:"
609a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang               " invalid kerning pairs table\n" ));
610a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    goto Exit;
611a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
612a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
613a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
614a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
615a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  static const PFR_ExtraItemRec  pfr_phy_font_extra_items[] =
616a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
617a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    { 1, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_bitmap_info },
618a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    { 2, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_font_id },
619a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    { 3, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_stem_snaps },
620a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    { 4, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_kerning_pairs },
621a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    { 0, NULL }
622a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  };
623a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
624a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
625a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /* Loads a name from the auxiliary data.  Since this extracts undocumented
626a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   * strings from the font file, we need to be careful here.
627a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   */
628a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  static FT_Error
629a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  pfr_aux_name_load( FT_Byte*     p,
630a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     FT_UInt      len,
631a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     FT_Memory    memory,
632a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     FT_String*  *astring )
633a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
634a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Error    error  = FT_Err_Ok;
635a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_String*  result = NULL;
636a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_UInt     n, ok;
637a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
638a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
639a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( len > 0 && p[len - 1] == 0 )
640a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      len--;
641a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
642a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* check that each character is ASCII for making sure not to
643a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       load garbage
644a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang     */
645a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    ok = ( len > 0 );
646a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    for ( n = 0; n < len; n++ )
647a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( p[n] < 32 || p[n] > 127 )
648a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      {
649a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        ok = 0;
650a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        break;
651a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      }
652a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
653a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( ok )
654a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    {
655a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( FT_ALLOC( result, len + 1 ) )
656a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        goto Exit;
657a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
658a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      FT_MEM_COPY( result, p, len );
659a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      result[len] = 0;
660a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    }
661a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  Exit:
662a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    *astring = result;
663a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return error;
664a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
665a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
666a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
667a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_LOCAL_DEF( void )
668a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  pfr_phy_font_done( PFR_PhyFont  phy_font,
669a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     FT_Memory    memory )
670a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
671a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_FREE( phy_font->font_id );
672a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_FREE( phy_font->family_name );
673a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_FREE( phy_font->style_name );
674a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
675a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_FREE( phy_font->vertical.stem_snaps );
676a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->vertical.num_stem_snaps = 0;
677a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
678a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->horizontal.stem_snaps     = NULL;
679a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->horizontal.num_stem_snaps = 0;
680a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
681a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_FREE( phy_font->strikes );
682a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->num_strikes = 0;
683a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->max_strikes = 0;
684a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
685a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_FREE( phy_font->chars );
686a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->num_chars    = 0;
687a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->chars_offset = 0;
688a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
689a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_FREE( phy_font->blue_values );
690a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->num_blue_values = 0;
691a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
692a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    {
693a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      PFR_KernItem  item, next;
694a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
695a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
696a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      item = phy_font->kern_items;
697a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      while ( item )
698a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      {
699a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        next = item->next;
700a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        FT_FREE( item );
701a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        item = next;
702a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      }
703a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      phy_font->kern_items      = NULL;
704a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      phy_font->kern_items_tail = NULL;
705a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    }
706a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
707a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->num_kern_pairs = 0;
708a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
709a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
710a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
711a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_LOCAL_DEF( FT_Error )
712a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  pfr_phy_font_load( PFR_PhyFont  phy_font,
713a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     FT_Stream    stream,
714a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     FT_UInt32    offset,
715a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     FT_UInt32    size )
716a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
717a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Error   error;
718a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Memory  memory = stream->memory;
719a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_UInt    flags;
720a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_ULong   num_aux;
721a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Byte*   p;
722a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Byte*   limit;
723a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
724a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
725a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->memory = memory;
726a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->offset = offset;
727a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
728a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->kern_items      = NULL;
729a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->kern_items_tail = &phy_font->kern_items;
730a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
731a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) )
732a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      goto Exit;
733a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
734a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->cursor = stream->cursor;
735a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
736a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    p     = stream->cursor;
737a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    limit = p + size;
738a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
739a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    PFR_CHECK( 15 );
740a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->font_ref_number    = PFR_NEXT_USHORT( p );
741a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->outline_resolution = PFR_NEXT_USHORT( p );
742a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->metrics_resolution = PFR_NEXT_USHORT( p );
743a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->bbox.xMin          = PFR_NEXT_SHORT( p );
744a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->bbox.yMin          = PFR_NEXT_SHORT( p );
745a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->bbox.xMax          = PFR_NEXT_SHORT( p );
746a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->bbox.yMax          = PFR_NEXT_SHORT( p );
747a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->flags      = flags = PFR_NEXT_BYTE( p );
748a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
749a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* get the standard advance for non-proportional fonts */
750a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( !(flags & PFR_PHY_PROPORTIONAL) )
751a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    {
752a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      PFR_CHECK( 2 );
753a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      phy_font->standard_advance = PFR_NEXT_SHORT( p );
754a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    }
755a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
756a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* load the extra items when present */
757a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( flags & PFR_PHY_EXTRA_ITEMS )
758a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    {
759a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      error =  pfr_extra_items_parse( &p, limit,
760a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                      pfr_phy_font_extra_items, phy_font );
761a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
762a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( error )
763a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        goto Fail;
764a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    }
765a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
766a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* In certain fonts, the auxiliary bytes contain interesting  */
767a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* information. These are not in the specification but can be */
768a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* guessed by looking at the content of a few PFR0 fonts.     */
769a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    PFR_CHECK( 3 );
770a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    num_aux = PFR_NEXT_ULONG( p );
771a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
772a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( num_aux > 0 )
773a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    {
774a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      FT_Byte*  q = p;
775a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      FT_Byte*  q2;
776a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
777a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
778a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      PFR_CHECK( num_aux );
779a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      p += num_aux;
780a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
781a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      while ( num_aux > 0 )
782a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      {
783a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        FT_UInt  length, type;
784a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
785a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
786a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( q + 4 > p )
787a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          break;
788a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
789a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        length = PFR_NEXT_USHORT( q );
790a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( length < 4 || length > num_aux )
791a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          break;
792a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
793a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        q2   = q + length - 2;
794a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        type = PFR_NEXT_USHORT( q );
795a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
796a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        switch ( type )
797a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        {
798a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        case 1:
799a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          /* this seems to correspond to the font's family name,
800a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang           * padded to 16-bits with one zero when necessary
801a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang           */
802a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          error = pfr_aux_name_load( q, length - 4U, memory,
803a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                     &phy_font->family_name );
804a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          if ( error )
805a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            goto Exit;
806a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          break;
807a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
808a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        case 2:
809a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          if ( q + 32 > q2 )
810a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            break;
811a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
812a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          q += 10;
813a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          phy_font->ascent  = PFR_NEXT_SHORT( q );
814a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          phy_font->descent = PFR_NEXT_SHORT( q );
815a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          phy_font->leading = PFR_NEXT_SHORT( q );
816a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          q += 16;
817a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          break;
818a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
819a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        case 3:
820a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          /* this seems to correspond to the font's style name,
821a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang           * padded to 16-bits with one zero when necessary
822a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang           */
823a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          error = pfr_aux_name_load( q, length - 4U, memory,
824a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                     &phy_font->style_name );
825a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          if ( error )
826a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            goto Exit;
827a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          break;
828a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
829a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        default:
830a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          ;
831a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        }
832a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
833a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        q        = q2;
834a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        num_aux -= length;
835a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      }
836a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    }
837a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
838a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* read the blue values */
839a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    {
840a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      FT_UInt  n, count;
841a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
842a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
843a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      PFR_CHECK( 1 );
844a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      phy_font->num_blue_values = count = PFR_NEXT_BYTE( p );
845a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
846a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      PFR_CHECK( count * 2 );
847a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
848a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( FT_NEW_ARRAY( phy_font->blue_values, count ) )
849a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        goto Fail;
850a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
851a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      for ( n = 0; n < count; n++ )
852a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        phy_font->blue_values[n] = PFR_NEXT_SHORT( p );
853a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    }
854a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
855a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    PFR_CHECK( 8 );
856a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->blue_fuzz  = PFR_NEXT_BYTE( p );
857a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->blue_scale = PFR_NEXT_BYTE( p );
858a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
859a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->vertical.standard   = PFR_NEXT_USHORT( p );
860a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->horizontal.standard = PFR_NEXT_USHORT( p );
861a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
862a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* read the character descriptors */
863a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    {
864a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      FT_UInt  n, count, Size;
865a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
866a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
867a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      phy_font->num_chars    = count = PFR_NEXT_USHORT( p );
868a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      phy_font->chars_offset = offset + ( p - stream->cursor );
869a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
870a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( FT_NEW_ARRAY( phy_font->chars, count ) )
871a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        goto Fail;
872a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
873a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      Size = 1 + 1 + 2;
874a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( flags & PFR_PHY_2BYTE_CHARCODE )
875a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        Size += 1;
876a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
877a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( flags & PFR_PHY_PROPORTIONAL )
878a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        Size += 2;
879a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
880a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( flags & PFR_PHY_ASCII_CODE )
881a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        Size += 1;
882a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
883a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( flags & PFR_PHY_2BYTE_GPS_SIZE )
884a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        Size += 1;
885a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
886a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( flags & PFR_PHY_3BYTE_GPS_OFFSET )
887a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        Size += 1;
888a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
889a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      PFR_CHECK( count * Size );
890a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
891a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      for ( n = 0; n < count; n++ )
892a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      {
893a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        PFR_Char  cur = &phy_font->chars[n];
894a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
895a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
896a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        cur->char_code = ( flags & PFR_PHY_2BYTE_CHARCODE )
897a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                         ? PFR_NEXT_USHORT( p )
898a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                         : PFR_NEXT_BYTE( p );
899a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
900a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        cur->advance   = ( flags & PFR_PHY_PROPORTIONAL )
901a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                         ? PFR_NEXT_SHORT( p )
902a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                         : (FT_Int) phy_font->standard_advance;
903a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
904a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#if 0
905a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        cur->ascii     = ( flags & PFR_PHY_ASCII_CODE )
906a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                         ? PFR_NEXT_BYTE( p )
907a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                         : 0;
908a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#else
909a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( flags & PFR_PHY_ASCII_CODE )
910a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          p += 1;
911a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#endif
912a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        cur->gps_size  = ( flags & PFR_PHY_2BYTE_GPS_SIZE )
913a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                         ? PFR_NEXT_USHORT( p )
914a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                         : PFR_NEXT_BYTE( p );
915a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
916a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        cur->gps_offset = ( flags & PFR_PHY_3BYTE_GPS_OFFSET )
917a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          ? PFR_NEXT_ULONG( p )
918a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          : PFR_NEXT_USHORT( p );
919a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      }
920a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    }
921a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
922a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* that's it! */
923a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
924a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  Fail:
925a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_FRAME_EXIT();
926a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
927a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* save position of bitmap info */
928a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->bct_offset = FT_STREAM_POS();
929a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    phy_font->cursor     = NULL;
930a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
931a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  Exit:
932a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return error;
933a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
934a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  Too_Short:
935a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    error = FT_THROW( Invalid_Table );
936a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_ERROR(( "pfr_phy_font_load: invalid physical font table\n" ));
937a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    goto Fail;
938a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
939a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
940a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
941a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/* END */
942