4 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * The Original Code is: all of this file.
25 * Contributor(s): none yet.
27 * ***** END GPL LICENSE BLOCK *****
28 * fromtype1 - Convert an Adobe type 1 font into .of or .sf format.
29 * Paul Haeberli - 1990
38 #include "MEM_guardedalloc.h"
40 #include "BLI_vfontdata.h"
41 #include "BLI_blenlib.h"
43 #include "DNA_packedFile_types.h"
44 #include "DNA_curve_types.h"
46 #include "BLO_sys_types.h" // for intptr_t support
54 typedef struct chardesc {
55 short movex, movey; /* advance */
56 short llx, lly; /* bounding box */
58 short *data; /* char data */
62 typedef struct objfnt {
63 struct objfnt *freeaddr; /* if freeaddr != 0, objfnt is one chunck */
65 short charmin, charmax;
71 #define OFMAGIC 0x93339333
77 /* ops for tmesh characters */
79 #define TM_BGNTMESH (1)
80 #define TM_SWAPTMESH (2)
81 #define TM_ENDBGNTMESH (3)
82 #define TM_RETENDTMESH (4)
85 /* ops for poly characters */
87 #define PO_BGNLOOP (1)
88 #define PO_ENDBGNLOOP (2)
89 #define PO_RETENDLOOP (3)
92 /* ops for spline characters */
96 #define SP_CURVETO (3)
97 #define SP_CLOSEPATH (4)
98 #define SP_RETCLOSEPATH (5)
102 #define MIN_ASCII ' '
103 #define MAX_ASCII '~'
104 #define NASCII (256 - 32)
106 #define NOBBOX (30000)
108 typedef struct pschar {
121 #define MAXSUBRS 4000
122 #define MAXCHARS 4000
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);
173 /* some local vars */
174 static int startx, starty;
175 static int curx, cury;
176 static int nextx, nexty;
177 static int delx, dely;
181 /* postscript commands */
188 #define RRCURVETO (8)
189 #define CLOSEPATH (9)
190 #define CALLSUBR (10)
196 #define VHCURVETO (30)
197 #define HVCURVETO (31)
198 #define DOTSECTION (256+0)
199 #define VSTEM3 (256+1)
200 #define HSTEM3 (256+2)
204 #define CALLOTHERSUBR (256+16)
206 #define SETCURRENTPOINT (256+33)
209 static char oneline[LINELEN];
212 static unsigned short int mr;
217 static short chardata[20000];
220 static int thecharwidth, thesidebearing;
221 static int npnts, nloops;
227 static float beztol = 100.0;
229 /* extern: from libfm */
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;
238 static short sidebearing[MAXCHARS];
239 static char tok[LINELEN];
240 static int sp_npnts, sp_nloops;
243 * interpreter globals
247 static float mat[2][2];
248 static char *pcstack[100];
252 static int coordsave[7][2];
254 static int retstack[1000];
256 static int stack[1000];
258 static int savesplines = 1;
260 static pschar ISOcharlist[NASCII] = {
263 {"/quotedbl", 042, 0},
264 {"/numbersign", 043, 0},
266 {"/percent", 045, 0},
267 {"/ampersand", 046, 0},
268 {"/quoteright", 047, 0},
270 {"/parenleft", 050, 0},
271 {"/parenright", 051, 0},
272 {"/asterisk", 052, 0},
291 {"/semicolon", 073, 0},
294 {"/greater", 076, 0},
295 {"/question", 077, 0},
327 {"/bracketleft", 0133, 0},
328 {"/backslash", 0134, 0},
329 {"/bracketright", 0135, 0},
330 {"/asciicircum", 0136, 0},
331 {"/underscore", 0137, 0},
333 {"/quoteleft", 0140, 0},
363 {"/braceleft", 0173, 0},
365 {"/braceright", 0175, 0},
366 {"/asciitilde", 0176, 0},
370 /* nonstandard defs */
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},
381 {"/daggerdbl", 0210, 0},
382 {"/trademark", 0211, 0},
383 {"/bullet", 0212, 0},
384 {"/perthousand", 0213, 0},
385 {"/Lslash", 0214, 0},
387 {"/lslash", 0216, 0},
390 /* endnonstandard defs */
392 {"/dotlessi", 0220, 0},
395 {"/circumflex", 0223, 0},
399 {"/dotaccent", 0227, 0},
406 {"/hungarumlaut", 0235, 0},
407 {"/ogonek", 0236, 0},
411 {"/exclamdown", 0241, 0},
413 {"/sterling", 0243, 0},
414 {"/florin", 0244, 0},
416 {"/brokenbar", 0246, 0},
417 {"/section", 0247, 0},
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},
428 {"/degree", 0260, 0},
429 {"/plusminus", 0261, 0},
430 {"/twosuperior", 0262, 0},
431 {"/threesuperior", 0263, 0},
434 {"/paragraph", 0266, 0},
435 {"/periodcentered", 0267, 0},
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},
446 {"/Agrave", 0300, 0},
447 {"/Aacute", 0301, 0},
448 {"/Acircumflex", 0302, 0},
449 {"/Atilde", 0303, 0},
450 {"/Adieresis", 0304, 0},
453 {"/Ccedilla", 0307, 0},
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},
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},
473 {"/Oslash", 0330, 0},
474 {"/Ugrave", 0331, 0},
475 {"/Uacute", 0332, 0},
476 {"/Ucircumflex",0333, 0},
477 {"/Udieresis", 0334, 0},
478 {"/Yacute", 0335, 0},
480 {"/germandbls", 0337, 0},
482 {"/agrave", 0340, 0},
483 {"/aacute", 0341, 0},
484 {"/acircumflex",0342, 0},
485 {"/atilde", 0343, 0},
486 {"/adieresis", 0344, 0},
489 {"/ccedilla", 0347, 0},
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},
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},
509 {"/oslash", 0370, 0},
510 {"/ugrave", 0371, 0},
511 {"/uacute", 0372, 0},
512 {"/ucircumflex",0373, 0},
513 {"/udieresis", 0374, 0},
514 {"/yacute", 0375, 0},
516 {"/ydieresis", 0377, 0},
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 */
547 /* from objfont.c, rest is in lfm_s !!*/
551 static int chartoindex(objfnt *fnt, int c)
557 return c-fnt->charmin;
561 static chardesc *getchardesc(objfnt *fnt, int c)
565 index = chartoindex(fnt,c);
568 return fnt->my_chars+index;
571 static objfnt *newobjfnt(int type, int charmin, int charmax, int fscale)
575 fnt = (objfnt *)MEM_mallocN(sizeof(objfnt), "newobjfnt");
578 fnt->charmin = charmin;
579 fnt->charmax = charmax;
580 fnt->my_nchars = fnt->charmax-fnt->charmin+1;
582 fnt->my_chars = (chardesc *)MEM_mallocN(fnt->my_nchars*sizeof(chardesc), "newobjfnt2");
583 memset(fnt->my_chars, 0, fnt->my_nchars*sizeof(chardesc));
588 static void addchardata (objfnt * fnt, int c, short * data, int nshorts)
593 index = chartoindex(fnt,c);
595 fprintf(stderr,"Addchardata bad poop\n");
598 cd = fnt->my_chars+index;
600 cd->datalen = nshorts*sizeof(short);
601 cd->data = (short *)MEM_mallocN(cd->datalen, "addchardata");
602 memcpy(cd->data, data, cd->datalen);
605 static void addcharmetrics(objfnt *fnt, int c, int movex, int movey)
610 index = chartoindex(fnt,c);
612 fprintf(stderr,"Addcharmetrics bad poop\n");
615 cd = fnt->my_chars+index;
621 static void fakechar(objfnt *fnt, int c, int width)
625 chardata[0] = PO_RET;
626 addchardata(fnt,c,chardata,1);
627 addcharmetrics(fnt,c,width,0);
631 static void freeobjfnt(objfnt * fnt)
637 for(i=0; i<fnt->my_nchars; i++) {
642 MEM_freeN(fnt->my_chars);
649 static short STDtoISO(short c)
651 short i = (sizeof(STDvsISO) / (2 * sizeof(short))) - 1;
654 if (STDvsISO[i][0] == c) return (STDvsISO[i][1]);
661 * read the font matrix out of the font file
665 static char * newfgets(char * s, int n, PackedFile * pf){
671 c = ((char *) pf->data)[pf->seek];
673 if (pf->seek > pf->size){
676 if (c == 10 || c == 13){
687 static int readfontmatrix(PackedFile * pf, float mat[2][2])
690 float a, b, c, d, e, f;
694 /* look for the FontMatrix def */
696 if(!newfgets(oneline, LINELEN, pf)) {
697 fprintf(stderr,"fromtype1: no FontMatrix found\n");
700 cptr = strchr(oneline,'/');
702 if(strncmp(cptr,"/FontMatrix",11) == 0) {
703 cptr = strchr(cptr,'[');
705 fprintf(stderr,"fromtype1: bad FontMatrix line\n");
708 sscanf(cptr+1,"%f %f %f %f %f %f\n",&a,&b,&c,&d,&e,&f);
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;
727 static void resetdecrypt(int n)
735 * decryption subroutines
739 static char mdecrypt(char cipher)
743 plain = (cipher^(mr>>8));
744 mr = (cipher+mr)*MC1 + MC2;
748 static void decryptdata(char * cptr, int n)
751 *cptr = mdecrypt(*cptr);
756 static int decryptprogram(char *buf, int len)
761 for(i=0; i<len; i++) {
766 buf[i-SKIP] = mdecrypt(buf[i]);
772 static void decryptall(void)
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]);
784 * decode the eexec part of the file
788 static int decodetype1(PackedFile * pf, char *outname)
791 int i, totlen, hexbytes, c;
797 for(i=0; i<256; i++) {
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';
811 /* allocate buffers */
813 hexdat = (char *)MEM_mallocN(totlen, "hexdat");
814 bindat = (char *)MEM_mallocN(totlen, "bindat");
816 /* look for eexec part of file */
818 if(!newfgets(oneline, LINELEN, pf)) {
819 fprintf(stderr,"fromtype1: no currentfile eexec found\n");
823 if(strcmp(oneline,"currentfile eexe") == 0)
827 /* initialize decryption variables */
830 /* first byte == 0 for binary data (???) */
832 c = ((char *) pf->data)[pf->seek];
834 if (hextab[c] != NOTHEX){
835 /* read all the hex bytes into the hex buffer */
837 while(newfgets(oneline, LINELEN, pf)) {
838 hptr = (char *)oneline;
840 if(hextab[*hptr] != NOTHEX)
841 hexdat[hexbytes++] = *hptr;
846 /* check number of hex bytes */
849 datbytes = hexbytes/2;
851 /* translate hex data to binary */
856 *bptr++ = (hextab[hptr[0]]<<4)+hextab[hptr[1]];
860 /* decrypt the data */
861 decryptdata(bindat,datbytes);
864 datbytes = pf->size - pf->seek;
865 memcpy(bindat, ((char *) pf->data) + pf->seek, datbytes);
867 if ((bindat[2] << (8 + bindat[3])) == 0x800){
868 /* order data (remove 6 bytes headers) */
870 hptr = bptr = bindat + 4;
874 if (i > 2046) c = 2046;
877 memcpy(bptr, hptr, c);
884 /* decrypt the data */
885 decryptdata(bindat+4,datbytes);
887 decryptdata(bindat+6,datbytes-6);
892 outf = fopen(outname,"wb");
893 fwrite(bindat,datbytes,1,outf);
903 * fake file reading funcs
908 static void fakefopen(void)
915 static void fakegettoken(char *str)
921 start = (char *) str;
922 cptr = bindat+fakepos;
930 while (fakepos<fakemax && !isspace(c)) {
939 if(fakepos>fakemax) {
940 fprintf(stderr,"fromtype1: unexpected eof\n");
941 strcpy(start, "end");
945 static int fakefgets(char *buf,int max)
949 cptr = (char *)(bindat+fakepos);
953 if(*cptr == 10 || *cptr == 13)
962 static char *fakefread(int n)
965 return bindat+fakepos-n;
968 static void applymat(float mat[][2], float *x, float *y)
972 tx = ((*x)*mat[0][0])+((*y)*mat[0][1]);
973 ty = ((*x)*mat[1][0])+((*y)*mat[1][1]);
978 static void setcharlist(void)
980 char *name; /*found;*/
983 for(i=0; i<NASCII; i++) ISOcharlist[i].prog = -1;
985 for(j=0; j<my_nchars; j++) {
986 name = my_charname[j];
989 for(i=0; i<NASCII; i++) {
990 if(ISOcharlist[i].name && (strcmp(name,ISOcharlist[i].name) == 0)){
991 ISOcharlist[i].prog = j;
995 /*if (found == 0) printf("no match found for: %s\n", name);*/
1003 static objfnt * objfnt_from_psfont(PackedFile * pf)
1012 /* read the font matrix from the font */
1013 if (readfontmatrix(pf,mat)) return(0);
1015 /* decode the font data */
1016 decodetype1(pf, "/usr/tmp/type1.dec");
1018 /* open the input file */
1021 /* look for the /Subrs def and get my_nsubrs */
1023 if(!fakefgets(oneline,LINELEN)) {
1024 fprintf(stderr,"fromtype1: no /Subrs found\n");
1029 cptr = strchr(oneline,'/');
1031 if(strncmp(cptr,"/Subrs",6) == 0) {
1032 my_nsubrs = atoi(cptr+6);
1038 /* read the Subrs in one by one */
1039 for(i=0; i<my_nsubrs; i++)
1041 for(i=0; i<my_nsubrs; i++) {
1042 for(k=0; k<MAXTRIES; k++) {
1044 if(strcmp(tok,"dup") == 0)
1048 fprintf(stderr,"dup for subr %d not found in range\n", i);
1052 /* get the Subr index here */
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);
1062 /* get the number of bytes to read */
1067 /* read in the subroutine */
1068 my_sublen[index] = nread;
1069 my_subrs[index] = fakefread(nread);
1073 /* look for the CharStrings */
1076 cptr = strchr(tok,'/');
1077 if(cptr && strcmp(cptr,"/CharStrings") == 0)
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 */
1087 /* read the CharStrings one by one */
1089 for(i=0; i<MAXCHARS; i++) {
1093 if(strcmp(tok,"end") == 0)
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);
1101 /* get the number of bytes to read */
1106 /* read in the char description */
1107 my_charlen[i] = nread;
1108 my_chars[i] = fakefread(nread);
1110 /* skip the end of line */
1116 /* decrypt the character descriptions */
1120 /* make the obj font */
1121 makeobjfont(savesplines);
1123 if (bindat) MEM_freeN(bindat);
1124 /* system("rm /usr/tmp/type1.dec"); */
1137 static void initpcstack(void)
1142 static void pushpc(char *pc)
1148 static char *poppc(void)
1152 fprintf(stderr,"\nYUCK: pc stack under flow\n");
1156 return pcstack[pcsp];
1160 * Data stack support
1164 static void initstack(void)
1169 static void push(int val)
1176 static int pop(void)
1180 fprintf(stderr,"\nYUCK: stack under flow\n");
1188 * call/return data stack
1192 static void initretstack(void)
1197 static void retpush(int val)
1200 retstack[retsp] = val;
1204 static int retpop(void)
1208 fprintf(stderr,"\nYUCK: ret stack under flow\n");
1212 return retstack[retsp];
1217 * execute the program:
1222 static void getmove(int *x, int *y)
1226 /* printf("ingetmove\n"); */
1229 static void getpos(int *x, int *y)
1235 static void subr1(void)
1241 static void subr2(void)
1247 fprintf(stderr,"subr2: bad poop\n");
1250 coordsave[coordpos][0] = x;
1251 coordsave[coordpos][1] = y;
1255 static void subr0(void)
1263 pop(); /* xpos, unused */
1264 pop(); /* ypos, unused */
1267 fprintf(stderr,"subr0: bad poop\n");
1270 x0 = coordsave[0][0];
1271 y0 = coordsave[0][1];
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);
1293 static void append_poly_offset(short ofsx, short ofsy, short * data)
1297 if (data == 0) return;
1300 switch(chardata[nshorts++] = *data++) {
1302 nshorts --; /* for the first time */
1308 nverts = chardata[nshorts++] = *data++;
1310 chardata[nshorts++] = (*data++) + ofsx;
1311 chardata[nshorts++] = (*data++) + ofsy;
1317 static void append_spline_offset(short ofsx, short ofsy, short * data)
1321 if (data == 0) return;
1324 switch(chardata[nshorts++] = *data++) {
1332 case SP_RETCLOSEPATH:
1337 for (; nverts > 0; nverts--) {
1338 chardata[nshorts++] = (*data++) + ofsx;
1339 chardata[nshorts++] = (*data++) + ofsy;
1353 /* poly output stuff */
1355 static void setwidth(int w, int x)
1361 static void poly_beginchar(void)
1367 static void poly_endchar(void)
1370 chardata[nshorts++] = PO_RET;
1372 chardata[nshorts++] = PO_RETENDLOOP;
1375 static void poly_close(void)
1377 chardata[nvertpos] = npnts;
1381 static void poly_pnt(float x, float y)
1385 applymat(mat,&x,&y);
1390 chardata[nshorts++] = PO_BGNLOOP;
1391 nvertpos = nshorts++;
1393 chardata[nshorts++] = PO_ENDBGNLOOP;
1394 nvertpos = nshorts++;
1398 chardata[nshorts++] = ix;
1399 chardata[nshorts++] = iy;
1404 /* spline output stuff */
1406 static void spline_beginchar(void)
1412 static void spline_endchar(void)
1415 chardata[nshorts++] = SP_RET;
1417 chardata[nshorts++] = SP_RETCLOSEPATH;
1420 static void spline_close(void)
1422 chardata[nshorts++] = SP_CLOSEPATH;
1427 static void spline_line(float x0, float y0, float x1, float y1)
1429 applymat(mat,&x0,&y0);
1430 applymat(mat,&x1,&y1);
1433 chardata[nshorts++] = SP_MOVETO;
1434 chardata[nshorts++] = floor(x0);
1435 chardata[nshorts++] = floor(y0);
1439 chardata[nshorts++] = SP_LINETO;
1440 chardata[nshorts++] = floor(x1);
1441 chardata[nshorts++] = floor(y1);
1445 static void spline_curveto(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
1447 applymat(mat,&x0,&y0);
1449 applymat(mat,&x1,&y1);
1450 applymat(mat,&x2,&y2);
1451 applymat(mat,&x3,&y3);
1453 chardata[nshorts++] = SP_MOVETO;
1454 chardata[nshorts++] = floor(x0);
1455 chardata[nshorts++] = floor(y0);
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);
1468 static void savestart(int x, int y)
1475 static void sbpoint( int x, int y)
1481 static void rmoveto( int x, int y)
1489 savestart(curx,cury);
1493 static void drawline(float x0, float y0, float x1, float y1, float dx0, float dy0, float dx1, float dy1)
1495 if(x0!=x1 || y0!=y1)
1500 static void rlineto( int x, int y)
1508 if (savesplines) spline_line( curx, cury, nextx, nexty);
1509 else drawline( curx, cury, nextx, nexty,dx,dy,dx,dy);
1514 static void closepath(void)
1524 drawline( curx, cury, startx, starty,dx,dy,dx,dy);
1531 static void bezadapt( float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float beztol)
1533 float ax0,ay0,ax1,ay1,ax2,ay2,ax3,ay3;
1534 float bx0,by0,bx1,by1,bx2,by2,bx3,by3;
1536 float linx, liny, dx, dy, mag;
1538 midx = (x0+3*x1+3*x2+x3)/8.0;
1539 midy = (y0+3*y1+3*y2+y3)/8.0;
1545 if(mag<(beztol*beztol))
1546 drawline(x0,y0,x3,y3,x1-x0,y1-y0,x3-x2,y3-y2);
1552 ax2 = (x0+2*x1+x2)/4;
1553 ay2 = (y0+2*y1+y2)/4;
1556 bezadapt(ax0,ay0,ax1,ay1,ax2,ay2,ax3,ay3,beztol);
1560 bx1 = (x1+2*x2+x3)/4;
1561 by1 = (y1+2*y2+y3)/4;
1566 bezadapt(bx0,by0,bx1,by1,bx2,by2,bx3,by3,beztol);
1570 static void drawbez( float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
1572 bezadapt(x0,y0,x1,y1,x2,y2,x3,y3,beztol);
1576 static void rcurveto( int dx1, int dy1, int dx2, int dy2, int dx3, int dy3)
1593 spline_curveto( x0, y0, x1, y1, x2, y2, x3, y3);
1595 drawbez( x0, y0, x1, y1, x2, y2, x3, y3);
1603 * save an object font.
1607 /* generic routines */
1609 static void makeobjfont(int savesplines)
1614 fnt = newobjfnt(SP_TYPE, 32, 32+NASCII-1, 9840);
1616 fnt = newobjfnt(PO_TYPE, 32, 32+NASCII-1, 9840);
1618 for(i=0; i<NASCII; i++) {
1620 if(ISOcharlist[i].prog>=0) {
1621 /*printf("decoding %s\n", ISOcharlist[i].name);*/
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);
1636 * run the character program
1641 static void drawchar(int c)
1660 static int docommand(int cmd)
1662 int x, y, w, c1, c2;
1674 fprintf(stderr,"\nYUCK: WHAT0\n");
1679 /*printf("hstem: %d %d\n", pop(), pop());*/
1684 /*printf("vstem: %d %d\n", pop(), pop());*/
1710 rcurveto(dx1,dy1,dx1+dx2,dy1+dy2,dx1+dx2+dx3,dy1+dy2+dy3);
1717 subpc = my_subrs[sub];
1719 fprintf(stderr,"\nYUCK no sub addr\n");
1752 rcurveto(dx1,dy1,dx1+dx2,dy1+dy2,dx1+dx2+dx3,dy1+dy2+dy3);
1761 rcurveto(dx1,dy1,dx1+dx2,dy1+dy2,dx1+dx2+dx3,dy1+dy2+dy3);
1766 /*printf("vstem3\n");*/
1775 /*printf("hstem3\n");*/
1785 printf("seac: %3d %3d %3d %3d %3d\n", pop(), pop(), pop(), pop(), pop());
1787 c2 = STDtoISO(pop()); /* accent */
1788 c1 = STDtoISO(pop()); /* letter */
1790 cd = getchardesc(fnt, c1);
1792 memcpy(chardata, cd->data, cd->datalen);
1793 nshorts = cd->datalen / sizeof(short);
1796 cd = getchardesc(fnt, c2);
1797 if (cd && cd->data && cd->datalen) {
1802 switch (chardata[nshorts - 1]){
1806 case SP_RETCLOSEPATH:
1807 chardata[nshorts - 1] = SP_CLOSEPATH;
1811 switch (chardata[nshorts - 1]){
1813 printf("PO_RET in character disription ?\n");
1817 if (ndata[0] == PO_BGNLOOP) {
1818 chardata[nshorts - 1] = PO_ENDBGNLOOP;
1820 printf("new character doesn't start with PO_BGNLOOP ?\n");
1827 /* instead of the sidebearing[c1] maybe thesidebearing should be used */
1830 dx1 = pop() + sidebearing[c1] - sidebearing[c2];
1835 applymat(mat, &fdx1, &fdy1);
1840 append_spline_offset(dx1, dy1, ndata);
1842 append_poly_offset(dx1, dy1, ndata);
1845 /*printf("first: %d %d\n", cd->data[0], cd->data[1]);*/
1853 fprintf(stderr,"sbw: width: %d %d\n",w,y);
1856 fprintf(stderr,"sbw: side: %d %d\n",x,y);
1875 for(i=0; i<n; i++) {
1883 case SETCURRENTPOINT:
1889 /*fprintf(stderr,"\nYUCK bad instruction %d\n",cmd);*/
1892 if(pc == 0 || cmd == ENDCHAR || cmd == WHAT0 || cmd == SEAC)
1900 * Character interpreter
1904 static void runprog(void)
1916 if(!docommand(cmd)) {
1919 } else if(v>=32 && v<=246) {
1922 } else if(v>=247 && v<=250) {
1924 num = (v-247)*256+w+108;
1926 } else if(v>=251 && v<=254) {
1928 num = -(v-251)*256-w-108;
1930 } else if(v == 255) {
1945 static VFontData *objfnt_to_vfontdata(objfnt *fnt)
1949 short *_data, *data;
1950 int a, i, count, stop, ready, meet;
1951 short first[2]={0,0}, last[2]={0,0};
1953 struct BezTriple *bezt, *bez2;
1954 float scale, dx, dy;
1957 if (!fnt || (fnt->type!=SP_TYPE)) {
1961 vfd= MEM_callocN(sizeof(*vfd), "VFontData");
1962 scale = 10.0/(float)fnt->scale; /* after IRIX 6.2, scaling went wrong */
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);
1970 che->width = scale * cd->movex;
1972 _data = data = cd->data;
1998 case SP_RETCLOSEPATH:
2008 if ((count>0) && last[0] == first[0] && last[1] == first[1]) meet = 1;
2011 /* is there more than 1 unique point ?*/
2013 if (count - meet > 0) {
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;
2022 nu->flagu= CU_CYCLIC;
2030 bezt->vec[1][0] = scale * *data++;
2031 bezt->vec[1][1] = scale * *data++;
2036 bezt->vec[1][0] = scale * *data++;
2037 bezt->vec[1][1] = scale * *data++;
2038 /* vector handles */
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;
2050 bezt->vec[2][0] = scale * *data++;
2051 bezt->vec[2][1] = scale * *data++;
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++;
2062 case SP_RETCLOSEPATH:
2070 } while (stop == 0);
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 */
2080 /* vector handles */
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;
2091 /* forbidden handle combinations */
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;
2102 if (nu) MEM_freeN(nu);
2103 if (bezt) MEM_freeN(bezt);
2107 } while (ready == 0);
2114 VFontData *BLI_vfontdata_from_psfont(PackedFile *pf)
2116 objfnt *fnt= objfnt_from_psfont(pf);
2117 VFontData *vfd= NULL;
2120 vfd= objfnt_to_vfontdata(fnt);