1 /***************************************************************************/
2 /*                                                                         */
3 /*  pfrcmap.c                                                              */
4 /*                                                                         */
5 /*    FreeType PFR cmap handling (body).                                   */
6 /*                                                                         */
7 /*  Copyright 2002, 2007, 2009 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 "pfrcmap.h"
20 #include "pfrobjs.h"
21 
22 #include "pfrerror.h"
23 
24 
25   FT_CALLBACK_DEF( FT_Error )
pfr_cmap_init(PFR_CMap cmap)26   pfr_cmap_init( PFR_CMap  cmap )
27   {
28     FT_Error  error = PFR_Err_Ok;
29     PFR_Face  face  = (PFR_Face)FT_CMAP_FACE( cmap );
30 
31 
32     cmap->num_chars = face->phy_font.num_chars;
33     cmap->chars     = face->phy_font.chars;
34 
35     /* just for safety, check that the character entries are correctly */
36     /* sorted in increasing character code order                       */
37     {
38       FT_UInt  n;
39 
40 
41       for ( n = 1; n < cmap->num_chars; n++ )
42       {
43         if ( cmap->chars[n - 1].char_code >= cmap->chars[n].char_code )
44         {
45           error = PFR_Err_Invalid_Table;
46           goto Exit;
47         }
48       }
49     }
50 
51   Exit:
52     return error;
53   }
54 
55 
56   FT_CALLBACK_DEF( void )
pfr_cmap_done(PFR_CMap cmap)57   pfr_cmap_done( PFR_CMap  cmap )
58   {
59     cmap->chars     = NULL;
60     cmap->num_chars = 0;
61   }
62 
63 
64   FT_CALLBACK_DEF( FT_UInt )
pfr_cmap_char_index(PFR_CMap cmap,FT_UInt32 char_code)65   pfr_cmap_char_index( PFR_CMap   cmap,
66                        FT_UInt32  char_code )
67   {
68     FT_UInt   min = 0;
69     FT_UInt   max = cmap->num_chars;
70     FT_UInt   mid;
71     PFR_Char  gchar;
72 
73 
74     while ( min < max )
75     {
76       mid   = min + ( max - min ) / 2;
77       gchar = cmap->chars + mid;
78 
79       if ( gchar->char_code == char_code )
80         return mid + 1;
81 
82       if ( gchar->char_code < char_code )
83         min = mid + 1;
84       else
85         max = mid;
86     }
87     return 0;
88   }
89 
90 
91   FT_CALLBACK_DEF( FT_UInt32 )
pfr_cmap_char_next(PFR_CMap cmap,FT_UInt32 * pchar_code)92   pfr_cmap_char_next( PFR_CMap    cmap,
93                       FT_UInt32  *pchar_code )
94   {
95     FT_UInt    result    = 0;
96     FT_UInt32  char_code = *pchar_code + 1;
97 
98 
99   Restart:
100     {
101       FT_UInt   min = 0;
102       FT_UInt   max = cmap->num_chars;
103       FT_UInt   mid;
104       PFR_Char  gchar;
105 
106 
107       while ( min < max )
108       {
109         mid   = min + ( ( max - min ) >> 1 );
110         gchar = cmap->chars + mid;
111 
112         if ( gchar->char_code == char_code )
113         {
114           result = mid;
115           if ( result != 0 )
116           {
117             result++;
118             goto Exit;
119           }
120 
121           char_code++;
122           goto Restart;
123         }
124 
125         if ( gchar->char_code < char_code )
126           min = mid+1;
127         else
128           max = mid;
129       }
130 
131       /* we didn't find it, but we have a pair just above it */
132       char_code = 0;
133 
134       if ( min < cmap->num_chars )
135       {
136         gchar  = cmap->chars + min;
137         result = min;
138         if ( result != 0 )
139         {
140           result++;
141           char_code = gchar->char_code;
142         }
143       }
144     }
145 
146   Exit:
147     *pchar_code = char_code;
148     return result;
149   }
150 
151 
152   FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec
153   pfr_cmap_class_rec =
154   {
155     sizeof ( PFR_CMapRec ),
156 
157     (FT_CMap_InitFunc)     pfr_cmap_init,
158     (FT_CMap_DoneFunc)     pfr_cmap_done,
159     (FT_CMap_CharIndexFunc)pfr_cmap_char_index,
160     (FT_CMap_CharNextFunc) pfr_cmap_char_next,
161 
162     NULL, NULL, NULL, NULL, NULL
163   };
164 
165 
166 /* END */
167