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