/*
 * VF_FNTWV.c
 *
 *  Programmed by Ein Terakawa, The University of Tokyo
 *  E-Mail:  t50942@hongo.ecc.u-tokyo.ac.jp
 *
 *  Edition History (VF_FNTWV.c)
 *  14 Feb 1997 Programmed by E.Terakawa, modifiying VF_TT.c.
 *
 * VF_TT.c
 *
 *  Programmmed by Hirotsugu Kakugawa, Hiroshima University
 *  E-Mail:  h.kakugawa@computer.org
 *
 *  Edition History (VF_Zeit.c)
 *   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().
 *
 *  Edition History (VF_TT.c)
 *  19 Jan 1994  Modified for TrueType font by I. Matsuda.
 *  20 Jan 1994  Added GetOutline2() by H.Kakugawa.
 *   4 Mar 1994  Bug fix (outline size) by T. Shimizu.
 *   3 Feb 1995  Bug fix for left slant conversion by H.Kakugawa.
 *   6 May 1995  Changed to call VF_Draw() to draw outline by H.Kakugawa.
 *   6 May 1995  Dynamic Opening/Closing font file feature by H.Kakugawa.
 *  23 May 1995  Added range checking of char code.
 *
 */


/* 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
  "rv"  (bool) --  Reverse black and white

  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. added `offset' :  (x1,y1)=(x0-x_offset, y0-y_offset) 
   2. maginification by `factor': (x2,y2)=(x1*x_factor, y2*y_factor)
   3. slanted
   3. rotate in clockwise direction
   4. reflect about x-axis
   5. reflect about y-axis
 */


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

#ifndef SEEK_SET
#  define SEEK_SET 0
#endif

/*
 * UNPACKING Constants
*/
#define ONCURVE             0x01
#define XSHORT              0x02
#define YSHORT              0x04
#define REPEAT_FLAGS        0x08 /* repeat flag n times */
/* IF XSHORT */
#define SHORT_X_IS_POS      0x10 /* the short vector is positive */
/* ELSE */
#define NEXT_X_IS_ZERO      0x10 /* the relative x coordinate is zero */
/* ENDIF */
/* IF YSHORT */
#define SHORT_Y_IS_POS      0x20 /* the short vector is positive */
/* ELSE */
#define NEXT_Y_IS_ZERO      0x20 /* the relative y coordinate is zero */
/* ENDIF */
/* 0x40 & 0x80              RESERVED
** Set to Zero
**
*/

/* from FS.h */
#define	D_RANGE		32768
#define	D_SIZE		8192
#define	D_OFFSET	((D_RANGE - D_SIZE) / 2)

typedef char    *BUFFER;
typedef double  floatp;

typedef struct
{
  int x, y;
} Point;



typedef struct
{
  int NumberOfChars;
  int SizeX,SizeY;
  int DataStartAddress;
  int  *FirstByteTable;
  char *SecondByteTable;
  long *AddressTable;
} FNTWV_Header;


struct s_font {
  FILE_Port   Fd;
  FNTWV_Header   Header;
  char   *FontFileName; /* ff */
  int    Frame;         /* fr */
  int    Thicken;       /* th */
  int    Rotate;        /* ro */
  int    XReflect;      /* rx */
  int    YReflect;      /* ry */
  int    Reverse;       /* rv */
  int    Slant;         /* sl */
  int    Xoffset;       /* xo */
  int    Yoffset;       /* yo */
  int    Xfactor;       /* xf */
  int    Yfactor;       /* yf */
  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();

Private void   Transformation();
Private char  *FNTWVread_font();
Private int    FNTWVread_header();
Private int    read_word();
Private long   read_long();



Public FontObj*
CreateFont_FontWave(ent)
  char *ent;
{
  Font     *font;
  FontObj  *fobj;
  Private int  ReadCapa();

  if ((font = (Font*) malloc(sizeof(Font))) == NULL){
    printf("in CreateFont malloc() Error!\n");
    return NULL;  /* ERR: malloc err */
  }
  font->Fd = NULL_PORT;
  if (ReadCapa(font, ent) < 0){
    printf("ReadCapa() Error!\n");
    free(font);
    return NULL;
  }

  fobj = (FontObj*) malloc(sizeof(FontObj));
  fobj->ClassID     = VF_FONT_FONTWAVE;
  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(obj)
  FontObj *obj;
{
  Private int   FNTWVOpenFont();

  return FNTWVOpenFont((Font*) obj->Locals);
}


Private int
CloseFont(obj)
  FontObj  *obj;
{
  Private int   FNTWVCloseFont();

  return FNTWVCloseFont((Font*) obj->Locals);
}


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;
{
  long      *vfdata, *vfp;
  int       vfsize;
  Font      *fobj;
  unsigned char *fontptr;
  int       i,c;
  int       d1,d2,d3,d4,d5,d6,d7,d8,d9;
  float     x0,y0,x1,y1,x2,y2,x3,y3, sizex,sizey;
  long      token;

#define ConvX(x)  \
   ((unsigned int)(OUTLINE_OFFSET+((float)((x)*OUTLINE_SIZE)/sizex)))
#define ConvY(y)  \
   ((unsigned int)(OUTLINE_OFFSET+((float)((y)*OUTLINE_SIZE)/sizey)))


  if (jiscode == 0x2121){
    if ((vfdata = (long*)malloc(3*sizeof(long))) == (long*)NULL)
      return NULL;
    vfdata[0] = (long) jiscode; 
    vfdata[1] = (long) VF_SONY_COORDINATES; 
    vfdata[2] = (long) 0; 
    return (long*) vfdata;
  }

  x0 = y0 = -100000.0;  /* junk value, as init */ 

  fobj = (Font*) obj->Locals;
  sizex=fobj->Header.SizeX;
  sizey=fobj->Header.SizeY;
  if((fontptr = (unsigned char*)FNTWVread_font(fobj, jiscode)) == NULL){
    if ((vfdata = (long*)malloc(3*sizeof(long))) == (long*)NULL)
      return NULL;
    vfdata[0] = (long) jiscode; 
    vfdata[1] = (long) VF_SONY_COORDINATES; 
    vfdata[2] = (long) 0; 
    return (long*) vfdata;
  }


  vfsize = 2;
  i=0;
  token=-1;
  do{
    c=fontptr[i++];
    switch(c){
    case 0xf:
      /* END of Character*/
      if(token!=1)vfsize++;
      vfsize+=2;
      break;
    case 0x2:
    case 0x12:
    case 0x82:
    case 0x92:
      /* NewPath */
      if(token!=-1){
	vfsize++;
	if(token!=1)vfsize++;
      }
      token=0;
      i+=3;
      break;
    case 0x3:
      /* AbsoluteLine8bit */
    case 0xa:
      /* RelativeLine8bit */
      if(token!=1){
	vfsize++;
	token=1;
      }
      vfsize++;
      i+=2;
      break;
    case 0x4:
      /* AbsoluteCurve8bit */
    case 0xb:
      /* RelativeCurve8bint */
      if(token!=2){
	vfsize++;
	token=2;
      }
      vfsize+=3;
      i+=6;
      break;
    case 0x13:
      /* AbsoluteLine12bit */
    case 0x1a:
      /* RelativeLine12bit */
      if(token!=1){
	vfsize++;
	token=1;
      }
      vfsize++;
      i+=3;
      break;
    case 0x14:
      /* AbsoluteCurve12bit */
    case 0x1b:
      /* RelativeCurve12bit */
      if(token!=2){
	vfsize++;
	token=2;
      }
      vfsize+=3;
      i+=9;
      break;
    }
  }while(c!=0xf);


  if((vfdata=(long*)malloc(vfsize*4))==NULL){
    free(fontptr);
    return NULL;
  }

  vfdata[0] = (long) jiscode; 
  vfdata[1] = (long) VF_SONY_COORDINATES; 

  vfp = &vfdata[2];
  i=0;
  token=-1;
  while(token!=-2){
    switch(fontptr[i++]){
    case 0x2:
    case 0x12:
    case 0x82:
    case 0x92:
      /* NewPath */
      if(token!=-1){
	if(token!=1)*(vfp++)=VFD_LINE;
	*(vfp++)=VFD_MAKE_XY(ConvX(x0),ConvY(y0));
      }
      d1=fontptr[i++];d2=fontptr[i++];d3=fontptr[i++];
      x0=(d1 / 16)*0x100 + d2; y0=(d1 % 16)*0x100 + d3;
      token=0;
      break;
    case 0x3:
      /* AbsoluteLine8bit */
      x1=fontptr[i++];y1=fontptr[i++];
      if(token==0)*(vfp++)=VFD_CHAR|VFD_CWCURV|VFD_LINE;
      if(token==2)*(vfp++)=VFD_LINE;
      token=1;
      *(vfp++)=VFD_MAKE_XY(ConvX(x0),ConvY(y0));
      x0=x1;y0=y1;
      break;
    case 0x4:
      /* AbsoluteCurve8bit */
      x1=fontptr[i++];y1=fontptr[i++];
      x2=fontptr[i++];y2=fontptr[i++];
      x3=fontptr[i++];y3=fontptr[i++];
      if(token==0)*(vfp++)=VFD_CHAR|VFD_CWCURV|VFD_BEZ;
      if(token==1)*(vfp++)=VFD_BEZ;
      token=2;
      *(vfp++)=VFD_MAKE_XY(ConvX(x0),ConvY(y0));
      *(vfp++)=VFD_MAKE_XY(ConvX(x1),ConvY(y1));
      *(vfp++)=VFD_MAKE_XY(ConvX(x2),ConvY(y2));
      x0=x3;y0=y3;
      break;
    case 0xa:
      /* RelativeLine8bit */
      x1=x0+fontptr[i++]-128; y1=y0+fontptr[i++]-128;
      if(token==0)*(vfp++)=VFD_CHAR|VFD_CWCURV|VFD_LINE;
      if(token==2)*(vfp++)=VFD_LINE;
      token=1;
      *(vfp++)=VFD_MAKE_XY(ConvX(x0),ConvY(y0));
      x0=x1;y0=y1;
      break;
    case 0xb:
      /* RelativeCurve8bit */
      x1=x0+fontptr[i++]-128; y1=y0+fontptr[i++]-128;
      x2=x0+fontptr[i++]-128; y2=y0+fontptr[i++]-128;
      x3=x0+fontptr[i++]-128; y3=y0+fontptr[i++]-128;
      if(token==0)*(vfp++)=VFD_CHAR|VFD_CWCURV|VFD_BEZ;
      if(token==1)*(vfp++)=VFD_BEZ;
      token=2;
      *(vfp++)=VFD_MAKE_XY(ConvX(x0),ConvY(y0));
      *(vfp++)=VFD_MAKE_XY(ConvX(x1),ConvY(y1));
      *(vfp++)=VFD_MAKE_XY(ConvX(x2),ConvY(y2));
      x0=x3;y0=y3;
      break;
    case 0x13:
      /* AbsoluteLine12bit */
      d1=fontptr[i++];d2=fontptr[i++];d3=fontptr[i++];
      x1=(d1 / 16)*0x100 + d2; y1=(d1 % 16)*0x100 + d3;
      if(token==0)*(vfp++)=VFD_CHAR|VFD_CWCURV|VFD_LINE;
      if(token==2)*(vfp++)=VFD_LINE;
      token=1;
      *(vfp++)=VFD_MAKE_XY(ConvX(x0),ConvY(y0));
      x0=x1;y0=y1;
      break;
    case 0x14:
      /* AbsoluteCurve12bit */
      d1=fontptr[i++];d2=fontptr[i++];d3=fontptr[i++];
      d4=fontptr[i++];d5=fontptr[i++];d6=fontptr[i++];
      d7=fontptr[i++];d8=fontptr[i++];d9=fontptr[i++];
      x1=(d1 / 16)*0x100+d2; y1=(d1 % 16)*0x100+d3;
      x2=(d4 / 16)*0x100+d5; y2=(d4 % 16)*0x100+d6;
      x3=(d7 / 16)*0x100+d8; y3=(d7 % 16)*0x100+d9;
      if(token==0)*(vfp++)=VFD_CHAR|VFD_CWCURV|VFD_BEZ;
      if(token==1)*(vfp++)=VFD_BEZ;
      token=2;
      *(vfp++)=VFD_MAKE_XY(ConvX(x0),ConvY(y0));
      *(vfp++)=VFD_MAKE_XY(ConvX(x1),ConvY(y1));
      *(vfp++)=VFD_MAKE_XY(ConvX(x2),ConvY(y2));
      x0=x3;y0=y3;
      break;
    case 0x1A:
      /* RelativeLine12bit */
      d1=fontptr[i++];d2=fontptr[i++];d3=fontptr[i++];
      x1=(d1 / 16)*0x100+d2+x0-2048;
      y1=(d1 % 16)*0x100+d3+y0-2048;
      if(token==0)*(vfp++)=VFD_CHAR|VFD_CWCURV|VFD_LINE;
      if(token==2)*(vfp++)=VFD_LINE;
      token=1;
      *(vfp++)=VFD_MAKE_XY(ConvX(x0),ConvY(y0));
      x0=x1;y0=y1;
      break;
    case 0x1B:
      /* RelativeCurve12bit */
      d1=fontptr[i++];d2=fontptr[i++];d3=fontptr[i++];
      d4=fontptr[i++];d5=fontptr[i++];d6=fontptr[i++];
      d7=fontptr[i++];d8=fontptr[i++];d9=fontptr[i++];
      x1=(d1 / 16)*0x100+d2+x0-2048;
      y1=(d1 % 16)*0x100+d3+y0-2048;
      x2=(d4 / 16)*0x100+d5+x0-2048;
      y2=(d4 % 16)*0x100+d6+y0-2048;
      x3=(d7 / 16)*0x100+d8+x0-2048;
      y3=(d7 % 16)*0x100+d9+y0-2048;
      if(token==0)*(vfp++)=VFD_CHAR|VFD_CWCURV|VFD_BEZ;
      if(token==1)*(vfp++)=VFD_BEZ;
      token=2;
      *(vfp++)=VFD_MAKE_XY(ConvX(x0),ConvY(y0));
      *(vfp++)=VFD_MAKE_XY(ConvX(x1),ConvY(y1));
      *(vfp++)=VFD_MAKE_XY(ConvX(x2),ConvY(y2));
      x0=x3;y0=y3;
      break;
    case 0xf:
      /* ENDofCharacter */
      if(token!=-1){
	if(token!=1)*(vfp++)=VFD_LINE;
	*(vfp++)=VFD_MAKE_XY(ConvX(x0),ConvY(y0));
      }
      *(vfp++)=(long)0;
      token=-2;
      break;
    default:
      printf("ERROR! in GetOutline of VF_FNTWV.c\n");
      printf("  認識できないコマンドです。 %02X\n",fontptr[i-1]);
      exit(-1);
    }
  }
  free(fontptr);
  Transformation(&vfdata[2], fobj);

  return (long*) vfdata;
}


Private long*
GetOutline2(obj, jiscode)
  FontObj  *obj;
  int      jiscode;
{
  return NULL;  /* NOT IMPLEMENTED */
}


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;
  int           VF_Draw();

  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(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;

  font->Thicken  = 0;
  font->Frame    = 0;
  font->Slant    = 0;
  font->Rotate   = 0;
  font->XReflect = 0;
  font->YReflect = 0;
  font->Reverse  = 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;
  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 (VFC_IsDefined(VFCE_REVERSE))
    font->Reverse = 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;

  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
Transformation(vfdata, fobj)
  long *vfdata;
  Font *fobj;
{
  double  t1, t2, t3, t4, t5, t6, sl;
  double tmp_x, tmp_y, xfact, yfact;
  int     x, y, x2, y2, xoffset, yoffset;
  long    *vfp;

  if (vfdata == NULL){
    fprintf(stderr, "NULL OUTLINE DATA [in Transformation() / VF_FNTWV.c]\n");
    abort();
  }

  x2 = y2 = -100000.0;  /* junk value, as init */ 

  /* Slant */
  sl = fobj->Slant/100.0; 
  if (sl < 0.0){
    t1 = 1.0+sl; t2 = -sl; t3 =0.0; t4 = 0.0; t5 = 1.0; t6 = 0.0; 
  } else {
    t1 = 1.0-sl; t2 = -sl; t3 = sl; t4 = 0.0; t5 = 1.0; t6 = 0.0; 
  }
  xfact = (double)(fobj->Xfactor)/100.0;
  yfact = (double)(fobj->Yfactor)/100.0;
  xoffset = D_OFFSET + fobj->Xoffset;
  yoffset = D_OFFSET + fobj->Yoffset;
  
  for (vfp = vfdata; *vfp != (long)0; vfp++){
    if ((*vfp & VFD_TOKEN) == (long)0){
      tmp_x = xfact * (double)(VFD_GET_X(*vfp) - xoffset);
      tmp_y = yfact * (double)(VFD_GET_Y(*vfp) - yoffset);
      
      /* slant */
      x = (int)(t1 * tmp_x + t2 * tmp_y + t3 * D_SIZE);
      y = (int)(t4 * tmp_x + t5 * tmp_y + t6 * D_SIZE);
      /* rotate */
      switch (fobj->Rotate % 4){
      case 0:  x2 = x;         y2 = y;         break;
      case 1:  x2 = D_SIZE-y;  y2 = x;         break;
      case 2:  x2 = D_SIZE-x;  y2 = D_SIZE-y;  break;
      case 3:  x2 = y;         y2 = D_SIZE-x;  break;
      }
      if (x2 < 0)       x2 = 0;
      if (x2 >= D_SIZE) x2 = D_SIZE;
      if (y2 < 0)       y2 = 0;
      if (y2 >= D_SIZE) y2 = D_SIZE;
      x2 += D_OFFSET;   y2 += D_OFFSET;
      /* reflect x, y */
      if (fobj->XReflect == 1) 
	x2 = D_RANGE - x2;
      if (fobj->YReflect == 1) 
	y2 = D_RANGE - y2;
      *vfp = VFD_MAKE_XY(x2, y2);
    }
  }
}




/***************************************************
 * TrueType Font Accsess Routines
 *     by I.Matsuda
 **************************************************/


Private int
FNTWVOpenFont(fobj)
  Font*  fobj;
{
  FILE_Port   wfd1,wfd2;
  FNTWV_Header   header;
  char *fn;

  if ((fn = malloc(strlen(fobj->FontFileName)+10)) == NULL){
    printf("in FNTWVread_header() malloc() Error.\n");
    return -1;  /* ERR; malloc err */
  }
  
  sprintf(fn, "%s.fws", fobj->FontFileName);
  if ((wfd1 = VFFM_Intern(fn, NULL, NULL)) == NULL_PORT){
    free(fn);
    printf("Error! in FNTWVread_header() VFFM_Intern().\n");
    printf("  Couldn't Open FontFile!\n");
    return -1;
  }
  sprintf(fn, "%s.fwi", fobj->FontFileName);
  if ((wfd2 = VFFM_Intern(fn, NULL, NULL)) == NULL_PORT){
    free(fn);
    VFFM_UnIntern(wfd1);
    printf("Error! in FNTWVread_header() VFFM_Intern().\n");
    printf("  Couldn't Open IndexFile!\n");
    return -1;
  }
  free(fn);
  if(FNTWVread_header(wfd1,wfd2, &header)<0){
    VFFM_UnIntern(wfd1);
    VFFM_UnIntern(wfd2);
    printf("FNTWVread_header() Error.\n");
    return(-1);
  }
  
  VFFM_UnIntern(wfd2);
  fobj->Fd           = wfd1;
  fobj->Header       = header;

  return 0;
}


Private int
FNTWVCloseFont(fobj)
  Font *fobj;
{
  if (fobj->FontFileName == NULL)
    return -1;

  free(fobj->FontFileName);
  fobj->FontFileName = NULL;
  VFFM_UnIntern(fobj->Fd);
  fobj->Fd = NULL_PORT;
  return 0;
}

Private int 
FNTWVread_header(fport1,fport2, hptr)
  FILE_Port fport1,fport2;
  FNTWV_Header *hptr;
{
  int   i;
  FILE  *fp;
  char  ID[9];

  fp=VFFM_FStream(fport1);
  fseek(fp, 0, 0);
  for(i=0;i<8;i++)ID[i]=getc(fp);
  ID[8]=0;
  if(strcmp(ID,"FontWave")!=0){
    printf("in FNTWVread_header() Header Error.\n");
    return -1;
  }
  fp=VFFM_FStream(fport2);
  fseek(fp,0,0);
  for(i=0;i<8;i++)ID[i]=getc(fp);
  ID[8]=0;
  if(strcmp(ID,"FW_INDEX")!=0){
    printf("in FNTWVread_header() Header Error! .fwi\n");
    return -1;
  }
  fp=VFFM_FStream(fport1);
  fseek(fp,FWS_BOUNDING_BOX,0);
  hptr->SizeX=read_word(fp);
  hptr->SizeY=read_word(fp);
  fp=VFFM_FStream(fport2);
  fseek(fp,FWI_NUMBER_OF_CHARS,0);
  hptr->NumberOfChars= read_word(fp);
  fseek(fp,FWI_FONT_DATA_START,0);
  hptr->DataStartAddress=read_long(fp);
  if( (hptr->FirstByteTable=(int*)malloc(0xc0*sizeof(int)))==NULL){
    printf("FirstByteTable malloc() Error!\n");
    return -1;
  }
  if( (hptr->SecondByteTable=malloc(hptr->NumberOfChars))==NULL){
    printf("SecondByteTable malloc() Error!\n");
    free(hptr->FirstByteTable);
    return(-1);
  }
  if( (hptr->AddressTable=(long*)malloc(hptr->NumberOfChars*4))==NULL){
    printf("AddressTable malloc() Error!\n");
    free(hptr->SecondByteTable);
    free(hptr->FirstByteTable);
    return(-1);
  }
  fseek(fp,FWI_TABLE1_START,SEEK_SET);
  fseek(fp,read_long(fp),SEEK_SET);
  for(i=0;i<0xc0;i++)hptr->FirstByteTable[i]=read_word(fp);
  fseek(fp,FWI_TABLE2_START,SEEK_SET);
  i=read_long(fp);
  fp=VFFM_FStream(fport1);
  fseek(fp,i,SEEK_SET);
  for(i=0;i<hptr->NumberOfChars;i++){
    hptr->SecondByteTable[i]=getc(fp);
    hptr->AddressTable[i]=read_long(fp);
  }
  return 0;
}

Private char *
FNTWVread_font(fobj,code)
     Font *fobj;
     int code;
     
{
  int *fbtbl;
  char *sbtbl;
  long *adrtbl;
  int count,start;
  int flag;
  int size;
  int i;
  char *fontdata;
  FILE *fp;

  fp = VFFM_FStream(fobj->Fd);
  fbtbl=fobj->Header.FirstByteTable;
  sbtbl=fobj->Header.SecondByteTable;
  adrtbl=fobj->Header.AddressTable;
  count=fbtbl[((code>>8)-0x20)*2+1];
  start=fbtbl[((code>>8)-0x20)*2]-1;
  flag=0;	      
  for(i=start;i<start+count;i++){
    if(sbtbl[i]==(code & 0xff)){
      flag=1;
      break;
    }
  }
  if(flag==0)return NULL;

  fseek(fp,fobj->Header.DataStartAddress+adrtbl[i]+2,0);
  size=read_word(fp);
  if((fontdata=malloc(size-2))==NULL)return NULL;
  for(i=0;i<size-2;i++)fontdata[i]=getc(fp);
  return fontdata;
}




Private int
read_word(fp)
  FILE *fp;
{
  char c[2];
  short num;

  c[0]=getc(fp);
  c[1]=getc(fp);
  num = (c[1]<<8)|(c[0] & 0xff);
  return (num);
}

Private long
read_long(fp)
  FILE *fp;
{
  short c[2];
  long num;

  c[0]=read_word(fp);
  c[1]=read_word(fp);
  num=(c[1]<<16)|(c[0] & 0xffff);
  return (num);
}




/* EOF */
