1 /*
2 Copyright: 2012 Barry Schwartz
3 Create is_Ligature.c (using a python script) to test for Vulgar fractions
4 Copyright: 2016 Joe Da Silva
5 Re-write is_Ligature.c to test for ligatures, Vulgar and Other-fractions.
6 Copyright: 2016 Gioele Barabucci
7 Simplify makeutype.c code. Split is_Ligature.c, create is_Ligature_data.h
8 License: BSD-3-clause
9 Contributions:
10 */
11
12 #include <fontforge-config.h>
13
14 #include "basics.h" /* for non-standard uint{16,32} typedefs */
15 #include "chardata.h"
16 #include "is_Ligature_data.h"
17 #include "utype.h"
18
compare_codepoints16(const void * uCode1,const void * uCode2)19 static int compare_codepoints16(const void *uCode1, const void *uCode2) {
20 const uint16 *cp1 = (const uint16 *)(uCode1);
21 const uint16 *cp2 = (const uint16 *)(uCode2);
22 return( (*cp1 < *cp2) ? -1 : ((*cp1 == *cp2) ? 0 : 1) );
23 }
24
compare_codepoints32(const void * uCode1,const void * uCode2)25 static int compare_codepoints32(const void *uCode1, const void *uCode2) {
26 const uint32 *cp1 = (const uint32 *)(uCode1);
27 const uint32 *cp2 = (const uint32 *)(uCode2);
28 return( (*cp1 < *cp2) ? -1 : ((*cp1 == *cp2) ? 0 : 1) );
29 }
30
LigatureCount(void)31 int LigatureCount(void) {
32 return( FF_ligatureTOTAL );
33 }
34
VulgarFractionCount(void)35 int VulgarFractionCount(void) {
36 return( FF_vulgfracTOTAL );
37 }
38
OtherFractionCount(void)39 int OtherFractionCount(void) {
40 return( FF_fractionTOTAL );
41 }
42
FractionCount(void)43 int FractionCount(void) {
44 return( FF_vulgfracTOTAL + FF_fractionTOTAL );
45 }
46
Ligature_get_U(int n)47 int32 Ligature_get_U(int n) {
48 if ( n < 0 || n >= FF_ligatureTOTAL )
49 return( -1 );
50 if ( n < FF_ligatureTOTAL16 )
51 return( (int32)(ligature16[n]) );
52 else
53 return( (int32)(ligature32[n-FF_ligatureTOTAL16]) );
54 }
55
VulgFrac_get_U(int n)56 int32 VulgFrac_get_U(int n) {
57 if ( n < 0 || n >= FF_vulgfracTOTAL )
58 return( -1 );
59 if ( n < FF_vulgfracTOTAL16 )
60 return( (int32)(vulgfrac16[n]) );
61 else
62 return( (int32)(vulgfrac32[n-FF_vulgfracTOTAL16]) );
63 }
64
Fraction_get_U(int n)65 int32 Fraction_get_U(int n) {
66 if ( n < 0 || n >= FF_fractionTOTAL )
67 return( -1 );
68 if ( n < FF_fractionTOTAL16 )
69 return( (int32)(fraction16[n]) );
70 else
71 return( (int32)(fraction32[n-FF_fractionTOTAL16]) );
72 }
73
Ligature_find_N(uint32 uCode)74 int Ligature_find_N(uint32 uCode) {
75 uint16 uCode16, *p16;
76 uint32 *p32;
77 int n=-1;
78
79 if ( uCode < FF_ligature16FIRST || uCode > FF_ligature32LAST || \
80 ((uCode < FF_UTYPE_MAXC) && (isligorfrac(uCode)==0)) )
81 return( -1 );
82 if ( uCode <= FF_ligature16LAST ) {
83 uCode16 = uCode;
84 p16 = (uint16 *)(bsearch(&uCode16, ligature16, FF_ligatureTOTAL16, \
85 sizeof(uint16), compare_codepoints16));
86 if ( p16 ) n = p16 - ligature16;
87 } else if ( uCode >= FF_ligature32FIRST ) {
88 p32 = (uint32 *)(bsearch(&uCode, ligature32, FF_ligatureTOTAL32, \
89 sizeof(uint32), compare_codepoints32));
90 if ( p32 ) n = p32 - ligature32 + FF_ligatureTOTAL16;
91 }
92 return( n );
93 }
94
VulgFrac_find_N(uint32 uCode)95 int VulgFrac_find_N(uint32 uCode) {
96 uint16 uCode16, *p16;
97 uint32 *p32;
98 int n=-1;
99
100 if ( uCode < FF_vulgfrac16FIRST || uCode > FF_vulgfrac32LAST || \
101 ((uCode < FF_UTYPE_MAXC) && (isligorfrac(uCode)==0)) )
102 return( -1 );
103 if (uCode <= FF_vulgfrac16LAST) {
104 uCode16 = uCode;
105 p16 = (uint16 *)(bsearch(&uCode16, vulgfrac16, FF_vulgfracTOTAL16, \
106 sizeof(uint16), compare_codepoints16));
107 if ( p16 ) n = p16 - vulgfrac16;
108 } else if ( uCode >= FF_vulgfrac32FIRST ) {
109 p32 = (uint32 *)(bsearch(&uCode, vulgfrac32, FF_vulgfracTOTAL32, \
110 sizeof(uint32), compare_codepoints32));
111 if (p32) n = p32 - vulgfrac32 + FF_vulgfracTOTAL16;
112 }
113 return( n );
114 }
115
Fraction_find_N(uint32 uCode)116 int Fraction_find_N(uint32 uCode) {
117 uint16 uCode16, *p16;
118 uint32 *p32;
119 int n=-1;
120
121 if ( uCode < FF_fractionTOTAL16 || uCode > FF_fraction32LAST || \
122 ((uCode < FF_UTYPE_MAXC) && (isligorfrac(uCode)==0)) )
123 return( -1 );
124 if ( uCode <= FF_fraction16LAST ) {
125 uCode16 = uCode;
126 p16 = (uint16 *)(bsearch(&uCode16, fraction16, FF_fractionTOTAL16, \
127 sizeof(uint16), compare_codepoints16));
128 if ( p16 ) n = p16 - fraction16;
129 } else if ( uCode >= FF_fraction32FIRST ) {
130 p32 = (uint32 *)(bsearch(&uCode, fraction32, FF_fractionTOTAL32, \
131 sizeof(uint32), compare_codepoints32));
132 if ( p32 ) n = p32 - fraction32 + FF_fractionTOTAL16;
133 }
134 return( n );
135 }
136
137 /* FontForge has a built-in internal table of ligatures. This function returns c */
138 /* for ligature[n], so for example if ligature[n] is 'ae' then c is 2 {a=0,e=1}, */
139 /* or if ligature[n] is 'ffi' then c is 3 {f=0,f=1,i=2}. Allowed range of n is 0 */
140 /* to n < LigatureCount() (the size of the internal table), otherwise return -1. */
Ligature_alt_getC(int n)141 int Ligature_alt_getC(int n) {
142 int i,j;
143
144 if ( n < 0 || n >= FF_ligatureTOTAL )
145 return( -1 );
146 if ( (i=ligatureAltI[n])&0x80 ) {
147 j = i & 0x7f;
148 for ( i=0; j; j=j>>1 )
149 if ( j&1 ) ++i;
150 return( i );
151 } else if ( i < FF_ligatureTIS ) {
152 return( ligatureAltIs[i+1] - ligatureAltIs[i] );
153 } else {
154 i -= FF_ligatureTIS;
155 return( ligatureAltIl[i+1] - ligatureAltIl[i] );
156 }
157 }
158
159 /* This function returns the unicode value for ligature[n][a]. Errors return -1. */
160 /* allowed ranges: {0 <= n < LigatureCount()} & {0 <= a < Ligature_alt_getC(n)}. */
161 /* For example, if ligature[n]='ae', then LigatureCount(n)=2 and the results are */
162 /* alternate values of 'a'=Ligature_alt_getV(n,0) and 'e'=Ligature_alt_getV(n,1) */
Ligature_alt_getV(int n,int a)163 int32 Ligature_alt_getV(int n,int a) {
164 int i,j;
165 const unichar_t *upt;
166 int32 u;
167
168 if ( n < 0 || n >= FF_ligatureTOTAL || a<0 || a>=Ligature_alt_getC(n) )
169 return( -1 );
170 if ( (i=ligatureAltI[n])&0x80 ) {
171 j = i & 0x7f;
172 for ( i=0; a; ++i )
173 if ( j&(1<<i) ) --a;
174 u = Ligature_get_U(n);
175 upt = unicode_alternates[u>>8][u&0xff];
176 return( (int32)(upt[i]) );
177 } else if ( i < FF_ligatureTIS ) {
178 i = ligatureAltIs[i];
179 u = ligatureAlt16[i+a];
180 return( u );
181 } else {
182 i -= FF_ligatureTIS;
183 i = ligatureAltIl[i];
184 u = ligatureAlt32[i+a];
185 return( u );
186 }
187 }
188
189 /* This returns similar results like Ligature_alt_getC(n) but uses unicode input */
190 /* uCode instead of ligature[n]. This isn't as speedy as c=Ligature_alt_getC(n). */
LigatureU_alt_getC(uint32 uCode)191 int LigatureU_alt_getC(uint32 uCode) {
192 return( Ligature_alt_getC(Ligature_find_N(uCode)) );
193 }
194
LigatureU_alt_getV(uint32 uCode,int a)195 int32 LigatureU_alt_getV(uint32 uCode,int a) {
196 int32 n;
197
198 if ( (n=Ligature_find_N(uCode))<0 )
199 return( -1 );
200 return( Ligature_alt_getV(n,a) );
201 }
202
VulgFrac_alt_getC(int n)203 int VulgFrac_alt_getC(int n) {
204 int i,j;
205
206 if ( n < 0 || n >= FF_vulgfracTOTAL )
207 return( -1 );
208 if ( (i=vulgfracAltI[n])&0x80 ) {
209 j = i & 0x7f;
210 for ( i=0; j; j=j>>1 )
211 if ( j&1 ) ++i;
212 return( i );
213 } else if ( i < FF_vulgfracTIS ) {
214 return( vulgfracAltIs[i+1] - vulgfracAltIs[i] );
215 } else {
216 i -= FF_vulgfracTIS;
217 return( vulgfracAltIl[i+1] - vulgfracAltIl[i] );
218 }
219 }
220
VulgFrac_alt_getV(int n,int a)221 int32 VulgFrac_alt_getV(int n,int a) {
222 int i,j;
223 const unichar_t *upt;
224 int32 u;
225
226 if ( n < 0 || n >= FF_vulgfracTOTAL || a<0 || a>=VulgFrac_alt_getC(n) )
227 return( -1 );
228 if ( (i=vulgfracAltI[n])&0x80 ) {
229 j = i & 0x7f;
230 for ( i=0; a; ++i )
231 if ( j&(1<<i) ) --a;
232 u = VulgFrac_get_U(n);
233 upt = unicode_alternates[u>>8][u&0xff];
234 return( (int32)(upt[i]) );
235 } else if ( i < FF_vulgfracTIS ) {
236 i = vulgfracAltIs[i];
237 u = vulgfracAlt16[i+a];
238 return( u );
239 } else {
240 i -= FF_vulgfracTIS;
241 i = vulgfracAltIl[i];
242 u = vulgfracAlt32[i+a];
243 return( u );
244 }
245 }
246
VulgFracU_alt_getC(uint32 uCode)247 int VulgFracU_alt_getC(uint32 uCode) {
248 return( VulgFrac_alt_getC(VulgFrac_find_N(uCode)) );
249 }
250
VulgFracU_alt_getV(uint32 uCode,int a)251 int32 VulgFracU_alt_getV(uint32 uCode,int a) {
252 int32 n;
253
254 if ( (n=VulgFrac_find_N(uCode))< 0 )
255 return( -1 );
256 return( VulgFrac_alt_getV(n,a) );
257 }
258
Fraction_alt_getC(int n)259 int Fraction_alt_getC(int n) {
260 int i,j;
261
262 if ( n < 0 || n >= FF_fractionTOTAL )
263 return( -1 );
264 if ( (i=fractionAltI[n])&0x80 ) {
265 j = i & 0x7f;
266 for ( i=0; j; j=j>>1 )
267 if ( j&1 ) ++i;
268 return( i );
269 } else if ( i < FF_fractionTIS ) {
270 return( fractionAltIs[i+1] - fractionAltIs[i] );
271 } else {
272 i -= FF_fractionTIS;
273 return( fractionAltIl[i+1] - fractionAltIl[i] );
274 }
275 }
276
Fraction_alt_getV(int n,int a)277 int32 Fraction_alt_getV(int n,int a) {
278 int i,j;
279 const unichar_t *upt;
280 int32 u;
281
282 if ( n < 0 || n >= FF_fractionTOTAL || a<0 || a>=Fraction_alt_getC(n) )
283 return( -1 );
284 if ( (i=fractionAltI[n])&0x80 ) {
285 j = i & 0x7f;
286 for ( i=0; a; ++i )
287 if ( j&(1<<i) ) --a;
288 u = Fraction_get_U(n);
289 upt = unicode_alternates[u>>8][u&0xff];
290 return( (int32)(upt[i]) );
291 } else if ( i < FF_fractionTIS ) {
292 i = fractionAltIs[i];
293 u = fractionAlt16[i+a];
294 return( u );
295 } else {
296 i -= FF_fractionTIS;
297 i = fractionAltIl[i];
298 u = fractionAlt16[i+a];
299 return( u );
300 }
301 }
302
FractionU_alt_getC(uint32 uCode)303 int FractionU_alt_getC(uint32 uCode) {
304 return( Fraction_alt_getC(Fraction_find_N(uCode)) );
305 }
306
FractionU_alt_getV(uint32 uCode,int a)307 int32 FractionU_alt_getV(uint32 uCode,int a) {
308 int32 n;
309
310 if ( (n=Fraction_find_N(uCode))< 0 )
311 return( -1 );
312 return( Fraction_alt_getV(n,a) );
313 }
314 /* Boolean-style tests (found==0) to see if your codepoint value is listed */
315 /* unicode.org codepoints for ligatures, vulgar fractions, other fractions */
316
is_LIGATURE(uint32 codepoint)317 int is_LIGATURE(uint32 codepoint) {
318 return( Ligature_find_N(codepoint)<0 );
319 }
320
is_VULGAR_FRACTION(uint32 codepoint)321 int is_VULGAR_FRACTION(uint32 codepoint) {
322 return( VulgFrac_find_N(codepoint)<0 );
323 }
324
is_OTHER_FRACTION(uint32 codepoint)325 int is_OTHER_FRACTION(uint32 codepoint) {
326 return( Fraction_find_N(codepoint)<0 );
327 }
328
is_FRACTION(uint32 codepoint)329 int is_FRACTION(uint32 codepoint) {
330 return( VulgFrac_find_N(codepoint)<0 && Fraction_find_N(codepoint)<0 );
331 }
332
is_LIGATURE_or_VULGAR_FRACTION(uint32 codepoint)333 int is_LIGATURE_or_VULGAR_FRACTION(uint32 codepoint) {
334 return( Ligature_find_N(codepoint)<0 && VulgFrac_find_N(codepoint)<0 );
335 }
336
is_LIGATURE_or_OTHER_FRACTION(uint32 codepoint)337 int is_LIGATURE_or_OTHER_FRACTION(uint32 codepoint) {
338 return( Ligature_find_N(codepoint)<0 && Fraction_find_N(codepoint)<0 );
339 }
340
is_LIGATURE_or_FRACTION(uint32 codepoint)341 int is_LIGATURE_or_FRACTION(uint32 codepoint) {
342 return( Ligature_find_N(codepoint)<0 && VulgFrac_find_N(codepoint)<0 && Fraction_find_N(codepoint)<0 );
343 }
344
345