Logo Search packages:      
Sourcecode: blender version File versions

psfont.c

/**
 * $Id: psfont.c,v 1.5 2003/04/26 16:02:22 ton Exp $
 *
 * ***** 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"

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

      /* ObjFnt types */

00055 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: from 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, rest is 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 --; /* for the first time */
                  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;
                                    }
                              }
                        }

                        /* instead of the sidebearing[c1] maybe thesidebearing should be used */

                        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;     /* after IRIX 6.2, scaling went wrong */

      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{
                        /* count first */
                        _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 ((count>0) && last[0] == first[0] && last[1] == first[1]) meet = 1;
                        else meet = 0;

                        /* is there more than 1 unique point ?*/

                        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;

                                    /* read points */
                                    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) {
                                          /* copy handles */
                                          nu->bezt->vec[0][0] = bezt->vec[0][0];
                                          nu->bezt->vec[0][1] = bezt->vec[0][1];
                                          /* and forget last point */
                                          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;
                                    }
                                    
                                    /* forbidden handle combinations */
                                    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;
}

02117 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;
}

Generated by  Doxygen 1.6.0   Back to index