/*
 * VF_Zeit.c
 *
 *  Programmmed by Hirotsugu Kakugawa, Hiroshima University
 *  E-Mail:  h.kakugawa@computer.org
 *
 *  Edition History
 *   2 Nov 1993
 *   3 Nov 1993  Added sl, rx, ry, ox, oy, fx, fy capabilities.
 *   4 Nov 1993  Added ro capability.
 *  29 Dec 1993  Added VF_GetOutline(), VF_FreeOutline().
 *  16 Jan 1994  New implementation of Syotai Club Font access routines.
 *  17 Jan 1994  New implementation of GetBitmap(),GetOutline(),DrawOutline()
 *  20 Jan 1994  Added GetOutline2().
 *  21 Jan 1994  Modified low level interface routines to syotai club font.
 *  22 Jan 1994  Improved TraceOutline() and FillEdges().
 *   8 Mar 1994  Fixed small bugs and removed dead code
 *  11 Mar 1994  Changed draw routine.
 *   3 Sep 1994  Changed type declaration of ConvXY() 
 *   3 Feb 1995  Bug fix to the (0,0) point in asiya24 font by Ito Tadashi
 *   3 Feb 1995  Bug fix for left slant conversion.
 *   3 Apr 1995  Fixed memory leak.
 *   6 May 1995  Dynamic Opening/Closing font file feature by H.Kakugawa.
 *  23 May 1995  Added range checking of char code.
 *  20 Nov 1995  Added return value checking of ZeitOpenFont() in OpenFont().
 */


/* This is a part of VFlib
 *
 * Copyright (C) 1993-1998 Hirotsugu KAKUGAWA.   All rights reserved.
 *
 * This file is part of the VFlib Library.  This library is free
 * software; you can redistribute it and/or modify it under the terms of
 * the GNU Library General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your
 * option) any later version.  This library 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 Library General Public License for more details.
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/*
  Capabilities interpretable by zeit font objects:
  "ff"  (str)  --  Font file path  (THIS IS NECESSARY)
  "fr"  (bool) --  Frame font if defined
  "th"  (bool) --  Thicken the char if defined
  "ro"  (num)  --  Rotate the char 90*n degree in clockwise
  "rx"  (bool) --  Reflect about x-axis if defined
  "ry"  (bool) --  Reflect about y-axis if defined
  "sl"  (num)  --  Slant the char n/100

  Corrrection Factors:
  "ox"  (num)  --  Offset for x-axis for vector font data (moved negative dir)
  "oy"  (num)  --  Offset for y-axis for vector font data (moved negative dir)
  "fx"  (num)  --  Factor for x-axis for vector font data
  "fy"  (num)  --  Factor for x-axis for vector font data

  Each point p0=(x0,y0) of vector font data is transformed in the following order:
   1. adding `offset' :  (x1,y1)=(x0-x_offset, y0-y_offset)
   2. magnification by `factor': (x2,y2)=(x1*x_factor, y2*y_factor)
   3. computation of the slant
   3. rotation in clockwise direction
   4. reflection about x-axis
   5. reflection about y-axis
 */


#include  <stdio.h> 
#include  <stdlib.h> 
#include  <string.h> 
#include  <fcntl.h> 
#include  "config.h"
#include  "defs.h"
#include  "_VF.h"
#include  "VF.h"
#include  "VFcap.h"


#define ZEIT_MAX_VALUE       0x0400
#define ZEIT_CODE_SIZE       0x1142
#define ZEIT_HEADER_SIZE     (2+4*ZEIT_CODE_SIZE)


#define CONV_X(x)  \
   ((unsigned int)(OUTLINE_OFFSET+((long)(x)*OUTLINE_SIZE)/ZEIT_MAX_VALUE))
#define CONV_Y(y)  \
   ((unsigned int)(OUTLINE_OFFSET+((long)(y)*OUTLINE_SIZE)/ZEIT_MAX_VALUE))
#define UNCONV_X(x)  \
   ((unsigned int)(ZEIT_MAX_VALUE*((long)(x)-OUTLINE_OFFSET))/OUTLINE_SIZE)
#define UNCONV_Y(y)  \
   ((unsigned int)(ZEIT_MAX_VALUE*((long)(y)-OUTLINE_OFFSET))/OUTLINE_SIZE)

#define END_XY	VFD_MAKE_XY(1023, 1023)

#define  STATIC  static

/* Font */
struct s_font {
  int    PrimFont;
  char   *FontFileName; /* ff */
  int    Frame;         /* fr */
  int    Thicken;       /* th */
  int    Rotate;        /* ro */
  int    XReflect;      /* rx */
  int    YReflect;      /* ry */
  int    Slant;         /* sl */
  int    Xoffset;       /* zxo */
  int    Yoffset;       /* zyo */
  int    Xfactor;       /* zxf */
  int    Yfactor;       /* zyf */
  double MatT1, MatT2, MatT3, MatT4, MatT5, MatT6;
};
typedef struct s_font  Font;


Private int    OpenFont();
Private int    CloseFont();
Private int    GetBitmap();
Private long   *GetOutline();
Private long   *GetOutline2();
Private int    DrawOutline();
Private int    FreeOutline();
Private int    Link();
Private int    Unlink();

int            VF_Draw();

Private int    ReadCapa();
Private int    ZeitOpenFont();
Private int    ZeitCloseFont();
Private long*  ZeitReadOutline();
Private long*  ZeitReadOutline();

Private int    jis2c();
Private void   ConvXY();

Private int            ReadHeader();
Private void           InitBitStream();
Private unsigned long  Read4Bytes();
Private int            Read1Byte();
Private int            Read10Bits();
Private int            CorrectSize();
Private void           Seek();
Private long           CurrentPos();



Public FontObj*
CreateFont_Zeit(ent)
  char *ent;
{
  Font     *font;
  FontObj  *fobj;

  if ((font = (Font*) malloc(sizeof(Font))) == NULL)
    return NULL;  /* ERR: malloc err */
  font->PrimFont = -1;
  if (ReadCapa(font, ent) < 0){
    free(font);
    return NULL;
  }
  
  fobj = (FontObj*) malloc(sizeof(FontObj));
  fobj->ClassID     = VF_FONT_ZEIT;
  fobj->Self        = fobj;
  fobj->LinkCount   = 0;
  fobj->OpenFont    = OpenFont;
  fobj->CloseFont   = CloseFont;
  fobj->GetBitmap   = GetBitmap;
  fobj->GetOutline  = GetOutline;
  fobj->GetOutline2 = GetOutline2;
  fobj->DrawOutline = DrawOutline;
  fobj->FreeOutline = FreeOutline;
  fobj->GetCharSet  = NULL;
  fobj->GetEnc      = NULL;
  fobj->Link        = Link;
  fobj->Unlink      = Unlink;
  fobj->Locals      = (long) font;
  return fobj;
}
       

Private int
OpenFont(fobj)
  FontObj *fobj;
{
  Font        *font;

  font = (Font*) fobj->Locals;
  font->PrimFont = ZeitOpenFont(font->FontFileName);
  if (font->PrimFont < 0)
      return -1;
  return 0;
}


Private int
CloseFont(fobj)
  FontObj  *fobj;
{
  int         val;
  Font        *font;

  font = (Font*) fobj->Locals;
  val = ZeitCloseFont(font->PrimFont);
  free(font->FontFileName);
  free((char*)fobj->Locals);
  free(fobj);
  return val;
}



Private int
GetBitmap(obj, jiscode, w, h, bw, bo, bm_buf)
  FontObj  *obj;
  int   jiscode;
  int   w;
  int   h;
  int   bw;
  int   bo;
  char  *bm_buf;
{
  int  val;
  long *vfdata;

  if ((vfdata = GetOutline(obj, jiscode)) == NULL)
    return -1;
  val = DrawOutline(obj, vfdata, w, h, bw, bo, bm_buf);
  FreeOutline(obj, vfdata);
  return val;
}



Private long*
GetOutline(obj, jiscode)
  FontObj  *obj;
  int      jiscode;
{
  Font   *font;
  int    id, x, y;
  long   *outline, *ptr;

  font = (Font*) obj->Locals;
  id = font->PrimFont;
  if ((outline = ZeitReadOutline(2, jiscode, id)) == NULL)
    return NULL;
  outline[0] = jiscode;
  outline[1] = VF_SONY_COORDINATES;
  for (ptr = &outline[2]; *ptr != END_XY; ptr++){
    if ((*ptr & VFD_TOKEN) == VFD_TOKEN)
      continue;
    ConvXY(&x, &y, (int)VFD_GET_X(*ptr), (int)VFD_GET_Y(*ptr), font);
    *ptr = VFD_MAKE_XY(CONV_X(x), CONV_Y(y));
  }
  *ptr = 0L;
  return outline;
}



Private long*
GetOutline2(obj, jiscode)
  FontObj  *obj;
  int      jiscode;
{
  Font   *font;
  int    id, x, y;
  long   *outline, *ptr;

  font = (Font*) obj->Locals;
  id = font->PrimFont;
  if ((outline = (long*) ZeitReadOutline(2, jiscode, id)) == NULL)
    return NULL;
  outline[0] = jiscode;
  outline[1] = VF_ZEIT_COORDINATES;
  for (ptr = &outline[2]; *ptr != END_XY; ptr++){
    if ((*ptr & VFD_TOKEN) == VFD_TOKEN)
      continue;
    ConvXY(&x, &y, (int)VFD_GET_X(*ptr), (int)VFD_GET_Y(*ptr), font);
    *ptr = VFD_MAKE_XY(x, y);
  }
  *ptr = 0L;
  return outline;
}



Private int
DrawOutline(obj, vfdata, w, h, bw, bo, bm_buf)
  FontObj  *obj;
  long     *vfdata;
  int   w;
  int   h;
  int   bw;
  int   bo;
  char  *bm_buf;
{
  Font          *font;
  unsigned char *buff, d;
  int           rast, x, y, yy1, yy2, val, frame;
  int           thin;

  font = (Font*) obj->Locals;
  rast = (w+7)/8;
  if ((buff = (unsigned char*) malloc(h*rast)) == NULL)
    return -1; /* ERR: malloc err */ 
  bzero(buff, rast*h);

  switch (font->Thicken){
  case 1:    thin = 30; break;
  case 0: 
  default:   thin =  0; break;
  }
  switch (font->Frame){
  case 1:    frame = 1; break;
  case 0: 
  default:   frame = 0; break;
  }
  if ((val = VF_Draw(vfdata, w, h, rast, buff, thin, frame)) < 0){
    free(buff);
    return -1;
  }    

  yy1 = 0;  yy2 = 0;
  for (y = 0; y < h; y++){
    for (x = 0; x < rast; x++){
      d = buff[yy2 + x];
      bm_buf[yy1 + x]   |= d >> bo;
      bm_buf[yy1 + x+1] |= d << (8-bo);
    }
    yy1 += bw;
    yy2 += rast;
  }
  free(buff);
  return 0;
}



Private int
FreeOutline(obj, vfdata)
  FontObj  *obj;
  long     *vfdata;
{
  free((char*) vfdata);
  return 0;
}



Private int
Link(obj)
  FontObj  *obj;
{
  obj->LinkCount = obj->LinkCount + 1;
  return obj->LinkCount;
}



Private int
Unlink(obj)
  FontObj  *obj;
{
  obj->LinkCount = obj->LinkCount - 1;
  return obj->LinkCount;
}



Private int
ReadCapa(font, ent)
  Font *font;
  char *ent;
{
  char *p;
  double sl;

  font->Thicken  = 0;
  font->Frame    = 0;
  font->Slant    = 0;
  font->Rotate   = 0;
  font->XReflect = 0;
  font->YReflect = 0;

  font->Xoffset  = 0;
  font->Yoffset  = 0;
  font->Xfactor  = 100;
  font->Yfactor  = 100; 

  VFC_GetEntry(ent);

  if (VFC_IsDefined(VFCE_THICKEN))
    font->Thicken = 1;
  if (VFC_IsDefined(VFCE_FRAME))
    font->Frame = 1;
  if ((font->Slant = VFC_GetNumber(VFCE_SLANT)) == -1)
    font->Slant = 0;
  sl = font->Slant/100.0; 
  if (sl < 0.0){
    font->MatT1 = 1.0+sl;  font->MatT2 = -sl;   font->MatT3 = 0.0;
  /*font->MatT1 = 1.0+sl;  font->MatT2 = -sl;   font->MatT3 = sl;*/
    font->MatT4 = 0.0;     font->MatT5 = 1.0;   font->MatT6 = 0.0; 
  } else {
    font->MatT1 = 1.0-sl;  font->MatT2 = -sl;   font->MatT3 = sl;
    font->MatT4 = 0.0;     font->MatT5 = 1.0;   font->MatT6 = 0.0; 
  }
  if ((font->Rotate = VFC_GetNumber(VFCE_ROTATE)) == -1)
    font->Rotate = 0;
  if (VFC_IsDefined(VFCE_REF_X))
    font->XReflect = 1;
  if (VFC_IsDefined(VFCE_REF_Y))
    font->YReflect = 1;
  if ((font->Xoffset = VFC_GetNumber(VFCE_XOFFSET)) == -1)
    font->Xoffset = 0;
  if ((font->Yoffset = VFC_GetNumber(VFCE_YOFFSET)) == -1)
    font->Yoffset = 0;
  if ((font->Xfactor = VFC_GetNumber(VFCE_XFACTOR)) == -1)
    font->Xfactor = 100;
  if ((font->Yfactor = VFC_GetNumber(VFCE_YFACTOR)) == -1)
    font->Yfactor = 100;

  font->FontFileName = NULL;
  if ((p = VFC_GetString(VFCE_FONT_FILE)) == NULL)
    return -1;
  if ((font->FontFileName = malloc(strlen(p)+1)) == NULL)
    return -1;  /* ERR: malloc err */
  strcpy(font->FontFileName, p);
  return 0;
}




Private void
ConvXY(xp, yp, x, y, fobj)
  int   *xp, *yp, x, y;
  Font  *fobj;
{
  double tmp_x, tmp_y, xfact, yfact;
  int    xx, yy, xxx, yyy;

  xfact = (double)(fobj->Xfactor)/100.0;
  yfact = (double)(fobj->Yfactor)/100.0;
  tmp_x = (double) (xfact*(x-(fobj->Xoffset)));
  tmp_y = (double) (yfact*(y-(fobj->Yoffset)));
  tmp_x = (((double)tmp_x*(fobj->MatT1)) + ((double)tmp_y*(fobj->MatT2)) 
	   + ((double) ZEIT_MAX_VALUE)*(fobj->MatT3));
  tmp_y = (((double)tmp_x*(fobj->MatT4)) + ((double)tmp_y*(fobj->MatT5))
	   + ((double) ZEIT_MAX_VALUE)*(fobj->MatT6));
  xxx = (int) tmp_x;
  yyy = (int) tmp_y;
  switch (fobj->Rotate % 4){
  default:
  case 0:
    xx = xxx;                    yy = yyy;                    break;
  case 1:    
    xx = ZEIT_MAX_VALUE-1 - yyy; yy = xxx;                    break;
  case 2:
    xx = ZEIT_MAX_VALUE-1 - xxx; yy = ZEIT_MAX_VALUE-1 - yyy; break;
  case 3:
    xx = yyy;                    yy = ZEIT_MAX_VALUE-1 - xxx; break;
  }
  if (fobj->XReflect != 0)  xx = ZEIT_MAX_VALUE-1 - xx;
  if (fobj->YReflect != 0)  yy = ZEIT_MAX_VALUE-1 - yy;
  if (xx < 0) xx = 0;
  if (yy < 0) yy = 0;
  if (xx >= ZEIT_MAX_VALUE) xx = ZEIT_MAX_VALUE-1;
  if (yy >= ZEIT_MAX_VALUE) yy = ZEIT_MAX_VALUE-1;
  *xp = xx; 
  *yp = yy;
}





/***
 *** LOW LEVEL INTERFACE ROUTINES FOR SYOTAI CLUB FONTS
 ***   BY HIROTSUGU KAKUGAWA 1994
 ***/

typedef struct {
  long Offset[ZEIT_CODE_SIZE];
  long Size[ZEIT_CODE_SIZE];
} Header;

struct prim_font {
  FILE_Port  Fd1;     /* Free if NULL_PORT */
  Header     *Header1;
  FILE_Port  Fd2;
  Header     *Header2;
  int        LinkCount;
  char       *FontFileName;   /* ff */
};
typedef struct prim_font  PrimFont;
static PrimFont  PrimFontTable[VF_MAX_ZEIT_FONTS];

#define THRESHOLD_SIZE       0x1000


/* OPEN THE FONT */
Private int
ZeitOpenFont(font)
  char *font;
{
  int     id;
  char	  *fn;
  Private int  inited = 0;

  if (inited == 0){
    for (id = 0; id < VF_MAX_ZEIT_FONTS; id++){
      PrimFontTable[id].Fd1          = NULL_PORT;
      PrimFontTable[id].Header1      = NULL;
      PrimFontTable[id].Fd2          = NULL_PORT;
      PrimFontTable[id].Header2      = NULL;
      PrimFontTable[id].LinkCount    = 0;
      PrimFontTable[id].FontFileName = NULL;
    }
    inited = 1;
  }

  for (id = 0; id < VF_MAX_ZEIT_FONTS; id++){
    /* linear search is sufficient since # of items is small */
    if ((PrimFontTable[id].Fd1 != NULL_PORT) &&
	(strcmp(PrimFontTable[id].FontFileName, font) == 0)){
      PrimFontTable[id].LinkCount++;
      return id;
    }
  }

  for (id = 0; id < VF_MAX_ZEIT_FONTS; id++){
    if (PrimFontTable[id].Fd1 == NULL_PORT)
      break;
  }
  if (id == VF_MAX_ZEIT_FONTS)
    return -1;  /* full */

  if ((PrimFontTable[id].FontFileName = malloc(strlen(font)+1)) == NULL)
    return -1;  /* ERR: malloc err */
  strcpy(PrimFontTable[id].FontFileName, font);

  fn = malloc(strlen(font)+5);
  if (fn == NULL)
    exit(1);

  sprintf(fn, "%s.vf1", font);
  if ((PrimFontTable[id].Fd1 = VFFM_Intern(fn, NULL, NULL)) == NULL_PORT)
    return -1;
  PrimFontTable[id].Header1 = (Header*) malloc(sizeof(Header));
  if (PrimFontTable[id].Header1 == NULL)
    exit(1);
  ReadHeader(PrimFontTable[id].Fd1, PrimFontTable[id].Header1, 0);

  sprintf(fn, "%s.vf2", font);    
  if ((PrimFontTable[id].Fd2 = VFFM_Intern(fn, NULL, NULL)) == NULL_PORT)
    return -1;
  PrimFontTable[id].Header2 = (Header*) malloc(sizeof(Header));
  if (PrimFontTable[id].Header2 == NULL)
    exit(1);
  ReadHeader(PrimFontTable[id].Fd2, PrimFontTable[id].Header2, 1);
  free(fn);
  return id;
}


/* CLOSE THE FONT */
Private int
ZeitCloseFont(id)
  int  id;
{
  if ((--PrimFontTable[id].LinkCount) <= 0){
    VFFM_UnIntern(PrimFontTable[id].Fd1);
    PrimFontTable[id].Fd1 = NULL_PORT;
    VFFM_UnIntern(PrimFontTable[id].Fd2);
    PrimFontTable[id].Fd2 = NULL_PORT;
    free(PrimFontTable[id].Header1);
    free(PrimFontTable[id].Header2);
    free(PrimFontTable[id].FontFileName);
  }
  return PrimFontTable[id].LinkCount;
}


/* READ FONT HEADER */
Private int 
ReadHeader(port, hd, b)
     FILE_Port   port;
     Header      *hd;
     int         b;
{
  int           i, j;
  FILE          *fp;

  fp = VFFM_FStream(port);
  fseek(fp, 0L, 0);
  (void) Read1Byte(fp);
  (void) Read1Byte(fp);
  for (i = 0; i < ZEIT_CODE_SIZE; i++){
    hd->Offset[i] = Read4Bytes(fp);
    /*printf("Ch %04x  Offs %04x\n", c2jis(b, i), hd->Offset[i]);*/
  }
  for (i = 0; i < ZEIT_CODE_SIZE-1; i++){
    if (hd->Offset[i] == 0xffffffff){
      hd->Size[i] = 0;
    } else {
      for (j = i+1; ; j++){
	if (j >= ZEIT_CODE_SIZE){
	  hd->Size[i] = -(THRESHOLD_SIZE+1);
	  break;
	}
	if (hd->Offset[j] != 0xffffffff){
	  hd->Size[i] = -(hd->Offset[j] - hd->Offset[i]);
	  break;
	}
      }
      if (-(hd->Size[i]) > THRESHOLD_SIZE) 
	CorrectSize(i, fp, hd);   /* TOO LARGE. IS THE SIZE CORRECT? */
      /*printf("Ch %04x  Offs %04x  Size %04x\n", 
	     c2jis(b, i), hd->Offset[i], -(hd->Size[i]));*/
    }
  }
  if (hd->Offset[ZEIT_CODE_SIZE-1] == 0xffffffff){
    hd->Size[ZEIT_CODE_SIZE-1] = 0;
  } else {
    hd->Size[ZEIT_CODE_SIZE-1] = -(THRESHOLD_SIZE+1);
    CorrectSize(ZEIT_CODE_SIZE-1, fp, hd);
  }

  return 0;
}

/* CORRECT THE SIZE OF FONT DATA */
Private int
CorrectSize(i, fp, hd)
  int    i;
  FILE   *fp;
  Header *hd;
{
  int   x, y;

  /*printf("Too Large for %04x\n   Size:%04x \n", i, -(hd->Size[i]));*/
  Seek(fp, hd->Offset[i]);
  InitBitStream(fp);
  for (;;){
    x = Read10Bits(fp);  y = Read10Bits(fp);
    /*printf("  x,y = %04d, %04d\n", x, y);*/
    if ((x == 1023) && (y == 1023))
      break;
    for (;;){
      x = Read10Bits(fp);  y = Read10Bits(fp);
      /*printf("  x,y = %04d, %04d\n", x, y);*/
      if ((x == 1023) && (y == 1023))
	break;
    }
  }
  hd->Size[i] = -(CurrentPos(fp) - hd->Offset[i]);
  /*printf("-->  %04x\n", -(hd->Size[i]));*/
  return hd->Size[i];
}


/* GET OUTLINE DATA (IN ZEIT COORDINATES) */
Private long*
ZeitReadOutline(offset, jiscode, id)
  int  offset, jiscode, id;
{
  FILE_Port  port;
  FILE       *fp;
  int        cnt, idx, x, y;
  long       *outline, *sizep, size, chd;
  unsigned int  scode;
  long          offs;

  if (jiscode == 0x2121){
    if ((outline = (long*) malloc((int)(1+offset)*sizeof(long))) == NULL)
      return NULL;
    outline[offset] = END_XY;
    return outline;
  }

  if ((0x2122 <= jiscode) && (jiscode <= 0x7424)){
    scode = jis2c(jiscode);
    if (jiscode < 0x5000){
      port  = PrimFontTable[id].Fd1;   
      offs  = PrimFontTable[id].Header1->Offset[scode];
      sizep = &PrimFontTable[id].Header1->Size[scode];
    } else {
      port  = PrimFontTable[id].Fd2;   
      offs  = PrimFontTable[id].Header2->Offset[scode];
      sizep = &PrimFontTable[id].Header2->Size[scode];
    }
  } else {
    return NULL;
  }

  if (*sizep == 0L)
    return NULL;
  if (*sizep < 0L)
    size = -2*(*sizep) + 2;  /* this is enough ... */
  else
    size = *sizep;
  /*
  printf("  OUTLINE SIZE %5Ld\n", *sizep);
  printf("       ALLOCED %5Ld\n", size);
  */
  if ((outline = (long*) malloc((int)(size+offset)*sizeof(long))) == NULL)
    return NULL;

  cnt = 0;
  idx = offset;
  fp = VFFM_FStream(port);
  Seek(fp, offs);
  InitBitStream(fp);
  chd = VFD_CHAR;
  for (;;){
    x = Read10Bits(fp);  y = Read10Bits(fp);
    if ((x == 1023) && (y == 1023)){
      outline[idx++] = END_XY;    /* END */
      cnt++;
      break;
    } else {
      outline[idx++] = (chd | VFD_CWCURV | VFD_LINE);  /* START */
      outline[idx++] = VFD_MAKE_XY(x, y);  /* X,Y */
      cnt += 2;
      chd = 0L;
    }
    for (;;){
      x = Read10Bits(fp);  y = Read10Bits(fp);
      if ((x == 1023) && (y == 1023))
	break;
      else {
	outline[idx++] = VFD_MAKE_XY(x, y); /* POINT */
	cnt++;
      }
    }
  }
  if (*sizep < 0)
    *sizep = (long) cnt;
  /*
  printf("         SIZE %5Ld\n", *sizep);
  */
  return outline;
}

Private int
jis2c(jis)
  int  jis;
{
  if (jis < 0x5000)
    return (((jis >> 8) & 0xff) - 0x21) * 0x5e + (jis & 0xff) - 0x21;
  else
    return (((jis >> 8) & 0xff) - 0x50) * 0x5e + (jis & 0xff) - 0x21;
}

/* READ 1 BYTE INTEGER */
Private int
Read1Byte(fp)
  FILE *fp; 
{
  return fgetc(fp);
}

/* READ 4 BYTE INTEGER */
Private unsigned long
Read4Bytes(fp)
  FILE *fp;
{
  unsigned long i1, i2, i3, i4;
  
  i1 = (unsigned long) Read1Byte(fp);
  i2 = (unsigned long) Read1Byte(fp);
  i3 = (unsigned long) Read1Byte(fp);
  i4 = (unsigned long) Read1Byte(fp);
  return i1 + i2*0x100 + i3*0x10000 + i4*0x1000000;
}

Private unsigned int   LeftBits  = 0;
Private unsigned long  BitStream = 0;
Private unsigned long  Power2Tbl[] = {
  0x000001,0x000002,0x000004,0x000008,0x000010,0x000020,0x000040,0x000080,
  0x000100,0x000200,0x000400,0x000800,0x001000,0x002000,0x004000,0x008000,
  0x010000,0x020000,0x040000,0x080000,0x100000,0x200000,0x400000,0x800000
}; 

/* INIT BIT STREAM */
Private void
InitBitStream(fp)
  FILE *fp;
{
  BitStream = 0;
  LeftBits  = 0;
}

/* READ 10 BITS INTEGER FROM BIT STREAM */
Private int 
Read10Bits(fp)
  FILE *fp;
{
  if (LeftBits < 10){
    BitStream  *= 0x10000;
    BitStream  += (unsigned int) Read1Byte(fp);
    BitStream  += (unsigned int) Read1Byte(fp) * 0x0100;
    LeftBits   += 16;
  }
  LeftBits -= 10;
  return (BitStream/Power2Tbl[LeftBits]) % ZEIT_MAX_VALUE;
}


/* SEEK TO THE OFFSET FOR FONT DATA */
Private void
Seek(fp, l)
  FILE *fp;
  long l;
{
  fseek(fp, l + ZEIT_HEADER_SIZE, 0);
}

/* RETURN CURRENT OFFSET FOR FONT DATA */
Private long
CurrentPos(fp)
  FILE *fp;
{
  return ftell(fp) - ZEIT_HEADER_SIZE;
}



/* EOF */
