/*
 * VF_Hbf.c
 *
 *  Programmmed by Werner Lemberg
 *  E-Mail:  a7621gac@awiuni11.bitnet
 *
 *  Edition History
 *    1 Apr 1996  First version.
 */

/*
 * Use bitmap font in HBF format.
 * This font driver also generates outline data from bitmaps.
 * Quality is poor since the source is a bitmap font, but 
 * you can get the font files for free!
 * 
 * This module assumes that all characters in a font file have the 
 * same size; variable width fonts are not supported. 
 *
 * This code is heavily based on VF_Bdf.c .
 */

/* This file is part of VFlib
 *
 * Copyright (C) 1995-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 HBF objects:
  "ff"  (str)  --  Font file path  (THIS IS NECESSARY)
  "en"  (str)  --  Font encoding (optional).
                   If defined, encoding must be identical with the value
                   in the HBF header file.
  "cs"  (str)  --  Font character set (optional).
                   If defined, character set must be identical with the
                   value in the HBF header file.
  "dz"  (num)  --  Dot size factor for each dot. 0(small)...100(full) 
  "ds"  (str)  --  Shape of dots. "square" (default) or "diamond" 
  "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. subtraction of `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  <ctype.h> 
#include  "config.h"
#include  "defs.h"
#include  "_VF.h"
#include  "VF.h"
#include  "VFcap.h"
#include  "VFenc.h"
#include  "hbf.h"


#define DOT_SHAPE_SQUARE   0
#define DOT_SHAPE_DIAMOND  1

#define HBF_SUFFIX  ".hbf"


struct s_font {
  int    hbf_id;
  /* capabilities */
  char   *Filename;     /* ff */
  int    Encoding;      /* en */
  int    CharSet;       /* cs */
  int    Rotate;        /* ro */
  int    DotSizeFactor; /* dz */
  int    DotShape;      /* ds */
  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;


#define OL_RANGE        32768
#define OL_SIZE         8192
#define OL_OFFSET       ((OL_RANGE - OL_SIZE) / 2)


struct s_hbf {
  int            link_count;
  HBF            *port;
  int            hbf_enc;
  int            hbf_chset;
  int            hbf_width; 
  int            hbf_height; 
  char           *hbf_filename;
  unsigned char  *hbf_bmbuf; /* will be allocated by hbfGetBitmap() */
  int            hbf_bmrast;
  int            hbf_nchar; 
};
typedef struct s_hbf  hbf;

Private hbf  *hbf_table[VF_MAX_HBF_FONTS];

  
Private int    OpenFont();
Private void   Transformation();
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    GetEnc();
Private int    GetCharSet();
Private int    ReadCapa();

int            VF_Draw();


Private int    HBF_Open();
Private int    HBF_Close();
Private unsigned char* HBF_ReadBitmap();
Private long   *HBF_GetOutline();



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

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

  fobj = (FontObj*) malloc(sizeof(FontObj));
  fobj->ClassID     = VF_FONT_HBF;
  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->Link        = Link;
  fobj->Unlink      = Unlink;
  fobj->GetEnc      = GetEnc;
  fobj->GetCharSet  = GetCharSet;
  fobj->Locals      = (long) font;
  return fobj;
}
       

Private int
OpenFont(obj)
  FontObj *obj;
{
  int  id;
  Font *fobj;

  fobj = (Font*) obj->Locals;
  if ((id = HBF_Open(fobj->Filename)) < 0)
    return -1;

  /* check whether the character set value in vfontcap is the same as
     the value in the HBF header file.
     The encoding value of vfontcap (if specified) will always override
     the default value derived from the character set in the HBF header
     since the HBF format don't specify an extra encoding parameter. */
  if (fobj->Encoding == 0)
    fobj->Encoding = hbf_table[id]->hbf_enc;
  if (fobj->CharSet == 0)
    fobj->CharSet = hbf_table[id]->hbf_chset;
  else if (fobj->CharSet != hbf_table[id]->hbf_chset)
    return -1; /* ERR: character set mismatch */

  fobj->hbf_id = id;
  return 0;
}


Private int
CloseFont(obj, fid)
  FontObj  *obj;
  int      fid;
{
  int  id;
  Font *fobj;

  fobj = (Font*) obj->Locals;
  if ((id = HBF_Close(fobj->hbf_id)) < 0)
    return -1;
  return 0;
}


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

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


Private long*
GetOutline(obj, CJKcode)
  FontObj  *obj;
  int      CJKcode;
{
  long  *outline;
  Font  *fobj;
  
  fobj = (Font*) obj->Locals;
  if ((outline = HBF_GetOutline(fobj, fobj->hbf_id, CJKcode)) == NULL)
    return NULL;
  Transformation(&outline[2], fobj);
  return outline;
}


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


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_Hbf.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 = OL_OFFSET + fobj->Xoffset;
  yoffset = OL_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 * OL_SIZE);
      y = (int)(t4 * tmp_x + t5 * tmp_y + t6 * OL_SIZE);

      /* rotate */
      switch (fobj->Rotate % 4){
      default:
      case 0:  x2 = x;          y2 = y;          break;
      case 1:  x2 = OL_SIZE-y;  y2 = x;          break;
      case 2:  x2 = OL_SIZE-x;  y2 = OL_SIZE-y;  break;
      case 3:  x2 = y;          y2 = OL_SIZE-x;  break;
      }

      if (x2 < 0)        x2 = 0;
      if (x2 >= OL_SIZE) x2 = OL_SIZE;
      if (y2 < 0)        y2 = 0;
      if (y2 >= OL_SIZE) y2 = OL_SIZE;
      x2 += OL_OFFSET;   y2 += OL_OFFSET;

      /* reflect x, y */
      if (fobj->XReflect == 1) 
        x2 = OL_RANGE - x2;
      if (fobj->YReflect == 1) 
        y2 = OL_RANGE - y2;
      *vfp = VFD_MAKE_XY(x2, y2);
    }
  }
}


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;
{
  unsigned char *buff, d;
  int           rast, x, y, yy1, yy2, val;
  
  rast = (w+7)/8;
  if ((buff = (unsigned char*) malloc(h*rast)) == NULL)
    return -1;   /* ERR: malloc err */ 
  bzero(buff, rast*h);
  if ((val = VF_Draw(vfdata, w, h, rast, buff, 0, 0)) < 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 val;
}


Private int
FreeOutline(obj, vfdata)
  FontObj  *obj;
  long*    vfdata;
{
  if (vfdata != NULL)
    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
GetEnc(obj)
  FontObj  *obj;
{
  Font  *fobj;

  fobj = (Font*) obj->Locals;
  return fobj->Encoding;
}


Private int
GetCharSet(obj)
  FontObj  *obj;
{
  Font  *fobj;

  fobj = (Font*) obj->Locals;
  return fobj->CharSet;
}


static int
ReadCapa(font, ent)
  Font *font;
  char *ent;
{
  char *p;

  font->Encoding      = 0;
  font->CharSet       = 0;
  font->DotSizeFactor = 100;
  font->DotShape      = DOT_SHAPE_SQUARE;
  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);
  /* encoding and character set values will be checked with values from
     HBF header file in OpenFont() */
  if ((p = VFC_GetString(VFCE_ENCODING)) != NULL)
    if ((font->Encoding = VFE_SearchEncoding(p)) < 0)
      return -1;  /* ERR: unknown encoding */
  if ((p = VFC_GetString(VFCE_CHARSET)) != NULL)
    if ((font->CharSet = VFE_SearchCharSet(p)) < 0)
      return -1;  /* ERR: unknown character set */
  if ((font->DotSizeFactor = VFC_GetNumber(VFCE_DOTSIZEFACT)) == -1)
    font->DotSizeFactor = 100;
  if (font->DotSizeFactor < 0)
    font->DotSizeFactor = 0;
  if ((p = VFC_GetString(VFCE_DOTSHAPE)) == NULL)
    font->DotShape = DOT_SHAPE_SQUARE;
  else {
    if (strcmp(p, "diamond") == 0){
      font->DotShape = DOT_SHAPE_DIAMOND;
    } else {
      font->DotShape = DOT_SHAPE_SQUARE;
    }
  }
  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->Filename = malloc(strlen(p)+1)) == NULL)
    return -1;  /* ERR: malloc err */
  strcpy(font->Filename, p);

  return 0;
}



/*-- HBF INTERFACE -----------------*/
/* uses the HBF API (in the files hbf.c and hbf.h)
   written by Ross Paterson (rap@doc.ic.ac.uk)     */

Private int
HBF_Open(fname)
     char *fname;
{
  int         hbf_id;
  static int  inited = 0;
  HBF_BBOX    *hbf_bbox;
  const char  *charset;
  int         i;

  if (inited == 0){
    /* initialize the table */
    for (hbf_id = 0; hbf_id < VF_MAX_HBF_FONTS; hbf_id++)
      hbf_table[hbf_id] = NULL;
    inited = 1;
  }

  /* Check if the same HBF file is opened */
  for (hbf_id = 0; hbf_id < VF_MAX_HBF_FONTS; hbf_id++){
    if (hbf_table[hbf_id] == NULL)
      continue;
    if (strcmp(fname, hbf_table[hbf_id]->hbf_filename) == 0){
      hbf_table[hbf_id]->link_count++;
      /*printf("FOUND\n");*/
      return hbf_id;
    }
  }

  /* Find a free slot */
  for (hbf_id = 0; hbf_id < VF_MAX_HBF_FONTS; hbf_id++){
    if (hbf_table[hbf_id] == NULL)
      break;
  }
  if (hbf_id == VF_MAX_HBF_FONTS)
    return -1;    /* no free slots */

  /* Allocate hbf structure and initialize it */
  /*printf("OPEN %d (%s)\n", hbf_id, fname);*/
  if ((hbf_table[hbf_id] = (hbf*)malloc(sizeof(hbf))) == NULL)
    return -1;
  hbf_table[hbf_id]->link_count = 1; 
  hbf_table[hbf_id]->hbf_nchar  = -1;
  hbf_table[hbf_id]->hbf_width  = 0; 
  hbf_table[hbf_id]->hbf_height = 0;
  hbf_table[hbf_id]->hbf_filename = malloc(strlen(fname)+strlen(HBF_SUFFIX)+1);
  if (hbf_table[hbf_id]->hbf_filename == NULL)
    goto Err4;
  strcpy(hbf_table[hbf_id]->hbf_filename, fname);
  strcat(hbf_table[hbf_id]->hbf_filename, HBF_SUFFIX);

  /* Open HBF font and fill hbf structure */
  hbf_table[hbf_id]->port = hbfOpen(hbf_table[hbf_id]->hbf_filename);
  if (hbf_table[hbf_id]->port == NULL)
    goto Err3;
  hbf_bbox = hbfBitmapBBox(hbf_table[hbf_id]->port);
  hbf_table[hbf_id]->hbf_width = hbf_bbox->hbf_width;
  hbf_table[hbf_id]->hbf_height = hbf_bbox->hbf_height;
  hbf_table[hbf_id]->hbf_nchar = (int) hbfChars(hbf_table[hbf_id]->port);
  hbf_table[hbf_id]->hbf_bmrast = HBF_RowSize(hbf_table[hbf_id]->port);

  charset = hbfProperty(hbf_table[hbf_id]->port, "HBF_CODE_SCHEME");
  if ((hbf_table[hbf_id]->hbf_chset = VFE_SearchCharSet(charset)) < 0)
    goto Err3; /* ilegal character set */

  for (i = 0; ChSetTable[i].CharSetValue != hbf_table[hbf_id]->hbf_chset; i++)
    ;
  hbf_table[hbf_id]->hbf_enc = ChSetTable[i].DefEncValue;

  return hbf_id;

Err3:
  free(hbf_table[hbf_id]->hbf_filename);
Err4:
  free(hbf_table[hbf_id]);
  hbf_table[hbf_id] = NULL;
  return -1;
}


Private int
HBF_Close(hbf_id)
     int  hbf_id;
{
  if (hbf_table[hbf_id] == NULL){
    printf("VFLIB: HBF - ILLEGAL TO CLOSE\n");
    return -1;
  }
  /* Decrement the link count */
  --hbf_table[hbf_id]->link_count;
  if (hbf_table[hbf_id]->link_count == 0){
    /* release it since the slot is no longer used. */
    hbfClose(hbf_table[hbf_id]->port);
    free(hbf_table[hbf_id]->hbf_filename);
    free(hbf_table[hbf_id]);
    hbf_table[hbf_id] = NULL;
  }
  return 0;
}


Private unsigned char*
HBF_ReadBitmap(hbf_id, CJKcode)
     int hbf_id;
     int CJKcode;
{
  hbf_table[hbf_id]->hbf_bmbuf
    = (unsigned char *) hbfGetBitmap(hbf_table[hbf_id]->port,
                                     (HBF_CHAR) CJKcode);
  return hbf_table[hbf_id]->hbf_bmbuf;
}


Private long*
HBF_GetOutline(fobj, hbf_id, CJKcode)
     Font  *fobj;
     int hbf_id;
     int  CJKcode;
{
  int            x, y, ry, xx, nbits, size, ol_index;
  int            ol_xl, ol_xr, ol_yu, ol_yl, ol_xc, ol_yc;
  int            ol_xl2, ol_xr2, ol_yu2, ol_yl2;
  long           *outline;
  unsigned char  bmch;
  static char    bit_tbl[] = {
    0x80, 0x40, 0x20, 0x10,
    0x08, 0x04, 0x02, 0x01
  };
  static int     nbits_tbl[] = {
    0, 1, 1, 2,   /* 0, 1, 2, 3 */
    1, 2, 2, 3,   /* 4, 5, 6, 7 */
    1, 2, 2, 3,   /* 8, 9, A, B */
    2, 3, 3, 4,   /* C, D, E, F */
  };    

  if (HBF_ReadBitmap(hbf_id, CJKcode) == NULL)
    return NULL;

  /* count # of single bits */
  nbits = 0;
  ry = 0;
  for (y = 0; y < hbf_table[hbf_id]->hbf_height; y++){
    for (x = 0; x < hbf_table[hbf_id]->hbf_bmrast; x++){
      nbits += nbits_tbl[(hbf_table[hbf_id]->hbf_bmbuf[ry+x]) >> 4];
      nbits += nbits_tbl[(hbf_table[hbf_id]->hbf_bmbuf[ry+x]) & 0x0F];
    }
    ry += hbf_table[hbf_id]->hbf_bmrast;
  }

  /* allocate outline data area */
  switch (fobj->DotShape){
  case DOT_SHAPE_SQUARE:
  case DOT_SHAPE_DIAMOND:
  default:
    size = 2 + 5*nbits + 1;
    break;
  }
  if ((outline = (long*)malloc(size*sizeof(long))) == NULL)
    return NULL;

  /* make outline data from bitmap */
  ol_index = 0;

  /* header */
  outline[ol_index++] = CJKcode;
  outline[ol_index++] = VF_SONY_COORDINATES;
  /* a set of black squares */
  ry = 0;
  for (y = 0; y < hbf_table[hbf_id]->hbf_height; y++){
    for (x = 0; x < hbf_table[hbf_id]->hbf_bmrast; x++){
      bmch = hbf_table[hbf_id]->hbf_bmbuf[ry+x];
      if (bmch == 0x00)
        continue;
      ol_yu = (y+0)*OL_SIZE/hbf_table[hbf_id]->hbf_width + OL_OFFSET;
      ol_yl = (y+1)*OL_SIZE/hbf_table[hbf_id]->hbf_width + OL_OFFSET - 1;
      ol_yc = (ol_yu+ol_yl)/2;
      ol_yu2 = fobj->DotSizeFactor*(ol_yu-ol_yc)/100+ol_yc;
      ol_yl2 = fobj->DotSizeFactor*(ol_yl-ol_yc)/100+ol_yc;
      for (xx = 0; xx <= 7; xx++){
        /* if ((bit_tbl[xx] & bmch) != 0x00) printf("x");
         * else printf(" "); */
        if ((bit_tbl[xx] & bmch) != 0x00){
          ol_xl = (8*x+xx+0)*OL_SIZE/hbf_table[hbf_id]->hbf_width+OL_OFFSET;
          ol_xr = (8*x+xx+1)*OL_SIZE/hbf_table[hbf_id]->hbf_width+OL_OFFSET-1;
          ol_xc = (ol_xl+ol_xr)/2;
          ol_xl2 = fobj->DotSizeFactor*(ol_xl-ol_xc)/100+ol_xc;
          ol_xr2 = fobj->DotSizeFactor*(ol_xr-ol_xc)/100+ol_xc;
          if (fobj->DotShape == DOT_SHAPE_SQUARE){
            outline[ol_index++] = VFD_TOKEN|VFD_CHAR|VFD_CWCURV|VFD_LINE;
            outline[ol_index++] = VFD_MAKE_XY(ol_xl2, ol_yu2);
            outline[ol_index++] = VFD_MAKE_XY(ol_xl2, ol_yl2);
            outline[ol_index++] = VFD_MAKE_XY(ol_xr2, ol_yl2);
            outline[ol_index++] = VFD_MAKE_XY(ol_xr2, ol_yu2);
          } else { /* (fobj->DotShape == DOT_SHAPE_DIAMOND) */
            outline[ol_index++] = VFD_TOKEN|VFD_CHAR|VFD_CWCURV|VFD_LINE;
            outline[ol_index++] = VFD_MAKE_XY(ol_xl2, ol_yc);
            outline[ol_index++] = VFD_MAKE_XY(ol_xc,  ol_yl2);
            outline[ol_index++] = VFD_MAKE_XY(ol_xr2, ol_yc);
            outline[ol_index++] = VFD_MAKE_XY(ol_xc,  ol_yu2);
          }
        }
      }
    }
    /*printf("\n");*/
    ry += hbf_table[hbf_id]->hbf_bmrast;
  }
  /* end of outline */
  outline[ol_index] = 0L;

  return outline;
}

/*EOF*/
