xref: /inferno-os/libfreetype/cffcmap.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1 /***************************************************************************/
2 /*                                                                         */
3 /*  cffcmap.c                                                              */
4 /*                                                                         */
5 /*    CFF character mapping table (cmap) 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 "cffcmap.h"
20 #include "cffload.h"
21 
22 
23   /*************************************************************************/
24   /*************************************************************************/
25   /*****                                                               *****/
26   /*****           CFF STANDARD (AND EXPERT) ENCODING CMAPS            *****/
27   /*****                                                               *****/
28   /*************************************************************************/
29   /*************************************************************************/
30 
31   FT_CALLBACK_DEF( FT_Error )
cff_cmap_encoding_init(CFF_CMapStd cmap)32   cff_cmap_encoding_init( CFF_CMapStd  cmap )
33   {
34     TT_Face       face     = (TT_Face)FT_CMAP_FACE( cmap );
35     CFF_Font      cff      = (CFF_Font)face->extra.data;
36     CFF_Encoding  encoding = &cff->encoding;
37 
38 
39     cmap->count = encoding->count;
40     cmap->gids  = encoding->codes;
41 
42     return 0;
43   }
44 
45 
46   FT_CALLBACK_DEF( void )
cff_cmap_encoding_done(CFF_CMapStd cmap)47   cff_cmap_encoding_done( CFF_CMapStd  cmap )
48   {
49     cmap->count = 0;
50     cmap->gids  = NULL;
51   }
52 
53 
54   FT_CALLBACK_DEF( FT_UInt )
cff_cmap_encoding_char_index(CFF_CMapStd cmap,FT_UInt32 char_code)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 < cmap->count )
62       result = cmap->gids[char_code];
63 
64     return result;
65   }
66 
67 
68   FT_CALLBACK_DEF( FT_UInt )
cff_cmap_encoding_char_next(CFF_CMapStd cmap,FT_UInt32 * pchar_code)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 < cmap->count )
79     {
80       FT_UInt  code = (FT_UInt)(char_code + 1);
81 
82 
83       for (;;)
84       {
85         if ( code >= cmap->count )
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 )
cff_cmap_uni_pair_compare(const void * pair1,const void * pair2)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 )
cff_cmap_unicode_init(CFF_CMapUnicode cmap)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     PSNames_Service  psnames = (PSNames_Service)cff->psnames;
150 
151 
152     cmap->num_pairs = 0;
153     cmap->pairs     = NULL;
154 
155     count = (FT_UInt)face->root.num_glyphs;
156 
157     if ( !FT_NEW_ARRAY( cmap->pairs, count ) )
158     {
159       FT_UInt          n, new_count;
160       CFF_CMapUniPair  pair;
161       FT_UInt32        uni_code;
162 
163 
164       pair = cmap->pairs;
165       for ( n = 0; n < count; n++ )
166       {
167         FT_UInt      sid   = charset->sids[n];
168         const char*  gname;
169 
170 
171         gname = cff_index_get_sid_string( &cff->string_index, sid, psnames );
172 
173         /* build unsorted pair table by matching glyph names */
174         if ( gname )
175         {
176           uni_code = psnames->unicode_value( gname );
177 
178           if ( uni_code != 0 )
179           {
180             pair->unicode = uni_code;
181             pair->gindex  = n;
182             pair++;
183           }
184 
185           FT_FREE( gname );
186         }
187       }
188 
189       new_count = (FT_UInt)( pair - cmap->pairs );
190       if ( new_count == 0 )
191       {
192         /* there are no unicode characters in here! */
193         FT_FREE( cmap->pairs );
194         error = FT_Err_Invalid_Argument;
195       }
196       else
197       {
198         /* re-allocate if the new array is much smaller than the original */
199         /* one                                                            */
200         if ( new_count != count && new_count < count / 2 )
201         {
202           (void)FT_RENEW_ARRAY( cmap->pairs, count, new_count );
203           error = 0;
204         }
205 
206         /* sort the pairs table to allow efficient binary searches */
207         ft_qsort( cmap->pairs,
208                   new_count,
209                   sizeof ( CFF_CMapUniPairRec ),
210                   cff_cmap_uni_pair_compare );
211 
212         cmap->num_pairs = new_count;
213       }
214     }
215 
216     return error;
217   }
218 
219 
220   FT_CALLBACK_DEF( void )
cff_cmap_unicode_done(CFF_CMapUnicode cmap)221   cff_cmap_unicode_done( CFF_CMapUnicode  cmap )
222   {
223     FT_Face    face   = FT_CMAP_FACE( cmap );
224     FT_Memory  memory = FT_FACE_MEMORY( face );
225 
226 
227     FT_FREE( cmap->pairs );
228     cmap->num_pairs = 0;
229   }
230 
231 
232   FT_CALLBACK_DEF( FT_UInt )
cff_cmap_unicode_char_index(CFF_CMapUnicode cmap,FT_UInt32 char_code)233   cff_cmap_unicode_char_index( CFF_CMapUnicode  cmap,
234                                FT_UInt32        char_code )
235   {
236     FT_UInt          min = 0;
237     FT_UInt          max = cmap->num_pairs;
238     FT_UInt          mid;
239     CFF_CMapUniPair  pair;
240 
241 
242     while ( min < max )
243     {
244       mid  = min + ( max - min ) / 2;
245       pair = cmap->pairs + mid;
246 
247       if ( pair->unicode == char_code )
248         return pair->gindex;
249 
250       if ( pair->unicode < char_code )
251         min = mid + 1;
252       else
253         max = mid;
254     }
255     return 0;
256   }
257 
258 
259   FT_CALLBACK_DEF( FT_UInt )
cff_cmap_unicode_char_next(CFF_CMapUnicode cmap,FT_UInt32 * pchar_code)260   cff_cmap_unicode_char_next( CFF_CMapUnicode  cmap,
261                               FT_UInt32       *pchar_code )
262   {
263     FT_UInt    result    = 0;
264     FT_UInt32  char_code = *pchar_code + 1;
265 
266 
267   Restart:
268     {
269       FT_UInt          min = 0;
270       FT_UInt          max = cmap->num_pairs;
271       FT_UInt          mid;
272       CFF_CMapUniPair  pair;
273 
274 
275       while ( min < max )
276       {
277         mid  = min + ( ( max - min ) >> 1 );
278         pair = cmap->pairs + mid;
279 
280         if ( pair->unicode == char_code )
281         {
282           result = pair->gindex;
283           if ( result != 0 )
284             goto Exit;
285 
286           char_code++;
287           goto Restart;
288         }
289 
290         if ( pair->unicode < char_code )
291           min = mid+1;
292         else
293           max = mid;
294       }
295 
296       /* we didn't find it, but we have a pair just above it */
297       char_code = 0;
298 
299       if ( min < cmap->num_pairs )
300       {
301         pair   = cmap->pairs + min;
302         result = pair->gindex;
303         if ( result != 0 )
304           char_code = pair->unicode;
305       }
306     }
307 
308   Exit:
309     *pchar_code = char_code;
310     return result;
311   }
312 
313 
314   FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec
315   cff_cmap_unicode_class_rec =
316   {
317     sizeof ( CFF_CMapUnicodeRec ),
318 
319     (FT_CMap_InitFunc)     cff_cmap_unicode_init,
320     (FT_CMap_DoneFunc)     cff_cmap_unicode_done,
321     (FT_CMap_CharIndexFunc)cff_cmap_unicode_char_index,
322     (FT_CMap_CharNextFunc) cff_cmap_unicode_char_next
323   };
324 
325 
326 /* END */
327