1 /* Copyright (C) 2001-2012 by George Williams */
2 /*
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are met:
5
6 * Redistributions of source code must retain the above copyright notice, this
7 * list of conditions and the following disclaimer.
8
9 * Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12
13 * The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include <fontforge-config.h>
29
30 #include "ttfinstrs.h"
31
32 #include "fontforgevw.h"
33 #include "ttf.h"
34 #include "ustring.h"
35 #include "utype.h"
36
37 const char *ff_ttf_instrnames[] = {
38 "SVTCA[y-axis]",
39 "SVTCA[x-axis]",
40 "SPVTCA[y-axis]",
41 "SPVTCA[x-axis]",
42 "SFVTCA[y-axis]",
43 "SFVTCA[x-axis]",
44 "SPVTL[parallel]",
45 "SPVTL[orthog]",
46 "SFVTL[parallel]",
47 "SFVTL[orthog]",
48 "SPVFS",
49 "SFVFS",
50 "GPV",
51 "GFV",
52 "SFVTPV",
53 "ISECT",
54 "SRP0",
55 "SRP1",
56 "SRP2",
57 "SZP0",
58 "SZP1",
59 "SZP2",
60 "SZPS",
61 "SLOOP",
62 "RTG",
63 "RTHG",
64 "SMD",
65 "ELSE",
66 "JMPR",
67 "SCVTCI",
68 "SSWCI",
69 "SSW",
70 "DUP",
71 "POP",
72 "CLEAR",
73 "SWAP",
74 "DEPTH",
75 "CINDEX",
76 "MINDEX",
77 "ALIGNPTS",
78 "Unknown28",
79 "UTP",
80 "LOOPCALL",
81 "CALL",
82 "FDEF",
83 "ENDF",
84 "MDAP[no-rnd]",
85 "MDAP[rnd]",
86 "IUP[y]",
87 "IUP[x]",
88 "SHP[rp2]",
89 "SHP[rp1]",
90 "SHC[rp2]",
91 "SHC[rp1]",
92 "SHZ[rp2]",
93 "SHZ[rp1]",
94 "SHPIX",
95 "IP",
96 "MSIRP[no-rp0]",
97 "MSIRP[rp0]",
98 "ALIGNRP",
99 "RTDG",
100 "MIAP[no-rnd]",
101 "MIAP[rnd]",
102 "NPUSHB",
103 "NPUSHW",
104 "WS",
105 "RS",
106 "WCVTP",
107 "RCVT",
108 "GC[cur]",
109 "GC[orig]",
110 "SCFS",
111 "MD[grid]",
112 "MD[orig]",
113 "MPPEM",
114 "MPS",
115 "FLIPON",
116 "FLIPOFF",
117 "DEBUG",
118 "LT",
119 "LTEQ",
120 "GT",
121 "GTEQ",
122 "EQ",
123 "NEQ",
124 "ODD",
125 "EVEN",
126 "IF",
127 "EIF",
128 "AND",
129 "OR",
130 "NOT",
131 "DELTAP1",
132 "SDB",
133 "SDS",
134 "ADD",
135 "SUB",
136 "DIV",
137 "MUL",
138 "ABS",
139 "NEG",
140 "FLOOR",
141 "CEILING",
142 "ROUND[Grey]",
143 "ROUND[Black]",
144 "ROUND[White]",
145 "ROUND[Undef4]",
146 "NROUND[Grey]",
147 "NROUND[Black]",
148 "NROUND[White]",
149 "NROUND[Undef4]",
150 "WCVTF",
151 "DELTAP2",
152 "DELTAP3",
153 "DELTAC1",
154 "DELTAC2",
155 "DELTAC3",
156 "SROUND",
157 "S45ROUND",
158 "JROT",
159 "JROF",
160 "ROFF",
161 "Unknown7B",
162 "RUTG",
163 "RDTG",
164 "SANGW",
165 "AA",
166 "FLIPPT",
167 "FLIPRGON",
168 "FLIPRGOFF",
169 "Unknown83",
170 "Unknown84",
171 "SCANCTRL",
172 "SDPVTL[parallel]",
173 "SDPVTL[orthog]",
174 "GETINFO",
175 "IDEF",
176 "ROLL",
177 "MAX",
178 "MIN",
179 "SCANTYPE",
180 "INSTCTRL",
181 "Unknown8F",
182 "Unknown90",
183 "Unknown91",
184 "Unknown92",
185 "Unknown93",
186 "Unknown94",
187 "Unknown95",
188 "Unknown96",
189 "Unknown97",
190 "Unknown98",
191 "Unknown99",
192 "Unknown9A",
193 "Unknown9B",
194 "Unknown9C",
195 "Unknown9D",
196 "Unknown9E",
197 "Unknown9F",
198 "UnknownA0",
199 "UnknownA1",
200 "UnknownA2",
201 "UnknownA3",
202 "UnknownA4",
203 "UnknownA5",
204 "UnknownA6",
205 "UnknownA7",
206 "UnknownA8",
207 "UnknownA9",
208 "UnknownAA",
209 "UnknownAB",
210 "UnknownAC",
211 "UnknownAD",
212 "UnknownAE",
213 "UnknownAF",
214 "PUSHB_1",
215 "PUSHB_2",
216 "PUSHB_3",
217 "PUSHB_4",
218 "PUSHB_5",
219 "PUSHB_6",
220 "PUSHB_7",
221 "PUSHB_8",
222 "PUSHW_1",
223 "PUSHW_2",
224 "PUSHW_3",
225 "PUSHW_4",
226 "PUSHW_5",
227 "PUSHW_6",
228 "PUSHW_7",
229 "PUSHW_8",
230 "MDRP[grey]",
231 "MDRP[black]",
232 "MDRP[white]",
233 "MDRP03",
234 "MDRP[rnd,grey]",
235 "MDRP[rnd,black]",
236 "MDRP[rnd,white]",
237 "MDRP07",
238 "MDRP[min,grey]",
239 "MDRP[min,black]",
240 "MDRP[min,white]",
241 "MDRP0b",
242 "MDRP[min,rnd,grey]",
243 "MDRP[min,rnd,black]",
244 "MDRP[min,rnd,white]",
245 "MDRP0f",
246 "MDRP[rp0,grey]",
247 "MDRP[rp0,black]",
248 "MDRP[rp0,white]",
249 "MDRP13",
250 "MDRP[rp0,rnd,grey]",
251 "MDRP[rp0,rnd,black]",
252 "MDRP[rp0,rnd,white]",
253 "MDRP17",
254 "MDRP[rp0,min,grey]",
255 "MDRP[rp0,min,black]",
256 "MDRP[rp0,min,white]",
257 "MDRP1b",
258 "MDRP[rp0,min,rnd,grey]",
259 "MDRP[rp0,min,rnd,black]",
260 "MDRP[rp0,min,rnd,white]",
261 "MDRP1f",
262 "MIRP[grey]",
263 "MIRP[black]",
264 "MIRP[white]",
265 "MIRP03",
266 "MIRP[rnd,grey]",
267 "MIRP[rnd,black]",
268 "MIRP[rnd,white]",
269 "MIRP07",
270 "MIRP[min,grey]",
271 "MIRP[min,black]",
272 "MIRP[min,white]",
273 "MIRP0b",
274 "MIRP[min,rnd,grey]",
275 "MIRP[min,rnd,black]",
276 "MIRP[min,rnd,white]",
277 "MIRP0f",
278 "MIRP[rp0,grey]",
279 "MIRP[rp0,black]",
280 "MIRP[rp0,white]",
281 "MIRP13",
282 "MIRP[rp0,rnd,grey]",
283 "MIRP[rp0,rnd,black]",
284 "MIRP[rp0,rnd,white]",
285 "MIRP17",
286 "MIRP[rp0,min,grey]",
287 "MIRP[rp0,min,black]",
288 "MIRP[rp0,min,white]",
289 "MIRP1b",
290 "MIRP[rp0,min,rnd,grey]",
291 "MIRP[rp0,min,rnd,black]",
292 "MIRP[rp0,min,rnd,white]",
293 "MIRP1f"
294 };
295
_IVParse(SplineFont * sf,char * text,int * len,void (* IVError)(void *,char *,int),void * iv)296 uint8 *_IVParse(SplineFont *sf, char *text, int *len,
297 void (*IVError)(void *,char *, int), void *iv) {
298 short numberstack[256];
299 int npos=0, nread, i;
300 int push_left= 0, push_size=0;
301 char *pt;
302 char *end, *bend, *brack;
303 int icnt=0, imax=strlen(text)/2, val, temp;
304 uint8 *instrs = malloc(imax);
305
306 for ( pt = text; *pt ; ++pt ) {
307 npos = 0;
308 while ( npos<256 ) {
309 while ( *pt==' ' || *pt=='\t' ) ++pt;
310 if ( isdigit( *pt ) || *pt=='-' ) {
311 val = strtol(pt,&end,0);
312 if ( val>32767 || val<-32768 ) {
313 IVError(iv,_("A value must be between [-32768,32767]"),pt-text);
314 free(instrs);
315 return( NULL );
316 }
317
318 pt = end;
319
320 if ( *pt == '@' ) { /* a delta control byte */
321 if ( val>8 || val<-8 || val==0 ) {
322 IVError(iv,_("A value must be between [-8,-1] or [1,8]"),pt-text);
323 free(instrs);
324 return( NULL );
325 }
326
327 pt++;
328
329 if ( !isdigit( *pt ) ) {
330 IVError(iv,_("Number expected"),pt-text);
331 free(instrs);
332 return( NULL );
333 }
334
335 temp = val;
336 val = strtol(pt,&end,0);
337
338 if ( val>15 || val<0 ) {
339 IVError(iv,_("A value must be between [0,15]"),pt-text);
340 free(instrs);
341 return( NULL );
342 }
343
344 val *= 16;
345 if (temp < 0) temp += 8;
346 else temp += 7;
347 val += temp;
348 pt = end;
349 }
350
351 numberstack[npos++] = val;
352 } else if ( strnmatch(pt,"cvt",3)==0 ) {
353 pt += 3;
354 while ( *pt==' ' || *pt=='\t' ) ++pt;
355 if ( *pt!='(' ) {
356 IVError(iv,_("Missing left parenthesis in command to get a cvt index"),pt-text);
357 free(instrs);
358 return( NULL );
359 }
360 temp = strtol(pt+1,&end,0);
361 pt = end;
362 while ( *pt==' ' || *pt=='\t' ) ++pt;
363 if ( *pt!=')' ) {
364 IVError(iv,_("Missing right paren in command to get a cvt index"),pt-text);
365 free(instrs);
366 return( NULL );
367 }
368 numberstack[npos++] = TTF__getcvtval(sf,temp);
369 ++pt;
370 } else
371 break;
372 }
373 while ( *pt==' ' || *pt=='\t' ) ++pt;
374 if ( npos==0 && (*pt=='\r' || *pt=='\n' || *pt=='\0') )
375 continue;
376 nread = 0;
377 if ( push_left==-1 ) {
378 /* we need a push count */
379 if ( npos==0 )
380 IVError(iv,_("Expected a number for a push count"),pt-text);
381 else if ( numberstack[0]>255 || numberstack[0]<=0 ) {
382 IVError(iv,_("The push count must be a number between 0 and 255"),pt-text);
383 free(instrs);
384 return( NULL );
385 } else {
386 nread = 1;
387 instrs[icnt++] = numberstack[0];
388 push_left = numberstack[0];
389 }
390 }
391 if ( push_left!=0 && push_left<npos-nread && (*pt=='\r' || *pt=='\n' || *pt=='\0') ) {
392 IVError(iv,_("More pushes specified than needed"),pt-text);
393 free(instrs);
394 return( NULL );
395 }
396 while ( push_left>0 && nread<npos ) {
397 if ( push_size==2 ) {
398 instrs[icnt++] = numberstack[nread]>>8;
399 instrs[icnt++] = numberstack[nread++]&0xff;
400 } else if ( numberstack[0]>255 || numberstack[0]<0 ) {
401 IVError(iv,_("A value to be pushed by a byte push must be between 0 and 255"),pt-text);
402 free(instrs);
403 return( NULL );
404 } else
405 instrs[icnt++] = numberstack[nread++];
406 --push_left;
407 }
408 if ( nread<npos && push_left==0 && (*pt=='\r' || *pt=='\n' || *pt=='\0')) {
409 IVError(iv,_("Unexpected number"),pt-text);
410 free(instrs);
411 return( NULL );
412 }
413 if ( *pt=='\r' || *pt=='\n' || *pt=='\0' )
414 continue;
415 if ( push_left>0 ) {
416 IVError(iv,_("Missing pushes"),pt-text);
417 free(instrs);
418 return( NULL );
419 }
420 while ( nread<npos ) {
421 i = nread;
422 if ( numberstack[nread]>=0 && numberstack[nread]<=255 ) {
423 while ( i<npos && numberstack[i]>=0 && numberstack[i]<=255 )
424 ++i;
425 if ( i-nread<=8 )
426 instrs[icnt++] = ttf_pushb+(i-nread)-1;
427 else {
428 instrs[icnt++] = ttf_npushb;
429 instrs[icnt++] = i-nread;
430 }
431 while ( nread<i )
432 instrs[icnt++] = numberstack[nread++];
433 } else {
434 while ( i<npos && (numberstack[i]<0 || numberstack[i]>255) )
435 ++i;
436 if ( i-nread<=8 )
437 instrs[icnt++] = ttf_pushw+(i-nread)-1;
438 else {
439 instrs[icnt++] = ttf_npushw;
440 instrs[icnt++] = i-nread;
441 }
442 while ( nread<i ) {
443 instrs[icnt++] = numberstack[nread]>>8;
444 instrs[icnt++] = numberstack[nread++]&0xff;
445 }
446 }
447 }
448 brack = NULL;
449 for ( end= pt; *end!='\r' && *end!='\n' && *end!=' ' && *end!='\0'; ++end )
450 if ( *end=='[' || *end=='_' ) brack=end;
451 for ( i=0; i<256; ++i )
452 if ( strnmatch(pt,ff_ttf_instrnames[i],end-pt)==0 && end-pt==strlen(ff_ttf_instrnames[i]))
453 break;
454 if ( i==256 && brack!=NULL ) {
455 for ( i=0; i<256; ++i )
456 if ( strnmatch(pt,ff_ttf_instrnames[i],brack-pt+1)==0 )
457 break;
458 val = strtol(brack+1,&bend,2); /* Stuff in brackets should be in binary */
459 while ( *bend==' ' || *bend=='\t' ) ++bend;
460 if ( *bend!=']' ) {
461 IVError(iv,_("Missing right bracket in command (or bad binary value in bracket)"),pt-text);
462 free(instrs);
463 return( NULL );
464 }
465 if ( val>=32 ) {
466 IVError(iv,_("Bracketted value is too large"),pt-text);
467 free(instrs);
468 return( NULL );
469 }
470 i += val;
471 }
472 pt = end;
473 instrs[icnt++] = i;
474 if ( i==ttf_npushb || i==ttf_npushw || (i>=ttf_pushb && i<=ttf_pushw+7)) {
475 push_size = (i==ttf_npushb || (i>=ttf_pushb && i<=ttf_pushb+7))? 1 : 2;
476 if ( i==ttf_npushb || i==ttf_npushw )
477 push_left = -1;
478 else if ( i>=ttf_pushb && i<=ttf_pushb+7 )
479 push_left = i-ttf_pushb+1;
480 else
481 push_left = i-ttf_pushw+1;
482 }
483 if ( *pt=='\0' )
484 break;
485 }
486 *len = icnt;
487 return( realloc(instrs,icnt==0?1:icnt)); /* some versions of realloc abort on 0 */
488 }
489
instr_typify(struct instrdata * id)490 int instr_typify(struct instrdata *id) {
491 int i, len = id->instr_cnt, cnt, j, lh;
492 uint8 *instrs = id->instrs;
493 uint8 *bts;
494
495 if ( id->bts==NULL )
496 id->bts = malloc(len+1);
497 bts = id->bts;
498 for ( i=lh=0; i<len; ++i ) {
499 bts[i] = bt_instr;
500 ++lh;
501 if ( instrs[i]==ttf_npushb ) {
502 /* NPUSHB */
503 bts[++i] = bt_cnt;
504 cnt = instrs[i];
505 for ( j=0 ; j<cnt; ++j)
506 bts[++i] = bt_byte;
507 lh += 1+cnt;
508 } else if ( instrs[i]==ttf_npushw ) {
509 /* NPUSHW */
510 bts[++i] = bt_cnt; ++lh;
511 cnt = instrs[i];
512 for ( j=0 ; j<cnt; ++j) {
513 bts[++i] = bt_wordhi;
514 bts[++i] = bt_wordlo;
515 }
516 lh += 1+cnt;
517 } else if ( (instrs[i]&0xf8) == 0xb0 ) {
518 /* PUSHB[n] */
519 cnt = (instrs[i]&7)+1;
520 for ( j=0 ; j<cnt; ++j)
521 bts[++i] = bt_byte;
522 lh += cnt;
523 } else if ( (instrs[i]&0xf8) == 0xb8 ) {
524 /* PUSHW[n] */
525 cnt = (instrs[i]&7)+1;
526 for ( j=0 ; j<cnt; ++j) {
527 bts[++i] = bt_wordhi;
528 bts[++i] = bt_wordlo;
529 }
530 lh += cnt;
531 }
532 }
533 bts[i] = bt_impliedreturn;
534 return( lh );
535 }
536
__IVUnParseInstrs(InstrBase * iv)537 char *__IVUnParseInstrs(InstrBase *iv) {
538 char *ubuf, *pt;
539 int i,l;
540
541 pt = ubuf = iv->offset = iv->scroll = malloc((iv->instrdata->instr_cnt*20+1));
542 for ( i=l=0; i<iv->instrdata->instr_cnt; ++i ) {
543 if ( iv->lpos == l )
544 iv->scroll = pt;
545 if ( iv->isel_pos == l )
546 iv->offset = pt;
547 if ( iv->instrdata->bts[i]==bt_wordhi ) {
548 sprintf( pt, " %d", (short) ((iv->instrdata->instrs[i]<<8) | iv->instrdata->instrs[i+1]) );
549 ++i;
550 } else if ( iv->instrdata->bts[i]==bt_cnt || iv->instrdata->bts[i]==bt_byte ) {
551 sprintf( pt, " %d", iv->instrdata->instrs[i]);
552 } else {
553 strcpy(pt, ff_ttf_instrnames[iv->instrdata->instrs[i]]);
554 }
555 pt += strlen(pt);
556 *pt++ = '\n';
557 ++l;
558 }
559 *pt = '\0';
560 return( ubuf );
561 }
562
_IVUnParseInstrs(uint8 * instrs,int instr_cnt)563 char *_IVUnParseInstrs(uint8 *instrs,int instr_cnt) {
564 struct instrbase iv;
565 struct instrdata id;
566 char *ret;
567
568 memset(&iv,0,sizeof(iv));
569 memset(&id,0,sizeof(id));
570 iv.instrdata = &id;
571 id.instr_cnt = instr_cnt;
572 id.instrs = instrs;
573 instr_typify(&id);
574 ret = __IVUnParseInstrs(&iv);
575 free(id.bts);
576 return( ret );
577 }
578