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