xref: /inferno-os/libfreetype/t1cmap.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1 /***************************************************************************/
2 /*                                                                         */
3 /*  t1cmap.c                                                               */
4 /*                                                                         */
5 /*    Type 1 character map support (body).                                 */
6 /*                                                                         */
7 /*  Copyright 2002 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 "t1cmap.h"
20 
21 #include FT_INTERNAL_DEBUG_H
22 
23 
24   /*************************************************************************/
25   /*************************************************************************/
26   /*****                                                               *****/
27   /*****          TYPE1 STANDARD (AND EXPERT) ENCODING CMAPS           *****/
28   /*****                                                               *****/
29   /*************************************************************************/
30   /*************************************************************************/
31 
32   static void
t1_cmap_std_init(T1_CMapStd cmap,FT_Int is_expert)33   t1_cmap_std_init( T1_CMapStd  cmap,
34                     FT_Int      is_expert )
35   {
36     T1_Face          face    = (T1_Face)FT_CMAP_FACE( cmap );
37     PSNames_Service  psnames = (PSNames_Service)face->psnames;
38 
39 
40     cmap->num_glyphs    = face->type1.num_glyphs;
41     cmap->glyph_names   = (const char* const*)face->type1.glyph_names;
42     cmap->sid_to_string = psnames->adobe_std_strings;
43     cmap->code_to_sid   = is_expert ? psnames->adobe_expert_encoding
44                                     : psnames->adobe_std_encoding;
45 
46     FT_ASSERT( cmap->code_to_sid != NULL );
47   }
48 
49 
50   FT_CALLBACK_DEF( void )
t1_cmap_std_done(T1_CMapStd cmap)51   t1_cmap_std_done( T1_CMapStd  cmap )
52   {
53     cmap->num_glyphs    = 0;
54     cmap->glyph_names   = NULL;
55     cmap->sid_to_string = NULL;
56     cmap->code_to_sid   = NULL;
57   }
58 
59 
60   FT_CALLBACK_DEF( FT_UInt )
t1_cmap_std_char_index(T1_CMapStd cmap,FT_UInt32 char_code)61   t1_cmap_std_char_index( T1_CMapStd  cmap,
62                           FT_UInt32   char_code )
63   {
64     FT_UInt  result = 0;
65 
66 
67     if ( char_code < 256 )
68     {
69       FT_UInt      code, n;
70       const char*  glyph_name;
71 
72 
73       /* convert character code to Adobe SID string */
74       code       = cmap->code_to_sid[char_code];
75       glyph_name = cmap->sid_to_string( code );
76 
77       /* look for the corresponding glyph name */
78       for ( n = 0; n < cmap->num_glyphs; n++ )
79       {
80         const char* gname = cmap->glyph_names[n];
81 
82 
83         if ( gname && gname[0] == glyph_name[0]  &&
84              ft_strcmp( gname, glyph_name ) == 0 )
85         {
86           result = n;
87           break;
88         }
89       }
90     }
91 
92     return result;
93   }
94 
95 
96   FT_CALLBACK_DEF( FT_UInt )
t1_cmap_std_char_next(T1_CMapStd cmap,FT_UInt32 * pchar_code)97   t1_cmap_std_char_next( T1_CMapStd   cmap,
98                          FT_UInt32   *pchar_code )
99   {
100     FT_UInt    result    = 0;
101     FT_UInt32  char_code = *pchar_code + 1;
102 
103 
104     while ( char_code < 256 )
105     {
106       result = t1_cmap_std_char_index( cmap, char_code );
107       if ( result != 0 )
108         goto Exit;
109 
110       char_code++;
111     }
112     char_code = 0;
113 
114   Exit:
115     *pchar_code = char_code;
116     return result;
117   }
118 
119 
120   FT_CALLBACK_DEF( FT_Error )
t1_cmap_standard_init(T1_CMapStd cmap)121   t1_cmap_standard_init( T1_CMapStd  cmap )
122   {
123     t1_cmap_std_init( cmap, 0 );
124     return 0;
125   }
126 
127 
128   FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec
129   t1_cmap_standard_class_rec =
130   {
131     sizeof ( T1_CMapStdRec ),
132 
133     (FT_CMap_InitFunc)     t1_cmap_standard_init,
134     (FT_CMap_DoneFunc)     t1_cmap_std_done,
135     (FT_CMap_CharIndexFunc)t1_cmap_std_char_index,
136     (FT_CMap_CharNextFunc) t1_cmap_std_char_next
137   };
138 
139 
140   FT_CALLBACK_DEF( FT_Error )
t1_cmap_expert_init(T1_CMapStd cmap)141   t1_cmap_expert_init( T1_CMapStd  cmap )
142   {
143     t1_cmap_std_init( cmap, 1 );
144     return 0;
145   }
146 
147   FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec
148   t1_cmap_expert_class_rec =
149   {
150     sizeof ( T1_CMapStdRec ),
151 
152     (FT_CMap_InitFunc)     t1_cmap_expert_init,
153     (FT_CMap_DoneFunc)     t1_cmap_std_done,
154     (FT_CMap_CharIndexFunc)t1_cmap_std_char_index,
155     (FT_CMap_CharNextFunc) t1_cmap_std_char_next
156   };
157 
158 
159   /*************************************************************************/
160   /*************************************************************************/
161   /*****                                                               *****/
162   /*****                    TYPE1 CUSTOM ENCODING CMAP                 *****/
163   /*****                                                               *****/
164   /*************************************************************************/
165   /*************************************************************************/
166 
167 
168   FT_CALLBACK_DEF( FT_Error )
t1_cmap_custom_init(T1_CMapCustom cmap)169   t1_cmap_custom_init( T1_CMapCustom  cmap )
170   {
171     T1_Face      face     = (T1_Face)FT_CMAP_FACE( cmap );
172     T1_Encoding  encoding = &face->type1.encoding;
173 
174 
175     cmap->first   = encoding->code_first;
176     cmap->count   = (FT_UInt)( encoding->code_last - cmap->first + 1 );
177     cmap->indices = encoding->char_index;
178 
179     FT_ASSERT( cmap->indices != NULL );
180     FT_ASSERT( encoding->code_first <= encoding->code_last );
181 
182     return 0;
183   }
184 
185 
186   FT_CALLBACK_DEF( void )
t1_cmap_custom_done(T1_CMapCustom cmap)187   t1_cmap_custom_done( T1_CMapCustom  cmap )
188   {
189     cmap->indices = NULL;
190     cmap->first   = 0;
191     cmap->count   = 0;
192   }
193 
194 
195   FT_CALLBACK_DEF( FT_UInt )
t1_cmap_custom_char_index(T1_CMapCustom cmap,FT_UInt32 char_code)196   t1_cmap_custom_char_index( T1_CMapCustom  cmap,
197                              FT_UInt32      char_code )
198   {
199     FT_UInt    result = 0;
200 
201 
202     if ( ( char_code >= cmap->first )                  &&
203          ( char_code < ( cmap->first + cmap->count ) ) )
204       result = cmap->indices[char_code];
205 
206     return result;
207   }
208 
209 
210   FT_CALLBACK_DEF( FT_UInt )
t1_cmap_custom_char_next(T1_CMapCustom cmap,FT_UInt32 * pchar_code)211   t1_cmap_custom_char_next( T1_CMapCustom  cmap,
212                             FT_UInt32     *pchar_code )
213   {
214     FT_UInt    result = 0;
215     FT_UInt32  char_code = *pchar_code;
216 
217 
218     ++char_code;
219 
220     if ( char_code < cmap->first )
221       char_code = cmap->first;
222 
223     for ( ; char_code < ( cmap->first + cmap->count ); char_code++ )
224     {
225       result = cmap->indices[char_code];
226       if ( result != 0 )
227         goto Exit;
228     }
229 
230     char_code = 0;
231 
232   Exit:
233     *pchar_code = char_code;
234     return result;
235   }
236 
237 
238   FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec
239   t1_cmap_custom_class_rec =
240   {
241     sizeof ( T1_CMapCustomRec ),
242 
243     (FT_CMap_InitFunc)     t1_cmap_custom_init,
244     (FT_CMap_DoneFunc)     t1_cmap_custom_done,
245     (FT_CMap_CharIndexFunc)t1_cmap_custom_char_index,
246     (FT_CMap_CharNextFunc) t1_cmap_custom_char_next
247   };
248 
249 
250   /*************************************************************************/
251   /*************************************************************************/
252   /*****                                                               *****/
253   /*****            TYPE1 SYNTHETIC UNICODE ENCODING CMAP              *****/
254   /*****                                                               *****/
255   /*************************************************************************/
256   /*************************************************************************/
257 
258   FT_CALLBACK_DEF( FT_Int )
t1_cmap_uni_pair_compare(const void * pair1,const void * pair2)259   t1_cmap_uni_pair_compare( const void*  pair1,
260                             const void*  pair2 )
261   {
262     FT_UInt32  u1 = ((T1_CMapUniPair)pair1)->unicode;
263     FT_UInt32  u2 = ((T1_CMapUniPair)pair2)->unicode;
264 
265 
266     if ( u1 < u2 )
267       return -1;
268 
269     if ( u1 > u2 )
270       return +1;
271 
272     return 0;
273   }
274 
275 
276   FT_CALLBACK_DEF( FT_Error )
t1_cmap_unicode_init(T1_CMapUnicode cmap)277   t1_cmap_unicode_init( T1_CMapUnicode  cmap )
278   {
279     FT_Error         error;
280     FT_UInt          count;
281     T1_Face          face    = (T1_Face)FT_CMAP_FACE( cmap );
282     FT_Memory        memory  = FT_FACE_MEMORY( face );
283     PSNames_Service  psnames = (PSNames_Service)face->psnames;
284 
285 
286     cmap->num_pairs = 0;
287     cmap->pairs     = NULL;
288 
289     count = face->type1.num_glyphs;
290 
291     if ( !FT_NEW_ARRAY( cmap->pairs, count ) )
292     {
293       FT_UInt         n, new_count;
294       T1_CMapUniPair  pair;
295       FT_UInt32       uni_code;
296 
297 
298       pair = cmap->pairs;
299       for ( n = 0; n < count; n++ )
300       {
301         const char*  gname = face->type1.glyph_names[n];
302 
303 
304         /* build unsorted pair table by matching glyph names */
305         if ( gname )
306         {
307           uni_code = psnames->unicode_value( gname );
308 
309           if ( uni_code != 0 )
310           {
311             pair->unicode = uni_code;
312             pair->gindex  = n;
313             pair++;
314           }
315         }
316       }
317 
318       new_count = (FT_UInt)( pair - cmap->pairs );
319       if ( new_count == 0 )
320       {
321         /* there are no unicode characters in here! */
322         FT_FREE( cmap->pairs );
323         error = FT_Err_Invalid_Argument;
324       }
325       else
326       {
327         /* re-allocate if the new array is much smaller than the original */
328         /* one                                                            */
329         if ( new_count != count && new_count < count / 2 )
330         {
331           (void)FT_RENEW_ARRAY( cmap->pairs, count, new_count );
332           error = 0;
333         }
334 
335         /* sort the pairs table to allow efficient binary searches */
336         ft_qsort( cmap->pairs,
337                   new_count,
338                   sizeof ( T1_CMapUniPairRec ),
339                   t1_cmap_uni_pair_compare );
340 
341         cmap->num_pairs = new_count;
342       }
343     }
344 
345     return error;
346   }
347 
348 
349   FT_CALLBACK_DEF( void )
t1_cmap_unicode_done(T1_CMapUnicode cmap)350   t1_cmap_unicode_done( T1_CMapUnicode  cmap )
351   {
352     FT_Face    face   = FT_CMAP_FACE(cmap);
353     FT_Memory  memory = FT_FACE_MEMORY(face);
354 
355     FT_FREE( cmap->pairs );
356     cmap->num_pairs = 0;
357   }
358 
359 
360   FT_CALLBACK_DEF( FT_UInt )
t1_cmap_unicode_char_index(T1_CMapUnicode cmap,FT_UInt32 char_code)361   t1_cmap_unicode_char_index( T1_CMapUnicode  cmap,
362                               FT_UInt32       char_code )
363   {
364     FT_UInt         min = 0;
365     FT_UInt         max = cmap->num_pairs;
366     FT_UInt         mid;
367     T1_CMapUniPair  pair;
368 
369 
370     while ( min < max )
371     {
372       mid  = min + ( max - min ) / 2;
373       pair = cmap->pairs + mid;
374 
375       if ( pair->unicode == char_code )
376         return pair->gindex;
377 
378       if ( pair->unicode < char_code )
379         min = mid + 1;
380       else
381         max = mid;
382     }
383     return 0;
384   }
385 
386 
387   FT_CALLBACK_DEF( FT_UInt )
t1_cmap_unicode_char_next(T1_CMapUnicode cmap,FT_UInt32 * pchar_code)388   t1_cmap_unicode_char_next( T1_CMapUnicode  cmap,
389                              FT_UInt32      *pchar_code )
390   {
391     FT_UInt    result    = 0;
392     FT_UInt32  char_code = *pchar_code + 1;
393 
394 
395   Restart:
396     {
397       FT_UInt         min = 0;
398       FT_UInt         max = cmap->num_pairs;
399       FT_UInt         mid;
400       T1_CMapUniPair  pair;
401 
402 
403       while ( min < max )
404       {
405         mid  = min + ( ( max - min ) >> 1 );
406         pair = cmap->pairs + mid;
407 
408         if ( pair->unicode == char_code )
409         {
410           result = pair->gindex;
411           if ( result != 0 )
412             goto Exit;
413 
414           char_code++;
415           goto Restart;
416         }
417 
418         if ( pair->unicode < char_code )
419           min = mid+1;
420         else
421           max = mid;
422       }
423 
424       /* we didn't find it, but we have a pair just above it */
425       char_code = 0;
426 
427       if ( min < cmap->num_pairs )
428       {
429         pair   = cmap->pairs + min;
430         result = pair->gindex;
431         if ( result != 0 )
432           char_code = pair->unicode;
433       }
434     }
435 
436   Exit:
437     *pchar_code = char_code;
438     return result;
439   }
440 
441 
442   FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec
443   t1_cmap_unicode_class_rec =
444   {
445     sizeof ( T1_CMapUnicodeRec ),
446 
447     (FT_CMap_InitFunc)     t1_cmap_unicode_init,
448     (FT_CMap_DoneFunc)     t1_cmap_unicode_done,
449     (FT_CMap_CharIndexFunc)t1_cmap_unicode_char_index,
450     (FT_CMap_CharNextFunc) t1_cmap_unicode_char_next
451   };
452 
453 
454 /* END */
455