2125 lines
40 KiB
C
2125 lines
40 KiB
C
/**
|
|
* $Id$
|
|
*
|
|
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version. The Blender
|
|
* Foundation also sells licenses for use in proprietary software under
|
|
* the Blender License. See http://www.blender.org/BL/ for information
|
|
* about this.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
* All rights reserved.
|
|
*
|
|
* The Original Code is: all of this file.
|
|
*
|
|
* Contributor(s): none yet.
|
|
*
|
|
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
|
* fromtype1 - Convert an Adobe type 1 font into .of or .sf format.
|
|
* Paul Haeberli - 1990
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
#include "BLI_vfontdata.h"
|
|
#include "BLI_blenlib.h"
|
|
|
|
#include "DNA_packedFile_types.h"
|
|
#include "DNA_curve_types.h"
|
|
|
|
/* ObjFnt types */
|
|
|
|
typedef struct chardesc {
|
|
short movex, movey; /* advance */
|
|
short llx, lly; /* bounding box */
|
|
short urx, ury;
|
|
short *data; /* char data */
|
|
long datalen;
|
|
} chardesc;
|
|
|
|
typedef struct objfnt {
|
|
struct objfnt *freeaddr; /* if freeaddr != 0, objfnt is one chunck */
|
|
short type;
|
|
short charmin, charmax;
|
|
short my_nchars;
|
|
short scale;
|
|
chardesc *my_chars;
|
|
} objfnt;
|
|
|
|
#define OFMAGIC 0x93339333
|
|
|
|
#define TM_TYPE 1
|
|
#define PO_TYPE 2
|
|
#define SP_TYPE 3
|
|
|
|
/* ops for tmesh characters */
|
|
|
|
#define TM_BGNTMESH (1)
|
|
#define TM_SWAPTMESH (2)
|
|
#define TM_ENDBGNTMESH (3)
|
|
#define TM_RETENDTMESH (4)
|
|
#define TM_RET (5)
|
|
|
|
/* ops for poly characters */
|
|
|
|
#define PO_BGNLOOP (1)
|
|
#define PO_ENDBGNLOOP (2)
|
|
#define PO_RETENDLOOP (3)
|
|
#define PO_RET (4)
|
|
|
|
/* ops for spline characters */
|
|
|
|
#define SP_MOVETO (1)
|
|
#define SP_LINETO (2)
|
|
#define SP_CURVETO (3)
|
|
#define SP_CLOSEPATH (4)
|
|
#define SP_RETCLOSEPATH (5)
|
|
#define SP_RET (6)
|
|
|
|
|
|
#define MIN_ASCII ' '
|
|
#define MAX_ASCII '~'
|
|
#define NASCII (256 - 32)
|
|
|
|
#define NOBBOX (30000)
|
|
|
|
typedef struct pschar {
|
|
char *name;
|
|
int code;
|
|
int prog;
|
|
} pschar;
|
|
|
|
/***/
|
|
|
|
#define SKIP 4
|
|
#define LINELEN 2048
|
|
#define NOTHEX (100)
|
|
#define MC1 52845
|
|
#define MC2 22719
|
|
#define MAXSUBRS 1000
|
|
#define MAXCHARS 1000
|
|
#define MAXTRIES 30
|
|
|
|
/* some local thingies */
|
|
static void rcurveto( int dx1, int dy1, int dx2, int dy2, int dx3, int dy3);
|
|
static void makeobjfont(int savesplines);
|
|
static void drawchar(int c);
|
|
static void runprog(void);
|
|
static int chartoindex(objfnt *fnt, int c);
|
|
static short STDtoISO(short c);
|
|
static char * newfgets(char * s, int n, PackedFile * pf);
|
|
static int readfontmatrix(PackedFile * pf, float mat[2][2]);
|
|
static char mdecrypt(char cipher);
|
|
static void decryptall(void);
|
|
static int decodetype1(PackedFile * pf, char *outname);
|
|
static void fakefopen(void);
|
|
static char *fakefread(int n);
|
|
static void setcharlist(void);
|
|
static void initpcstack(void);
|
|
static char *poppc(void);
|
|
static void initstack(void);
|
|
static void push(int val);
|
|
static int pop(void);
|
|
static void initretstack(void);
|
|
static void retpush(int val);
|
|
static int retpop(void);
|
|
static void subr1(void);
|
|
static void subr2(void);
|
|
static void subr0(void);
|
|
static void append_poly_offset(short ofsx, short ofsy, short * data);
|
|
static void append_spline_offset(short ofsx, short ofsy, short * data);
|
|
static void setwidth(int w, int x);
|
|
static void poly_beginchar(void);
|
|
static void poly_endchar(void);
|
|
static void poly_close(void);
|
|
static void poly_pnt(float x, float y);
|
|
static void spline_beginchar(void);
|
|
static void spline_endchar(void);
|
|
static void spline_close(void);
|
|
static void spline_line(float x0, float y0, float x1, float y1);
|
|
static void spline_curveto(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
|
|
static void savestart(int x, int y);
|
|
static void sbpoint( int x, int y);
|
|
static void rmoveto( int x, int y);
|
|
static void drawline(float x0, float y0, float x1, float y1, float dx0, float dy0, float dx1, float dy1);
|
|
static void rlineto( int x, int y);
|
|
static void closepath(void);
|
|
static void bezadapt( float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float beztol);
|
|
static void drawbez( float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
|
|
static int docommand(int cmd);
|
|
|
|
/* some local vars */
|
|
static int startx, starty;
|
|
static int curx, cury;
|
|
static int nextx, nexty;
|
|
static int delx, dely;
|
|
static int started;
|
|
|
|
|
|
/* postscript commands */
|
|
#define HSTEM (1)
|
|
#define VSTEM (3)
|
|
#define VMOVETO (4)
|
|
#define RLINETO (5)
|
|
#define HLINETO (6)
|
|
#define VLINETO (7)
|
|
#define RRCURVETO (8)
|
|
#define CLOSEPATH (9)
|
|
#define CALLSUBR (10)
|
|
#define RETURN (11)
|
|
#define HSBW (13)
|
|
#define ENDCHAR (14)
|
|
#define RMOVETO (21)
|
|
#define HMOVETO (22)
|
|
#define VHCURVETO (30)
|
|
#define HVCURVETO (31)
|
|
#define DOTSECTION (256+0)
|
|
#define VSTEM3 (256+1)
|
|
#define HSTEM3 (256+2)
|
|
#define SEAC (256+6)
|
|
#define SBW (256+7)
|
|
#define DIV (256+12)
|
|
#define CALLOTHERSUBR (256+16)
|
|
#define POP (256+17)
|
|
#define SETCURRENTPOINT (256+33)
|
|
#define WHAT0 (0)
|
|
|
|
/* some dirt for windows */
|
|
#ifdef WIN32
|
|
#include "BLI_winstuff.h"
|
|
#endif
|
|
|
|
static char oneline[LINELEN];
|
|
static objfnt *fnt;
|
|
|
|
static unsigned short int mr;
|
|
|
|
static char *bindat;
|
|
static int datbytes;
|
|
static int firsted;
|
|
static short chardata[2000];
|
|
static int nshorts;
|
|
|
|
static int thecharwidth, thesidebearing;
|
|
static int npnts, nloops;
|
|
static int nvertpos;
|
|
|
|
static int fakepos;
|
|
static int fakemax;
|
|
|
|
static float beztol = 100.0;
|
|
|
|
/* extern: uit de libfm */
|
|
|
|
static char *my_subrs[MAXSUBRS];
|
|
static unsigned int my_sublen[MAXSUBRS];
|
|
static char *my_chars[MAXCHARS];
|
|
static unsigned int my_charlen[MAXCHARS];
|
|
static char *my_charname[MAXCHARS];
|
|
static int my_nsubrs, my_nchars;
|
|
|
|
static short sidebearing[MAXCHARS];
|
|
static char tok[LINELEN];
|
|
static int sp_npnts, sp_nloops;
|
|
|
|
/*
|
|
* interpreter globals
|
|
*/
|
|
|
|
|
|
static float mat[2][2];
|
|
static char *pcstack[100];
|
|
static char *pc;
|
|
static int pcsp;
|
|
static int coordpos;
|
|
static int coordsave[7][2];
|
|
static int incusp;
|
|
static int retstack[1000];
|
|
static int retsp;
|
|
static int stack[1000];
|
|
static int sp;
|
|
static int savesplines = 1;
|
|
|
|
static pschar ISOcharlist[NASCII] = {
|
|
"/space", 040, 0,
|
|
"/exclam", 041, 0,
|
|
"/quotedbl", 042, 0,
|
|
"/numbersign", 043, 0,
|
|
"/dollar", 044, 0,
|
|
"/percent", 045, 0,
|
|
"/ampersand", 046, 0,
|
|
"/quoteright", 047, 0,
|
|
|
|
"/parenleft", 050, 0,
|
|
"/parenright", 051, 0,
|
|
"/asterisk", 052, 0,
|
|
"/plus", 053, 0,
|
|
"/comma", 054, 0,
|
|
"/hyphen", 055, 0,
|
|
"/period", 056, 0,
|
|
"/slash", 057, 0,
|
|
|
|
"/zero", 060, 0,
|
|
"/one", 061, 0,
|
|
"/two", 062, 0,
|
|
"/three", 063, 0,
|
|
"/four", 064, 0,
|
|
"/five", 065, 0,
|
|
"/six", 066, 0,
|
|
"/seven", 067, 0,
|
|
|
|
"/eight", 070, 0,
|
|
"/nine", 071, 0,
|
|
"/colon", 072, 0,
|
|
"/semicolon", 073, 0,
|
|
"/less", 074, 0,
|
|
"/equal", 075, 0,
|
|
"/greater", 076, 0,
|
|
"/question", 077, 0,
|
|
|
|
"/at", 0100, 0,
|
|
"/A", 0101, 0,
|
|
"/B", 0102, 0,
|
|
"/C", 0103, 0,
|
|
"/D", 0104, 0,
|
|
"/E", 0105, 0,
|
|
"/F", 0106, 0,
|
|
"/G", 0107, 0,
|
|
|
|
"/H", 0110, 0,
|
|
"/I", 0111, 0,
|
|
"/J", 0112, 0,
|
|
"/K", 0113, 0,
|
|
"/L", 0114, 0,
|
|
"/M", 0115, 0,
|
|
"/N", 0116, 0,
|
|
"/O", 0117, 0,
|
|
|
|
"/P", 0120, 0,
|
|
"/Q", 0121, 0,
|
|
"/R", 0122, 0,
|
|
"/S", 0123, 0,
|
|
"/T", 0124, 0,
|
|
"/U", 0125, 0,
|
|
"/V", 0126, 0,
|
|
"/W", 0127, 0,
|
|
|
|
"/X", 0130, 0,
|
|
"/Y", 0131, 0,
|
|
"/Z", 0132, 0,
|
|
"/bracketleft", 0133, 0,
|
|
"/backslash", 0134, 0,
|
|
"/bracketright", 0135, 0,
|
|
"/asciicircum", 0136, 0,
|
|
"/underscore", 0137, 0,
|
|
|
|
"/quoteleft", 0140, 0,
|
|
"/a", 0141, 0,
|
|
"/b", 0142, 0,
|
|
"/c", 0143, 0,
|
|
"/d", 0144, 0,
|
|
"/e", 0145, 0,
|
|
"/f", 0146, 0,
|
|
"/g", 0147, 0,
|
|
|
|
"/h", 0150, 0,
|
|
"/i", 0151, 0,
|
|
"/j", 0152, 0,
|
|
"/k", 0153, 0,
|
|
"/l", 0154, 0,
|
|
"/m", 0155, 0,
|
|
"/n", 0156, 0,
|
|
"/o", 0157, 0,
|
|
|
|
"/p", 0160, 0,
|
|
"/q", 0161, 0,
|
|
"/r", 0162, 0,
|
|
"/s", 0163, 0,
|
|
"/t", 0164, 0,
|
|
"/u", 0165, 0,
|
|
"/v", 0166, 0,
|
|
"/w", 0167, 0,
|
|
|
|
"/x", 0170, 0,
|
|
"/y", 0171, 0,
|
|
"/z", 0172, 0,
|
|
"/braceleft", 0173, 0,
|
|
"/bar", 0174, 0,
|
|
"/braceright", 0175, 0,
|
|
"/asciitilde", 0176, 0,
|
|
"/", 0177, 0,
|
|
|
|
|
|
/* nonstandard defs */
|
|
|
|
"/quotedblleft", 0200, 0,
|
|
"/quotedblright", 0201, 0,
|
|
"/quotedblbase", 0202, 0,
|
|
"/quotesinglbase", 0203, 0,
|
|
"/guilsinglleft", 0204, 0,
|
|
"/guilsinglright", 0205, 0,
|
|
"/endash", 0206, 0,
|
|
"/dagger", 0207, 0,
|
|
|
|
"/daggerdbl", 0210, 0,
|
|
"/trademark", 0211, 0,
|
|
"/bullet", 0212, 0,
|
|
"/perthousand", 0213, 0,
|
|
"/Lslash", 0214, 0,
|
|
"/OE", 0215, 0,
|
|
"/lslash", 0216, 0,
|
|
"/oe", 0217, 0,
|
|
|
|
/* endnonstandard defs */
|
|
|
|
"/dotlessi", 0220, 0,
|
|
"/grave", 0221, 0,
|
|
"/acute", 0222, 0,
|
|
"/circumflex", 0223, 0,
|
|
"/tilde", 0224, 0,
|
|
"/", 0225, 0,
|
|
"/breve", 0226, 0,
|
|
"/dotaccent", 0227, 0,
|
|
|
|
"/", 0230, 0,
|
|
"/", 0231, 0,
|
|
"/ring", 0232, 0,
|
|
"/", 0233, 0,
|
|
"/", 0234, 0,
|
|
"/hungarumlaut", 0235, 0,
|
|
"/ogonek", 0236, 0,
|
|
"/caron", 0237, 0,
|
|
|
|
"/", 0240, 0,
|
|
"/exclamdown", 0241, 0,
|
|
"/cent", 0242, 0,
|
|
"/sterling", 0243, 0,
|
|
"/florin", 0244, 0,
|
|
"/yen", 0245, 0,
|
|
"/brokenbar", 0246, 0,
|
|
"/section", 0247, 0,
|
|
|
|
"/dieresis", 0250, 0,
|
|
"/copyright", 0251, 0,
|
|
"/ordfeminine", 0252, 0,
|
|
"/guillemotleft", 0253, 0,
|
|
"/logicalnot", 0254, 0,
|
|
"/hyphen", 0255, 0,
|
|
"/registered", 0256, 0,
|
|
"/macron", 0257, 0,
|
|
|
|
"/degree", 0260, 0,
|
|
"/plusminus", 0261, 0,
|
|
"/twosuperior", 0262, 0,
|
|
"/threesuperior", 0263, 0,
|
|
"/acute", 0264, 0,
|
|
"/mu", 0265, 0,
|
|
"/paragraph", 0266, 0,
|
|
"/periodcentered", 0267, 0,
|
|
|
|
"/cedilla", 0270, 0,
|
|
"/onesuperior", 0271, 0,
|
|
"/ordmasculine", 0272, 0,
|
|
"/guillemotright", 0273, 0,
|
|
"/onequarter", 0274, 0,
|
|
"/onehalf", 0275, 0,
|
|
"/threequarters", 0276, 0,
|
|
"/questiondown", 0277, 0,
|
|
|
|
"/Agrave", 0300, 0,
|
|
"/Aacute", 0301, 0,
|
|
"/Acircumflex", 0302, 0,
|
|
"/Atilde", 0303, 0,
|
|
"/Adieresis", 0304, 0,
|
|
"/Aring", 0305, 0,
|
|
"/AE", 0306, 0,
|
|
"/Ccedilla", 0307, 0,
|
|
|
|
"/Egrave", 0310, 0,
|
|
"/Eacute", 0311, 0,
|
|
"/Ecircumflex", 0312, 0,
|
|
"/Edieresis", 0313, 0,
|
|
"/Igrave", 0314, 0,
|
|
"/Iacute", 0315, 0,
|
|
"/Icircumflex", 0316, 0,
|
|
"/Idieresis", 0317, 0,
|
|
|
|
"/Eth", 0320, 0,
|
|
"/Ntilde", 0321, 0,
|
|
"/Ograve", 0322, 0,
|
|
"/Oacute", 0323, 0,
|
|
"/Ocircumflex", 0324, 0,
|
|
"/Otilde", 0325, 0,
|
|
"/Odieresis", 0326, 0,
|
|
"/multiply", 0327, 0,
|
|
|
|
"/Oslash", 0330, 0,
|
|
"/Ugrave", 0331, 0,
|
|
"/Uacute", 0332, 0,
|
|
"/Ucircumflex", 0333, 0,
|
|
"/Udieresis", 0334, 0,
|
|
"/Yacute", 0335, 0,
|
|
"/Thorn", 0336, 0,
|
|
"/germandbls", 0337, 0,
|
|
|
|
"/agrave", 0340, 0,
|
|
"/aacute", 0341, 0,
|
|
"/acircumflex", 0342, 0,
|
|
"/atilde", 0343, 0,
|
|
"/adieresis", 0344, 0,
|
|
"/aring", 0345, 0,
|
|
"/ae", 0346, 0,
|
|
"/ccedilla", 0347, 0,
|
|
|
|
"/egrave", 0350, 0,
|
|
"/eacute", 0351, 0,
|
|
"/ecircumflex", 0352, 0,
|
|
"/edieresis", 0353, 0,
|
|
"/igrave", 0354, 0,
|
|
"/iacute", 0355, 0,
|
|
"/icircumflex", 0356, 0,
|
|
"/idieresis", 0357, 0,
|
|
|
|
"/eth", 0360, 0,
|
|
"/ntilde", 0361, 0,
|
|
"/ograve", 0362, 0,
|
|
"/oacute", 0363, 0,
|
|
"/ocircumflex", 0364, 0,
|
|
"/otilde", 0365, 0,
|
|
"/odieresis", 0366, 0,
|
|
"/divide", 0367, 0,
|
|
|
|
"/oslash", 0370, 0,
|
|
"/ugrave", 0371, 0,
|
|
"/uacute", 0372, 0,
|
|
"/ucircumflex", 0373, 0,
|
|
"/udieresis", 0374, 0,
|
|
"/yacute", 0375, 0,
|
|
"/thorn", 0376, 0,
|
|
"/ydieresis", 0377, 0,
|
|
};
|
|
|
|
|
|
static short STDvsISO [][2] = {
|
|
0341, 0306, /* AE */
|
|
0351, 0330, /* Oslash */
|
|
0302, 0222, /* acute */
|
|
0361, 0346, /* ae */
|
|
0306, 0226, /* breve */
|
|
0317, 0237, /* caron */
|
|
0313, 0270, /* cedilla */
|
|
0303, 0223, /* circumflex */
|
|
0250, 0244, /* currency */
|
|
0310, 0250, /* dieresis */
|
|
0307, 0227, /* dotaccent */
|
|
0365, 0220, /* dotlessi */
|
|
0373, 0337, /* germandbls */
|
|
0301, 0221, /* grave */
|
|
0315, 0235, /* hungarumlaut */
|
|
0055, 0255, /* hyphen */
|
|
0305, 0257, /* macron */
|
|
0316, 0236, /* ogenek */
|
|
0343, 0252, /* ordfeminine */
|
|
0353, 0272, /* ordmasculine */
|
|
0371, 0370, /* oslash */
|
|
0264, 0267, /* periodcentered */
|
|
0312, 0232, /* ring */
|
|
0304, 0224, /* tilde */
|
|
};
|
|
|
|
/* from objfont.c de rest zit in lfm_s !!*/
|
|
|
|
/* START 5.2 */
|
|
|
|
static int chartoindex(objfnt *fnt, int c)
|
|
{
|
|
if(c<fnt->charmin)
|
|
return -1;
|
|
if(c>fnt->charmax)
|
|
return -1;
|
|
return c-fnt->charmin;
|
|
}
|
|
|
|
|
|
static chardesc *getchardesc(objfnt *fnt, int c)
|
|
{
|
|
int index;
|
|
|
|
index = chartoindex(fnt,c);
|
|
if(index<0)
|
|
return 0;
|
|
return fnt->my_chars+index;
|
|
}
|
|
|
|
static objfnt *newobjfnt(int type, int charmin, int charmax, int fscale)
|
|
{
|
|
objfnt *fnt;
|
|
|
|
fnt = (objfnt *)MEM_mallocN(sizeof(objfnt), "newobjfnt");
|
|
fnt->freeaddr = 0;
|
|
fnt->type = type;
|
|
fnt->charmin = charmin;
|
|
fnt->charmax = charmax;
|
|
fnt->my_nchars = fnt->charmax-fnt->charmin+1;
|
|
fnt->scale = fscale;
|
|
fnt->my_chars = (chardesc *)MEM_mallocN(fnt->my_nchars*sizeof(chardesc), "newobjfnt2");
|
|
memset(fnt->my_chars, 0, fnt->my_nchars*sizeof(chardesc));
|
|
return fnt;
|
|
}
|
|
|
|
|
|
static void addchardata (objfnt * fnt, int c, short * data, int nshorts)
|
|
{
|
|
int index;
|
|
chardesc *cd;
|
|
|
|
index = chartoindex(fnt,c);
|
|
if(index<0) {
|
|
fprintf(stderr,"Addchardata bad poop\n");
|
|
return;
|
|
}
|
|
cd = fnt->my_chars+index;
|
|
fnt->freeaddr = 0;
|
|
cd->datalen = nshorts*sizeof(short);
|
|
cd->data = (short *)MEM_mallocN(cd->datalen, "addchardata");
|
|
memcpy(cd->data, data, cd->datalen);
|
|
}
|
|
|
|
static void addcharmetrics(objfnt *fnt, int c, int movex, int movey)
|
|
{
|
|
int index;
|
|
chardesc *cd;
|
|
|
|
index = chartoindex(fnt,c);
|
|
if(index<0) {
|
|
fprintf(stderr,"Addcharmetrics bad poop\n");
|
|
return;
|
|
}
|
|
cd = fnt->my_chars+index;
|
|
cd->movex = movex;
|
|
cd->movey = movey;
|
|
}
|
|
|
|
|
|
static void fakechar(objfnt *fnt, int c, int width)
|
|
{
|
|
short chardata[1];
|
|
|
|
chardata[0] = PO_RET;
|
|
addchardata(fnt,c,chardata,1);
|
|
addcharmetrics(fnt,c,width,0);
|
|
}
|
|
|
|
|
|
static void freeobjfnt(objfnt * fnt)
|
|
{
|
|
int i;
|
|
chardesc *cd;
|
|
|
|
cd = fnt->my_chars;
|
|
for(i=0; i<fnt->my_nchars; i++) {
|
|
if(cd->data)
|
|
MEM_freeN(cd->data);
|
|
cd++;
|
|
}
|
|
MEM_freeN(fnt->my_chars);
|
|
MEM_freeN(fnt);
|
|
}
|
|
|
|
|
|
/* END 5.2 */
|
|
|
|
static short STDtoISO(short c)
|
|
{
|
|
short i = (sizeof(STDvsISO) / (2 * sizeof(short))) - 1;
|
|
|
|
for (;i >= 0; i--){
|
|
if (STDvsISO[i][0] == c) return (STDvsISO[i][1]);
|
|
}
|
|
return(c);
|
|
}
|
|
|
|
|
|
/*
|
|
* read the font matrix out of the font file
|
|
*
|
|
*/
|
|
|
|
static char * newfgets(char * s, int n, PackedFile * pf){
|
|
int read = 0;
|
|
int c;
|
|
char * p;
|
|
|
|
p = s;
|
|
while (n > 0){
|
|
c = ((char *) pf->data)[pf->seek];
|
|
pf->seek++;
|
|
if (pf->seek > pf->size){
|
|
if (read == 0) return (0);
|
|
*p = 0;
|
|
return(s);
|
|
}
|
|
if (c == 10 || c == 13){
|
|
*p = 0;
|
|
return(s);
|
|
}
|
|
*p++ = c;
|
|
n--;
|
|
}
|
|
*p = 0;
|
|
return(s);
|
|
}
|
|
|
|
static int readfontmatrix(PackedFile * pf, float mat[2][2])
|
|
{
|
|
char *cptr;
|
|
float a, b, c, d, e, f;
|
|
|
|
pf->seek = 0;
|
|
|
|
/* look for the FontMatrix def */
|
|
while(1) {
|
|
if(!newfgets(oneline, LINELEN, pf)) {
|
|
fprintf(stderr,"fromtype1: no FontMatrix found\n");
|
|
return(-1);
|
|
}
|
|
cptr = strchr(oneline,'/');
|
|
if(cptr) {
|
|
if(strncmp(cptr,"/FontMatrix",11) == 0) {
|
|
cptr = strchr(cptr,'[');
|
|
if(!cptr) {
|
|
fprintf(stderr,"fromtype1: bad FontMatrix line\n");
|
|
return(-1);
|
|
}
|
|
sscanf(cptr+1,"%f %f %f %f %f %f\n",&a,&b,&c,&d,&e,&f);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
mat[0][0] = 1000.0*a;
|
|
mat[1][0] = 1000.0*b;
|
|
mat[0][1] = 1000.0*c;
|
|
mat[1][1] = 1000.0*d;
|
|
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Decryption support
|
|
*
|
|
*
|
|
*/
|
|
static void resetdecrypt(int n)
|
|
{
|
|
mr = n;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* decryption subroutines
|
|
*
|
|
*/
|
|
|
|
static char mdecrypt(char cipher)
|
|
{
|
|
char plain;
|
|
|
|
plain = (cipher^(mr>>8));
|
|
mr = (cipher+mr)*MC1 + MC2;
|
|
return plain;
|
|
}
|
|
|
|
static void decryptdata(char * cptr, int n)
|
|
{
|
|
while(n--) {
|
|
*cptr = mdecrypt(*cptr);
|
|
cptr++;
|
|
}
|
|
}
|
|
|
|
static int decryptprogram(char *buf, int len)
|
|
{
|
|
int i;
|
|
|
|
resetdecrypt(4330);
|
|
for(i=0; i<len; i++) {
|
|
if(i<SKIP)
|
|
mdecrypt(buf[i]);
|
|
else
|
|
buf[i-SKIP] = mdecrypt(buf[i]);
|
|
}
|
|
return len-SKIP;
|
|
}
|
|
|
|
static void decryptall(void)
|
|
{
|
|
int i;
|
|
|
|
for(i=0; i<my_nsubrs; i++)
|
|
my_sublen[i] = decryptprogram(my_subrs[i],my_sublen[i]);
|
|
for(i=0; i<my_nchars; i++)
|
|
my_charlen[i] = decryptprogram(my_chars[i],my_charlen[i]);
|
|
}
|
|
|
|
|
|
/*
|
|
* decode the eexec part of the file
|
|
*
|
|
*/
|
|
|
|
static int decodetype1(PackedFile * pf, char *outname)
|
|
{
|
|
char *hptr, *bptr;
|
|
int i, totlen, hexbytes, c;
|
|
char *hexdat;
|
|
char hextab[256];
|
|
|
|
/* make hex table */
|
|
if(!firsted) {
|
|
for(i=0; i<256; i++) {
|
|
if(i>='0' && i<='9')
|
|
hextab[i] = i-'0';
|
|
else if(i>='a' && i<='f')
|
|
hextab[i] = 10+i-'a';
|
|
else if(i>='A' && i<='F')
|
|
hextab[i] = 10+i-'A';
|
|
else
|
|
hextab[i] = NOTHEX;
|
|
}
|
|
}
|
|
|
|
pf->seek = 0;
|
|
|
|
/* allocate buffers */
|
|
totlen = pf->size;
|
|
hexdat = (char *)MEM_mallocN(totlen, "hexdat");
|
|
bindat = (char *)MEM_mallocN(totlen, "bindat");
|
|
|
|
/* look for eexec part of file */
|
|
while(1) {
|
|
if(!newfgets(oneline, LINELEN, pf)) {
|
|
fprintf(stderr,"fromtype1: no currentfile eexec found\n");
|
|
return(-1);
|
|
}
|
|
oneline[16] = 0;
|
|
if(strcmp(oneline,"currentfile eexe") == 0)
|
|
break;
|
|
}
|
|
|
|
/* initialize decryption variables */
|
|
mr = 55665;
|
|
|
|
/* first byte == 0 for binary data (???) */
|
|
|
|
c = ((char *) pf->data)[pf->seek];
|
|
|
|
if (hextab[c] != NOTHEX){
|
|
/* read all the hex bytes into the hex buffer */
|
|
hexbytes = 0;
|
|
while(newfgets(oneline, LINELEN, pf)) {
|
|
hptr = (char *)oneline;
|
|
while(*hptr) {
|
|
if(hextab[*hptr] != NOTHEX)
|
|
hexdat[hexbytes++] = *hptr;
|
|
hptr++;
|
|
}
|
|
}
|
|
|
|
/* check number of hex bytes */
|
|
if(hexbytes & 1)
|
|
hexbytes--;
|
|
datbytes = hexbytes/2;
|
|
|
|
/* translate hex data to binary */
|
|
hptr = hexdat;
|
|
bptr = bindat;
|
|
c = datbytes;
|
|
while(c--) {
|
|
*bptr++ = (hextab[hptr[0]]<<4)+hextab[hptr[1]];
|
|
hptr += 2;
|
|
}
|
|
|
|
/* decrypt the data */
|
|
decryptdata(bindat,datbytes);
|
|
|
|
} else {
|
|
datbytes = pf->size - pf->seek;
|
|
memcpy(bindat, ((char *) pf->data) + pf->seek, datbytes);
|
|
|
|
if ((bindat[2] << 8 + bindat[3]) == 0x800){
|
|
/* order data (remove 6 bytes headers) */
|
|
i = datbytes;
|
|
hptr = bptr = bindat + 4;
|
|
hptr += 2;
|
|
|
|
while (i > 0){
|
|
if (i > 2046) c = 2046;
|
|
else c = i;
|
|
|
|
memcpy(bptr, hptr, c);
|
|
bptr += 2046;
|
|
hptr += 2046 + 6;
|
|
i -= 2046 + 6;
|
|
datbytes -= 6;
|
|
}
|
|
|
|
/* decrypt the data */
|
|
decryptdata(bindat+4,datbytes);
|
|
} else{
|
|
decryptdata(bindat+6,datbytes-6);
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
outf = fopen(outname,"wb");
|
|
fwrite(bindat,datbytes,1,outf);
|
|
fclose(outf);
|
|
#endif
|
|
|
|
MEM_freeN(hexdat);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* fake file reading funcs
|
|
*
|
|
*
|
|
*/
|
|
|
|
static void fakefopen(void)
|
|
{
|
|
fakepos = 0;
|
|
fakemax = datbytes;
|
|
}
|
|
|
|
|
|
static void fakegettoken(char *str)
|
|
{
|
|
int c;
|
|
char *cptr;
|
|
char *start;
|
|
|
|
start = (char *) str;
|
|
cptr = bindat+fakepos;
|
|
c = *cptr++;
|
|
fakepos++;
|
|
if(c != '\n') {
|
|
while(isspace(c)) {
|
|
c = *cptr++;
|
|
fakepos++;
|
|
}
|
|
while (fakepos<fakemax && !isspace(c)) {
|
|
*str++ = c;
|
|
c = *cptr++;
|
|
fakepos++;
|
|
}
|
|
if(c == '\n')
|
|
fakepos--;
|
|
}
|
|
*str = 0;
|
|
if(fakepos>fakemax) {
|
|
fprintf(stderr,"fromtype1: unexpected eof\n");
|
|
strcpy(start, "end");
|
|
}
|
|
}
|
|
|
|
static int fakefgets(char *buf,int max)
|
|
{
|
|
char *cptr;
|
|
|
|
cptr = (char *)(bindat+fakepos);
|
|
while(max--) {
|
|
*buf++ = *cptr;
|
|
fakepos++;
|
|
if(*cptr == 10 || *cptr == 13)
|
|
return 1;
|
|
cptr++;
|
|
if(fakepos>fakemax)
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static char *fakefread(int n)
|
|
{
|
|
fakepos += n;
|
|
return bindat+fakepos-n;
|
|
}
|
|
|
|
static void applymat(float mat[][2], float *x, float *y)
|
|
{
|
|
float tx, ty;
|
|
|
|
tx = ((*x)*mat[0][0])+((*y)*mat[0][1]);
|
|
ty = ((*x)*mat[1][0])+((*y)*mat[1][1]);
|
|
*x = tx;
|
|
*y = ty;
|
|
}
|
|
|
|
static void setcharlist(void)
|
|
{
|
|
char *name, found;
|
|
int i, j;
|
|
|
|
for(i=0; i<NASCII; i++) ISOcharlist[i].prog = -1;
|
|
|
|
for(j=0; j<my_nchars; j++) {
|
|
name = my_charname[j];
|
|
if(name) {
|
|
found = 0;
|
|
for(i=0; i<NASCII; i++) {
|
|
if(ISOcharlist[i].name && (strcmp(name,ISOcharlist[i].name) == 0)){
|
|
ISOcharlist[i].prog = j;
|
|
found = 1;
|
|
}
|
|
}
|
|
/*if (found == 0) printf("no match found for: %s\n", name);*/
|
|
MEM_freeN(name);
|
|
my_charname[j] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static objfnt * objfnt_from_psfont(PackedFile * pf)
|
|
{
|
|
int i, k, index;
|
|
int nread, namelen;
|
|
char *cptr;
|
|
|
|
fnt = 0;
|
|
bindat = 0;
|
|
|
|
/* read the font matrix from the font */
|
|
if (readfontmatrix(pf,mat)) return(0);
|
|
|
|
/* decode the font data */
|
|
decodetype1(pf, "/usr/tmp/type1.dec");
|
|
|
|
/* open the input file */
|
|
fakefopen();
|
|
|
|
/* look for the /Subrs def and get my_nsubrs */
|
|
while(1) {
|
|
if(!fakefgets(oneline,LINELEN)) {
|
|
fprintf(stderr,"fromtype1: no /Subrs found\n");
|
|
my_nsubrs = 0;
|
|
fakefopen();
|
|
break;
|
|
}
|
|
cptr = strchr(oneline,'/');
|
|
if(cptr) {
|
|
if(strncmp(cptr,"/Subrs",6) == 0) {
|
|
my_nsubrs = atoi(cptr+6);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* read the Subrs in one by one */
|
|
for(i=0; i<my_nsubrs; i++)
|
|
my_sublen[i] = 0;
|
|
for(i=0; i<my_nsubrs; i++) {
|
|
for(k=0; k<MAXTRIES; k++) {
|
|
fakegettoken(tok);
|
|
if(strcmp(tok,"dup") == 0)
|
|
break;
|
|
}
|
|
if(k == MAXTRIES) {
|
|
fprintf(stderr,"dup for subr %d not found in range\n", i);
|
|
/*exit(1);*/
|
|
}
|
|
|
|
/* get the Subr index here */
|
|
fakegettoken(tok);
|
|
index = atoi(tok);
|
|
|
|
/* check to make sure it is in range */
|
|
if(index<0 || index>my_nsubrs) {
|
|
fprintf(stderr,"bad Subr index %d\n",index);
|
|
/*exit(1);*/
|
|
}
|
|
|
|
/* get the number of bytes to read */
|
|
fakegettoken(tok);
|
|
nread = atoi(tok);
|
|
fakegettoken(tok);
|
|
|
|
/* read in the subroutine */
|
|
my_sublen[index] = nread;
|
|
my_subrs[index] = fakefread(nread);
|
|
fakegettoken(tok);
|
|
}
|
|
|
|
/* look for the CharStrings */
|
|
while(1) {
|
|
fakegettoken(tok);
|
|
cptr = strchr(tok,'/');
|
|
if(cptr && strcmp(cptr,"/CharStrings") == 0)
|
|
break;
|
|
}
|
|
|
|
fakegettoken(tok); /* skip my_ncharscrings */
|
|
fakegettoken(tok); /* skip dict */
|
|
fakegettoken(tok); /* skip dup */
|
|
fakegettoken(tok); /* skip begin */
|
|
fakegettoken(tok); /* skip newline */
|
|
|
|
/* read the CharStrings one by one */
|
|
my_nchars = 0;
|
|
for(i=0; i<MAXCHARS; i++) {
|
|
|
|
/* check for end */
|
|
fakegettoken(tok);
|
|
if(strcmp(tok,"end") == 0)
|
|
break;
|
|
|
|
/* get the char name and allocate space for it */
|
|
namelen = strlen(tok);
|
|
my_charname[i] = (char *)MEM_mallocN(namelen+1, "my_charname");
|
|
strcpy(my_charname[i],tok);
|
|
|
|
/* get the number of bytes to read */
|
|
fakegettoken(tok);
|
|
nread = atoi(tok);
|
|
fakegettoken(tok);
|
|
|
|
/* read in the char description */
|
|
my_charlen[i] = nread;
|
|
my_chars[i] = fakefread(nread);
|
|
|
|
/* skip the end of line */
|
|
fakegettoken(tok);
|
|
fakegettoken(tok);
|
|
my_nchars++;
|
|
}
|
|
|
|
/* decrypt the character descriptions */
|
|
decryptall();
|
|
setcharlist();
|
|
|
|
/* make the obj font */
|
|
makeobjfont(savesplines);
|
|
|
|
if (bindat) MEM_freeN(bindat);
|
|
/* system("rm /usr/tmp/type1.dec"); */
|
|
|
|
return (fnt);
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* pc stack support
|
|
*
|
|
*/
|
|
|
|
static void initpcstack(void)
|
|
{
|
|
pcsp = 0;
|
|
}
|
|
|
|
static void pushpc(char *pc)
|
|
{
|
|
pcstack[pcsp] = pc;
|
|
pcsp++;
|
|
}
|
|
|
|
static char *poppc(void)
|
|
{
|
|
pcsp--;
|
|
if(pcsp<0) {
|
|
fprintf(stderr,"\nYUCK: pc stack under flow\n");
|
|
pcsp = 0;
|
|
return 0;
|
|
}
|
|
return pcstack[pcsp];
|
|
}
|
|
|
|
/*
|
|
* Data stack support
|
|
*
|
|
*/
|
|
|
|
static void initstack(void)
|
|
{
|
|
sp = 0;
|
|
}
|
|
|
|
static void push(int val)
|
|
/* int val; */
|
|
{
|
|
stack[sp] = val;
|
|
sp++;
|
|
}
|
|
|
|
static int pop(void)
|
|
{
|
|
sp--;
|
|
if(sp<0) {
|
|
fprintf(stderr,"\nYUCK: stack under flow\n");
|
|
sp = 0;
|
|
return 0;
|
|
}
|
|
return stack[sp];
|
|
}
|
|
|
|
/*
|
|
* call/return data stack
|
|
*
|
|
*/
|
|
|
|
static void initretstack(void)
|
|
{
|
|
retsp = 0;
|
|
}
|
|
|
|
static void retpush(int val)
|
|
/* int val; */
|
|
{
|
|
retstack[retsp] = val;
|
|
retsp++;
|
|
}
|
|
|
|
static int retpop(void)
|
|
{
|
|
retsp--;
|
|
if(retsp<0) {
|
|
fprintf(stderr,"\nYUCK: ret stack under flow\n");
|
|
retsp = 0;
|
|
return 0;
|
|
}
|
|
return retstack[retsp];
|
|
}
|
|
|
|
|
|
/*
|
|
* execute the program:
|
|
*
|
|
*
|
|
*/
|
|
|
|
static void getmove(int *x, int *y)
|
|
{
|
|
*x = delx;
|
|
*y = dely;
|
|
/* printf("ingetmove\n"); */
|
|
}
|
|
|
|
static void getpos(int *x, int *y)
|
|
{
|
|
*x = curx;
|
|
*y = cury;
|
|
}
|
|
|
|
static void subr1(void)
|
|
{
|
|
coordpos = 0;
|
|
incusp = 1;
|
|
}
|
|
|
|
static void subr2(void)
|
|
{
|
|
int x, y;
|
|
|
|
getmove(&x,&y);
|
|
if(coordpos>=7) {
|
|
fprintf(stderr,"subr2: bad poop\n");
|
|
/*exit(1);*/
|
|
}
|
|
coordsave[coordpos][0] = x;
|
|
coordsave[coordpos][1] = y;
|
|
coordpos++;
|
|
}
|
|
|
|
static void subr0(void)
|
|
{
|
|
int x0, y0;
|
|
int x1, y1;
|
|
int x2, y2;
|
|
int x3, y3;
|
|
int xpos, ypos, noise;
|
|
|
|
ypos = pop();
|
|
xpos = pop();
|
|
noise = pop();
|
|
if(coordpos!=7) {
|
|
fprintf(stderr,"subr0: bad poop\n");
|
|
/*exit(1);*/
|
|
}
|
|
x0 = coordsave[0][0];
|
|
y0 = coordsave[0][1];
|
|
|
|
x1 = coordsave[1][0]+x0;
|
|
y1 = coordsave[1][1]+y0;
|
|
x2 = coordsave[2][0];
|
|
y2 = coordsave[2][1];
|
|
x3 = coordsave[3][0];
|
|
y3 = coordsave[3][1];
|
|
rcurveto(x1,y1,x1+x2,y1+y2,x1+x2+x3,y1+y2+y3);
|
|
x1 = coordsave[4][0];
|
|
y1 = coordsave[4][1];
|
|
x2 = coordsave[5][0];
|
|
y2 = coordsave[5][1];
|
|
x3 = coordsave[6][0];
|
|
y3 = coordsave[6][1];
|
|
rcurveto(x1,y1,x1+x2,y1+y2,x1+x2+x3,y1+y2+y3);
|
|
getpos(&x0,&y0);
|
|
retpush(y0);
|
|
retpush(x0);
|
|
incusp = 0;
|
|
}
|
|
|
|
static void append_poly_offset(short ofsx, short ofsy, short * data)
|
|
{
|
|
int nverts;
|
|
|
|
if (data == 0) return;
|
|
|
|
while(1) {
|
|
switch(chardata[nshorts++] = *data++) {
|
|
case PO_BGNLOOP:
|
|
nshorts --; /* voor de eerste keer */
|
|
break;
|
|
case PO_RETENDLOOP:
|
|
case PO_RET:
|
|
return;
|
|
}
|
|
nverts = chardata[nshorts++] = *data++;
|
|
while(nverts--) {
|
|
chardata[nshorts++] = (*data++) + ofsx;
|
|
chardata[nshorts++] = (*data++) + ofsy;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void append_spline_offset(short ofsx, short ofsy, short * data)
|
|
{
|
|
int nverts = 0;
|
|
|
|
if (data == 0) return;
|
|
|
|
while(1) {
|
|
switch(chardata[nshorts++] = *data++) {
|
|
case SP_MOVETO:
|
|
case SP_LINETO:
|
|
nverts = 1;
|
|
break;
|
|
case SP_CURVETO:
|
|
nverts = 3;
|
|
break;
|
|
case SP_RETCLOSEPATH:
|
|
case SP_RET:
|
|
return;
|
|
}
|
|
|
|
for (; nverts > 0; nverts--) {
|
|
chardata[nshorts++] = (*data++) + ofsx;
|
|
chardata[nshorts++] = (*data++) + ofsy;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* graphics follows
|
|
*
|
|
*
|
|
*/
|
|
|
|
|
|
/* poly output stuff */
|
|
|
|
static void setwidth(int w, int x)
|
|
{
|
|
thecharwidth = w;
|
|
thesidebearing = x;
|
|
}
|
|
|
|
static void poly_beginchar(void)
|
|
{
|
|
npnts = 0;
|
|
nloops = 0;
|
|
}
|
|
|
|
static void poly_endchar(void)
|
|
{
|
|
if(nloops == 0)
|
|
chardata[nshorts++] = PO_RET;
|
|
else
|
|
chardata[nshorts++] = PO_RETENDLOOP;
|
|
}
|
|
|
|
static void poly_close(void)
|
|
{
|
|
chardata[nvertpos] = npnts;
|
|
npnts = 0;
|
|
}
|
|
|
|
static void poly_pnt(float x, float y)
|
|
{
|
|
int ix, iy;
|
|
|
|
applymat(mat,&x,&y);
|
|
ix = floor(x);
|
|
iy = floor(y);
|
|
if(npnts == 0) {
|
|
if(nloops == 0) {
|
|
chardata[nshorts++] = PO_BGNLOOP;
|
|
nvertpos = nshorts++;
|
|
} else {
|
|
chardata[nshorts++] = PO_ENDBGNLOOP;
|
|
nvertpos = nshorts++;
|
|
}
|
|
nloops++;
|
|
}
|
|
chardata[nshorts++] = ix;
|
|
chardata[nshorts++] = iy;
|
|
npnts++;
|
|
|
|
}
|
|
|
|
/* spline output stuff */
|
|
|
|
static void spline_beginchar(void)
|
|
{
|
|
sp_npnts = 0;
|
|
sp_nloops = 0;
|
|
}
|
|
|
|
static void spline_endchar(void)
|
|
{
|
|
if(sp_nloops == 0)
|
|
chardata[nshorts++] = SP_RET;
|
|
else
|
|
chardata[nshorts++] = SP_RETCLOSEPATH;
|
|
}
|
|
|
|
static void spline_close(void)
|
|
{
|
|
chardata[nshorts++] = SP_CLOSEPATH;
|
|
sp_npnts = 0;
|
|
sp_nloops = 0;
|
|
}
|
|
|
|
static void spline_line(float x0, float y0, float x1, float y1)
|
|
{
|
|
applymat(mat,&x0,&y0);
|
|
applymat(mat,&x1,&y1);
|
|
|
|
if(sp_npnts == 0) {
|
|
chardata[nshorts++] = SP_MOVETO;
|
|
chardata[nshorts++] = floor(x0);
|
|
chardata[nshorts++] = floor(y0);
|
|
sp_npnts++;
|
|
sp_nloops++;
|
|
}
|
|
chardata[nshorts++] = SP_LINETO;
|
|
chardata[nshorts++] = floor(x1);
|
|
chardata[nshorts++] = floor(y1);
|
|
sp_npnts++;
|
|
}
|
|
|
|
static void spline_curveto(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
|
|
{
|
|
applymat(mat,&x0,&y0);
|
|
applymat(mat,&x1,&y1);
|
|
applymat(mat,&x2,&y2);
|
|
applymat(mat,&x3,&y3);
|
|
|
|
if(sp_npnts == 0) {
|
|
chardata[nshorts++] = SP_MOVETO;
|
|
chardata[nshorts++] = floor(x0);
|
|
chardata[nshorts++] = floor(y0);
|
|
sp_npnts++;
|
|
sp_nloops++;
|
|
}
|
|
chardata[nshorts++] = SP_CURVETO;
|
|
chardata[nshorts++] = floor(x1);
|
|
chardata[nshorts++] = floor(y1);
|
|
chardata[nshorts++] = floor(x2);
|
|
chardata[nshorts++] = floor(y2);
|
|
chardata[nshorts++] = floor(x3);
|
|
chardata[nshorts++] = floor(y3);
|
|
}
|
|
|
|
static void savestart(int x, int y)
|
|
{
|
|
startx = x;
|
|
starty = y;
|
|
started = 1;
|
|
}
|
|
|
|
static void sbpoint( int x, int y)
|
|
{
|
|
curx = x;
|
|
cury = y;
|
|
}
|
|
|
|
static void rmoveto( int x, int y)
|
|
{
|
|
if(incusp) {
|
|
delx = x;
|
|
dely = y;
|
|
} else {
|
|
curx += x;
|
|
cury += y;
|
|
savestart(curx,cury);
|
|
}
|
|
}
|
|
|
|
static void drawline(float x0, float y0, float x1, float y1, float dx0, float dy0, float dx1, float dy1)
|
|
{
|
|
if(x0!=x1 || y0!=y1)
|
|
poly_pnt(x1,y1);
|
|
}
|
|
|
|
|
|
static void rlineto( int x, int y)
|
|
{
|
|
float dx, dy;
|
|
|
|
nextx = curx + x;
|
|
nexty = cury + y;
|
|
dx = nextx-curx;
|
|
dy = nexty-cury;
|
|
if (savesplines) spline_line( curx, cury, nextx, nexty);
|
|
else drawline( curx, cury, nextx, nexty,dx,dy,dx,dy);
|
|
curx = nextx;
|
|
cury = nexty;
|
|
}
|
|
|
|
static void closepath(void)
|
|
{
|
|
float dx, dy;
|
|
|
|
if(started) {
|
|
dx = startx-curx;
|
|
dy = starty-cury;
|
|
if (savesplines) {
|
|
spline_close();
|
|
} else {
|
|
drawline( curx, cury, startx, starty,dx,dy,dx,dy);
|
|
poly_close();
|
|
}
|
|
started = 0;
|
|
}
|
|
}
|
|
|
|
static void bezadapt( float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float beztol)
|
|
{
|
|
float ax0,ay0,ax1,ay1,ax2,ay2,ax3,ay3;
|
|
float bx0,by0,bx1,by1,bx2,by2,bx3,by3;
|
|
float midx, midy;
|
|
float linx, liny, dx, dy, mag;
|
|
|
|
midx = (x0+3*x1+3*x2+x3)/8.0;
|
|
midy = (y0+3*y1+3*y2+y3)/8.0;
|
|
linx = (x0+x3)/2.0;
|
|
liny = (y0+y3)/2.0;
|
|
dx = midx-linx;
|
|
dy = midy-liny;
|
|
mag = dx*dx+dy*dy;
|
|
if(mag<(beztol*beztol))
|
|
drawline(x0,y0,x3,y3,x1-x0,y1-y0,x3-x2,y3-y2);
|
|
else {
|
|
ax0 = x0;
|
|
ay0 = y0;
|
|
ax1 = (x0+x1)/2;
|
|
ay1 = (y0+y1)/2;
|
|
ax2 = (x0+2*x1+x2)/4;
|
|
ay2 = (y0+2*y1+y2)/4;
|
|
ax3 = midx;
|
|
ay3 = midy;
|
|
bezadapt(ax0,ay0,ax1,ay1,ax2,ay2,ax3,ay3,beztol);
|
|
|
|
bx0 = midx;
|
|
by0 = midy;
|
|
bx1 = (x1+2*x2+x3)/4;
|
|
by1 = (y1+2*y2+y3)/4;
|
|
bx2 = (x2+x3)/2;
|
|
by2 = (y2+y3)/2;
|
|
bx3 = x3;
|
|
by3 = y3;
|
|
bezadapt(bx0,by0,bx1,by1,bx2,by2,bx3,by3,beztol);
|
|
}
|
|
}
|
|
|
|
static void drawbez( float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
|
|
{
|
|
bezadapt(x0,y0,x1,y1,x2,y2,x3,y3,beztol);
|
|
}
|
|
|
|
|
|
static void rcurveto( int dx1, int dy1, int dx2, int dy2, int dx3, int dy3)
|
|
{
|
|
int x0, y0;
|
|
int x1, y1;
|
|
int x2, y2;
|
|
int x3, y3;
|
|
|
|
x0 = curx;
|
|
y0 = cury;
|
|
x1 = curx+dx1;
|
|
y1 = cury+dy1;
|
|
x2 = curx+dx2;
|
|
y2 = cury+dy2;
|
|
x3 = curx+dx3;
|
|
y3 = cury+dy3;
|
|
|
|
if (savesplines) {
|
|
spline_curveto( x0, y0, x1, y1, x2, y2, x3, y3);
|
|
} else{
|
|
drawbez( x0, y0, x1, y1, x2, y2, x3, y3);
|
|
}
|
|
curx = x3;
|
|
cury = y3;
|
|
}
|
|
|
|
/*
|
|
* saveobjfont -
|
|
* save an object font.
|
|
*
|
|
*/
|
|
|
|
/* generic routines */
|
|
|
|
static void makeobjfont(int savesplines)
|
|
{
|
|
int i, c;
|
|
|
|
if(savesplines)
|
|
fnt = newobjfnt(SP_TYPE, 32, 32+NASCII-1, 9840);
|
|
else
|
|
fnt = newobjfnt(PO_TYPE, 32, 32+NASCII-1, 9840);
|
|
|
|
for(i=0; i<NASCII; i++) {
|
|
c = i+32;
|
|
if(ISOcharlist[i].prog>=0) {
|
|
/*printf("decoding %s\n", ISOcharlist[i].name);*/
|
|
|
|
nshorts = 0;
|
|
drawchar(ISOcharlist[i].prog);
|
|
addchardata(fnt,c,chardata,nshorts);
|
|
addcharmetrics(fnt,c,thecharwidth,0);
|
|
sidebearing[c] = thesidebearing;
|
|
} else if(c == ' ') {
|
|
printf("faking space %d\n",i);
|
|
fakechar(fnt,' ',400);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* run the character program
|
|
*
|
|
*
|
|
*/
|
|
|
|
static void drawchar(int c)
|
|
{
|
|
if (savesplines) {
|
|
spline_beginchar();
|
|
} else {
|
|
poly_beginchar();
|
|
}
|
|
initstack();
|
|
initpcstack();
|
|
initretstack();
|
|
pc = my_chars[c];
|
|
runprog();
|
|
if (savesplines){
|
|
spline_endchar();
|
|
} else {
|
|
poly_endchar();
|
|
}
|
|
}
|
|
|
|
static int docommand(int cmd)
|
|
{
|
|
int x, y, w, c1, c2;
|
|
int dx1, dy1;
|
|
int dx2, dy2;
|
|
int dx3, dy3;
|
|
float fdx1, fdy1;
|
|
int i, sub, n;
|
|
char *subpc;
|
|
chardesc *cd;
|
|
short *ndata;
|
|
|
|
switch(cmd) {
|
|
case WHAT0:
|
|
fprintf(stderr,"\nYUCK: WHAT0\n");
|
|
break;
|
|
case HSTEM:
|
|
pop();
|
|
pop();
|
|
/*printf("hstem: %d %d\n", pop(), pop());*/
|
|
break;
|
|
case VSTEM:
|
|
pop();
|
|
pop();
|
|
/*printf("vstem: %d %d\n", pop(), pop());*/
|
|
break;
|
|
case VMOVETO:
|
|
y = pop();
|
|
rmoveto(0,y);
|
|
break;
|
|
case RLINETO:
|
|
y = pop();
|
|
x = pop();
|
|
rlineto(x,y);
|
|
break;
|
|
case HLINETO:
|
|
x = pop();
|
|
rlineto(x,0);
|
|
break;
|
|
case VLINETO:
|
|
y = pop();
|
|
rlineto(0,y);
|
|
break;
|
|
case RRCURVETO:
|
|
dy3 = pop();
|
|
dx3 = pop();
|
|
dy2 = pop();
|
|
dx2 = pop();
|
|
dy1 = pop();
|
|
dx1 = pop();
|
|
rcurveto(dx1,dy1,dx1+dx2,dy1+dy2,dx1+dx2+dx3,dy1+dy2+dy3);
|
|
break;
|
|
case CLOSEPATH:
|
|
closepath();
|
|
break;
|
|
case CALLSUBR:
|
|
sub = pop();
|
|
subpc = my_subrs[sub];
|
|
if(!subpc) {
|
|
fprintf(stderr,"\nYUCK no sub addr\n");
|
|
}
|
|
pushpc(pc);
|
|
pc = subpc;
|
|
break;
|
|
case RETURN:
|
|
pc = poppc();
|
|
break;
|
|
case HSBW:
|
|
w = pop();
|
|
x = pop();
|
|
setwidth(w, x);
|
|
sbpoint(x,0);
|
|
break;
|
|
case ENDCHAR:
|
|
closepath();
|
|
break;
|
|
case RMOVETO:
|
|
y = pop();
|
|
x = pop();
|
|
rmoveto(x,y);
|
|
break;
|
|
case HMOVETO:
|
|
x = pop();
|
|
rmoveto(x,0);
|
|
break;
|
|
case VHCURVETO:
|
|
dy3 = 0;
|
|
dx3 = pop();
|
|
dy2 = pop();
|
|
dx2 = pop();
|
|
dy1 = pop();
|
|
dx1 = 0;
|
|
rcurveto(dx1,dy1,dx1+dx2,dy1+dy2,dx1+dx2+dx3,dy1+dy2+dy3);
|
|
break;
|
|
case HVCURVETO:
|
|
dy3 = pop();
|
|
dx3 = 0;
|
|
dy2 = pop();
|
|
dx2 = pop();
|
|
dy1 = 0;
|
|
dx1 = pop();
|
|
rcurveto(dx1,dy1,dx1+dx2,dy1+dy2,dx1+dx2+dx3,dy1+dy2+dy3);
|
|
break;
|
|
case DOTSECTION:
|
|
break;
|
|
case VSTEM3:
|
|
/*printf("vstem3\n");*/
|
|
pop();
|
|
pop();
|
|
pop();
|
|
pop();
|
|
pop();
|
|
pop();
|
|
break;
|
|
case HSTEM3:
|
|
/*printf("hstem3\n");*/
|
|
pop();
|
|
pop();
|
|
pop();
|
|
pop();
|
|
pop();
|
|
pop();
|
|
break;
|
|
case SEAC:
|
|
if (0) {
|
|
printf("seac: %3d %3d %3d %3d %3d\n", pop(), pop(), pop(), pop(), pop());
|
|
} else{
|
|
c2 = STDtoISO(pop()); /* accent */
|
|
c1 = STDtoISO(pop()); /* letter */
|
|
|
|
cd = getchardesc(fnt, c1);
|
|
if (cd) {
|
|
memcpy(chardata, cd->data, cd->datalen);
|
|
nshorts = cd->datalen / sizeof(short);
|
|
}
|
|
|
|
cd = getchardesc(fnt, c2);
|
|
if (cd && cd->data && cd->datalen) {
|
|
ndata = cd->data;
|
|
|
|
if (nshorts) {
|
|
if (savesplines) {
|
|
switch (chardata[nshorts - 1]){
|
|
case SP_RET:
|
|
nshorts--;
|
|
break;
|
|
case SP_RETCLOSEPATH:
|
|
chardata[nshorts - 1] = SP_CLOSEPATH;
|
|
break;
|
|
}
|
|
} else {
|
|
switch (chardata[nshorts - 1]){
|
|
case PO_RET:
|
|
printf("PO_RET in character disription ?\n");
|
|
nshorts--;
|
|
break;
|
|
case PO_RETENDLOOP:
|
|
if (ndata[0] == PO_BGNLOOP) {
|
|
chardata[nshorts - 1] = PO_ENDBGNLOOP;
|
|
} else {
|
|
printf("new character doesn't start with PO_BGNLOOP ?\n");
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* i.p.v. the sidebearing[c1] moet misschen thesidebearing gebruikt worden */
|
|
|
|
dy1 = pop();
|
|
dx1 = pop() + sidebearing[c1] - sidebearing[c2];
|
|
pop();
|
|
|
|
fdx1 = dx1;
|
|
fdy1 = dy1;
|
|
applymat(mat, &fdx1, &fdy1);
|
|
dx1 = floor(fdx1);
|
|
dy1 = floor(fdy1);
|
|
|
|
if (savesplines) {
|
|
append_spline_offset(dx1, dy1, ndata);
|
|
} else{
|
|
append_poly_offset(dx1, dy1, ndata);
|
|
}
|
|
|
|
/*printf("first: %d %d\n", cd->data[0], cd->data[1]);*/
|
|
}
|
|
fflush(stdout);
|
|
}
|
|
break;
|
|
case SBW:
|
|
w = pop();
|
|
y = pop();
|
|
fprintf(stderr,"sbw: width: %d %d\n",w,y);
|
|
y = pop();
|
|
x = pop();
|
|
fprintf(stderr,"sbw: side: %d %d\n",x,y);
|
|
setwidth(w, x);
|
|
sbpoint(x,y);
|
|
break;
|
|
case DIV:
|
|
x = pop();
|
|
y = pop();
|
|
push(x/y);
|
|
break;
|
|
case CALLOTHERSUBR:
|
|
sub = pop();
|
|
n = pop();
|
|
if(sub == 0)
|
|
subr0();
|
|
else if(sub == 1)
|
|
subr1();
|
|
else if(sub == 2)
|
|
subr2();
|
|
else {
|
|
for(i=0; i<n; i++) {
|
|
retpush(pop());
|
|
}
|
|
}
|
|
break;
|
|
case POP:
|
|
push(retpop());
|
|
break;
|
|
case SETCURRENTPOINT:
|
|
y = pop();
|
|
x = pop();
|
|
sbpoint(x,y);
|
|
break;
|
|
default:
|
|
/*fprintf(stderr,"\nYUCK bad instruction %d\n",cmd);*/
|
|
break;
|
|
}
|
|
if(pc == 0 || cmd == ENDCHAR || cmd == WHAT0 || cmd == SEAC)
|
|
return 0;
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*
|
|
* Character interpreter
|
|
*
|
|
*/
|
|
|
|
static void runprog(void)
|
|
{
|
|
int v, w, num, cmd;
|
|
|
|
while(1) {
|
|
v = *pc++;
|
|
if(v>=0 && v<=31) {
|
|
if(v == 12) {
|
|
w = *pc++;
|
|
cmd = 256+w;
|
|
} else
|
|
cmd = v;
|
|
if(!docommand(cmd)) {
|
|
return;
|
|
}
|
|
} else if(v>=32 && v<=246) {
|
|
num = v-139;
|
|
push(num);
|
|
} else if(v>=247 && v<=250) {
|
|
w = *pc++;
|
|
num = (v-247)*256+w+108;
|
|
push(num);
|
|
} else if(v>=251 && v<=254) {
|
|
w = *pc++;
|
|
num = -(v-251)*256-w-108;
|
|
push(num);
|
|
} else if(v == 255) {
|
|
num = *pc++;
|
|
num <<= 8;
|
|
num |= *pc++;
|
|
num <<= 8;
|
|
num |= *pc++;
|
|
num <<= 8;
|
|
num |= *pc++;
|
|
push(num);
|
|
}
|
|
}
|
|
}
|
|
|
|
/***/
|
|
|
|
static VFontData *objfnt_to_vfontdata(objfnt *fnt)
|
|
{
|
|
VFontData *vfd;
|
|
chardesc *cd;
|
|
short *_data, *data;
|
|
int a, i, count, stop, ready, meet;
|
|
short first[2], last[2];
|
|
struct Nurb *nu;
|
|
struct BezTriple *bezt, *bez2;
|
|
float scale, dx, dy;
|
|
|
|
if (!fnt || (fnt->type!=SP_TYPE)) {
|
|
return NULL;
|
|
}
|
|
|
|
vfd= MEM_callocN(sizeof(*vfd), "VFontData");
|
|
scale = 10.0/(float)fnt->scale; /* na IRIX 6.2, schaal klopte niet meer */
|
|
|
|
for (i = 0; i < MAX_VF_CHARS; i++) {
|
|
cd = getchardesc(fnt, i);
|
|
if (cd && cd->data && cd->datalen) {
|
|
vfd->width[i] = scale * cd->movex;
|
|
|
|
_data = data = cd->data;
|
|
|
|
do{
|
|
/* eerst even tellen */
|
|
_data = data;
|
|
count = 0;
|
|
ready = stop = 0;
|
|
|
|
do{
|
|
switch(*data++){
|
|
case SP_MOVETO:
|
|
first[0] = data[0];
|
|
first[1] = data[1];
|
|
case SP_LINETO:
|
|
count++;
|
|
last[0] = data[0];
|
|
last[1] = data[1];
|
|
data += 2;
|
|
break;
|
|
case SP_CURVETO:
|
|
count++;
|
|
last[0] = data[4];
|
|
last[1] = data[5];
|
|
data += 6;
|
|
break;
|
|
case SP_RET:
|
|
case SP_RETCLOSEPATH:
|
|
stop = 1;
|
|
ready = 1;
|
|
break;
|
|
case SP_CLOSEPATH:
|
|
stop = 1;
|
|
break;
|
|
}
|
|
} while (!stop);
|
|
|
|
if (last[0] == first[0] && last[1] == first[1]) meet = 1;
|
|
else meet = 0;
|
|
|
|
/* is er meer dan 1 uniek punt ?*/
|
|
|
|
if (count - meet > 0) {
|
|
data = _data;
|
|
nu = (Nurb*)MEM_callocN(sizeof(struct Nurb),"objfnt_nurb");
|
|
bezt = (BezTriple*)MEM_callocN((count)* sizeof(BezTriple),"objfnt_bezt") ;
|
|
if (nu != 0 && bezt != 0) {
|
|
BLI_addtail(&vfd->nurbsbase[i], nu);
|
|
nu->type= CU_BEZIER+CU_2D;
|
|
nu->pntsu = count;
|
|
nu->resolu= 8;
|
|
nu->flagu= 1;
|
|
nu->bezt = bezt;
|
|
stop = 0;
|
|
|
|
/* punten inlezen */
|
|
do {
|
|
switch(*data++){
|
|
case SP_MOVETO:
|
|
bezt->vec[1][0] = scale * *data++;
|
|
bezt->vec[1][1] = scale * *data++;
|
|
|
|
break;
|
|
case SP_LINETO:
|
|
bez2 = bezt++;
|
|
bezt->vec[1][0] = scale * *data++;
|
|
bezt->vec[1][1] = scale * *data++;
|
|
/* vector handles */
|
|
bezt->h1= HD_VECT;
|
|
bez2->h2= HD_VECT;
|
|
dx = (bezt->vec[1][0] - bez2->vec[1][0]) / 3.0;
|
|
dy = (bezt->vec[1][1] - bez2->vec[1][1]) / 3.0;
|
|
bezt->vec[0][0] = bezt->vec[1][0] - dx;
|
|
bezt->vec[0][1] = bezt->vec[1][1] - dy;
|
|
bez2->vec[2][0] = bez2->vec[1][0] + dx;
|
|
bez2->vec[2][1] = bez2->vec[1][1] + dy;
|
|
break;
|
|
|
|
case SP_CURVETO:
|
|
bezt->vec[2][0] = scale * *data++;
|
|
bezt->vec[2][1] = scale * *data++;
|
|
bezt->h2= HD_ALIGN;
|
|
bezt++;
|
|
bezt->vec[0][0] = scale * *data++;
|
|
bezt->vec[0][1] = scale * *data++;
|
|
bezt->vec[1][0] = scale * *data++;
|
|
bezt->vec[1][1] = scale * *data++;
|
|
bezt->h1= HD_ALIGN;
|
|
break;
|
|
|
|
case SP_RET:
|
|
case SP_RETCLOSEPATH:
|
|
stop = 1;
|
|
ready = 1;
|
|
break;
|
|
case SP_CLOSEPATH:
|
|
stop = 1;
|
|
break;
|
|
}
|
|
} while (stop == 0);
|
|
|
|
if (meet) {
|
|
/* kopieer handles */
|
|
nu->bezt->vec[0][0] = bezt->vec[0][0];
|
|
nu->bezt->vec[0][1] = bezt->vec[0][1];
|
|
/* en vergeet laatste punt */
|
|
nu->pntsu--;
|
|
}
|
|
else {
|
|
/* vector handles */
|
|
bez2 = nu->bezt;
|
|
dx = (bezt->vec[1][0] - bez2->vec[1][0]) / 3.0;
|
|
dy = (bezt->vec[1][1] - bez2->vec[1][1]) / 3.0;
|
|
bezt->vec[2][0] = bezt->vec[1][0] - dx;
|
|
bezt->vec[2][1] = bezt->vec[1][1] - dy;
|
|
bez2->vec[0][0] = bez2->vec[1][0] + dx;
|
|
bez2->vec[0][1] = bez2->vec[1][1] + dy;
|
|
bezt->h2= bez2->h1= HD_VECT;
|
|
}
|
|
|
|
/* verboden handle combinaties */
|
|
a= nu->pntsu;
|
|
bezt= nu->bezt;
|
|
while(a--) {
|
|
if(bezt->h1!=HD_ALIGN && bezt->h2==HD_ALIGN) bezt->h2= 0;
|
|
else if(bezt->h2!=HD_ALIGN && bezt->h1==HD_ALIGN) bezt->h1= 0;
|
|
bezt++;
|
|
}
|
|
|
|
}
|
|
else {
|
|
if (nu) MEM_freeN(nu);
|
|
if (bezt) MEM_freeN(bezt);
|
|
}
|
|
}
|
|
_data = data;
|
|
} while (ready == 0);
|
|
}
|
|
}
|
|
|
|
return vfd;
|
|
}
|
|
|
|
VFontData *BLI_vfontdata_from_psfont(PackedFile *pf)
|
|
{
|
|
objfnt *fnt= objfnt_from_psfont(pf);
|
|
VFontData *vfd= NULL;
|
|
|
|
if (fnt) {
|
|
vfd= objfnt_to_vfontdata(fnt);
|
|
freeobjfnt(fnt);
|
|
}
|
|
|
|
return vfd;
|
|
}
|