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/*                                                                         */
7a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin/*  Copyright 2002-2017 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
54055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  /* Too large glyph index return values are caught in `FT_Get_Char_Index' */
55055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  /* and `FT_Get_Next_Char' (the latter calls the internal `next' function */
56055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  /* again in this case).  To mark character code return values as invalid */
57055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  /* it is sufficient to set the corresponding glyph index return value to */
58055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  /* zero.                                                                 */
59055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
60055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
61049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
62049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap_init( TT_CMap   cmap,
63049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                FT_Byte*  table )
64049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
65049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->data = table;
66727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
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  /*****                           FORMAT 0                            *****/
74049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
75049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
76049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
77049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
78049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
79049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
80049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* TABLE OVERVIEW                                                        */
81049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* --------------                                                        */
82049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
83049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME        OFFSET         TYPE          DESCRIPTION                */
84049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
85049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   format      0              USHORT        must be 0                  */
86049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   length      2              USHORT        table length in bytes      */
87049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   language    4              USHORT        Mac language code          */
88049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   glyph_ids   6              BYTE[256]     array of glyph indices     */
89049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*               262                                                     */
90049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
91049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
92049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_0
93049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
94049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
95049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap0_validate( FT_Byte*      table,
96049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Validator  valid )
97049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
989c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_Byte*  p;
999c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_UInt   length;
1009c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1029c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    if ( table + 2 + 2 > valid->limit )
1039c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      FT_INVALID_TOO_SHORT;
1049c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
1059c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    p      = table + 2;           /* skip format */
1069c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    length = TT_NEXT_USHORT( p );
107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + length > valid->limit || length < 262 )
109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* check glyph indices whenever necessary */
112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( valid->level >= FT_VALIDATE_TIGHT )
113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  n, idx;
115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p = table + 6;
118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( n = 0; n < 256; n++ )
119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        idx = *p++;
121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_GLYPH_ID;
123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
126727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap0_char_index( TT_CMap    cmap,
132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_UInt32  char_code )
133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  table = cmap->data;
135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return char_code < 256 ? table[6 + char_code] : 0;
138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
141295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_UInt32 )
142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap0_char_next( TT_CMap     cmap,
143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_UInt32  *pchar_code )
144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   table    = cmap->data;
146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  charcode = *pchar_code;
147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  result   = 0;
148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    gindex   = 0;
149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
15177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    table += 6;  /* go to glyph IDs */
152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( ++charcode < 256 )
153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      gindex = table[charcode];
155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( gindex != 0 )
156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        result = charcode;
158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *pchar_code = result;
163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap0_get_info( TT_CMap       cmap,
169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     TT_CMapInfo  *cmap_info )
170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = cmap->data + 4;
172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
174295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap_info->format   = 0;
175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
177727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
181727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  FT_DEFINE_TT_CMAP(
182727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    tt_cmap0_class_rec,
183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
184a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      sizeof ( TT_CMapRec ),
185727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
186a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_InitFunc)     tt_cmap_init,         /* init       */
187a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_DoneFunc)     NULL,                 /* done       */
188a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharIndexFunc)tt_cmap0_char_index,  /* char_index */
189a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharNextFunc) tt_cmap0_char_next,   /* char_next  */
190a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
191a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
192a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
193a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
194a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
195a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    0,
198a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    (TT_CMap_ValidateFunc)tt_cmap0_validate,  /* validate      */
199a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    (TT_CMap_Info_GetFunc)tt_cmap0_get_info   /* get_cmap_info */
200a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  )
201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* TT_CONFIG_CMAP_FORMAT_0 */
203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                          FORMAT 2                             *****/
209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** This is used for certain CJK encodings that encode text in a  *****/
211055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  /***** mixed 8/16 bits encoding along the following lines.           *****/
212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** * Certain byte values correspond to an 8-bit character code   *****/
214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   (typically in the range 0..127 for ASCII compatibility).    *****/
215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** * Certain byte values signal the first byte of a 2-byte       *****/
217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   character code (but these values are also valid as the      *****/
218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   second byte of a 2-byte character).                         *****/
219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** The following charmap lookup and iteration functions all      *****/
221055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  /***** assume that the value `charcode' fulfills the following.      *****/
222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
223055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  /*****   - For one byte characters, `charcode' is simply the         *****/
224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****     character code.                                           *****/
225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
226055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  /*****   - For two byte characters, `charcode' is the 2-byte         *****/
227055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  /*****     character code in big endian format.  More precisely:     *****/
228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****       (charcode >> 8)    is the first byte value              *****/
230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****       (charcode & 0xFF)  is the second byte value             *****/
231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
232055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  /***** Note that not all values of `charcode' are valid according    *****/
233055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  /***** to these rules, and the function moderately checks the        *****/
234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** arguments.                                                    *****/
235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* TABLE OVERVIEW                                                        */
242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* --------------                                                        */
243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME        OFFSET         TYPE            DESCRIPTION              */
245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   format      0              USHORT          must be 2                */
247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   length      2              USHORT          table length in bytes    */
248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   language    4              USHORT          Mac language code        */
249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   keys        6              USHORT[256]     sub-header keys          */
250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   subs        518            SUBHEAD[NSUBS]  sub-headers array        */
25177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /*   glyph_ids   518+NSUB*8     USHORT[]        glyph ID array           */
252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* The `keys' table is used to map charcode high-bytes to sub-headers.   */
254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* The value of `NSUBS' is the number of sub-headers defined in the      */
255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* table and is computed by finding the maximum of the `keys' table.     */
256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Note that for any n, `keys[n]' is a byte offset within the `subs'     */
258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* table, i.e., it is the corresponding sub-header index multiplied      */
259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* by 8.                                                                 */
260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
261055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  /* Each sub-header has the following format.                             */
262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME        OFFSET      TYPE            DESCRIPTION                 */
264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   first       0           USHORT          first valid low-byte        */
266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   count       2           USHORT          number of valid low-bytes   */
267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   delta       4           SHORT           see below                   */
268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   offset      6           USHORT          see below                   */
269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* A sub-header defines, for each high-byte, the range of valid          */
271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* low-bytes within the charmap.  Note that the range defined by `first' */
272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* and `count' must be completely included in the interval [0..255]      */
273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* according to the specification.                                       */
274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* If a character code is contained within a given sub-header, then      */
276055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  /* mapping it to a glyph index is done as follows.                       */
277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* * The value of `offset' is read.  This is a _byte_ distance from the  */
279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   location of the `offset' field itself into a slice of the           */
280055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  /*   `glyph_ids' table.  Let's call it `slice' (it is a USHORT[], too).  */
281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* * The value `slice[char.lo - first]' is read.  If it is 0, there is   */
283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   no glyph for the charcode.  Otherwise, the value of `delta' is      */
284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   added to it (modulo 65536) to form a new glyph index.               */
285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* It is up to the validation routine to check that all offsets fall     */
28777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* within the glyph IDs table (and not within the `subs' table itself or */
288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* outside of the CMap).                                                 */
289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_2
292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap2_validate( FT_Byte*      table,
295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Validator  valid )
296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2979c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_Byte*  p;
2989c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_UInt   length;
2999c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   n, max_subs;
3019c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_Byte*  keys;        /* keys table     */
3029c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_Byte*  subs;        /* sub-headers    */
3039c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_Byte*  glyph_ids;   /* glyph ID array */
304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3069c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    if ( table + 2 + 2 > valid->limit )
3079c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      FT_INVALID_TOO_SHORT;
3089c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
3099c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    p      = table + 2;           /* skip format */
3109c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    length = TT_NEXT_USHORT( p );
3119c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + length > valid->limit || length < 6 + 512 )
313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    keys = table + 6;
316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* parse keys to compute sub-headers count */
318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p        = keys;
319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    max_subs = 0;
320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( n = 0; n < 256; n++ )
321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  idx = TT_NEXT_USHORT( p );
323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* value must be multiple of 8 */
326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 )
327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_INVALID_DATA;
328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      idx >>= 3;
330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( idx > max_subs )
332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        max_subs = idx;
333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ASSERT( p == table + 518 );
336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    subs      = p;
338055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    glyph_ids = subs + ( max_subs + 1 ) * 8;
339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( glyph_ids > valid->limit )
340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* parse sub-headers */
343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( n = 0; n <= max_subs; n++ )
344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
345ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      FT_UInt  first_code, code_count, offset;
346ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      FT_Int   delta;
347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      first_code = TT_NEXT_USHORT( p );
350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      code_count = TT_NEXT_USHORT( p );
351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta      = TT_NEXT_SHORT( p );
352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      offset     = TT_NEXT_USHORT( p );
353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
35477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      /* many Dynalab fonts have empty sub-headers */
35577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      if ( code_count == 0 )
35677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        continue;
35777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* check range within 0..255 */
359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( valid->level >= FT_VALIDATE_PARANOID )
360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( first_code >= 256 || first_code + code_count > 256 )
362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_DATA;
363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* check offset */
366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( offset != 0 )
367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
368ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease        FT_Byte*  ids;
369ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
370ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ids = p - 2 + offset;
372fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        if ( ids < glyph_ids || ids + code_count * 2 > table + length )
373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_OFFSET;
374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
37577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        /* check glyph IDs */
376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( valid->level >= FT_VALIDATE_TIGHT )
377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Byte*  limit = p + code_count * 2;
379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt   idx;
380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( ; p < limit; )
383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            idx = TT_NEXT_USHORT( p );
385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( idx != 0 )
386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
387fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki              idx = (FT_UInt)( (FT_Int)idx + delta ) & 0xFFFFU;
388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                FT_INVALID_GLYPH_ID;
390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
396727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* return sub header corresponding to a given character code */
401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* NULL on invalid charcode                                  */
402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Byte*
403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap2_get_subheader( FT_Byte*   table,
404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          FT_UInt32  char_code )
405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  result = NULL;
407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( char_code < 0x10000UL )
410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   char_lo = (FT_UInt)( char_code & 0xFF );
412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   char_hi = (FT_UInt)( char_code >> 8 );
413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  p       = table + 6;    /* keys table */
414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  subs    = table + 518;  /* subheaders table */
415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  sub;
416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_hi == 0 )
419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* an 8-bit character code -- we use subHeader 0 in this case */
421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* to test whether the character code is in the charmap       */
422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /*                                                            */
423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        sub = subs;  /* jump to first sub-header */
424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* check that the sub-header for this byte is 0, which */
42677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        /* indicates that it is really a valid one-byte value  */
427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* Otherwise, return 0                                 */
428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /*                                                     */
429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p += char_lo * 2;
430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( TT_PEEK_USHORT( p ) != 0 )
431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Exit;
432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* a 16-bit character code */
436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* jump to key entry  */
438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p  += char_hi * 2;
439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* jump to sub-header */
440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        sub = subs + ( FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 8 ) );
441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* check that the high byte isn't a valid one-byte value */
443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( sub == subs )
444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Exit;
445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = sub;
447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
448055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return result;
451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap2_char_index( TT_CMap    cmap,
456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_UInt32  char_code )
457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  table   = cmap->data;
459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   result  = 0;
460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  subheader;
461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    subheader = tt_cmap2_get_subheader( table, char_code );
464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( subheader )
465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  p   = subheader;
467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   idx = (FT_UInt)(char_code & 0xFF);
468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   start, count;
469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int    delta;
470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   offset;
471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start  = TT_NEXT_USHORT( p );
474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      count  = TT_NEXT_USHORT( p );
475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta  = TT_NEXT_SHORT ( p );
476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      offset = TT_PEEK_USHORT( p );
477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      idx -= start;
479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( idx < count && offset != 0 )
480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p  += offset + 2 * idx;
482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        idx = TT_PEEK_USHORT( p );
483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( idx != 0 )
485fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          result = (FT_UInt)( (FT_Int)idx + delta ) & 0xFFFFU;
486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
488055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return result;
490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
493295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_UInt32 )
494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap2_char_next( TT_CMap     cmap,
495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_UInt32  *pcharcode )
496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   table    = cmap->data;
498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    gindex   = 0;
499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  result   = 0;
500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  charcode = *pcharcode + 1;
501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   subheader;
502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( charcode < 0x10000UL )
505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      subheader = tt_cmap2_get_subheader( table, charcode );
507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( subheader )
508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Byte*  p       = subheader;
510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt   start   = TT_NEXT_USHORT( p );
511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt   count   = TT_NEXT_USHORT( p );
512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Int    delta   = TT_NEXT_SHORT ( p );
513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt   offset  = TT_PEEK_USHORT( p );
514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt   char_lo = (FT_UInt)( charcode & 0xFF );
515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt   pos, idx;
516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( offset == 0 )
519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Next_SubHeader;
520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( char_lo < start )
522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          char_lo = start;
524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          pos     = 0;
525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          pos = (FT_UInt)( char_lo - start );
528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p       += offset + pos * 2;
530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        charcode = FT_PAD_FLOOR( charcode, 256 ) + char_lo;
531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( ; pos < count; pos++, charcode++ )
533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          idx = TT_NEXT_USHORT( p );
535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( idx != 0 )
537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
538fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            gindex = (FT_UInt)( (FT_Int)idx + delta ) & 0xFFFFU;
539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( gindex != 0 )
540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              result = charcode;
542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              goto Exit;
543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* jump to next sub-header, i.e. higher byte value */
549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    Next_SubHeader:
550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      charcode = FT_PAD_FLOOR( charcode, 256 ) + 256;
551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *pcharcode = result;
555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap2_get_info( TT_CMap       cmap,
562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     TT_CMapInfo  *cmap_info )
563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = cmap->data + 4;
565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
567295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap_info->format   = 2;
568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
570727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
574727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  FT_DEFINE_TT_CMAP(
575727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    tt_cmap2_class_rec,
576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
577a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      sizeof ( TT_CMapRec ),
578727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
579a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_InitFunc)     tt_cmap_init,         /* init       */
580a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_DoneFunc)     NULL,                 /* done       */
581a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharIndexFunc)tt_cmap2_char_index,  /* char_index */
582a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharNextFunc) tt_cmap2_char_next,   /* char_next  */
583a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
584a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
585a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
586a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
587a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
588a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    2,
591a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    (TT_CMap_ValidateFunc)tt_cmap2_validate,  /* validate      */
592a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    (TT_CMap_Info_GetFunc)tt_cmap2_get_info   /* get_cmap_info */
593a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  )
594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* TT_CONFIG_CMAP_FORMAT_2 */
596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                           FORMAT 4                            *****/
602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* TABLE OVERVIEW                                                        */
609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* --------------                                                        */
610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME          OFFSET         TYPE              DESCRIPTION          */
612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   format        0              USHORT            must be 4            */
614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   length        2              USHORT            table length         */
615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                  in bytes             */
616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   language      4              USHORT            Mac language code    */
617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   segCountX2    6              USHORT            2*NUM_SEGS           */
619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   searchRange   8              USHORT            2*(1 << LOG_SEGS)    */
620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   entrySelector 10             USHORT            LOG_SEGS             */
621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   rangeShift    12             USHORT            segCountX2 -         */
622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                    searchRange        */
623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   endCount      14             USHORT[NUM_SEGS]  end charcode for     */
625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                  each segment; last   */
626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                  is 0xFFFF            */
627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   pad           14+NUM_SEGS*2  USHORT            padding              */
629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   startCount    16+NUM_SEGS*2  USHORT[NUM_SEGS]  first charcode for   */
631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                  each segment         */
632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   idDelta       16+NUM_SEGS*4  SHORT[NUM_SEGS]   delta for each       */
634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                  segment              */
635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   idOffset      16+NUM_SEGS*6  SHORT[NUM_SEGS]   range offset for     */
636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                  each segment; can be */
637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                  zero                 */
638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
63977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /*   glyphIds      16+NUM_SEGS*8  USHORT[]          array of glyph ID    */
640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                  ranges               */
641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Character codes are modelled by a series of ordered (increasing)      */
643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* intervals called segments.  Each segment has start and end codes,     */
644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* provided by the `startCount' and `endCount' arrays.  Segments must    */
64577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* not overlap, and the last segment should always contain the value     */
64677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* 0xFFFF for `endCount'.                                                */
647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* The fields `searchRange', `entrySelector' and `rangeShift' are better */
649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* ignored (they are traces of over-engineering in the TrueType          */
650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* specification).                                                       */
651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Each segment also has a signed `delta', as well as an optional offset */
653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* within the `glyphIds' table.                                          */
654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* If a segment's idOffset is 0, the glyph index corresponding to any    */
656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* charcode within the segment is obtained by adding the value of        */
657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* `idDelta' directly to the charcode, modulo 65536.                     */
658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
65977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* Otherwise, a glyph index is taken from the glyph IDs sub-array for    */
660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* the segment, and the value of `idDelta' is added to it.               */
661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
66377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* Finally, note that a lot of fonts contain an invalid last segment,    */
66477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* where `start' and `end' are correctly set to 0xFFFF but both `delta'  */
66577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* and `offset' are incorrect (e.g., `opens___.ttf' which comes with     */
66677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* OpenOffice.org).  We need special code to deal with them correctly.   */
667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_4
670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef struct  TT_CMap4Rec_
672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMapRec  cmap;
674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32   cur_charcode;   /* current charcode */
675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     cur_gindex;     /* current glyph index */
676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     num_ranges;
678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     cur_range;
679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     cur_start;
680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     cur_end;
681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int      cur_delta;
682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*    cur_values;
683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  } TT_CMap4Rec, *TT_CMap4;
685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap4_init( TT_CMap4  cmap,
689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 FT_Byte*  table )
690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p;
692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->cmap.data    = table;
695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p                  = table + 6;
697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->num_ranges   = FT_PEEK_USHORT( p ) >> 1;
698295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL;
699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->cur_gindex   = 0;
700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
701727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Int
706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap4_set_range( TT_CMap4  cmap,
707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_UInt   range_index )
708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  table = cmap->cmap.data;
710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p;
711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   num_ranges = cmap->num_ranges;
712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( range_index < num_ranges )
715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  offset;
717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p             = table + 14 + range_index * 2;
720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cmap->cur_end = FT_PEEK_USHORT( p );
721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p              += 2 + num_ranges * 2;
723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cmap->cur_start = FT_PEEK_USHORT( p );
724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p              += num_ranges * 2;
726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cmap->cur_delta = FT_PEEK_SHORT( p );
727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p     += num_ranges * 2;
729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      offset = FT_PEEK_USHORT( p );
730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
73177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      /* some fonts have an incorrect last segment; */
73277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      /* we have to catch it                        */
73377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      if ( range_index     >= num_ranges - 1 &&
73477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner           cmap->cur_start == 0xFFFFU        &&
73577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner           cmap->cur_end   == 0xFFFFU        )
73677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      {
73777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        TT_Face   face  = (TT_Face)cmap->cmap.cmap.charmap.face;
73877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        FT_Byte*  limit = face->cmap_table + face->cmap_size;
73977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
74077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
74177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        if ( offset && p + offset + 2 > limit )
74277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        {
74377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          cmap->cur_delta = 1;
74477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          offset          = 0;
74577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        }
74677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      }
74777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( offset != 0xFFFFU )
749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cmap->cur_values = offset ? p + offset : NULL;
751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cmap->cur_range  = range_index;
752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return 0;
753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we skip empty segments */
756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      range_index++;
757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return -1;
760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* search the index of the charcode next to cmap->cur_charcode; */
764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* caller should call tt_cmap4_set_range with proper range      */
765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* before calling this function                                 */
766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                              */
767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap4_next( TT_CMap4  cmap )
769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
770055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    TT_Face   face  = (TT_Face)cmap->cmap.cmap.charmap.face;
771055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    FT_Byte*  limit = face->cmap_table + face->cmap_size;
772055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt  charcode;
774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( cmap->cur_charcode >= 0xFFFFUL )
777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Fail;
778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
779295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    charcode = (FT_UInt)cmap->cur_charcode + 1;
780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( charcode < cmap->cur_start )
782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      charcode = cmap->cur_start;
783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
784055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    for (;;)
785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  values = cmap->cur_values;
787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   end    = cmap->cur_end;
788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int    delta  = cmap->cur_delta;
789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( charcode <= end )
792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( values )
794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_Byte*  p = values + 2 * ( charcode - cmap->cur_start );
796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
798055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          /* if p > limit, the whole segment is invalid */
799055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          if ( p > limit )
800055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            goto Next_Segment;
801055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          do
803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_UInt  gindex = FT_NEXT_USHORT( p );
805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
807055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            if ( gindex )
808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
809fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki              gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU;
810055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin              if ( gindex )
811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                cmap->cur_charcode = charcode;
813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                cmap->cur_gindex   = gindex;
814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                return;
815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          } while ( ++charcode <= end );
818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          do
822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
823fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            FT_UInt  gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU;
824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
826055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            if ( gindex >= (FT_UInt)face->root.num_glyphs )
827055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            {
828055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin              /* we have an invalid glyph index; if there is an overflow, */
829055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin              /* we can adjust `charcode', otherwise the whole segment is */
830055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin              /* invalid                                                  */
831055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin              gindex = 0;
832055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
833055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin              if ( (FT_Int)charcode + delta < 0 &&
834055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                   (FT_Int)end + delta >= 0     )
835055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                charcode = (FT_UInt)( -delta );
836055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
837055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin              else if ( (FT_Int)charcode + delta < 0x10000L &&
838055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                        (FT_Int)end + delta >= 0x10000L     )
839055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                charcode = (FT_UInt)( 0x10000L - delta );
840055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
841055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin              else
842055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                goto Next_Segment;
843055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            }
844055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
845055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            if ( gindex )
846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              cmap->cur_charcode = charcode;
848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              cmap->cur_gindex   = gindex;
849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              return;
850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          } while ( ++charcode <= end );
852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
855055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    Next_Segment:
856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we need to find another range */
857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tt_cmap4_set_range( cmap, cmap->cur_range + 1 ) < 0 )
858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( charcode < cmap->cur_start )
861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        charcode = cmap->cur_start;
862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Fail:
865295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL;
866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->cur_gindex   = 0;
867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap4_validate( FT_Byte*      table,
872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Validator  valid )
873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
8749c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_Byte*  p;
8759c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_UInt   length;
8769c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte   *ends, *starts, *offsets, *deltas, *glyph_ids;
878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   num_segs;
879727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Error  error = FT_Err_Ok;
880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
8829c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    if ( table + 2 + 2 > valid->limit )
8839c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      FT_INVALID_TOO_SHORT;
8849c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
8859c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    p      = table + 2;           /* skip format */
8869c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    length = TT_NEXT_USHORT( p );
8879c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* in certain fonts, the `length' field is invalid and goes */
889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* out of bound.  We try to correct this here...            */
890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + length > valid->limit )
891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( valid->level >= FT_VALIDATE_TIGHT )
893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_INVALID_TOO_SHORT;
894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      length = (FT_UInt)( valid->limit - table );
896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
898fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( length < 16 )
899fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      FT_INVALID_TOO_SHORT;
900fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p        = table + 6;
902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_segs = TT_NEXT_USHORT( p );   /* read segCountX2 */
903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( valid->level >= FT_VALIDATE_PARANOID )
905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* check that we have an even value here */
907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( num_segs & 1 )
908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_INVALID_DATA;
909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_segs /= 2;
912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( length < 16 + num_segs * 2 * 4 )
914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* check the search parameters - even though we never use them */
917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                             */
918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( valid->level >= FT_VALIDATE_PARANOID )
919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
92077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      /* check the values of `searchRange', `entrySelector', `rangeShift' */
921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  search_range   = TT_NEXT_USHORT( p );
922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  entry_selector = TT_NEXT_USHORT( p );
923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  range_shift    = TT_NEXT_USHORT( p );
924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ( search_range | range_shift ) & 1 )  /* must be even values */
927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_INVALID_DATA;
928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      search_range /= 2;
930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      range_shift  /= 2;
931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* `search range' is the greatest power of 2 that is <= num_segs */
933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( search_range                > num_segs                 ||
935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           search_range * 2            < num_segs                 ||
936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           search_range + range_shift != num_segs                 ||
937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           search_range               != ( 1U << entry_selector ) )
938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_INVALID_DATA;
939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ends      = table   + 14;
942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    starts    = table   + 16 + num_segs * 2;
943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    deltas    = starts  + num_segs * 2;
944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    offsets   = deltas  + num_segs * 2;
945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    glyph_ids = offsets + num_segs * 2;
946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
94777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    /* check last segment; its end count value must be 0xFFFF */
948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( valid->level >= FT_VALIDATE_PARANOID )
949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p = ends + ( num_segs - 1 ) * 2;
951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( TT_PEEK_USHORT( p ) != 0xFFFFU )
952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_INVALID_DATA;
953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
95677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      FT_UInt   start, end, offset, n;
95777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      FT_UInt   last_start = 0, last_end = 0;
95877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner      FT_Int    delta;
959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  p_start   = starts;
960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  p_end     = ends;
961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  p_delta   = deltas;
962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  p_offset  = offsets;
963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( n = 0; n < num_segs; n++ )
966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p      = p_offset;
968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        start  = TT_NEXT_USHORT( p_start );
969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        end    = TT_NEXT_USHORT( p_end );
970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        delta  = TT_NEXT_SHORT( p_delta );
971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        offset = TT_NEXT_USHORT( p_offset );
972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( start > end )
974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_DATA;
975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
97677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        /* this test should be performed at default validation level; */
97777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        /* unfortunately, some popular Asian fonts have overlapping   */
97877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        /* ranges in their charmaps                                   */
97977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        /*                                                            */
980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( start <= last_end && n > 0 )
981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( valid->level >= FT_VALIDATE_TIGHT )
983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_INVALID_DATA;
984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* allow overlapping segments, provided their start points */
98777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner            /* and end points, respectively, are in ascending order    */
988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /*                                                         */
989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( last_start > start || last_end > end )
990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              error |= TT_CMAP_FLAG_UNSORTED;
991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              error |= TT_CMAP_FLAG_OVERLAPPING;
993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( offset && offset != 0xFFFFU )
997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
99877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          p += offset;  /* start of glyph ID array */
999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
100077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* check that we point within the glyph IDs table only */
1001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( valid->level >= FT_VALIDATE_TIGHT )
1002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( p < glyph_ids                                ||
1004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 p + ( end - start + 1 ) * 2 > table + length )
1005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_INVALID_DATA;
1006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
100777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* Some fonts handle the last segment incorrectly.  In */
100877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* theory, 0xFFFF might point to an ordinary glyph --  */
100977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* a cmap 4 is versatile and could be used for any     */
101077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* encoding, not only Unicode.  However, reality shows */
101177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* that far too many fonts are sloppy and incorrectly  */
101277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* set all fields but `start' and `end' for the last   */
101377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* segment if it contains only a single character.     */
101477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /*                                                     */
101577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* We thus omit the test here, delaying it to the      */
1016055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          /* routines that actually access the cmap.             */
101777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          else if ( n != num_segs - 1                       ||
101877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner                    !( start == 0xFFFFU && end == 0xFFFFU ) )
1019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( p < glyph_ids                              ||
1021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 p + ( end - start + 1 ) * 2 > valid->limit )
1022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_INVALID_DATA;
1023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* check glyph indices within the segment range */
1026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( valid->level >= FT_VALIDATE_TIGHT )
1027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_UInt  i, idx;
1029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            for ( i = start; i < end; i++ )
1032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              idx = FT_NEXT_USHORT( p );
1034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( idx != 0 )
1035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
1036fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                idx = (FT_UInt)( (FT_Int)idx + delta ) & 0xFFFFU;
1037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
1039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_INVALID_GLYPH_ID;
1040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
1041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( offset == 0xFFFFU )
1045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
104677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          /* some fonts (erroneously?) use a range offset of 0xFFFF */
1047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* to mean missing glyph in cmap table                    */
1048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /*                                                        */
104977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          if ( valid->level >= FT_VALIDATE_PARANOID    ||
105077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner               n != num_segs - 1                       ||
105177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner               !( start == 0xFFFFU && end == 0xFFFFU ) )
1052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_INVALID_DATA;
1053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        last_start = start;
1056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        last_end   = end;
1057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_UInt
106577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  tt_cmap4_char_map_linear( TT_CMap     cmap,
106677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner                            FT_UInt32*  pcharcode,
106777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner                            FT_Bool     next )
1068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1069055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    TT_Face   face  = (TT_Face)cmap->cmap.charmap.face;
1070055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    FT_Byte*  limit = face->cmap_table + face->cmap_size;
1071055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1072055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    num_segs2, start, end, offset;
1074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int     delta;
1075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    i, num_segs;
1076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  charcode = *pcharcode;
1077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    gindex   = 0;
1078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p;
1079055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    FT_Byte*   q;
1080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p = cmap->data + 6;
1083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );
1084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_segs = num_segs2 >> 1;
1086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !num_segs )
1088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
1089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( next )
1091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      charcode++;
1092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1093055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    if ( charcode > 0xFFFFU )
1094055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      return 0;
1095055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* linear search */
1097055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    p = cmap->data + 14;               /* ends table   */
1098055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    q = cmap->data + 16 + num_segs2;   /* starts table */
1099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1100055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    for ( i = 0; i < num_segs; i++ )
1101055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    {
1102055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      end   = TT_NEXT_USHORT( p );
1103055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      start = TT_NEXT_USHORT( q );
1104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1105055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      if ( charcode < start )
1106055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      {
1107055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        if ( next )
1108055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          charcode = start;
1109055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        else
1110055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          break;
1111055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      }
1112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1113055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    Again:
1114055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      if ( charcode <= end )
1115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1116055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        FT_Byte*  r;
1117055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1118055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1119055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        r       = q - 2 + num_segs2;
1120055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        delta   = TT_PEEK_SHORT( r );
1121055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        r      += num_segs2;
1122055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        offset  = TT_PEEK_USHORT( r );
1123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1124055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        /* some fonts have an incorrect last segment; */
1125055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        /* we have to catch it                        */
1126055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        if ( i >= num_segs - 1                  &&
1127055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin             start == 0xFFFFU && end == 0xFFFFU )
1128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1129055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          if ( offset && r + offset + 2 > limit )
113077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          {
1131055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            delta  = 1;
1132055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            offset = 0;
1133055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          }
1134055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        }
113577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
1136055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        if ( offset == 0xFFFFU )
1137055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          continue;
113877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
1139055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        if ( offset )
1140055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        {
1141055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          r += offset + ( charcode - start ) * 2;
114277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
1143055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          /* if r > limit, the whole segment is invalid */
1144055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          if ( next && r > limit )
1145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            continue;
1146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1147055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          gindex = TT_PEEK_USHORT( r );
1148055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          if ( gindex )
1149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1150055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU;
1151055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            if ( gindex >= (FT_UInt)face->root.num_glyphs )
1152055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin              gindex = 0;
1153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1154055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        }
1155055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        else
1156055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        {
1157055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU;
1158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1159055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          if ( next && gindex >= (FT_UInt)face->root.num_glyphs )
1160055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          {
1161055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            /* we have an invalid glyph index; if there is an overflow, */
1162055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            /* we can adjust `charcode', otherwise the whole segment is */
1163055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            /* invalid                                                  */
1164055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            gindex = 0;
1165055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1166055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            if ( (FT_Int)charcode + delta < 0 &&
1167055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                 (FT_Int)end + delta >= 0     )
1168055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin              charcode = (FT_UInt)( -delta );
1169055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1170055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            else if ( (FT_Int)charcode + delta < 0x10000L &&
1171055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                      (FT_Int)end + delta >= 0x10000L     )
1172055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin              charcode = (FT_UInt)( 0x10000L - delta );
1173055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1174055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            else
1175055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin              continue;
1176055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          }
1177055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        }
1178055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1179055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        if ( next && !gindex )
1180055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        {
1181055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          if ( charcode >= 0xFFFFU )
1182055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            break;
1183055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1184055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          charcode++;
1185055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          goto Again;
1186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
1189055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      }
1190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1192055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    if ( next )
1193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      *pcharcode = charcode;
1194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
1196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_UInt
120077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  tt_cmap4_char_map_binary( TT_CMap     cmap,
120177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner                            FT_UInt32*  pcharcode,
120277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner                            FT_Bool     next )
1203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1204055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    TT_Face   face  = (TT_Face)cmap->cmap.charmap.face;
1205055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    FT_Byte*  limit = face->cmap_table + face->cmap_size;
1206055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   num_segs2, start, end, offset;
1208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int    delta;
1209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   max, min, mid, num_segs;
1210295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt   charcode = (FT_UInt)*pcharcode;
1211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   gindex   = 0;
1212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p;
1213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p = cmap->data + 6;
1216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );
1217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !num_segs2 )
1219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
1220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_segs = num_segs2 >> 1;
1222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* make compiler happy */
1224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    mid = num_segs;
1225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    end = 0xFFFFU;
1226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( next )
1228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      charcode++;
1229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    min = 0;
1231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    max = num_segs;
1232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* binary search */
1234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( min < max )
1235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mid    = ( min + max ) >> 1;
1237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p      = cmap->data + 14 + mid * 2;
1238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      end    = TT_PEEK_USHORT( p );
1239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p     += 2 + num_segs2;
1240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start  = TT_PEEK_USHORT( p );
1241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( charcode < start )
1243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        max = mid;
1244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( charcode > end )
1245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        min = mid + 1;
1246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p     += num_segs2;
1249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        delta  = TT_PEEK_SHORT( p );
1250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        p     += num_segs2;
1251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        offset = TT_PEEK_USHORT( p );
1252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
125377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        /* some fonts have an incorrect last segment; */
125477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        /* we have to catch it                        */
125577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        if ( mid >= num_segs - 1                &&
125677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner             start == 0xFFFFU && end == 0xFFFFU )
125777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        {
125877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          if ( offset && p + offset + 2 > limit )
125977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          {
126077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner            delta  = 1;
126177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner            offset = 0;
126277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner          }
126377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner        }
126477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner
1265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* search the first segment containing `charcode' */
1266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( cmap->flags & TT_CMAP_FLAG_OVERLAPPING )
1267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt  i;
1269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* call the current segment `max' */
1272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          max = mid;
1273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( offset == 0xFFFFU )
1275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            mid = max + 1;
1276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* search in segments before the current segment */
1278055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          for ( i = max; i > 0; i-- )
1279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_UInt   prev_end;
1281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Byte*  old_p;
1282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            old_p    = p;
1285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p        = cmap->data + 14 + ( i - 1 ) * 2;
1286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            prev_end = TT_PEEK_USHORT( p );
1287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( charcode > prev_end )
1289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p = old_p;
1291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
1292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            end    = prev_end;
1295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p     += 2 + num_segs2;
1296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            start  = TT_PEEK_USHORT( p );
1297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p     += num_segs2;
1298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta  = TT_PEEK_SHORT( p );
1299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p     += num_segs2;
1300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            offset = TT_PEEK_USHORT( p );
1301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( offset != 0xFFFFU )
1303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              mid = i - 1;
1304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* no luck */
1307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( mid == max + 1 )
1308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( i != max )
1310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p      = cmap->data + 14 + max * 2;
1312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              end    = TT_PEEK_USHORT( p );
1313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p     += 2 + num_segs2;
1314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              start  = TT_PEEK_USHORT( p );
1315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p     += num_segs2;
1316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              delta  = TT_PEEK_SHORT( p );
1317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p     += num_segs2;
1318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              offset = TT_PEEK_USHORT( p );
1319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            mid = max;
1322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* search in segments after the current segment */
1324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            for ( i = max + 1; i < num_segs; i++ )
1325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_UInt  next_end, next_start;
1327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p          = cmap->data + 14 + i * 2;
1330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              next_end   = TT_PEEK_USHORT( p );
1331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p         += 2 + num_segs2;
1332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              next_start = TT_PEEK_USHORT( p );
1333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( charcode < next_start )
1335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                break;
1336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              end    = next_end;
1338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              start  = next_start;
1339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p     += num_segs2;
1340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              delta  = TT_PEEK_SHORT( p );
1341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              p     += num_segs2;
1342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              offset = TT_PEEK_USHORT( p );
1343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( offset != 0xFFFFU )
1345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                mid = i;
1346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            i--;
1348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* still no luck */
1350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( mid == max )
1351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              mid = i;
1353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              break;
1355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* end, start, delta, and offset are for the i'th segment */
1359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( mid != i )
1360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p      = cmap->data + 14 + mid * 2;
1362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            end    = TT_PEEK_USHORT( p );
1363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p     += 2 + num_segs2;
1364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            start  = TT_PEEK_USHORT( p );
1365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p     += num_segs2;
1366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            delta  = TT_PEEK_SHORT( p );
1367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            p     += num_segs2;
1368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            offset = TT_PEEK_USHORT( p );
1369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( offset == 0xFFFFU )
1374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
1375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( offset )
1378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p += offset + ( charcode - start ) * 2;
1380055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1381055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          /* if p > limit, the whole segment is invalid */
1382055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          if ( next && p > limit )
1383055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            break;
1384055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          gindex = TT_PEEK_USHORT( p );
1386055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          if ( gindex )
1387055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          {
1388fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU;
1389055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            if ( gindex >= (FT_UInt)face->root.num_glyphs )
1390055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin              gindex = 0;
1391055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          }
1392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1394055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        {
1395fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU;
1396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1397055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          if ( next && gindex >= (FT_UInt)face->root.num_glyphs )
1398055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          {
1399055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            /* we have an invalid glyph index; if there is an overflow, */
1400055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            /* we can adjust `charcode', otherwise the whole segment is */
1401055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            /* invalid                                                  */
1402055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            gindex = 0;
1403055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1404055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            if ( (FT_Int)charcode + delta < 0 &&
1405055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                 (FT_Int)end + delta >= 0     )
1406055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin              charcode = (FT_UInt)( -delta );
1407055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1408055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            else if ( (FT_Int)charcode + delta < 0x10000L &&
1409055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                      (FT_Int)end + delta >= 0x10000L     )
1410055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin              charcode = (FT_UInt)( 0x10000L - delta );
1411055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          }
1412055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        }
1413055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
1415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( next )
1419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TT_CMap4  cmap4 = (TT_CMap4)cmap;
1421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* if `charcode' is not in any segment, then `mid' is */
1424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* the segment nearest to `charcode'                  */
1425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( charcode > end )
1427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        mid++;
1429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( mid == num_segs )
1430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          return 0;
1431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tt_cmap4_set_range( cmap4, mid ) )
1434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( gindex )
1436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          *pcharcode = charcode;
1437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cmap4->cur_charcode = charcode;
1441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( gindex )
1443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cmap4->cur_gindex = gindex;
1444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cmap4->cur_charcode = charcode;
1447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          tt_cmap4_next( cmap4 );
1448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          gindex = cmap4->cur_gindex;
1449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( gindex )
1452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          *pcharcode = cmap4->cur_charcode;
1453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
1457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
1461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap4_char_index( TT_CMap    cmap,
1462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_UInt32  char_code )
1463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( char_code >= 0x10000UL )
1465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
1466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( cmap->flags & TT_CMAP_FLAG_UNSORTED )
1468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return tt_cmap4_char_map_linear( cmap, &char_code, 0 );
1469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return tt_cmap4_char_map_binary( cmap, &char_code, 0 );
1471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1474295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_UInt32 )
1475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap4_char_next( TT_CMap     cmap,
1476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_UInt32  *pchar_code )
1477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt  gindex;
1479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( *pchar_code >= 0xFFFFU )
1482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
1483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( cmap->flags & TT_CMAP_FLAG_UNSORTED )
1485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      gindex = tt_cmap4_char_map_linear( cmap, pchar_code, 1 );
1486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TT_CMap4  cmap4 = (TT_CMap4)cmap;
1489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* no need to search */
1492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( *pchar_code == cmap4->cur_charcode )
1493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tt_cmap4_next( cmap4 );
1495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gindex = cmap4->cur_gindex;
1496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( gindex )
1497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          *pchar_code = cmap4->cur_charcode;
1498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gindex = tt_cmap4_char_map_binary( cmap, pchar_code, 1 );
1501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
1504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
1508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap4_get_info( TT_CMap       cmap,
1509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     TT_CMapInfo  *cmap_info )
1510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = cmap->data + 4;
1512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1514295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap_info->format   = 4;
1515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
1516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1517727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
1518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1521727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  FT_DEFINE_TT_CMAP(
1522727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    tt_cmap4_class_rec,
1523727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
1524a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      sizeof ( TT_CMap4Rec ),
1525a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1526a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_InitFunc)     tt_cmap4_init,        /* init       */
1527a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_DoneFunc)     NULL,                 /* done       */
1528a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharIndexFunc)tt_cmap4_char_index,  /* char_index */
1529a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharNextFunc) tt_cmap4_char_next,   /* char_next  */
1530a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1531a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
1532a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
1533a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
1534a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
1535a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
1536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    4,
1538a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    (TT_CMap_ValidateFunc)tt_cmap4_validate,  /* validate      */
1539a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    (TT_CMap_Info_GetFunc)tt_cmap4_get_info   /* get_cmap_info */
1540a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  )
1541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* TT_CONFIG_CMAP_FORMAT_4 */
1543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                          FORMAT 6                             *****/
1549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* TABLE OVERVIEW                                                        */
1556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* --------------                                                        */
1557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME        OFFSET          TYPE             DESCRIPTION            */
1559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1560055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  /*   format       0              USHORT           must be 6              */
1561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   length       2              USHORT           table length in bytes  */
1562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   language     4              USHORT           Mac language code      */
1563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   first        6              USHORT           first segment code     */
1565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   count        8              USHORT           segment size in chars  */
156677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /*   glyphIds     10             USHORT[count]    glyph IDs              */
1567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* A very simplified segment mapping.                                    */
1569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_6
1572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
1574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap6_validate( FT_Byte*      table,
1575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Validator  valid )
1576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p;
1578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   length, count;
1579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + 10 > valid->limit )
1582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
1583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p      = table + 2;
1585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    length = TT_NEXT_USHORT( p );
1586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p      = table + 8;             /* skip language and start index */
1588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    count  = TT_NEXT_USHORT( p );
1589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + length > valid->limit || length < 10 + count * 2 )
1591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
1592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* check glyph indices */
1594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( valid->level >= FT_VALIDATE_TIGHT )
1595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  gindex;
1597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; count > 0; count-- )
1600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gindex = TT_NEXT_USHORT( p );
1602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
1603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_GLYPH_ID;
1604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1607727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
1608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
1612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap6_char_index( TT_CMap    cmap,
1613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_UInt32  char_code )
1614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  table  = cmap->data;
1616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   result = 0;
1617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p      = table + 6;
1618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   start  = TT_NEXT_USHORT( p );
1619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   count  = TT_NEXT_USHORT( p );
1620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   idx    = (FT_UInt)( char_code - start );
1621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( idx < count )
1624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p += 2 * idx;
1626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = TT_PEEK_USHORT( p );
1627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1628055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return result;
1630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1633295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_UInt32 )
1634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap6_char_next( TT_CMap     cmap,
1635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_UInt32  *pchar_code )
1636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   table     = cmap->data;
1638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  result    = 0;
1639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  char_code = *pchar_code + 1;
1640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    gindex    = 0;
1641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p         = table + 6;
1643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    start     = TT_NEXT_USHORT( p );
1644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    count     = TT_NEXT_USHORT( p );
1645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    idx;
1646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( char_code >= 0x10000UL )
1649055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      return 0;
1650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( char_code < start )
1652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      char_code = start;
1653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    idx = (FT_UInt)( char_code - start );
1655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p  += 2 * idx;
1656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; idx < count; idx++ )
1658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      gindex = TT_NEXT_USHORT( p );
1660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( gindex != 0 )
1661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        result = char_code;
1663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
1664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1665055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1666055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      if ( char_code >= 0xFFFFU )
1667055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        return 0;
1668055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      char_code++;
1670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *pchar_code = result;
1673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
1674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
1678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap6_get_info( TT_CMap       cmap,
1679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     TT_CMapInfo  *cmap_info )
1680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = cmap->data + 4;
1682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1684295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap_info->format   = 6;
1685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
1686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1687727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
1688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1691727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  FT_DEFINE_TT_CMAP(
1692727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    tt_cmap6_class_rec,
1693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1694a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      sizeof ( TT_CMapRec ),
1695727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
1696a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_InitFunc)     tt_cmap_init,         /* init       */
1697a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_DoneFunc)     NULL,                 /* done       */
1698a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharIndexFunc)tt_cmap6_char_index,  /* char_index */
1699a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharNextFunc) tt_cmap6_char_next,   /* char_next  */
1700a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1701a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
1702a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
1703a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
1704a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
1705a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
1706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    6,
1708a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    (TT_CMap_ValidateFunc)tt_cmap6_validate,  /* validate      */
1709a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    (TT_CMap_Info_GetFunc)tt_cmap6_get_info   /* get_cmap_info */
1710a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  )
1711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* TT_CONFIG_CMAP_FORMAT_6 */
1713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                          FORMAT 8                             *****/
1719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
172077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /***** It is hard to completely understand what the OpenType spec    *****/
1721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** says about this format, but here is my conclusion.            *****/
1722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** The purpose of this format is to easily map UTF-16 text to    *****/
1724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** glyph indices.  Basically, the `char_code' must be in one of  *****/
1725055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  /***** the following formats.                                        *****/
1726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   - A 16-bit value that isn't part of the Unicode Surrogates  *****/
1728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****     Area (i.e. U+D800-U+DFFF).                                *****/
1729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   - A 32-bit value, made of two surrogate values, i.e.. if    *****/
1731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****     `char_code = (char_hi << 16) | char_lo', then both        *****/
1732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****     `char_hi' and `char_lo' must be in the Surrogates Area.   *****/
1733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****      Area.                                                    *****/
1734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
173577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /***** The `is32' table embedded in the charmap indicates whether a  *****/
1736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /***** given 16-bit value is in the surrogates area or not.          *****/
1737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1738055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  /***** So, for any given `char_code', we can assert the following.   *****/
1739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   If `char_hi == 0' then we must have `is32[char_lo] == 0'.   *****/
1741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   If `char_hi != 0' then we must have both                    *****/
1743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****   `is32[char_hi] != 0' and `is32[char_lo] != 0'.              *****/
1744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* TABLE OVERVIEW                                                        */
1751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* --------------                                                        */
1752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME        OFFSET         TYPE        DESCRIPTION                  */
1754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   format      0              USHORT      must be 8                    */
1756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   reserved    2              USHORT      reserved                     */
1757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   length      4              ULONG       length in bytes              */
1758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   language    8              ULONG       Mac language code            */
1759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   is32        12             BYTE[8192]  32-bitness bitmap            */
1760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   count       8204           ULONG       number of groups             */
1761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
176277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /* This header is followed by `count' groups of the following format:    */
1763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   start       0              ULONG       first charcode               */
1765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   end         4              ULONG       last charcode                */
176677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /*   startId     8              ULONG       start glyph ID for the group */
1767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_8
1770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
1772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap8_validate( FT_Byte*      table,
1773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Validator  valid )
1774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p = table + 4;
1776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   is32;
1777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  length;
1778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  num_groups;
1779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + 16 + 8192 > valid->limit )
1782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
1783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    length = TT_NEXT_ULONG( p );
1785295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( length > (FT_UInt32)( valid->limit - table ) || length < 8192 + 16 )
1786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
1787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    is32       = table + 12;
1789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p          = is32  + 8192;          /* skip `is32' array */
1790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_groups = TT_NEXT_ULONG( p );
1791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1792fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    /* p + num_groups * 12 > valid->limit ? */
1793fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( num_groups > (FT_UInt32)( valid->limit - p ) / 12 )
1794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
1795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* check groups, they must be in increasing order */
1797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  n, start, end, start_id, count, last = 0;
1799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( n = 0; n < num_groups; n++ )
1802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt   hi, lo;
1804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        start    = TT_NEXT_ULONG( p );
1807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        end      = TT_NEXT_ULONG( p );
1808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        start_id = TT_NEXT_ULONG( p );
1809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( start > end )
1811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_DATA;
1812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( n > 0 && start <= last )
1814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_DATA;
1815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( valid->level >= FT_VALIDATE_TIGHT )
1817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1818fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          FT_UInt32  d = end - start;
1819fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1820fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1821fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          /* start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ? */
1822fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          if ( d > TT_VALID_GLYPH_COUNT( valid )             ||
1823fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki               start_id >= TT_VALID_GLYPH_COUNT( valid ) - d )
1824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_INVALID_GLYPH_ID;
1825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          count = (FT_UInt32)( end - start + 1 );
1827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( start & ~0xFFFFU )
1829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* start_hi != 0; check that is32[i] is 1 for each i in */
1831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* the `hi' and `lo' of the range [start..end]          */
1832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            for ( ; count > 0; count--, start++ )
1833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              hi = (FT_UInt)( start >> 16 );
1835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              lo = (FT_UInt)( start & 0xFFFFU );
1836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 )
1838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                FT_INVALID_DATA;
1839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 )
1841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                FT_INVALID_DATA;
1842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          else
1845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* start_hi == 0; check that is32[i] is 0 for each i in */
1847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* the range [start..end]                               */
1848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            /* end_hi cannot be != 0! */
1850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( end & ~0xFFFFU )
1851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_INVALID_DATA;
1852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            for ( ; count > 0; count--, start++ )
1854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              lo = (FT_UInt)( start & 0xFFFFU );
1856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 )
1858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                FT_INVALID_DATA;
1859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        last = end;
1864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1867727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
1868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
1872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap8_char_index( TT_CMap    cmap,
1873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_UInt32  char_code )
1874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   table      = cmap->data;
1876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    result     = 0;
1877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p          = table + 8204;
1878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  num_groups = TT_NEXT_ULONG( p );
1879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  start, end, start_id;
1880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; num_groups > 0; num_groups-- )
1883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start    = TT_NEXT_ULONG( p );
1885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      end      = TT_NEXT_ULONG( p );
1886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start_id = TT_NEXT_ULONG( p );
1887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code < start )
1889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
1890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code <= end )
1892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1893055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) )
1894055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          return 0;
1895055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1896055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        result = (FT_UInt)( start_id + ( char_code - start ) );
1897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
1898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return result;
1901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1904295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_UInt32 )
1905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap8_char_next( TT_CMap     cmap,
1906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_UInt32  *pchar_code )
1907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1908055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    FT_Face    face       = cmap->cmap.charmap.face;
1909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  result     = 0;
1910055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    FT_UInt32  char_code;
1911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    gindex     = 0;
1912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   table      = cmap->data;
1913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p          = table + 8204;
1914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  num_groups = TT_NEXT_ULONG( p );
1915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  start, end, start_id;
1916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1918055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    if ( *pchar_code >= 0xFFFFFFFFUL )
1919055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      return 0;
1920055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1921055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    char_code = *pchar_code + 1;
1922055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p = table + 8208;
1924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; num_groups > 0; num_groups-- )
1926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start    = TT_NEXT_ULONG( p );
1928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      end      = TT_NEXT_ULONG( p );
1929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start_id = TT_NEXT_ULONG( p );
1930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code < start )
1932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        char_code = start;
1933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1934055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    Again:
1935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code <= end )
1936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1937055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        /* ignore invalid group */
1938055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) )
1939055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          continue;
1940055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1941055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        gindex = (FT_UInt)( start_id + ( char_code - start ) );
1942055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1943055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        /* does first element of group point to `.notdef' glyph? */
1944055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        if ( gindex == 0 )
1945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1946055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          if ( char_code >= 0xFFFFFFFFUL )
1947055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            break;
1948055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1949055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          char_code++;
1950055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          goto Again;
1951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1952055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1953055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        /* if `gindex' is invalid, the remaining values */
1954055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        /* in this group are invalid, too               */
1955055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        if ( gindex >= (FT_UInt)face->num_glyphs )
1956055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        {
1957055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          gindex = 0;
1958055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          continue;
1959055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        }
1960055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1961055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        result = char_code;
1962055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        break;
1963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *pchar_code = result;
1967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
1968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
1972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap8_get_info( TT_CMap       cmap,
1973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     TT_CMapInfo  *cmap_info )
1974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = cmap->data + 8;
1976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1978295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap_info->format   = 8;
1979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
1980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1981727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
1982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1985727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  FT_DEFINE_TT_CMAP(
1986727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    tt_cmap8_class_rec,
1987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1988a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      sizeof ( TT_CMapRec ),
1989727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
1990a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_InitFunc)     tt_cmap_init,         /* init       */
1991a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_DoneFunc)     NULL,                 /* done       */
1992a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharIndexFunc)tt_cmap8_char_index,  /* char_index */
1993a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharNextFunc) tt_cmap8_char_next,   /* char_next  */
1994a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1995a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
1996a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
1997a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
1998a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
1999a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
2000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    8,
2002a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    (TT_CMap_ValidateFunc)tt_cmap8_validate,  /* validate      */
2003a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    (TT_CMap_Info_GetFunc)tt_cmap8_get_info   /* get_cmap_info */
2004a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  )
2005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* TT_CONFIG_CMAP_FORMAT_8 */
2007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
2012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                          FORMAT 10                            *****/
2013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
2014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* TABLE OVERVIEW                                                        */
2020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* --------------                                                        */
2021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME      OFFSET  TYPE               DESCRIPTION                    */
2023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   format     0      USHORT             must be 10                     */
2025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   reserved   2      USHORT             reserved                       */
2026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   length     4      ULONG              length in bytes                */
2027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   language   8      ULONG              Mac language code              */
2028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   start     12      ULONG              first char in range            */
2030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   count     16      ULONG              number of chars in range       */
2031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   glyphIds  20      USHORT[count]      glyph indices covered          */
2032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_10
2035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
2037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap10_validate( FT_Byte*      table,
2038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Validator  valid )
2039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = table + 4;
2041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  length, count;
2042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + 20 > valid->limit )
2045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
2046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    length = TT_NEXT_ULONG( p );
2048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p      = table + 16;
2049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    count  = TT_NEXT_ULONG( p );
2050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2051295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( length > (FT_ULong)( valid->limit - table ) ||
2052fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki         /* length < 20 + count * 2 ? */
2053fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki         length < 20                                 ||
2054fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki         ( length - 20 ) / 2 < count                 )
2055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
2056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* check glyph indices */
2058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( valid->level >= FT_VALIDATE_TIGHT )
2059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  gindex;
2061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; count > 0; count-- )
2064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gindex = TT_NEXT_USHORT( p );
2066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
2067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_GLYPH_ID;
2068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2071727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
2072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
2076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap10_char_index( TT_CMap    cmap,
2077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        FT_UInt32  char_code )
2078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   table  = cmap->data;
2080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    result = 0;
2081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p      = table + 12;
2082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  start  = TT_NEXT_ULONG( p );
2083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  count  = TT_NEXT_ULONG( p );
2084055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    FT_UInt32  idx;
2085055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
2086055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
2087055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    if ( char_code < start )
2088055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      return 0;
2089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2090055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    idx = char_code - start;
2091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( idx < count )
2093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p     += 2 * idx;
2095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      result = TT_PEEK_USHORT( p );
2096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2097055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
2098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return result;
2099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2102295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_UInt32 )
2103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap10_char_next( TT_CMap     cmap,
2104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_UInt32  *pchar_code )
2105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   table     = cmap->data;
2107055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    FT_UInt32  char_code;
2108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    gindex    = 0;
2109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p         = table + 12;
2110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  start     = TT_NEXT_ULONG( p );
2111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  count     = TT_NEXT_ULONG( p );
2112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  idx;
2113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2115055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    if ( *pchar_code >= 0xFFFFFFFFUL )
2116055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      return 0;
2117055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
2118055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    char_code = *pchar_code + 1;
2119055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
2120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( char_code < start )
2121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      char_code = start;
2122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2123055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    idx = char_code - start;
2124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p  += 2 * idx;
2125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; idx < count; idx++ )
2127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      gindex = TT_NEXT_USHORT( p );
2129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( gindex != 0 )
2130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
2131055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
2132055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      if ( char_code >= 0xFFFFFFFFUL )
2133055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        return 0;
2134055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
2135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      char_code++;
2136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *pchar_code = char_code;
2139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
2140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
2144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap10_get_info( TT_CMap       cmap,
2145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      TT_CMapInfo  *cmap_info )
2146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = cmap->data + 8;
2148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2150295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap_info->format   = 10;
2151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
2152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2153727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
2154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2157727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  FT_DEFINE_TT_CMAP(
2158727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    tt_cmap10_class_rec,
2159727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
2160a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      sizeof ( TT_CMapRec ),
2161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2162a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_InitFunc)     tt_cmap_init,          /* init       */
2163a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_DoneFunc)     NULL,                  /* done       */
2164a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharIndexFunc)tt_cmap10_char_index,  /* char_index */
2165a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharNextFunc) tt_cmap10_char_next,   /* char_next  */
2166a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2167a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
2168a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
2169a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
2170a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
2171a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
2172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    10,
2174a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    (TT_CMap_ValidateFunc)tt_cmap10_validate,  /* validate      */
2175a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    (TT_CMap_Info_GetFunc)tt_cmap10_get_info   /* get_cmap_info */
2176a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  )
2177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* TT_CONFIG_CMAP_FORMAT_10 */
2179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
2184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                          FORMAT 12                            *****/
2185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
2186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* TABLE OVERVIEW                                                        */
2192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* --------------                                                        */
2193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME        OFFSET     TYPE       DESCRIPTION                       */
2195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   format      0          USHORT     must be 12                        */
2197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   reserved    2          USHORT     reserved                          */
2198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   length      4          ULONG      length in bytes                   */
2199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   language    8          ULONG      Mac language code                 */
2200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   count       12         ULONG      number of groups                  */
2201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*               16                                                      */
2202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* This header is followed by `count' groups of the following format:    */
2204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   start       0          ULONG      first charcode                    */
2206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   end         4          ULONG      last charcode                     */
220777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  /*   startId     8          ULONG      start glyph ID for the group      */
2208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_12
2211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef struct  TT_CMap12Rec_
2213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMapRec  cmap;
2215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Bool     valid;
2216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    cur_charcode;
2217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     cur_gindex;
2218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    cur_group;
2219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    num_groups;
2220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  } TT_CMap12Rec, *TT_CMap12;
2222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
2225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap12_init( TT_CMap12  cmap,
2226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_Byte*   table )
2227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->cmap.data  = table;
2229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    table           += 12;
2231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->num_groups = FT_PEEK_ULONG( table );
2232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->valid      = 0;
2234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2235727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
2236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
2240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap12_validate( FT_Byte*      table,
2241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Validator  valid )
2242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
22439c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_Byte*  p;
22449c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_ULong  length;
22459c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_ULong  num_groups;
2246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( table + 16 > valid->limit )
2249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
2250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p      = table + 4;
2252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    length = TT_NEXT_ULONG( p );
2253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p          = table + 12;
2255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_groups = TT_NEXT_ULONG( p );
2256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2257295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( length > (FT_ULong)( valid->limit - table ) ||
2258fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki         /* length < 16 + 12 * num_groups ? */
2259fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki         length < 16                                 ||
2260fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki         ( length - 16 ) / 12 < num_groups           )
2261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
2262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* check groups, they must be in increasing order */
2264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ULong  n, start, end, start_id, last = 0;
2266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( n = 0; n < num_groups; n++ )
2269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        start    = TT_NEXT_ULONG( p );
2271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        end      = TT_NEXT_ULONG( p );
2272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        start_id = TT_NEXT_ULONG( p );
2273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( start > end )
2275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_DATA;
2276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( n > 0 && start <= last )
2278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_DATA;
2279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( valid->level >= FT_VALIDATE_TIGHT )
2281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2282fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          FT_UInt32  d = end - start;
2283fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2284fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2285fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          /* start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ? */
2286fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          if ( d > TT_VALID_GLYPH_COUNT( valid )             ||
2287fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki               start_id >= TT_VALID_GLYPH_COUNT( valid ) - d )
2288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_INVALID_GLYPH_ID;
2289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        last = end;
2292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2295727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
2296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* search the index of the charcode next to cmap->cur_charcode */
2300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* cmap->cur_group should be set up properly by caller         */
2301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                             */
2302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
2303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap12_next( TT_CMap12  cmap )
2304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2305055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    FT_Face   face = cmap->cmap.cmap.charmap.face;
2306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p;
2307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  start, end, start_id, char_code;
2308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  n;
2309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   gindex;
2310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
2313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Fail;
2314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    char_code = cmap->cur_charcode + 1;
2316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
2318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p        = cmap->cmap.data + 16 + 12 * n;
2320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start    = TT_NEXT_ULONG( p );
2321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      end      = TT_NEXT_ULONG( p );
2322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start_id = TT_PEEK_ULONG( p );
2323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code < start )
2325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        char_code = start;
2326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2327055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    Again:
2328055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      if ( char_code <= end )
2329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2330055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        /* ignore invalid group */
2331055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) )
2332055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          continue;
2333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2334055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        gindex = (FT_UInt)( start_id + ( char_code - start ) );
2335055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
2336055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        /* does first element of group point to `.notdef' glyph? */
2337055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        if ( gindex == 0 )
2338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2339055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          if ( char_code >= 0xFFFFFFFFUL )
2340055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            goto Fail;
2341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2342055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          char_code++;
2343055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          goto Again;
2344055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        }
2345055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
2346055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        /* if `gindex' is invalid, the remaining values */
2347055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        /* in this group are invalid, too               */
2348055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        if ( gindex >= (FT_UInt)face->num_glyphs )
2349055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        {
2350055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          gindex = 0;
2351055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          continue;
2352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2353055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
2354055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        cmap->cur_charcode = char_code;
2355055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        cmap->cur_gindex   = gindex;
2356055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        cmap->cur_group    = n;
2357055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
2358055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        return;
2359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Fail:
2363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->valid = 0;
2364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_UInt
2368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap12_char_map_binary( TT_CMap     cmap,
2369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             FT_UInt32*  pchar_code,
2370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             FT_Bool     next )
2371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    gindex     = 0;
2373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*   p          = cmap->data + 12;
2374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  num_groups = TT_PEEK_ULONG( p );
2375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  char_code  = *pchar_code;
2376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  start, end, start_id;
2377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  max, min, mid;
2378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !num_groups )
2381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
2382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* make compiler happy */
2384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    mid = num_groups;
2385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    end = 0xFFFFFFFFUL;
2386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( next )
2388055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    {
2389055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      if ( char_code >= 0xFFFFFFFFUL )
2390055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        return 0;
2391055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
2392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      char_code++;
2393055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    }
2394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    min = 0;
2396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    max = num_groups;
2397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* binary search */
2399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( min < max )
2400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mid = ( min + max ) >> 1;
2402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p   = cmap->data + 16 + 12 * mid;
2403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      start = TT_NEXT_ULONG( p );
2405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      end   = TT_NEXT_ULONG( p );
2406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code < start )
2408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        max = mid;
2409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( char_code > end )
2410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        min = mid + 1;
2411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
2412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        start_id = TT_PEEK_ULONG( p );
2414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2415055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        /* reject invalid glyph index */
2416055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) )
2417055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          gindex = 0;
2418055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        else
2419055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          gindex = (FT_UInt)( start_id + ( char_code - start ) );
2420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
2421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( next )
2425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2426055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      FT_Face    face   = cmap->cmap.charmap.face;
2427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TT_CMap12  cmap12 = (TT_CMap12)cmap;
2428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* if `char_code' is not in any group, then `mid' is */
2431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* the group nearest to `char_code'                  */
2432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code > end )
2434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        mid++;
2436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( mid == num_groups )
2437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          return 0;
2438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cmap12->valid        = 1;
2441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cmap12->cur_charcode = char_code;
2442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cmap12->cur_group    = mid;
2443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2444055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      if ( gindex >= (FT_UInt)face->num_glyphs )
2445055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        gindex = 0;
2446055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
2447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !gindex )
2448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tt_cmap12_next( cmap12 );
2450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( cmap12->valid )
2452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          gindex = cmap12->cur_gindex;
2453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
2455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cmap12->cur_gindex = gindex;
2456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2457055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      *pchar_code = cmap12->cur_charcode;
2458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return gindex;
2461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
2465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap12_char_index( TT_CMap    cmap,
2466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        FT_UInt32  char_code )
2467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return tt_cmap12_char_map_binary( cmap, &char_code, 0 );
2469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2472295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_UInt32 )
2473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap12_char_next( TT_CMap     cmap,
2474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_UInt32  *pchar_code )
2475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMap12  cmap12 = (TT_CMap12)cmap;
2477055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    FT_UInt    gindex;
2478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* no need to search */
2481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( cmap12->valid && cmap12->cur_charcode == *pchar_code )
2482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      tt_cmap12_next( cmap12 );
2484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( cmap12->valid )
2485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2486055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        gindex      = cmap12->cur_gindex;
2487055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        *pchar_code = (FT_UInt32)cmap12->cur_charcode;
2488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
2490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gindex = 0;
2491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
2493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 );
2494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2495055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    return gindex;
2496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
2500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap12_get_info( TT_CMap       cmap,
2501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      TT_CMapInfo  *cmap_info )
2502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = cmap->data + 8;
2504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2506295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap_info->format   = 12;
2507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
2508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2509727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
2510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2513727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  FT_DEFINE_TT_CMAP(
2514727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    tt_cmap12_class_rec,
2515727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
2516a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      sizeof ( TT_CMap12Rec ),
2517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2518a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_InitFunc)     tt_cmap12_init,        /* init       */
2519a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_DoneFunc)     NULL,                  /* done       */
2520a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharIndexFunc)tt_cmap12_char_index,  /* char_index */
2521a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharNextFunc) tt_cmap12_char_next,   /* char_next  */
2522a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2523a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
2524a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
2525a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
2526a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
2527a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
2528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    12,
2530a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    (TT_CMap_ValidateFunc)tt_cmap12_validate,  /* validate      */
2531a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    (TT_CMap_Info_GetFunc)tt_cmap12_get_info   /* get_cmap_info */
2532a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  )
2533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* TT_CONFIG_CMAP_FORMAT_12 */
2535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
2540295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*****                          FORMAT 13                            *****/
2541295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*****                                                               *****/
2542295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*************************************************************************/
2543295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*************************************************************************/
2544295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2545295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*************************************************************************/
2546295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
2547295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* TABLE OVERVIEW                                                        */
2548295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* --------------                                                        */
2549295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
2550295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*   NAME        OFFSET     TYPE       DESCRIPTION                       */
2551295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
2552295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*   format      0          USHORT     must be 13                        */
2553295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*   reserved    2          USHORT     reserved                          */
2554295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*   length      4          ULONG      length in bytes                   */
2555295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*   language    8          ULONG      Mac language code                 */
2556295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*   count       12         ULONG      number of groups                  */
2557295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*               16                                                      */
2558295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
2559295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* This header is followed by `count' groups of the following format:    */
2560295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
2561295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*   start       0          ULONG      first charcode                    */
2562295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*   end         4          ULONG      last charcode                     */
2563295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*   glyphId     8          ULONG      glyph ID for the whole group      */
2564295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
2565295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2566295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#ifdef TT_CONFIG_CMAP_FORMAT_13
2567295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2568295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  typedef struct  TT_CMap13Rec_
2569295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
2570295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    TT_CMapRec  cmap;
2571295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_Bool     valid;
2572295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_ULong    cur_charcode;
2573295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt     cur_gindex;
2574295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_ULong    cur_group;
2575295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_ULong    num_groups;
2576295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2577295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  } TT_CMap13Rec, *TT_CMap13;
2578295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2579295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2580295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_Error )
2581295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  tt_cmap13_init( TT_CMap13  cmap,
2582295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                  FT_Byte*   table )
2583295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
2584295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap->cmap.data  = table;
2585295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2586295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    table           += 12;
2587295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap->num_groups = FT_PEEK_ULONG( table );
2588295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2589295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap->valid      = 0;
2590295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2591727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
2592295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  }
2593295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2594295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2595295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_Error )
2596295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  tt_cmap13_validate( FT_Byte*      table,
2597295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                      FT_Validator  valid )
2598295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
2599727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Byte*  p;
2600727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_ULong  length;
2601727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_ULong  num_groups;
2602295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2603295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2604295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( table + 16 > valid->limit )
2605295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_INVALID_TOO_SHORT;
2606295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2607295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    p      = table + 4;
2608295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    length = TT_NEXT_ULONG( p );
2609295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2610295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    p          = table + 12;
2611295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    num_groups = TT_NEXT_ULONG( p );
2612295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2613295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( length > (FT_ULong)( valid->limit - table ) ||
2614fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki         /* length < 16 + 12 * num_groups ? */
2615fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki         length < 16                                 ||
2616fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki         ( length - 16 ) / 12 < num_groups           )
2617295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_INVALID_TOO_SHORT;
2618295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2619295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* check groups, they must be in increasing order */
2620295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    {
2621295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_ULong  n, start, end, glyph_id, last = 0;
2622295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2623295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2624295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      for ( n = 0; n < num_groups; n++ )
2625295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      {
2626295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        start    = TT_NEXT_ULONG( p );
2627295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        end      = TT_NEXT_ULONG( p );
2628295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        glyph_id = TT_NEXT_ULONG( p );
2629295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2630295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        if ( start > end )
2631295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          FT_INVALID_DATA;
2632295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2633295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        if ( n > 0 && start <= last )
2634295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          FT_INVALID_DATA;
2635295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2636295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        if ( valid->level >= FT_VALIDATE_TIGHT )
2637295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        {
2638295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          if ( glyph_id >= TT_VALID_GLYPH_COUNT( valid ) )
2639295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            FT_INVALID_GLYPH_ID;
2640295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        }
2641295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2642295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        last = end;
2643295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      }
2644295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    }
2645295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2646727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
2647295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  }
2648295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2649295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2650295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* search the index of the charcode next to cmap->cur_charcode */
2651295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* cmap->cur_group should be set up properly by caller         */
2652295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                             */
2653295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  static void
2654295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  tt_cmap13_next( TT_CMap13  cmap )
2655295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
2656055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    FT_Face   face = cmap->cmap.cmap.charmap.face;
2657295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_Byte*  p;
2658295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_ULong  start, end, glyph_id, char_code;
2659295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_ULong  n;
2660295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt   gindex;
2661295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2662295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2663295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
2664295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      goto Fail;
2665295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2666295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    char_code = cmap->cur_charcode + 1;
2667295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2668295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
2669295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    {
2670295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      p        = cmap->cmap.data + 16 + 12 * n;
2671295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      start    = TT_NEXT_ULONG( p );
2672295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      end      = TT_NEXT_ULONG( p );
2673295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      glyph_id = TT_PEEK_ULONG( p );
2674295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2675295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( char_code < start )
2676295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        char_code = start;
2677295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2678295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( char_code <= end )
2679295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      {
2680295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        gindex = (FT_UInt)glyph_id;
2681295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2682055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        if ( gindex && gindex < (FT_UInt)face->num_glyphs )
2683295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        {
2684055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          cmap->cur_charcode = char_code;
2685295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          cmap->cur_gindex   = gindex;
2686295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          cmap->cur_group    = n;
2687295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2688295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          return;
2689295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        }
2690295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      }
2691295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    }
2692295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2693295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  Fail:
2694295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap->valid = 0;
2695295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  }
2696295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2697295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2698295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  static FT_UInt
2699295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  tt_cmap13_char_map_binary( TT_CMap     cmap,
2700295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                             FT_UInt32*  pchar_code,
2701295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                             FT_Bool     next )
2702295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
2703295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt    gindex     = 0;
2704295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_Byte*   p          = cmap->data + 12;
2705295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt32  num_groups = TT_PEEK_ULONG( p );
2706295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt32  char_code  = *pchar_code;
2707295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt32  start, end;
2708295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt32  max, min, mid;
2709295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2710295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2711295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( !num_groups )
2712295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      return 0;
2713295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2714295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* make compiler happy */
2715295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    mid = num_groups;
2716295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    end = 0xFFFFFFFFUL;
2717295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2718295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( next )
2719055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    {
2720055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      if ( char_code >= 0xFFFFFFFFUL )
2721055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        return 0;
2722055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
2723295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      char_code++;
2724055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    }
2725295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2726295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    min = 0;
2727295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    max = num_groups;
2728295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2729295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* binary search */
2730295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    while ( min < max )
2731295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    {
2732295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      mid = ( min + max ) >> 1;
2733295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      p   = cmap->data + 16 + 12 * mid;
2734295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2735295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      start = TT_NEXT_ULONG( p );
2736295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      end   = TT_NEXT_ULONG( p );
2737295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2738295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( char_code < start )
2739295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        max = mid;
2740295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      else if ( char_code > end )
2741295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        min = mid + 1;
2742295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      else
2743295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      {
2744295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        gindex = (FT_UInt)TT_PEEK_ULONG( p );
2745295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2746295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        break;
2747295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      }
2748295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    }
2749295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2750295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( next )
2751295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    {
2752055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      FT_Face    face   = cmap->cmap.charmap.face;
2753295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      TT_CMap13  cmap13 = (TT_CMap13)cmap;
2754295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2755295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2756295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      /* if `char_code' is not in any group, then `mid' is */
2757295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      /* the group nearest to `char_code'                  */
2758295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2759295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( char_code > end )
2760295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      {
2761295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        mid++;
2762295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        if ( mid == num_groups )
2763295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          return 0;
2764295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      }
2765295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2766295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      cmap13->valid        = 1;
2767295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      cmap13->cur_charcode = char_code;
2768295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      cmap13->cur_group    = mid;
2769295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2770055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      if ( gindex >= (FT_UInt)face->num_glyphs )
2771055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        gindex = 0;
2772055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
2773295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( !gindex )
2774295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      {
2775295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        tt_cmap13_next( cmap13 );
2776295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2777295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        if ( cmap13->valid )
2778295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          gindex = cmap13->cur_gindex;
2779295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      }
2780295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      else
2781295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        cmap13->cur_gindex = gindex;
2782295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2783055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      *pchar_code = cmap13->cur_charcode;
2784295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    }
2785295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2786295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    return gindex;
2787295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  }
2788295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2789295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2790295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_UInt )
2791295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  tt_cmap13_char_index( TT_CMap    cmap,
2792295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                        FT_UInt32  char_code )
2793295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
2794295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    return tt_cmap13_char_map_binary( cmap, &char_code, 0 );
2795295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  }
2796295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2797295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2798295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_UInt32 )
2799295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  tt_cmap13_char_next( TT_CMap     cmap,
2800295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                       FT_UInt32  *pchar_code )
2801295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
2802295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    TT_CMap13  cmap13 = (TT_CMap13)cmap;
2803295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt    gindex;
2804295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2805295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2806295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* no need to search */
2807295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( cmap13->valid && cmap13->cur_charcode == *pchar_code )
2808295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    {
2809295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      tt_cmap13_next( cmap13 );
2810295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      if ( cmap13->valid )
2811295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      {
2812055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        gindex      = cmap13->cur_gindex;
2813055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        *pchar_code = cmap13->cur_charcode;
2814295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      }
2815295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      else
2816295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        gindex = 0;
2817295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    }
2818295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    else
2819295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      gindex = tt_cmap13_char_map_binary( cmap, pchar_code, 1 );
2820295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2821295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    return gindex;
2822295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  }
2823295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2824295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2825295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_Error )
2826295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  tt_cmap13_get_info( TT_CMap       cmap,
2827295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                      TT_CMapInfo  *cmap_info )
2828295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
2829295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_Byte*  p = cmap->data + 8;
2830295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2831295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2832295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap_info->format   = 13;
2833295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
2834295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2835727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
2836295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  }
2837295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2838295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2839727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  FT_DEFINE_TT_CMAP(
2840727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    tt_cmap13_class_rec,
2841295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2842a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      sizeof ( TT_CMap13Rec ),
2843727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
2844a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_InitFunc)     tt_cmap13_init,        /* init       */
2845a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_DoneFunc)     NULL,                  /* done       */
2846a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharIndexFunc)tt_cmap13_char_index,  /* char_index */
2847a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharNextFunc) tt_cmap13_char_next,   /* char_next  */
2848a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2849a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
2850a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
2851a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
2852a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
2853a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
2854295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2855295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    13,
2856a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    (TT_CMap_ValidateFunc)tt_cmap13_validate,  /* validate      */
2857a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    (TT_CMap_Info_GetFunc)tt_cmap13_get_info   /* get_cmap_info */
2858a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  )
2859295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2860295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#endif /* TT_CONFIG_CMAP_FORMAT_13 */
2861295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2862295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
2863295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*************************************************************************/
2864295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*************************************************************************/
2865295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*****                                                               *****/
2866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                           FORMAT 14                           *****/
2867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
2868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* TABLE OVERVIEW                                                        */
2874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* --------------                                                        */
2875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   NAME         OFFSET  TYPE    DESCRIPTION                            */
2877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   format         0     USHORT  must be 14                             */
2879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   length         2     ULONG   table length in bytes                  */
2880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   numSelector    6     ULONG   number of variation sel. records       */
2881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Followed by numSelector records, each of which looks like             */
2883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   varSelector    0     UINT24  Unicode codepoint of sel.              */
2885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   defaultOff     3     ULONG   offset to a default UVS table          */
2886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                describing any variants to be found in */
2887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                the normal Unicode subtable.           */
2888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   nonDefOff      7     ULONG   offset to a non-default UVS table      */
2889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                describing any variants not in the     */
2890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                standard cmap, with GIDs here          */
2891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* (either offset may be 0 NULL)                                         */
2892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Selectors are sorted by code point.                                   */
2894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* A default Unicode Variation Selector (UVS) subtable is just a list of */
2896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* ranges of code points which are to be found in the standard cmap.  No */
2897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* glyph IDs (GIDs) here.                                                */
2898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   numRanges      0     ULONG   number of ranges following             */
2900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* A range looks like                                                    */
2902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   uniStart       0     UINT24  code point of the first character in   */
2904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                this range                             */
2905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   additionalCnt  3     UBYTE   count of additional characters in this */
2906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                range (zero means a range of a single  */
2907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                character)                             */
2908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Ranges are sorted by `uniStart'.                                      */
2910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* A non-default Unicode Variation Selector (UVS) subtable is a list of  */
2912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* mappings from codepoint to GID.                                       */
2913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   numMappings    0     ULONG   number of mappings                     */
2915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* A range looks like                                                    */
2917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   uniStart       0     UINT24  code point of the first character in   */
2919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                this range                             */
2920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   GID            3     USHORT  and its GID                            */
2921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Ranges are sorted by `uniStart'.                                      */
2923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_CMAP_FORMAT_14
2925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef struct  TT_CMap14Rec_
2927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMapRec  cmap;
2929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    num_selectors;
2930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* This array is used to store the results of various
2932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * cmap 14 query functions.  The data is overwritten
2933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     * on each call to these functions.
2934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     */
2935295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt32   max_results;
2936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32*  results;
2937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory   memory;
2938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  } TT_CMap14Rec, *TT_CMap14;
2940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( void )
2943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_done( TT_CMap14  cmap )
2944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory  memory = cmap->memory;
2946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->max_results = 0;
2949a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( memory && cmap->results )
2950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FREE( cmap->results );
2951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
2955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_ensure( TT_CMap14  cmap,
2956295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                    FT_UInt32  num_results,
2957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    FT_Memory  memory )
2958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2959727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_UInt32  old_max = cmap->max_results;
2960727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Error   error   = FT_Err_Ok;
2961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( num_results > cmap->max_results )
2964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       cmap->memory = memory;
2966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       if ( FT_QRENEW_ARRAY( cmap->results, old_max, num_results ) )
2968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         return error;
2969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       cmap->max_results = num_results;
2971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
2974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
2978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_init( TT_CMap14  cmap,
2979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_Byte*   table )
2980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap->cmap.data = table;
2982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    table               += 6;
2984727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    cmap->num_selectors  = FT_PEEK_ULONG( table );
2985727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    cmap->max_results    = 0;
2986727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    cmap->results        = NULL;
2987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2988727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
2989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
2993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_validate( FT_Byte*      table,
2994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Validator  valid )
2995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
29969c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_Byte*  p;
29979c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_ULong  length;
29989c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_ULong  num_selectors;
29999c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
30009c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
30019c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    if ( table + 2 + 4 + 4 > valid->limit )
30029c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      FT_INVALID_TOO_SHORT;
3003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
30049c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    p             = table + 2;
30059c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    length        = TT_NEXT_ULONG( p );
30069c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    num_selectors = TT_NEXT_ULONG( p );
3007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3008295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( length > (FT_ULong)( valid->limit - table ) ||
3009fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki         /* length < 10 + 11 * num_selectors ? */
3010fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki         length < 10                                 ||
3011fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki         ( length - 10 ) / 11 < num_selectors        )
3012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_INVALID_TOO_SHORT;
3013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* check selectors, they must be in increasing order */
3015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we start lastVarSel at 1 because a variant selector value of 0
3017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       * isn't valid.
3018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       */
3019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ULong  n, lastVarSel = 1;
3020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( n = 0; n < num_selectors; n++ )
3023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
3024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_ULong  varSel    = TT_NEXT_UINT24( p );
3025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_ULong  defOff    = TT_NEXT_ULONG( p );
3026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_ULong  nondefOff = TT_NEXT_ULONG( p );
3027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( defOff >= length || nondefOff >= length )
3030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_TOO_SHORT;
3031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( varSel < lastVarSel )
3033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_INVALID_DATA;
3034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        lastVarSel = varSel + 1;
3036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* check the default table (these glyphs should be reached     */
3038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* through the normal Unicode cmap, no GIDs, just check order) */
3039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( defOff != 0 )
3040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
3041055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          FT_Byte*  defp     = table + defOff;
3042055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          FT_ULong  numRanges;
3043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_ULong  i;
3044055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          FT_ULong  lastBase = 0;
3045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3047055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          if ( defp + 4 > valid->limit )
3048055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            FT_INVALID_TOO_SHORT;
3049055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
3050055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          numRanges = TT_NEXT_ULONG( defp );
3051055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
3052fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          /* defp + numRanges * 4 > valid->limit ? */
3053fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          if ( numRanges > (FT_ULong)( valid->limit - defp ) / 4 )
3054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_INVALID_TOO_SHORT;
3055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3056a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          for ( i = 0; i < numRanges; i++ )
3057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
3058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_ULong  base = TT_NEXT_UINT24( defp );
3059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_ULong  cnt  = FT_NEXT_BYTE( defp );
3060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( base + cnt >= 0x110000UL )              /* end of Unicode */
3063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_INVALID_DATA;
3064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( base < lastBase )
3066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_INVALID_DATA;
3067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            lastBase = base + cnt + 1U;
3069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
3070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
3071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* and the non-default table (these glyphs are specified here) */
3073aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        if ( nondefOff != 0 )
3074aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        {
3075055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          FT_Byte*  ndp        = table + nondefOff;
3076055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          FT_ULong  numMappings;
3077055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          FT_ULong  i, lastUni = 0;
3078055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
3079055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
3080055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          if ( ndp + 4 > valid->limit )
3081055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            FT_INVALID_TOO_SHORT;
3082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3083055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          numMappings = TT_NEXT_ULONG( ndp );
3084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3085055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          /* numMappings * 5 > (FT_ULong)( valid->limit - ndp ) ? */
3086055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          if ( numMappings > ( (FT_ULong)( valid->limit - ndp ) ) / 5 )
3087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_INVALID_TOO_SHORT;
3088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3089a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          for ( i = 0; i < numMappings; i++ )
3090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
3091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_ULong  uni = TT_NEXT_UINT24( ndp );
3092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_ULong  gid = TT_NEXT_USHORT( ndp );
3093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( uni >= 0x110000UL )                     /* end of Unicode */
3096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_INVALID_DATA;
3097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( uni < lastUni )
3099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_INVALID_DATA;
3100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            lastUni = uni + 1U;
3102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( valid->level >= FT_VALIDATE_TIGHT    &&
3104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 gid >= TT_VALID_GLYPH_COUNT( valid ) )
3105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_INVALID_GLYPH_ID;
3106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
3107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
3108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
3109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3111727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
3112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
3116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_char_index( TT_CMap    cmap,
3117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        FT_UInt32  char_code )
3118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( cmap );
3120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( char_code );
3121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* This can't happen */
3123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
3124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3127295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_CALLBACK_DEF( FT_UInt32 )
3128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_char_next( TT_CMap     cmap,
3129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       FT_UInt32  *pchar_code )
3130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( cmap );
3132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* This can't happen */
3134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *pchar_code = 0;
3135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
3136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Error )
3140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_get_info( TT_CMap       cmap,
3141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      TT_CMapInfo  *cmap_info )
3142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( cmap );
3144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3145295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    cmap_info->format   = 14;
3146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* subtable 14 does not define a language field */
3147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cmap_info->language = 0xFFFFFFFFUL;
3148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3149727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
3150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_UInt
3154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_char_map_def_binary( FT_Byte    *base,
3155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 FT_UInt32   char_code )
3156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  numRanges = TT_PEEK_ULONG( base );
3158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  max, min;
3159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    min = 0;
3162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    max = numRanges;
3163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base += 4;
3165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* binary search */
3167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( min < max )
3168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  mid   = ( min + max ) >> 1;
3170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*   p     = base + 4 * mid;
3171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ULong   start = TT_NEXT_UINT24( p );
3172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt    cnt   = FT_NEXT_BYTE( p );
3173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code < start )
3176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        max = mid;
3177055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      else if ( char_code > start + cnt )
3178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        min = mid + 1;
3179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
3180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return TRUE;
3181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return FALSE;
3184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_UInt
3188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_char_map_nondef_binary( FT_Byte    *base,
3189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                    FT_UInt32   char_code )
3190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  numMappings = TT_PEEK_ULONG( base );
3192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  max, min;
3193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    min = 0;
3196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    max = numMappings;
3197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base += 4;
3199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* binary search */
3201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( min < max )
3202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  mid = ( min + max ) >> 1;
3204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*   p   = base + 5 * mid;
3205295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_UInt32  uni = (FT_UInt32)TT_NEXT_UINT24( p );
3206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( char_code < uni )
3209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        max = mid;
3210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( char_code > uni )
3211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        min = mid + 1;
3212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
3213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return TT_PEEK_USHORT( p );
3214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
3217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Byte*
3221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_find_variant( FT_Byte    *base,
3222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          FT_UInt32   variantCode )
3223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  numVar = TT_PEEK_ULONG( base );
3225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  max, min;
3226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    min = 0;
3229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    max = numVar;
3230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base += 4;
3232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* binary search */
3234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( min < max )
3235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  mid    = ( min + max ) >> 1;
3237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*   p      = base + 11 * mid;
3238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ULong   varSel = TT_NEXT_UINT24( p );
3239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( variantCode < varSel )
3242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        max = mid;
3243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( variantCode > varSel )
3244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        min = mid + 1;
3245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
3246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return p;
3247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return NULL;
3250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt )
3254295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  tt_cmap14_char_var_index( TT_CMap    cmap,
3255295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                            TT_CMap    ucmap,
3256295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                            FT_UInt32  charcode,
3257727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                            FT_UInt32  variantSelector )
3258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
3260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  defOff;
3261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  nondefOff;
3262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !p )
3265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
3266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    defOff    = TT_NEXT_ULONG( p );
3268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    nondefOff = TT_PEEK_ULONG( p );
3269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( defOff != 0                                                    &&
3271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )
3272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* This is the default variant of this charcode.  GID not stored */
3274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* here; stored in the normal Unicode charmap instead.           */
3275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return ucmap->cmap.clazz->char_index( &ucmap->cmap, charcode );
3276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( nondefOff != 0 )
3279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
3280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                               charcode );
3281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
3283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_Int )
3287295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  tt_cmap14_char_var_isdefault( TT_CMap    cmap,
3288295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                                FT_UInt32  charcode,
3289295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                                FT_UInt32  variantSelector )
3290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
3292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  defOff;
3293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong  nondefOff;
3294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !p )
3297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return -1;
3298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    defOff    = TT_NEXT_ULONG( p );
3300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    nondefOff = TT_NEXT_ULONG( p );
3301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( defOff != 0                                                    &&
3303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )
3304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 1;
3305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( nondefOff != 0                                            &&
3307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
3308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                           charcode ) != 0         )
3309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
3310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return -1;
3312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt32* )
3316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_variants( TT_CMap    cmap,
3317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Memory  memory )
3318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMap14   cmap14 = (TT_CMap14)cmap;
3320295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt32   count  = cmap14->num_selectors;
3321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*    p      = cmap->data + 10;
3322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32*  result;
3323295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt32   i;
3324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
3327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return NULL;
3328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    result = cmap14->results;
3330a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    for ( i = 0; i < count; i++ )
3331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3332295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      result[i] = (FT_UInt32)TT_NEXT_UINT24( p );
3333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p        += 8;
3334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    result[i] = 0;
3336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return result;
3338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt32 * )
3342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_char_variants( TT_CMap    cmap,
3343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_Memory  memory,
3344295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                           FT_UInt32  charCode )
3345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMap14   cmap14 = (TT_CMap14)  cmap;
3347295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt32   count  = cmap14->num_selectors;
3348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*    p      = cmap->data + 10;
3349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32*  q;
3350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
3353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return NULL;
3354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3355a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    for ( q = cmap14->results; count > 0; count-- )
3356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  varSel    = TT_NEXT_UINT24( p );
3358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ULong   defOff    = TT_NEXT_ULONG( p );
3359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_ULong   nondefOff = TT_NEXT_ULONG( p );
3360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ( defOff != 0                                               &&
3363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             tt_cmap14_char_map_def_binary( cmap->data + defOff,
3364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                            charCode )                 ) ||
3365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           ( nondefOff != 0                                            &&
3366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
3367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                               charCode ) != 0         ) )
3368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
3369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        q[0] = varSel;
3370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        q++;
3371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
3372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    q[0] = 0;
3374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return cmap14->results;
3376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_UInt
3380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_def_char_count( FT_Byte  *p )
3381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3382295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt32  numRanges = (FT_UInt32)TT_NEXT_ULONG( p );
3383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt    tot       = 0;
3384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
338677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner    p += 3;  /* point to the first `cnt' field */
3387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; numRanges > 0; numRanges-- )
3388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      tot += 1 + p[0];
3390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p   += 4;
3391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return tot;
3394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_UInt32*
3398727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  tt_cmap14_get_def_chars( TT_CMap    cmap,
3399727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                           FT_Byte*   p,
3400727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                           FT_Memory  memory )
3401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMap14   cmap14 = (TT_CMap14) cmap;
3403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32   numRanges;
3404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     cnt;
3405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32*  q;
3406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cnt       = tt_cmap14_def_char_count( p );
3409295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    numRanges = (FT_UInt32)TT_NEXT_ULONG( p );
3410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( tt_cmap14_ensure( cmap14, ( cnt + 1 ), memory ) )
3412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return NULL;
3413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3414a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    for ( q = cmap14->results; numRanges > 0; numRanges-- )
3415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3416727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      FT_UInt32  uni = (FT_UInt32)TT_NEXT_UINT24( p );
3417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cnt = FT_NEXT_BYTE( p ) + 1;
3420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      do
3421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
3422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        q[0]  = uni;
3423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        uni  += 1;
3424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        q    += 1;
3425727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
3426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      } while ( --cnt != 0 );
3427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    q[0] = 0;
3429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return cmap14->results;
3431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
343477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner  static FT_UInt32*
3435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_get_nondef_chars( TT_CMap     cmap,
3436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              FT_Byte    *p,
3437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              FT_Memory   memory )
3438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMap14   cmap14 = (TT_CMap14) cmap;
3440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32   numMappings;
3441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     i;
3442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt32  *ret;
3443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3445295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    numMappings = (FT_UInt32)TT_NEXT_ULONG( p );
3446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( tt_cmap14_ensure( cmap14, ( numMappings + 1 ), memory ) )
3448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return NULL;
3449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ret = cmap14->results;
3451a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    for ( i = 0; i < numMappings; i++ )
3452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3453295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      ret[i] = (FT_UInt32)TT_NEXT_UINT24( p );
3454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p += 2;
3455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ret[i] = 0;
3457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return ret;
3459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_CALLBACK_DEF( FT_UInt32 * )
3463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_cmap14_variant_chars( TT_CMap    cmap,
3464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_Memory  memory,
3465295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                           FT_UInt32  variantSelector )
3466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte    *p  = tt_cmap14_find_variant( cmap->data + 6,
3468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                             variantSelector );
3469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int      i;
3470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    defOff;
3471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    nondefOff;
3472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !p )
3475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return NULL;
3476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    defOff    = TT_NEXT_ULONG( p );
3478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    nondefOff = TT_NEXT_ULONG( p );
3479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( defOff == 0 && nondefOff == 0 )
3481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return NULL;
3482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( defOff == 0 )
3484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,
3485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                         memory );
3486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else if ( nondefOff == 0 )
3487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,
3488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                      memory );
3489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
3490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* Both a default and a non-default glyph set?  That's probably not */
3492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* good font design, but the spec allows for it...                  */
3493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TT_CMap14  cmap14 = (TT_CMap14) cmap;
3494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  numRanges;
3495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  numMappings;
3496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  duni;
3497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  dcnt;
3498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32  nuni;
3499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*   dp;
3500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt    di, ni, k;
3501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3502ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      FT_UInt32  *ret;
3503ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
3504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p  = cmap->data + nondefOff;
3506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dp = cmap->data + defOff;
3507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3508295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      numMappings = (FT_UInt32)TT_NEXT_ULONG( p );
3509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dcnt        = tt_cmap14_def_char_count( dp );
3510295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      numRanges   = (FT_UInt32)TT_NEXT_ULONG( dp );
3511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( numMappings == 0 )
3513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,
3514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                        memory );
3515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( dcnt == 0 )
3516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,
3517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                           memory );
3518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tt_cmap14_ensure( cmap14, ( dcnt + numMappings + 1 ), memory ) )
3520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return NULL;
3521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ret  = cmap14->results;
3523295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      duni = (FT_UInt32)TT_NEXT_UINT24( dp );
3524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dcnt = FT_NEXT_BYTE( dp );
3525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      di   = 1;
3526295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      nuni = (FT_UInt32)TT_NEXT_UINT24( p );
3527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p   += 2;
3528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ni   = 1;
3529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      i    = 0;
3530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3531055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      for (;;)
3532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
3533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( nuni > duni + dcnt )
3534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
3535a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          for ( k = 0; k <= dcnt; k++ )
3536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            ret[i++] = duni + k;
3537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3538a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          di++;
3539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( di > numRanges )
3541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
3542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3543295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          duni = (FT_UInt32)TT_NEXT_UINT24( dp );
3544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dcnt = FT_NEXT_BYTE( dp );
3545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
3546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
3547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
3548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( nuni < duni )
3549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            ret[i++] = nuni;
3550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* If it is within the default range then ignore it -- */
3551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* that should not have happened                       */
3552a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          ni++;
3553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( ni > numMappings )
3554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
3555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3556295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          nuni = (FT_UInt32)TT_NEXT_UINT24( p );
3557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p += 2;
3558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
3559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
3560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ni <= numMappings )
3562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
3563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* If we get here then we have run out of all default ranges.   */
3564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* We have read one non-default mapping which we haven't stored */
3565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* and there may be others that need to be read.                */
3566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ret[i++] = nuni;
3567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        while ( ni < numMappings )
3568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
3569295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          ret[i++] = (FT_UInt32)TT_NEXT_UINT24( p );
3570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p += 2;
3571a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          ni++;
3572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
3573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
3574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( di <= numRanges )
3575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
3576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* If we get here then we have run out of all non-default     */
3577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* mappings.  We have read one default range which we haven't */
3578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* stored and there may be others that need to be read.       */
3579a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        for ( k = 0; k <= dcnt; k++ )
3580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ret[i++] = duni + k;
3581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        while ( di < numRanges )
3583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
3584295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          duni = (FT_UInt32)TT_NEXT_UINT24( dp );
3585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          dcnt = FT_NEXT_BYTE( dp );
3586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3587a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          for ( k = 0; k <= dcnt; k++ )
3588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            ret[i++] = duni + k;
3589a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          di++;
3590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
3591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
3592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ret[i] = 0;
3594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return ret;
3596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3600727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  FT_DEFINE_TT_CMAP(
3601727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    tt_cmap14_class_rec,
3602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3603a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      sizeof ( TT_CMap14Rec ),
3604a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
3605a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_InitFunc)     tt_cmap14_init,        /* init       */
3606a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_DoneFunc)     tt_cmap14_done,        /* done       */
3607a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharIndexFunc)tt_cmap14_char_index,  /* char_index */
3608a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharNextFunc) tt_cmap14_char_next,   /* char_next  */
3609727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
3610a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      /* Format 14 extension functions */
3611a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVarIndexFunc)    tt_cmap14_char_var_index,
3612a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault,
3613a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_VariantListFunc)     tt_cmap14_variants,
3614a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants,
3615a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars,
3616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    14,
3618a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    (TT_CMap_ValidateFunc)tt_cmap14_validate,  /* validate      */
3619a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    (TT_CMap_Info_GetFunc)tt_cmap14_get_info   /* get_cmap_info */
3620a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  )
3621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
362277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner#endif /* TT_CONFIG_CMAP_FORMAT_14 */
3623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3625295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#ifndef FT_CONFIG_OPTION_PIC
3626295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
3627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static const TT_CMap_Class  tt_cmap_classes[] =
3628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3629727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#define TTCMAPCITEM( a )  &a,
3630295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#include "ttcmapc.h"
3631295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    NULL,
3632295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  };
3633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3634295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#else /*FT_CONFIG_OPTION_PIC*/
3635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3636727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  void
3637727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  FT_Destroy_Class_tt_cmap_classes( FT_Library      library,
3638727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                                    TT_CMap_Class*  clazz )
3639295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
3640727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Memory  memory = library->memory;
3641727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
3642727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
3643295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( clazz )
3644295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_FREE( clazz );
3645295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  }
3646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3647727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
3648727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  FT_Error
3649727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  FT_Create_Class_tt_cmap_classes( FT_Library       library,
3650727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                                   TT_CMap_Class**  output_class )
3651295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
3652727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    TT_CMap_Class*     clazz  = NULL;
3653727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    TT_CMap_ClassRec*  recs;
3654727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Error           error;
3655727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Memory          memory = library->memory;
3656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3657727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    int  i = 0;
3658727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
3659727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
3660727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#define TTCMAPCITEM( a ) i++;
3661295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#include "ttcmapc.h"
3662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3663727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    /* allocate enough space for both the pointers */
3664727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    /* plus terminator and the class instances     */
3665727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    if ( FT_ALLOC( clazz, sizeof ( *clazz ) * ( i + 1 ) +
3666727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                          sizeof ( TT_CMap_ClassRec ) * i ) )
3667295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      return error;
3668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3669295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* the location of the class instances follows the array of pointers */
3670727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    recs = (TT_CMap_ClassRec*)( (char*)clazz +
3671727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                                sizeof ( *clazz ) * ( i + 1 ) );
3672727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    i    = 0;
3673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3674295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#undef TTCMAPCITEM
3675727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#define  TTCMAPCITEM( a )             \
3676727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Init_Class_ ## a( &recs[i] );  \
3677727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    clazz[i] = &recs[i];              \
3678295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    i++;
3679295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#include "ttcmapc.h"
3680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3681295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    clazz[i] = NULL;
3682295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
3683295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    *output_class = clazz;
3684727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
3685295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  }
3686295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
3687295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#endif /*FT_CONFIG_OPTION_PIC*/
3688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* parse the `cmap' table and build the corresponding TT_CMap objects */
3691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* in the current face                                                */
3692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                    */
3693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
3694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_face_build_cmaps( TT_Face  face )
3695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*           table = face->cmap_table;
3697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*           limit = table + face->cmap_size;
3698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt volatile   num_cmaps;
3699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte* volatile  p     = table;
3700aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    FT_Library         library = FT_FACE_LIBRARY( face );
3701aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
3702aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    FT_UNUSED( library );
3703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3705aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    if ( !p || p + 4 > limit )
3706727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      return FT_THROW( Invalid_Table );
3707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* only recognize format 0 */
3709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( TT_NEXT_USHORT( p ) != 0 )
3710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3711295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_ERROR(( "tt_face_build_cmaps:"
3712295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                 " unsupported `cmap' table format = %d\n",
3713fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                 TT_PEEK_USHORT( p - 2 ) ));
3714727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      return FT_THROW( Invalid_Table );
3715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_cmaps = TT_NEXT_USHORT( p );
3718727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
3719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- )
3720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_CharMapRec  charmap;
3722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt32      offset;
3723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      charmap.platform_id = TT_NEXT_USHORT( p );
3726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      charmap.encoding_id = TT_NEXT_USHORT( p );
3727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      charmap.face        = FT_FACE( face );
3728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      charmap.encoding    = FT_ENCODING_NONE;  /* will be filled later */
3729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      offset              = TT_NEXT_ULONG( p );
3730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( offset && offset <= face->cmap_size - 2 )
3732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
3733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Byte* volatile              cmap   = table + offset;
3734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        volatile FT_UInt               format = TT_PEEK_USHORT( cmap );
3735727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        const TT_CMap_Class* volatile  pclazz = TT_CMAP_CLASSES_GET;
3736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        TT_CMap_Class volatile         clazz;
3737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( ; *pclazz; pclazz++ )
3740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
3741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          clazz = *pclazz;
3742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( clazz->format == format )
3743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
3744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            volatile TT_ValidatorRec  valid;
3745727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease            volatile FT_Error         error = FT_Err_Ok;
3746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit,
3749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                               FT_VALIDATE_DEFAULT );
3750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            valid.num_glyphs = (FT_UInt)face->max_profile.numGlyphs;
3752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3753727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease            if ( ft_setjmp( FT_VALIDATOR( &valid )->jump_buffer) == 0 )
3754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
3755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              /* validate this cmap sub-table */
3756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              error = clazz->validate( cmap, FT_VALIDATOR( &valid ) );
3757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
3758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3759a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin            if ( !valid.validator.error )
3760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
3761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_CMap  ttcmap;
3762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3764727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease              /* It might make sense to store the single variation         */
3765727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease              /* selector cmap somewhere special.  But it would have to be */
3766727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease              /* in the public FT_FaceRec, and we can't change that.       */
3767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( !FT_CMap_New( (FT_CMap_Class)clazz,
3769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 cmap, &charmap, &ttcmap ) )
3770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              {
3771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                /* it is simpler to directly set `flags' than adding */
3772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                /* a parameter to FT_CMap_New                        */
3773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                ((TT_CMap)ttcmap)->flags = (FT_Int)error;
3774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              }
3775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
3776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else
3777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
3778295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner              FT_TRACE0(( "tt_face_build_cmaps:"
3779295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                          " broken cmap sub-table ignored\n" ));
3780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
3781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
3782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
3783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
3784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3785a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        if ( !*pclazz )
3786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
3787295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          FT_TRACE0(( "tt_face_build_cmaps:"
3788295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                      " unsupported cmap sub-table ignored\n" ));
3789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
3790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
3791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3793727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_Err_Ok;
3794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL( FT_Error )
3798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_get_cmap_info( FT_CharMap    charmap,
3799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    TT_CMapInfo  *cmap_info )
3800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_CMap        cmap  = (FT_CMap)charmap;
3802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TT_CMap_Class  clazz = (TT_CMap_Class)cmap->clazz;
3803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return clazz->get_cmap_info( charmap, cmap_info );
3806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* END */
3810