b9af301cb221fbf99e83d3a2883350cee00864e6
[blender.git] / source / blender / blenlib / intern / psfont.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  * fromtype1 - Convert an Adobe type 1 font into .of or .sf format.
32  *                              Paul Haeberli - 1990
33  */
34
35 #include <stdio.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include <stdlib.h>
39 #include <math.h>
40
41 #include "MEM_guardedalloc.h"
42
43 #include "BLI_vfontdata.h"
44 #include "BLI_blenlib.h"
45
46 #include "DNA_packedFile_types.h"
47 #include "DNA_curve_types.h"
48
49 #ifdef HAVE_CONFIG_H
50 #include <config.h>
51 #endif
52
53         /* ObjFnt types */
54
55 typedef struct chardesc {
56     short movex, movey;         /* advance */
57     short llx, lly;             /* bounding box */
58     short urx, ury;
59     short *data;                /* char data */
60     long datalen;               
61 } chardesc;
62
63 typedef struct objfnt {
64     struct objfnt *freeaddr;    /* if freeaddr != 0, objfnt is one chunck */
65     short type;
66     short charmin, charmax;
67     short my_nchars;
68     short scale;
69     chardesc *my_chars;
70 } objfnt;
71
72 #define OFMAGIC         0x93339333
73
74 #define TM_TYPE         1
75 #define PO_TYPE         2
76 #define SP_TYPE         3
77
78 /* ops for tmesh characters */
79
80 #define TM_BGNTMESH     (1)
81 #define TM_SWAPTMESH    (2)
82 #define TM_ENDBGNTMESH  (3)
83 #define TM_RETENDTMESH  (4)
84 #define TM_RET          (5)
85
86 /* ops for poly characters */
87
88 #define PO_BGNLOOP      (1)
89 #define PO_ENDBGNLOOP   (2)
90 #define PO_RETENDLOOP   (3)
91 #define PO_RET          (4)
92
93 /* ops for spline  characters */
94
95 #define SP_MOVETO       (1)
96 #define SP_LINETO       (2)
97 #define SP_CURVETO      (3)
98 #define SP_CLOSEPATH    (4)
99 #define SP_RETCLOSEPATH (5)
100 #define SP_RET          (6)
101
102
103 #define MIN_ASCII       ' '
104 #define MAX_ASCII       '~'
105 #define NASCII          (256 - 32)
106
107 #define NOBBOX          (30000)
108
109 typedef struct pschar {
110     char *name;
111     int code;
112     int prog;
113 } pschar;
114
115         /***/
116
117 #define SKIP 4
118 #define LINELEN 2048
119 #define NOTHEX          (100)
120 #define MC1 52845
121 #define MC2 22719
122 #define MAXSUBRS 1000
123 #define MAXCHARS 1000
124 #define MAXTRIES 30
125
126 /* some local thingies */
127 static void rcurveto( int dx1, int dy1, int dx2, int dy2, int dx3, int dy3);
128 static void makeobjfont(int savesplines);
129 static void drawchar(int c);
130 static void runprog(void);
131 static int chartoindex(objfnt *fnt, int c);
132 static short STDtoISO(short c);
133 static char * newfgets(char * s, int n, PackedFile * pf);
134 static int readfontmatrix(PackedFile * pf, float mat[2][2]);
135 static char mdecrypt(char cipher);
136 static void decryptall(void);
137 static int decodetype1(PackedFile * pf, char *outname);
138 static void fakefopen(void);
139 static char *fakefread(int n);
140 static void setcharlist(void);
141 static void initpcstack(void);
142 static char *poppc(void);
143 static void initstack(void);
144 static void push(int val);
145 static int pop(void);
146 static void initretstack(void);
147 static void retpush(int val);
148 static int retpop(void);
149 static void subr1(void);
150 static void subr2(void);
151 static void subr0(void);
152 static void append_poly_offset(short ofsx, short ofsy, short * data);
153 static void append_spline_offset(short ofsx, short ofsy, short * data);
154 static void setwidth(int w, int x);
155 static void poly_beginchar(void);
156 static void poly_endchar(void);
157 static void poly_close(void);
158 static void poly_pnt(float x, float y);
159 static void spline_beginchar(void);
160 static void spline_endchar(void);
161 static void spline_close(void);
162 static void spline_line(float x0, float y0, float x1, float y1);
163 static void spline_curveto(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
164 static void savestart(int x, int y);
165 static void sbpoint( int x, int y);
166 static void rmoveto( int x, int y);
167 static void drawline(float x0, float y0, float x1, float y1, float dx0, float dy0, float dx1, float dy1);
168 static void rlineto( int x, int y);
169 static void closepath(void);
170 static void bezadapt( float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float beztol);
171 static void drawbez( float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
172 static int docommand(int cmd);
173
174 /* some local vars */
175 static int startx, starty;
176 static int curx, cury;
177 static int nextx, nexty;
178 static int delx, dely;
179 static int started;
180
181
182 /* postscript commands */
183 #define HSTEM           (1)
184 #define VSTEM           (3)
185 #define VMOVETO         (4)
186 #define RLINETO         (5)
187 #define HLINETO         (6)
188 #define VLINETO         (7)
189 #define RRCURVETO       (8)
190 #define CLOSEPATH       (9)
191 #define CALLSUBR        (10)
192 #define RETURN          (11)
193 #define HSBW            (13)
194 #define ENDCHAR         (14)
195 #define RMOVETO         (21)
196 #define HMOVETO         (22)
197 #define VHCURVETO       (30)
198 #define HVCURVETO       (31)
199 #define DOTSECTION      (256+0)
200 #define VSTEM3          (256+1)
201 #define HSTEM3          (256+2)
202 #define SEAC            (256+6)
203 #define SBW             (256+7)
204 #define DIV             (256+12)
205 #define CALLOTHERSUBR   (256+16)
206 #define POP             (256+17)
207 #define SETCURRENTPOINT (256+33)
208 #define WHAT0           (0)
209
210 /* some dirt for windows */
211 #ifdef WIN32
212 #include "BLI_winstuff.h"
213 #endif
214
215 static char oneline[LINELEN];
216 static objfnt *fnt;
217
218 static unsigned short int mr;
219
220 static char *bindat;
221 static int datbytes;
222 static int firsted;
223 static short chardata[2000];
224 static int nshorts;
225
226 static int thecharwidth, thesidebearing;
227 static int npnts, nloops;
228 static int nvertpos;
229
230 static int fakepos;
231 static int fakemax;
232
233 static float beztol = 100.0;
234
235 /* extern: uit de libfm */
236
237 static char *my_subrs[MAXSUBRS];
238 static unsigned int my_sublen[MAXSUBRS];
239 static char *my_chars[MAXCHARS];
240 static unsigned int my_charlen[MAXCHARS];
241 static char *my_charname[MAXCHARS];
242 static int my_nsubrs, my_nchars;
243
244 static short sidebearing[MAXCHARS];
245 static char tok[LINELEN];
246 static int sp_npnts, sp_nloops;
247
248 /* 
249  *      interpreter globals
250  */
251
252
253 static float mat[2][2];
254 static char *pcstack[100];
255 static char *pc;
256 static int pcsp;
257 static int coordpos;
258 static int coordsave[7][2];
259 static int incusp;
260 static int retstack[1000];
261 static int retsp;
262 static int stack[1000];
263 static int sp;
264 static int savesplines = 1;
265
266 static pschar ISOcharlist[NASCII] = {
267         "/space",               040,    0,
268             "/exclam",          041,    0,
269             "/quotedbl",        042,    0,
270             "/numbersign",      043,    0,
271             "/dollar",          044,    0,
272             "/percent",         045,    0,
273             "/ampersand",       046,    0,
274             "/quoteright",      047,    0,
275
276             "/parenleft",       050,    0,
277             "/parenright",      051,    0,
278             "/asterisk",        052,    0,
279             "/plus",            053,    0,
280             "/comma",           054,    0,
281             "/hyphen",          055,    0,
282             "/period",          056,    0,
283             "/slash",           057,    0,
284
285             "/zero",            060,    0,
286             "/one",             061,    0,
287             "/two",             062,    0,
288             "/three",           063,    0,
289             "/four",            064,    0,
290             "/five",            065,    0,
291             "/six",             066,    0,
292             "/seven",           067,    0,
293
294             "/eight",           070,    0,
295             "/nine",            071,    0,
296             "/colon",           072,    0,
297             "/semicolon",       073,    0,
298             "/less",            074,    0,
299             "/equal",           075,    0,
300             "/greater",         076,    0,
301             "/question",        077,    0,
302
303             "/at",              0100,   0,
304             "/A",               0101,   0,
305             "/B",               0102,   0,
306             "/C",               0103,   0,
307             "/D",               0104,   0,
308             "/E",               0105,   0,
309             "/F",               0106,   0,
310             "/G",               0107,   0,
311
312             "/H",               0110,   0,
313             "/I",               0111,   0,
314             "/J",               0112,   0,
315             "/K",               0113,   0,
316             "/L",               0114,   0,
317             "/M",               0115,   0,
318             "/N",               0116,   0,
319             "/O",               0117,   0,
320
321             "/P",               0120,   0,
322             "/Q",               0121,   0,
323             "/R",               0122,   0,
324             "/S",               0123,   0,
325             "/T",               0124,   0,
326             "/U",               0125,   0,
327             "/V",               0126,   0,
328             "/W",               0127,   0,
329
330             "/X",               0130,   0,
331             "/Y",               0131,   0,
332             "/Z",               0132,   0,
333             "/bracketleft",     0133,   0,
334             "/backslash",       0134,   0,
335             "/bracketright",    0135,   0,
336             "/asciicircum",     0136,   0,
337             "/underscore",      0137,   0,
338
339             "/quoteleft",       0140,   0,
340             "/a",               0141,   0,
341             "/b",               0142,   0,
342             "/c",               0143,   0,
343             "/d",               0144,   0,
344             "/e",               0145,   0,
345             "/f",               0146,   0,
346             "/g",               0147,   0,
347
348             "/h",               0150,   0,
349             "/i",               0151,   0,
350             "/j",               0152,   0,
351             "/k",               0153,   0,
352             "/l",               0154,   0,
353             "/m",               0155,   0,
354             "/n",               0156,   0,
355             "/o",               0157,   0,
356
357             "/p",               0160,   0,
358             "/q",               0161,   0,
359             "/r",               0162,   0,
360             "/s",               0163,   0,
361             "/t",               0164,   0,
362             "/u",               0165,   0,
363             "/v",               0166,   0,
364             "/w",               0167,   0,
365
366             "/x",               0170,   0,
367             "/y",               0171,   0,
368             "/z",               0172,   0,
369             "/braceleft",       0173,   0,
370             "/bar",             0174,   0,
371             "/braceright",      0175,   0,
372             "/asciitilde",      0176,   0,
373             "/",                0177,   0,
374
375
376             /* nonstandard defs */
377
378         "/quotedblleft",        0200,   0,
379             "/quotedblright",   0201,   0,
380             "/quotedblbase",    0202,   0,
381             "/quotesinglbase",  0203,   0,
382             "/guilsinglleft",   0204,   0,
383             "/guilsinglright",  0205,   0,
384             "/endash",          0206,   0,
385             "/dagger",          0207,   0,
386
387             "/daggerdbl",       0210,   0,
388             "/trademark",       0211,   0,
389             "/bullet",          0212,   0,
390             "/perthousand",     0213,   0,
391             "/Lslash",          0214,   0,
392             "/OE",              0215,   0,
393             "/lslash",          0216,   0,
394             "/oe",              0217,   0,
395
396             /* endnonstandard defs */
397
398         "/dotlessi",    0220,   0,
399             "/grave",           0221,   0,
400             "/acute",           0222,   0,
401             "/circumflex",      0223,   0,
402             "/tilde",           0224,   0,
403             "/",                0225,   0,
404             "/breve",           0226,   0,
405             "/dotaccent",       0227,   0,
406
407             "/",                0230,   0,
408             "/",                0231,   0,
409             "/ring",            0232,   0,
410             "/",                0233,   0,
411             "/",                0234,   0,
412             "/hungarumlaut",    0235,   0,
413             "/ogonek",          0236,   0,
414             "/caron",           0237,   0,
415
416             "/",                0240,   0,
417             "/exclamdown",      0241,   0,
418             "/cent",            0242,   0,
419             "/sterling",        0243,   0,
420             "/florin",          0244,   0,
421             "/yen",             0245,   0,
422             "/brokenbar",       0246,   0,
423             "/section",         0247,   0,
424
425             "/dieresis",        0250,   0,
426             "/copyright",       0251,   0,
427             "/ordfeminine",     0252,   0,
428             "/guillemotleft",   0253,   0,
429             "/logicalnot",      0254,   0,
430             "/hyphen",          0255,   0,
431             "/registered",      0256,   0,
432             "/macron",          0257,   0,
433
434             "/degree",          0260,   0,
435             "/plusminus",       0261,   0,
436             "/twosuperior",     0262,   0,
437             "/threesuperior",   0263,   0,
438             "/acute",           0264,   0,
439             "/mu",              0265,   0,
440             "/paragraph",       0266,   0,
441             "/periodcentered",  0267,   0,
442
443             "/cedilla",         0270,   0,
444             "/onesuperior",     0271,   0,
445             "/ordmasculine",    0272,   0,
446             "/guillemotright",  0273,   0,
447             "/onequarter",      0274,   0,
448             "/onehalf",         0275,   0,
449             "/threequarters",   0276,   0,
450             "/questiondown",    0277,   0,
451
452             "/Agrave",          0300,   0,
453             "/Aacute",          0301,   0,
454             "/Acircumflex",     0302,   0,
455             "/Atilde",          0303,   0,
456             "/Adieresis",       0304,   0,
457             "/Aring",           0305,   0,
458             "/AE",              0306,   0,
459             "/Ccedilla",        0307,   0,
460
461             "/Egrave",          0310,   0,
462             "/Eacute",          0311,   0,
463             "/Ecircumflex",     0312,   0,
464             "/Edieresis",       0313,   0,
465             "/Igrave",          0314,   0,
466             "/Iacute",          0315,   0,
467             "/Icircumflex",     0316,   0,
468             "/Idieresis",       0317,   0,
469
470             "/Eth",             0320,   0,
471             "/Ntilde",          0321,   0,
472             "/Ograve",          0322,   0,
473             "/Oacute",          0323,   0,
474             "/Ocircumflex",     0324,   0,
475             "/Otilde",          0325,   0,
476             "/Odieresis",       0326,   0,
477             "/multiply",        0327,   0,
478
479             "/Oslash",          0330,   0,
480             "/Ugrave",          0331,   0,
481             "/Uacute",          0332,   0,
482             "/Ucircumflex",     0333,   0,
483             "/Udieresis",       0334,   0,
484             "/Yacute",          0335,   0,
485             "/Thorn",           0336,   0,
486             "/germandbls",      0337,   0,
487
488             "/agrave",          0340,   0,
489             "/aacute",          0341,   0,
490             "/acircumflex",     0342,   0,
491             "/atilde",          0343,   0,
492             "/adieresis",       0344,   0,
493             "/aring",           0345,   0,
494             "/ae",              0346,   0,
495             "/ccedilla",        0347,   0,
496
497             "/egrave",          0350,   0,
498             "/eacute",          0351,   0,
499             "/ecircumflex",     0352,   0,
500             "/edieresis",       0353,   0,
501             "/igrave",          0354,   0,
502             "/iacute",          0355,   0,
503             "/icircumflex",     0356,   0,
504             "/idieresis",       0357,   0,
505
506             "/eth",             0360,   0,
507             "/ntilde",          0361,   0,
508             "/ograve",          0362,   0,
509             "/oacute",          0363,   0,
510             "/ocircumflex",     0364,   0,
511             "/otilde",          0365,   0,
512             "/odieresis",       0366,   0,
513             "/divide",          0367,   0,
514
515             "/oslash",          0370,   0,
516             "/ugrave",          0371,   0,
517             "/uacute",          0372,   0,
518             "/ucircumflex",     0373,   0,
519             "/udieresis",       0374,   0,
520             "/yacute",          0375,   0,
521             "/thorn",           0376,   0,
522             "/ydieresis",       0377,   0,
523 };
524
525
526 static short STDvsISO [][2] = {
527         0341, 0306, /* AE */
528         0351, 0330, /* Oslash */
529         0302, 0222, /* acute */
530         0361, 0346, /* ae */
531         0306, 0226, /* breve */
532         0317, 0237, /* caron */
533         0313, 0270, /* cedilla */
534         0303, 0223, /* circumflex */
535         0250, 0244, /* currency */
536         0310, 0250, /* dieresis */
537         0307, 0227, /* dotaccent */
538         0365, 0220, /* dotlessi */
539         0373, 0337, /* germandbls */
540         0301, 0221, /* grave */
541         0315, 0235, /* hungarumlaut */
542         0055, 0255, /* hyphen */
543         0305, 0257, /* macron */
544         0316, 0236, /* ogenek */
545         0343, 0252, /* ordfeminine */
546         0353, 0272, /* ordmasculine */
547         0371, 0370, /* oslash */
548         0264, 0267, /* periodcentered */
549         0312, 0232, /* ring */
550         0304, 0224, /* tilde */
551 };
552
553 /* from objfont.c de rest zit in lfm_s !!*/
554
555 /* START 5.2 */
556
557 static int chartoindex(objfnt *fnt, int c)
558 {
559         if(c<fnt->charmin)
560                 return -1;
561         if(c>fnt->charmax)
562                 return -1;
563         return c-fnt->charmin;
564 }
565
566
567 static chardesc *getchardesc(objfnt *fnt, int c)
568 {
569         int index;
570
571         index = chartoindex(fnt,c);
572         if(index<0)
573                 return 0;
574         return fnt->my_chars+index;
575 }
576
577 static objfnt *newobjfnt(int type, int charmin, int charmax, int fscale)
578 {
579         objfnt *fnt;
580
581         fnt = (objfnt *)MEM_mallocN(sizeof(objfnt), "newobjfnt");
582         fnt->freeaddr = 0;
583         fnt->type = type;
584         fnt->charmin = charmin;
585         fnt->charmax = charmax;
586         fnt->my_nchars = fnt->charmax-fnt->charmin+1;
587         fnt->scale = fscale;
588         fnt->my_chars = (chardesc *)MEM_mallocN(fnt->my_nchars*sizeof(chardesc), "newobjfnt2");
589         memset(fnt->my_chars, 0, fnt->my_nchars*sizeof(chardesc));
590         return fnt;
591 }
592
593
594 static void addchardata (objfnt * fnt, int c, short * data, int nshorts)
595 {
596         int index;
597         chardesc *cd;
598
599         index = chartoindex(fnt,c);
600         if(index<0) {
601                 fprintf(stderr,"Addchardata bad poop\n");
602                 return;
603         }
604         cd = fnt->my_chars+index;
605         fnt->freeaddr = 0;
606         cd->datalen = nshorts*sizeof(short);
607         cd->data = (short *)MEM_mallocN(cd->datalen, "addchardata");
608         memcpy(cd->data, data, cd->datalen);
609 }
610
611 static void addcharmetrics(objfnt *fnt, int c, int movex, int movey)
612 {
613         int index;
614         chardesc *cd;
615
616         index = chartoindex(fnt,c);
617         if(index<0) {
618                 fprintf(stderr,"Addcharmetrics bad poop\n");
619                 return;
620         }
621         cd = fnt->my_chars+index;
622         cd->movex = movex;
623         cd->movey = movey;
624 }
625
626
627 static void fakechar(objfnt *fnt, int c, int width)
628 {
629         short chardata[1];
630
631         chardata[0] = PO_RET;
632         addchardata(fnt,c,chardata,1);
633         addcharmetrics(fnt,c,width,0);
634 }
635
636
637 static void freeobjfnt(objfnt * fnt)
638 {
639         int i;
640         chardesc *cd;
641
642         cd = fnt->my_chars;
643         for(i=0; i<fnt->my_nchars; i++) {
644                 if(cd->data)
645                         MEM_freeN(cd->data);
646                 cd++;
647         }
648         MEM_freeN(fnt->my_chars);
649         MEM_freeN(fnt);
650 }
651
652
653 /* END 5.2 */
654
655 static short STDtoISO(short c)
656 {
657         short i = (sizeof(STDvsISO) / (2 * sizeof(short))) - 1;
658
659         for (;i >= 0; i--){
660                 if (STDvsISO[i][0] == c) return (STDvsISO[i][1]);
661         }
662         return(c);
663 }
664
665
666 /*
667  *      read the font matrix out of the font file
668  *
669  */
670
671 static char * newfgets(char * s, int n, PackedFile * pf){
672         int read = 0;
673         int c;
674         char * p;
675
676         p = s;
677         while (n > 0){
678                 c = ((char *) pf->data)[pf->seek];
679                 pf->seek++;
680                 if (pf->seek > pf->size){
681                         if (read == 0) return (0);
682                         *p = 0;
683                         return(s);
684                 }
685                 if (c == 10 || c == 13){
686                         *p = 0;
687                         return(s);
688                 }
689                 *p++ = c;
690                 n--;
691         }
692         *p = 0;
693         return(s);
694 }
695
696 static int readfontmatrix(PackedFile * pf, float mat[2][2])
697 {
698         char *cptr;
699         float a, b, c, d, e, f;
700
701         pf->seek = 0;
702         
703         /* look for the FontMatrix def */
704         while(1) {
705                 if(!newfgets(oneline, LINELEN, pf)) {
706                         fprintf(stderr,"fromtype1: no FontMatrix found\n");
707                         return(-1);
708                 }
709                 cptr = strchr(oneline,'/');
710                 if(cptr) {
711                         if(strncmp(cptr,"/FontMatrix",11) == 0) {
712                                 cptr = strchr(cptr,'[');
713                                 if(!cptr) {
714                                         fprintf(stderr,"fromtype1: bad FontMatrix line\n");
715                                         return(-1);
716                                 }
717                                 sscanf(cptr+1,"%f %f %f %f %f %f\n",&a,&b,&c,&d,&e,&f);
718                                 break;
719                         }
720                 }
721         }
722
723         mat[0][0] = 1000.0*a;
724         mat[1][0] = 1000.0*b;
725         mat[0][1] = 1000.0*c;
726         mat[1][1] = 1000.0*d;
727
728         return(0);
729 }
730
731 /*
732  *      Decryption support
733  *
734  *
735  */
736 static void resetdecrypt(int n)
737 {
738         mr = n;
739 }
740
741
742
743 /*
744  *      decryption subroutines
745  *
746  */
747
748 static char mdecrypt(char cipher)
749 {
750         char plain;
751
752         plain = (cipher^(mr>>8));
753         mr = (cipher+mr)*MC1 + MC2;
754         return plain;
755 }
756
757 static void decryptdata(char * cptr, int n)
758 {
759         while(n--) {
760                 *cptr = mdecrypt(*cptr);
761                 cptr++;
762         }
763 }
764
765 static int decryptprogram(char *buf, int len)
766 {
767         int i;
768
769         resetdecrypt(4330);
770         for(i=0; i<len; i++) {
771                 if(i<SKIP)
772                         mdecrypt(buf[i]);
773                 else
774                         buf[i-SKIP] = mdecrypt(buf[i]);
775         }
776         return len-SKIP;
777 }
778
779 static void decryptall(void)
780 {
781         int i;
782
783         for(i=0; i<my_nsubrs; i++)
784                 my_sublen[i] = decryptprogram(my_subrs[i],my_sublen[i]);
785         for(i=0; i<my_nchars; i++)
786                 my_charlen[i] = decryptprogram(my_chars[i],my_charlen[i]);
787 }
788
789
790 /*
791  *      decode the eexec part of the file
792  *
793  */
794
795 static int decodetype1(PackedFile * pf, char *outname)
796 {
797         char *hptr, *bptr;
798         int i, totlen, hexbytes, c;
799         char *hexdat;
800         char hextab[256];
801
802         /* make hex table */
803         if(!firsted) {
804                 for(i=0; i<256; i++) {
805                         if(i>='0' && i<='9')
806                                 hextab[i] = i-'0';
807                         else if(i>='a' && i<='f')
808                                 hextab[i] = 10+i-'a';
809                         else if(i>='A' && i<='F')
810                                 hextab[i] = 10+i-'A';
811                         else
812                                 hextab[i] = NOTHEX;
813                 }
814         }
815
816         pf->seek = 0;
817         
818         /* allocate buffers */
819         totlen = pf->size;
820         hexdat = (char *)MEM_mallocN(totlen, "hexdat");
821         bindat = (char *)MEM_mallocN(totlen, "bindat");
822
823         /* look for eexec part of file */
824         while(1) {
825                 if(!newfgets(oneline, LINELEN, pf)) {
826                         fprintf(stderr,"fromtype1: no currentfile eexec found\n");
827                         return(-1);
828                 }
829                 oneline[16] = 0;
830                 if(strcmp(oneline,"currentfile eexe") == 0)
831                         break;
832         }
833
834         /* initialize decryption variables */
835         mr = 55665;
836
837         /* first byte == 0 for binary data (???) */
838         
839         c = ((char *) pf->data)[pf->seek];
840
841         if (hextab[c] != NOTHEX){
842                 /* read all the hex bytes into the hex buffer */
843                 hexbytes = 0;
844                 while(newfgets(oneline, LINELEN, pf)) {
845                         hptr = (char *)oneline;
846                         while(*hptr) {
847                                 if(hextab[*hptr] != NOTHEX)
848                                         hexdat[hexbytes++] = *hptr;
849                                 hptr++;
850                         }
851                 }
852
853                 /* check number of hex bytes */
854                 if(hexbytes & 1)
855                         hexbytes--;
856                 datbytes = hexbytes/2;
857
858                 /* translate hex data to binary */
859                 hptr = hexdat;
860                 bptr = bindat;
861                 c = datbytes;
862                 while(c--) {
863                         *bptr++  = (hextab[hptr[0]]<<4)+hextab[hptr[1]];
864                         hptr += 2;
865                 }
866
867                 /* decrypt the data */
868                 decryptdata(bindat,datbytes);
869
870         } else {
871                 datbytes = pf->size - pf->seek;
872                 memcpy(bindat, ((char *) pf->data) + pf->seek, datbytes);
873
874                 if ((bindat[2] << 8 + bindat[3]) == 0x800){
875                         /* order data (remove 6 bytes headers) */
876                         i = datbytes;
877                         hptr = bptr = bindat + 4;
878                         hptr += 2;
879
880                         while (i > 0){
881                                 if (i > 2046) c = 2046;
882                                 else c = i;
883
884                                 memcpy(bptr, hptr, c);
885                                 bptr += 2046;
886                                 hptr += 2046 + 6;
887                                 i -= 2046 + 6;
888                                 datbytes -= 6;
889                         }
890
891                         /* decrypt the data */
892                         decryptdata(bindat+4,datbytes);
893                 } else{
894                         decryptdata(bindat+6,datbytes-6);
895                 }
896         }
897
898 #ifdef DEBUG
899         outf = fopen(outname,"wb");
900         fwrite(bindat,datbytes,1,outf);
901         fclose(outf);
902 #endif 
903
904         MEM_freeN(hexdat);
905         
906         return 1;
907 }
908
909 /* 
910  *      fake file reading funcs
911  *
912  *
913  */
914
915 static void fakefopen(void)
916 {
917         fakepos = 0;
918         fakemax = datbytes;
919 }
920
921
922 static void fakegettoken(char *str)
923 {
924         int c;
925         char *cptr;
926         char *start;
927
928         start = (char *) str;
929         cptr = bindat+fakepos;
930         c = *cptr++;
931         fakepos++;
932         if(c != '\n') {
933                 while(isspace(c)) {
934                         c = *cptr++;
935                         fakepos++;
936                 }
937                 while (fakepos<fakemax && !isspace(c)) {
938                         *str++ = c;
939                         c = *cptr++;
940                         fakepos++;
941                 }
942                 if(c == '\n')
943                         fakepos--;
944         }
945         *str = 0;
946         if(fakepos>fakemax) {
947                 fprintf(stderr,"fromtype1: unexpected eof\n");
948                 strcpy(start, "end");
949         }
950 }
951
952 static int fakefgets(char *buf,int max)
953 {
954         char *cptr;
955
956         cptr = (char *)(bindat+fakepos);
957         while(max--) {
958                 *buf++ = *cptr;
959                 fakepos++;
960                 if(*cptr == 10 || *cptr == 13)
961                         return 1;
962                 cptr++;
963                 if(fakepos>fakemax)
964                         return 0;
965         }
966         return 0;
967 }
968
969 static char *fakefread(int n)
970 {
971         fakepos += n;
972         return bindat+fakepos-n;
973 }
974
975 static void applymat(float mat[][2], float *x, float *y)
976 {
977         float tx, ty;
978
979         tx = ((*x)*mat[0][0])+((*y)*mat[0][1]);
980         ty = ((*x)*mat[1][0])+((*y)*mat[1][1]);
981         *x = tx;
982         *y = ty;
983 }
984
985 static void setcharlist(void)
986 {
987         char *name, found;
988         int i, j;
989
990         for(i=0; i<NASCII; i++) ISOcharlist[i].prog = -1;
991
992         for(j=0; j<my_nchars; j++) {
993                 name = my_charname[j];
994                 if(name) {
995                         found = 0;
996                         for(i=0; i<NASCII; i++) {
997                                 if(ISOcharlist[i].name && (strcmp(name,ISOcharlist[i].name) == 0)){
998                                         ISOcharlist[i].prog = j;
999                                         found = 1;
1000                                 }
1001                         }
1002                         /*if (found == 0) printf("no match found for: %s\n", name);*/
1003                         MEM_freeN(name);
1004                         my_charname[j] = 0;
1005                 }
1006         }
1007 }
1008
1009
1010 static objfnt * objfnt_from_psfont(PackedFile * pf)
1011 {
1012         int i, k, index;
1013         int nread, namelen;
1014         char *cptr;
1015                         
1016         fnt = 0;
1017         bindat = 0;
1018         
1019         /* read the font matrix from the font */
1020         if (readfontmatrix(pf,mat)) return(0);
1021
1022         /* decode the font data */
1023         decodetype1(pf, "/usr/tmp/type1.dec");
1024
1025         /* open the input file */
1026         fakefopen();
1027
1028         /* look for the /Subrs def and get my_nsubrs */
1029         while(1) {
1030                 if(!fakefgets(oneline,LINELEN)) {
1031                         fprintf(stderr,"fromtype1: no /Subrs found\n");
1032                         my_nsubrs = 0;
1033                         fakefopen();
1034                         break;
1035                 }
1036                 cptr = strchr(oneline,'/');
1037                 if(cptr) {
1038                         if(strncmp(cptr,"/Subrs",6) == 0) {
1039                                 my_nsubrs = atoi(cptr+6);
1040                                 break;
1041                         }
1042                 }
1043         }
1044
1045         /* read the Subrs in one by one */
1046         for(i=0; i<my_nsubrs; i++)
1047                 my_sublen[i] = 0;
1048         for(i=0; i<my_nsubrs; i++) {
1049                 for(k=0; k<MAXTRIES; k++) {
1050                         fakegettoken(tok);
1051                         if(strcmp(tok,"dup") == 0)
1052                                 break;
1053                 }
1054                 if(k == MAXTRIES) {
1055                         fprintf(stderr,"dup for subr %d not found in range\n", i);
1056                         /*exit(1);*/
1057                 }
1058
1059                 /* get the Subr index here */
1060                 fakegettoken(tok);
1061                 index = atoi(tok);
1062
1063                 /* check to make sure it is in range */
1064                 if(index<0 || index>my_nsubrs) {
1065                         fprintf(stderr,"bad Subr index %d\n",index);
1066                         /*exit(1);*/
1067                 }
1068
1069                 /* get the number of bytes to read */
1070                 fakegettoken(tok);
1071                 nread = atoi(tok);
1072                 fakegettoken(tok);
1073
1074                 /* read in the subroutine */
1075                 my_sublen[index] = nread;
1076                 my_subrs[index] = fakefread(nread);
1077                 fakegettoken(tok);
1078         }
1079
1080         /* look for the CharStrings */
1081         while(1) {
1082                 fakegettoken(tok);
1083                 cptr = strchr(tok,'/');
1084                 if(cptr && strcmp(cptr,"/CharStrings") == 0)
1085                         break;
1086         }
1087
1088         fakegettoken(tok);      /* skip my_ncharscrings */
1089         fakegettoken(tok);      /* skip dict */
1090         fakegettoken(tok);      /* skip dup */
1091         fakegettoken(tok);      /* skip begin */
1092         fakegettoken(tok);      /* skip newline */
1093
1094         /* read the CharStrings one by one */
1095         my_nchars = 0;
1096         for(i=0; i<MAXCHARS; i++) {
1097
1098                 /* check for end */
1099                 fakegettoken(tok);
1100                 if(strcmp(tok,"end") == 0)
1101                         break;
1102
1103                 /* get the char name and allocate space for it */
1104                 namelen = strlen(tok);
1105                 my_charname[i] = (char *)MEM_mallocN(namelen+1, "my_charname");
1106                 strcpy(my_charname[i],tok);
1107
1108                 /* get the number of bytes to read */
1109                 fakegettoken(tok);
1110                 nread = atoi(tok);
1111                 fakegettoken(tok);
1112
1113                 /* read in the char description */
1114                 my_charlen[i] = nread;
1115                 my_chars[i] = fakefread(nread);
1116
1117                 /* skip the end of line */
1118                 fakegettoken(tok);
1119                 fakegettoken(tok);
1120                 my_nchars++;
1121         }
1122
1123         /* decrypt the character descriptions */
1124         decryptall();
1125         setcharlist();
1126
1127         /* make the obj font */
1128         makeobjfont(savesplines);
1129
1130         if (bindat) MEM_freeN(bindat);
1131         /* system("rm /usr/tmp/type1.dec"); */
1132
1133         return (fnt);
1134 }
1135
1136
1137
1138
1139 /*
1140  *      pc stack support
1141  *
1142  */
1143
1144 static void initpcstack(void)
1145 {
1146         pcsp = 0;
1147 }
1148
1149 static void pushpc(char *pc)
1150 {
1151         pcstack[pcsp] = pc;
1152         pcsp++;
1153 }
1154
1155 static char *poppc(void)
1156 {
1157         pcsp--;
1158         if(pcsp<0) {
1159                 fprintf(stderr,"\nYUCK: pc stack under flow\n");
1160                 pcsp = 0;
1161                 return 0;
1162         }
1163         return pcstack[pcsp];
1164 }
1165
1166 /*
1167  *      Data stack support
1168  *
1169  */
1170
1171 static void initstack(void)
1172 {
1173         sp = 0;
1174 }
1175
1176 static void push(int val)
1177 /*  int val; */
1178 {
1179         stack[sp] = val;
1180         sp++;
1181 }
1182
1183 static int pop(void)
1184 {
1185         sp--;
1186         if(sp<0) {
1187                 fprintf(stderr,"\nYUCK: stack under flow\n");
1188                 sp = 0;
1189                 return 0;
1190         }
1191         return stack[sp];
1192 }
1193
1194 /*
1195  *      call/return data stack
1196  *
1197  */
1198
1199 static void initretstack(void)
1200 {
1201         retsp = 0;
1202 }
1203
1204 static void retpush(int val)
1205 /*  int val; */
1206 {
1207         retstack[retsp] = val;
1208         retsp++;
1209 }
1210
1211 static int retpop(void)
1212 {
1213         retsp--;
1214         if(retsp<0) {
1215                 fprintf(stderr,"\nYUCK: ret stack under flow\n");
1216                 retsp = 0;
1217                 return 0;
1218         }
1219         return retstack[retsp];
1220 }
1221
1222
1223 /*
1224  *      execute the program:
1225  *
1226  *
1227  */
1228
1229 static void getmove(int *x, int *y)
1230 {
1231         *x = delx;
1232         *y = dely;
1233         /*      printf("ingetmove\n"); */
1234 }
1235
1236 static void getpos(int *x, int *y)
1237 {
1238         *x = curx;
1239         *y = cury;
1240 }
1241
1242 static void subr1(void)
1243 {
1244         coordpos = 0;
1245         incusp = 1;
1246 }
1247
1248 static void subr2(void)
1249 {
1250         int x, y;
1251
1252         getmove(&x,&y);
1253         if(coordpos>=7) {
1254                 fprintf(stderr,"subr2: bad poop\n");
1255                 /*exit(1);*/
1256         }
1257         coordsave[coordpos][0] = x;
1258         coordsave[coordpos][1] = y;
1259         coordpos++;
1260 }
1261
1262 static void subr0(void)
1263 {
1264         int x0, y0;
1265         int x1, y1;
1266         int x2, y2;
1267         int x3, y3;
1268         int xpos, ypos, noise;
1269
1270         ypos = pop();
1271         xpos = pop();
1272         noise = pop();
1273         if(coordpos!=7) {
1274                 fprintf(stderr,"subr0: bad poop\n");
1275                 /*exit(1);*/
1276         }
1277         x0 =  coordsave[0][0];
1278         y0 =  coordsave[0][1];
1279
1280         x1 =  coordsave[1][0]+x0;
1281         y1 =  coordsave[1][1]+y0;
1282         x2 =  coordsave[2][0];
1283         y2 =  coordsave[2][1];
1284         x3 =  coordsave[3][0];
1285         y3 =  coordsave[3][1];
1286         rcurveto(x1,y1,x1+x2,y1+y2,x1+x2+x3,y1+y2+y3);
1287         x1 =  coordsave[4][0];
1288         y1 =  coordsave[4][1];
1289         x2 =  coordsave[5][0];
1290         y2 =  coordsave[5][1];
1291         x3 =  coordsave[6][0];
1292         y3 =  coordsave[6][1];
1293         rcurveto(x1,y1,x1+x2,y1+y2,x1+x2+x3,y1+y2+y3);
1294         getpos(&x0,&y0);
1295         retpush(y0);
1296         retpush(x0);
1297         incusp = 0;
1298 }
1299
1300 static void append_poly_offset(short ofsx, short ofsy, short * data)
1301 {
1302         int nverts;
1303
1304         if (data == 0) return;
1305
1306         while(1) {
1307                 switch(chardata[nshorts++] = *data++) {
1308                 case PO_BGNLOOP:
1309                         nshorts --;     /* voor de eerste keer */
1310                         break;
1311                 case PO_RETENDLOOP:
1312                 case PO_RET:
1313                         return;
1314                 }
1315                 nverts = chardata[nshorts++] = *data++;
1316                 while(nverts--) {
1317                         chardata[nshorts++] = (*data++) + ofsx;
1318                         chardata[nshorts++] = (*data++) + ofsy;
1319                 }
1320         }
1321 }
1322
1323
1324 static void append_spline_offset(short ofsx, short ofsy, short * data)
1325 {
1326         int nverts = 0;
1327
1328         if (data == 0) return;
1329
1330         while(1) {
1331                 switch(chardata[nshorts++] = *data++) {
1332                 case SP_MOVETO:
1333                 case SP_LINETO:
1334                         nverts = 1;
1335                         break;
1336                 case SP_CURVETO:
1337                         nverts = 3;
1338                         break;
1339                 case SP_RETCLOSEPATH:
1340                 case SP_RET:
1341                         return;
1342                 }
1343
1344                 for (; nverts > 0; nverts--) {
1345                         chardata[nshorts++] = (*data++) + ofsx;
1346                         chardata[nshorts++] = (*data++) + ofsy;
1347                 }
1348         }
1349 }
1350
1351
1352
1353 /* 
1354  *    graphics follows 
1355  *
1356  *
1357  */
1358
1359
1360 /* poly output stuff */
1361
1362 static void setwidth(int w, int x)
1363 {
1364         thecharwidth = w;
1365         thesidebearing = x;
1366 }
1367
1368 static void poly_beginchar(void)
1369 {
1370         npnts = 0;
1371         nloops = 0;
1372 }
1373
1374 static void poly_endchar(void)
1375 {
1376         if(nloops == 0)
1377                 chardata[nshorts++] = PO_RET;
1378         else
1379                 chardata[nshorts++] = PO_RETENDLOOP;
1380 }
1381
1382 static void poly_close(void)
1383 {
1384         chardata[nvertpos] = npnts;
1385         npnts = 0;
1386 }
1387
1388 static void poly_pnt(float x, float y)
1389 {
1390         int ix, iy;
1391
1392         applymat(mat,&x,&y);
1393         ix = floor(x);
1394         iy = floor(y);
1395         if(npnts == 0) {
1396                 if(nloops == 0) {
1397                         chardata[nshorts++] = PO_BGNLOOP;
1398                         nvertpos = nshorts++;
1399                 } else {
1400                         chardata[nshorts++] = PO_ENDBGNLOOP;
1401                         nvertpos = nshorts++;
1402                 }
1403                 nloops++;
1404         }
1405         chardata[nshorts++] = ix;
1406         chardata[nshorts++] = iy;
1407         npnts++;
1408
1409 }
1410
1411 /* spline output stuff */
1412
1413 static void spline_beginchar(void)
1414 {
1415         sp_npnts = 0;
1416         sp_nloops = 0;
1417 }
1418
1419 static void spline_endchar(void)
1420 {
1421         if(sp_nloops == 0)
1422                 chardata[nshorts++] = SP_RET;
1423         else
1424                 chardata[nshorts++] = SP_RETCLOSEPATH;
1425 }
1426
1427 static void spline_close(void)
1428 {
1429         chardata[nshorts++] = SP_CLOSEPATH;
1430         sp_npnts = 0;
1431         sp_nloops = 0;
1432 }
1433
1434 static void spline_line(float x0, float y0, float x1, float y1)
1435 {
1436         applymat(mat,&x0,&y0);
1437         applymat(mat,&x1,&y1);
1438
1439         if(sp_npnts == 0) {
1440                 chardata[nshorts++] = SP_MOVETO;
1441                 chardata[nshorts++] = floor(x0);
1442                 chardata[nshorts++] = floor(y0);
1443                 sp_npnts++;
1444                 sp_nloops++;
1445         }
1446         chardata[nshorts++] = SP_LINETO;
1447         chardata[nshorts++] = floor(x1);
1448         chardata[nshorts++] = floor(y1);
1449         sp_npnts++;
1450 }
1451
1452 static void spline_curveto(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
1453 {
1454         applymat(mat,&x0,&y0);
1455         applymat(mat,&x1,&y1);
1456         applymat(mat,&x2,&y2);
1457         applymat(mat,&x3,&y3);
1458
1459         if(sp_npnts == 0) {
1460                 chardata[nshorts++] = SP_MOVETO;
1461                 chardata[nshorts++] = floor(x0);
1462                 chardata[nshorts++] = floor(y0);
1463                 sp_npnts++;
1464                 sp_nloops++;
1465         }
1466         chardata[nshorts++] = SP_CURVETO;
1467         chardata[nshorts++] = floor(x1);
1468         chardata[nshorts++] = floor(y1);
1469         chardata[nshorts++] = floor(x2);
1470         chardata[nshorts++] = floor(y2);
1471         chardata[nshorts++] = floor(x3);
1472         chardata[nshorts++] = floor(y3);
1473 }
1474
1475 static void savestart(int x, int y)
1476 {
1477         startx = x;
1478         starty = y;
1479         started = 1;
1480 }
1481
1482 static void sbpoint( int x, int y)
1483 {
1484         curx = x;
1485         cury = y;
1486 }
1487
1488 static void rmoveto( int x, int y)
1489 {
1490         if(incusp) {
1491                 delx = x;
1492                 dely = y;
1493         } else {
1494                 curx += x;
1495                 cury += y;
1496                 savestart(curx,cury);
1497         }
1498 }
1499
1500 static void drawline(float x0, float y0, float x1, float y1, float dx0, float dy0, float dx1, float dy1)
1501 {
1502         if(x0!=x1 || y0!=y1)
1503                 poly_pnt(x1,y1);
1504 }
1505
1506
1507 static void rlineto( int x, int y)
1508 {
1509         float dx, dy;
1510
1511         nextx = curx + x;
1512         nexty = cury + y;
1513         dx = nextx-curx;
1514         dy = nexty-cury;
1515         if (savesplines) spline_line( curx, cury, nextx, nexty);
1516         else drawline( curx, cury, nextx, nexty,dx,dy,dx,dy);
1517         curx = nextx;
1518         cury = nexty;
1519 }
1520
1521 static void closepath(void)
1522 {
1523         float dx, dy;
1524
1525         if(started) {
1526                 dx = startx-curx;
1527                 dy = starty-cury;
1528                 if (savesplines) {
1529                         spline_close();
1530                 } else {
1531                         drawline( curx, cury, startx, starty,dx,dy,dx,dy);
1532                         poly_close();
1533                 }
1534                 started = 0;
1535         }
1536 }
1537
1538 static void bezadapt( float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float beztol)
1539 {
1540         float ax0,ay0,ax1,ay1,ax2,ay2,ax3,ay3;
1541         float bx0,by0,bx1,by1,bx2,by2,bx3,by3;
1542         float midx, midy;
1543         float linx, liny, dx, dy, mag;
1544
1545         midx = (x0+3*x1+3*x2+x3)/8.0;
1546         midy = (y0+3*y1+3*y2+y3)/8.0;
1547         linx = (x0+x3)/2.0;
1548         liny = (y0+y3)/2.0;
1549         dx = midx-linx;
1550         dy = midy-liny;
1551         mag = dx*dx+dy*dy;
1552         if(mag<(beztol*beztol))
1553                 drawline(x0,y0,x3,y3,x1-x0,y1-y0,x3-x2,y3-y2);
1554         else {
1555                 ax0 = x0;
1556                 ay0 = y0;
1557                 ax1 = (x0+x1)/2;
1558                 ay1 = (y0+y1)/2;
1559                 ax2 = (x0+2*x1+x2)/4;
1560                 ay2 = (y0+2*y1+y2)/4;
1561                 ax3 = midx;
1562                 ay3 = midy;
1563                 bezadapt(ax0,ay0,ax1,ay1,ax2,ay2,ax3,ay3,beztol);
1564
1565                 bx0 = midx;
1566                 by0 = midy;
1567                 bx1 = (x1+2*x2+x3)/4;
1568                 by1 = (y1+2*y2+y3)/4;
1569                 bx2 = (x2+x3)/2;
1570                 by2 = (y2+y3)/2;
1571                 bx3 = x3;
1572                 by3 = y3;
1573                 bezadapt(bx0,by0,bx1,by1,bx2,by2,bx3,by3,beztol);
1574         }
1575 }
1576
1577 static void drawbez( float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
1578 {
1579         bezadapt(x0,y0,x1,y1,x2,y2,x3,y3,beztol);
1580 }
1581
1582
1583 static void rcurveto( int dx1, int dy1, int dx2, int dy2, int dx3, int dy3)
1584 {
1585         int x0, y0;
1586         int x1, y1;
1587         int x2, y2;
1588         int x3, y3;
1589
1590         x0 = curx;
1591         y0 = cury;
1592         x1 = curx+dx1;
1593         y1 = cury+dy1;
1594         x2 = curx+dx2;
1595         y2 = cury+dy2;
1596         x3 = curx+dx3;
1597         y3 = cury+dy3;
1598
1599         if (savesplines) {
1600                 spline_curveto( x0, y0, x1, y1, x2, y2, x3, y3);
1601         } else{
1602                 drawbez( x0, y0, x1, y1, x2, y2, x3, y3);
1603         }
1604         curx = x3;
1605         cury = y3;
1606 }
1607
1608 /*
1609  *      saveobjfont -
1610  *              save an object font.
1611  *
1612  */
1613
1614 /* generic routines */
1615
1616 static void makeobjfont(int savesplines)
1617 {
1618         int i, c;
1619
1620         if(savesplines)
1621                 fnt = newobjfnt(SP_TYPE, 32, 32+NASCII-1, 9840);
1622         else
1623                 fnt = newobjfnt(PO_TYPE, 32, 32+NASCII-1, 9840);
1624
1625         for(i=0; i<NASCII; i++) {
1626                 c = i+32;
1627                 if(ISOcharlist[i].prog>=0) {
1628                         /*printf("decoding %s\n", ISOcharlist[i].name);*/
1629
1630                         nshorts = 0;
1631                         drawchar(ISOcharlist[i].prog);
1632                         addchardata(fnt,c,chardata,nshorts);
1633                         addcharmetrics(fnt,c,thecharwidth,0);
1634                         sidebearing[c] = thesidebearing;
1635                 } else if(c == ' ') {
1636                         printf("faking space %d\n",i);
1637                         fakechar(fnt,' ',400);
1638                 }
1639         }
1640 }
1641
1642 /*
1643  * run the character program    
1644  *
1645  *
1646  */
1647
1648 static void drawchar(int c)
1649 {
1650         if (savesplines) {
1651                 spline_beginchar();
1652         } else {
1653                 poly_beginchar();
1654         }
1655         initstack();
1656         initpcstack();
1657         initretstack();
1658         pc = my_chars[c];
1659         runprog();
1660         if (savesplines){
1661                 spline_endchar();
1662         } else {
1663                 poly_endchar();
1664         }
1665 }
1666
1667 static int docommand(int cmd)
1668 {
1669         int x, y, w, c1, c2;
1670         int dx1, dy1;
1671         int dx2, dy2;
1672         int dx3, dy3;
1673         float fdx1, fdy1;
1674         int i, sub, n;
1675         char *subpc;
1676         chardesc *cd;
1677         short *ndata;
1678
1679         switch(cmd) {
1680         case WHAT0:
1681                 fprintf(stderr,"\nYUCK: WHAT0\n");
1682                 break;
1683         case HSTEM:
1684                 pop();
1685                 pop();
1686                 /*printf("hstem: %d %d\n", pop(), pop());*/
1687                 break;
1688         case VSTEM:
1689                 pop();
1690                 pop();
1691                 /*printf("vstem: %d %d\n", pop(), pop());*/
1692                 break;
1693         case VMOVETO:
1694                 y = pop();
1695                 rmoveto(0,y);
1696                 break;
1697         case RLINETO:
1698                 y = pop();
1699                 x = pop();
1700                 rlineto(x,y);
1701                 break;
1702         case HLINETO:
1703                 x = pop();
1704                 rlineto(x,0);
1705                 break;
1706         case VLINETO:
1707                 y = pop();
1708                 rlineto(0,y);
1709                 break;
1710         case RRCURVETO:
1711                 dy3 = pop();
1712                 dx3 = pop();
1713                 dy2 = pop();
1714                 dx2 = pop();
1715                 dy1 = pop();
1716                 dx1 = pop();
1717                 rcurveto(dx1,dy1,dx1+dx2,dy1+dy2,dx1+dx2+dx3,dy1+dy2+dy3);
1718                 break;
1719         case CLOSEPATH:
1720                 closepath();
1721                 break;
1722         case CALLSUBR:
1723                 sub = pop();
1724                 subpc = my_subrs[sub];
1725                 if(!subpc) {
1726                         fprintf(stderr,"\nYUCK no sub addr\n");
1727                 }
1728                 pushpc(pc);
1729                 pc = subpc;
1730                 break;
1731         case RETURN:
1732                 pc = poppc();
1733                 break;
1734         case HSBW:
1735                 w = pop();
1736                 x = pop();
1737                 setwidth(w, x);
1738                 sbpoint(x,0);
1739                 break;
1740         case ENDCHAR:
1741                 closepath();
1742                 break;
1743         case RMOVETO:
1744                 y = pop();
1745                 x = pop();
1746                 rmoveto(x,y);
1747                 break;
1748         case HMOVETO:
1749                 x = pop();
1750                 rmoveto(x,0);
1751                 break;
1752         case VHCURVETO:
1753                 dy3 = 0;
1754                 dx3 = pop();
1755                 dy2 = pop();
1756                 dx2 = pop();
1757                 dy1 = pop();
1758                 dx1 = 0;
1759                 rcurveto(dx1,dy1,dx1+dx2,dy1+dy2,dx1+dx2+dx3,dy1+dy2+dy3);
1760                 break;
1761         case HVCURVETO:
1762                 dy3 = pop();
1763                 dx3 = 0;
1764                 dy2 = pop();
1765                 dx2 = pop();
1766                 dy1 = 0;
1767                 dx1 = pop();
1768                 rcurveto(dx1,dy1,dx1+dx2,dy1+dy2,dx1+dx2+dx3,dy1+dy2+dy3);
1769                 break;
1770         case DOTSECTION:
1771                 break;
1772         case VSTEM3:
1773                 /*printf("vstem3\n");*/
1774                 pop();
1775                 pop();
1776                 pop();
1777                 pop();
1778                 pop();
1779                 pop();
1780                 break;
1781         case HSTEM3:
1782                 /*printf("hstem3\n");*/
1783                 pop();
1784                 pop();
1785                 pop();
1786                 pop();
1787                 pop();
1788                 pop();
1789                 break;
1790         case SEAC:
1791                 if (0) {
1792                         printf("seac: %3d %3d %3d %3d %3d\n", pop(), pop(), pop(), pop(), pop());
1793                 } else{
1794                         c2 = STDtoISO(pop());   /* accent */
1795                         c1 = STDtoISO(pop());   /* letter */
1796
1797                         cd = getchardesc(fnt, c1);
1798                         if (cd) {
1799                                 memcpy(chardata, cd->data, cd->datalen);
1800                                 nshorts = cd->datalen / sizeof(short);
1801                         }
1802
1803                         cd = getchardesc(fnt, c2);
1804                         if (cd && cd->data && cd->datalen) {
1805                                 ndata = cd->data;
1806
1807                                 if (nshorts) {
1808                                         if (savesplines) {
1809                                                 switch (chardata[nshorts - 1]){
1810                                                 case SP_RET:
1811                                                         nshorts--;
1812                                                         break;
1813                                                 case SP_RETCLOSEPATH:
1814                                                         chardata[nshorts - 1] = SP_CLOSEPATH;
1815                                                         break;
1816                                                 }
1817                                         } else {
1818                                                 switch (chardata[nshorts - 1]){
1819                                                 case PO_RET:
1820                                                         printf("PO_RET in character disription ?\n");
1821                                                         nshorts--;
1822                                                         break;
1823                                                 case PO_RETENDLOOP:
1824                                                         if (ndata[0] == PO_BGNLOOP) {
1825                                                                 chardata[nshorts - 1] = PO_ENDBGNLOOP;
1826                                                         } else {
1827                                                                 printf("new character doesn't start with PO_BGNLOOP ?\n");
1828                                                         }
1829                                                         break;
1830                                                 }
1831                                         }
1832                                 }
1833
1834                                 /* i.p.v. the sidebearing[c1] moet misschen thesidebearing gebruikt worden */
1835
1836                                 dy1 = pop();
1837                                 dx1 = pop() + sidebearing[c1] - sidebearing[c2];
1838                                 pop();
1839
1840                                 fdx1 = dx1; 
1841                                 fdy1 = dy1;
1842                                 applymat(mat, &fdx1, &fdy1);
1843                                 dx1 = floor(fdx1); 
1844                                 dy1 = floor(fdy1);
1845
1846                                 if (savesplines) {
1847                                         append_spline_offset(dx1, dy1, ndata);
1848                                 } else{
1849                                         append_poly_offset(dx1, dy1, ndata);
1850                                 }
1851
1852                                 /*printf("first: %d %d\n", cd->data[0], cd->data[1]);*/
1853                         }
1854                         fflush(stdout);
1855                 }
1856                 break;
1857         case SBW:
1858                 w = pop();
1859                 y = pop();
1860                 fprintf(stderr,"sbw: width: %d %d\n",w,y);
1861                 y = pop();
1862                 x = pop();
1863                 fprintf(stderr,"sbw: side: %d %d\n",x,y);
1864                 setwidth(w, x);
1865                 sbpoint(x,y);
1866                 break;
1867         case DIV:
1868                 x = pop();
1869                 y = pop();
1870                 push(x/y);
1871                 break;
1872         case CALLOTHERSUBR:
1873                 sub = pop();
1874                 n = pop();
1875                 if(sub == 0)
1876                         subr0();
1877                 else if(sub == 1)
1878                         subr1();
1879                 else if(sub == 2)
1880                         subr2();
1881                 else {
1882                         for(i=0; i<n; i++) {
1883                                 retpush(pop());
1884                         }
1885                 }
1886                 break;
1887         case POP:
1888                 push(retpop());
1889                 break;
1890         case SETCURRENTPOINT:
1891                 y = pop();
1892                 x = pop();
1893                 sbpoint(x,y);
1894                 break;
1895         default:
1896                 /*fprintf(stderr,"\nYUCK bad instruction %d\n",cmd);*/
1897                 break;
1898         }
1899         if(pc == 0 || cmd == ENDCHAR || cmd == WHAT0 || cmd == SEAC)
1900                 return 0;
1901         else
1902                 return 1;
1903 }
1904
1905
1906 /*
1907  *      Character interpreter
1908  *
1909  */
1910
1911 static void runprog(void)
1912 {
1913         int v, w, num, cmd;
1914
1915         while(1) {
1916                 v  = *pc++;
1917                 if(v>=0 && v<=31) {
1918                         if(v == 12) {
1919                                 w  = *pc++;
1920                                 cmd = 256+w;
1921                         } else 
1922                                 cmd = v;
1923                         if(!docommand(cmd)) {
1924                                 return;
1925                         }
1926                 } else if(v>=32 && v<=246) {
1927                         num = v-139;
1928                         push(num);
1929                 } else if(v>=247 && v<=250) {
1930                         w  = *pc++;
1931                         num = (v-247)*256+w+108;
1932                         push(num);
1933                 } else if(v>=251 && v<=254) {
1934                         w  = *pc++;
1935                         num = -(v-251)*256-w-108;
1936                         push(num);
1937                 } else if(v == 255) {
1938                         num  = *pc++;
1939                         num <<= 8;
1940                         num |= *pc++;
1941                         num <<= 8;
1942                         num |= *pc++;
1943                         num <<= 8;
1944                         num |= *pc++;
1945                         push(num);
1946                 }
1947         }
1948 }
1949
1950 /***/
1951
1952 static VFontData *objfnt_to_vfontdata(objfnt *fnt)
1953 {
1954         VFontData *vfd;
1955         chardesc *cd;
1956         short *_data, *data;
1957         int a, i, count, stop, ready, meet;
1958         short first[2], last[2];
1959         struct Nurb *nu;
1960         struct BezTriple *bezt, *bez2;
1961         float scale, dx, dy;
1962
1963         if (!fnt || (fnt->type!=SP_TYPE)) {
1964                 return NULL;
1965         }
1966
1967         vfd= MEM_callocN(sizeof(*vfd), "VFontData");
1968         scale = 10.0/(float)fnt->scale; /* na IRIX 6.2, schaal klopte niet meer */
1969
1970         for (i = 0; i < MAX_VF_CHARS; i++) {
1971                 cd = getchardesc(fnt, i);
1972                 if (cd && cd->data && cd->datalen) {
1973                         vfd->width[i] = scale * cd->movex;
1974
1975                         _data = data = cd->data;
1976
1977                         do{
1978                                 /* eerst even tellen */
1979                                 _data = data;
1980                                 count = 0;
1981                                 ready = stop = 0;
1982
1983                                 do{
1984                                         switch(*data++){
1985                                         case SP_MOVETO:
1986                                                 first[0] = data[0];
1987                                                 first[1] = data[1];
1988                                         case SP_LINETO:
1989                                                 count++;
1990                                                 last[0] = data[0];
1991                                                 last[1] = data[1];
1992                                                 data += 2;
1993                                                 break;
1994                                         case SP_CURVETO:
1995                                                 count++;
1996                                                 last[0] = data[4];
1997                                                 last[1] = data[5];
1998                                                 data += 6;
1999                                                 break;
2000                                         case SP_RET:
2001                                         case SP_RETCLOSEPATH:
2002                                                 stop = 1;
2003                                                 ready = 1;
2004                                                 break;
2005                                         case SP_CLOSEPATH:
2006                                                 stop = 1;
2007                                                 break;
2008                                         }
2009                                 } while (!stop);
2010
2011                                 if ((count>0) && last[0] == first[0] && last[1] == first[1]) meet = 1;
2012                                 else meet = 0;
2013
2014                                 /* is er meer dan 1 uniek punt ?*/
2015
2016                                 if (count - meet > 0) {
2017                                         data = _data;
2018                                         nu  =  (Nurb*)MEM_callocN(sizeof(struct Nurb),"objfnt_nurb");
2019                                         bezt = (BezTriple*)MEM_callocN((count)* sizeof(BezTriple),"objfnt_bezt") ;
2020                                         if (nu != 0 && bezt != 0) {
2021                                                 BLI_addtail(&vfd->nurbsbase[i], nu);
2022                                                 nu->type= CU_BEZIER+CU_2D;
2023                                                 nu->pntsu = count;
2024                                                 nu->resolu= 8;
2025                                                 nu->flagu= 1;
2026                                                 nu->bezt = bezt;
2027                                                 stop = 0;
2028
2029                                                 /* punten inlezen */
2030                                                 do {
2031                                                         switch(*data++){
2032                                                         case SP_MOVETO:
2033                                                                 bezt->vec[1][0] = scale * *data++;
2034                                                                 bezt->vec[1][1] = scale * *data++;
2035                                                                 
2036                                                                 break;
2037                                                         case SP_LINETO:
2038                                                                 bez2 = bezt++;
2039                                                                 bezt->vec[1][0] = scale * *data++;
2040                                                                 bezt->vec[1][1] = scale * *data++;
2041                                                                 /* vector handles */
2042                                                                 bezt->h1= HD_VECT;
2043                                                                 bez2->h2= HD_VECT;
2044                                                                 dx = (bezt->vec[1][0] - bez2->vec[1][0]) / 3.0;
2045                                                                 dy = (bezt->vec[1][1] - bez2->vec[1][1]) / 3.0;
2046                                                                 bezt->vec[0][0] = bezt->vec[1][0] - dx;
2047                                                                 bezt->vec[0][1] = bezt->vec[1][1] - dy;
2048                                                                 bez2->vec[2][0] = bez2->vec[1][0] + dx;
2049                                                                 bez2->vec[2][1] = bez2->vec[1][1] + dy;
2050                                                                 break;
2051                                                                 
2052                                                         case SP_CURVETO:
2053                                                                 bezt->vec[2][0] = scale * *data++;
2054                                                                 bezt->vec[2][1] = scale * *data++;
2055                                                                 bezt->h2= HD_ALIGN;
2056                                                                 bezt++;
2057                                                                 bezt->vec[0][0] = scale * *data++;
2058                                                                 bezt->vec[0][1] = scale * *data++;
2059                                                                 bezt->vec[1][0] = scale * *data++;
2060                                                                 bezt->vec[1][1] = scale * *data++;
2061                                                                 bezt->h1= HD_ALIGN;
2062                                                                 break;
2063                                                                 
2064                                                         case SP_RET:
2065                                                         case SP_RETCLOSEPATH:
2066                                                                 stop = 1;
2067                                                                 ready = 1;
2068                                                                 break;
2069                                                         case SP_CLOSEPATH:
2070                                                                 stop = 1;
2071                                                                 break;
2072                                                         }
2073                                                 } while (stop == 0);
2074
2075                                                 if (meet) {
2076                                                         /* kopieer handles */
2077                                                         nu->bezt->vec[0][0] = bezt->vec[0][0];
2078                                                         nu->bezt->vec[0][1] = bezt->vec[0][1];
2079                                                         /* en vergeet laatste punt */
2080                                                         nu->pntsu--;
2081                                                 }
2082                                                 else {
2083                                                         /* vector handles */
2084                                                         bez2 = nu->bezt;
2085                                                         dx = (bezt->vec[1][0] - bez2->vec[1][0]) / 3.0;
2086                                                         dy = (bezt->vec[1][1] - bez2->vec[1][1]) / 3.0;
2087                                                         bezt->vec[2][0] = bezt->vec[1][0] - dx;
2088                                                         bezt->vec[2][1] = bezt->vec[1][1] - dy;
2089                                                         bez2->vec[0][0] = bez2->vec[1][0] + dx;
2090                                                         bez2->vec[0][1] = bez2->vec[1][1] + dy;
2091                                                         bezt->h2= bez2->h1= HD_VECT;
2092                                                 }
2093                                                 
2094                                                 /* verboden handle combinaties */
2095                                                 a= nu->pntsu;
2096                                                 bezt= nu->bezt;
2097                                                 while(a--) {
2098                                                         if(bezt->h1!=HD_ALIGN && bezt->h2==HD_ALIGN) bezt->h2= 0;
2099                                                         else if(bezt->h2!=HD_ALIGN && bezt->h1==HD_ALIGN) bezt->h1= 0;
2100                                                         bezt++;
2101                                                 }
2102                                                 
2103                                         }
2104                                         else {
2105                                                 if (nu) MEM_freeN(nu);
2106                                                 if (bezt) MEM_freeN(bezt);
2107                                         }
2108                                 }
2109                                 _data = data;
2110                         } while (ready == 0);
2111                 }
2112         }
2113
2114         return vfd;
2115 }
2116
2117 VFontData *BLI_vfontdata_from_psfont(PackedFile *pf)
2118 {
2119         objfnt *fnt= objfnt_from_psfont(pf);
2120         VFontData *vfd= NULL;
2121         
2122         if (fnt) {
2123                 vfd= objfnt_to_vfontdata(fnt);
2124                 freeobjfnt(fnt);
2125         }
2126         
2127         return vfd;
2128 }