1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/
2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  psmodule.c                                                             */
4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*    PSNames module implementation (body).                                */
6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
7ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann/*  Copyright 1996-2015 by                                                 */
8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  This file is part of the FreeType project, and may only be used,       */
11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  modified, and distributed under the terms of the FreeType project      */
12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  this file you indicate that you have read the license and              */
14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  understand and accept it fully.                                        */
15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/
17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
18e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
19e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include <ft2build.h>
20e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include FT_INTERNAL_DEBUG_H
21e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include FT_INTERNAL_OBJECTS_H
22e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include FT_SERVICE_POSTSCRIPT_CMAPS_H
23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "psmodule.h"
25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "pstables.h"
26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "psnamerr.h"
28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "pspic.h"
29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define VARIANT_BIT         0x80000000UL
38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define BASE_GLYPH( code )  ( (FT_UInt32)( (code) & ~VARIANT_BIT ) )
39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
40e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* Return the Unicode value corresponding to a given glyph.  Note that */
42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* we do deal with glyph variants by detecting a non-initial dot in    */
43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* the name, as in `A.swash' or `e.final'; in this case, the           */
44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* VARIANT_BIT is set in the return value.                             */
45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*                                                                     */
46e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov  static FT_UInt32
47e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov  ps_unicode_value( const char*  glyph_name )
48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* If the name begins with `uni', then the glyph name may be a */
50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* hard-coded unicode character code.                          */
51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( glyph_name[0] == 'u' &&
52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         glyph_name[1] == 'n' &&
53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         glyph_name[2] == 'i' )
54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* determine whether the next four characters following are */
56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* hexadecimal.                                             */
57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* XXX: Add code to deal with ligatures, i.e. glyph names like */
59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /*      `uniXXXXYYYYZZZZ'...                                   */
60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Int       count;
62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_UInt32    value = 0;
63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      const char*  p     = glyph_name + 3;
64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      for ( count = 4; count > 0; count--, p++ )
67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        char          c = *p;
69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        unsigned int  d;
70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d = (unsigned char)c - '0';
73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( d >= 10 )
74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          d = (unsigned char)c - 'A';
76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          if ( d >= 6 )
77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            d = 16;
78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          else
79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            d += 10;
80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* Exit if a non-uppercase hexadecimal character was found   */
83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* -- this also catches character codes below `0' since such */
84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* negative numbers cast to `unsigned int' are far too big.  */
85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( d >= 16 )
86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          break;
87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        value = ( value << 4 ) + d;
89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* there must be exactly four hex digits */
92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( count == 0 )
93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( *p == '\0' )
95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          return value;
96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( *p == '.' )
97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          return (FT_UInt32)( value | VARIANT_BIT );
98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* If the name begins with `u', followed by four to six uppercase */
102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* hexadecimal digits, it is a hard-coded unicode character code. */
103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( glyph_name[0] == 'u' )
104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Int       count;
106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_UInt32    value = 0;
107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      const char*  p     = glyph_name + 1;
108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      for ( count = 6; count > 0; count--, p++ )
111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        char          c = *p;
113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        unsigned int  d;
114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d = (unsigned char)c - '0';
117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( d >= 10 )
118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          d = (unsigned char)c - 'A';
120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          if ( d >= 6 )
121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            d = 16;
122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          else
123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            d += 10;
124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( d >= 16 )
127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          break;
128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        value = ( value << 4 ) + d;
130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( count <= 2 )
133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( *p == '\0' )
135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          return value;
136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( *p == '.' )
137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          return (FT_UInt32)( value | VARIANT_BIT );
138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* Look for a non-initial dot in the glyph name in order to */
142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* find variants like `A.swash', `e.final', etc.            */
143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      const char*  p   = glyph_name;
145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      const char*  dot = NULL;
146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      for ( ; *p; p++ )
149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( *p == '.' && p > glyph_name )
151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          dot = p;
153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          break;
154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* now look up the glyph in the Adobe Glyph List */
158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( !dot )
159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return (FT_UInt32)ft_get_adobe_glyph_index( glyph_name, p );
160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return (FT_UInt32)( ft_get_adobe_glyph_index( glyph_name, dot ) |
162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            VARIANT_BIT );
163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* ft_qsort callback to sort the unicode map */
168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_CALLBACK_DEF( int )
169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  compare_uni_maps( const void*  a,
170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    const void*  b )
171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    PS_UniMap*  map1 = (PS_UniMap*)a;
173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    PS_UniMap*  map2 = (PS_UniMap*)b;
174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt32   unicode1 = BASE_GLYPH( map1->unicode );
175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt32   unicode2 = BASE_GLYPH( map2->unicode );
176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* sort base glyphs before glyph variants */
179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( unicode1 == unicode2 )
180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( map1->unicode > map2->unicode )
182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return 1;
183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else if ( map1->unicode < map2->unicode )
184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return -1;
185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return 0;
187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( unicode1 > unicode2 )
191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return 1;
192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else if ( unicode1 < unicode2 )
193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return -1;
194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return 0;
196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* support for extra glyphs not handled (well) in AGL; */
201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* we add extra mappings for them if necessary         */
202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define EXTRA_GLYPH_LIST_SIZE  10
204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static const FT_UInt32  ft_extra_glyph_unicodes[EXTRA_GLYPH_LIST_SIZE] =
206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* WGL 4 */
208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0x0394,
209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0x03A9,
210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0x2215,
211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0x00AD,
212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0x02C9,
213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0x03BC,
214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0x2219,
215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0x00A0,
216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* Romanian */
217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0x021A,
218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0x021B
219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  };
220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static const char  ft_extra_glyph_names[] =
222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    'D','e','l','t','a',0,
224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    'O','m','e','g','a',0,
225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    'f','r','a','c','t','i','o','n',0,
226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    'h','y','p','h','e','n',0,
227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    'm','a','c','r','o','n',0,
228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    'm','u',0,
229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    'p','e','r','i','o','d','c','e','n','t','e','r','e','d',0,
230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    's','p','a','c','e',0,
231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    'T','c','o','m','m','a','a','c','c','e','n','t',0,
232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    't','c','o','m','m','a','a','c','c','e','n','t',0
233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  };
234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static const FT_Int
236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ft_extra_glyph_name_offsets[EXTRA_GLYPH_LIST_SIZE] =
237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     0,
239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     6,
240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    12,
241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    21,
242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    28,
243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    35,
244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    38,
245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    53,
246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    59,
247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    72
248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  };
249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static void
252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ps_check_extra_glyph_name( const char*  gname,
253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                             FT_UInt      glyph,
254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                             FT_UInt*     extra_glyphs,
255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                             FT_UInt     *states )
256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt  n;
258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( ft_strcmp( ft_extra_glyph_names +
263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        ft_extra_glyph_name_offsets[n], gname ) == 0 )
264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( states[n] == 0 )
266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          /* mark this extra glyph as a candidate for the cmap */
268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          states[n]     = 1;
269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          extra_glyphs[n] = glyph;
270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return;
273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static void
279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ps_check_extra_glyph_unicode( FT_UInt32  uni_char,
280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                FT_UInt   *states )
281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt  n;
283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( uni_char == ft_extra_glyph_unicodes[n] )
288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* disable this extra glyph from being added to the cmap */
290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        states[n] = 2;
291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return;
293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* Build a table that maps Unicode values to glyph indices. */
299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Error
300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ps_unicodes_init( FT_Memory             memory,
301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    PS_Unicodes           table,
302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    FT_UInt               num_glyphs,
303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    PS_GetGlyphNameFunc   get_glyph_name,
304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    PS_FreeGlyphNameFunc  free_glyph_name,
305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    FT_Pointer            glyph_data )
306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error  error;
308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt  extra_glyph_list_states[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt  extra_glyphs[EXTRA_GLYPH_LIST_SIZE];
311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* we first allocate the table */
314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    table->num_maps = 0;
315ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    table->maps     = NULL;
316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( !FT_NEW_ARRAY( table->maps, num_glyphs + EXTRA_GLYPH_LIST_SIZE ) )
318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_UInt     n;
320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_UInt     count;
321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      PS_UniMap*  map;
322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_UInt32   uni_char;
323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      map = table->maps;
326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      for ( n = 0; n < num_glyphs; n++ )
328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        const char*  gname = get_glyph_name( glyph_data, n );
330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( gname )
333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          ps_check_extra_glyph_name( gname, n,
335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                     extra_glyphs, extra_glyph_list_states );
336e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov          uni_char = ps_unicode_value( gname );
337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          if ( BASE_GLYPH( uni_char ) != 0 )
339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          {
340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            ps_check_extra_glyph_unicode( uni_char,
341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                          extra_glyph_list_states );
342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            map->unicode     = uni_char;
343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            map->glyph_index = n;
344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            map++;
345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          }
346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          if ( free_glyph_name )
348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            free_glyph_name( glyph_data, gname );
349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( extra_glyph_list_states[n] == 1 )
355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          /* This glyph name has an additional representation. */
357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          /* Add it to the cmap.                               */
358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          map->unicode     = ft_extra_glyph_unicodes[n];
360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          map->glyph_index = extra_glyphs[n];
361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          map++;
362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* now compress the table a bit */
366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      count = (FT_UInt)( map - table->maps );
367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( count == 0 )
369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* No unicode chars here! */
371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_FREE( table->maps );
372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( !error )
373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          error = FT_THROW( No_Unicode_Glyph_Name );
374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* Reallocate if the number of used entries is much smaller. */
378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( count < num_glyphs / 2 )
379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          (void)FT_RENEW_ARRAY( table->maps, num_glyphs, count );
381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          error = FT_Err_Ok;
382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* Sort the table in increasing order of unicode values, */
385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* taking care of glyph variants.                        */
386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ft_qsort( table->maps, count, sizeof ( PS_UniMap ),
387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  compare_uni_maps );
388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      table->num_maps = count;
391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return error;
394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_UInt
398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ps_unicodes_char_index( PS_Unicodes  table,
399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                          FT_UInt32    unicode )
400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    PS_UniMap  *min, *max, *mid, *result = NULL;
402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* Perform a binary search on the table. */
405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    min = table->maps;
407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    max = min + table->num_maps - 1;
408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    while ( min <= max )
410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_UInt32  base_glyph;
412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      mid = min + ( ( max - min ) >> 1 );
415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( mid->unicode == unicode )
417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        result = mid;
419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        break;
420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      base_glyph = BASE_GLYPH( mid->unicode );
423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( base_glyph == unicode )
425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        result = mid; /* remember match but continue search for base glyph */
426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( min == max )
428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        break;
429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( base_glyph < unicode )
431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        min = mid + 1;
432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        max = mid - 1;
434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( result )
437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return result->glyph_index;
438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return 0;
440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_UInt32
444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ps_unicodes_char_next( PS_Unicodes  table,
445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                         FT_UInt32   *unicode )
446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt    result    = 0;
448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt32  char_code = *unicode + 1;
449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_UInt     min = 0;
453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_UInt     max = table->num_maps;
454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_UInt     mid;
455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      PS_UniMap*  map;
456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_UInt32   base_glyph;
457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      while ( min < max )
460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        mid = min + ( ( max - min ) >> 1 );
462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        map = table->maps + mid;
463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( map->unicode == char_code )
465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          result = map->glyph_index;
467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto Exit;
468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        base_glyph = BASE_GLYPH( map->unicode );
471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( base_glyph == char_code )
473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          result = map->glyph_index;
474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( base_glyph < char_code )
476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          min = mid + 1;
477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else
478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          max = mid;
479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( result )
482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Exit;               /* we have a variant glyph */
483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* we didn't find it; check whether we have a map just above it */
485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      char_code = 0;
486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( min < table->num_maps )
488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        map       = table->maps + min;
490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        result    = map->glyph_index;
491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        char_code = BASE_GLYPH( map->unicode );
492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Exit:
496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *unicode = char_code;
497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return result;
498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static const char*
505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ps_get_macintosh_name( FT_UInt  name_index )
506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( name_index >= FT_NUM_MAC_NAMES )
508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      name_index = 0;
509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ft_standard_glyph_names + ft_mac_names[name_index];
511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static const char*
515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ps_get_standard_strings( FT_UInt  sid )
516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( sid >= FT_NUM_SID_NAMES )
518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return 0;
519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ft_standard_glyph_names + ft_sid_names[sid];
521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_DEFINE_SERVICE_PSCMAPSREC(
527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pscmaps_interface,
528e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    (PS_Unicode_ValueFunc)     ps_unicode_value,
529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    (PS_Unicodes_InitFunc)     ps_unicodes_init,
530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index,
531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    (PS_Unicodes_CharNextFunc) ps_unicodes_char_next,
532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    (PS_Macintosh_NameFunc)    ps_get_macintosh_name,
534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    t1_standard_encoding,
537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    t1_expert_encoding )
538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else
540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_DEFINE_SERVICE_PSCMAPSREC(
542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pscmaps_interface,
543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    NULL,
544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    NULL,
545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    NULL,
546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    NULL,
547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    (PS_Macintosh_NameFunc)    ps_get_macintosh_name,
549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    t1_standard_encoding,
552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    t1_expert_encoding )
553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_DEFINE_SERVICEDESCREC1(
558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pscmaps_services,
559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_SERVICE_ID_POSTSCRIPT_CMAPS, &PSCMAPS_INTERFACE_GET )
560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Pointer
563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  psnames_get_service( FT_Module    module,
564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                       const char*  service_id )
565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
566ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    /* PSCMAPS_SERVICES_GET dereferences `library' in PIC mode */
567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_CONFIG_OPTION_PIC
568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Library  library;
569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( !module )
572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return NULL;
573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    library = module->library;
574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( !library )
575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return NULL;
576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else
577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UNUSED( module );
578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ft_service_list_lookup( PSCMAPS_SERVICES_GET, service_id );
581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifndef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define PUT_PS_NAMES_SERVICE( a )  NULL
588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else
589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define PUT_PS_NAMES_SERVICE( a )  a
590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_DEFINE_MODULE(
593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    psnames_module_class,
594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0,  /* this is not a font driver, nor a renderer */
596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    sizeof ( FT_ModuleRec ),
597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    "psnames",  /* driver name                         */
599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0x10000L,   /* driver version                      */
600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    0x20000L,   /* driver requires FreeType 2 or above */
601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    PUT_PS_NAMES_SERVICE(
603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      (void*)&PSCMAPS_INTERFACE_GET ),   /* module specific interface */
604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    (FT_Module_Constructor)NULL,
605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    (FT_Module_Destructor) NULL,
606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    (FT_Module_Requester)  PUT_PS_NAMES_SERVICE( psnames_get_service ) )
607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* END */
610