142dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org#if !defined(_FXFT_VERSION_) || _FXFT_VERSION_ == 2501
242dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/***************************************************************************/
342dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/*                                                                         */
442dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/*  psmodule.c                                                             */
542dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/*                                                                         */
642dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/*    PSNames module implementation (body).                                */
742dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/*                                                                         */
842dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/*  Copyright 1996-2003, 2005-2008, 2012, 2013 by                          */
942dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
1042dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/*                                                                         */
1124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org/*  This file is part of the FreeType project, and may only be used,       */
1242dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/*  modified, and distributed under the terms of the FreeType project      */
1342dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
1442dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/*  this file you indicate that you have read the license and              */
1542dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/*  understand and accept it fully.                                        */
1642dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/*                                                                         */
1742dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/***************************************************************************/
1842dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org
1942dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org#define FT2_BUILD_LIBRARY
2042dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org#include "../../include/ft2build.h"
2142dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org#include "../../include/freetype/internal/ftdebug.h"
2242dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org#include "../../include/freetype/internal/ftobjs.h"
2342dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org#include "../../include/freetype/internal/services/svpscmap.h"
2442dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org
2542dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org#include "psmodule.h"
2642dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org#include "pstables.h"
2742dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org
2842dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org#include "psnamerr.h"
2942dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org#include "pspic.h"
3042dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org
3142dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org
3242dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
3342dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org
3442dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org
3542dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
3642dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org
3724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org
3824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org#define VARIANT_BIT         0x80000000UL
3924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org#define BASE_GLYPH( code )  ( (FT_UInt32)( (code) & ~VARIANT_BIT ) )
4024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org
4124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org#ifdef __cplusplus
4224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.orgextern "C" {
4324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org#endif
4424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org  /* Return the Unicode value corresponding to a given glyph.  Note that */
4524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org  /* we do deal with glyph variants by detecting a non-initial dot in    */
4624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org  /* the name, as in `A.swash' or `e.final'; in this case, the           */
4724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org  /* VARIANT_BIT is set in the return value.                             */
4824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org  /*                                                                     */
4924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.orgint FXFT_unicode_from_adobe_name( const char*  glyph_name )
5024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org  {
5124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    /* If the name begins with `uni', then the glyph name may be a */
5224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    /* hard-coded unicode character code.                          */
5324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    if ( glyph_name[0] == 'u' &&
5424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org         glyph_name[1] == 'n' &&
5524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org         glyph_name[2] == 'i' )
5624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    {
5724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org      /* determine whether the next four characters following are */
5824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org      /* hexadecimal.                                             */
5924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org
6024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org      /* XXX: Add code to deal with ligatures, i.e. glyph names like */
6124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org      /*      `uniXXXXYYYYZZZZ'...                                   */
6224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org
6324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org      FT_Int       count;
6424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org      FT_UInt32    value = 0;
6524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org      const char*  p     = glyph_name + 3;
6624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org
6724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org
6824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org      for ( count = 4; count > 0; count--, p++ )
6924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org      {
7024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        char          c = *p;
7124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        unsigned int  d;
7224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org
7324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org
7424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        d = (unsigned char)c - '0';
7524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        if ( d >= 10 )
76f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org        {
7724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org          d = (unsigned char)c - 'A';
7824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org          if ( d >= 6 )
7924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org            d = 16;
8024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org          else
8124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org            d += 10;
8224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        }
8324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org
8424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        /* Exit if a non-uppercase hexadecimal character was found   */
8524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        /* -- this also catches character codes below `0' since such */
8624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        /* negative numbers cast to `unsigned int' are far too big.  */
8724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        if ( d >= 16 )
8824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org          break;
8924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org
9024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        value = ( value << 4 ) + d;
9124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org      }
9224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org
9324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org      /* there must be exactly four hex digits */
9424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org      if ( count == 0 )
9524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org      {
9624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        if ( *p == '\0' )
9724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org          return value;
9824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        if ( *p == '.' )
9924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org          return (FT_UInt32)( value | VARIANT_BIT );
10024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org      }
10124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    }
10224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org
10324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    /* If the name begins with `u', followed by four to six uppercase */
10424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    /* hexadecimal digits, it is a hard-coded unicode character code. */
10524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    if ( glyph_name[0] == 'u' )
10624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    {
10788cb22b6b4816c7a9ca6c5b795965b4606f9eb7bcommit-bot@chromium.org      FT_Int       count;
10824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org      FT_UInt32    value = 0;
10924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org      const char*  p     = glyph_name + 1;
11024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org
11124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org
11224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org      for ( count = 6; count > 0; count--, p++ )
11324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org      {
11424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        char          c = *p;
11524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        unsigned int  d;
11624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org
11724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org
11824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        d = (unsigned char)c - '0';
11924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        if ( d >= 10 )
12024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        {
12124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org          d = (unsigned char)c - 'A';
12224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org          if ( d >= 6 )
12324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org            d = 16;
124          else
125            d += 10;
126        }
127
128        if ( d >= 16 )
129          break;
130
131        value = ( value << 4 ) + d;
132      }
133
134      if ( count <= 2 )
135      {
136        if ( *p == '\0' )
137          return value;
138        if ( *p == '.' )
139          return (FT_UInt32)( value | VARIANT_BIT );
140      }
141    }
142
143    /* Look for a non-initial dot in the glyph name in order to */
144    /* find variants like `A.swash', `e.final', etc.            */
145    {
146      const char*  p   = glyph_name;
147      const char*  dot = NULL;
148
149
150      for ( ; *p; p++ )
151      {
152        if ( *p == '.' && p > glyph_name )
153        {
154          dot = p;
155          break;
156        }
157      }
158
159      /* now look up the glyph in the Adobe Glyph List */
160      if ( !dot )
161        return (FT_UInt32)ft_get_adobe_glyph_index( glyph_name, p );
162      else
163        return (FT_UInt32)( ft_get_adobe_glyph_index( glyph_name, dot ) |
164                            VARIANT_BIT );
165    }
166  }
167  #ifdef __cplusplus
168}
169#endif
170
171#if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_)
172static int xyq_search_node(char* glyph_name, int name_offset, int table_offset, FT_UInt32 unicode)
173{
174	int i, count;
175
176	// copy letters
177	while (1) {
178		glyph_name[name_offset] = ft_adobe_glyph_list[table_offset] & 0x7f;
179		name_offset ++;
180		table_offset ++;
181		if (!(ft_adobe_glyph_list[table_offset-1] & 0x80)) break;
182	}
183	glyph_name[name_offset] = 0;
184
185	// get child count
186	count = ft_adobe_glyph_list[table_offset] & 0x7f;
187
188	// check if we have value for this node
189	if (ft_adobe_glyph_list[table_offset] & 0x80) {
190		unsigned short thiscode = ft_adobe_glyph_list[table_offset+1] * 256 + ft_adobe_glyph_list[table_offset+2];
191		if (thiscode == unicode)	// found it!
192			return 1;
193		table_offset += 3;
194	} else
195		table_offset ++;
196
197	// now search in sub-nodes
198	if (count == 0) return 0;
199	for (i = 0; i < count; i ++) {
200		int child_offset = ft_adobe_glyph_list[table_offset+i*2] * 256 + ft_adobe_glyph_list[table_offset+i*2+1];
201		if (xyq_search_node(glyph_name, name_offset, child_offset, unicode))
202			// found in child
203			return 1;
204	}
205	return 0;
206}
207
208// XYQ: function for searching Unicode in the glyph list
209void FXFT_adobe_name_from_unicode(char* glyph_name, FT_UInt32 unicode)
210{
211	int i, count;
212
213	// start from top level node
214	count = ft_adobe_glyph_list[1];
215	for (i = 0; i < count; i ++) {
216		int child_offset = ft_adobe_glyph_list[i*2+2] * 256 + ft_adobe_glyph_list[i*2+3];
217		if (xyq_search_node(glyph_name, 0, child_offset, unicode))
218			return;
219	}
220
221	// failed, clear the buffer
222	glyph_name[0] = 0;
223}
224#endif
225
226  /* ft_qsort callback to sort the unicode map */
227  FT_CALLBACK_DEF( int )
228  compare_uni_maps( const void*  a,
229                    const void*  b )
230  {
231    PS_UniMap*  map1 = (PS_UniMap*)a;
232    PS_UniMap*  map2 = (PS_UniMap*)b;
233    FT_UInt32   unicode1 = BASE_GLYPH( map1->unicode );
234    FT_UInt32   unicode2 = BASE_GLYPH( map2->unicode );
235
236
237    /* sort base glyphs before glyph variants */
238    if ( unicode1 == unicode2 )
239    {
240      if ( map1->unicode > map2->unicode )
241        return 1;
242      else if ( map1->unicode < map2->unicode )
243        return -1;
244      else
245        return 0;
246    }
247    else
248    {
249      if ( unicode1 > unicode2 )
250        return 1;
251      else if ( unicode1 < unicode2 )
252        return -1;
253      else
254        return 0;
255    }
256  }
257
258
259  /* support for extra glyphs not handled (well) in AGL; */
260  /* we add extra mappings for them if necessary         */
261
262#define EXTRA_GLYPH_LIST_SIZE  10
263
264  static const FT_UInt32  ft_extra_glyph_unicodes[EXTRA_GLYPH_LIST_SIZE] =
265  {
266    /* WGL 4 */
267    0x0394,
268    0x03A9,
269    0x2215,
270    0x00AD,
271    0x02C9,
272    0x03BC,
273    0x2219,
274    0x00A0,
275    /* Romanian */
276    0x021A,
277    0x021B
278  };
279
280  static const char  ft_extra_glyph_names[] =
281  {
282    'D','e','l','t','a',0,
283    'O','m','e','g','a',0,
284    'f','r','a','c','t','i','o','n',0,
285    'h','y','p','h','e','n',0,
286    'm','a','c','r','o','n',0,
287    'm','u',0,
288    'p','e','r','i','o','d','c','e','n','t','e','r','e','d',0,
289    's','p','a','c','e',0,
290    'T','c','o','m','m','a','a','c','c','e','n','t',0,
291    't','c','o','m','m','a','a','c','c','e','n','t',0
292  };
293
294  static const FT_Int
295  ft_extra_glyph_name_offsets[EXTRA_GLYPH_LIST_SIZE] =
296  {
297     0,
298     6,
299    12,
300    21,
301    28,
302    35,
303    38,
304    53,
305    59,
306    72
307  };
308
309
310  static void
311  ps_check_extra_glyph_name( const char*  gname,
312                             FT_UInt      glyph,
313                             FT_UInt*     extra_glyphs,
314                             FT_UInt     *states )
315  {
316    FT_UInt  n;
317
318
319    for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
320    {
321      if ( ft_strcmp( ft_extra_glyph_names +
322                        ft_extra_glyph_name_offsets[n], gname ) == 0 )
323      {
324        if ( states[n] == 0 )
325        {
326          /* mark this extra glyph as a candidate for the cmap */
327          states[n]     = 1;
328          extra_glyphs[n] = glyph;
329        }
330
331        return;
332      }
333    }
334  }
335
336
337  static void
338  ps_check_extra_glyph_unicode( FT_UInt32  uni_char,
339                                FT_UInt   *states )
340  {
341    FT_UInt  n;
342
343
344    for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
345    {
346      if ( uni_char == ft_extra_glyph_unicodes[n] )
347      {
348        /* disable this extra glyph from being added to the cmap */
349        states[n] = 2;
350
351        return;
352      }
353    }
354  }
355
356
357  /* Build a table that maps Unicode values to glyph indices. */
358  static FT_Error
359  ps_unicodes_init( FT_Memory             memory,
360                    PS_Unicodes           table,
361                    FT_UInt               num_glyphs,
362                    PS_GetGlyphNameFunc   get_glyph_name,
363                    PS_FreeGlyphNameFunc  free_glyph_name,
364                    FT_Pointer            glyph_data )
365  {
366    FT_Error  error;
367
368    FT_UInt  extra_glyph_list_states[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
369    FT_UInt  extra_glyphs[EXTRA_GLYPH_LIST_SIZE];
370
371
372    /* we first allocate the table */
373    table->num_maps = 0;
374    table->maps     = 0;
375
376    if ( !FT_NEW_ARRAY( table->maps, num_glyphs + EXTRA_GLYPH_LIST_SIZE ) )
377    {
378      FT_UInt     n;
379      FT_UInt     count;
380      PS_UniMap*  map;
381      FT_UInt32   uni_char;
382
383
384      map = table->maps;
385
386      for ( n = 0; n < num_glyphs; n++ )
387      {
388        const char*  gname = get_glyph_name( glyph_data, n );
389
390
391        if ( gname )
392        {
393          ps_check_extra_glyph_name( gname, n,
394                                     extra_glyphs, extra_glyph_list_states );
395          uni_char = FXFT_unicode_from_adobe_name( gname );
396
397          if ( BASE_GLYPH( uni_char ) != 0 )
398          {
399            ps_check_extra_glyph_unicode( uni_char,
400                                          extra_glyph_list_states );
401            map->unicode     = uni_char;
402            map->glyph_index = n;
403            map++;
404          }
405
406          if ( free_glyph_name )
407            free_glyph_name( glyph_data, gname );
408        }
409      }
410
411      for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
412      {
413        if ( extra_glyph_list_states[n] == 1 )
414        {
415          /* This glyph name has an additional representation. */
416          /* Add it to the cmap.                               */
417
418          map->unicode     = ft_extra_glyph_unicodes[n];
419          map->glyph_index = extra_glyphs[n];
420          map++;
421        }
422      }
423
424      /* now compress the table a bit */
425      count = (FT_UInt)( map - table->maps );
426
427      if ( count == 0 )
428      {
429        /* No unicode chars here! */
430        FT_FREE( table->maps );
431        if ( !error )
432          error = FT_THROW( No_Unicode_Glyph_Name );
433      }
434      else
435      {
436        /* Reallocate if the number of used entries is much smaller. */
437        if ( count < num_glyphs / 2 )
438        {
439          (void)FT_RENEW_ARRAY( table->maps, num_glyphs, count );
440          error = FT_Err_Ok;
441        }
442
443        /* Sort the table in increasing order of unicode values, */
444        /* taking care of glyph variants.                        */
445        ft_qsort( table->maps, count, sizeof ( PS_UniMap ),
446                  compare_uni_maps );
447      }
448
449      table->num_maps = count;
450    }
451
452    return error;
453  }
454
455
456  static FT_UInt
457  ps_unicodes_char_index( PS_Unicodes  table,
458                          FT_UInt32    unicode )
459  {
460    PS_UniMap  *min, *max, *mid, *result = NULL;
461
462
463    /* Perform a binary search on the table. */
464
465    min = table->maps;
466    max = min + table->num_maps - 1;
467
468    while ( min <= max )
469    {
470      FT_UInt32  base_glyph;
471
472
473      mid = min + ( ( max - min ) >> 1 );
474
475      if ( mid->unicode == unicode )
476      {
477        result = mid;
478        break;
479      }
480
481      base_glyph = BASE_GLYPH( mid->unicode );
482
483      if ( base_glyph == unicode )
484        result = mid; /* remember match but continue search for base glyph */
485
486      if ( min == max )
487        break;
488
489      if ( base_glyph < unicode )
490        min = mid + 1;
491      else
492        max = mid - 1;
493    }
494
495    if ( result )
496      return result->glyph_index;
497    else
498      return 0;
499  }
500
501
502  static FT_UInt32
503  ps_unicodes_char_next( PS_Unicodes  table,
504                         FT_UInt32   *unicode )
505  {
506    FT_UInt    result    = 0;
507    FT_UInt32  char_code = *unicode + 1;
508
509
510    {
511      FT_UInt     min = 0;
512      FT_UInt     max = table->num_maps;
513      FT_UInt     mid;
514      PS_UniMap*  map;
515      FT_UInt32   base_glyph;
516
517
518      while ( min < max )
519      {
520        mid = min + ( ( max - min ) >> 1 );
521        map = table->maps + mid;
522
523        if ( map->unicode == char_code )
524        {
525          result = map->glyph_index;
526          goto Exit;
527        }
528
529        base_glyph = BASE_GLYPH( map->unicode );
530
531        if ( base_glyph == char_code )
532          result = map->glyph_index;
533
534        if ( base_glyph < char_code )
535          min = mid + 1;
536        else
537          max = mid;
538      }
539
540      if ( result )
541        goto Exit;               /* we have a variant glyph */
542
543      /* we didn't find it; check whether we have a map just above it */
544      char_code = 0;
545
546      if ( min < table->num_maps )
547      {
548        map       = table->maps + min;
549        result    = map->glyph_index;
550        char_code = BASE_GLYPH( map->unicode );
551      }
552    }
553
554  Exit:
555    *unicode = char_code;
556    return result;
557  }
558
559
560#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
561
562
563  static const char*
564  ps_get_macintosh_name( FT_UInt  name_index )
565  {
566    if ( name_index >= FT_NUM_MAC_NAMES )
567      name_index = 0;
568
569    return ft_standard_glyph_names + ft_mac_names[name_index];
570  }
571
572
573  static const char*
574  ps_get_standard_strings( FT_UInt  sid )
575  {
576    if ( sid >= FT_NUM_SID_NAMES )
577      return 0;
578
579    return ft_standard_glyph_names + ft_sid_names[sid];
580  }
581
582
583#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
584
585  FT_DEFINE_SERVICE_PSCMAPSREC(
586    pscmaps_interface,
587    (PS_Unicode_ValueFunc)     FXFT_unicode_from_adobe_name,
588    (PS_Unicodes_InitFunc)     ps_unicodes_init,
589    (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index,
590    (PS_Unicodes_CharNextFunc) ps_unicodes_char_next,
591
592    (PS_Macintosh_NameFunc)    ps_get_macintosh_name,
593    (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
594
595    t1_standard_encoding,
596    t1_expert_encoding )
597
598#else
599
600  FT_DEFINE_SERVICE_PSCMAPSREC(
601    pscmaps_interface,
602    NULL,
603    NULL,
604    NULL,
605    NULL,
606
607    (PS_Macintosh_NameFunc)    ps_get_macintosh_name,
608    (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
609
610    t1_standard_encoding,
611    t1_expert_encoding )
612
613#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
614
615
616  FT_DEFINE_SERVICEDESCREC1(
617    pscmaps_services,
618    FT_SERVICE_ID_POSTSCRIPT_CMAPS, &PSCMAPS_INTERFACE_GET )
619
620
621  static FT_Pointer
622  psnames_get_service( FT_Module    module,
623                       const char*  service_id )
624  {
625    /* PSCMAPS_SERVICES_GET derefers `library' in PIC mode */
626#ifdef FT_CONFIG_OPTION_PIC
627    FT_Library  library;
628
629
630    if ( !module )
631      return NULL;
632    library = module->library;
633    if ( !library )
634      return NULL;
635#else
636    FT_UNUSED( module );
637#endif
638
639    return ft_service_list_lookup( PSCMAPS_SERVICES_GET, service_id );
640  }
641
642#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
643
644
645#ifndef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
646#define PUT_PS_NAMES_SERVICE( a )  NULL
647#else
648#define PUT_PS_NAMES_SERVICE( a )  a
649#endif
650
651  FT_DEFINE_MODULE(
652    psnames_module_class,
653
654    0,  /* this is not a font driver, nor a renderer */
655    sizeof ( FT_ModuleRec ),
656
657    "psnames",  /* driver name                         */
658    0x10000L,   /* driver version                      */
659    0x20000L,   /* driver requires FreeType 2 or above */
660
661    PUT_PS_NAMES_SERVICE(
662      (void*)&PSCMAPS_INTERFACE_GET ),   /* module specific interface */
663    (FT_Module_Constructor)NULL,
664    (FT_Module_Destructor) NULL,
665    (FT_Module_Requester)  PUT_PS_NAMES_SERVICE( psnames_get_service ) )
666
667
668/* END */
669#endif
670
671