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