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