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