/*
 * VF_Sony.c
 *
 *  Programmmed by Hirotsugu Kakugawa, Hiroshima University
 *  E-Mail:  h.kakugawa@computer.org
 *
 *  Edition History
 *  29 Oct 1993
 *   2 Nov 1993  Added sl, rx, ry, ox, oy, fx, fy capabilities.
 *  12 Nov 1993  Changed x,y reflection, rotation transformation. 
 *  28 Dec 1993  Added VF_GetOutline(), VF_DrawOutine(), VF_FreeOutline().
 *  13 Jan 1994  Added Zenkaku space handling.
 *  15 Jan 1994  Added Primitive Font for less working memory 
 *  20 Jan 1994  Added GetOutline2().
 *  11 Mar 1994  Added #ifdef USE_SONY_FONT ... #endif
 *   8 May 1994  Fixed the bug failing getting bitmap 0x2121 in DrawOutline() 
 *   3 Feb 1995  Bug fix for left slant conversion.
 *   3 Apr 1995  Fixed memory leak.
 *   6 May 1995  Added dynamic opening/closing feature.
 *  23 May 1995  Added range checking of char code.
 *  15 Feb 1996  Fixed a bug in SonyOpenFont().
 *  26 Dec 1997  Changed USE_SONY_FONT => WITH_SONY_FSLIB
 */

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

  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  "config.h"
#include  "defs.h"
#include  "with.h"
#include  "_VF.h"
#include  "VF.h"
#include  "VFcap.h"

#ifdef WITH_SONY_FSLIB 

#include "/usr/sony/include/FS.h"

/* Font */
struct s_font {
  FILE_Port  Port;
  char   *FontFileName; /* ff */
  int    Frame;         /* fr */
  int    Thicken;       /* th */
  int    Rotate;        /* ro */
  int    XReflect;      /* rx */
  int    YReflect;      /* ry */
  int    Slant;         /* sl */
};
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();

Private int    SonyOpenFont();
Private int    SonyCloseFont();


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

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

  fobj = (FontObj*) malloc(sizeof(FontObj));
  fobj->ClassID     = VF_FONT_SONY;
  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->Port = VFFM_InternInt(font->FontFileName, SonyOpenFont, SonyCloseFont);
  return (font->Port >= 0)?0:-1;
}


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

  font = (Font*) fobj->Locals;
  (void) VFFM_UnIntern(font->Port);
  free(font->FontFileName);
  free((char*)fobj->Locals);
  free(fobj);
  return 0;
}


Private int
SonyOpenFont(port, ftp)
     FILE_Port  port;
     fm_tbl     *ftp;
{
  ftp->uu.fd = FS_open_font(ftp->path);
#ifdef DYNAMIC_OPEN_CLOSE_DEBUG
  printf("Sony Open: %s (%d)\n", ftp->path, ftp->uu.fd);
#endif
  return ((ftp->uu.fd) >= 0)?0:-1;
}

Private int
SonyCloseFont(port, ftp)
     FILE_Port  port;
     fm_tbl     *ftp;
{
#ifdef DYNAMIC_OPEN_CLOSE_DEBUG
  printf("Sony Close: %s\n", ftp->path);
#endif
  FS_close_font((int)(ftp->uu.fd)); 
  return 0;
}




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, *sony_vf, *ptr, *ptr2;
  int   f, size, ccode;
  Font  *fobj;

  if (jiscode == 0x2121){
    /* zenkaku space */
    if ((sony_vf = (long*)calloc(1, sizeof(long))) == (long*)NULL)
      return NULL;
    sony_vf[0] = 0L;
  } else if ((0x2122 <= jiscode) && (jiscode <= 0x7424)){
    ccode = (jiscode/0x100 - 0x21)*94 + (jiscode%0x100 - 0x21);
    fobj  = (Font*) obj->Locals;
    f = VFFM_FInt(fobj->Port);
    FS_get_outline(ccode, f, &sony_vf);
    if (sony_vf == NULL)
      return NULL;
    Transformation(sony_vf, fobj);
  } else {
    return NULL;
  }

  size = 2+1;
  for (ptr = sony_vf; *ptr != 0L; ptr++)
    size++;
  if ((vfdata = (long*)calloc(size, sizeof(long))) == NULL){
    free((char*)sony_vf);
    return NULL;
  }

  vfdata[0] = jiscode;
  vfdata[1] = VF_SONY_COORDINATES;
  ptr  = &vfdata[2];
  ptr2 = sony_vf;
  for (;;){
    if ((*(ptr++) = *(ptr2++)) == 0L)
      break;
  }
  free((char*)sony_vf);
  return vfdata;
}



Private long*
GetOutline2(obj, jiscode)
  FontObj  *obj;
  int      jiscode;
{
  return  GetOutline(obj, jiscode);
}



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;
{
  int             val, rast, x, y, yy1, yy2;
  unsigned char   *buff, d;
  Font            *fobj;

  fobj = (Font*) obj->Locals;
  rast = (w+7)/8;
  if ((buff = (unsigned char*) malloc(h*rast)) == NULL)
    return -1; /* ERR: malloc err */ 
  bzero(buff, rast*h);
  val = 0;
  if (vfdata[2] != 0L)
    val = FS_scan_conv(&vfdata[2], w, h, rast, 0, buff, 
		       fobj->Thicken, fobj->Frame, 0);
  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 val;
}

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 void
Transformation(vfdata, fobj)
  long *vfdata;
  Font *fobj;
{
  double  t1, t2, t3, t4, t5, t6, sl;
  int     x, y, x2, y2, x3, y3;
  long    *vfp;

  if (vfdata == NULL){
    fprintf(stderr, "NULL OUTLINE DATA [in Transformation() / VF_Sony.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; 
  }
  
  for (vfp = vfdata; *vfp != (long)0; vfp++){
    if ((*vfp & VFD_TOKEN) == (long)0){
      x = VFD_GET_X(*vfp);    y = VFD_GET_Y(*vfp);
      x = x - D_OFFSET;      y = y - D_OFFSET;
      /* slant */
      x2 = (int) (t1*(double)x + t2*(double)y + t3*D_SIZE);
      y2 = (int) (t4*(double)x + t5*(double)y + t6*D_SIZE);
      /* rotate */
      switch (fobj->Rotate % 4){
      default:
      case 0:  x3 = x2;         y3 = y2;         break;
      case 1:  x3 = D_SIZE-y2;  y3 = x2;         break;
      case 2:  x3 = D_SIZE-x2;  y3 = D_SIZE-y2;  break;
      case 3:  x3 = y2;         y3 = D_SIZE-x2;  break;
      }
      if (x3 < 0)       x3 = 0;
      if (x3 >= D_SIZE) x3 = D_SIZE;
      if (y3 < 0)       y3 = 0;
      if (y3 >= D_SIZE) y3 = D_SIZE;
      x3 = x3 + D_OFFSET;  y3 = y3 + D_OFFSET;
      /* reflect x, y */
      if (fobj->XReflect == 1) 
	x3 = D_RANGE - x3;
      if (fobj->YReflect == 1) 
	y3 = D_RANGE - y3;
      *vfp = VFD_MAKE_XY(x3, y3);
    }
  }
}


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;

  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;

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

#else

/* a dummy */
Public FontObj*
CreateFont_Sony(ent)
{
  return NULL; 
}

#endif /*WITH_SONY_FSLIB*/


/*EOF*/
