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