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