ttcmap.c revision 77f63d23f7d380b0ff02c18fd6a154ab9063128a
1049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
2049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
3049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  ttcmap.c                                                               */
4049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
5049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*    TrueType character mapping table (cmap) support (body).              */
6049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner/*  Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 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
22049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "sferrors.h"           /* must come before FT_INTERNAL_VALIDATE_H */
23049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
24049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_VALIDATE_H
25049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_STREAM_H
26049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "ttload.h"
27049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "ttcmap.h"
28049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
29049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
30049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
31049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
32049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
33049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
34049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* messages during execution.                                            */
35049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
36049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#undef  FT_COMPONENT
37049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_COMPONENT  trace_ttcmap
38049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
39049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
40049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define TT_PEEK_SHORT   FT_PEEK_SHORT
41049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define TT_PEEK_USHORT  FT_PEEK_USHORT
42049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define TT_PEEK_UINT24  FT_PEEK_UOFF3
43049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define TT_PEEK_LONG    FT_PEEK_LONG
44049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define TT_PEEK_ULONG   FT_PEEK_ULONG
45049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
46049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define TT_NEXT_SHORT   FT_NEXT_SHORT
47049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define TT_NEXT_USHORT  FT_NEXT_USHORT
48049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define TT_NEXT_UINT24  FT_NEXT_UOFF3
49049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define TT_NEXT_LONG    FT_NEXT_LONG
50049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define TT_NEXT_ULONG   FT_NEXT_ULONG
51049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
52049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
53049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
54049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap_init( TT_CMap   cmap,
55049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                FT_Byte*  table )
56049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
57049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->data = table;
58049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return SFNT_Err_Ok;
59049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
60049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
61049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
62049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
63049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
64049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
65049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                           FORMAT 0                            *****/
66049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
67049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
68049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
69049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
70049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
71049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
72049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* TABLE OVERVIEW                                                        */
73049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* --------------                                                        */
74049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
75049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME        OFFSET         TYPE          DESCRIPTION                */
76049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
77049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   format      0              USHORT        must be 0                  */
78049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   length      2              USHORT        table length in bytes      */
79049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   language    4              USHORT        Mac language code          */
80049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   glyph_ids   6              BYTE[256]     array of glyph indices     */
81049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*               262                                                     */
82049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
83049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
84049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_0
85049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
86049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
87049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap0_validate( FT_Byte*      table,
88049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Validator  valid )
89049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
90049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p      = table + 2;
91049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   length = TT_NEXT_USHORT( p );
92049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
93049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
94049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + length > valid->limit || length < 262 )
95049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
96049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
97049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* check glyph indices whenever necessary */
98049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( valid->level >= FT_VALIDATE_TIGHT )
99049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  n, idx;
101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p = table + 6;
104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( n = 0; n < 256; n++ )
105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        idx = *p++;
107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_GLYPH_ID;
109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return SFNT_Err_Ok;
113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap0_char_index( TT_CMap    cmap,
118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_UInt32  char_code )
119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  table = cmap->data;
121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return char_code < 256 ? table[6 + char_code] : 0;
124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap0_char_next( TT_CMap     cmap,
129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_UInt32  *pchar_code )
130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   table    = cmap->data;
132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  charcode = *pchar_code;
133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  result   = 0;
134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    gindex   = 0;
135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
13777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    table += 6;  /* go to glyph IDs */
138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( ++charcode < 256 )
139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      gindex = table[charcode];
141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( gindex != 0 )
142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        result = charcode;
144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *pchar_code = result;
149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap0_get_info( TT_CMap       cmap,
155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     TT_CMapInfo  *cmap_info )
156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = cmap->data + 4;
158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->format = 0;
161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return SFNT_Err_Ok;
164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_TABLE_DEF
168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  const TT_CMap_ClassRec  tt_cmap0_class_rec =
169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      sizeof ( TT_CMapRec ),
172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_InitFunc)     tt_cmap_init,
174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_DoneFunc)     NULL,
175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_CharIndexFunc)tt_cmap0_char_index,
176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_CharNextFunc) tt_cmap0_char_next,
177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      NULL, NULL, NULL, NULL, NULL
179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    },
180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    0,
181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (TT_CMap_ValidateFunc)   tt_cmap0_validate,
182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (TT_CMap_Info_GetFunc)   tt_cmap0_get_info
183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  };
184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* TT_CONFIG_CMAP_FORMAT_0 */
186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                          FORMAT 2                             *****/
192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** This is used for certain CJK encodings that encode text in a  *****/
194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** mixed 8/16 bits encoding along the following lines:           *****/
195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** * Certain byte values correspond to an 8-bit character code   *****/
197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   (typically in the range 0..127 for ASCII compatibility).    *****/
198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** * Certain byte values signal the first byte of a 2-byte       *****/
200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   character code (but these values are also valid as the      *****/
201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   second byte of a 2-byte character).                         *****/
202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** The following charmap lookup and iteration functions all      *****/
204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** assume that the value "charcode" correspond to following:     *****/
205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   - For one byte characters, "charcode" is simply the         *****/
207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****     character code.                                           *****/
208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   - For two byte characters, "charcode" is the 2-byte         *****/
210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****     character code in big endian format.  More exactly:       *****/
211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****       (charcode >> 8)    is the first byte value              *****/
213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****       (charcode & 0xFF)  is the second byte value             *****/
214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** Note that not all values of "charcode" are valid according    *****/
216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** to these rules, and the function moderately check the         *****/
217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** arguments.                                                    *****/
218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* TABLE OVERVIEW                                                        */
225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* --------------                                                        */
226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME        OFFSET         TYPE            DESCRIPTION              */
228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   format      0              USHORT          must be 2                */
230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   length      2              USHORT          table length in bytes    */
231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   language    4              USHORT          Mac language code        */
232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   keys        6              USHORT[256]     sub-header keys          */
233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   subs        518            SUBHEAD[NSUBS]  sub-headers array        */
23477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /*   glyph_ids   518+NSUB*8     USHORT[]        glyph ID array           */
235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* The `keys' table is used to map charcode high-bytes to sub-headers.   */
237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* The value of `NSUBS' is the number of sub-headers defined in the      */
238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* table and is computed by finding the maximum of the `keys' table.     */
239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Note that for any n, `keys[n]' is a byte offset within the `subs'     */
241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* table, i.e., it is the corresponding sub-header index multiplied      */
242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* by 8.                                                                 */
243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Each sub-header has the following format:                             */
245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME        OFFSET      TYPE            DESCRIPTION                 */
247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   first       0           USHORT          first valid low-byte        */
249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   count       2           USHORT          number of valid low-bytes   */
250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   delta       4           SHORT           see below                   */
251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   offset      6           USHORT          see below                   */
252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* A sub-header defines, for each high-byte, the range of valid          */
254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* low-bytes within the charmap.  Note that the range defined by `first' */
255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* and `count' must be completely included in the interval [0..255]      */
256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* according to the specification.                                       */
257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* If a character code is contained within a given sub-header, then      */
259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* mapping it to a glyph index is done as follows:                       */
260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* * The value of `offset' is read.  This is a _byte_ distance from the  */
262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   location of the `offset' field itself into a slice of the           */
26377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /*   `glyph_ids' table.  Let's call it `slice' (it is a USHORT[] too).   */
264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* * The value `slice[char.lo - first]' is read.  If it is 0, there is   */
266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   no glyph for the charcode.  Otherwise, the value of `delta' is      */
267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   added to it (modulo 65536) to form a new glyph index.               */
268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* It is up to the validation routine to check that all offsets fall     */
27077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* within the glyph IDs table (and not within the `subs' table itself or */
271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* outside of the CMap).                                                 */
272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_2
275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap2_validate( FT_Byte*      table,
278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Validator  valid )
279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p      = table + 2;           /* skip format */
281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   length = TT_PEEK_USHORT( p );
282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   n, max_subs;
283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  keys;                         /* keys table */
284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  subs;                         /* sub-headers */
28577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Byte*  glyph_ids;                    /* glyph ID array */
286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + length > valid->limit || length < 6 + 512 )
289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    keys = table + 6;
292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* parse keys to compute sub-headers count */
294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p        = keys;
295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    max_subs = 0;
296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( n = 0; n < 256; n++ )
297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  idx = TT_NEXT_USHORT( p );
299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* value must be multiple of 8 */
302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 )
303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_INVALID_DATA;
304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      idx >>= 3;
306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( idx > max_subs )
308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        max_subs = idx;
309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ASSERT( p == table + 518 );
312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    subs      = p;
314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    glyph_ids = subs + (max_subs + 1) * 8;
315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( glyph_ids > valid->limit )
316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* parse sub-headers */
319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( n = 0; n <= max_subs; n++ )
320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   first_code, code_count, offset;
322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int    delta;
323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  ids;
324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      first_code = TT_NEXT_USHORT( p );
327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      code_count = TT_NEXT_USHORT( p );
328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta      = TT_NEXT_SHORT( p );
329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      offset     = TT_NEXT_USHORT( p );
330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
33177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      /* many Dynalab fonts have empty sub-headers */
33277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      if ( code_count == 0 )
33377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        continue;
33477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* check range within 0..255 */
336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( valid->level >= FT_VALIDATE_PARANOID )
337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( first_code >= 256 || first_code + code_count > 256 )
339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_DATA;
340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* check offset */
343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( offset != 0 )
344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ids = p - 2 + offset;
346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( ids < glyph_ids || ids + code_count*2 > table + length )
347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_OFFSET;
348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
34977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        /* check glyph IDs */
350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( valid->level >= FT_VALIDATE_TIGHT )
351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Byte*  limit = p + code_count * 2;
353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt   idx;
354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( ; p < limit; )
357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            idx = TT_NEXT_USHORT( p );
359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( idx != 0 )
360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              idx = ( idx + delta ) & 0xFFFFU;
362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                FT_INVALID_GLYPH_ID;
364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return SFNT_Err_Ok;
371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* return sub header corresponding to a given character code */
375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* NULL on invalid charcode                                  */
376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Byte*
377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap2_get_subheader( FT_Byte*   table,
378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          FT_UInt32  char_code )
379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  result = NULL;
381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( char_code < 0x10000UL )
384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   char_lo = (FT_UInt)( char_code & 0xFF );
386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   char_hi = (FT_UInt)( char_code >> 8 );
387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  p       = table + 6;    /* keys table */
388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  subs    = table + 518;  /* subheaders table */
389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  sub;
390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_hi == 0 )
393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* an 8-bit character code -- we use subHeader 0 in this case */
395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* to test whether the character code is in the charmap       */
396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /*                                                            */
397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        sub = subs;  /* jump to first sub-header */
398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* check that the sub-header for this byte is 0, which */
40077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        /* indicates that it is really a valid one-byte value  */
401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* Otherwise, return 0                                 */
402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /*                                                     */
403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p += char_lo * 2;
404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( TT_PEEK_USHORT( p ) != 0 )
405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Exit;
406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* a 16-bit character code */
410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* jump to key entry  */
412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p  += char_hi * 2;
413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* jump to sub-header */
414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        sub = subs + ( FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 8 ) );
415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* check that the high byte isn't a valid one-byte value */
417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( sub == subs )
418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Exit;
419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = sub;
421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return result;
424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap2_char_index( TT_CMap    cmap,
429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_UInt32  char_code )
430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  table   = cmap->data;
432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   result  = 0;
433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  subheader;
434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    subheader = tt_cmap2_get_subheader( table, char_code );
437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( subheader )
438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  p   = subheader;
440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   idx = (FT_UInt)(char_code & 0xFF);
441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   start, count;
442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int    delta;
443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   offset;
444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start  = TT_NEXT_USHORT( p );
447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      count  = TT_NEXT_USHORT( p );
448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta  = TT_NEXT_SHORT ( p );
449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      offset = TT_PEEK_USHORT( p );
450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      idx -= start;
452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( idx < count && offset != 0 )
453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p  += offset + 2 * idx;
455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        idx = TT_PEEK_USHORT( p );
456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( idx != 0 )
458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          result = (FT_UInt)( idx + delta ) & 0xFFFFU;
459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return result;
462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap2_char_next( TT_CMap     cmap,
467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_UInt32  *pcharcode )
468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   table    = cmap->data;
470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    gindex   = 0;
471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  result   = 0;
472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  charcode = *pcharcode + 1;
473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   subheader;
474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( charcode < 0x10000UL )
477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      subheader = tt_cmap2_get_subheader( table, charcode );
479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( subheader )
480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Byte*  p       = subheader;
482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt   start   = TT_NEXT_USHORT( p );
483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt   count   = TT_NEXT_USHORT( p );
484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Int    delta   = TT_NEXT_SHORT ( p );
485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt   offset  = TT_PEEK_USHORT( p );
486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt   char_lo = (FT_UInt)( charcode & 0xFF );
487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt   pos, idx;
488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( offset == 0 )
491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Next_SubHeader;
492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( char_lo < start )
494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          char_lo = start;
496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          pos     = 0;
497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          pos = (FT_UInt)( char_lo - start );
500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p       += offset + pos * 2;
502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        charcode = FT_PAD_FLOOR( charcode, 256 ) + char_lo;
503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( ; pos < count; pos++, charcode++ )
505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          idx = TT_NEXT_USHORT( p );
507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( idx != 0 )
509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            gindex = ( idx + delta ) & 0xFFFFU;
511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( gindex != 0 )
512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              result = charcode;
514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              goto Exit;
515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* jump to next sub-header, i.e. higher byte value */
521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    Next_SubHeader:
522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      charcode = FT_PAD_FLOOR( charcode, 256 ) + 256;
523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *pcharcode = result;
527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap2_get_info( TT_CMap       cmap,
534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     TT_CMapInfo  *cmap_info )
535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = cmap->data + 4;
537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->format = 2;
540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return SFNT_Err_Ok;
543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_TABLE_DEF
547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  const TT_CMap_ClassRec  tt_cmap2_class_rec =
548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      sizeof ( TT_CMapRec ),
551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_InitFunc)     tt_cmap_init,
553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_DoneFunc)     NULL,
554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_CharIndexFunc)tt_cmap2_char_index,
555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_CharNextFunc) tt_cmap2_char_next,
556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      NULL, NULL, NULL, NULL, NULL
558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    },
559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    2,
560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (TT_CMap_ValidateFunc)   tt_cmap2_validate,
561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (TT_CMap_Info_GetFunc)   tt_cmap2_get_info
562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  };
563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* TT_CONFIG_CMAP_FORMAT_2 */
565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                           FORMAT 4                            *****/
571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* TABLE OVERVIEW                                                        */
578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* --------------                                                        */
579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME          OFFSET         TYPE              DESCRIPTION          */
581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   format        0              USHORT            must be 4            */
583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   length        2              USHORT            table length         */
584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                  in bytes             */
585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   language      4              USHORT            Mac language code    */
586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   segCountX2    6              USHORT            2*NUM_SEGS           */
588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   searchRange   8              USHORT            2*(1 << LOG_SEGS)    */
589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   entrySelector 10             USHORT            LOG_SEGS             */
590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   rangeShift    12             USHORT            segCountX2 -         */
591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                    searchRange        */
592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   endCount      14             USHORT[NUM_SEGS]  end charcode for     */
594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                  each segment; last   */
595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                  is 0xFFFF            */
596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   pad           14+NUM_SEGS*2  USHORT            padding              */
598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   startCount    16+NUM_SEGS*2  USHORT[NUM_SEGS]  first charcode for   */
600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                  each segment         */
601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   idDelta       16+NUM_SEGS*4  SHORT[NUM_SEGS]   delta for each       */
603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                  segment              */
604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   idOffset      16+NUM_SEGS*6  SHORT[NUM_SEGS]   range offset for     */
605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                  each segment; can be */
606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                  zero                 */
607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
60877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /*   glyphIds      16+NUM_SEGS*8  USHORT[]          array of glyph ID    */
609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                  ranges               */
610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Character codes are modelled by a series of ordered (increasing)      */
612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* intervals called segments.  Each segment has start and end codes,     */
613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* provided by the `startCount' and `endCount' arrays.  Segments must    */
61477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* not overlap, and the last segment should always contain the value     */
61577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* 0xFFFF for `endCount'.                                                */
616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* The fields `searchRange', `entrySelector' and `rangeShift' are better */
618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* ignored (they are traces of over-engineering in the TrueType          */
619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* specification).                                                       */
620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Each segment also has a signed `delta', as well as an optional offset */
622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* within the `glyphIds' table.                                          */
623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* If a segment's idOffset is 0, the glyph index corresponding to any    */
625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* charcode within the segment is obtained by adding the value of        */
626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* `idDelta' directly to the charcode, modulo 65536.                     */
627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
62877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* Otherwise, a glyph index is taken from the glyph IDs sub-array for    */
629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* the segment, and the value of `idDelta' is added to it.               */
630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
63277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* Finally, note that a lot of fonts contain an invalid last segment,    */
63377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* where `start' and `end' are correctly set to 0xFFFF but both `delta'  */
63477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* and `offset' are incorrect (e.g., `opens___.ttf' which comes with     */
63577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* OpenOffice.org).  We need special code to deal with them correctly.   */
636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_4
639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef struct  TT_CMap4Rec_
641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMapRec  cmap;
643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32   cur_charcode;   /* current charcode */
644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     cur_gindex;     /* current glyph index */
645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     num_ranges;
647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     cur_range;
648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     cur_start;
649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     cur_end;
650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int      cur_delta;
651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*    cur_values;
652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  } TT_CMap4Rec, *TT_CMap4;
654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap4_init( TT_CMap4  cmap,
658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 FT_Byte*  table )
659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p;
661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->cmap.data    = table;
664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p                  = table + 6;
666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->num_ranges   = FT_PEEK_USHORT( p ) >> 1;
667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->cur_charcode = 0xFFFFFFFFUL;
668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->cur_gindex   = 0;
669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return SFNT_Err_Ok;
671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Int
675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap4_set_range( TT_CMap4  cmap,
676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_UInt   range_index )
677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  table = cmap->cmap.data;
679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p;
680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   num_ranges = cmap->num_ranges;
681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( range_index < num_ranges )
684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  offset;
686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p             = table + 14 + range_index * 2;
689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cmap->cur_end = FT_PEEK_USHORT( p );
690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p              += 2 + num_ranges * 2;
692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cmap->cur_start = FT_PEEK_USHORT( p );
693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p              += num_ranges * 2;
695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cmap->cur_delta = FT_PEEK_SHORT( p );
696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p     += num_ranges * 2;
698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      offset = FT_PEEK_USHORT( p );
699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
70077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      /* some fonts have an incorrect last segment; */
70177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      /* we have to catch it                        */
70277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      if ( range_index     >= num_ranges - 1 &&
70377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner           cmap->cur_start == 0xFFFFU        &&
70477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner           cmap->cur_end   == 0xFFFFU        )
70577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      {
70677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        TT_Face   face  = (TT_Face)cmap->cmap.cmap.charmap.face;
70777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        FT_Byte*  limit = face->cmap_table + face->cmap_size;
70877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
70977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
71077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        if ( offset && p + offset + 2 > limit )
71177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        {
71277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          cmap->cur_delta = 1;
71377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          offset          = 0;
71477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        }
71577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      }
71677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( offset != 0xFFFFU )
718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cmap->cur_values = offset ? p + offset : NULL;
720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cmap->cur_range  = range_index;
721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return 0;
722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we skip empty segments */
725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      range_index++;
726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return -1;
729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* search the index of the charcode next to cmap->cur_charcode; */
733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* caller should call tt_cmap4_set_range with proper range      */
734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* before calling this function                                 */
735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                              */
736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap4_next( TT_CMap4  cmap )
738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt  charcode;
740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( cmap->cur_charcode >= 0xFFFFUL )
743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Fail;
744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    charcode = cmap->cur_charcode + 1;
746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( charcode < cmap->cur_start )
748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      charcode = cmap->cur_start;
749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ;; )
751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  values = cmap->cur_values;
753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   end    = cmap->cur_end;
754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int    delta  = cmap->cur_delta;
755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( charcode <= end )
758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( values )
760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Byte*  p = values + 2 * ( charcode - cmap->cur_start );
762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          do
765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_UInt  gindex = FT_NEXT_USHORT( p );
767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( gindex != 0 )
770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              gindex = (FT_UInt)( ( gindex + delta ) & 0xFFFFU );
772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( gindex != 0 )
773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                cmap->cur_charcode = charcode;
775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                cmap->cur_gindex   = gindex;
776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                return;
777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          } while ( ++charcode <= end );
780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          do
784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_UInt  gindex = (FT_UInt)( ( charcode + delta ) & 0xFFFFU );
786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( gindex != 0 )
789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              cmap->cur_charcode = charcode;
791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              cmap->cur_gindex   = gindex;
792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              return;
793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          } while ( ++charcode <= end );
795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we need to find another range */
799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tt_cmap4_set_range( cmap, cmap->cur_range + 1 ) < 0 )
800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( charcode < cmap->cur_start )
803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        charcode = cmap->cur_start;
804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Fail:
807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->cur_charcode = 0xFFFFFFFFUL;
808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->cur_gindex   = 0;
809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap4_validate( FT_Byte*      table,
814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Validator  valid )
815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p      = table + 2;               /* skip format */
817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   length = TT_NEXT_USHORT( p );
818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte   *ends, *starts, *offsets, *deltas, *glyph_ids;
819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   num_segs;
820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error  error = SFNT_Err_Ok;
821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( length < 16 )
824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* in certain fonts, the `length' field is invalid and goes */
827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* out of bound.  We try to correct this here...            */
828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + length > valid->limit )
829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( valid->level >= FT_VALIDATE_TIGHT )
831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_INVALID_TOO_SHORT;
832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      length = (FT_UInt)( valid->limit - table );
834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p        = table + 6;
837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_segs = TT_NEXT_USHORT( p );   /* read segCountX2 */
838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( valid->level >= FT_VALIDATE_PARANOID )
840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* check that we have an even value here */
842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( num_segs & 1 )
843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_INVALID_DATA;
844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_segs /= 2;
847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( length < 16 + num_segs * 2 * 4 )
849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* check the search parameters - even though we never use them */
852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                             */
853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( valid->level >= FT_VALIDATE_PARANOID )
854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
85577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      /* check the values of `searchRange', `entrySelector', `rangeShift' */
856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  search_range   = TT_NEXT_USHORT( p );
857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  entry_selector = TT_NEXT_USHORT( p );
858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  range_shift    = TT_NEXT_USHORT( p );
859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ( search_range | range_shift ) & 1 )  /* must be even values */
862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_INVALID_DATA;
863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      search_range /= 2;
865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      range_shift  /= 2;
866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* `search range' is the greatest power of 2 that is <= num_segs */
868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( search_range                > num_segs                 ||
870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           search_range * 2            < num_segs                 ||
871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           search_range + range_shift != num_segs                 ||
872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           search_range               != ( 1U << entry_selector ) )
873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_INVALID_DATA;
874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ends      = table   + 14;
877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    starts    = table   + 16 + num_segs * 2;
878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    deltas    = starts  + num_segs * 2;
879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    offsets   = deltas  + num_segs * 2;
880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    glyph_ids = offsets + num_segs * 2;
881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
88277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    /* check last segment; its end count value must be 0xFFFF */
883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( valid->level >= FT_VALIDATE_PARANOID )
884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p = ends + ( num_segs - 1 ) * 2;
886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( TT_PEEK_USHORT( p ) != 0xFFFFU )
887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_INVALID_DATA;
888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
89177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      FT_UInt   start, end, offset, n;
89277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      FT_UInt   last_start = 0, last_end = 0;
89377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      FT_Int    delta;
894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  p_start   = starts;
895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  p_end     = ends;
896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  p_delta   = deltas;
897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  p_offset  = offsets;
898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( n = 0; n < num_segs; n++ )
901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p      = p_offset;
903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        start  = TT_NEXT_USHORT( p_start );
904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        end    = TT_NEXT_USHORT( p_end );
905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        delta  = TT_NEXT_SHORT( p_delta );
906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        offset = TT_NEXT_USHORT( p_offset );
907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( start > end )
909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_DATA;
910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
91177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        /* this test should be performed at default validation level; */
91277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        /* unfortunately, some popular Asian fonts have overlapping   */
91377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        /* ranges in their charmaps                                   */
91477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        /*                                                            */
915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( start <= last_end && n > 0 )
916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( valid->level >= FT_VALIDATE_TIGHT )
918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_INVALID_DATA;
919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* allow overlapping segments, provided their start points */
92277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner            /* and end points, respectively, are in ascending order    */
923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /*                                                         */
924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( last_start > start || last_end > end )
925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              error |= TT_CMAP_FLAG_UNSORTED;
926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              error |= TT_CMAP_FLAG_OVERLAPPING;
928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( offset && offset != 0xFFFFU )
932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
93377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          p += offset;  /* start of glyph ID array */
934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
93577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* check that we point within the glyph IDs table only */
936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( valid->level >= FT_VALIDATE_TIGHT )
937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( p < glyph_ids                                ||
939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 p + ( end - start + 1 ) * 2 > table + length )
940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_INVALID_DATA;
941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
94277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* Some fonts handle the last segment incorrectly.  In */
94377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* theory, 0xFFFF might point to an ordinary glyph --  */
94477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* a cmap 4 is versatile and could be used for any     */
94577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* encoding, not only Unicode.  However, reality shows */
94677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* that far too many fonts are sloppy and incorrectly  */
94777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* set all fields but `start' and `end' for the last   */
94877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* segment if it contains only a single character.     */
94977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /*                                                     */
95077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* We thus omit the test here, delaying it to the      */
95177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* routines which actually access the cmap.            */
95277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          else if ( n != num_segs - 1                       ||
95377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner                    !( start == 0xFFFFU && end == 0xFFFFU ) )
954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( p < glyph_ids                              ||
956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 p + ( end - start + 1 ) * 2 > valid->limit )
957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_INVALID_DATA;
958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* check glyph indices within the segment range */
961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( valid->level >= FT_VALIDATE_TIGHT )
962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_UInt  i, idx;
964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            for ( i = start; i < end; i++ )
967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              idx = FT_NEXT_USHORT( p );
969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( idx != 0 )
970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                idx = (FT_UInt)( idx + delta ) & 0xFFFFU;
972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_INVALID_GLYPH_ID;
975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( offset == 0xFFFFU )
980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
98177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* some fonts (erroneously?) use a range offset of 0xFFFF */
982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* to mean missing glyph in cmap table                    */
983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /*                                                        */
98477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          if ( valid->level >= FT_VALIDATE_PARANOID    ||
98577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner               n != num_segs - 1                       ||
98677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner               !( start == 0xFFFFU && end == 0xFFFFU ) )
987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_INVALID_DATA;
988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        last_start = start;
991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        last_end   = end;
992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_UInt
100077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  tt_cmap4_char_map_linear( TT_CMap     cmap,
100177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner                            FT_UInt32*  pcharcode,
100277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner                            FT_Bool     next )
1003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    num_segs2, start, end, offset;
1005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int     delta;
1006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    i, num_segs;
1007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  charcode = *pcharcode;
1008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    gindex   = 0;
1009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p;
1010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p = cmap->data + 6;
1013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );
1014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_segs = num_segs2 >> 1;
1016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !num_segs )
1018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
1019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( next )
1021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      charcode++;
1022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* linear search */
1024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; charcode <= 0xFFFFU; charcode++ )
1025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  q;
1027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p = cmap->data + 14;               /* ends table   */
1030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      q = cmap->data + 16 + num_segs2;   /* starts table */
1031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( i = 0; i < num_segs; i++ )
1033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        end   = TT_NEXT_USHORT( p );
1035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        start = TT_NEXT_USHORT( q );
1036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( charcode >= start && charcode <= end )
1038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p       = q - 2 + num_segs2;
1040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta   = TT_PEEK_SHORT( p );
1041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p      += num_segs2;
1042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          offset  = TT_PEEK_USHORT( p );
1043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
104477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* some fonts have an incorrect last segment; */
104577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* we have to catch it                        */
104677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          if ( i >= num_segs - 1                  &&
104777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner               start == 0xFFFFU && end == 0xFFFFU )
104877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          {
104977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner            TT_Face   face  = (TT_Face)cmap->cmap.charmap.face;
105077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner            FT_Byte*  limit = face->cmap_table + face->cmap_size;
105177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
105277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
105377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner            if ( offset && p + offset + 2 > limit )
105477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner            {
105577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner              delta  = 1;
105677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner              offset = 0;
105777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner            }
105877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          }
105977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
1060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( offset == 0xFFFFU )
1061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            continue;
1062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( offset )
1064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p += offset + ( charcode - start ) * 2;
1066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            gindex = TT_PEEK_USHORT( p );
1067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( gindex != 0 )
1068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
1069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU;
1072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          break;
1074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !next || gindex )
1078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
1079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( next && gindex )
1082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      *pcharcode = charcode;
1083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
1085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_UInt
108977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  tt_cmap4_char_map_binary( TT_CMap     cmap,
109077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner                            FT_UInt32*  pcharcode,
109177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner                            FT_Bool     next )
1092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   num_segs2, start, end, offset;
1094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int    delta;
1095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   max, min, mid, num_segs;
1096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   charcode = *pcharcode;
1097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   gindex   = 0;
1098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p;
1099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p = cmap->data + 6;
1102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );
1103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !num_segs2 )
1105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
1106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_segs = num_segs2 >> 1;
1108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* make compiler happy */
1110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    mid = num_segs;
1111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    end = 0xFFFFU;
1112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( next )
1114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      charcode++;
1115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    min = 0;
1117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    max = num_segs;
1118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* binary search */
1120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( min < max )
1121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mid    = ( min + max ) >> 1;
1123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p      = cmap->data + 14 + mid * 2;
1124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      end    = TT_PEEK_USHORT( p );
1125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p     += 2 + num_segs2;
1126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start  = TT_PEEK_USHORT( p );
1127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( charcode < start )
1129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        max = mid;
1130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( charcode > end )
1131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        min = mid + 1;
1132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p     += num_segs2;
1135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        delta  = TT_PEEK_SHORT( p );
1136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p     += num_segs2;
1137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        offset = TT_PEEK_USHORT( p );
1138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
113977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        /* some fonts have an incorrect last segment; */
114077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        /* we have to catch it                        */
114177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        if ( mid >= num_segs - 1                &&
114277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner             start == 0xFFFFU && end == 0xFFFFU )
114377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        {
114477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          TT_Face   face  = (TT_Face)cmap->cmap.charmap.face;
114577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          FT_Byte*  limit = face->cmap_table + face->cmap_size;
114677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
114777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
114877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          if ( offset && p + offset + 2 > limit )
114977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          {
115077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner            delta  = 1;
115177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner            offset = 0;
115277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          }
115377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        }
115477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
1155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* search the first segment containing `charcode' */
1156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( cmap->flags & TT_CMAP_FLAG_OVERLAPPING )
1157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt  i;
1159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* call the current segment `max' */
1162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          max = mid;
1163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( offset == 0xFFFFU )
1165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            mid = max + 1;
1166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* search in segments before the current segment */
1168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( i = max ; i > 0; i-- )
1169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_UInt   prev_end;
1171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Byte*  old_p;
1172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            old_p    = p;
1175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p        = cmap->data + 14 + ( i - 1 ) * 2;
1176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            prev_end = TT_PEEK_USHORT( p );
1177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( charcode > prev_end )
1179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p = old_p;
1181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
1182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            end    = prev_end;
1185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p     += 2 + num_segs2;
1186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            start  = TT_PEEK_USHORT( p );
1187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p     += num_segs2;
1188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta  = TT_PEEK_SHORT( p );
1189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p     += num_segs2;
1190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            offset = TT_PEEK_USHORT( p );
1191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( offset != 0xFFFFU )
1193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              mid = i - 1;
1194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* no luck */
1197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( mid == max + 1 )
1198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( i != max )
1200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p      = cmap->data + 14 + max * 2;
1202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              end    = TT_PEEK_USHORT( p );
1203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p     += 2 + num_segs2;
1204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              start  = TT_PEEK_USHORT( p );
1205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p     += num_segs2;
1206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              delta  = TT_PEEK_SHORT( p );
1207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p     += num_segs2;
1208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              offset = TT_PEEK_USHORT( p );
1209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            mid = max;
1212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* search in segments after the current segment */
1214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            for ( i = max + 1; i < num_segs; i++ )
1215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_UInt  next_end, next_start;
1217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p          = cmap->data + 14 + i * 2;
1220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              next_end   = TT_PEEK_USHORT( p );
1221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p         += 2 + num_segs2;
1222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              next_start = TT_PEEK_USHORT( p );
1223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( charcode < next_start )
1225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                break;
1226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              end    = next_end;
1228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              start  = next_start;
1229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p     += num_segs2;
1230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              delta  = TT_PEEK_SHORT( p );
1231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p     += num_segs2;
1232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              offset = TT_PEEK_USHORT( p );
1233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( offset != 0xFFFFU )
1235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                mid = i;
1236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            i--;
1238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* still no luck */
1240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( mid == max )
1241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              mid = i;
1243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
1245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* end, start, delta, and offset are for the i'th segment */
1249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( mid != i )
1250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p      = cmap->data + 14 + mid * 2;
1252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            end    = TT_PEEK_USHORT( p );
1253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p     += 2 + num_segs2;
1254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            start  = TT_PEEK_USHORT( p );
1255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p     += num_segs2;
1256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta  = TT_PEEK_SHORT( p );
1257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p     += num_segs2;
1258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            offset = TT_PEEK_USHORT( p );
1259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( offset == 0xFFFFU )
1264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
1265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( offset )
1268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p += offset + ( charcode - start ) * 2;
1270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          gindex = TT_PEEK_USHORT( p );
1271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( gindex != 0 )
1272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
1273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU;
1276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
1278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( next )
1282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TT_CMap4  cmap4 = (TT_CMap4)cmap;
1284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* if `charcode' is not in any segment, then `mid' is */
1287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* the segment nearest to `charcode'                  */
1288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /*                                                    */
1289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( charcode > end )
1291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        mid++;
1293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( mid == num_segs )
1294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          return 0;
1295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tt_cmap4_set_range( cmap4, mid ) )
1298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( gindex )
1300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          *pcharcode = charcode;
1301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cmap4->cur_charcode = charcode;
1305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( gindex )
1307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cmap4->cur_gindex = gindex;
1308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cmap4->cur_charcode = charcode;
1311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          tt_cmap4_next( cmap4 );
1312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          gindex = cmap4->cur_gindex;
1313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( gindex )
1316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          *pcharcode = cmap4->cur_charcode;
1317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
1321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
1325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap4_char_index( TT_CMap    cmap,
1326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_UInt32  char_code )
1327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( char_code >= 0x10000UL )
1329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
1330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( cmap->flags & TT_CMAP_FLAG_UNSORTED )
1332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return tt_cmap4_char_map_linear( cmap, &char_code, 0 );
1333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return tt_cmap4_char_map_binary( cmap, &char_code, 0 );
1335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
1339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap4_char_next( TT_CMap     cmap,
1340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_UInt32  *pchar_code )
1341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt  gindex;
1343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( *pchar_code >= 0xFFFFU )
1346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
1347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( cmap->flags & TT_CMAP_FLAG_UNSORTED )
1349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      gindex = tt_cmap4_char_map_linear( cmap, pchar_code, 1 );
1350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TT_CMap4  cmap4 = (TT_CMap4)cmap;
1353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* no need to search */
1356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( *pchar_code == cmap4->cur_charcode )
1357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tt_cmap4_next( cmap4 );
1359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gindex = cmap4->cur_gindex;
1360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( gindex )
1361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          *pchar_code = cmap4->cur_charcode;
1362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gindex = tt_cmap4_char_map_binary( cmap, pchar_code, 1 );
1365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
1368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
1372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap4_get_info( TT_CMap       cmap,
1373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     TT_CMapInfo  *cmap_info )
1374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = cmap->data + 4;
1376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->format = 4;
1379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
1380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return SFNT_Err_Ok;
1382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_TABLE_DEF
1386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  const TT_CMap_ClassRec  tt_cmap4_class_rec =
1387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      sizeof ( TT_CMap4Rec ),
1390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_InitFunc)     tt_cmap4_init,
1391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_DoneFunc)     NULL,
1392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_CharIndexFunc)tt_cmap4_char_index,
1393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_CharNextFunc) tt_cmap4_char_next,
1394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      NULL, NULL, NULL, NULL, NULL
1396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    },
1397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    4,
1398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (TT_CMap_ValidateFunc)   tt_cmap4_validate,
1399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (TT_CMap_Info_GetFunc)   tt_cmap4_get_info
1400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  };
1401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* TT_CONFIG_CMAP_FORMAT_4 */
1403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                          FORMAT 6                             *****/
1409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* TABLE OVERVIEW                                                        */
1416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* --------------                                                        */
1417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME        OFFSET          TYPE             DESCRIPTION            */
1419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   format       0              USHORT           must be 4              */
1421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   length       2              USHORT           table length in bytes  */
1422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   language     4              USHORT           Mac language code      */
1423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   first        6              USHORT           first segment code     */
1425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   count        8              USHORT           segment size in chars  */
142677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /*   glyphIds     10             USHORT[count]    glyph IDs              */
1427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* A very simplified segment mapping.                                    */
1429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_6
1432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
1434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap6_validate( FT_Byte*      table,
1435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Validator  valid )
1436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p;
1438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   length, count;
1439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + 10 > valid->limit )
1442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
1443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p      = table + 2;
1445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    length = TT_NEXT_USHORT( p );
1446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p      = table + 8;             /* skip language and start index */
1448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    count  = TT_NEXT_USHORT( p );
1449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + length > valid->limit || length < 10 + count * 2 )
1451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
1452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* check glyph indices */
1454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( valid->level >= FT_VALIDATE_TIGHT )
1455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  gindex;
1457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; count > 0; count-- )
1460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gindex = TT_NEXT_USHORT( p );
1462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
1463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_GLYPH_ID;
1464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return SFNT_Err_Ok;
1468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
1472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap6_char_index( TT_CMap    cmap,
1473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_UInt32  char_code )
1474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  table  = cmap->data;
1476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   result = 0;
1477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p      = table + 6;
1478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   start  = TT_NEXT_USHORT( p );
1479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   count  = TT_NEXT_USHORT( p );
1480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   idx    = (FT_UInt)( char_code - start );
1481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( idx < count )
1484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p += 2 * idx;
1486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = TT_PEEK_USHORT( p );
1487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return result;
1489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
1493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap6_char_next( TT_CMap     cmap,
1494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_UInt32  *pchar_code )
1495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   table     = cmap->data;
1497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  result    = 0;
1498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  char_code = *pchar_code + 1;
1499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    gindex    = 0;
1500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p         = table + 6;
1502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    start     = TT_NEXT_USHORT( p );
1503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    count     = TT_NEXT_USHORT( p );
1504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    idx;
1505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( char_code >= 0x10000UL )
1508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
1509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( char_code < start )
1511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      char_code = start;
1512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    idx = (FT_UInt)( char_code - start );
1514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p  += 2 * idx;
1515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; idx < count; idx++ )
1517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      gindex = TT_NEXT_USHORT( p );
1519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( gindex != 0 )
1520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        result = char_code;
1522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
1523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      char_code++;
1525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
1528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *pchar_code = result;
1529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
1530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
1534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap6_get_info( TT_CMap       cmap,
1535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     TT_CMapInfo  *cmap_info )
1536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = cmap->data + 4;
1538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->format = 6;
1541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
1542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return SFNT_Err_Ok;
1544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_TABLE_DEF
1548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  const TT_CMap_ClassRec  tt_cmap6_class_rec =
1549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      sizeof ( TT_CMapRec ),
1552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_InitFunc)     tt_cmap_init,
1554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_DoneFunc)     NULL,
1555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_CharIndexFunc)tt_cmap6_char_index,
1556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_CharNextFunc) tt_cmap6_char_next,
1557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      NULL, NULL, NULL, NULL, NULL
1559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    },
1560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    6,
1561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (TT_CMap_ValidateFunc)   tt_cmap6_validate,
1562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (TT_CMap_Info_GetFunc)   tt_cmap6_get_info
1563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  };
1564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* TT_CONFIG_CMAP_FORMAT_6 */
1566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                          FORMAT 8                             *****/
1572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
157377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /***** It is hard to completely understand what the OpenType spec    *****/
1574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** says about this format, but here is my conclusion.            *****/
1575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** The purpose of this format is to easily map UTF-16 text to    *****/
1577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** glyph indices.  Basically, the `char_code' must be in one of  *****/
1578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** the following formats:                                        *****/
1579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   - A 16-bit value that isn't part of the Unicode Surrogates  *****/
1581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****     Area (i.e. U+D800-U+DFFF).                                *****/
1582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   - A 32-bit value, made of two surrogate values, i.e.. if    *****/
1584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****     `char_code = (char_hi << 16) | char_lo', then both        *****/
1585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****     `char_hi' and `char_lo' must be in the Surrogates Area.   *****/
1586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****      Area.                                                    *****/
1587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
158877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /***** The `is32' table embedded in the charmap indicates whether a  *****/
1589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** given 16-bit value is in the surrogates area or not.          *****/
1590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** So, for any given `char_code', we can assert the following:   *****/
1592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   If `char_hi == 0' then we must have `is32[char_lo] == 0'.   *****/
1594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   If `char_hi != 0' then we must have both                    *****/
1596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   `is32[char_hi] != 0' and `is32[char_lo] != 0'.              *****/
1597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* TABLE OVERVIEW                                                        */
1604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* --------------                                                        */
1605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME        OFFSET         TYPE        DESCRIPTION                  */
1607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   format      0              USHORT      must be 8                    */
1609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   reserved    2              USHORT      reserved                     */
1610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   length      4              ULONG       length in bytes              */
1611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   language    8              ULONG       Mac language code            */
1612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   is32        12             BYTE[8192]  32-bitness bitmap            */
1613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   count       8204           ULONG       number of groups             */
1614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
161577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* This header is followed by `count' groups of the following format:    */
1616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   start       0              ULONG       first charcode               */
1618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   end         4              ULONG       last charcode                */
161977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /*   startId     8              ULONG       start glyph ID for the group */
1620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_8
1623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
1625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap8_validate( FT_Byte*      table,
1626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Validator  valid )
1627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p = table + 4;
1629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   is32;
1630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  length;
1631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  num_groups;
1632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + 16 + 8192 > valid->limit )
1635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
1636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    length = TT_NEXT_ULONG( p );
1638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + length > valid->limit || length < 8208 )
1639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
1640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    is32       = table + 12;
1642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p          = is32  + 8192;          /* skip `is32' array */
1643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_groups = TT_NEXT_ULONG( p );
1644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( p + num_groups * 12 > valid->limit )
1646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
1647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* check groups, they must be in increasing order */
1649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  n, start, end, start_id, count, last = 0;
1651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( n = 0; n < num_groups; n++ )
1654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt   hi, lo;
1656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        start    = TT_NEXT_ULONG( p );
1659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        end      = TT_NEXT_ULONG( p );
1660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        start_id = TT_NEXT_ULONG( p );
1661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( start > end )
1663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_DATA;
1664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( n > 0 && start <= last )
1666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_DATA;
1667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( valid->level >= FT_VALIDATE_TIGHT )
1669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
1671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_INVALID_GLYPH_ID;
1672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          count = (FT_UInt32)( end - start + 1 );
1674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( start & ~0xFFFFU )
1676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* start_hi != 0; check that is32[i] is 1 for each i in */
1678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* the `hi' and `lo' of the range [start..end]          */
1679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            for ( ; count > 0; count--, start++ )
1680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              hi = (FT_UInt)( start >> 16 );
1682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              lo = (FT_UInt)( start & 0xFFFFU );
1683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 )
1685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                FT_INVALID_DATA;
1686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 )
1688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                FT_INVALID_DATA;
1689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* start_hi == 0; check that is32[i] is 0 for each i in */
1694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* the range [start..end]                               */
1695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* end_hi cannot be != 0! */
1697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( end & ~0xFFFFU )
1698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_INVALID_DATA;
1699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            for ( ; count > 0; count--, start++ )
1701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              lo = (FT_UInt)( start & 0xFFFFU );
1703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 )
1705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                FT_INVALID_DATA;
1706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        last = end;
1711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return SFNT_Err_Ok;
1715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
1719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap8_char_index( TT_CMap    cmap,
1720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_UInt32  char_code )
1721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   table      = cmap->data;
1723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    result     = 0;
1724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p          = table + 8204;
1725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  num_groups = TT_NEXT_ULONG( p );
1726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  start, end, start_id;
1727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; num_groups > 0; num_groups-- )
1730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start    = TT_NEXT_ULONG( p );
1732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      end      = TT_NEXT_ULONG( p );
1733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start_id = TT_NEXT_ULONG( p );
1734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code < start )
1736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
1737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code <= end )
1739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        result = (FT_UInt)( start_id + char_code - start );
1741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
1742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return result;
1745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
1749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap8_char_next( TT_CMap     cmap,
1750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_UInt32  *pchar_code )
1751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  result     = 0;
1753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  char_code  = *pchar_code + 1;
1754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    gindex     = 0;
1755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   table      = cmap->data;
1756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p          = table + 8204;
1757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  num_groups = TT_NEXT_ULONG( p );
1758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  start, end, start_id;
1759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p = table + 8208;
1762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; num_groups > 0; num_groups-- )
1764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start    = TT_NEXT_ULONG( p );
1766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      end      = TT_NEXT_ULONG( p );
1767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start_id = TT_NEXT_ULONG( p );
1768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code < start )
1770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        char_code = start;
1771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code <= end )
1773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gindex = (FT_UInt)( char_code - start + start_id );
1775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( gindex != 0 )
1776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          result = char_code;
1778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Exit;
1779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
1784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *pchar_code = result;
1785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
1786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
1790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap8_get_info( TT_CMap       cmap,
1791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     TT_CMapInfo  *cmap_info )
1792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = cmap->data + 8;
1794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->format = 8;
1797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
1798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return SFNT_Err_Ok;
1800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_TABLE_DEF
1804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  const TT_CMap_ClassRec  tt_cmap8_class_rec =
1805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      sizeof ( TT_CMapRec ),
1808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_InitFunc)     tt_cmap_init,
1810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_DoneFunc)     NULL,
1811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_CharIndexFunc)tt_cmap8_char_index,
1812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_CharNextFunc) tt_cmap8_char_next,
1813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      NULL, NULL, NULL, NULL, NULL
1815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    },
1816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    8,
1817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (TT_CMap_ValidateFunc)   tt_cmap8_validate,
1818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (TT_CMap_Info_GetFunc)   tt_cmap8_get_info
1819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  };
1820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* TT_CONFIG_CMAP_FORMAT_8 */
1822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                          FORMAT 10                            *****/
1828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* TABLE OVERVIEW                                                        */
1835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* --------------                                                        */
1836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME      OFFSET  TYPE               DESCRIPTION                    */
1838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   format     0      USHORT             must be 10                     */
1840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   reserved   2      USHORT             reserved                       */
1841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   length     4      ULONG              length in bytes                */
1842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   language   8      ULONG              Mac language code              */
1843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   start     12      ULONG              first char in range            */
1845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   count     16      ULONG              number of chars in range       */
1846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   glyphIds  20      USHORT[count]      glyph indices covered          */
1847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_10
1850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
1852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap10_validate( FT_Byte*      table,
1853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Validator  valid )
1854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = table + 4;
1856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  length, count;
1857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + 20 > valid->limit )
1860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
1861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    length = TT_NEXT_ULONG( p );
1863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p      = table + 16;
1864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    count  = TT_NEXT_ULONG( p );
1865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + length > valid->limit || length < 20 + count * 2 )
1867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
1868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* check glyph indices */
1870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( valid->level >= FT_VALIDATE_TIGHT )
1871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  gindex;
1873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; count > 0; count-- )
1876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gindex = TT_NEXT_USHORT( p );
1878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
1879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_GLYPH_ID;
1880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return SFNT_Err_Ok;
1884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
1888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap10_char_index( TT_CMap    cmap,
1889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        FT_UInt32  char_code )
1890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   table  = cmap->data;
1892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    result = 0;
1893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p      = table + 12;
1894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  start  = TT_NEXT_ULONG( p );
1895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  count  = TT_NEXT_ULONG( p );
1896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  idx    = (FT_ULong)( char_code - start );
1897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( idx < count )
1900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p     += 2 * idx;
1902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = TT_PEEK_USHORT( p );
1903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return result;
1905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
1909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap10_char_next( TT_CMap     cmap,
1910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_UInt32  *pchar_code )
1911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   table     = cmap->data;
1913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  char_code = *pchar_code + 1;
1914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    gindex    = 0;
1915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p         = table + 12;
1916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  start     = TT_NEXT_ULONG( p );
1917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  count     = TT_NEXT_ULONG( p );
1918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  idx;
1919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( char_code < start )
1922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      char_code = start;
1923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    idx = (FT_UInt32)( char_code - start );
1925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p  += 2 * idx;
1926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; idx < count; idx++ )
1928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      gindex = TT_NEXT_USHORT( p );
1930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( gindex != 0 )
1931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
1932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      char_code++;
1933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *pchar_code = char_code;
1936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
1937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
1941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap10_get_info( TT_CMap       cmap,
1942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      TT_CMapInfo  *cmap_info )
1943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = cmap->data + 8;
1945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->format = 10;
1948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
1949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return SFNT_Err_Ok;
1951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_TABLE_DEF
1955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  const TT_CMap_ClassRec  tt_cmap10_class_rec =
1956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      sizeof ( TT_CMapRec ),
1959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_InitFunc)     tt_cmap_init,
1961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_DoneFunc)     NULL,
1962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_CharIndexFunc)tt_cmap10_char_index,
1963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_CharNextFunc) tt_cmap10_char_next,
1964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      NULL, NULL, NULL, NULL, NULL
1966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    },
1967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    10,
1968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (TT_CMap_ValidateFunc)   tt_cmap10_validate,
1969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (TT_CMap_Info_GetFunc)   tt_cmap10_get_info
1970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  };
1971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* TT_CONFIG_CMAP_FORMAT_10 */
1973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                          FORMAT 12                            *****/
1979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* TABLE OVERVIEW                                                        */
1986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* --------------                                                        */
1987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME        OFFSET     TYPE       DESCRIPTION                       */
1989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   format      0          USHORT     must be 12                        */
1991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   reserved    2          USHORT     reserved                          */
1992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   length      4          ULONG      length in bytes                   */
1993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   language    8          ULONG      Mac language code                 */
1994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   count       12         ULONG      number of groups                  */
1995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*               16                                                      */
1996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* This header is followed by `count' groups of the following format:    */
1998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   start       0          ULONG      first charcode                    */
2000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   end         4          ULONG      last charcode                     */
200177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /*   startId     8          ULONG      start glyph ID for the group      */
2002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_12
2005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef struct  TT_CMap12Rec_
2007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMapRec  cmap;
2009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Bool     valid;
2010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    cur_charcode;
2011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     cur_gindex;
2012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    cur_group;
2013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    num_groups;
2014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  } TT_CMap12Rec, *TT_CMap12;
2016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
2019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap12_init( TT_CMap12  cmap,
2020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_Byte*   table )
2021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->cmap.data  = table;
2023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    table           += 12;
2025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->num_groups = FT_PEEK_ULONG( table );
2026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->valid      = 0;
2028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return SFNT_Err_Ok;
2030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
2034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap12_validate( FT_Byte*      table,
2035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Validator  valid )
2036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p;
2038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong   length;
2039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong   num_groups;
2040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + 16 > valid->limit )
2043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
2044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p      = table + 4;
2046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    length = TT_NEXT_ULONG( p );
2047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p          = table + 12;
2049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_groups = TT_NEXT_ULONG( p );
2050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + length > valid->limit || length < 16 + 12 * num_groups )
2052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
2053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* check groups, they must be in increasing order */
2055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ULong  n, start, end, start_id, last = 0;
2057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( n = 0; n < num_groups; n++ )
2060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        start    = TT_NEXT_ULONG( p );
2062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        end      = TT_NEXT_ULONG( p );
2063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        start_id = TT_NEXT_ULONG( p );
2064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( start > end )
2066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_DATA;
2067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( n > 0 && start <= last )
2069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_DATA;
2070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( valid->level >= FT_VALIDATE_TIGHT )
2072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
2074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_INVALID_GLYPH_ID;
2075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        last = end;
2078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return SFNT_Err_Ok;
2082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* search the index of the charcode next to cmap->cur_charcode */
2086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* cmap->cur_group should be set up properly by caller         */
2087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                             */
2088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
2089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap12_next( TT_CMap12  cmap )
2090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p;
2092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  start, end, start_id, char_code;
2093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  n;
2094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   gindex;
2095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
2098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Fail;
2099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    char_code = cmap->cur_charcode + 1;
2101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    n = cmap->cur_group;
2103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
2105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p        = cmap->cmap.data + 16 + 12 * n;
2107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start    = TT_NEXT_ULONG( p );
2108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      end      = TT_NEXT_ULONG( p );
2109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start_id = TT_PEEK_ULONG( p );
2110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code < start )
2112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        char_code = start;
2113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; char_code <= end; char_code++ )
2115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gindex = (FT_UInt)( start_id + char_code - start );
2117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( gindex )
2119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cmap->cur_charcode = char_code;;
2121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cmap->cur_gindex   = gindex;
2122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cmap->cur_group    = n;
2123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          return;
2125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Fail:
2130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->valid = 0;
2131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_UInt
2135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap12_char_map_binary( TT_CMap     cmap,
2136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             FT_UInt32*  pchar_code,
2137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             FT_Bool     next )
2138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    gindex     = 0;
2140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p          = cmap->data + 12;
2141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  num_groups = TT_PEEK_ULONG( p );
2142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  char_code  = *pchar_code;
2143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  start, end, start_id;
2144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  max, min, mid;
2145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !num_groups )
2148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
2149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* make compiler happy */
2151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    mid = num_groups;
2152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    end = 0xFFFFFFFFUL;
2153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( next )
2155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      char_code++;
2156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    min = 0;
2158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    max = num_groups;
2159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* binary search */
2161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( min < max )
2162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mid = ( min + max ) >> 1;
2164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p   = cmap->data + 16 + 12 * mid;
2165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start = TT_NEXT_ULONG( p );
2167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      end   = TT_NEXT_ULONG( p );
2168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code < start )
2170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        max = mid;
2171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( char_code > end )
2172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        min = mid + 1;
2173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
2174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        start_id = TT_PEEK_ULONG( p );
2176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gindex = (FT_UInt)( start_id + char_code - start );
2177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
2179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( next )
2183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TT_CMap12  cmap12 = (TT_CMap12)cmap;
2185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* if `char_code' is not in any group, then `mid' is */
2188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* the group nearest to `char_code'                  */
2189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /*                                                   */
2190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code > end )
2192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        mid++;
2194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( mid == num_groups )
2195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          return 0;
2196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cmap12->valid        = 1;
2199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cmap12->cur_charcode = char_code;
2200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cmap12->cur_group    = mid;
2201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !gindex )
2203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tt_cmap12_next( cmap12 );
2205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( cmap12->valid )
2207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          gindex = cmap12->cur_gindex;
2208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
2210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cmap12->cur_gindex = gindex;
2211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( gindex )
2213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *pchar_code = cmap12->cur_charcode;
2214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
2217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
2221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap12_char_index( TT_CMap    cmap,
2222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        FT_UInt32  char_code )
2223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return tt_cmap12_char_map_binary( cmap, &char_code, 0 );
2225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
2229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap12_char_next( TT_CMap     cmap,
2230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_UInt32  *pchar_code )
2231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMap12  cmap12 = (TT_CMap12)cmap;
2233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong   gindex;
2234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( cmap12->cur_charcode >= 0xFFFFFFFFUL )
2237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
2238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* no need to search */
2240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( cmap12->valid && cmap12->cur_charcode == *pchar_code )
2241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      tt_cmap12_next( cmap12 );
2243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( cmap12->valid )
2244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gindex = cmap12->cur_gindex;
2246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( gindex )
2247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          *pchar_code = cmap12->cur_charcode;
2248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
2250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gindex = 0;
2251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
2253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 );
2254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
2256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
2260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap12_get_info( TT_CMap       cmap,
2261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      TT_CMapInfo  *cmap_info )
2262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = cmap->data + 8;
2264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->format = 12;
2267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
2268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return SFNT_Err_Ok;
2270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_TABLE_DEF
2274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  const TT_CMap_ClassRec  tt_cmap12_class_rec =
2275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      sizeof ( TT_CMap12Rec ),
2278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_InitFunc)     tt_cmap12_init,
2280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_DoneFunc)     NULL,
2281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_CharIndexFunc)tt_cmap12_char_index,
2282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_CharNextFunc) tt_cmap12_char_next,
2283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      NULL, NULL, NULL, NULL, NULL
2285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    },
2286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    12,
2287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (TT_CMap_ValidateFunc)   tt_cmap12_validate,
2288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (TT_CMap_Info_GetFunc)   tt_cmap12_get_info
2289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  };
2290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* TT_CONFIG_CMAP_FORMAT_12 */
2292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
2297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                           FORMAT 14                           *****/
2298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
2299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* TABLE OVERVIEW                                                        */
2305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* --------------                                                        */
2306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME         OFFSET  TYPE    DESCRIPTION                            */
2308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   format         0     USHORT  must be 14                             */
2310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   length         2     ULONG   table length in bytes                  */
2311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   numSelector    6     ULONG   number of variation sel. records       */
2312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Followed by numSelector records, each of which looks like             */
2314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   varSelector    0     UINT24  Unicode codepoint of sel.              */
2316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   defaultOff     3     ULONG   offset to a default UVS table          */
2317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                describing any variants to be found in */
2318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                the normal Unicode subtable.           */
2319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   nonDefOff      7     ULONG   offset to a non-default UVS table      */
2320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                describing any variants not in the     */
2321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                standard cmap, with GIDs here          */
2322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* (either offset may be 0 NULL)                                         */
2323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Selectors are sorted by code point.                                   */
2325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* A default Unicode Variation Selector (UVS) subtable is just a list of */
2327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* ranges of code points which are to be found in the standard cmap.  No */
2328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* glyph IDs (GIDs) here.                                                */
2329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   numRanges      0     ULONG   number of ranges following             */
2331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* A range looks like                                                    */
2333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   uniStart       0     UINT24  code point of the first character in   */
2335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                this range                             */
2336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   additionalCnt  3     UBYTE   count of additional characters in this */
2337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                range (zero means a range of a single  */
2338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                character)                             */
2339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Ranges are sorted by `uniStart'.                                      */
2341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* A non-default Unicode Variation Selector (UVS) subtable is a list of  */
2343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* mappings from codepoint to GID.                                       */
2344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   numMappings    0     ULONG   number of mappings                     */
2346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* A range looks like                                                    */
2348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   uniStart       0     UINT24  code point of the first character in   */
2350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                this range                             */
2351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   GID            3     USHORT  and its GID                            */
2352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Ranges are sorted by `uniStart'.                                      */
2354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_14
2356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef struct  TT_CMap14Rec_
2358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMapRec  cmap;
2360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    num_selectors;
2361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* This array is used to store the results of various
2363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * cmap 14 query functions.  The data is overwritten
2364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * on each call to these functions.
2365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
2366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     max_results;
2367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32*  results;
2368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory   memory;
2369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  } TT_CMap14Rec, *TT_CMap14;
2371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( void )
2374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_done( TT_CMap14  cmap )
2375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory  memory = cmap->memory;
2377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->max_results = 0;
2380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( memory != NULL && cmap->results != NULL )
2381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FREE( cmap->results );
2382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
2386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_ensure( TT_CMap14  cmap,
2387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    FT_UInt    num_results,
2388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    FT_Memory  memory )
2389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   old_max = cmap->max_results;
2391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error  error   = 0;
2392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( num_results > cmap->max_results )
2395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       cmap->memory = memory;
2397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       if ( FT_QRENEW_ARRAY( cmap->results, old_max, num_results ) )
2399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         return error;
2400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       cmap->max_results = num_results;
2402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
2405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
2409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_init( TT_CMap14  cmap,
2410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_Byte*   table )
2411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->cmap.data = table;
2413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    table               += 6;
2415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->num_selectors = FT_PEEK_ULONG( table );
2416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->max_results   = 0;
2417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->results       = NULL;
2418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return SFNT_Err_Ok;
2420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
2424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_validate( FT_Byte*      table,
2425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Validator  valid )
2426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p             = table + 2;
2428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  length        = TT_NEXT_ULONG( p );
2429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  num_selectors = TT_NEXT_ULONG( p );
2430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + length > valid->limit || length < 10 + 11 * num_selectors )
2433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
2434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* check selectors, they must be in increasing order */
2436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we start lastVarSel at 1 because a variant selector value of 0
2438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       * isn't valid.
2439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       */
2440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ULong  n, lastVarSel = 1;
2441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( n = 0; n < num_selectors; n++ )
2444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_ULong  varSel    = TT_NEXT_UINT24( p );
2446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_ULong  defOff    = TT_NEXT_ULONG( p );
2447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_ULong  nondefOff = TT_NEXT_ULONG( p );
2448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( defOff >= length || nondefOff >= length )
2451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_TOO_SHORT;
2452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( varSel < lastVarSel )
2454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_DATA;
2455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        lastVarSel = varSel + 1;
2457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* check the default table (these glyphs should be reached     */
2459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* through the normal Unicode cmap, no GIDs, just check order) */
2460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( defOff != 0 )
2461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Byte*  defp      = table + defOff;
2463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_ULong  numRanges = TT_NEXT_ULONG( defp );
2464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_ULong  i;
2465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_ULong  lastBase  = 0;
2466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( defp + numRanges * 4 > valid->limit )
2469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_INVALID_TOO_SHORT;
2470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( i = 0; i < numRanges; ++i )
2472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_ULong  base = TT_NEXT_UINT24( defp );
2474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_ULong  cnt  = FT_NEXT_BYTE( defp );
2475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( base + cnt >= 0x110000UL )              /* end of Unicode */
2478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_INVALID_DATA;
2479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( base < lastBase )
2481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_INVALID_DATA;
2482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            lastBase = base + cnt + 1U;
2484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* and the non-default table (these glyphs are specified here) */
2488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( nondefOff != 0 ) {
2489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Byte*  ndp         = table + nondefOff;
2490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_ULong  numMappings = TT_NEXT_ULONG( ndp );
2491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_ULong  i, lastUni = 0;
2492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( ndp + numMappings * 4 > valid->limit )
2495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_INVALID_TOO_SHORT;
2496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( i = 0; i < numMappings; ++i )
2498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_ULong  uni = TT_NEXT_UINT24( ndp );
2500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_ULong  gid = TT_NEXT_USHORT( ndp );
2501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( uni >= 0x110000UL )                     /* end of Unicode */
2504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_INVALID_DATA;
2505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( uni < lastUni )
2507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_INVALID_DATA;
2508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            lastUni = uni + 1U;
2510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( valid->level >= FT_VALIDATE_TIGHT    &&
2512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 gid >= TT_VALID_GLYPH_COUNT( valid ) )
2513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_INVALID_GLYPH_ID;
2514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return SFNT_Err_Ok;
2520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
2524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_char_index( TT_CMap    cmap,
2525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        FT_UInt32  char_code )
2526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( cmap );
2528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( char_code );
2529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* This can't happen */
2531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
2532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
2536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_char_next( TT_CMap     cmap,
2537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_UInt32  *pchar_code )
2538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( cmap );
2540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* This can't happen */
2542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *pchar_code = 0;
2543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
2544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
2548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_get_info( TT_CMap       cmap,
2549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      TT_CMapInfo  *cmap_info )
2550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( cmap );
2552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->format = 14;
2554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* subtable 14 does not define a language field */
2555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->language = 0xFFFFFFFFUL;
2556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return SFNT_Err_Ok;
2558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_UInt
2562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_char_map_def_binary( FT_Byte    *base,
2563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 FT_UInt32   char_code )
2564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  numRanges = TT_PEEK_ULONG( base );
2566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  max, min;
2567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    min = 0;
2570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    max = numRanges;
2571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base += 4;
2573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* binary search */
2575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( min < max )
2576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  mid   = ( min + max ) >> 1;
2578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*   p     = base + 4 * mid;
2579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ULong   start = TT_NEXT_UINT24( p );
2580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt    cnt   = FT_NEXT_BYTE( p );
2581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code < start )
2584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        max = mid;
2585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( char_code > start+cnt )
2586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        min = mid + 1;
2587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
2588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return TRUE;
2589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return FALSE;
2592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_UInt
2596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_char_map_nondef_binary( FT_Byte    *base,
2597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                    FT_UInt32   char_code )
2598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  numMappings = TT_PEEK_ULONG( base );
2600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  max, min;
2601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    min = 0;
2604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    max = numMappings;
2605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base += 4;
2607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* binary search */
2609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( min < max )
2610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  mid = ( min + max ) >> 1;
2612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*   p   = base + 5 * mid;
2613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  uni = TT_NEXT_UINT24( p );
2614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code < uni )
2617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        max = mid;
2618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( char_code > uni )
2619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        min = mid + 1;
2620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
2621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return TT_PEEK_USHORT( p );
2622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
2625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Byte*
2629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_find_variant( FT_Byte    *base,
2630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          FT_UInt32   variantCode )
2631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  numVar = TT_PEEK_ULONG( base );
2633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  max, min;
2634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    min = 0;
2637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    max = numVar;
2638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base += 4;
2640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* binary search */
2642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( min < max )
2643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  mid    = ( min + max ) >> 1;
2645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*   p      = base + 11 * mid;
2646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ULong   varSel = TT_NEXT_UINT24( p );
2647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( variantCode < varSel )
2650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        max = mid;
2651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( variantCode > varSel )
2652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        min = mid + 1;
2653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
2654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return p;
2655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return NULL;
2658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
2662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_char_var_index( TT_CMap   cmap,
2663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            TT_CMap   ucmap,
2664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            FT_ULong  charcode,
2665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            FT_ULong  variantSelector)
2666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
2668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  defOff;
2669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  nondefOff;
2670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !p )
2673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
2674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    defOff    = TT_NEXT_ULONG( p );
2676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    nondefOff = TT_PEEK_ULONG( p );
2677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( defOff != 0                                                    &&
2679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )
2680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* This is the default variant of this charcode.  GID not stored */
2682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* here; stored in the normal Unicode charmap instead.           */
2683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return ucmap->cmap.clazz->char_index( &ucmap->cmap, charcode );
2684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( nondefOff != 0 )
2687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
2688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                               charcode );
2689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
2691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Int )
2695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_char_var_isdefault( TT_CMap   cmap,
2696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                FT_ULong  charcode,
2697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                FT_ULong  variantSelector )
2698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
2700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  defOff;
2701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  nondefOff;
2702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !p )
2705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return -1;
2706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    defOff    = TT_NEXT_ULONG( p );
2708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    nondefOff = TT_NEXT_ULONG( p );
2709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( defOff != 0                                                    &&
2711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )
2712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 1;
2713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( nondefOff != 0                                            &&
2715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
2716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                           charcode ) != 0         )
2717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
2718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return -1;
2720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt32* )
2724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_variants( TT_CMap    cmap,
2725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Memory  memory )
2726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMap14   cmap14 = (TT_CMap14)cmap;
2728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     count  = cmap14->num_selectors;
2729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*    p      = cmap->data + 10;
2730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32*  result;
2731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     i;
2732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
2735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return NULL;
2736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    result = cmap14->results;
2738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( i = 0; i < count; ++i )
2739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result[i] = TT_NEXT_UINT24( p );
2741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p        += 8;
2742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    result[i] = 0;
2744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return result;
2746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt32 * )
2750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_char_variants( TT_CMap    cmap,
2751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_Memory  memory,
2752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_ULong   charCode )
2753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMap14   cmap14 = (TT_CMap14)  cmap;
2755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     count  = cmap14->num_selectors;
2756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*    p      = cmap->data + 10;
2757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32*  q;
2758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
2761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return NULL;
2762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( q = cmap14->results; count > 0; --count )
2764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  varSel    = TT_NEXT_UINT24( p );
2766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ULong   defOff    = TT_NEXT_ULONG( p );
2767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ULong   nondefOff = TT_NEXT_ULONG( p );
2768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ( defOff != 0                                               &&
2771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             tt_cmap14_char_map_def_binary( cmap->data + defOff,
2772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                            charCode )                 ) ||
2773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           ( nondefOff != 0                                            &&
2774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
2775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                               charCode ) != 0         ) )
2776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        q[0] = varSel;
2778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        q++;
2779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    q[0] = 0;
2782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return cmap14->results;
2784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_UInt
2788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_def_char_count( FT_Byte  *p )
2789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  numRanges = TT_NEXT_ULONG( p );
2791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    tot       = 0;
2792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
279477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    p += 3;  /* point to the first `cnt' field */
2795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; numRanges > 0; numRanges-- )
2796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      tot += 1 + p[0];
2798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p   += 4;
2799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return tot;
2802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_UInt32*
2806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_get_def_chars( TT_CMap     cmap,
2807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_Byte*    p,
2808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_Memory   memory )
2809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMap14   cmap14 = (TT_CMap14) cmap;
2811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32   numRanges;
2812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     cnt;
2813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32*  q;
2814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cnt       = tt_cmap14_def_char_count( p );
2817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    numRanges = TT_NEXT_ULONG( p );
2818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( tt_cmap14_ensure( cmap14, ( cnt + 1 ), memory ) )
2820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return NULL;
2821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( q = cmap14->results; numRanges > 0; --numRanges )
2823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  uni = TT_NEXT_UINT24( p );
2825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cnt = FT_NEXT_BYTE( p ) + 1;
2828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      do
2829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        q[0]  = uni;
2831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        uni  += 1;
2832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        q    += 1;
2833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      } while ( --cnt != 0 );
2834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    q[0] = 0;
2836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return cmap14->results;
2838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
284177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  static FT_UInt32*
2842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_get_nondef_chars( TT_CMap     cmap,
2843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              FT_Byte    *p,
2844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              FT_Memory   memory )
2845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMap14   cmap14 = (TT_CMap14) cmap;
2847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32   numMappings;
2848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     i;
2849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  *ret;
2850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    numMappings = TT_NEXT_ULONG( p );
2853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( tt_cmap14_ensure( cmap14, ( numMappings + 1 ), memory ) )
2855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return NULL;
2856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ret = cmap14->results;
2858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( i = 0; i < numMappings; ++i )
2859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ret[i] = TT_NEXT_UINT24( p );
2861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p += 2;
2862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ret[i] = 0;
2864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return ret;
2866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt32 * )
2870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_variant_chars( TT_CMap    cmap,
2871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_Memory  memory,
2872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_ULong   variantSelector )
2873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte    *p  = tt_cmap14_find_variant( cmap->data + 6,
2875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                             variantSelector );
2876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  *ret;
2877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int      i;
2878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    defOff;
2879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    nondefOff;
2880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !p )
2883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return NULL;
2884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    defOff    = TT_NEXT_ULONG( p );
2886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    nondefOff = TT_NEXT_ULONG( p );
2887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( defOff == 0 && nondefOff == 0 )
2889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return NULL;
2890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( defOff == 0 )
2892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,
2893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                         memory );
2894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else if ( nondefOff == 0 )
2895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,
2896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                      memory );
2897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
2898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* Both a default and a non-default glyph set?  That's probably not */
2900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* good font design, but the spec allows for it...                  */
2901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TT_CMap14  cmap14 = (TT_CMap14) cmap;
2902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  numRanges;
2903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  numMappings;
2904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  duni;
2905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  dcnt;
2906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  nuni;
2907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*   dp;
2908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt    di, ni, k;
2909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p  = cmap->data + nondefOff;
2912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dp = cmap->data + defOff;
2913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      numMappings = TT_NEXT_ULONG( p );
2915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dcnt        = tt_cmap14_def_char_count( dp );
2916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      numRanges   = TT_NEXT_ULONG( dp );
2917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( numMappings == 0 )
2919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,
2920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                        memory );
2921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( dcnt == 0 )
2922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,
2923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                           memory );
2924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tt_cmap14_ensure( cmap14, ( dcnt + numMappings + 1 ), memory ) )
2926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return NULL;
2927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ret  = cmap14->results;
2929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      duni = TT_NEXT_UINT24( dp );
2930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dcnt = FT_NEXT_BYTE( dp );
2931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      di   = 1;
2932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      nuni = TT_NEXT_UINT24( p );
2933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p   += 2;
2934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ni   = 1;
2935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      i    = 0;
2936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ;; )
2938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( nuni > duni + dcnt )
2940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( k = 0; k <= dcnt; ++k )
2942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            ret[i++] = duni + k;
2943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ++di;
2945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( di > numRanges )
2947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
2948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          duni = TT_NEXT_UINT24( dp );
2950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dcnt = FT_NEXT_BYTE( dp );
2951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
2953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( nuni < duni )
2955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            ret[i++] = nuni;
2956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* If it is within the default range then ignore it -- */
2957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* that should not have happened                       */
2958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ++ni;
2959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( ni > numMappings )
2960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
2961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          nuni = TT_NEXT_UINT24( p );
2963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p += 2;
2964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ni <= numMappings )
2968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* If we get here then we have run out of all default ranges.   */
2970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* We have read one non-default mapping which we haven't stored */
2971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* and there may be others that need to be read.                */
2972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ret[i++] = nuni;
2973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        while ( ni < numMappings )
2974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ret[i++] = TT_NEXT_UINT24( p );
2976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p += 2;
2977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ++ni;
2978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( di <= numRanges )
2981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* If we get here then we have run out of all non-default     */
2983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* mappings.  We have read one default range which we haven't */
2984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* stored and there may be others that need to be read.       */
2985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( k = 0; k <= dcnt; ++k )
2986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ret[i++] = duni + k;
2987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        while ( di < numRanges )
2989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          duni = TT_NEXT_UINT24( dp );
2991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dcnt = FT_NEXT_BYTE( dp );
2992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( k = 0; k <= dcnt; ++k )
2994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            ret[i++] = duni + k;
2995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ++di;
2996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ret[i] = 0;
3000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return ret;
3002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_TABLE_DEF
3007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  const TT_CMap_ClassRec  tt_cmap14_class_rec =
3008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      sizeof ( TT_CMap14Rec ),
3011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_InitFunc)     tt_cmap14_init,
3013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_DoneFunc)     tt_cmap14_done,
3014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_CharIndexFunc)tt_cmap14_char_index,
3015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_CharNextFunc) tt_cmap14_char_next,
3016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* Format 14 extension functions */
3018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_CharVarIndexFunc)    tt_cmap14_char_var_index,
3019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault,
3020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_VariantListFunc)     tt_cmap14_variants,
3021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants,
3022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars
3023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    },
3024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    14,
3025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (TT_CMap_ValidateFunc)tt_cmap14_validate,
3026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (TT_CMap_Info_GetFunc)tt_cmap14_get_info
3027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  };
3028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
302977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner#endif /* TT_CONFIG_CMAP_FORMAT_14 */
3030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static const TT_CMap_Class  tt_cmap_classes[] =
3033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_0
3035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    &tt_cmap0_class_rec,
3036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
3037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_2
3039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    &tt_cmap2_class_rec,
3040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
3041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_4
3043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    &tt_cmap4_class_rec,
3044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
3045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_6
3047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    &tt_cmap6_class_rec,
3048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
3049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_8
3051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    &tt_cmap8_class_rec,
3052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
3053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_10
3055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    &tt_cmap10_class_rec,
3056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
3057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_12
3059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    &tt_cmap12_class_rec,
3060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
3061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_14
3063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    &tt_cmap14_class_rec,
3064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
3065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    NULL,
3067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  };
3068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* parse the `cmap' table and build the corresponding TT_CMap objects */
3071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* in the current face                                                */
3072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                    */
3073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
3074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_face_build_cmaps( TT_Face  face )
3075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*           table = face->cmap_table;
3077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*           limit = table + face->cmap_size;
3078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt volatile   num_cmaps;
3079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte* volatile  p     = table;
3080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( p + 4 > limit )
3083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return SFNT_Err_Invalid_Table;
3084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* only recognize format 0 */
3086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( TT_NEXT_USHORT( p ) != 0 )
3087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p -= 2;
3089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ERROR(( "tt_face_build_cmaps: unsupported `cmap' table format = %d\n",
3090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 TT_PEEK_USHORT( p ) ));
3091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return SFNT_Err_Invalid_Table;
3092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_cmaps = TT_NEXT_USHORT( p );
3095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- )
3097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_CharMapRec  charmap;
3099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32      offset;
3100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      charmap.platform_id = TT_NEXT_USHORT( p );
3103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      charmap.encoding_id = TT_NEXT_USHORT( p );
3104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      charmap.face        = FT_FACE( face );
3105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      charmap.encoding    = FT_ENCODING_NONE;  /* will be filled later */
3106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      offset              = TT_NEXT_ULONG( p );
3107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( offset && offset <= face->cmap_size - 2 )
3109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
3110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Byte* volatile              cmap   = table + offset;
3111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        volatile FT_UInt               format = TT_PEEK_USHORT( cmap );
3112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        const TT_CMap_Class* volatile  pclazz = tt_cmap_classes;
3113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        TT_CMap_Class volatile         clazz;
3114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( ; *pclazz; pclazz++ )
3117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
3118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          clazz = *pclazz;
3119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( clazz->format == format )
3120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
3121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            volatile TT_ValidatorRec  valid;
3122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            volatile FT_Error         error = SFNT_Err_Ok;
3123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit,
3126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                               FT_VALIDATE_DEFAULT );
3127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            valid.num_glyphs = (FT_UInt)face->max_profile.numGlyphs;
3129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( ft_setjmp(
3131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              *((ft_jmp_buf*)&FT_VALIDATOR( &valid )->jump_buffer) ) == 0 )
3132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
3133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              /* validate this cmap sub-table */
3134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              error = clazz->validate( cmap, FT_VALIDATOR( &valid ) );
3135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
3136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( valid.validator.error == 0 )
3138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
3139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_CMap  ttcmap;
3140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              /* It might make sense to store the single variation selector */
3143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              /* cmap somewhere special.  But it would have to be in the    */
3144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              /* public FT_FaceRec, and we can't change that.               */
3145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( !FT_CMap_New( (FT_CMap_Class)clazz,
3147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 cmap, &charmap, &ttcmap ) )
3148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
3149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                /* it is simpler to directly set `flags' than adding */
3150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                /* a parameter to FT_CMap_New                        */
3151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                ((TT_CMap)ttcmap)->flags = (FT_Int)error;
3152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
3153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
3154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
3155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
3156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_ERROR(( "tt_face_build_cmaps:" ));
3157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_ERROR(( " broken cmap sub-table ignored!\n" ));
3158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
3159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
3160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
3161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
3162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( *pclazz == NULL )
3164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
3165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_ERROR(( "tt_face_build_cmaps:" ));
3166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_ERROR(( " unsupported cmap sub-table ignored!\n" ));
3167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
3168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
3169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return SFNT_Err_Ok;
3172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL( FT_Error )
3176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_get_cmap_info( FT_CharMap    charmap,
3177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    TT_CMapInfo  *cmap_info )
3178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_CMap        cmap  = (FT_CMap)charmap;
3180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMap_Class  clazz = (TT_CMap_Class)cmap->clazz;
3181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return clazz->get_cmap_info( charmap, cmap_info );
3184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* END */
3188