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/*                                                                         */
7a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  Copyright 2002-2010, 2012, 2013 by                                     */
8049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
10049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  This file is part of the FreeType project, and may only be used,       */
11049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  modified, and distributed under the terms of the FreeType project      */
12049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  this file you indicate that you have read the license and              */
14049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  understand and accept it fully.                                        */
15049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
16049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
17049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
18049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
19049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include <ft2build.h>
20049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_DEBUG_H
21049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
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"
28295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#include "sfntpic.h"
29049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
30049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
31049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
32049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
33049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
34049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
35049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* messages during execution.                                            */
36049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
37049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#undef  FT_COMPONENT
38049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_COMPONENT  trace_ttcmap
39049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
40049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
41049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define TT_PEEK_SHORT   FT_PEEK_SHORT
42049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define TT_PEEK_USHORT  FT_PEEK_USHORT
43049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define TT_PEEK_UINT24  FT_PEEK_UOFF3
44049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define TT_PEEK_LONG    FT_PEEK_LONG
45049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define TT_PEEK_ULONG   FT_PEEK_ULONG
46049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
47049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define TT_NEXT_SHORT   FT_NEXT_SHORT
48049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define TT_NEXT_USHORT  FT_NEXT_USHORT
49049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define TT_NEXT_UINT24  FT_NEXT_UOFF3
50049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define TT_NEXT_LONG    FT_NEXT_LONG
51049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define TT_NEXT_ULONG   FT_NEXT_ULONG
52049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
53049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
54049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
55049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap_init( TT_CMap   cmap,
56049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                FT_Byte*  table )
57049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
58049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->data = table;
59a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
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  /*****                                                               *****/
66049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                           FORMAT 0                            *****/
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  /*                                                                       */
73049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* TABLE OVERVIEW                                                        */
74049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* --------------                                                        */
75049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
76049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME        OFFSET         TYPE          DESCRIPTION                */
77049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
78049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   format      0              USHORT        must be 0                  */
79049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   length      2              USHORT        table length in bytes      */
80049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   language    4              USHORT        Mac language code          */
81049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   glyph_ids   6              BYTE[256]     array of glyph indices     */
82049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*               262                                                     */
83049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
84049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
85049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_0
86049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
87049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
88049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap0_validate( FT_Byte*      table,
89049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Validator  valid )
90049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
91049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p      = table + 2;
92049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   length = TT_NEXT_USHORT( p );
93049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
94049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
95049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + length > valid->limit || length < 262 )
96049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
97049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
98049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* check glyph indices whenever necessary */
99049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( valid->level >= FT_VALIDATE_TIGHT )
100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  n, idx;
102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p = table + 6;
105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( n = 0; n < 256; n++ )
106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        idx = *p++;
108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_GLYPH_ID;
110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
113a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap0_char_index( TT_CMap    cmap,
119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_UInt32  char_code )
120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  table = cmap->data;
122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return char_code < 256 ? table[6 + char_code] : 0;
125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
128295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_UInt32 )
129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap0_char_next( TT_CMap     cmap,
130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_UInt32  *pchar_code )
131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   table    = cmap->data;
133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  charcode = *pchar_code;
134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  result   = 0;
135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    gindex   = 0;
136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
13877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    table += 6;  /* go to glyph IDs */
139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( ++charcode < 256 )
140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      gindex = table[charcode];
142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( gindex != 0 )
143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        result = charcode;
145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *pchar_code = result;
150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap0_get_info( TT_CMap       cmap,
156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     TT_CMapInfo  *cmap_info )
157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = cmap->data + 4;
159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
161295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap_info->format   = 0;
162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
164a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
168a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_DEFINE_TT_CMAP(
169a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    tt_cmap0_class_rec,
170a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    sizeof ( TT_CMapRec ),
171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
172a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_InitFunc)     tt_cmap_init,
173a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_DoneFunc)     NULL,
174a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_CharIndexFunc)tt_cmap0_char_index,
175a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_CharNextFunc) tt_cmap0_char_next,
176a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
177a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
178a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
179a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
180a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
181a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    0,
184a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (TT_CMap_ValidateFunc)tt_cmap0_validate,
185a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (TT_CMap_Info_GetFunc)tt_cmap0_get_info )
186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* TT_CONFIG_CMAP_FORMAT_0 */
188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                          FORMAT 2                             *****/
194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** This is used for certain CJK encodings that encode text in a  *****/
196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** mixed 8/16 bits encoding along the following lines:           *****/
197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** * Certain byte values correspond to an 8-bit character code   *****/
199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   (typically in the range 0..127 for ASCII compatibility).    *****/
200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** * Certain byte values signal the first byte of a 2-byte       *****/
202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   character code (but these values are also valid as the      *****/
203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   second byte of a 2-byte character).                         *****/
204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** The following charmap lookup and iteration functions all      *****/
206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** assume that the value "charcode" correspond to following:     *****/
207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   - For one byte characters, "charcode" is simply the         *****/
209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****     character code.                                           *****/
210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   - For two byte characters, "charcode" is the 2-byte         *****/
212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****     character code in big endian format.  More exactly:       *****/
213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****       (charcode >> 8)    is the first byte value              *****/
215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****       (charcode & 0xFF)  is the second byte value             *****/
216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** Note that not all values of "charcode" are valid according    *****/
218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** to these rules, and the function moderately check the         *****/
219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** arguments.                                                    *****/
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  /*************************************************************************/
225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* TABLE OVERVIEW                                                        */
227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* --------------                                                        */
228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME        OFFSET         TYPE            DESCRIPTION              */
230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   format      0              USHORT          must be 2                */
232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   length      2              USHORT          table length in bytes    */
233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   language    4              USHORT          Mac language code        */
234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   keys        6              USHORT[256]     sub-header keys          */
235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   subs        518            SUBHEAD[NSUBS]  sub-headers array        */
23677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /*   glyph_ids   518+NSUB*8     USHORT[]        glyph ID array           */
237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* The `keys' table is used to map charcode high-bytes to sub-headers.   */
239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* The value of `NSUBS' is the number of sub-headers defined in the      */
240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* table and is computed by finding the maximum of the `keys' table.     */
241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Note that for any n, `keys[n]' is a byte offset within the `subs'     */
243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* table, i.e., it is the corresponding sub-header index multiplied      */
244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* by 8.                                                                 */
245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Each sub-header has the following format:                             */
247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME        OFFSET      TYPE            DESCRIPTION                 */
249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   first       0           USHORT          first valid low-byte        */
251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   count       2           USHORT          number of valid low-bytes   */
252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   delta       4           SHORT           see below                   */
253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   offset      6           USHORT          see below                   */
254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* A sub-header defines, for each high-byte, the range of valid          */
256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* low-bytes within the charmap.  Note that the range defined by `first' */
257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* and `count' must be completely included in the interval [0..255]      */
258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* according to the specification.                                       */
259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* If a character code is contained within a given sub-header, then      */
261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* mapping it to a glyph index is done as follows:                       */
262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* * The value of `offset' is read.  This is a _byte_ distance from the  */
264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   location of the `offset' field itself into a slice of the           */
26577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /*   `glyph_ids' table.  Let's call it `slice' (it is a USHORT[] too).   */
266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* * The value `slice[char.lo - first]' is read.  If it is 0, there is   */
268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   no glyph for the charcode.  Otherwise, the value of `delta' is      */
269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   added to it (modulo 65536) to form a new glyph index.               */
270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* It is up to the validation routine to check that all offsets fall     */
27277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* within the glyph IDs table (and not within the `subs' table itself or */
273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* outside of the CMap).                                                 */
274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_2
277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap2_validate( FT_Byte*      table,
280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Validator  valid )
281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p      = table + 2;           /* skip format */
283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   length = TT_PEEK_USHORT( p );
284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   n, max_subs;
285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  keys;                         /* keys table */
286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  subs;                         /* sub-headers */
28777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    FT_Byte*  glyph_ids;                    /* glyph ID array */
288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + length > valid->limit || length < 6 + 512 )
291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    keys = table + 6;
294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* parse keys to compute sub-headers count */
296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p        = keys;
297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    max_subs = 0;
298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( n = 0; n < 256; n++ )
299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  idx = TT_NEXT_USHORT( p );
301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* value must be multiple of 8 */
304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 )
305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_INVALID_DATA;
306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      idx >>= 3;
308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( idx > max_subs )
310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        max_subs = idx;
311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ASSERT( p == table + 518 );
314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    subs      = p;
316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    glyph_ids = subs + (max_subs + 1) * 8;
317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( glyph_ids > valid->limit )
318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* parse sub-headers */
321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( n = 0; n <= max_subs; n++ )
322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   first_code, code_count, offset;
324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int    delta;
325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  ids;
326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      first_code = TT_NEXT_USHORT( p );
329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      code_count = TT_NEXT_USHORT( p );
330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta      = TT_NEXT_SHORT( p );
331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      offset     = TT_NEXT_USHORT( p );
332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
33377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      /* many Dynalab fonts have empty sub-headers */
33477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      if ( code_count == 0 )
33577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        continue;
33677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* check range within 0..255 */
338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( valid->level >= FT_VALIDATE_PARANOID )
339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( first_code >= 256 || first_code + code_count > 256 )
341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_DATA;
342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* check offset */
345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( offset != 0 )
346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ids = p - 2 + offset;
348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( ids < glyph_ids || ids + code_count*2 > table + length )
349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_OFFSET;
350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
35177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        /* check glyph IDs */
352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( valid->level >= FT_VALIDATE_TIGHT )
353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Byte*  limit = p + code_count * 2;
355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt   idx;
356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( ; p < limit; )
359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            idx = TT_NEXT_USHORT( p );
361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( idx != 0 )
362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              idx = ( idx + delta ) & 0xFFFFU;
364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                FT_INVALID_GLYPH_ID;
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    }
371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
372a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* return sub header corresponding to a given character code */
377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* NULL on invalid charcode                                  */
378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Byte*
379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap2_get_subheader( FT_Byte*   table,
380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          FT_UInt32  char_code )
381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  result = NULL;
383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( char_code < 0x10000UL )
386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   char_lo = (FT_UInt)( char_code & 0xFF );
388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   char_hi = (FT_UInt)( char_code >> 8 );
389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  p       = table + 6;    /* keys table */
390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  subs    = table + 518;  /* subheaders table */
391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  sub;
392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_hi == 0 )
395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* an 8-bit character code -- we use subHeader 0 in this case */
397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* to test whether the character code is in the charmap       */
398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /*                                                            */
399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        sub = subs;  /* jump to first sub-header */
400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* check that the sub-header for this byte is 0, which */
40277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        /* indicates that it is really a valid one-byte value  */
403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* Otherwise, return 0                                 */
404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /*                                                     */
405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p += char_lo * 2;
406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( TT_PEEK_USHORT( p ) != 0 )
407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Exit;
408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* a 16-bit character code */
412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* jump to key entry  */
414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p  += char_hi * 2;
415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* jump to sub-header */
416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        sub = subs + ( FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 8 ) );
417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* check that the high byte isn't a valid one-byte value */
419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( sub == subs )
420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Exit;
421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = sub;
423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return result;
426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap2_char_index( TT_CMap    cmap,
431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_UInt32  char_code )
432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  table   = cmap->data;
434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   result  = 0;
435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  subheader;
436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    subheader = tt_cmap2_get_subheader( table, char_code );
439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( subheader )
440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  p   = subheader;
442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   idx = (FT_UInt)(char_code & 0xFF);
443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   start, count;
444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int    delta;
445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   offset;
446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start  = TT_NEXT_USHORT( p );
449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      count  = TT_NEXT_USHORT( p );
450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta  = TT_NEXT_SHORT ( p );
451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      offset = TT_PEEK_USHORT( p );
452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      idx -= start;
454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( idx < count && offset != 0 )
455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p  += offset + 2 * idx;
457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        idx = TT_PEEK_USHORT( p );
458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( idx != 0 )
460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          result = (FT_UInt)( idx + delta ) & 0xFFFFU;
461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return result;
464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
467295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_UInt32 )
468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap2_char_next( TT_CMap     cmap,
469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_UInt32  *pcharcode )
470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   table    = cmap->data;
472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    gindex   = 0;
473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  result   = 0;
474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  charcode = *pcharcode + 1;
475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   subheader;
476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( charcode < 0x10000UL )
479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      subheader = tt_cmap2_get_subheader( table, charcode );
481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( subheader )
482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Byte*  p       = subheader;
484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt   start   = TT_NEXT_USHORT( p );
485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt   count   = TT_NEXT_USHORT( p );
486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Int    delta   = TT_NEXT_SHORT ( p );
487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt   offset  = TT_PEEK_USHORT( p );
488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt   char_lo = (FT_UInt)( charcode & 0xFF );
489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt   pos, idx;
490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( offset == 0 )
493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Next_SubHeader;
494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( char_lo < start )
496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          char_lo = start;
498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          pos     = 0;
499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          pos = (FT_UInt)( char_lo - start );
502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p       += offset + pos * 2;
504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        charcode = FT_PAD_FLOOR( charcode, 256 ) + char_lo;
505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( ; pos < count; pos++, charcode++ )
507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          idx = TT_NEXT_USHORT( p );
509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( idx != 0 )
511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            gindex = ( idx + delta ) & 0xFFFFU;
513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( gindex != 0 )
514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              result = charcode;
516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              goto Exit;
517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* jump to next sub-header, i.e. higher byte value */
523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    Next_SubHeader:
524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      charcode = FT_PAD_FLOOR( charcode, 256 ) + 256;
525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *pcharcode = result;
529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap2_get_info( TT_CMap       cmap,
536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     TT_CMapInfo  *cmap_info )
537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = cmap->data + 4;
539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
541295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap_info->format   = 2;
542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
544a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
548a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_DEFINE_TT_CMAP(
549a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    tt_cmap2_class_rec,
550a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    sizeof ( TT_CMapRec ),
551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
552a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_InitFunc)     tt_cmap_init,
553a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_DoneFunc)     NULL,
554a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_CharIndexFunc)tt_cmap2_char_index,
555a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_CharNextFunc) tt_cmap2_char_next,
556a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
557a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
558a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
559a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
560a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
561a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    2,
564a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (TT_CMap_ValidateFunc)tt_cmap2_validate,
565a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (TT_CMap_Info_GetFunc)tt_cmap2_get_info )
566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* TT_CONFIG_CMAP_FORMAT_2 */
568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                           FORMAT 4                            *****/
574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* TABLE OVERVIEW                                                        */
581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* --------------                                                        */
582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME          OFFSET         TYPE              DESCRIPTION          */
584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   format        0              USHORT            must be 4            */
586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   length        2              USHORT            table length         */
587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                  in bytes             */
588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   language      4              USHORT            Mac language code    */
589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   segCountX2    6              USHORT            2*NUM_SEGS           */
591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   searchRange   8              USHORT            2*(1 << LOG_SEGS)    */
592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   entrySelector 10             USHORT            LOG_SEGS             */
593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   rangeShift    12             USHORT            segCountX2 -         */
594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                    searchRange        */
595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   endCount      14             USHORT[NUM_SEGS]  end charcode for     */
597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                  each segment; last   */
598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                  is 0xFFFF            */
599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   pad           14+NUM_SEGS*2  USHORT            padding              */
601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   startCount    16+NUM_SEGS*2  USHORT[NUM_SEGS]  first charcode for   */
603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                  each segment         */
604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   idDelta       16+NUM_SEGS*4  SHORT[NUM_SEGS]   delta for each       */
606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                  segment              */
607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   idOffset      16+NUM_SEGS*6  SHORT[NUM_SEGS]   range offset for     */
608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                  each segment; can be */
609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                  zero                 */
610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
61177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /*   glyphIds      16+NUM_SEGS*8  USHORT[]          array of glyph ID    */
612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                  ranges               */
613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Character codes are modelled by a series of ordered (increasing)      */
615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* intervals called segments.  Each segment has start and end codes,     */
616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* provided by the `startCount' and `endCount' arrays.  Segments must    */
61777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* not overlap, and the last segment should always contain the value     */
61877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* 0xFFFF for `endCount'.                                                */
619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* The fields `searchRange', `entrySelector' and `rangeShift' are better */
621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* ignored (they are traces of over-engineering in the TrueType          */
622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* specification).                                                       */
623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Each segment also has a signed `delta', as well as an optional offset */
625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* within the `glyphIds' table.                                          */
626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* If a segment's idOffset is 0, the glyph index corresponding to any    */
628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* charcode within the segment is obtained by adding the value of        */
629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* `idDelta' directly to the charcode, modulo 65536.                     */
630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
63177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* Otherwise, a glyph index is taken from the glyph IDs sub-array for    */
632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* the segment, and the value of `idDelta' is added to it.               */
633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
63577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* Finally, note that a lot of fonts contain an invalid last segment,    */
63677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* where `start' and `end' are correctly set to 0xFFFF but both `delta'  */
63777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* and `offset' are incorrect (e.g., `opens___.ttf' which comes with     */
63877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* OpenOffice.org).  We need special code to deal with them correctly.   */
639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_4
642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef struct  TT_CMap4Rec_
644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMapRec  cmap;
646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32   cur_charcode;   /* current charcode */
647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     cur_gindex;     /* current glyph index */
648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     num_ranges;
650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     cur_range;
651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     cur_start;
652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     cur_end;
653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int      cur_delta;
654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*    cur_values;
655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  } TT_CMap4Rec, *TT_CMap4;
657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap4_init( TT_CMap4  cmap,
661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 FT_Byte*  table )
662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p;
664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->cmap.data    = table;
667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p                  = table + 6;
669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->num_ranges   = FT_PEEK_USHORT( p ) >> 1;
670295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL;
671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->cur_gindex   = 0;
672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
673a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Int
678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap4_set_range( TT_CMap4  cmap,
679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_UInt   range_index )
680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  table = cmap->cmap.data;
682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p;
683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   num_ranges = cmap->num_ranges;
684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( range_index < num_ranges )
687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  offset;
689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p             = table + 14 + range_index * 2;
692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cmap->cur_end = FT_PEEK_USHORT( p );
693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p              += 2 + num_ranges * 2;
695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cmap->cur_start = FT_PEEK_USHORT( p );
696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p              += num_ranges * 2;
698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cmap->cur_delta = FT_PEEK_SHORT( p );
699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p     += num_ranges * 2;
701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      offset = FT_PEEK_USHORT( p );
702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
70377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      /* some fonts have an incorrect last segment; */
70477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      /* we have to catch it                        */
70577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      if ( range_index     >= num_ranges - 1 &&
70677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner           cmap->cur_start == 0xFFFFU        &&
70777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner           cmap->cur_end   == 0xFFFFU        )
70877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      {
70977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        TT_Face   face  = (TT_Face)cmap->cmap.cmap.charmap.face;
71077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        FT_Byte*  limit = face->cmap_table + face->cmap_size;
71177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
71277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
71377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        if ( offset && p + offset + 2 > limit )
71477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        {
71577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          cmap->cur_delta = 1;
71677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          offset          = 0;
71777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        }
71877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      }
71977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( offset != 0xFFFFU )
721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cmap->cur_values = offset ? p + offset : NULL;
723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cmap->cur_range  = range_index;
724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return 0;
725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we skip empty segments */
728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      range_index++;
729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return -1;
732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* search the index of the charcode next to cmap->cur_charcode; */
736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* caller should call tt_cmap4_set_range with proper range      */
737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* before calling this function                                 */
738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                              */
739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap4_next( TT_CMap4  cmap )
741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt  charcode;
743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( cmap->cur_charcode >= 0xFFFFUL )
746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Fail;
747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
748295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    charcode = (FT_UInt)cmap->cur_charcode + 1;
749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( charcode < cmap->cur_start )
751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      charcode = cmap->cur_start;
752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ;; )
754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  values = cmap->cur_values;
756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   end    = cmap->cur_end;
757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int    delta  = cmap->cur_delta;
758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( charcode <= end )
761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( values )
763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Byte*  p = values + 2 * ( charcode - cmap->cur_start );
765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          do
768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_UInt  gindex = FT_NEXT_USHORT( p );
770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( gindex != 0 )
773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              gindex = (FT_UInt)( ( gindex + delta ) & 0xFFFFU );
775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( gindex != 0 )
776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                cmap->cur_charcode = charcode;
778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                cmap->cur_gindex   = gindex;
779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                return;
780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          } while ( ++charcode <= end );
783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          do
787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_UInt  gindex = (FT_UInt)( ( charcode + delta ) & 0xFFFFU );
789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( gindex != 0 )
792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              cmap->cur_charcode = charcode;
794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              cmap->cur_gindex   = gindex;
795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              return;
796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          } while ( ++charcode <= end );
798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we need to find another range */
802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tt_cmap4_set_range( cmap, cmap->cur_range + 1 ) < 0 )
803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( charcode < cmap->cur_start )
806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        charcode = cmap->cur_start;
807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Fail:
810295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL;
811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->cur_gindex   = 0;
812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap4_validate( FT_Byte*      table,
817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Validator  valid )
818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p      = table + 2;               /* skip format */
820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   length = TT_NEXT_USHORT( p );
821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte   *ends, *starts, *offsets, *deltas, *glyph_ids;
822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   num_segs;
823a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Error  error = FT_Err_Ok;
824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( length < 16 )
827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* in certain fonts, the `length' field is invalid and goes */
830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* out of bound.  We try to correct this here...            */
831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + length > valid->limit )
832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( valid->level >= FT_VALIDATE_TIGHT )
834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_INVALID_TOO_SHORT;
835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      length = (FT_UInt)( valid->limit - table );
837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p        = table + 6;
840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_segs = TT_NEXT_USHORT( p );   /* read segCountX2 */
841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( valid->level >= FT_VALIDATE_PARANOID )
843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* check that we have an even value here */
845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( num_segs & 1 )
846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_INVALID_DATA;
847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_segs /= 2;
850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( length < 16 + num_segs * 2 * 4 )
852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* check the search parameters - even though we never use them */
855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                             */
856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( valid->level >= FT_VALIDATE_PARANOID )
857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
85877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      /* check the values of `searchRange', `entrySelector', `rangeShift' */
859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  search_range   = TT_NEXT_USHORT( p );
860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  entry_selector = TT_NEXT_USHORT( p );
861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  range_shift    = TT_NEXT_USHORT( p );
862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ( search_range | range_shift ) & 1 )  /* must be even values */
865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_INVALID_DATA;
866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      search_range /= 2;
868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      range_shift  /= 2;
869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* `search range' is the greatest power of 2 that is <= num_segs */
871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( search_range                > num_segs                 ||
873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           search_range * 2            < num_segs                 ||
874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           search_range + range_shift != num_segs                 ||
875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           search_range               != ( 1U << entry_selector ) )
876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_INVALID_DATA;
877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ends      = table   + 14;
880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    starts    = table   + 16 + num_segs * 2;
881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    deltas    = starts  + num_segs * 2;
882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    offsets   = deltas  + num_segs * 2;
883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    glyph_ids = offsets + num_segs * 2;
884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
88577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    /* check last segment; its end count value must be 0xFFFF */
886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( valid->level >= FT_VALIDATE_PARANOID )
887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p = ends + ( num_segs - 1 ) * 2;
889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( TT_PEEK_USHORT( p ) != 0xFFFFU )
890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_INVALID_DATA;
891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
89477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      FT_UInt   start, end, offset, n;
89577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      FT_UInt   last_start = 0, last_end = 0;
89677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      FT_Int    delta;
897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  p_start   = starts;
898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  p_end     = ends;
899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  p_delta   = deltas;
900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  p_offset  = offsets;
901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( n = 0; n < num_segs; n++ )
904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p      = p_offset;
906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        start  = TT_NEXT_USHORT( p_start );
907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        end    = TT_NEXT_USHORT( p_end );
908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        delta  = TT_NEXT_SHORT( p_delta );
909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        offset = TT_NEXT_USHORT( p_offset );
910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( start > end )
912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_DATA;
913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
91477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        /* this test should be performed at default validation level; */
91577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        /* unfortunately, some popular Asian fonts have overlapping   */
91677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        /* ranges in their charmaps                                   */
91777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        /*                                                            */
918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( start <= last_end && n > 0 )
919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( valid->level >= FT_VALIDATE_TIGHT )
921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_INVALID_DATA;
922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* allow overlapping segments, provided their start points */
92577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner            /* and end points, respectively, are in ascending order    */
926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /*                                                         */
927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( last_start > start || last_end > end )
928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              error |= TT_CMAP_FLAG_UNSORTED;
929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              error |= TT_CMAP_FLAG_OVERLAPPING;
931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( offset && offset != 0xFFFFU )
935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
93677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          p += offset;  /* start of glyph ID array */
937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
93877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* check that we point within the glyph IDs table only */
939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( valid->level >= FT_VALIDATE_TIGHT )
940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( p < glyph_ids                                ||
942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 p + ( end - start + 1 ) * 2 > table + length )
943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_INVALID_DATA;
944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
94577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* Some fonts handle the last segment incorrectly.  In */
94677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* theory, 0xFFFF might point to an ordinary glyph --  */
94777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* a cmap 4 is versatile and could be used for any     */
94877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* encoding, not only Unicode.  However, reality shows */
94977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* that far too many fonts are sloppy and incorrectly  */
95077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* set all fields but `start' and `end' for the last   */
95177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* segment if it contains only a single character.     */
95277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /*                                                     */
95377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* We thus omit the test here, delaying it to the      */
95477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* routines which actually access the cmap.            */
95577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          else if ( n != num_segs - 1                       ||
95677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner                    !( start == 0xFFFFU && end == 0xFFFFU ) )
957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( p < glyph_ids                              ||
959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 p + ( end - start + 1 ) * 2 > valid->limit )
960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_INVALID_DATA;
961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* check glyph indices within the segment range */
964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( valid->level >= FT_VALIDATE_TIGHT )
965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_UInt  i, idx;
967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            for ( i = start; i < end; i++ )
970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              idx = FT_NEXT_USHORT( p );
972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( idx != 0 )
973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                idx = (FT_UInt)( idx + delta ) & 0xFFFFU;
975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_INVALID_GLYPH_ID;
978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( offset == 0xFFFFU )
983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
98477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* some fonts (erroneously?) use a range offset of 0xFFFF */
985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* to mean missing glyph in cmap table                    */
986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /*                                                        */
98777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          if ( valid->level >= FT_VALIDATE_PARANOID    ||
98877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner               n != num_segs - 1                       ||
98977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner               !( start == 0xFFFFU && end == 0xFFFFU ) )
990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_INVALID_DATA;
991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        last_start = start;
994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        last_end   = end;
995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_UInt
100377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  tt_cmap4_char_map_linear( TT_CMap     cmap,
100477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner                            FT_UInt32*  pcharcode,
100577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner                            FT_Bool     next )
1006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    num_segs2, start, end, offset;
1008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int     delta;
1009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    i, num_segs;
1010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  charcode = *pcharcode;
1011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    gindex   = 0;
1012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p;
1013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p = cmap->data + 6;
1016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );
1017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_segs = num_segs2 >> 1;
1019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !num_segs )
1021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
1022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( next )
1024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      charcode++;
1025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* linear search */
1027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; charcode <= 0xFFFFU; charcode++ )
1028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  q;
1030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p = cmap->data + 14;               /* ends table   */
1033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      q = cmap->data + 16 + num_segs2;   /* starts table */
1034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( i = 0; i < num_segs; i++ )
1036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        end   = TT_NEXT_USHORT( p );
1038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        start = TT_NEXT_USHORT( q );
1039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( charcode >= start && charcode <= end )
1041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p       = q - 2 + num_segs2;
1043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta   = TT_PEEK_SHORT( p );
1044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p      += num_segs2;
1045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          offset  = TT_PEEK_USHORT( p );
1046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
104777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* some fonts have an incorrect last segment; */
104877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* we have to catch it                        */
104977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          if ( i >= num_segs - 1                  &&
105077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner               start == 0xFFFFU && end == 0xFFFFU )
105177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          {
105277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner            TT_Face   face  = (TT_Face)cmap->cmap.charmap.face;
105377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner            FT_Byte*  limit = face->cmap_table + face->cmap_size;
105477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
105577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
105677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner            if ( offset && p + offset + 2 > limit )
105777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner            {
105877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner              delta  = 1;
105977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner              offset = 0;
106077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner            }
106177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          }
106277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
1063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( offset == 0xFFFFU )
1064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            continue;
1065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( offset )
1067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p += offset + ( charcode - start ) * 2;
1069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            gindex = TT_PEEK_USHORT( p );
1070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( gindex != 0 )
1071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
1072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU;
1075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          break;
1077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !next || gindex )
1081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
1082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( next && gindex )
1085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      *pcharcode = charcode;
1086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
1088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_UInt
109277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  tt_cmap4_char_map_binary( TT_CMap     cmap,
109377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner                            FT_UInt32*  pcharcode,
109477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner                            FT_Bool     next )
1095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   num_segs2, start, end, offset;
1097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int    delta;
1098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   max, min, mid, num_segs;
1099295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt   charcode = (FT_UInt)*pcharcode;
1100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   gindex   = 0;
1101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p;
1102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p = cmap->data + 6;
1105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );
1106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !num_segs2 )
1108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
1109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_segs = num_segs2 >> 1;
1111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* make compiler happy */
1113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    mid = num_segs;
1114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    end = 0xFFFFU;
1115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( next )
1117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      charcode++;
1118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    min = 0;
1120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    max = num_segs;
1121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* binary search */
1123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( min < max )
1124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mid    = ( min + max ) >> 1;
1126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p      = cmap->data + 14 + mid * 2;
1127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      end    = TT_PEEK_USHORT( p );
1128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p     += 2 + num_segs2;
1129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start  = TT_PEEK_USHORT( p );
1130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( charcode < start )
1132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        max = mid;
1133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( charcode > end )
1134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        min = mid + 1;
1135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p     += num_segs2;
1138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        delta  = TT_PEEK_SHORT( p );
1139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p     += num_segs2;
1140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        offset = TT_PEEK_USHORT( p );
1141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
114277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        /* some fonts have an incorrect last segment; */
114377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        /* we have to catch it                        */
114477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        if ( mid >= num_segs - 1                &&
114577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner             start == 0xFFFFU && end == 0xFFFFU )
114677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        {
114777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          TT_Face   face  = (TT_Face)cmap->cmap.charmap.face;
114877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          FT_Byte*  limit = face->cmap_table + face->cmap_size;
114977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
115077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
115177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          if ( offset && p + offset + 2 > limit )
115277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          {
115377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner            delta  = 1;
115477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner            offset = 0;
115577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          }
115677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        }
115777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
1158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* search the first segment containing `charcode' */
1159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( cmap->flags & TT_CMAP_FLAG_OVERLAPPING )
1160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt  i;
1162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* call the current segment `max' */
1165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          max = mid;
1166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( offset == 0xFFFFU )
1168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            mid = max + 1;
1169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* search in segments before the current segment */
1171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( i = max ; i > 0; i-- )
1172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_UInt   prev_end;
1174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Byte*  old_p;
1175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            old_p    = p;
1178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p        = cmap->data + 14 + ( i - 1 ) * 2;
1179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            prev_end = TT_PEEK_USHORT( p );
1180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( charcode > prev_end )
1182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p = old_p;
1184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
1185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            end    = prev_end;
1188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p     += 2 + num_segs2;
1189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            start  = TT_PEEK_USHORT( p );
1190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p     += num_segs2;
1191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta  = TT_PEEK_SHORT( p );
1192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p     += num_segs2;
1193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            offset = TT_PEEK_USHORT( p );
1194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( offset != 0xFFFFU )
1196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              mid = i - 1;
1197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* no luck */
1200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( mid == max + 1 )
1201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( i != max )
1203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p      = cmap->data + 14 + max * 2;
1205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              end    = TT_PEEK_USHORT( p );
1206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p     += 2 + num_segs2;
1207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              start  = TT_PEEK_USHORT( p );
1208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p     += num_segs2;
1209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              delta  = TT_PEEK_SHORT( p );
1210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p     += num_segs2;
1211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              offset = TT_PEEK_USHORT( p );
1212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            mid = max;
1215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* search in segments after the current segment */
1217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            for ( i = max + 1; i < num_segs; i++ )
1218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_UInt  next_end, next_start;
1220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p          = cmap->data + 14 + i * 2;
1223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              next_end   = TT_PEEK_USHORT( p );
1224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p         += 2 + num_segs2;
1225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              next_start = TT_PEEK_USHORT( p );
1226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( charcode < next_start )
1228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                break;
1229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              end    = next_end;
1231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              start  = next_start;
1232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p     += num_segs2;
1233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              delta  = TT_PEEK_SHORT( p );
1234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p     += num_segs2;
1235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              offset = TT_PEEK_USHORT( p );
1236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( offset != 0xFFFFU )
1238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                mid = i;
1239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            i--;
1241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* still no luck */
1243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( mid == max )
1244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              mid = i;
1246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
1248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* end, start, delta, and offset are for the i'th segment */
1252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( mid != i )
1253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p      = cmap->data + 14 + mid * 2;
1255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            end    = TT_PEEK_USHORT( p );
1256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p     += 2 + num_segs2;
1257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            start  = TT_PEEK_USHORT( p );
1258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p     += num_segs2;
1259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta  = TT_PEEK_SHORT( p );
1260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p     += num_segs2;
1261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            offset = TT_PEEK_USHORT( p );
1262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( offset == 0xFFFFU )
1267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
1268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( offset )
1271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p += offset + ( charcode - start ) * 2;
1273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          gindex = TT_PEEK_USHORT( p );
1274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( gindex != 0 )
1275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
1276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU;
1279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
1281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( next )
1285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TT_CMap4  cmap4 = (TT_CMap4)cmap;
1287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* if `charcode' is not in any segment, then `mid' is */
1290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* the segment nearest to `charcode'                  */
1291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /*                                                    */
1292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( charcode > end )
1294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        mid++;
1296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( mid == num_segs )
1297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          return 0;
1298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tt_cmap4_set_range( cmap4, mid ) )
1301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( gindex )
1303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          *pcharcode = charcode;
1304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cmap4->cur_charcode = charcode;
1308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( gindex )
1310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cmap4->cur_gindex = gindex;
1311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cmap4->cur_charcode = charcode;
1314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          tt_cmap4_next( cmap4 );
1315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          gindex = cmap4->cur_gindex;
1316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( gindex )
1319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          *pcharcode = cmap4->cur_charcode;
1320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
1324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
1328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap4_char_index( TT_CMap    cmap,
1329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_UInt32  char_code )
1330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( char_code >= 0x10000UL )
1332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
1333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( cmap->flags & TT_CMAP_FLAG_UNSORTED )
1335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return tt_cmap4_char_map_linear( cmap, &char_code, 0 );
1336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return tt_cmap4_char_map_binary( cmap, &char_code, 0 );
1338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1341295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_UInt32 )
1342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap4_char_next( TT_CMap     cmap,
1343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_UInt32  *pchar_code )
1344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt  gindex;
1346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( *pchar_code >= 0xFFFFU )
1349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
1350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( cmap->flags & TT_CMAP_FLAG_UNSORTED )
1352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      gindex = tt_cmap4_char_map_linear( cmap, pchar_code, 1 );
1353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TT_CMap4  cmap4 = (TT_CMap4)cmap;
1356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* no need to search */
1359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( *pchar_code == cmap4->cur_charcode )
1360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tt_cmap4_next( cmap4 );
1362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gindex = cmap4->cur_gindex;
1363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( gindex )
1364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          *pchar_code = cmap4->cur_charcode;
1365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gindex = tt_cmap4_char_map_binary( cmap, pchar_code, 1 );
1368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
1371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
1375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap4_get_info( TT_CMap       cmap,
1376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     TT_CMapInfo  *cmap_info )
1377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = cmap->data + 4;
1379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1381295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap_info->format   = 4;
1382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
1383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1384a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
1385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1388a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_DEFINE_TT_CMAP(
1389a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    tt_cmap4_class_rec,
1390a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    sizeof ( TT_CMap4Rec ),
1391a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_InitFunc)     tt_cmap4_init,
1392a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_DoneFunc)     NULL,
1393a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_CharIndexFunc)tt_cmap4_char_index,
1394a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_CharNextFunc) tt_cmap4_char_next,
1395a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1396a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
1397a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
1398a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
1399a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
1400a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
1401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    4,
1403a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (TT_CMap_ValidateFunc)tt_cmap4_validate,
1404a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (TT_CMap_Info_GetFunc)tt_cmap4_get_info )
1405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* TT_CONFIG_CMAP_FORMAT_4 */
1407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                          FORMAT 6                             *****/
1413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* TABLE OVERVIEW                                                        */
1420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* --------------                                                        */
1421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME        OFFSET          TYPE             DESCRIPTION            */
1423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   format       0              USHORT           must be 4              */
1425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   length       2              USHORT           table length in bytes  */
1426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   language     4              USHORT           Mac language code      */
1427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   first        6              USHORT           first segment code     */
1429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   count        8              USHORT           segment size in chars  */
143077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /*   glyphIds     10             USHORT[count]    glyph IDs              */
1431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* A very simplified segment mapping.                                    */
1433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_6
1436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
1438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap6_validate( FT_Byte*      table,
1439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Validator  valid )
1440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p;
1442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   length, count;
1443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + 10 > valid->limit )
1446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
1447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p      = table + 2;
1449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    length = TT_NEXT_USHORT( p );
1450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p      = table + 8;             /* skip language and start index */
1452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    count  = TT_NEXT_USHORT( p );
1453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + length > valid->limit || length < 10 + count * 2 )
1455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
1456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* check glyph indices */
1458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( valid->level >= FT_VALIDATE_TIGHT )
1459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  gindex;
1461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; count > 0; count-- )
1464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gindex = TT_NEXT_USHORT( p );
1466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
1467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_GLYPH_ID;
1468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1471a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
1472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
1476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap6_char_index( TT_CMap    cmap,
1477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_UInt32  char_code )
1478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  table  = cmap->data;
1480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   result = 0;
1481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p      = table + 6;
1482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   start  = TT_NEXT_USHORT( p );
1483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   count  = TT_NEXT_USHORT( p );
1484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   idx    = (FT_UInt)( char_code - start );
1485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( idx < count )
1488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p += 2 * idx;
1490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = TT_PEEK_USHORT( p );
1491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return result;
1493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1496295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_UInt32 )
1497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap6_char_next( TT_CMap     cmap,
1498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_UInt32  *pchar_code )
1499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   table     = cmap->data;
1501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  result    = 0;
1502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  char_code = *pchar_code + 1;
1503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    gindex    = 0;
1504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p         = table + 6;
1506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    start     = TT_NEXT_USHORT( p );
1507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    count     = TT_NEXT_USHORT( p );
1508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    idx;
1509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( char_code >= 0x10000UL )
1512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
1513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( char_code < start )
1515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      char_code = start;
1516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    idx = (FT_UInt)( char_code - start );
1518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p  += 2 * idx;
1519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; idx < count; idx++ )
1521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      gindex = TT_NEXT_USHORT( p );
1523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( gindex != 0 )
1524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        result = char_code;
1526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
1527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      char_code++;
1529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
1532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *pchar_code = result;
1533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
1534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
1538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap6_get_info( TT_CMap       cmap,
1539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     TT_CMapInfo  *cmap_info )
1540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = cmap->data + 4;
1542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1544295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap_info->format   = 6;
1545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
1546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1547a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
1548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1551a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_DEFINE_TT_CMAP(
1552a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    tt_cmap6_class_rec,
1553a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    sizeof ( TT_CMapRec ),
1554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1555a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_InitFunc)     tt_cmap_init,
1556a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_DoneFunc)     NULL,
1557a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_CharIndexFunc)tt_cmap6_char_index,
1558a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_CharNextFunc) tt_cmap6_char_next,
1559a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1560a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
1561a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
1562a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
1563a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
1564a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
1565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    6,
1567a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (TT_CMap_ValidateFunc)tt_cmap6_validate,
1568a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (TT_CMap_Info_GetFunc)tt_cmap6_get_info )
1569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* TT_CONFIG_CMAP_FORMAT_6 */
1571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                          FORMAT 8                             *****/
1577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
157877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /***** It is hard to completely understand what the OpenType spec    *****/
1579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** says about this format, but here is my conclusion.            *****/
1580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** The purpose of this format is to easily map UTF-16 text to    *****/
1582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** glyph indices.  Basically, the `char_code' must be in one of  *****/
1583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** the following formats:                                        *****/
1584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   - A 16-bit value that isn't part of the Unicode Surrogates  *****/
1586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****     Area (i.e. U+D800-U+DFFF).                                *****/
1587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   - A 32-bit value, made of two surrogate values, i.e.. if    *****/
1589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****     `char_code = (char_hi << 16) | char_lo', then both        *****/
1590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****     `char_hi' and `char_lo' must be in the Surrogates Area.   *****/
1591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****      Area.                                                    *****/
1592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
159377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /***** The `is32' table embedded in the charmap indicates whether a  *****/
1594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** given 16-bit value is in the surrogates area or not.          *****/
1595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** So, for any given `char_code', we can assert the following:   *****/
1597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   If `char_hi == 0' then we must have `is32[char_lo] == 0'.   *****/
1599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   If `char_hi != 0' then we must have both                    *****/
1601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   `is32[char_hi] != 0' and `is32[char_lo] != 0'.              *****/
1602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* TABLE OVERVIEW                                                        */
1609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* --------------                                                        */
1610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME        OFFSET         TYPE        DESCRIPTION                  */
1612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   format      0              USHORT      must be 8                    */
1614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   reserved    2              USHORT      reserved                     */
1615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   length      4              ULONG       length in bytes              */
1616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   language    8              ULONG       Mac language code            */
1617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   is32        12             BYTE[8192]  32-bitness bitmap            */
1618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   count       8204           ULONG       number of groups             */
1619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
162077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* This header is followed by `count' groups of the following format:    */
1621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   start       0              ULONG       first charcode               */
1623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   end         4              ULONG       last charcode                */
162477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /*   startId     8              ULONG       start glyph ID for the group */
1625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_8
1628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
1630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap8_validate( FT_Byte*      table,
1631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Validator  valid )
1632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p = table + 4;
1634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   is32;
1635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  length;
1636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  num_groups;
1637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + 16 + 8192 > valid->limit )
1640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
1641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    length = TT_NEXT_ULONG( p );
1643295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( length > (FT_UInt32)( valid->limit - table ) || length < 8192 + 16 )
1644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
1645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    is32       = table + 12;
1647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p          = is32  + 8192;          /* skip `is32' array */
1648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_groups = TT_NEXT_ULONG( p );
1649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( p + num_groups * 12 > valid->limit )
1651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
1652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* check groups, they must be in increasing order */
1654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  n, start, end, start_id, count, last = 0;
1656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( n = 0; n < num_groups; n++ )
1659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt   hi, lo;
1661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        start    = TT_NEXT_ULONG( p );
1664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        end      = TT_NEXT_ULONG( p );
1665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        start_id = TT_NEXT_ULONG( p );
1666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( start > end )
1668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_DATA;
1669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( n > 0 && start <= last )
1671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_DATA;
1672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( valid->level >= FT_VALIDATE_TIGHT )
1674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
1676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_INVALID_GLYPH_ID;
1677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          count = (FT_UInt32)( end - start + 1 );
1679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( start & ~0xFFFFU )
1681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* start_hi != 0; check that is32[i] is 1 for each i in */
1683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* the `hi' and `lo' of the range [start..end]          */
1684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            for ( ; count > 0; count--, start++ )
1685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              hi = (FT_UInt)( start >> 16 );
1687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              lo = (FT_UInt)( start & 0xFFFFU );
1688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 )
1690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                FT_INVALID_DATA;
1691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 )
1693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                FT_INVALID_DATA;
1694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* start_hi == 0; check that is32[i] is 0 for each i in */
1699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* the range [start..end]                               */
1700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* end_hi cannot be != 0! */
1702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( end & ~0xFFFFU )
1703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_INVALID_DATA;
1704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            for ( ; count > 0; count--, start++ )
1706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              lo = (FT_UInt)( start & 0xFFFFU );
1708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 )
1710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                FT_INVALID_DATA;
1711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        last = end;
1716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1719a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
1720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
1724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap8_char_index( TT_CMap    cmap,
1725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_UInt32  char_code )
1726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   table      = cmap->data;
1728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    result     = 0;
1729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p          = table + 8204;
1730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  num_groups = TT_NEXT_ULONG( p );
1731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  start, end, start_id;
1732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; num_groups > 0; num_groups-- )
1735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start    = TT_NEXT_ULONG( p );
1737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      end      = TT_NEXT_ULONG( p );
1738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start_id = TT_NEXT_ULONG( p );
1739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code < start )
1741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
1742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code <= end )
1744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        result = (FT_UInt)( start_id + char_code - start );
1746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
1747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return result;
1750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1753295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_UInt32 )
1754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap8_char_next( TT_CMap     cmap,
1755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_UInt32  *pchar_code )
1756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  result     = 0;
1758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  char_code  = *pchar_code + 1;
1759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    gindex     = 0;
1760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   table      = cmap->data;
1761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p          = table + 8204;
1762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  num_groups = TT_NEXT_ULONG( p );
1763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  start, end, start_id;
1764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p = table + 8208;
1767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; num_groups > 0; num_groups-- )
1769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start    = TT_NEXT_ULONG( p );
1771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      end      = TT_NEXT_ULONG( p );
1772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start_id = TT_NEXT_ULONG( p );
1773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code < start )
1775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        char_code = start;
1776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code <= end )
1778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gindex = (FT_UInt)( char_code - start + start_id );
1780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( gindex != 0 )
1781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          result = char_code;
1783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Exit;
1784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
1789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *pchar_code = result;
1790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
1791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
1795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap8_get_info( TT_CMap       cmap,
1796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     TT_CMapInfo  *cmap_info )
1797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = cmap->data + 8;
1799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1801295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap_info->format   = 8;
1802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
1803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1804a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
1805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1808a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_DEFINE_TT_CMAP(
1809a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    tt_cmap8_class_rec,
1810a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    sizeof ( TT_CMapRec ),
1811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1812a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_InitFunc)     tt_cmap_init,
1813a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_DoneFunc)     NULL,
1814a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_CharIndexFunc)tt_cmap8_char_index,
1815a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_CharNextFunc) tt_cmap8_char_next,
1816a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1817a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
1818a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
1819a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
1820a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
1821a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
1822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    8,
1824a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (TT_CMap_ValidateFunc)tt_cmap8_validate,
1825a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (TT_CMap_Info_GetFunc)tt_cmap8_get_info )
1826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* TT_CONFIG_CMAP_FORMAT_8 */
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  /*****                          FORMAT 10                            *****/
1834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* TABLE OVERVIEW                                                        */
1841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* --------------                                                        */
1842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME      OFFSET  TYPE               DESCRIPTION                    */
1844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   format     0      USHORT             must be 10                     */
1846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   reserved   2      USHORT             reserved                       */
1847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   length     4      ULONG              length in bytes                */
1848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   language   8      ULONG              Mac language code              */
1849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   start     12      ULONG              first char in range            */
1851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   count     16      ULONG              number of chars in range       */
1852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   glyphIds  20      USHORT[count]      glyph indices covered          */
1853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_10
1856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
1858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap10_validate( FT_Byte*      table,
1859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Validator  valid )
1860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = table + 4;
1862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  length, count;
1863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + 20 > valid->limit )
1866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
1867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    length = TT_NEXT_ULONG( p );
1869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p      = table + 16;
1870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    count  = TT_NEXT_ULONG( p );
1871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1872295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( length > (FT_ULong)( valid->limit - table ) ||
1873295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner         length < 20 + count * 2                     )
1874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
1875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* check glyph indices */
1877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( valid->level >= FT_VALIDATE_TIGHT )
1878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  gindex;
1880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; count > 0; count-- )
1883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gindex = TT_NEXT_USHORT( p );
1885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
1886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_GLYPH_ID;
1887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1890a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
1891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
1895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap10_char_index( TT_CMap    cmap,
1896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        FT_UInt32  char_code )
1897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   table  = cmap->data;
1899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    result = 0;
1900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p      = table + 12;
1901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  start  = TT_NEXT_ULONG( p );
1902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  count  = TT_NEXT_ULONG( p );
1903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  idx    = (FT_ULong)( char_code - start );
1904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( idx < count )
1907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p     += 2 * idx;
1909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = TT_PEEK_USHORT( p );
1910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return result;
1912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1915295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_UInt32 )
1916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap10_char_next( TT_CMap     cmap,
1917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_UInt32  *pchar_code )
1918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   table     = cmap->data;
1920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  char_code = *pchar_code + 1;
1921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    gindex    = 0;
1922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p         = table + 12;
1923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  start     = TT_NEXT_ULONG( p );
1924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  count     = TT_NEXT_ULONG( p );
1925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  idx;
1926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( char_code < start )
1929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      char_code = start;
1930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    idx = (FT_UInt32)( char_code - start );
1932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p  += 2 * idx;
1933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; idx < count; idx++ )
1935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      gindex = TT_NEXT_USHORT( p );
1937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( gindex != 0 )
1938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
1939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      char_code++;
1940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *pchar_code = char_code;
1943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
1944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
1948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap10_get_info( TT_CMap       cmap,
1949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      TT_CMapInfo  *cmap_info )
1950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = cmap->data + 8;
1952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1954295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap_info->format   = 10;
1955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
1956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1957a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
1958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1961a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_DEFINE_TT_CMAP(
1962a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    tt_cmap10_class_rec,
1963a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    sizeof ( TT_CMapRec ),
1964a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1965a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_InitFunc)     tt_cmap_init,
1966a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_DoneFunc)     NULL,
1967a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_CharIndexFunc)tt_cmap10_char_index,
1968a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_CharNextFunc) tt_cmap10_char_next,
1969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1970a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
1971a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
1972a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
1973a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
1974a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
1975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    10,
1977a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (TT_CMap_ValidateFunc)tt_cmap10_validate,
1978a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (TT_CMap_Info_GetFunc)tt_cmap10_get_info )
1979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* TT_CONFIG_CMAP_FORMAT_10 */
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  /*****                                                               *****/
1986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                          FORMAT 12                            *****/
1987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* TABLE OVERVIEW                                                        */
1994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* --------------                                                        */
1995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME        OFFSET     TYPE       DESCRIPTION                       */
1997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   format      0          USHORT     must be 12                        */
1999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   reserved    2          USHORT     reserved                          */
2000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   length      4          ULONG      length in bytes                   */
2001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   language    8          ULONG      Mac language code                 */
2002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   count       12         ULONG      number of groups                  */
2003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*               16                                                      */
2004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* This header is followed by `count' groups of the following format:    */
2006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   start       0          ULONG      first charcode                    */
2008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   end         4          ULONG      last charcode                     */
200977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /*   startId     8          ULONG      start glyph ID for the group      */
2010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_12
2013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef struct  TT_CMap12Rec_
2015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMapRec  cmap;
2017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Bool     valid;
2018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    cur_charcode;
2019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     cur_gindex;
2020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    cur_group;
2021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    num_groups;
2022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  } TT_CMap12Rec, *TT_CMap12;
2024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
2027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap12_init( TT_CMap12  cmap,
2028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_Byte*   table )
2029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->cmap.data  = table;
2031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    table           += 12;
2033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->num_groups = FT_PEEK_ULONG( table );
2034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->valid      = 0;
2036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2037a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
2038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
2042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap12_validate( FT_Byte*      table,
2043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Validator  valid )
2044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p;
2046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong   length;
2047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong   num_groups;
2048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + 16 > valid->limit )
2051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
2052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p      = table + 4;
2054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    length = TT_NEXT_ULONG( p );
2055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p          = table + 12;
2057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_groups = TT_NEXT_ULONG( p );
2058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2059295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( length > (FT_ULong)( valid->limit - table ) ||
2060295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner         length < 16 + 12 * num_groups               )
2061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
2062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* check groups, they must be in increasing order */
2064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ULong  n, start, end, start_id, last = 0;
2066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( n = 0; n < num_groups; n++ )
2069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        start    = TT_NEXT_ULONG( p );
2071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        end      = TT_NEXT_ULONG( p );
2072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        start_id = TT_NEXT_ULONG( p );
2073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( start > end )
2075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_DATA;
2076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( n > 0 && start <= last )
2078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_DATA;
2079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( valid->level >= FT_VALIDATE_TIGHT )
2081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
2083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_INVALID_GLYPH_ID;
2084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        last = end;
2087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2090a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
2091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* search the index of the charcode next to cmap->cur_charcode */
2095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* cmap->cur_group should be set up properly by caller         */
2096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                             */
2097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
2098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap12_next( TT_CMap12  cmap )
2099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p;
2101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  start, end, start_id, char_code;
2102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  n;
2103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   gindex;
2104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
2107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Fail;
2108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    char_code = cmap->cur_charcode + 1;
2110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    n = cmap->cur_group;
2112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
2114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p        = cmap->cmap.data + 16 + 12 * n;
2116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start    = TT_NEXT_ULONG( p );
2117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      end      = TT_NEXT_ULONG( p );
2118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start_id = TT_PEEK_ULONG( p );
2119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code < start )
2121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        char_code = start;
2122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; char_code <= end; char_code++ )
2124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gindex = (FT_UInt)( start_id + char_code - start );
2126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( gindex )
2128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cmap->cur_charcode = char_code;;
2130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cmap->cur_gindex   = gindex;
2131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cmap->cur_group    = n;
2132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          return;
2134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Fail:
2139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->valid = 0;
2140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_UInt
2144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap12_char_map_binary( TT_CMap     cmap,
2145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             FT_UInt32*  pchar_code,
2146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             FT_Bool     next )
2147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    gindex     = 0;
2149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p          = cmap->data + 12;
2150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  num_groups = TT_PEEK_ULONG( p );
2151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  char_code  = *pchar_code;
2152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  start, end, start_id;
2153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  max, min, mid;
2154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !num_groups )
2157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
2158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* make compiler happy */
2160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    mid = num_groups;
2161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    end = 0xFFFFFFFFUL;
2162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( next )
2164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      char_code++;
2165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    min = 0;
2167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    max = num_groups;
2168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* binary search */
2170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( min < max )
2171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mid = ( min + max ) >> 1;
2173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p   = cmap->data + 16 + 12 * mid;
2174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start = TT_NEXT_ULONG( p );
2176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      end   = TT_NEXT_ULONG( p );
2177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code < start )
2179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        max = mid;
2180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( char_code > end )
2181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        min = mid + 1;
2182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
2183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        start_id = TT_PEEK_ULONG( p );
2185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gindex = (FT_UInt)( start_id + char_code - start );
2186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
2188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( next )
2192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TT_CMap12  cmap12 = (TT_CMap12)cmap;
2194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* if `char_code' is not in any group, then `mid' is */
2197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* the group nearest to `char_code'                  */
2198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /*                                                   */
2199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code > end )
2201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        mid++;
2203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( mid == num_groups )
2204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          return 0;
2205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cmap12->valid        = 1;
2208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cmap12->cur_charcode = char_code;
2209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cmap12->cur_group    = mid;
2210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !gindex )
2212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tt_cmap12_next( cmap12 );
2214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( cmap12->valid )
2216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          gindex = cmap12->cur_gindex;
2217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
2219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cmap12->cur_gindex = gindex;
2220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( gindex )
2222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        *pchar_code = cmap12->cur_charcode;
2223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
2226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
2230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap12_char_index( TT_CMap    cmap,
2231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        FT_UInt32  char_code )
2232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return tt_cmap12_char_map_binary( cmap, &char_code, 0 );
2234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2237295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_UInt32 )
2238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap12_char_next( TT_CMap     cmap,
2239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_UInt32  *pchar_code )
2240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMap12  cmap12 = (TT_CMap12)cmap;
2242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong   gindex;
2243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( cmap12->cur_charcode >= 0xFFFFFFFFUL )
2246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
2247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* no need to search */
2249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( cmap12->valid && cmap12->cur_charcode == *pchar_code )
2250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      tt_cmap12_next( cmap12 );
2252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( cmap12->valid )
2253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gindex = cmap12->cur_gindex;
2255295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2256295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        /* XXX: check cur_charcode overflow is expected */
2257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( gindex )
2258295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          *pchar_code = (FT_UInt32)cmap12->cur_charcode;
2259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
2261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gindex = 0;
2262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
2264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 );
2265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2266295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* XXX: check gindex overflow is expected */
2267295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    return (FT_UInt32)gindex;
2268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
2272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap12_get_info( TT_CMap       cmap,
2273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      TT_CMapInfo  *cmap_info )
2274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = cmap->data + 8;
2276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2278295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap_info->format   = 12;
2279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
2280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2281a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
2282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2285a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_DEFINE_TT_CMAP(
2286a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    tt_cmap12_class_rec,
2287a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    sizeof ( TT_CMap12Rec ),
2288a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
2289a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_InitFunc)     tt_cmap12_init,
2290a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_DoneFunc)     NULL,
2291a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_CharIndexFunc)tt_cmap12_char_index,
2292a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_CharNextFunc) tt_cmap12_char_next,
2293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2294a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
2295a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
2296a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
2297a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
2298a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
2299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    12,
2301a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (TT_CMap_ValidateFunc)tt_cmap12_validate,
2302a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (TT_CMap_Info_GetFunc)tt_cmap12_get_info )
2303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* TT_CONFIG_CMAP_FORMAT_12 */
2305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
2310295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*****                          FORMAT 13                            *****/
2311295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*****                                                               *****/
2312295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*************************************************************************/
2313295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*************************************************************************/
2314295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2315295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*************************************************************************/
2316295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
2317295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* TABLE OVERVIEW                                                        */
2318295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* --------------                                                        */
2319295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
2320295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*   NAME        OFFSET     TYPE       DESCRIPTION                       */
2321295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
2322295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*   format      0          USHORT     must be 13                        */
2323295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*   reserved    2          USHORT     reserved                          */
2324295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*   length      4          ULONG      length in bytes                   */
2325295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*   language    8          ULONG      Mac language code                 */
2326295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*   count       12         ULONG      number of groups                  */
2327295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*               16                                                      */
2328295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
2329295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* This header is followed by `count' groups of the following format:    */
2330295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
2331295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*   start       0          ULONG      first charcode                    */
2332295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*   end         4          ULONG      last charcode                     */
2333295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*   glyphId     8          ULONG      glyph ID for the whole group      */
2334295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
2335295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2336295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#ifdef TT_CONFIG_CMAP_FORMAT_13
2337295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2338295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  typedef struct  TT_CMap13Rec_
2339295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
2340295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    TT_CMapRec  cmap;
2341295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_Bool     valid;
2342295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_ULong    cur_charcode;
2343295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt     cur_gindex;
2344295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_ULong    cur_group;
2345295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_ULong    num_groups;
2346295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2347295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  } TT_CMap13Rec, *TT_CMap13;
2348295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2349295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2350295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_Error )
2351295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  tt_cmap13_init( TT_CMap13  cmap,
2352295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                  FT_Byte*   table )
2353295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
2354295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap->cmap.data  = table;
2355295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2356295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    table           += 12;
2357295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap->num_groups = FT_PEEK_ULONG( table );
2358295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2359295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap->valid      = 0;
2360295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2361a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
2362295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  }
2363295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2364295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2365295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_Error )
2366295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  tt_cmap13_validate( FT_Byte*      table,
2367295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                      FT_Validator  valid )
2368295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
2369a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Byte*  p;
2370a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_ULong  length;
2371a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_ULong  num_groups;
2372295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2373295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2374295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( table + 16 > valid->limit )
2375295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_INVALID_TOO_SHORT;
2376295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2377295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    p      = table + 4;
2378295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    length = TT_NEXT_ULONG( p );
2379295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2380295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    p          = table + 12;
2381295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    num_groups = TT_NEXT_ULONG( p );
2382295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2383295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( length > (FT_ULong)( valid->limit - table ) ||
2384295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner         length < 16 + 12 * num_groups               )
2385295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_INVALID_TOO_SHORT;
2386295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2387295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* check groups, they must be in increasing order */
2388295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    {
2389295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_ULong  n, start, end, glyph_id, last = 0;
2390295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2391295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2392295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      for ( n = 0; n < num_groups; n++ )
2393295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      {
2394295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        start    = TT_NEXT_ULONG( p );
2395295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        end      = TT_NEXT_ULONG( p );
2396295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        glyph_id = TT_NEXT_ULONG( p );
2397295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2398295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        if ( start > end )
2399295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          FT_INVALID_DATA;
2400295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2401295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        if ( n > 0 && start <= last )
2402295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          FT_INVALID_DATA;
2403295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2404295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        if ( valid->level >= FT_VALIDATE_TIGHT )
2405295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        {
2406295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          if ( glyph_id >= TT_VALID_GLYPH_COUNT( valid ) )
2407295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            FT_INVALID_GLYPH_ID;
2408295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        }
2409295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2410295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        last = end;
2411295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      }
2412295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    }
2413295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2414a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
2415295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  }
2416295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2417295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2418295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* search the index of the charcode next to cmap->cur_charcode */
2419295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* cmap->cur_group should be set up properly by caller         */
2420295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                             */
2421295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  static void
2422295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  tt_cmap13_next( TT_CMap13  cmap )
2423295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
2424295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_Byte*  p;
2425295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_ULong  start, end, glyph_id, char_code;
2426295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_ULong  n;
2427295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt   gindex;
2428295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2429295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2430295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
2431295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      goto Fail;
2432295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2433295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    char_code = cmap->cur_charcode + 1;
2434295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2435295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    n = cmap->cur_group;
2436295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2437295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
2438295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    {
2439295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      p        = cmap->cmap.data + 16 + 12 * n;
2440295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      start    = TT_NEXT_ULONG( p );
2441295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      end      = TT_NEXT_ULONG( p );
2442295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      glyph_id = TT_PEEK_ULONG( p );
2443295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2444295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( char_code < start )
2445295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        char_code = start;
2446295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2447295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( char_code <= end )
2448295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      {
2449295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        gindex = (FT_UInt)glyph_id;
2450295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2451295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        if ( gindex )
2452295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        {
2453295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          cmap->cur_charcode = char_code;;
2454295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          cmap->cur_gindex   = gindex;
2455295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          cmap->cur_group    = n;
2456295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2457295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          return;
2458295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        }
2459295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      }
2460295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    }
2461295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2462295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  Fail:
2463295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap->valid = 0;
2464295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  }
2465295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2466295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2467295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  static FT_UInt
2468295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  tt_cmap13_char_map_binary( TT_CMap     cmap,
2469295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                             FT_UInt32*  pchar_code,
2470295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                             FT_Bool     next )
2471295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
2472295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt    gindex     = 0;
2473295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_Byte*   p          = cmap->data + 12;
2474295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt32  num_groups = TT_PEEK_ULONG( p );
2475295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt32  char_code  = *pchar_code;
2476295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt32  start, end;
2477295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt32  max, min, mid;
2478295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2479295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2480295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( !num_groups )
2481295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      return 0;
2482295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2483295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* make compiler happy */
2484295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    mid = num_groups;
2485295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    end = 0xFFFFFFFFUL;
2486295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2487295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( next )
2488295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      char_code++;
2489295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2490295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    min = 0;
2491295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    max = num_groups;
2492295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2493295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* binary search */
2494295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    while ( min < max )
2495295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    {
2496295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      mid = ( min + max ) >> 1;
2497295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      p   = cmap->data + 16 + 12 * mid;
2498295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2499295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      start = TT_NEXT_ULONG( p );
2500295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      end   = TT_NEXT_ULONG( p );
2501295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2502295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( char_code < start )
2503295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        max = mid;
2504295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      else if ( char_code > end )
2505295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        min = mid + 1;
2506295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      else
2507295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      {
2508295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        gindex = (FT_UInt)TT_PEEK_ULONG( p );
2509295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2510295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        break;
2511295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      }
2512295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    }
2513295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2514295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( next )
2515295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    {
2516295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      TT_CMap13  cmap13 = (TT_CMap13)cmap;
2517295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2518295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2519295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      /* if `char_code' is not in any group, then `mid' is */
2520295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      /* the group nearest to `char_code'                  */
2521295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2522295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( char_code > end )
2523295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      {
2524295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        mid++;
2525295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        if ( mid == num_groups )
2526295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          return 0;
2527295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      }
2528295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2529295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      cmap13->valid        = 1;
2530295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      cmap13->cur_charcode = char_code;
2531295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      cmap13->cur_group    = mid;
2532295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2533295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( !gindex )
2534295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      {
2535295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        tt_cmap13_next( cmap13 );
2536295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2537295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        if ( cmap13->valid )
2538295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          gindex = cmap13->cur_gindex;
2539295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      }
2540295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      else
2541295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        cmap13->cur_gindex = gindex;
2542295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2543295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( gindex )
2544295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        *pchar_code = cmap13->cur_charcode;
2545295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    }
2546295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2547295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    return gindex;
2548295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  }
2549295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2550295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2551295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_UInt )
2552295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  tt_cmap13_char_index( TT_CMap    cmap,
2553295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                        FT_UInt32  char_code )
2554295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
2555295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    return tt_cmap13_char_map_binary( cmap, &char_code, 0 );
2556295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  }
2557295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2558295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2559295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_UInt32 )
2560295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  tt_cmap13_char_next( TT_CMap     cmap,
2561295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                       FT_UInt32  *pchar_code )
2562295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
2563295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    TT_CMap13  cmap13 = (TT_CMap13)cmap;
2564295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt    gindex;
2565295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2566295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2567295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( cmap13->cur_charcode >= 0xFFFFFFFFUL )
2568295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      return 0;
2569295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2570295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* no need to search */
2571295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( cmap13->valid && cmap13->cur_charcode == *pchar_code )
2572295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    {
2573295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      tt_cmap13_next( cmap13 );
2574295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( cmap13->valid )
2575295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      {
2576295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        gindex = cmap13->cur_gindex;
2577295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        if ( gindex )
2578295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          *pchar_code = cmap13->cur_charcode;
2579295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      }
2580295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      else
2581295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        gindex = 0;
2582295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    }
2583295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    else
2584295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      gindex = tt_cmap13_char_map_binary( cmap, pchar_code, 1 );
2585295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2586295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    return gindex;
2587295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  }
2588295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2589295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2590295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_Error )
2591295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  tt_cmap13_get_info( TT_CMap       cmap,
2592295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                      TT_CMapInfo  *cmap_info )
2593295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
2594295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_Byte*  p = cmap->data + 8;
2595295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2596295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2597295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap_info->format   = 13;
2598295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
2599295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2600a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
2601295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  }
2602295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2603295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2604a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_DEFINE_TT_CMAP(
2605a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    tt_cmap13_class_rec,
2606a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    sizeof ( TT_CMap13Rec ),
2607295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2608a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_InitFunc)     tt_cmap13_init,
2609a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_DoneFunc)     NULL,
2610a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_CharIndexFunc)tt_cmap13_char_index,
2611a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_CharNextFunc) tt_cmap13_char_next,
2612a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
2613a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
2614a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
2615a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
2616a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
2617a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    NULL,
2618295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2619295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    13,
2620a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (TT_CMap_ValidateFunc)tt_cmap13_validate,
2621a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (TT_CMap_Info_GetFunc)tt_cmap13_get_info )
2622295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2623295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#endif /* TT_CONFIG_CMAP_FORMAT_13 */
2624295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2625295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2626295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*************************************************************************/
2627295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*************************************************************************/
2628295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*****                                                               *****/
2629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                           FORMAT 14                           *****/
2630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
2631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* TABLE OVERVIEW                                                        */
2637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* --------------                                                        */
2638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME         OFFSET  TYPE    DESCRIPTION                            */
2640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   format         0     USHORT  must be 14                             */
2642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   length         2     ULONG   table length in bytes                  */
2643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   numSelector    6     ULONG   number of variation sel. records       */
2644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Followed by numSelector records, each of which looks like             */
2646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   varSelector    0     UINT24  Unicode codepoint of sel.              */
2648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   defaultOff     3     ULONG   offset to a default UVS table          */
2649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                describing any variants to be found in */
2650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                the normal Unicode subtable.           */
2651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   nonDefOff      7     ULONG   offset to a non-default UVS table      */
2652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                describing any variants not in the     */
2653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                standard cmap, with GIDs here          */
2654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* (either offset may be 0 NULL)                                         */
2655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Selectors are sorted by code point.                                   */
2657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* A default Unicode Variation Selector (UVS) subtable is just a list of */
2659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* ranges of code points which are to be found in the standard cmap.  No */
2660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* glyph IDs (GIDs) here.                                                */
2661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   numRanges      0     ULONG   number of ranges following             */
2663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* A range looks like                                                    */
2665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   uniStart       0     UINT24  code point of the first character in   */
2667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                this range                             */
2668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   additionalCnt  3     UBYTE   count of additional characters in this */
2669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                range (zero means a range of a single  */
2670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                character)                             */
2671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Ranges are sorted by `uniStart'.                                      */
2673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* A non-default Unicode Variation Selector (UVS) subtable is a list of  */
2675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* mappings from codepoint to GID.                                       */
2676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   numMappings    0     ULONG   number of mappings                     */
2678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* A range looks like                                                    */
2680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   uniStart       0     UINT24  code point of the first character in   */
2682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                this range                             */
2683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   GID            3     USHORT  and its GID                            */
2684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Ranges are sorted by `uniStart'.                                      */
2686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_14
2688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef struct  TT_CMap14Rec_
2690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMapRec  cmap;
2692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    num_selectors;
2693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* This array is used to store the results of various
2695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * cmap 14 query functions.  The data is overwritten
2696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * on each call to these functions.
2697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
2698295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt32   max_results;
2699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32*  results;
2700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory   memory;
2701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  } TT_CMap14Rec, *TT_CMap14;
2703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( void )
2706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_done( TT_CMap14  cmap )
2707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory  memory = cmap->memory;
2709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->max_results = 0;
2712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( memory != NULL && cmap->results != NULL )
2713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FREE( cmap->results );
2714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
2718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_ensure( TT_CMap14  cmap,
2719295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                    FT_UInt32  num_results,
2720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    FT_Memory  memory )
2721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2722a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_UInt32  old_max = cmap->max_results;
2723a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Error   error   = FT_Err_Ok;
2724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( num_results > cmap->max_results )
2727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       cmap->memory = memory;
2729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       if ( FT_QRENEW_ARRAY( cmap->results, old_max, num_results ) )
2731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         return error;
2732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       cmap->max_results = num_results;
2734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
2737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
2741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_init( TT_CMap14  cmap,
2742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_Byte*   table )
2743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->cmap.data = table;
2745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    table               += 6;
2747a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cmap->num_selectors  = FT_PEEK_ULONG( table );
2748a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cmap->max_results    = 0;
2749a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cmap->results        = NULL;
2750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2751a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
2752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
2756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_validate( FT_Byte*      table,
2757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Validator  valid )
2758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p             = table + 2;
2760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  length        = TT_NEXT_ULONG( p );
2761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  num_selectors = TT_NEXT_ULONG( p );
2762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2764295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( length > (FT_ULong)( valid->limit - table ) ||
2765295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner         length < 10 + 11 * num_selectors            )
2766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
2767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* check selectors, they must be in increasing order */
2769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we start lastVarSel at 1 because a variant selector value of 0
2771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       * isn't valid.
2772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       */
2773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ULong  n, lastVarSel = 1;
2774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( n = 0; n < num_selectors; n++ )
2777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_ULong  varSel    = TT_NEXT_UINT24( p );
2779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_ULong  defOff    = TT_NEXT_ULONG( p );
2780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_ULong  nondefOff = TT_NEXT_ULONG( p );
2781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( defOff >= length || nondefOff >= length )
2784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_TOO_SHORT;
2785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( varSel < lastVarSel )
2787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_DATA;
2788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        lastVarSel = varSel + 1;
2790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* check the default table (these glyphs should be reached     */
2792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* through the normal Unicode cmap, no GIDs, just check order) */
2793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( defOff != 0 )
2794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Byte*  defp      = table + defOff;
2796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_ULong  numRanges = TT_NEXT_ULONG( defp );
2797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_ULong  i;
2798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_ULong  lastBase  = 0;
2799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( defp + numRanges * 4 > valid->limit )
2802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_INVALID_TOO_SHORT;
2803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( i = 0; i < numRanges; ++i )
2805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_ULong  base = TT_NEXT_UINT24( defp );
2807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_ULong  cnt  = FT_NEXT_BYTE( defp );
2808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( base + cnt >= 0x110000UL )              /* end of Unicode */
2811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_INVALID_DATA;
2812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( base < lastBase )
2814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_INVALID_DATA;
2815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            lastBase = base + cnt + 1U;
2817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* and the non-default table (these glyphs are specified here) */
2821aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        if ( nondefOff != 0 )
2822aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        {
2823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Byte*  ndp         = table + nondefOff;
2824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_ULong  numMappings = TT_NEXT_ULONG( ndp );
2825a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          FT_ULong  i, lastUni  = 0;
2826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2828295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          if ( numMappings * 4 > (FT_ULong)( valid->limit - ndp ) )
2829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_INVALID_TOO_SHORT;
2830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( i = 0; i < numMappings; ++i )
2832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_ULong  uni = TT_NEXT_UINT24( ndp );
2834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_ULong  gid = TT_NEXT_USHORT( ndp );
2835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( uni >= 0x110000UL )                     /* end of Unicode */
2838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_INVALID_DATA;
2839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( uni < lastUni )
2841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_INVALID_DATA;
2842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            lastUni = uni + 1U;
2844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( valid->level >= FT_VALIDATE_TIGHT    &&
2846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 gid >= TT_VALID_GLYPH_COUNT( valid ) )
2847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_INVALID_GLYPH_ID;
2848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2853a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
2854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
2858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_char_index( TT_CMap    cmap,
2859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        FT_UInt32  char_code )
2860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( cmap );
2862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( char_code );
2863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* This can't happen */
2865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
2866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2869295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_UInt32 )
2870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_char_next( TT_CMap     cmap,
2871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_UInt32  *pchar_code )
2872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( cmap );
2874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* This can't happen */
2876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *pchar_code = 0;
2877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
2878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
2882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_get_info( TT_CMap       cmap,
2883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      TT_CMapInfo  *cmap_info )
2884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( cmap );
2886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2887295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap_info->format   = 14;
2888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* subtable 14 does not define a language field */
2889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->language = 0xFFFFFFFFUL;
2890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2891a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
2892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_UInt
2896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_char_map_def_binary( FT_Byte    *base,
2897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 FT_UInt32   char_code )
2898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  numRanges = TT_PEEK_ULONG( base );
2900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  max, min;
2901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    min = 0;
2904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    max = numRanges;
2905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base += 4;
2907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* binary search */
2909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( min < max )
2910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  mid   = ( min + max ) >> 1;
2912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*   p     = base + 4 * mid;
2913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ULong   start = TT_NEXT_UINT24( p );
2914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt    cnt   = FT_NEXT_BYTE( p );
2915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code < start )
2918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        max = mid;
2919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( char_code > start+cnt )
2920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        min = mid + 1;
2921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
2922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return TRUE;
2923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return FALSE;
2926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_UInt
2930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_char_map_nondef_binary( FT_Byte    *base,
2931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                    FT_UInt32   char_code )
2932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  numMappings = TT_PEEK_ULONG( base );
2934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  max, min;
2935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    min = 0;
2938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    max = numMappings;
2939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base += 4;
2941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* binary search */
2943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( min < max )
2944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  mid = ( min + max ) >> 1;
2946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*   p   = base + 5 * mid;
2947295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_UInt32  uni = (FT_UInt32)TT_NEXT_UINT24( p );
2948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code < uni )
2951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        max = mid;
2952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( char_code > uni )
2953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        min = mid + 1;
2954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
2955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return TT_PEEK_USHORT( p );
2956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
2959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Byte*
2963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_find_variant( FT_Byte    *base,
2964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          FT_UInt32   variantCode )
2965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  numVar = TT_PEEK_ULONG( base );
2967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  max, min;
2968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    min = 0;
2971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    max = numVar;
2972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base += 4;
2974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* binary search */
2976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( min < max )
2977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  mid    = ( min + max ) >> 1;
2979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*   p      = base + 11 * mid;
2980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ULong   varSel = TT_NEXT_UINT24( p );
2981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( variantCode < varSel )
2984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        max = mid;
2985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( variantCode > varSel )
2986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        min = mid + 1;
2987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
2988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return p;
2989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return NULL;
2992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
2996295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  tt_cmap14_char_var_index( TT_CMap    cmap,
2997295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                            TT_CMap    ucmap,
2998295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                            FT_UInt32  charcode,
2999a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                            FT_UInt32  variantSelector )
3000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
3002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  defOff;
3003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  nondefOff;
3004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !p )
3007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
3008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    defOff    = TT_NEXT_ULONG( p );
3010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    nondefOff = TT_PEEK_ULONG( p );
3011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( defOff != 0                                                    &&
3013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )
3014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* This is the default variant of this charcode.  GID not stored */
3016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* here; stored in the normal Unicode charmap instead.           */
3017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return ucmap->cmap.clazz->char_index( &ucmap->cmap, charcode );
3018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( nondefOff != 0 )
3021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
3022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                               charcode );
3023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
3025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Int )
3029295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  tt_cmap14_char_var_isdefault( TT_CMap    cmap,
3030295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                                FT_UInt32  charcode,
3031295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                                FT_UInt32  variantSelector )
3032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
3034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  defOff;
3035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  nondefOff;
3036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !p )
3039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return -1;
3040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    defOff    = TT_NEXT_ULONG( p );
3042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    nondefOff = TT_NEXT_ULONG( p );
3043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( defOff != 0                                                    &&
3045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )
3046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 1;
3047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( nondefOff != 0                                            &&
3049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
3050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                           charcode ) != 0         )
3051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
3052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return -1;
3054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt32* )
3058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_variants( TT_CMap    cmap,
3059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Memory  memory )
3060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMap14   cmap14 = (TT_CMap14)cmap;
3062295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt32   count  = cmap14->num_selectors;
3063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*    p      = cmap->data + 10;
3064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32*  result;
3065295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt32   i;
3066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
3069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return NULL;
3070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    result = cmap14->results;
3072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( i = 0; i < count; ++i )
3073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3074295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      result[i] = (FT_UInt32)TT_NEXT_UINT24( p );
3075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p        += 8;
3076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    result[i] = 0;
3078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return result;
3080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt32 * )
3084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_char_variants( TT_CMap    cmap,
3085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_Memory  memory,
3086295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                           FT_UInt32  charCode )
3087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMap14   cmap14 = (TT_CMap14)  cmap;
3089295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt32   count  = cmap14->num_selectors;
3090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*    p      = cmap->data + 10;
3091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32*  q;
3092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
3095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return NULL;
3096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( q = cmap14->results; count > 0; --count )
3098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  varSel    = TT_NEXT_UINT24( p );
3100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ULong   defOff    = TT_NEXT_ULONG( p );
3101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ULong   nondefOff = TT_NEXT_ULONG( p );
3102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ( defOff != 0                                               &&
3105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             tt_cmap14_char_map_def_binary( cmap->data + defOff,
3106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                            charCode )                 ) ||
3107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           ( nondefOff != 0                                            &&
3108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
3109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                               charCode ) != 0         ) )
3110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
3111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        q[0] = varSel;
3112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        q++;
3113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
3114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    q[0] = 0;
3116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return cmap14->results;
3118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_UInt
3122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_def_char_count( FT_Byte  *p )
3123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3124295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt32  numRanges = (FT_UInt32)TT_NEXT_ULONG( p );
3125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    tot       = 0;
3126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
312877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    p += 3;  /* point to the first `cnt' field */
3129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; numRanges > 0; numRanges-- )
3130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      tot += 1 + p[0];
3132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p   += 4;
3133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return tot;
3136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_UInt32*
3140a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  tt_cmap14_get_def_chars( TT_CMap    cmap,
3141a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                           FT_Byte*   p,
3142a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                           FT_Memory  memory )
3143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMap14   cmap14 = (TT_CMap14) cmap;
3145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32   numRanges;
3146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     cnt;
3147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32*  q;
3148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cnt       = tt_cmap14_def_char_count( p );
3151295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    numRanges = (FT_UInt32)TT_NEXT_ULONG( p );
3152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( tt_cmap14_ensure( cmap14, ( cnt + 1 ), memory ) )
3154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return NULL;
3155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( q = cmap14->results; numRanges > 0; --numRanges )
3157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3158a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      FT_UInt32  uni = (FT_UInt32)TT_NEXT_UINT24( p );
3159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cnt = FT_NEXT_BYTE( p ) + 1;
3162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      do
3163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
3164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        q[0]  = uni;
3165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        uni  += 1;
3166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        q    += 1;
3167a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
3168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      } while ( --cnt != 0 );
3169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    q[0] = 0;
3171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return cmap14->results;
3173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
317677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  static FT_UInt32*
3177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_get_nondef_chars( TT_CMap     cmap,
3178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              FT_Byte    *p,
3179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              FT_Memory   memory )
3180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMap14   cmap14 = (TT_CMap14) cmap;
3182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32   numMappings;
3183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     i;
3184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  *ret;
3185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3187295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    numMappings = (FT_UInt32)TT_NEXT_ULONG( p );
3188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( tt_cmap14_ensure( cmap14, ( numMappings + 1 ), memory ) )
3190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return NULL;
3191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ret = cmap14->results;
3193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( i = 0; i < numMappings; ++i )
3194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3195295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      ret[i] = (FT_UInt32)TT_NEXT_UINT24( p );
3196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p += 2;
3197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ret[i] = 0;
3199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return ret;
3201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt32 * )
3205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_variant_chars( TT_CMap    cmap,
3206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_Memory  memory,
3207295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                           FT_UInt32  variantSelector )
3208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte    *p  = tt_cmap14_find_variant( cmap->data + 6,
3210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                             variantSelector );
3211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  *ret;
3212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int      i;
3213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    defOff;
3214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    nondefOff;
3215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !p )
3218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return NULL;
3219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    defOff    = TT_NEXT_ULONG( p );
3221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    nondefOff = TT_NEXT_ULONG( p );
3222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( defOff == 0 && nondefOff == 0 )
3224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return NULL;
3225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( defOff == 0 )
3227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,
3228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                         memory );
3229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else if ( nondefOff == 0 )
3230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,
3231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                      memory );
3232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
3233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* Both a default and a non-default glyph set?  That's probably not */
3235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* good font design, but the spec allows for it...                  */
3236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TT_CMap14  cmap14 = (TT_CMap14) cmap;
3237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  numRanges;
3238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  numMappings;
3239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  duni;
3240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  dcnt;
3241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  nuni;
3242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*   dp;
3243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt    di, ni, k;
3244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p  = cmap->data + nondefOff;
3247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dp = cmap->data + defOff;
3248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3249295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      numMappings = (FT_UInt32)TT_NEXT_ULONG( p );
3250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dcnt        = tt_cmap14_def_char_count( dp );
3251295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      numRanges   = (FT_UInt32)TT_NEXT_ULONG( dp );
3252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( numMappings == 0 )
3254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,
3255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                        memory );
3256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( dcnt == 0 )
3257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,
3258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                           memory );
3259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tt_cmap14_ensure( cmap14, ( dcnt + numMappings + 1 ), memory ) )
3261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return NULL;
3262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ret  = cmap14->results;
3264295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      duni = (FT_UInt32)TT_NEXT_UINT24( dp );
3265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dcnt = FT_NEXT_BYTE( dp );
3266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      di   = 1;
3267295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      nuni = (FT_UInt32)TT_NEXT_UINT24( p );
3268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p   += 2;
3269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ni   = 1;
3270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      i    = 0;
3271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ;; )
3273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
3274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( nuni > duni + dcnt )
3275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
3276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( k = 0; k <= dcnt; ++k )
3277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            ret[i++] = duni + k;
3278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ++di;
3280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( di > numRanges )
3282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
3283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3284295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          duni = (FT_UInt32)TT_NEXT_UINT24( dp );
3285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dcnt = FT_NEXT_BYTE( dp );
3286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
3287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
3288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
3289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( nuni < duni )
3290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            ret[i++] = nuni;
3291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* If it is within the default range then ignore it -- */
3292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* that should not have happened                       */
3293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ++ni;
3294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( ni > numMappings )
3295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
3296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3297295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          nuni = (FT_UInt32)TT_NEXT_UINT24( p );
3298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p += 2;
3299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
3300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
3301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ni <= numMappings )
3303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
3304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* If we get here then we have run out of all default ranges.   */
3305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* We have read one non-default mapping which we haven't stored */
3306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* and there may be others that need to be read.                */
3307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ret[i++] = nuni;
3308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        while ( ni < numMappings )
3309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
3310295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          ret[i++] = (FT_UInt32)TT_NEXT_UINT24( p );
3311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p += 2;
3312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ++ni;
3313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
3314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
3315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( di <= numRanges )
3316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
3317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* If we get here then we have run out of all non-default     */
3318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* mappings.  We have read one default range which we haven't */
3319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* stored and there may be others that need to be read.       */
3320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( k = 0; k <= dcnt; ++k )
3321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ret[i++] = duni + k;
3322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        while ( di < numRanges )
3324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
3325295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          duni = (FT_UInt32)TT_NEXT_UINT24( dp );
3326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dcnt = FT_NEXT_BYTE( dp );
3327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( k = 0; k <= dcnt; ++k )
3329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            ret[i++] = duni + k;
3330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ++di;
3331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
3332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
3333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ret[i] = 0;
3335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return ret;
3337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3341a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_DEFINE_TT_CMAP(
3342a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    tt_cmap14_class_rec,
3343a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    sizeof ( TT_CMap14Rec ),
3344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3345a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_InitFunc)     tt_cmap14_init,
3346a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_DoneFunc)     tt_cmap14_done,
3347a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_CharIndexFunc)tt_cmap14_char_index,
3348a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_CharNextFunc) tt_cmap14_char_next,
3349a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
3350a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* Format 14 extension functions */
3351a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_CharVarIndexFunc)    tt_cmap14_char_var_index,
3352a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault,
3353a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_VariantListFunc)     tt_cmap14_variants,
3354a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants,
3355a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars,
3356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    14,
3358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (TT_CMap_ValidateFunc)tt_cmap14_validate,
3359a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    (TT_CMap_Info_GetFunc)tt_cmap14_get_info )
3360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
336177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner#endif /* TT_CONFIG_CMAP_FORMAT_14 */
3362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3364295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#ifndef FT_CONFIG_OPTION_PIC
3365295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
3366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static const TT_CMap_Class  tt_cmap_classes[] =
3367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3368a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#define TTCMAPCITEM( a )  &a,
3369295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#include "ttcmapc.h"
3370295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    NULL,
3371295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  };
3372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3373295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#else /*FT_CONFIG_OPTION_PIC*/
3374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3375a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  void
3376a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_Destroy_Class_tt_cmap_classes( FT_Library      library,
3377a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                    TT_CMap_Class*  clazz )
3378295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
3379a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Memory  memory = library->memory;
3380a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
3381a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
3382295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( clazz )
3383295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_FREE( clazz );
3384295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  }
3385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3386a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
3387a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_Error
3388a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_Create_Class_tt_cmap_classes( FT_Library       library,
3389a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                   TT_CMap_Class**  output_class )
3390295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
3391a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    TT_CMap_Class*     clazz  = NULL;
3392a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    TT_CMap_ClassRec*  recs;
3393a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Error           error;
3394a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Memory          memory = library->memory;
3395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3396a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    int  i = 0;
3397a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
3398a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
3399a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#define TTCMAPCITEM( a ) i++;
3400295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#include "ttcmapc.h"
3401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3402a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* allocate enough space for both the pointers */
3403a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* plus terminator and the class instances     */
3404a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( FT_ALLOC( clazz, sizeof ( *clazz ) * ( i + 1 ) +
3405a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          sizeof ( TT_CMap_ClassRec ) * i ) )
3406295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      return error;
3407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3408295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* the location of the class instances follows the array of pointers */
3409a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    recs = (TT_CMap_ClassRec*)( (char*)clazz +
3410a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                sizeof ( *clazz ) * ( i + 1 ) );
3411a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    i    = 0;
3412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3413295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#undef TTCMAPCITEM
3414a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#define  TTCMAPCITEM( a )             \
3415a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Init_Class_ ## a( &recs[i] );  \
3416a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    clazz[i] = &recs[i];              \
3417295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    i++;
3418295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#include "ttcmapc.h"
3419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3420295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    clazz[i] = NULL;
3421295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
3422295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    *output_class = clazz;
3423a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
3424295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  }
3425295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
3426295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#endif /*FT_CONFIG_OPTION_PIC*/
3427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* parse the `cmap' table and build the corresponding TT_CMap objects */
3430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* in the current face                                                */
3431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                    */
3432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
3433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_face_build_cmaps( TT_Face  face )
3434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*           table = face->cmap_table;
3436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*           limit = table + face->cmap_size;
3437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt volatile   num_cmaps;
3438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte* volatile  p     = table;
3439aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    FT_Library         library = FT_FACE_LIBRARY( face );
3440aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
3441aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    FT_UNUSED( library );
3442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3444aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    if ( !p || p + 4 > limit )
3445a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_THROW( Invalid_Table );
3446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* only recognize format 0 */
3448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( TT_NEXT_USHORT( p ) != 0 )
3449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p -= 2;
3451295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_ERROR(( "tt_face_build_cmaps:"
3452295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                 " unsupported `cmap' table format = %d\n",
3453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 TT_PEEK_USHORT( p ) ));
3454a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_THROW( Invalid_Table );
3455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_cmaps = TT_NEXT_USHORT( p );
3458a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
3459aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich#ifdef FT_MAX_CHARMAP_CACHEABLE
3460aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    if ( num_cmaps > FT_MAX_CHARMAP_CACHEABLE )
3461a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      FT_ERROR(( "tt_face_build_cmaps: too many cmap subtables (%d)\n"
3462a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                 "                     subtable #%d and higher are loaded"
3463a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                 "                     but cannot be searched\n",
3464aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich                 num_cmaps, FT_MAX_CHARMAP_CACHEABLE + 1 ));
3465aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich#endif
3466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- )
3468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_CharMapRec  charmap;
3470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32      offset;
3471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      charmap.platform_id = TT_NEXT_USHORT( p );
3474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      charmap.encoding_id = TT_NEXT_USHORT( p );
3475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      charmap.face        = FT_FACE( face );
3476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      charmap.encoding    = FT_ENCODING_NONE;  /* will be filled later */
3477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      offset              = TT_NEXT_ULONG( p );
3478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( offset && offset <= face->cmap_size - 2 )
3480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
3481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Byte* volatile              cmap   = table + offset;
3482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        volatile FT_UInt               format = TT_PEEK_USHORT( cmap );
3483a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        const TT_CMap_Class* volatile  pclazz = TT_CMAP_CLASSES_GET;
3484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        TT_CMap_Class volatile         clazz;
3485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( ; *pclazz; pclazz++ )
3488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
3489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          clazz = *pclazz;
3490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( clazz->format == format )
3491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
3492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            volatile TT_ValidatorRec  valid;
3493a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            volatile FT_Error         error = FT_Err_Ok;
3494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit,
3497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                               FT_VALIDATE_DEFAULT );
3498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            valid.num_glyphs = (FT_UInt)face->max_profile.numGlyphs;
3500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3501a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            if ( ft_setjmp( FT_VALIDATOR( &valid )->jump_buffer) == 0 )
3502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
3503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              /* validate this cmap sub-table */
3504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              error = clazz->validate( cmap, FT_VALIDATOR( &valid ) );
3505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
3506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( valid.validator.error == 0 )
3508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
3509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_CMap  ttcmap;
3510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3512a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              /* It might make sense to store the single variation         */
3513a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              /* selector cmap somewhere special.  But it would have to be */
3514a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              /* in the public FT_FaceRec, and we can't change that.       */
3515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( !FT_CMap_New( (FT_CMap_Class)clazz,
3517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 cmap, &charmap, &ttcmap ) )
3518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
3519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                /* it is simpler to directly set `flags' than adding */
3520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                /* a parameter to FT_CMap_New                        */
3521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                ((TT_CMap)ttcmap)->flags = (FT_Int)error;
3522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
3523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
3524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
3525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
3526295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner              FT_TRACE0(( "tt_face_build_cmaps:"
3527295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                          " broken cmap sub-table ignored\n" ));
3528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
3529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
3530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
3531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
3532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( *pclazz == NULL )
3534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
3535295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          FT_TRACE0(( "tt_face_build_cmaps:"
3536295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                      " unsupported cmap sub-table ignored\n" ));
3537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
3538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
3539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3541a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_Err_Ok;
3542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL( FT_Error )
3546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_get_cmap_info( FT_CharMap    charmap,
3547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    TT_CMapInfo  *cmap_info )
3548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_CMap        cmap  = (FT_CMap)charmap;
3550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMap_Class  clazz = (TT_CMap_Class)cmap->clazz;
3551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return clazz->get_cmap_info( charmap, cmap_info );
3554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* END */
3558