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 ) |
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 ) |
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 ) |
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 ) |
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 | |