1a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg/***************************************************************************/
2a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg/*                                                                         */
3a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg/*  psmodule.c                                                             */
4a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg/*                                                                         */
5a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg/*    PSNames module implementation (body).                                */
6a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg/*                                                                         */
70a0c22569deab933df21127e75db5c81f724f292Werner Lemberg/*  Copyright 1996-2018 by                                                 */
8a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg/*                                                                         */
10a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg/*  This file is part of the FreeType project, and may only be used,       */
11a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg/*  modified, and distributed under the terms of the FreeType project      */
12a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg/*  this file you indicate that you have read the license and              */
14a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg/*  understand and accept it fully.                                        */
15a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg/*                                                                         */
16a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg/***************************************************************************/
17a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg
18cc069beb2d2b6b1cb9f9b9f2af2a7ea12780f634Werner Lemberg
1919ed8afe60bbc5becf0fbbe3987a91b35a36aad4David Turner#include <ft2build.h>
20059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg#include FT_INTERNAL_DEBUG_H
2119ed8afe60bbc5becf0fbbe3987a91b35a36aad4David Turner#include FT_INTERNAL_OBJECTS_H
227760595f84a8edc365f280a9358d4075d42d51eaDavid Turner#include FT_SERVICE_POSTSCRIPT_CMAPS_H
231f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg
248d3a401fa808a8c70bd6a9ce17d5a840fb0ae2dbDavid Turner#include "psmodule.h"
256fb549ddab976e9b1993c6f14fdcee07d3397016Werner Lemberg
26c87fec0299533fee9b20505a4955c7f2f5c5bed7Werner Lemberg  /*
27c87fec0299533fee9b20505a4955c7f2f5c5bed7Werner Lemberg   *  The file `pstables.h' with its arrays and its function
28c87fec0299533fee9b20505a4955c7f2f5c5bed7Werner Lemberg   *  `ft_get_adobe_glyph_index' is useful for other projects also (for
29c87fec0299533fee9b20505a4955c7f2f5c5bed7Werner Lemberg   *  example, `pdfium' is using it).  However, if used as a C++ header,
30c87fec0299533fee9b20505a4955c7f2f5c5bed7Werner Lemberg   *  including it in two different source files makes it necessary to use
31c87fec0299533fee9b20505a4955c7f2f5c5bed7Werner Lemberg   *  `extern const' for the declaration of its arrays, otherwise the data
32c87fec0299533fee9b20505a4955c7f2f5c5bed7Werner Lemberg   *  would be duplicated as mandated by the C++ standard.
33c87fec0299533fee9b20505a4955c7f2f5c5bed7Werner Lemberg   *
34c87fec0299533fee9b20505a4955c7f2f5c5bed7Werner Lemberg   *  For this reason, we use `DEFINE_PS_TABLES' to guard the function
35c87fec0299533fee9b20505a4955c7f2f5c5bed7Werner Lemberg   *  definitions, and `DEFINE_PS_TABLES_DATA' to provide both proper array
36c87fec0299533fee9b20505a4955c7f2f5c5bed7Werner Lemberg   *  declarations and definitions.
37c87fec0299533fee9b20505a4955c7f2f5c5bed7Werner Lemberg   */
38248eaa4f601381bdcb584c16a370b5e0ad553613Werner Lemberg#include "pstables.h"
396fb549ddab976e9b1993c6f14fdcee07d3397016Werner Lemberg#define  DEFINE_PS_TABLES
40c87fec0299533fee9b20505a4955c7f2f5c5bed7Werner Lemberg#define  DEFINE_PS_TABLES_DATA
418d3a401fa808a8c70bd6a9ce17d5a840fb0ae2dbDavid Turner#include "pstables.h"
42cc069beb2d2b6b1cb9f9b9f2af2a7ea12780f634Werner Lemberg
431f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#include "psnamerr.h"
4424b110c6c61cc52713ba4f58dd41f08b5af05025Oran Agra#include "pspic.h"
451f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg
46aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
47d6752a6bfbda66cfb3040ea7c7138edc6d3e68ffWerner Lemberg#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
48aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
49a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg
50aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
51a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg
52a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg
53607dec79bb6ad524a9d2e7f93b836b795fe234cfWerner Lemberg#define VARIANT_BIT         0x80000000UL
5482ebaa7b0512030cd3c9d80dcfac58612246be8dSuzuki, Toshiya (鈴木俊哉)#define BASE_GLYPH( code )  ( (FT_UInt32)( (code) & ~VARIANT_BIT ) )
55adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg
56adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg
5756ef6bc4d67230aac635298006fd7a9f1096c744Werner Lemberg  /* Return the Unicode value corresponding to a given glyph.  Note that */
58a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg  /* we do deal with glyph variants by detecting a non-initial dot in    */
59adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg  /* the name, as in `A.swash' or `e.final'; in this case, the           */
60adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg  /* VARIANT_BIT is set in the return value.                             */
61a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg  /*                                                                     */
6268e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg  static FT_UInt32
63b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner  ps_unicode_value( const char*  glyph_name )
64aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner  {
65eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg    /* If the name begins with `uni', then the glyph name may be a */
66a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg    /* hard-coded unicode character code.                          */
67aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner    if ( glyph_name[0] == 'u' &&
68aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner         glyph_name[1] == 'n' &&
69aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner         glyph_name[2] == 'i' )
70aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner    {
71a8bbc267a20c62806a87c8755e2c4bf58acfc7b5Werner Lemberg      /* determine whether the next four characters following are */
72a8bbc267a20c62806a87c8755e2c4bf58acfc7b5Werner Lemberg      /* hexadecimal.                                             */
73a8bbc267a20c62806a87c8755e2c4bf58acfc7b5Werner Lemberg
74a8bbc267a20c62806a87c8755e2c4bf58acfc7b5Werner Lemberg      /* XXX: Add code to deal with ligatures, i.e. glyph names like */
75a8bbc267a20c62806a87c8755e2c4bf58acfc7b5Werner Lemberg      /*      `uniXXXXYYYYZZZZ'...                                   */
76a8bbc267a20c62806a87c8755e2c4bf58acfc7b5Werner Lemberg
77a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg      FT_Int       count;
7882ebaa7b0512030cd3c9d80dcfac58612246be8dSuzuki, Toshiya (鈴木俊哉)      FT_UInt32    value = 0;
7912841de1c7b37ffb56af5a51b65cc76feb27cde6David Turner      const char*  p     = glyph_name + 3;
80a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg
81aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
82a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg      for ( count = 4; count > 0; count--, p++ )
83aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner      {
84c3b21608699a72698d382ad44c5f9fd6946ce43cWerner Lemberg        char          c = *p;
85c3b21608699a72698d382ad44c5f9fd6946ce43cWerner Lemberg        unsigned int  d;
86aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
87a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg
88a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg        d = (unsigned char)c - '0';
89a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg        if ( d >= 10 )
90aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner        {
91aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner          d = (unsigned char)c - 'A';
92aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner          if ( d >= 6 )
93aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner            d = 16;
94aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner          else
95aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner            d += 10;
96aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner        }
97a8bbc267a20c62806a87c8755e2c4bf58acfc7b5Werner Lemberg
98adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        /* Exit if a non-uppercase hexadecimal character was found   */
99adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        /* -- this also catches character codes below `0' since such */
100adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        /* negative numbers cast to `unsigned int' are far too big.  */
101a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg        if ( d >= 16 )
102aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner          break;
103aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
104a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg        value = ( value << 4 ) + d;
105aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner      }
106eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg
107eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg      /* there must be exactly four hex digits */
108adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      if ( count == 0 )
109adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      {
110adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        if ( *p == '\0' )
111adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg          return value;
112adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        if ( *p == '.' )
11382ebaa7b0512030cd3c9d80dcfac58612246be8dSuzuki, Toshiya (鈴木俊哉)          return (FT_UInt32)( value | VARIANT_BIT );
114adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      }
115eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg    }
116eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg
117eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg    /* If the name begins with `u', followed by four to six uppercase */
1186e87ed9f04f7914e15f9284b0b762b730222c399Werner Lemberg    /* hexadecimal digits, it is a hard-coded unicode character code. */
119eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg    if ( glyph_name[0] == 'u' )
120eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg    {
121eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg      FT_Int       count;
12282ebaa7b0512030cd3c9d80dcfac58612246be8dSuzuki, Toshiya (鈴木俊哉)      FT_UInt32    value = 0;
123eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg      const char*  p     = glyph_name + 1;
124eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg
125eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg
126eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg      for ( count = 6; count > 0; count--, p++ )
127eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg      {
128eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg        char          c = *p;
129eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg        unsigned int  d;
130eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg
131eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg
132eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg        d = (unsigned char)c - '0';
133eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg        if ( d >= 10 )
134eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg        {
135eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg          d = (unsigned char)c - 'A';
136eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg          if ( d >= 6 )
137eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg            d = 16;
138eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg          else
139eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg            d += 10;
140eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg        }
141eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg
142eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg        if ( d >= 16 )
143eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg          break;
144eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg
145eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg        value = ( value << 4 ) + d;
146eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg      }
147eb17a92a78645ca232eb2a85aded9b358a589fdcWerner Lemberg
148adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      if ( count <= 2 )
149adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      {
150adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        if ( *p == '\0' )
151adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg          return value;
152adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        if ( *p == '.' )
15382ebaa7b0512030cd3c9d80dcfac58612246be8dSuzuki, Toshiya (鈴木俊哉)          return (FT_UInt32)( value | VARIANT_BIT );
154adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      }
155aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner    }
156aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
157adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg    /* Look for a non-initial dot in the glyph name in order to */
158adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg    /* find variants like `A.swash', `e.final', etc.            */
159aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner    {
16012e51f16857feeae87327b5ccf0e519373f6ae59David Turner      const char*  p   = glyph_name;
16112e51f16857feeae87327b5ccf0e519373f6ae59David Turner      const char*  dot = NULL;
162a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg
163a8bbc267a20c62806a87c8755e2c4bf58acfc7b5Werner Lemberg
16412e51f16857feeae87327b5ccf0e519373f6ae59David Turner      for ( ; *p; p++ )
165aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner      {
166adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        if ( *p == '.' && p > glyph_name )
167adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        {
16812e51f16857feeae87327b5ccf0e519373f6ae59David Turner          dot = p;
169adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg          break;
170adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        }
171aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner      }
172aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
173adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      /* now look up the glyph in the Adobe Glyph List */
17412e51f16857feeae87327b5ccf0e519373f6ae59David Turner      if ( !dot )
17582ebaa7b0512030cd3c9d80dcfac58612246be8dSuzuki, Toshiya (鈴木俊哉)        return (FT_UInt32)ft_get_adobe_glyph_index( glyph_name, p );
176adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      else
17782ebaa7b0512030cd3c9d80dcfac58612246be8dSuzuki, Toshiya (鈴木俊哉)        return (FT_UInt32)( ft_get_adobe_glyph_index( glyph_name, dot ) |
17882ebaa7b0512030cd3c9d80dcfac58612246be8dSuzuki, Toshiya (鈴木俊哉)                            VARIANT_BIT );
179aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner    }
180aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner  }
181aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
182aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
183d15bc0d13a163995e1ca11925349bd64d1c33617David Turner  /* ft_qsort callback to sort the unicode map */
18452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  FT_CALLBACK_DEF( int )
185dee781342b932b60c0c885d4f493b8246710a34cDavid Turner  compare_uni_maps( const void*  a,
186dee781342b932b60c0c885d4f493b8246710a34cDavid Turner                    const void*  b )
187aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner  {
188aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner    PS_UniMap*  map1 = (PS_UniMap*)a;
189aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner    PS_UniMap*  map2 = (PS_UniMap*)b;
190adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg    FT_UInt32   unicode1 = BASE_GLYPH( map1->unicode );
191adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg    FT_UInt32   unicode2 = BASE_GLYPH( map2->unicode );
192aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
193a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg
194adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg    /* sort base glyphs before glyph variants */
195adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg    if ( unicode1 == unicode2 )
196a4cb0d95d90a7ed76625dc5d60af66dca03733c5Werner Lemberg    {
197a4cb0d95d90a7ed76625dc5d60af66dca03733c5Werner Lemberg      if ( map1->unicode > map2->unicode )
198a4cb0d95d90a7ed76625dc5d60af66dca03733c5Werner Lemberg        return 1;
199a4cb0d95d90a7ed76625dc5d60af66dca03733c5Werner Lemberg      else if ( map1->unicode < map2->unicode )
200a4cb0d95d90a7ed76625dc5d60af66dca03733c5Werner Lemberg        return -1;
201a4cb0d95d90a7ed76625dc5d60af66dca03733c5Werner Lemberg      else
202a4cb0d95d90a7ed76625dc5d60af66dca03733c5Werner Lemberg        return 0;
203a4cb0d95d90a7ed76625dc5d60af66dca03733c5Werner Lemberg    }
204adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg    else
205a4cb0d95d90a7ed76625dc5d60af66dca03733c5Werner Lemberg    {
206a4cb0d95d90a7ed76625dc5d60af66dca03733c5Werner Lemberg      if ( unicode1 > unicode2 )
207a4cb0d95d90a7ed76625dc5d60af66dca03733c5Werner Lemberg        return 1;
208a4cb0d95d90a7ed76625dc5d60af66dca03733c5Werner Lemberg      else if ( unicode1 < unicode2 )
209a4cb0d95d90a7ed76625dc5d60af66dca03733c5Werner Lemberg        return -1;
210a4cb0d95d90a7ed76625dc5d60af66dca03733c5Werner Lemberg      else
211a4cb0d95d90a7ed76625dc5d60af66dca03733c5Werner Lemberg        return 0;
212a4cb0d95d90a7ed76625dc5d60af66dca03733c5Werner Lemberg    }
213aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner  }
214aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
215aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
2167f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg  /* support for extra glyphs not handled (well) in AGL; */
2177f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg  /* we add extra mappings for them if necessary         */
218a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg
2197f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg#define EXTRA_GLYPH_LIST_SIZE  10
220a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg
2217f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg  static const FT_UInt32  ft_extra_glyph_unicodes[EXTRA_GLYPH_LIST_SIZE] =
222a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg  {
2237f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg    /* WGL 4 */
224a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg    0x0394,
225a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg    0x03A9,
226a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg    0x2215,
227a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg    0x00AD,
228a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg    0x02C9,
229a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg    0x03BC,
230a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg    0x2219,
2317f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg    0x00A0,
2327f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg    /* Romanian */
2337f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg    0x021A,
2347f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg    0x021B
235a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg  };
236a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg
2377f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg  static const char  ft_extra_glyph_names[] =
238a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg  {
239a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg    'D','e','l','t','a',0,
240a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg    'O','m','e','g','a',0,
241a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg    'f','r','a','c','t','i','o','n',0,
242a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg    'h','y','p','h','e','n',0,
243a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg    'm','a','c','r','o','n',0,
244a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg    'm','u',0,
245a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg    'p','e','r','i','o','d','c','e','n','t','e','r','e','d',0,
2467f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg    's','p','a','c','e',0,
2477f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg    'T','c','o','m','m','a','a','c','c','e','n','t',0,
2487f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg    't','c','o','m','m','a','a','c','c','e','n','t',0
249a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg  };
250a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg
251a92cec567c816673d1abd237c34a3a01b576b976David Turner  static const FT_Int
2527f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg  ft_extra_glyph_name_offsets[EXTRA_GLYPH_LIST_SIZE] =
253a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg  {
254a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg     0,
255a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg     6,
256a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg    12,
257a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg    21,
258a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg    28,
259a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg    35,
260a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg    38,
2617f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg    53,
2627f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg    59,
2637f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg    72
264a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg  };
265a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg
266a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg
267a92cec567c816673d1abd237c34a3a01b576b976David Turner  static void
2687f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg  ps_check_extra_glyph_name( const char*  gname,
2697f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg                             FT_UInt      glyph,
2707f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg                             FT_UInt*     extra_glyphs,
2717f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg                             FT_UInt     *states )
272a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg  {
273a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg    FT_UInt  n;
274a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg
275a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg
2767f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg    for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
277a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg    {
2787f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg      if ( ft_strcmp( ft_extra_glyph_names +
2797f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg                        ft_extra_glyph_name_offsets[n], gname ) == 0 )
280a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg      {
281a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg        if ( states[n] == 0 )
282a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg        {
2837f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg          /* mark this extra glyph as a candidate for the cmap */
284a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg          states[n]     = 1;
2857f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg          extra_glyphs[n] = glyph;
286a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg        }
287a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg
288a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg        return;
289a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg      }
290a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg    }
291a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg  }
292a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg
293a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg
294a92cec567c816673d1abd237c34a3a01b576b976David Turner  static void
2957f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg  ps_check_extra_glyph_unicode( FT_UInt32  uni_char,
2967f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg                                FT_UInt   *states )
297a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg  {
298a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg    FT_UInt  n;
299a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg
300a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg
3017f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg    for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
302a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg    {
3037f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg      if ( uni_char == ft_extra_glyph_unicodes[n] )
304a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg      {
3057f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg        /* disable this extra glyph from being added to the cmap */
306a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg        states[n] = 2;
307a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg
308a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg        return;
309a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg      }
310a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg    }
311a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg  }
312a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg
313a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg
314adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg  /* Build a table that maps Unicode values to glyph indices. */
31552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static FT_Error
316457b4a81a190500fbbea8bc7b5750903704e715fDavid Turner  ps_unicodes_init( FT_Memory             memory,
317457b4a81a190500fbbea8bc7b5750903704e715fDavid Turner                    PS_Unicodes           table,
318457b4a81a190500fbbea8bc7b5750903704e715fDavid Turner                    FT_UInt               num_glyphs,
319457b4a81a190500fbbea8bc7b5750903704e715fDavid Turner                    PS_GetGlyphNameFunc   get_glyph_name,
320457b4a81a190500fbbea8bc7b5750903704e715fDavid Turner                    PS_FreeGlyphNameFunc  free_glyph_name,
321457b4a81a190500fbbea8bc7b5750903704e715fDavid Turner                    FT_Pointer            glyph_data )
322aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner  {
323aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner    FT_Error  error;
324aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
3257f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg    FT_UInt  extra_glyph_list_states[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
3267f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg    FT_UInt  extra_glyphs[EXTRA_GLYPH_LIST_SIZE];
327a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg
328a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg
329aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner    /* we first allocate the table */
330aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner    table->num_maps = 0;
331eabc8d72e0dddf8fa85ba07677ba4ba565283e1eAlexei Podtelezhnikov (Алексей Подтележников)    table->maps     = NULL;
332aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
3337f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg    if ( !FT_NEW_ARRAY( table->maps, num_glyphs + EXTRA_GLYPH_LIST_SIZE ) )
334aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner    {
335aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner      FT_UInt     n;
336aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner      FT_UInt     count;
337aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner      PS_UniMap*  map;
33868e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg      FT_UInt32   uni_char;
339aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
340a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg
341aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner      map = table->maps;
342a8bbc267a20c62806a87c8755e2c4bf58acfc7b5Werner Lemberg
343aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner      for ( n = 0; n < num_glyphs; n++ )
344aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner      {
3458ab0979d6e2d29fe5d489d55ff4adc6a55744308Werner Lemberg        const char*  gname = get_glyph_name( glyph_data, n );
346a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg
347a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg
348a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg        if ( gname )
349aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner        {
3507f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg          ps_check_extra_glyph_name( gname, n,
3517f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg                                     extra_glyphs, extra_glyph_list_states );
352b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner          uni_char = ps_unicode_value( gname );
353a8bbc267a20c62806a87c8755e2c4bf58acfc7b5Werner Lemberg
354adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg          if ( BASE_GLYPH( uni_char ) != 0 )
355aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner          {
3567f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg            ps_check_extra_glyph_unicode( uni_char,
3577f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg                                          extra_glyph_list_states );
358adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg            map->unicode     = uni_char;
359aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner            map->glyph_index = n;
360aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner            map++;
361aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner          }
362457b4a81a190500fbbea8bc7b5750903704e715fDavid Turner
363457b4a81a190500fbbea8bc7b5750903704e715fDavid Turner          if ( free_glyph_name )
364457b4a81a190500fbbea8bc7b5750903704e715fDavid Turner            free_glyph_name( glyph_data, gname );
365aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner        }
366aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner      }
367aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
3687f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg      for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
369a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg      {
3707f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg        if ( extra_glyph_list_states[n] == 1 )
371a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg        {
3727f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg          /* This glyph name has an additional representation. */
3737f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg          /* Add it to the cmap.                               */
374a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg
3757f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg          map->unicode     = ft_extra_glyph_unicodes[n];
3767f30c0c64c397ee76d17690dedf86dae1d7f6a1bWerner Lemberg          map->glyph_index = extra_glyphs[n];
377a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg          map++;
378a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg        }
379a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg      }
380a2f17cc1508ddc476c21356a0b7bbee31d009d65Werner Lemberg
381adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      /* now compress the table a bit */
382914b289f1623b1030b66537d3b3ce4b652e4606cWerner Lemberg      count = (FT_UInt)( map - table->maps );
383a8bbc267a20c62806a87c8755e2c4bf58acfc7b5Werner Lemberg
384a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg      if ( count == 0 )
385aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner      {
386b8ca6de3653b5c3d50e9fadc6a1d7b606deffbdbSuzuki, Toshiya (鈴木俊哉)        /* No unicode chars here! */
387e459d742e6236df43f542b8c29dfdcf05d69716cDavid Turner        FT_FREE( table->maps );
388a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg        if ( !error )
389059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg          error = FT_THROW( No_Unicode_Glyph_Name );
390adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      }
391370aea802c9ed3b8bd42ce8d1308c44e1487367bWerner Lemberg      else
392370aea802c9ed3b8bd42ce8d1308c44e1487367bWerner Lemberg      {
393adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        /* Reallocate if the number of used entries is much smaller. */
394adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        if ( count < num_glyphs / 2 )
395adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        {
396adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg          (void)FT_RENEW_ARRAY( table->maps, num_glyphs, count );
397e3c9301581a450fae5db73a3b94b10ed6a0aeb5eWerner Lemberg          error = FT_Err_Ok;
398adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        }
399adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg
400adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        /* Sort the table in increasing order of unicode values, */
401adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        /* taking care of glyph variants.                        */
402adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        ft_qsort( table->maps, count, sizeof ( PS_UniMap ),
403adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg                  compare_uni_maps );
404aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner      }
405aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
406aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner      table->num_maps = count;
407aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner    }
408a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg
409aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner    return error;
410aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner  }
411aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
412a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg
41352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static FT_UInt
4148ab0979d6e2d29fe5d489d55ff4adc6a55744308Werner Lemberg  ps_unicodes_char_index( PS_Unicodes  table,
4158ab0979d6e2d29fe5d489d55ff4adc6a55744308Werner Lemberg                          FT_UInt32    unicode )
416aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner  {
417adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg    PS_UniMap  *min, *max, *mid, *result = NULL;
418a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg
419a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg
420adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg    /* Perform a binary search on the table. */
421a8bbc267a20c62806a87c8755e2c4bf58acfc7b5Werner Lemberg
422aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner    min = table->maps;
423aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner    max = min + table->num_maps - 1;
424aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
425a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg    while ( min <= max )
426aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner    {
427adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      FT_UInt32  base_glyph;
428adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg
429adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg
430adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      mid = min + ( ( max - min ) >> 1 );
431adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg
432aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner      if ( mid->unicode == unicode )
433adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      {
434adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        result = mid;
435adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        break;
436adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      }
437adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg
438adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      base_glyph = BASE_GLYPH( mid->unicode );
439adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg
440adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      if ( base_glyph == unicode )
441adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        result = mid; /* remember match but continue search for base glyph */
442aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
443a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg      if ( min == max )
444aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner        break;
445aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
446adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      if ( base_glyph < unicode )
447a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg        min = mid + 1;
448a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg      else
449a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg        max = mid - 1;
450aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner    }
451aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
452adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg    if ( result )
453adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      return result->glyph_index;
454adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg    else
455adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      return 0;
456aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner  }
457aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
458aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
4593f0f2e462bcbb3d5f9b26ccbc351a3049c22b4b0Suzuki, Toshiya (鈴木俊哉)  static FT_UInt32
4608ab0979d6e2d29fe5d489d55ff4adc6a55744308Werner Lemberg  ps_unicodes_char_next( PS_Unicodes  table,
4618ab0979d6e2d29fe5d489d55ff4adc6a55744308Werner Lemberg                         FT_UInt32   *unicode )
4620f7c2f1aa58c2251d6c1a3f388a50bfa97cb097fWerner Lemberg  {
463adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg    FT_UInt    result    = 0;
464adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg    FT_UInt32  char_code = *unicode + 1;
4650f7c2f1aa58c2251d6c1a3f388a50bfa97cb097fWerner Lemberg
4660f7c2f1aa58c2251d6c1a3f388a50bfa97cb097fWerner Lemberg
467adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg    {
468adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      FT_UInt     min = 0;
469adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      FT_UInt     max = table->num_maps;
470adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      FT_UInt     mid;
471adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      PS_UniMap*  map;
472adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      FT_UInt32   base_glyph;
4730f7c2f1aa58c2251d6c1a3f388a50bfa97cb097fWerner Lemberg
4740f7c2f1aa58c2251d6c1a3f388a50bfa97cb097fWerner Lemberg
475adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      while ( min < max )
476adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      {
477adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        mid = min + ( ( max - min ) >> 1 );
478adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        map = table->maps + mid;
4790f7c2f1aa58c2251d6c1a3f388a50bfa97cb097fWerner Lemberg
480adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        if ( map->unicode == char_code )
481adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        {
482adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg          result = map->glyph_index;
483adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg          goto Exit;
484adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        }
4850f7c2f1aa58c2251d6c1a3f388a50bfa97cb097fWerner Lemberg
486adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        base_glyph = BASE_GLYPH( map->unicode );
4870f7c2f1aa58c2251d6c1a3f388a50bfa97cb097fWerner Lemberg
488adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        if ( base_glyph == char_code )
489adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg          result = map->glyph_index;
490b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner
491adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        if ( base_glyph < char_code )
492adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg          min = mid + 1;
493adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        else
494adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg          max = mid;
495adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      }
496adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg
497adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      if ( result )
498adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg        goto Exit;               /* we have a variant glyph */
499adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg
500adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      /* we didn't find it; check whether we have a map just above it */
501adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      char_code = 0;
502adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg
503adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      if ( min < table->num_maps )
504adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      {
50547bf95dd705962679ba50aace24361066db777a1Werner Lemberg        map       = table->maps + min;
50647bf95dd705962679ba50aace24361066db777a1Werner Lemberg        result    = map->glyph_index;
50747bf95dd705962679ba50aace24361066db777a1Werner Lemberg        char_code = BASE_GLYPH( map->unicode );
508adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg      }
5090f7c2f1aa58c2251d6c1a3f388a50bfa97cb097fWerner Lemberg    }
5100f7c2f1aa58c2251d6c1a3f388a50bfa97cb097fWerner Lemberg
511adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg  Exit:
512adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg    *unicode = char_code;
513adf828ff953b0db3492ddf7678fdcefe34a5058bWerner Lemberg    return result;
5140f7c2f1aa58c2251d6c1a3f388a50bfa97cb097fWerner Lemberg  }
5150f7c2f1aa58c2251d6c1a3f388a50bfa97cb097fWerner Lemberg
5160f7c2f1aa58c2251d6c1a3f388a50bfa97cb097fWerner Lemberg
517a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
518aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
519aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
52052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static const char*
521b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner  ps_get_macintosh_name( FT_UInt  name_index )
522aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner  {
52312e51f16857feeae87327b5ccf0e519373f6ae59David Turner    if ( name_index >= FT_NUM_MAC_NAMES )
524aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner      name_index = 0;
525aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
52612e51f16857feeae87327b5ccf0e519373f6ae59David Turner    return ft_standard_glyph_names + ft_mac_names[name_index];
527aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner  }
528aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
529aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
53052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static const char*
531b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner  ps_get_standard_strings( FT_UInt  sid )
532aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner  {
53312e51f16857feeae87327b5ccf0e519373f6ae59David Turner    if ( sid >= FT_NUM_SID_NAMES )
53412e51f16857feeae87327b5ccf0e519373f6ae59David Turner      return 0;
53512e51f16857feeae87327b5ccf0e519373f6ae59David Turner
53612e51f16857feeae87327b5ccf0e519373f6ae59David Turner    return ft_standard_glyph_names + ft_sid_names[sid];
537aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner  }
538aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
539aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
540aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
541ee09c8616360880def9e0e95a4c6fd56a5202a96Werner Lemberg
542ee09c8616360880def9e0e95a4c6fd56a5202a96Werner Lemberg  FT_DEFINE_SERVICE_PSCMAPSREC(
543ee09c8616360880def9e0e95a4c6fd56a5202a96Werner Lemberg    pscmaps_interface,
544c95b7652d8db19530c91e80d23c288bbf27f1b72Werner Lemberg
5454188deacf3ca89bbd8fb74707f7b70d0c3f8469dWerner Lemberg    (PS_Unicode_ValueFunc)     ps_unicode_value,        /* unicode_value         */
5464188deacf3ca89bbd8fb74707f7b70d0c3f8469dWerner Lemberg    (PS_Unicodes_InitFunc)     ps_unicodes_init,        /* unicodes_init         */
5474188deacf3ca89bbd8fb74707f7b70d0c3f8469dWerner Lemberg    (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index,  /* unicodes_char_index   */
5484188deacf3ca89bbd8fb74707f7b70d0c3f8469dWerner Lemberg    (PS_Unicodes_CharNextFunc) ps_unicodes_char_next,   /* unicodes_char_next    */
549a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg
5504188deacf3ca89bbd8fb74707f7b70d0c3f8469dWerner Lemberg    (PS_Macintosh_NameFunc)    ps_get_macintosh_name,   /* macintosh_name        */
5514188deacf3ca89bbd8fb74707f7b70d0c3f8469dWerner Lemberg    (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, /* adobe_std_strings     */
55224b110c6c61cc52713ba4f58dd41f08b5af05025Oran Agra
5534188deacf3ca89bbd8fb74707f7b70d0c3f8469dWerner Lemberg    t1_standard_encoding,                               /* adobe_std_encoding    */
554c95b7652d8db19530c91e80d23c288bbf27f1b72Werner Lemberg    t1_expert_encoding                                  /* adobe_expert_encoding */
555c95b7652d8db19530c91e80d23c288bbf27f1b72Werner Lemberg  )
55624b110c6c61cc52713ba4f58dd41f08b5af05025Oran Agra
557aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner#else
558a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg
559ee09c8616360880def9e0e95a4c6fd56a5202a96Werner Lemberg  FT_DEFINE_SERVICE_PSCMAPSREC(
560ee09c8616360880def9e0e95a4c6fd56a5202a96Werner Lemberg    pscmaps_interface,
561c95b7652d8db19530c91e80d23c288bbf27f1b72Werner Lemberg
5624188deacf3ca89bbd8fb74707f7b70d0c3f8469dWerner Lemberg    NULL,                                               /* unicode_value         */
5634188deacf3ca89bbd8fb74707f7b70d0c3f8469dWerner Lemberg    NULL,                                               /* unicodes_init         */
5644188deacf3ca89bbd8fb74707f7b70d0c3f8469dWerner Lemberg    NULL,                                               /* unicodes_char_index   */
5654188deacf3ca89bbd8fb74707f7b70d0c3f8469dWerner Lemberg    NULL,                                               /* unicodes_char_next    */
566aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
5674188deacf3ca89bbd8fb74707f7b70d0c3f8469dWerner Lemberg    (PS_Macintosh_NameFunc)    ps_get_macintosh_name,   /* macintosh_name        */
5684188deacf3ca89bbd8fb74707f7b70d0c3f8469dWerner Lemberg    (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, /* adobe_std_strings     */
569aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
5704188deacf3ca89bbd8fb74707f7b70d0c3f8469dWerner Lemberg    t1_standard_encoding,                               /* adobe_std_encoding    */
571c95b7652d8db19530c91e80d23c288bbf27f1b72Werner Lemberg    t1_expert_encoding                                  /* adobe_expert_encoding */
572c95b7652d8db19530c91e80d23c288bbf27f1b72Werner Lemberg  )
57324b110c6c61cc52713ba4f58dd41f08b5af05025Oran Agra
57424b110c6c61cc52713ba4f58dd41f08b5af05025Oran Agra#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
57524b110c6c61cc52713ba4f58dd41f08b5af05025Oran Agra
57624b110c6c61cc52713ba4f58dd41f08b5af05025Oran Agra
577ee09c8616360880def9e0e95a4c6fd56a5202a96Werner Lemberg  FT_DEFINE_SERVICEDESCREC1(
578ee09c8616360880def9e0e95a4c6fd56a5202a96Werner Lemberg    pscmaps_services,
579c95b7652d8db19530c91e80d23c288bbf27f1b72Werner Lemberg
580d9bf44a430339bc40285eb96b0b700eb4ce9d6c3Werner Lemberg    FT_SERVICE_ID_POSTSCRIPT_CMAPS, &PSCMAPS_INTERFACE_GET )
581aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
582f4c0b921a18ad421a022ee7c1d2449daae502ae0Werner Lemberg
583b72d8a85212e1dc2dc103c28e19a4f4a2d71767eDavid Turner  static FT_Pointer
584b72d8a85212e1dc2dc103c28e19a4f4a2d71767eDavid Turner  psnames_get_service( FT_Module    module,
585b72d8a85212e1dc2dc103c28e19a4f4a2d71767eDavid Turner                       const char*  service_id )
586b72d8a85212e1dc2dc103c28e19a4f4a2d71767eDavid Turner  {
5875018477f4efdaaa5eaa7b57f76bf337d6ad59e78Werner Lemberg    /* PSCMAPS_SERVICES_GET dereferences `library' in PIC mode */
588226f3619750ff34ca698304f1d009d0abdcf720eSuzuki, Toshiya (鈴木俊哉)#ifdef FT_CONFIG_OPTION_PIC
589226f3619750ff34ca698304f1d009d0abdcf720eSuzuki, Toshiya (鈴木俊哉)    FT_Library  library;
590226f3619750ff34ca698304f1d009d0abdcf720eSuzuki, Toshiya (鈴木俊哉)
591226f3619750ff34ca698304f1d009d0abdcf720eSuzuki, Toshiya (鈴木俊哉)
592226f3619750ff34ca698304f1d009d0abdcf720eSuzuki, Toshiya (鈴木俊哉)    if ( !module )
593226f3619750ff34ca698304f1d009d0abdcf720eSuzuki, Toshiya (鈴木俊哉)      return NULL;
594226f3619750ff34ca698304f1d009d0abdcf720eSuzuki, Toshiya (鈴木俊哉)    library = module->library;
595226f3619750ff34ca698304f1d009d0abdcf720eSuzuki, Toshiya (鈴木俊哉)    if ( !library )
596226f3619750ff34ca698304f1d009d0abdcf720eSuzuki, Toshiya (鈴木俊哉)      return NULL;
597226f3619750ff34ca698304f1d009d0abdcf720eSuzuki, Toshiya (鈴木俊哉)#else
598d9145241fe378104ba4c12a42534549faacc92e6Suzuki, Toshiya (鈴木俊哉)    FT_UNUSED( module );
599226f3619750ff34ca698304f1d009d0abdcf720eSuzuki, Toshiya (鈴木俊哉)#endif
600b72d8a85212e1dc2dc103c28e19a4f4a2d71767eDavid Turner
601d9bf44a430339bc40285eb96b0b700eb4ce9d6c3Werner Lemberg    return ft_service_list_lookup( PSCMAPS_SERVICES_GET, service_id );
602b72d8a85212e1dc2dc103c28e19a4f4a2d71767eDavid Turner  }
603aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
604d6752a6bfbda66cfb3040ea7c7138edc6d3e68ffWerner Lemberg#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
605aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
606aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
60724b110c6c61cc52713ba4f58dd41f08b5af05025Oran Agra#ifndef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
608ee09c8616360880def9e0e95a4c6fd56a5202a96Werner Lemberg#define PUT_PS_NAMES_SERVICE( a )  NULL
60924b110c6c61cc52713ba4f58dd41f08b5af05025Oran Agra#else
610ee09c8616360880def9e0e95a4c6fd56a5202a96Werner Lemberg#define PUT_PS_NAMES_SERVICE( a )  a
61124b110c6c61cc52713ba4f58dd41f08b5af05025Oran Agra#endif
612b72d8a85212e1dc2dc103c28e19a4f4a2d71767eDavid Turner
613ee09c8616360880def9e0e95a4c6fd56a5202a96Werner Lemberg  FT_DEFINE_MODULE(
614ee09c8616360880def9e0e95a4c6fd56a5202a96Werner Lemberg    psnames_module_class,
6151749d8bc6af8108df5a6555a894ed474138f2552Suzuki, Toshiya (鈴木俊哉)
616aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner    0,  /* this is not a font driver, nor a renderer */
617c3b21608699a72698d382ad44c5f9fd6946ce43cWerner Lemberg    sizeof ( FT_ModuleRec ),
618aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
619aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner    "psnames",  /* driver name                         */
620a8bbc267a20c62806a87c8755e2c4bf58acfc7b5Werner Lemberg    0x10000L,   /* driver version                      */
621a8bbc267a20c62806a87c8755e2c4bf58acfc7b5Werner Lemberg    0x20000L,   /* driver requires FreeType 2 or above */
622aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
623ee09c8616360880def9e0e95a4c6fd56a5202a96Werner Lemberg    PUT_PS_NAMES_SERVICE(
624d9bf44a430339bc40285eb96b0b700eb4ce9d6c3Werner Lemberg      (void*)&PSCMAPS_INTERFACE_GET ),   /* module specific interface */
625c95b7652d8db19530c91e80d23c288bbf27f1b72Werner Lemberg
626c95b7652d8db19530c91e80d23c288bbf27f1b72Werner Lemberg    (FT_Module_Constructor)NULL,                                       /* module_init   */
627c95b7652d8db19530c91e80d23c288bbf27f1b72Werner Lemberg    (FT_Module_Destructor) NULL,                                       /* module_done   */
628c95b7652d8db19530c91e80d23c288bbf27f1b72Werner Lemberg    (FT_Module_Requester)  PUT_PS_NAMES_SERVICE( psnames_get_service ) /* get_interface */
629c95b7652d8db19530c91e80d23c288bbf27f1b72Werner Lemberg  )
630aa4c28f9fe5debca5822217eb3cf8dcebe7dd6a7David Turner
631a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg
632a929ba9b205c9756f1c0d3c261185e3bacf7fdadWerner Lemberg/* END */
633