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