source: trunk/poppler/freetype-2.1.10/src/cff/cffcmap.c @ 2

Last change on this file since 2 was 2, checked in by Eugene Romanenko, 15 years ago

First import

File size: 8.7 KB
Line 
1/***************************************************************************/
2/*                                                                         */
3/*  cffcmap.c                                                              */
4/*                                                                         */
5/*    CFF character mapping table (cmap) support (body).                   */
6/*                                                                         */
7/*  Copyright 2002, 2003, 2004, 2005 by                                    */
8/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9/*                                                                         */
10/*  This file is part of the FreeType project, and may only be used,       */
11/*  modified, and distributed under the terms of the FreeType project      */
12/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13/*  this file you indicate that you have read the license and              */
14/*  understand and accept it fully.                                        */
15/*                                                                         */
16/***************************************************************************/
17
18
19#include "cffcmap.h"
20#include "cffload.h"
21
22#include "cfferrs.h"
23
24
25  /*************************************************************************/
26  /*************************************************************************/
27  /*****                                                               *****/
28  /*****           CFF STANDARD (AND EXPERT) ENCODING CMAPS            *****/
29  /*****                                                               *****/
30  /*************************************************************************/
31  /*************************************************************************/
32
33  FT_CALLBACK_DEF( FT_Error )
34  cff_cmap_encoding_init( CFF_CMapStd  cmap )
35  {
36    TT_Face       face     = (TT_Face)FT_CMAP_FACE( cmap );
37    CFF_Font      cff      = (CFF_Font)face->extra.data;
38    CFF_Encoding  encoding = &cff->encoding;
39
40
41    cmap->gids  = encoding->codes;
42
43    return 0;
44  }
45
46
47  FT_CALLBACK_DEF( void )
48  cff_cmap_encoding_done( CFF_CMapStd  cmap )
49  {
50    cmap->gids  = NULL;
51  }
52
53
54  FT_CALLBACK_DEF( FT_UInt )
55  cff_cmap_encoding_char_index( CFF_CMapStd  cmap,
56                                FT_UInt32    char_code )
57  {
58    FT_UInt  result = 0;
59
60
61    if ( char_code < 256 )
62      result = cmap->gids[char_code];
63
64    return result;
65  }
66
67
68  FT_CALLBACK_DEF( FT_UInt )
69  cff_cmap_encoding_char_next( CFF_CMapStd   cmap,
70                               FT_UInt32    *pchar_code )
71  {
72    FT_UInt    result    = 0;
73    FT_UInt32  char_code = *pchar_code;
74
75
76    *pchar_code = 0;
77
78    if ( char_code < 255 )
79    {
80      FT_UInt  code = (FT_UInt)(char_code + 1);
81
82
83      for (;;)
84      {
85        if ( code >= 256 )
86          break;
87
88        result = cmap->gids[code];
89        if ( result != 0 )
90        {
91          *pchar_code = code;
92          break;
93        }
94
95        code++;
96      }
97    }
98    return result;
99  }
100
101
102  FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec
103  cff_cmap_encoding_class_rec =
104  {
105    sizeof ( CFF_CMapStdRec ),
106
107    (FT_CMap_InitFunc)     cff_cmap_encoding_init,
108    (FT_CMap_DoneFunc)     cff_cmap_encoding_done,
109    (FT_CMap_CharIndexFunc)cff_cmap_encoding_char_index,
110    (FT_CMap_CharNextFunc) cff_cmap_encoding_char_next
111  };
112
113
114  /*************************************************************************/
115  /*************************************************************************/
116  /*****                                                               *****/
117  /*****              CFF SYNTHETIC UNICODE ENCODING CMAP              *****/
118  /*****                                                               *****/
119  /*************************************************************************/
120  /*************************************************************************/
121
122  FT_CALLBACK_DEF( FT_Int )
123  cff_cmap_uni_pair_compare( const void*  pair1,
124                             const void*  pair2 )
125  {
126    FT_UInt32  u1 = ((CFF_CMapUniPair)pair1)->unicode;
127    FT_UInt32  u2 = ((CFF_CMapUniPair)pair2)->unicode;
128
129
130    if ( u1 < u2 )
131      return -1;
132
133    if ( u1 > u2 )
134      return +1;
135
136    return 0;
137  }
138
139
140  FT_CALLBACK_DEF( FT_Error )
141  cff_cmap_unicode_init( CFF_CMapUnicode  cmap )
142  {
143    FT_Error            error;
144    FT_UInt             count;
145    TT_Face             face    = (TT_Face)FT_CMAP_FACE( cmap );
146    FT_Memory           memory  = FT_FACE_MEMORY( face );
147    CFF_Font            cff     = (CFF_Font)face->extra.data;
148    CFF_Charset         charset = &cff->charset;
149    FT_Service_PsCMaps  psnames = (FT_Service_PsCMaps)cff->psnames;
150
151
152    /* can't build Unicode map for CID-keyed font */
153    if ( !charset->sids )
154    {
155      error = CFF_Err_Invalid_Argument;
156      goto Exit;
157    }
158
159    cmap->num_pairs = 0;
160    cmap->pairs     = NULL;
161
162    count = cff->num_glyphs;
163
164    if ( !FT_NEW_ARRAY( cmap->pairs, count ) )
165    {
166      FT_UInt          n, new_count;
167      CFF_CMapUniPair  pair;
168      FT_UInt32        uni_code;
169
170
171      pair = cmap->pairs;
172      for ( n = 0; n < count; n++ )
173      {
174        FT_UInt      sid = charset->sids[n];
175        const char*  gname;
176
177
178        gname = cff_index_get_sid_string( &cff->string_index, sid, psnames );
179
180        /* build unsorted pair table by matching glyph names */
181        if ( gname )
182        {
183          uni_code = psnames->unicode_value( gname );
184
185          if ( uni_code != 0 )
186          {
187            pair->unicode = uni_code;
188            pair->gindex  = n;
189            pair++;
190          }
191
192          FT_FREE( gname );
193        }
194      }
195
196      new_count = (FT_UInt)( pair - cmap->pairs );
197      if ( new_count == 0 )
198      {
199        /* there are no unicode characters in here! */
200        FT_FREE( cmap->pairs );
201        error = CFF_Err_Invalid_Argument;
202      }
203      else
204      {
205        /* re-allocate if the new array is much smaller than the original */
206        /* one                                                            */
207        if ( new_count != count && new_count < count / 2 )
208        {
209          (void)FT_RENEW_ARRAY( cmap->pairs, count, new_count );
210          error = CFF_Err_Ok;
211        }
212
213        /* sort the pairs table to allow efficient binary searches */
214        ft_qsort( cmap->pairs,
215                  new_count,
216                  sizeof ( CFF_CMapUniPairRec ),
217                  cff_cmap_uni_pair_compare );
218
219        cmap->num_pairs = new_count;
220      }
221    }
222
223  Exit:
224    return error;
225  }
226
227
228  FT_CALLBACK_DEF( void )
229  cff_cmap_unicode_done( CFF_CMapUnicode  cmap )
230  {
231    FT_Face    face   = FT_CMAP_FACE( cmap );
232    FT_Memory  memory = FT_FACE_MEMORY( face );
233
234
235    FT_FREE( cmap->pairs );
236    cmap->num_pairs = 0;
237  }
238
239
240  FT_CALLBACK_DEF( FT_UInt )
241  cff_cmap_unicode_char_index( CFF_CMapUnicode  cmap,
242                               FT_UInt32        char_code )
243  {
244    FT_UInt          min = 0;
245    FT_UInt          max = cmap->num_pairs;
246    FT_UInt          mid;
247    CFF_CMapUniPair  pair;
248
249
250    while ( min < max )
251    {
252      mid  = min + ( max - min ) / 2;
253      pair = cmap->pairs + mid;
254
255      if ( pair->unicode == char_code )
256        return pair->gindex;
257
258      if ( pair->unicode < char_code )
259        min = mid + 1;
260      else
261        max = mid;
262    }
263    return 0;
264  }
265
266
267  FT_CALLBACK_DEF( FT_UInt )
268  cff_cmap_unicode_char_next( CFF_CMapUnicode  cmap,
269                              FT_UInt32       *pchar_code )
270  {
271    FT_UInt    result    = 0;
272    FT_UInt32  char_code = *pchar_code + 1;
273
274
275  Restart:
276    {
277      FT_UInt          min = 0;
278      FT_UInt          max = cmap->num_pairs;
279      FT_UInt          mid;
280      CFF_CMapUniPair  pair;
281
282
283      while ( min < max )
284      {
285        mid  = min + ( ( max - min ) >> 1 );
286        pair = cmap->pairs + mid;
287
288        if ( pair->unicode == char_code )
289        {
290          result = pair->gindex;
291          if ( result != 0 )
292            goto Exit;
293
294          char_code++;
295          goto Restart;
296        }
297
298        if ( pair->unicode < char_code )
299          min = mid+1;
300        else
301          max = mid;
302      }
303
304      /* we didn't find it, but we have a pair just above it */
305      char_code = 0;
306
307      if ( min < cmap->num_pairs )
308      {
309        pair   = cmap->pairs + min;
310        result = pair->gindex;
311        if ( result != 0 )
312          char_code = pair->unicode;
313      }
314    }
315
316  Exit:
317    *pchar_code = char_code;
318    return result;
319  }
320
321
322  FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec
323  cff_cmap_unicode_class_rec =
324  {
325    sizeof ( CFF_CMapUnicodeRec ),
326
327    (FT_CMap_InitFunc)     cff_cmap_unicode_init,
328    (FT_CMap_DoneFunc)     cff_cmap_unicode_done,
329    (FT_CMap_CharIndexFunc)cff_cmap_unicode_char_index,
330    (FT_CMap_CharNextFunc) cff_cmap_unicode_char_next
331  };
332
333
334/* END */
Note: See TracBrowser for help on using the repository browser.