xref: /aosp_15_r20/external/freetype/src/pfr/pfrcmap.c (revision 63949dbd25bcc50c4e1178497ff9e9574d44fc5a)
1 /****************************************************************************
2  *
3  * pfrcmap.c
4  *
5  *   FreeType PFR cmap handling (body).
6  *
7  * Copyright (C) 2002-2023 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 <freetype/internal/ftdebug.h>
20 #include "pfrcmap.h"
21 #include "pfrobjs.h"
22 
23 #include "pfrerror.h"
24 
25 
26   FT_CALLBACK_DEF( FT_Error )
pfr_cmap_init(FT_CMap cmap,FT_Pointer pointer)27   pfr_cmap_init( FT_CMap     cmap,     /* PFR_CMap */
28                  FT_Pointer  pointer )
29   {
30     PFR_CMap  pfrcmap = (PFR_CMap)cmap;
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     pfrcmap->num_chars = face->phy_font.num_chars;
38     pfrcmap->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 < pfrcmap->num_chars; n++ )
47       {
48         if ( pfrcmap->chars[n - 1].char_code >= pfrcmap->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 )
pfr_cmap_done(FT_CMap cmap)62   pfr_cmap_done( FT_CMap  cmap )    /* PFR_CMap */
63   {
64     PFR_CMap  pfrcmap = (PFR_CMap)cmap;
65 
66 
67     pfrcmap->chars     = NULL;
68     pfrcmap->num_chars = 0;
69   }
70 
71 
72   FT_CALLBACK_DEF( FT_UInt )
pfr_cmap_char_index(FT_CMap cmap,FT_UInt32 char_code)73   pfr_cmap_char_index( FT_CMap    cmap,       /* PFR_CMap */
74                        FT_UInt32  char_code )
75   {
76     PFR_CMap  pfrcmap = (PFR_CMap)cmap;
77     FT_UInt   min     = 0;
78     FT_UInt   max     = pfrcmap->num_chars;
79     FT_UInt   mid     = min + ( max - min ) / 2;
80     PFR_Char  gchar;
81 
82 
83     while ( min < max )
84     {
85       gchar = pfrcmap->chars + mid;
86 
87       if ( gchar->char_code == char_code )
88         return mid + 1;
89 
90       if ( gchar->char_code < char_code )
91         min = mid + 1;
92       else
93         max = mid;
94 
95       /* reasonable prediction in a continuous block */
96       mid += char_code - gchar->char_code;
97       if ( mid >= max || mid < min )
98         mid = min + ( max - min ) / 2;
99     }
100     return 0;
101   }
102 
103 
104   FT_CALLBACK_DEF( FT_UInt )
pfr_cmap_char_next(FT_CMap cmap,FT_UInt32 * pchar_code)105   pfr_cmap_char_next( FT_CMap     cmap,        /* PFR_CMap */
106                       FT_UInt32  *pchar_code )
107   {
108     PFR_CMap   pfrcmap   = (PFR_CMap)cmap;
109     FT_UInt    result    = 0;
110     FT_UInt32  char_code = *pchar_code + 1;
111 
112 
113   Restart:
114     {
115       FT_UInt   min = 0;
116       FT_UInt   max = pfrcmap->num_chars;
117       FT_UInt   mid = min + ( max - min ) / 2;
118       PFR_Char  gchar;
119 
120 
121       while ( min < max )
122       {
123         gchar = pfrcmap->chars + mid;
124 
125         if ( gchar->char_code == char_code )
126         {
127           result = mid;
128           if ( result != 0 )
129           {
130             result++;
131             goto Exit;
132           }
133 
134           char_code++;
135           goto Restart;
136         }
137 
138         if ( gchar->char_code < char_code )
139           min = mid + 1;
140         else
141           max = mid;
142 
143         /* reasonable prediction in a continuous block */
144         mid += char_code - gchar->char_code;
145         if ( mid >= max || mid < min )
146           mid = min + ( max - min ) / 2;
147       }
148 
149       /* we didn't find it, but we have a pair just above it */
150       char_code = 0;
151 
152       if ( min < pfrcmap->num_chars )
153       {
154         gchar  = pfrcmap->chars + min;
155         result = min;
156         if ( result != 0 )
157         {
158           result++;
159           char_code = gchar->char_code;
160         }
161       }
162     }
163 
164   Exit:
165     *pchar_code = char_code;
166     return result;
167   }
168 
169 
170   FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec
171   pfr_cmap_class_rec =
172   {
173     sizeof ( PFR_CMapRec ),
174 
175     (FT_CMap_InitFunc)     pfr_cmap_init,        /* init       */
176     (FT_CMap_DoneFunc)     pfr_cmap_done,        /* done       */
177     (FT_CMap_CharIndexFunc)pfr_cmap_char_index,  /* char_index */
178     (FT_CMap_CharNextFunc) pfr_cmap_char_next,   /* char_next  */
179 
180     (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
181     (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
182     (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
183     (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
184     (FT_CMap_VariantCharListFunc) NULL   /* variantchar_list */
185   };
186 
187 
188 /* END */
189