/*
 * 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.
 *  12 Dec 1995  Patches for fonts of Windows95 by I. Matsuda.
 *
 */


/* This file is 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 TrueType 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 degrees in clockwise direction
  "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 (will be subtracted)
  "oy"  (num)  --  Offset for y-axis for vector font data (will be subtracted)
  "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. subtracting `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  <math.h> 
#include  <string.h> 
#include  <fcntl.h> 
#include  "config.h"
#include  "defs.h"
#include  "_VF.h"
#include  "VF.h"
#include  "VFcap.h"



/*
 * 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
**
*/

#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 num_cts;
  int num_pts;
  unsigned short *end_points;
  unsigned char *flags;
  short *xlist;
  short *ylist;
} TTFont;

typedef struct
{
  unsigned short CodeTable;
  unsigned short MaxJIS;
  unsigned short unitsPerEm;
  short xMin;
  short yMin;
  unsigned short maxPoints;
  unsigned short maxContours;
  unsigned long IndexBase;
  unsigned long GlyphBase;
} TT_Header;



struct s_font {
  FILE_Port   Fd1;
  FILE_Port   Fd2;
  TT_Header   ReadHeader;
  char   *FontFileName; /* ff */
  int    Frame;         /* fr */
  int    Thicken;       /* th */
  int    Rotate;        /* ro */
  int    XReflect;      /* rx */
  int    YReflect;      /* ry */
  int    Slant;         /* sl */
  int    Xoffset;       /* xo */
  int    Yoffset;       /* yo */
  int    Xfactor;       /* xf */
  int    Yfactor;       /* yf */
};
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 int    ReadCapa();
Private void   Transformation();

int            VF_Draw();

Private int    TTOpenFont();
Private int    TTCloseFont();
Private TTFont *TTread_font();
Private void   TTfree_font();
Private int    TTread_header();
Private long   TTread_long();
Private int    TTread_short();
Private int    TTseek();
Private int    jis2c();


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

  if ((font = (Font*) malloc(sizeof(Font))) == NULL)
    return NULL;  /* ERR: malloc err */
  font->Fd1 = NULL_PORT;
  font->Fd2 = NULL_PORT;
  if (ReadCapa(font, ent) < 0){
    free(font);
    return NULL;
  }

  fobj = (FontObj*) malloc(sizeof(FontObj));
  fobj->ClassID     = VF_FONT_TT;
  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;
{
  return TTOpenFont((Font*) obj->Locals);
}


Private int
CloseFont(obj)
  FontObj  *obj;
{
  return TTCloseFont((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;
  TTFont    *fontptr;
  int       ct, pt, sp, ep, p1, p2, p3;
  float     x1, y1, x2, y2, x3, y3, UPE;
  long      token;

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

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

  fobj = (Font*) obj->Locals;
  UPE = fobj->ReadHeader.unitsPerEm;
  if((fontptr = TTread_font(fobj, jiscode)) == NULL)
    return NULL;

  vfsize = 0;
  ep = -1;
  for (ct = 0; ct < fontptr->num_cts; ct++) {
    token = 0;
    sp = ep + 1;
    ep = fontptr->end_points[ct];
    for (pt = sp; pt <= ep; pt++) {
      p1 = pt;
      p2 = (p1 < ep)? (p1 + 1) : sp;
      if (fontptr->flags[p1] & fontptr->flags[p2] & ONCURVE) {  /* line */
        if (token != VFD_LINE) {
          token = VFD_LINE;
          vfsize ++;
        }
        vfsize += 1;
      } else {
        if (fontptr->flags[p2] & ONCURVE) continue;
        /* spline */
        if (token != VFD_BEZ) {
          token = VFD_BEZ;
          vfsize ++;
        }
        vfsize += 3;
      }
    }
  }
  if ((vfdata = (long*)malloc((vfsize + 3)*sizeof(long))) == (long*)NULL)
    return NULL;
  vfdata[0] = (long) jiscode; 
  vfdata[1] = (long) VF_SONY_COORDINATES; 

  vfp = &vfdata[2];
  ep = -1;
  for (ct = 0; ct < fontptr->num_cts; ct++) {
    token = (VFD_CHAR | VFD_CWCURV);
    sp = ep + 1;
    ep = fontptr->end_points[ct];
    for (pt = sp; pt <= ep; pt++) {
      p1 = pt;
      p2 = (p1 < ep)? (p1 + 1) : sp;
      p3 = (p2 < ep)? (p2 + 1) : sp;
      if (fontptr->flags[p1] & fontptr->flags[p2] & ONCURVE) {  /* line */
        if (token != VFD_LINE) {
          if (token == (VFD_CHAR | VFD_CWCURV)) {
            *(vfp++) = token | VFD_LINE;
          } else {
            *(vfp++) = VFD_LINE;
          }
          token = VFD_LINE;
        }
        x1 = fontptr->xlist[p1];
        y1 = fontptr->ylist[p1];
        *(vfp++) = VFD_MAKE_XY(ConvX(x1), ConvY(y1));
      } else {
        if (fontptr->flags[p2] & ONCURVE) continue;
        /* spline */
        if (token != VFD_BEZ) {
          if (token == (VFD_CHAR | VFD_CWCURV)) {
            *(vfp++) = token | VFD_BEZ;
          } else {
            *(vfp++) = VFD_BEZ;
          }
          token = VFD_BEZ;
        }
        if (fontptr->flags[p1] & ONCURVE) {
          x1 = (float)fontptr->xlist[p1];
          y1 = (float)fontptr->ylist[p1];
        } else {
          x1 = (float)(fontptr->xlist[p1] + fontptr->xlist[p2]) / 2.0;
          y1 = (float)(fontptr->ylist[p1] + fontptr->ylist[p2]) / 2.0;
        }
        x2 = (float)fontptr->xlist[p2];
        y2 = (float)fontptr->ylist[p2];
        if (fontptr->flags[p3] & ONCURVE) {
          x3 = (float)fontptr->xlist[p3];
          y3 = (float)fontptr->ylist[p3];
        } else {
          x3 = (float)(fontptr->xlist[p2] + fontptr->xlist[p3]) / 2.0;
          y3 = (float)(fontptr->ylist[p2] + fontptr->ylist[p3]) / 2.0;
        }
        /* spline -> bezier */
        *(vfp++) = VFD_MAKE_XY(ConvX(x1), ConvY(y1));
        *(vfp++) = VFD_MAKE_XY(ConvX((x1 + 2.0*x2) / 3.0),
                               ConvY((y1 + 2.0*y2) / 3.0));
        *(vfp++) = VFD_MAKE_XY(ConvX((2.0*x2 + x3) / 3.0),
                               ConvY((2.0*y2 + y3) / 3.0));
      }
    }
  }
  *(vfp++) = (long)0;
  TTfree_font(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;

  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->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 ((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_TT.c]\n");
    abort();
  }

  /* 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){
      default:
      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 Access Routines
 *     by I.Matsuda
 **************************************************/


Private int
TTOpenFont(fobj)
  Font*  fobj;
{
  FILE_Port   wfd1, wfd2;
  TT_Header   header;
  char	      *the_name, *fn, *ext;

  if ((the_name = malloc(strlen(fobj->FontFileName)+1)) == NULL)
    return -1;  /* ERR: malloc err */
  if ((fn = malloc(strlen(fobj->FontFileName)+10)) == NULL){
    free(the_name);
    return -1;  /* ERR: malloc err */
  }
  strcpy(the_name, fobj->FontFileName);
  
  strcpy(fn, fobj->FontFileName);
  ext = fn + strlen(fn);
  strcpy(ext, ".ttf");
  if ((wfd1 = VFFM_Intern(fn, NULL, NULL)) == NULL_PORT){
    strcpy(ext, ".ttc");
    if ((wfd1 = VFFM_Intern(fn, NULL, NULL)) == NULL_PORT){
      free(fn); free(the_name);
      return -1;
    }
  }
  strcpy(ext, ".tti");
  if ((wfd2 = VFFM_Intern(fn, NULL, NULL)) == NULL_PORT){
    free(fn); free(the_name);
    return -1;
  }
  free(fn);
  TTread_header(wfd2, &header);
  
  fobj->FontFileName = the_name;
  fobj->Fd1          = wfd1;
  fobj->Fd2          = wfd2;
  fobj->ReadHeader   = header;

  return 0;
}


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

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

Private int 
TTread_header(fport, hptr)
  FILE_Port fport;
  TT_Header *hptr;
{
  FILE  *fp;

  fp = VFFM_FStream(fport);
  fseek(fp, 0, 0);
  hptr->CodeTable    = TTread_short(fp);
  hptr->MaxJIS       = TTread_short(fp);
  hptr->unitsPerEm   = TTread_short(fp);
  hptr->xMin         = TTread_short(fp);
  hptr->yMin         = TTread_short(fp);
  hptr->maxPoints    = TTread_short(fp);
  hptr->maxContours  = TTread_short(fp);
  hptr->IndexBase    = TTread_long(fp);
  hptr->GlyphBase    = TTread_long(fp);
  
  return 0;
}


Private TTFont* 
TTread_font(fobj, code)
  Font *fobj;
  int  code;
{

  static TTFont ttfont;

  int   code_offset;
  int   i, j, UPE;
  short cp;
  FILE  *fp;
  
  code_offset = jis2c(code);
  if ((code < 0x2122) || (0x7c7e < code)){
    return NULL;
  }

  if ((code >> 8) - 0x21 >= fobj->ReadHeader.MaxJIS)
    return NULL;
  if (TTseek(fobj, code_offset) < 0)
    return NULL;
  
  fp = VFFM_FStream(fobj->Fd1);
  UPE = fobj->ReadHeader.unitsPerEm;
  ttfont.num_cts = TTread_short(fp);	/* number of contours */
  if (ttfont.num_cts > fobj->ReadHeader.maxContours)
    return NULL;	/* error check */
  fseek(fp, 8, 1);	/* ignore 8 bytes */
  if ((ttfont.end_points = (unsigned short *)
    malloc(sizeof(short) * ttfont.num_cts)) == NULL)
      return NULL;
  for (i = 0; i < ttfont.num_cts; i++) {
    ttfont.end_points[i] = TTread_short(fp);
  }
  ttfont.num_pts = ttfont.end_points[ttfont.num_cts - 1] + 1;
  if (ttfont.num_pts > fobj->ReadHeader.maxPoints)
    return NULL;	/* error check */
  i = TTread_short(fp);
  fseek(fp, i, 1);	/* ignore instruction code */
  if ((ttfont.flags = (unsigned char *)
    malloc(sizeof(char) * ttfont.num_pts)) == NULL)
      return NULL;
  if ((ttfont.xlist = (short *)
    malloc(sizeof(short) * ttfont.num_pts)) == NULL)
      return NULL;
  if ((ttfont.ylist = (short *)
    malloc(sizeof(short) * ttfont.num_pts)) == NULL)
      return NULL;
  
  /* read flags */
  for (i = 0; i < ttfont.num_pts; i++) {
    ttfont.flags[i] = getc(fp);
      if (ttfont.flags[i] & REPEAT_FLAGS) {
      for (j = (unsigned char)getc(fp); j > 0; j--, i++) {
        ttfont.flags[i + 1] = ttfont.flags[i];
      }
    }
  }
  /* read x_list */
  cp = -fobj->ReadHeader.xMin;
  for (i = 0; i < ttfont.num_pts; i++) {
    if (ttfont.flags[i] & XSHORT) {
      if (ttfont.flags[i] & SHORT_X_IS_POS) {
        cp += (unsigned char)getc(fp);
      } else {
        cp -= (unsigned char)getc(fp);
      }
    } else {
      if (!(ttfont.flags[i] & NEXT_X_IS_ZERO)) {
        cp += TTread_short(fp);
      }
    }
    ttfont.xlist[i] = cp;
  }
  /* read y_list */
  cp = -fobj->ReadHeader.yMin;
  for (i = 0; i < ttfont.num_pts; i++) {
    if (ttfont.flags[i] & YSHORT) {
      if (ttfont.flags[i] & SHORT_Y_IS_POS) {
        cp += (unsigned char)getc(fp);
      } else {
        cp -= (unsigned char)getc(fp);
      }
    } else {
      if (!(ttfont.flags[i] & NEXT_Y_IS_ZERO)) {
        cp += TTread_short(fp);
      }
    }
    ttfont.ylist[i] = UPE - cp;
  }
#if 0
    for (i = j = 0; i < ttfont.num_pts; i++) {
    printf("!%3d %s(%d, %d)\n", i, (ttfont.flags[i] & ONCURVE)? "*" : " ",
    ttfont.xlist[i], ttfont.ylist[i]);
    if (i == ttfont.end_points[j]) {
      j++;
      printf("--------\n");
    }
  }
#endif
  
  return (&ttfont);
}


Private void 
TTfree_font(ptr)
  TTFont *ptr;
{
  free(ptr->end_points);
  free(ptr->flags);
  free(ptr->xlist);
  free(ptr->ylist);
}


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

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


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

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


Private int
TTseek(fobj, code_offset)
  Font *fobj;
  int code_offset;
{
  unsigned short gindex;
  unsigned long glyph_offset;
  FILE  *fd1, *fd2;

  /* code_offset -> glyph index */
  fd2 = VFFM_FStream(fobj->Fd2);
  fseek(fd2, fobj->ReadHeader.CodeTable + code_offset * 2L, 0);
  if((gindex = TTread_short(fd2)) == 0)
    return (-1);	/* no glyph index */

  /* glyph index -> offset */
  fd1 = VFFM_FStream(fobj->Fd1);
  fseek(fd1, fobj->ReadHeader.IndexBase + gindex * 4L, 0);
  glyph_offset = TTread_long(fd1);
  /* seek to glyph data */
  fseek(fd1, fobj->ReadHeader.GlyphBase + glyph_offset, 0);
  return (0);
}


Private int
jis2c(code)
  int  code;
{
  int  zscode;
  
  zscode = (((code >> 8) & 0xff) - 0x21) * 0x5e + (code & 0xff) - 0x21;
  
  return zscode;
}

/* EOF */
