//
// Copyright (C) 1999-2004 Toshikaz Hirabayashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// TOSHIKAZ HIRABAYASHI BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// Except as contained in this notice, the name of Toshikaz Hirabayashi shall
// not be used in advertising or otherwise to promote the sale, use or other
// dealings in this Software without prior written authorization from
// Toshikaz Hirabayashi.

#include <WSDfont.h>
#include <WSCfontSet.h>
#include <WSDcolor.h>
#include <WSCcolorSet.h>
#include <WSDimage.h>
#include <WSCimageSet.h>
#include <WSCstring.h>
//#include <WSCvarc.h>
#include <WSClocaleSet.h>
#include <WSDpsdraw.h>
#include <WSDmwindowDev.h>

//#define TDBG

#define CBUF_MAX 256
WSMFclassInit(WSDpsdraw,WSCroot);
WSClistData _file_list;
WSClistData _count_list;

WSDpsdraw::WSDpsdraw(){
  _fg_cno = 0;
  _bg_cno = 0;
  _fg_color = NULL;
  _bg_color = NULL;
  _line_width = 1;
  _line_type = -1;
  _clipping = False;
  _file = NULL;
  _format = WS_PR_A4;
  _type = WS_PR_PS;
  _orientation = WS_VERTICAL;
  _work_x = 10;
  _work_y = 10;
  _work_width = 512;
  _work_height = 724;
}
WSDpsdraw::~WSDpsdraw(){}

long WSDpsdraw::setValue(long kind,long val){
  if (kind == WSDEV_PR_TYPE){
    _type = val;
  }else
  if (kind == WSDEV_PR_FORMAT){
    _format = val;
  }else
  if (kind == WSDEV_WORK_X){
    _work_x = val;
  }else
  if (kind == WSDEV_WORK_Y){
    _work_y = val;
  }else
  if (kind == WSDEV_WORK_WIDTH){
    _work_width = val;
  }else
  if (kind == WSDEV_WORK_HEIGHT){
    _work_height = val;
  }else
  if (kind == WSDEV_PR_ORIENTATION){
    _orientation = val;
  }
  return WS_NO_ERR;
}

long WSDpsdraw::setForeColor(short cno){
  short bk = _fg_cno;
  _fg_cno = cno;
  _fg_color = WSGIappColorSet()->getColor(cno);
  return bk;
}

long WSDpsdraw::setBackColor(short cno){
  short bk = _bg_cno;
  _bg_cno = cno;
  _bg_color = WSGIappColorSet()->getColor(cno);
  return bk;
}
long WSDpsdraw::setForeColor(WSDcolor* color){
  if (color== NULL){
    return _fg_cno;
  }
  short bk = _fg_cno;
  _fg_cno = color->getId();
  _fg_color = color;
  return bk;
}

long WSDpsdraw::setBackColor(WSDcolor* color){
  if (color== NULL){
    return _bg_cno;
  }
  short bk = _bg_cno;
  _bg_cno = color->getId();
  _bg_color = color;
  return bk;
}
long WSDpsdraw::setLineWidth(short width){
  long bk = _line_width; 
  _line_width = width;
  if (_line_width < 1){
    _line_width = 1;
  }
  return bk;
}

long WSDpsdraw::setLineDashType(char type){
  long bk = _line_type; 
  _line_type = type;
  return bk;
}
static long _fill_type = 0;
long WSDpsdraw::setHatchPattern(char type){
  long bk = _fill_type; 
  _fill_type = type;
  return bk;
}

long WSDpsdraw::beginDraw(WSDdev* dev,long val1,long val2,long val3){
  _file = (WSDfile*)val1;
  long num = _file_list.getNum();
  long fl = 0;
  long i;
  for(i=0; i<num; i++){
    WSDfile* file = (WSDfile*)_file_list[i];
    if (_file == file){
      long val = (long)_count_list[i];
      val++;
      _count_list.setData(i,(void*)val);
      fl = True;
      break;
    }
  }
  if (fl == 0){
    _file_list.add((void*)_file);
    _count_list.add((void*)1);
    outputHeader();
  }
  if (_line_width < 0){
    _line_width = 1;
  }
  _fill_type = 0;
  _line_type = 0;
  _clipping = False;

  _fg_cno = WSGIappColorSet()->getColorNo("#000000");
  _bg_cno = WSGIappColorSet()->getColorNo("#000000");
  _fg_color = WSGIappColorSet()->getColor("#000000");
  _bg_color = WSGIappColorSet()->getColor("#000000");
  return WS_NO_ERR;
}

long WSDpsdraw::endDraw(){
  long num = _file_list.getNum();
  long i;
  for(i=0; i<num; i++){
    WSDfile* file = (WSDfile*)_file_list[i];
    if (_file == file){
      long val = (long)_count_list[i];
      val--;
      if (val == 0){
        _file_list.delPos(i);
        _count_list.delPos(i);
        outputFooter();
      }else{
        _count_list.setData(i,(void*)val);
      }
      break;
    }
  }
  return WS_NO_ERR;
}
void putcolor(WSDcolor* color,WSCstring* str){
  long r,g,b;
  color->getRGB(&r,&g,&b); 
  (*str) << (double)r/256 << " "; 
  (*str) << (double)g/256 << " "; 
  (*str) << (double)b/256 << " setrgbcolor\n"; 
}
void drawfill(long no,long x,long y,WSCulong w,WSCulong h,WSCstring* str){
  long x1 = x;
  if ( x%16 != 0){
    x1 = (x/16)*16;
  }
  long y1 = y;
  if ( y%16 != 0){
    y1 = (y/16)*16;
  }
  WSCulong w1 = w;
  w1 = (w/16+1)*16;
  WSCulong h1 = h;
  h1 = (h/16+1)*16;
  (*str) << "hatch" << no << " 8 " << x1 << " " << y1
         << " " << w1 << " " << h1 << " ws_hatchfill\n";
}

long WSDpsdraw::setRegion(short x,short y,WSCushort w,WSCushort h){
  return WS_NO_ERR;
}

long WSDpsdraw::drawArc(short x,short y,WSCushort w,WSCushort h,short a1,short a2){
  if (_file == NULL){
    return WS_ERR;
  }
  if ((a2 - a1)/64/360 != 0){
    WSCstring str;
    putcolor(_fg_color,&str);
    str << "gsave gsave newpath\n";
    str << x+w/2 << " " << y+h/2 << " ";
    str << w << " " << h << " ws_ellipse\n";
    if (_fill_type != 0){
      str << "closepath clip newpath\n";
      drawfill(_fill_type,x,y,w,h,&str);
    }
    str << " stroke grestore grestore\n";

    _file->write((char*)str,strlen((char*)str));
    return WS_NO_ERR;
  }
  WSCstring str;
  str << "gsave gsave newpath\n";
  str << x+w/2 << " " << y + h/2 << " " << w/2 << " " << h/2 << " "
      << -a1/64 << " " << -a2/64 << " ws_arc\n";
  if (_fill_type != 0){
    str << x+w/2 << " " << y + h/2 << " " << w/2 << " " << h/2 << " "
      << -a2/64 << " " << -a1/64 << " ws_arcn\n";
    str << "closepath clip newpath\n";
    drawfill(_fill_type,x,y,w,h,&str);
  }
  str << "stroke grestore grestore\n";

  _file->write((char*)str,strlen((char*)str));
  return WS_NO_ERR;
}
long WSDpsdraw::drawFillArc(short x,short y,WSCushort w,WSCushort h,short a1,short a2,char kind){
  if (_file == NULL){
    return WS_ERR;
  }
  if ((a2 - a1)/64/360 != 0){
    WSCstring str;
    putcolor(_fg_color,&str);
    str << "gsave\nnewpath ";
    str << x+w/2 << " " << y+h/2 << " ";
    if (_fill_type == 0){
      str << w/2 << " " << h/2 << " ws_ellipse fill\n";
    }else{
      str << w/2 << " " << h/2 << " ws_ellipse closepath clip newpath\n";
      drawfill(_fill_type,x,y,w,h,&str);
    }
    str << "grestore\n";
    _file->write((char*)str,strlen((char*)str));
    return WS_NO_ERR;
  }

  if (kind == WS_PI){
    WSCstring str;
    putcolor(_fg_color,&str);
    str << "gsave\nnewpath\n";
    str << x+w/2 << " " << y+h/2 << " moveto\n";
    str << x+w/2 << " " << y+h/2 << " " << w/2 << " " << h/2 << " "
        << -a1/64 << " " << -a2/64 << " ws_arc\n";
    if (_fill_type == 0){
      str << x+w/2 << " " << y+h/2 << " lineto fill\n";
    }else{
      str << x+w/2 << " " << y+h/2 << " lineto\nclosepath clip newpath\n";
      drawfill(_fill_type,x,y,w,h,&str);
    }
    str << "grestore\n";
    _file->write((char*)str,strlen((char*)str));
  }else{
    WSCstring str;
    putcolor(_fg_color,&str);
    str << "gsave\nnewpath\n";
    str << x+w/2 << " " << y+h/2 << " " << w/2 << " " << h/2 << " ";
    if (_fill_type == 0){
      str  << -a1/64 << " " << -a2/64 << " ws_arc fill\n";
    }else{
      str  << -a1/64 << " " << -a2/64 << " ws_arc closepath clip newpath\n";
      drawfill(_fill_type,x,y,w,h,&str);
    }
    str << "grestore\n";
    _file->write((char*)str,strlen((char*)str));
  }
  return WS_NO_ERR;
}
long WSDpsdraw::drawLine(short x1,short y1,short x2,short y2){
  if (_file == NULL){
    return WS_ERR;
  }
  WSCstring str;
  putcolor(_fg_color,&str);
  str << "gsave newpath\n";
  str << x1 << " " << y1 << " moveto\n";
  str << x2 << " " << y2 << " lineto\n";
  str << _line_width << " setlinewidth\n";
  if (_fill_type == 0){
    str << "stroke grestore\n\n";
  }else{
    long vx = x1;
    if (vx > x2){
      vx = x2;
    }
    long vy = y1;
    if (vy > y2){
      vy = y2;
    }
    long w = x2 - x1;
    long h = y2 - y1;
    if (w < 0){
      w = -w;
    }
    if (w < _line_width){
      w = _line_width;
    }
    if (h < 0){
      h = -h;
    }
    if (h < _line_width){
      h = _line_width;
    }
    str << "closepath clip newpath\n";
    drawfill(_fill_type,vx,vy,w,h,&str);
    str << "stroke grestore\n\n";
  }
  _file->write((char*)str,strlen((char*)str));
  return WS_NO_ERR;
}
long WSDpsdraw::drawLines(WSCpoint* points,long num){
  if (_file == NULL){
    return WS_ERR;
  }
  if (num < 2){
    return WS_NO_ERR;
  }
  long i;
  for(i=0; i<num -1; i++){
    drawLine(points[i].x,points[i].y,points[i+1].x,points[i+1].y);
  }
  return WS_NO_ERR;
}
long WSDpsdraw::drawRect(short x,short y,WSCushort w,WSCushort h){
  if (_file == NULL){
    return WS_ERR;
  }
  drawLine(x,y,x+w,y);
  drawLine(x+w,y,x+w,y+h);
  drawLine(x+w,y+h,x,y+h);
  drawLine(x,y+h,x,y);
  return WS_NO_ERR;
}
long WSDpsdraw::drawFillRect(short x,short y,WSCushort w,WSCushort h){
  if (_file == NULL){
    return WS_ERR;
  }
  WSCstring str;
  putcolor(_fg_color,&str);
  str << "gsave newpath\n";
  str << x << " " << y << " moveto " << x+w << " " << y << " lineto ";
  str << x+w << " " << y+h << " lineto " << x << " " << y+h << " lineto\n";
  if ( _fill_type == 0){
    str << "closepath fill\n";
  }else{
    str << "closepath clip newpath\n";
    drawfill(_fill_type,x,y,w,h,&str);
  }
  str << "grestore\n";

  _file->write((char*)str,strlen((char*)str));
  return WS_NO_ERR;
}
long WSDpsdraw::drawRects(WSCrect* rects,long num){
  if (_file == NULL){
    return WS_ERR;
  }
  long i;
  for(i=0; i<num; i++){
    drawRect(rects[i].x,rects[i].y,rects[i].width,rects[i].height);
  }

  return WS_NO_ERR;
}
long WSDpsdraw::drawFillRects(WSCrect* rects,long num){
  if (_file == NULL){
    return WS_ERR;
  }
  long i;
  for(i=0; i<num; i++){
    drawRect(rects[i].x,rects[i].y,rects[i].width,rects[i].height);
  }
  return WS_NO_ERR;
}
long WSDpsdraw::drawPoly(WSCpoint* points,long num){
  if (_file == NULL){
    return WS_ERR;
  }
  if (num < 2){
    return WS_ERR;
  }
  long i;
  for(i=0; i<num -1; i++){
    drawLine(points[i].x,points[i].y,points[i+1].x,points[i+1].y);
  }
  drawLine(points[num-1].x,points[num-1].y,points[0].x,points[0].y);

  return WS_NO_ERR;
}

long WSDpsdraw::drawFillPoly(WSCpoint* points,long num){
  if (_file == NULL){
    return WS_ERR;
  }
  short x1 = points[0].x;
  short y1 = points[0].y;
  short x2 = points[0].x;
  short y2 = points[0].y;

  long i = 0;
  WSCstring str;
  putcolor(_fg_color,&str);
  str << "gsave newpath\n";
  str << points[0].x << " " << points[0].y << " moveto\n";
  for(i=1; i<num;i++){
    str << points[i].x << " " << points[i].y << " lineto\n";
    if (x1 > points[i].x){
      x1 = points[i].x;
    }
    if (y1 > points[i].y){
      y1 = points[i].y;
    }
    if (x2 < points[i].x){
      x2 = points[i].x;
    }
    if (y2 < points[i].y){
      y2 = points[i].y;
    }

  }
  str << points[0].x << " " << points[0].y << " lineto\n";

  if ( _fill_type == 0){
    str << "closepath fill\n";
  }else{
    str << "closepath clip newpath\n";
    drawfill(_fill_type,x1,y1,x2 - x1,y2 - y1,&str);
  }
  str << "grestore\n";

  _file->write((char*)str,strlen((char*)str));
  return WS_NO_ERR;
}

long WSDpsdraw::drawImage(short x,short y,WSCushort w,WSCushort h,WSDimage* image,char align){

  if (_file == NULL){
    return WS_ERR;
  }
  WSCushort pw = image->getImageWidth();
  WSCushort ph = image->getImageHeight();
  short xoff = 0;
  short yoff = 0;
  if (align == WS_CENTER){
    xoff = ((short)w - (short)pw)/2;
    yoff = ((short)h - (short)ph)/2;
  }else
  if (align == WS_LEFT){
    yoff = ((short)h - (short)ph)/2;
  }else
  if (align == WS_LEFT_TOP){
    xoff = 0;
    yoff = 0;
  }else
  if (align == WS_TOP){
    xoff = ((short)w - (short)pw)/2;
    yoff = 0;
  }else
  if (align == WS_RIGHT){
    xoff = ((short)w - (short)pw);
    yoff = ((short)h - (short)ph)/2;
  }else
  if (align == WS_BOTTOM){
    xoff = ((short)w - (short)pw)/2;
    yoff = ((short)h - (short)ph);
  }else
  if (align == WS_LEFT_BOTTOM){
    xoff = 0;
    yoff = ((short)h - (short)ph);
  }else
  if (align == WS_RIGHT_TOP){
    xoff = ((short)w - (short)pw);
    yoff = 0;
  }else
  if (align == WS_RIGHT_BOTTOM){
    xoff = ((short)w - (short)pw);
    yoff = ((short)h - (short)ph);
  }

  WSClistData rlist[CBUF_MAX];
  WSClistData glist[CBUF_MAX];
  WSClistData blist[CBUF_MAX];
  long ccnt_a[CBUF_MAX];
  long ccnt = 0;
  long i;
  for(i=0; i<CBUF_MAX; i++){
    ccnt_a[i] = 0;
  }
  WSDmwindowDev* mdev = WSDmwindowDev::getNewInstance();
  if (mdev == NULL){
    return WS_ERR;
  }
//printf("WSDpsdraw::drawImage this=0x%x\n",this);
  WSDdraw* bk = WSDdev::getDraw();
  WSDdev::setDraw(WSDdev::getNativeDraw());

  mdev->createPixmap(w,h);
  mdev->beginDraw(0,0,w,h);
  mdev->setForeColor(_bg_cno);
  mdev->drawRect(0,0,w,h);
  mdev->drawImage(xoff,yoff,w,h,image,WS_LEFT_TOP);
  mdev->endDraw();
  mdev->initBuffer();
  WSDdev::setDraw(bk);

  WSCulong* buf = new WSCulong[w*h];

  long x1,y1;
  for(x1=0; x1<w; x1++){
    for(y1=0; y1<h; y1++){
      WSCuchar r = 0,g = 0,b = 0;
      mdev->getBufferRGB(x1,y1,&r,&g,&b);
      r &=0xe0;
      g &=0xe0;
      b &=0xe0;
      long hash = (r+g+b)&0xff;
      long fl = 0;
      long c;
      for(c=0; c<ccnt_a[hash]; c++){
        WSCulong r1 = (WSCulong)(rlist[hash])[c];
        WSCulong g1 = (WSCulong)(glist[hash])[c];
        WSCulong b1 = (WSCulong)(blist[hash])[c];
        if ((WSCuchar)r1 == r && (WSCuchar)g1 == g && (WSCuchar)b1 == b){
          fl = 1;
          buf[y1*w + x1] = c*256 + hash;
          break;
        }
      }
      if (fl == 0){
        WSCulong r1 = r;
        WSCulong g1 = g;
        WSCulong b1 = b;
        rlist[hash].add((void*)r1);
        glist[hash].add((void*)g1);
        blist[hash].add((void*)b1);
        buf[y1*w + x1] = ccnt_a[hash] * 256 + hash;
        ccnt++;
        ccnt_a[hash]++;
      }
    }
  }

  WSCstring str;
  str << "gsave\n";
  str << "3 " << ccnt << " mul array ws_setpixels\n";

  _file->write((char*)str,strlen((char*)str));
  long j;
  WSCulong cnt = 0;
  for(i=0; i<CBUF_MAX; i++){
    for(j=0; j<ccnt_a[i]; j++){
      WSCulong r = (WSCulong)(rlist[i])[j];
      WSCulong g = (WSCulong)(glist[i])[j];
      WSCulong b = (WSCulong)(blist[i])[j];
      char buffer[256];
      sprintf(buffer,"%d [ %lf %lf %lf ] ws_setpix\n",3*cnt,
           (double)r/256,(double)g/256,(double)b/256);
      _file->write(buffer,strlen(buffer));
      (rlist[i]).setData(j,(void*)cnt);
      cnt++;
    }
  }
  long bit = 8;
  if (cnt > 256){
    bit = 32; 
  }
  str = "";
  str << x << " " << y << " translate 1.00 1.00 scale 0 rotate\n";
  str << w << " " << h << " " << bit << "\n[1 0 0 1 0 0]\n";
  str << "{currentfile ws_bwpicstr readhexstring pop 0 get ws_colorspot}\n";
  str << "false 3 colorimage\n";
  _file->write((char*)str,strlen(str));
//printf("here2\n");
  for(y1=0; y1<h; y1++){
    for(x1=0; x1<w; x1++){
      WSCulong val =  buf[y1*w + x1] / 256;
      WSCulong hash =  buf[y1*w + x1] & 0xff;
      WSCulong num = (WSCulong)(rlist[hash])[val];
      char tmp[32];
      if (bit == 8){
        sprintf(tmp,"%02x",num);
      }else{
        sprintf(tmp,"%04x",num);
      }
      _file->write((char*)tmp,strlen(tmp));
    }
    _file->write((char*)"\n",strlen("\n"));
  }
  str = "";
  str << "grestore\n";
  _file->write((char*)str,strlen((char*)str));

  delete buf;
  return WS_NO_ERR;
}
long WSDpsdraw::drawStretchedImage(short x,short y,WSCushort w,WSCushort h,WSDimage* image){
  if (_file == NULL){
    return WS_ERR;
  }
  if (image == NULL){
    return WS_ERR;
  }
  if (image->getValue1() == 0 ||
      image->getValue1() == -1 ){
    return WS_ERR;
  }
  WSClistData rlist[CBUF_MAX];
  WSClistData glist[CBUF_MAX];
  WSClistData blist[CBUF_MAX];
  long ccnt_a[CBUF_MAX];
  long ccnt = 0;
  long i;
  for(i=0; i<CBUF_MAX; i++){
    ccnt_a[i] = 0;
  }
  WSDmwindowDev* mdev = WSDmwindowDev::getNewInstance();
  if (mdev == NULL){
    return WS_ERR;
  }
//printf("WSDpsdraw::drawImage this=0x%x\n",this);
  WSDdraw* bk = WSDdev::getDraw();
  WSDdev::setDraw(WSDdev::getNativeDraw());

  mdev->createPixmap(w,h);
  mdev->beginDraw(0,0,w,h);
  mdev->drawStretchedImage(0,0,w,h,image);
  mdev->endDraw();
  mdev->initBuffer();
  WSDdev::setDraw(bk);

  WSCulong* buf = new WSCulong[w*h];

  long x1,y1;
  for(x1=0; x1<w; x1++){
    for(y1=0; y1<h; y1++){
      WSCuchar r = 0,g = 0,b = 0;
      mdev->getBufferRGB(x1,y1,&r,&g,&b);
      r &=0xe0;
      g &=0xe0;
      b &=0xe0;
      long hash = (r+g+b)&0xff;
      long fl = 0;
      long c;
      for(c=0; c<ccnt_a[hash]; c++){
        WSCulong r1 = (WSCulong)(rlist[hash])[c];
        WSCulong g1 = (WSCulong)(glist[hash])[c];
        WSCulong b1 = (WSCulong)(blist[hash])[c];
        if ((WSCuchar)r1 == r && (WSCuchar)g1 == g && (WSCuchar)b1 == b){
          fl = 1;
          buf[y1*w + x1] = c*256 + hash;
          break;
        }
      }
      if (fl == 0){
        WSCulong r1 = r;
        WSCulong g1 = g;
        WSCulong b1 = b;
        rlist[hash].add((void*)r1);
        glist[hash].add((void*)g1);
        blist[hash].add((void*)b1);
        buf[y1*w + x1] = ccnt_a[hash] * 256 + hash;
        ccnt++;
        ccnt_a[hash]++;
      }
    }
  }

  WSCstring str;
  str << "gsave\n";
  str << "3 " << ccnt << " mul array ws_setpixels\n";

  _file->write((char*)str,strlen((char*)str));
  long j;
  WSCulong cnt = 0;
  for(i=0; i<CBUF_MAX; i++){
    for(j=0; j<ccnt_a[i]; j++){
      WSCulong r = (WSCulong)(rlist[i])[j];
      WSCulong g = (WSCulong)(glist[i])[j];
      WSCulong b = (WSCulong)(blist[i])[j];
      char buffer[256];
      sprintf(buffer,"%d [ %lf %lf %lf ] ws_setpix\n",3*cnt,
           (double)r/256,(double)g/256,(double)b/256);
      _file->write(buffer,strlen(buffer));
      (rlist[i]).setData(j,(void*)cnt);
      cnt++;
    }
  }
  long bit = 8;
  if (cnt > 256){
    bit = 32; 
  }
  str = "";
  str << x << " " << y << " translate 1.00 1.00 scale 0 rotate\n";
  str << w << " " << h << " " << bit << "\n[1 0 0 1 0 0]\n";
  str << "{currentfile ws_bwpicstr readhexstring pop 0 get ws_colorspot}\n";
  str << "false 3 colorimage\n";
  _file->write((char*)str,strlen(str));
//printf("here2\n");
  for(y1=0; y1<h; y1++){
    for(x1=0; x1<w; x1++){
      WSCulong val =  buf[y1*w + x1] / 256;
      WSCulong hash =  buf[y1*w + x1] & 0xff;
      WSCulong num = (WSCulong)(rlist[hash])[val];
      char tmp[32];
      if (bit == 8){
        sprintf(tmp,"%02x",num);
      }else{
        sprintf(tmp,"%04x",num);
      }
      _file->write((char*)tmp,strlen(tmp));
    }
    _file->write((char*)"\n",strlen("\n"));
  }
  str = "";
  str << "grestore\n";
  _file->write((char*)str,strlen((char*)str));

  delete buf;
  return WS_NO_ERR;
}


long WSDpsdraw::drawImage(short x,short y,short sx,short sy,WSCushort w,WSCushort h,WSDimage* image){
  if (_file == NULL){
    return WS_ERR;
  }

  return WS_NO_ERR;
}
long WSDpsdraw::drawUString(long x,long y,WSCulong w,WSCulong h,
         WSCushort* str,char font,char align,long cur,WSCbool inter_cur,
         long scur1,long scur2){
  char* str1 = WSGFgetString(str,WS_EN_UTF8);
  WSCstring str2(str1,WS_EN_UTF8);
  long ret = drawString(x,y,w,h,&str2,font,align,cur,inter_cur,scur1,scur2);
  delete str1;
  return ret;
}
long WSDpsdraw::drawFillUString(long x,long y,WSCulong w,WSCulong h,
           WSCushort* str,char font,char align,short cur,WSCbool inter_cur){
  char* str1 = WSGFgetString(str,WS_EN_UTF8);
  WSCstring str2(str1,WS_EN_UTF8);
  long ret = drawFillString(x,y,w,h,&str2,font,align,cur,inter_cur);
  delete str1;
  return ret;
}

long WSDpsdraw::drawString(long x,long y,WSCulong w,WSCulong h,
         WSCstring* str,char font,char align,long cur,WSCbool inter_cur,
         long scur1,long scur2){

  if (scur1 == scur2){
    scur1 = scur2 = 0;
  }
  if (scur1 > scur2){
    long bk = scur1;
    scur1 = scur2;
    scur2 = bk;
  }
  if (_file == NULL){
    return WS_ERR;
  }

  WSDfont* fn = WSGIappFontSet()->getFont(font);
  if (fn == NULL){
    fn = WSGIappFontSet()->getDefaultFont();
    if (fn == NULL){
      return WS_ERR;
    }
  }
  long fheight = fn->getFontHeight();


  WSCstring str1;
  putcolor(_fg_color,&str1);
  str1 <<"/Times-Roman-Ryumin-Light-EUC-H /Times-Roman /Ryumin-Light-EUC-H eucfont\n/Times-Roman-Ryumin-Light-EUC-H findfont [";

  str1 << fheight << " 0 0 -";
  str1 << fheight << " 0 0] makefont setfont\ngsave\n";
  str1 << x << " " << y+fheight << " moveto (";

  WSCstring tmp1;
  if (WSGIappLocaleSet()->getSystemLocaleEncoding() == WS_EN_EUCJP){
    char* ptr = str->getString(WS_EN_EUCJP);
    long num = strlen(ptr);
    long i;
    char buffer[16];
    for(i=0; i<num; i++){
      if ((unsigned char)ptr[i] & 0x80){
        sprintf(buffer,"\\%o",(unsigned char)(ptr[i]));
      }else{
        buffer[0] = ptr[i];
        buffer[1] = 0;
      }
      tmp1 << buffer;
    }
  }else
  if (WSGIappLocaleSet()->getSystemLocaleEncoding() == WS_EN_SJIS){
    char* ptr = str->getString(WS_EN_EUCJP);
    long num = strlen(ptr);
    long i;
    char buffer[16];
    for(i=0; i<num; i++){
      if ((unsigned char)ptr[i] & 0x80){
        sprintf(buffer,"\\%o",(unsigned char)(ptr[i]));
      }else{
        buffer[0] = ptr[i];
        buffer[1] = 0;
      }
      tmp1 << buffer;
    }
  }else{
    char* ptr = str->getString();
    long num = strlen(ptr);
    long i;
    char buffer[16];
    for(i=0; i<num; i++){
      if ((unsigned char)ptr[i] & 0x80){
        sprintf(buffer,"\\%o",(unsigned char)(ptr[i]));
      }else{
        buffer[0] = ptr[i];
        buffer[1] = 0;
      }
      tmp1 << ptr;
    }
  }

  str1 << tmp1;
  str1 << ") show\ngrestore\n";

  _file->write((char*)str1,strlen((char*)str1));

  return WS_NO_ERR;
}

long WSDpsdraw::drawFillString(long x,long y,WSCulong w,WSCulong h,
           WSCstring* str,char font,char align,short cur,WSCbool inter_cur){

  if (_file == NULL){
    return WS_ERR;
  }
  WSCulong bk = _fg_cno;
  drawFillRect(x,y,w,h);
  _fg_cno = bk;
  drawString(x,y,w,h,str,font,align,cur,inter_cur);

  return WS_NO_ERR;
}


long WSDpsdraw::drawGradation(long type,short c1,short c2,short c3,
                  short x,short y,WSCushort w,WSCushort h,WSCuchar gradm){

  if (_file == NULL){
    return WS_ERR;
  }


  return WS_NO_ERR;
}

extern char* ws_ps_header;
extern char* ws_ps_header2;
long WSDpsdraw::outputHeader(){
//  WSCstring str;
//  str << ws_ps_header;
//  _file->write((char*)str,strlen((char*)str));
//printf("_file2=0x%x\n",_file);
  _file->write((char*)ws_ps_header,strlen((char*)ws_ps_header));

  WSCstring str;
  if (_orientation == WS_VERTICAL){
    str << " 72 0 mul 72 ";
    char* size = "11.70";
    double pointw = 11.70 * 72 * 20.9 / 29.6;
    double pointh = 11.70 * 72;
    if (_format == WS_PR_A5){
      size = "8.30";
      pointw = 8.30 * 72 * 20.9 / 29.6;
      pointh = 8.30 * 72;
    }else
    if (_format == WS_PR_A3){
      size = "16.55";
      pointw = 16.55 * 72 * 20.9 / 29.6;
      pointh = 16.55 * 72;
    }else
    if (_format == WS_PR_B4){
      size = "14.35";
      pointw = 14.35 * 72 * 20.9 / 29.6;
      pointh = 14.35 * 72;
    }else
    if (_format == WS_PR_B5){
      size = "10.15";
      pointw = 10.15 * 72 * 20.9 / 29.6;
      pointh = 10.15 * 72;
    }else
    if (_format == WS_PR_LETTER){
      size = "11.00";
      pointw = 11.00 * 72 * 612 / 792;
      pointh = 11.00 * 72;
    }else
    if (_format == WS_PR_LEGAL){
      size = "14.00";
      pointw = 14.00 * 72 * 612 / 1008;
      pointh = 14.00 * 72;
    }else
    if (_format == WS_PR_STATEMENT){
      size = "8.50";
      pointw = 8.50 * 72 * 396 / 612;
      pointh = 8.50 * 72;
    }else
    if (_format == WS_PR_TABLOID){
      size = "17.00";
      pointw = 17.00 * 72 * 792 / 1224;
      pointh = 17.00 * 72;
    }else
    if (_format == WS_PR_LEDGER){
      size = "11.00";
      pointw = 11.00 * 72 * 1224 / 792;
      pointh = 11.00 * 72;
    }else
    if (_format == WS_PR_FOLIO){
      size = "13.00";
      pointw = 13.00 * 72 * 612 / 936;
      pointh = 13.00 * 72;
    }else
    if (_format == WS_PR_QUARTO){
      size = "10.85";
      pointw = 10.85 * 72 * 610 / 780;
      pointh = 10.85 * 72;
    }else
    if (_format == WS_PR_10X14){
      size = "14.00";
      pointw = 14.00 * 72 * 720 / 1008;
      pointh = 14.00 * 72;
    }else
    if (_format == WS_PR_EXECUTIVE){
      size = "10.00";
      pointw = 10.00 * 72 * 540 / 720;
      pointh = 10.00 * 72;
    }
    str << size;
    str << " mul translate\n1.00 dup neg scale\n";
    double scalex = pointw / _work_width;
    double scaley = pointh / _work_height;
    if (_format == WS_PR_FREE){
      scalex = 1.0;
      scaley = 1.0;
    }
    str << scalex << " " << scaley << " scale\n";
    str << _work_x * _work_width / pointw << " "
        << _work_y * _work_height / pointh << " translate\n";

  }else{
    str << " 90 rotate\n";
    str << " 72 0 mul 72 0 mul translate\n";

    double pointw = 11.70 * 72;
    double pointh = 11.70 * 72 * 20.9 / 29.6;
    if (_format == WS_PR_A5){
      pointw = 8.30 * 72;
      pointh = 8.30 * 72 * 20.9 / 29.6;
    }else
    if (_format == WS_PR_A3){
      pointw = 16.55 * 72;
      pointh = 16.55 * 72 * 20.9 / 29.6;
    }else
    if (_format == WS_PR_B4){
      pointw = 14.35 * 72;
      pointh = 14.35 * 72 * 20.9 / 29.6;
    }else
    if (_format == WS_PR_B5){
      pointw = 10.15 * 72;
      pointh = 10.15 * 72 * 20.9 / 29.6;
    }else
    if (_format == WS_PR_LETTER){
      pointw = 11.00 * 72;
      pointh = 11.00 * 72 * 612 / 792;
    }else
    if (_format == WS_PR_LEGAL){
      pointw = 14.00 * 72;
      pointh = 14.00 * 72 * 612 / 1008;
    }else
    if (_format == WS_PR_STATEMENT){
      pointw = 8.50 * 72;
      pointh = 8.50 * 72 * 396 / 612;
    }else
    if (_format == WS_PR_TABLOID){
      pointw = 17.00 * 72;
      pointh = 17.00 * 72 * 792 / 1224;
    }else
    if (_format == WS_PR_LEDGER){
      pointw = 11.00 * 72;
      pointh = 11.00 * 72 * 1224 / 792;
    }else
    if (_format == WS_PR_FOLIO){
      pointw = 13.00 * 72;
      pointh = 13.00 * 72 * 612 / 936;
    }else
    if (_format == WS_PR_QUARTO){
      pointw = 10.85 * 72;
      pointh = 10.85 * 72 * 610 / 780;
    }else
    if (_format == WS_PR_10X14){
      pointw = 14.00 * 72;
      pointh = 14.00 * 72 * 720 / 1008;
    }else
    if (_format == WS_PR_EXECUTIVE){
      pointw = 10.00 * 72;
      pointh = 10.00 * 72 * 540 / 720;
    }
    str << " 1.00 dup neg scale\n";
    double scalex = pointw / _work_width;
    double scaley = pointh / _work_height;
    if (_format == WS_PR_FREE){
      scalex = 1.0;
      scaley = 1.0;
    }

    str << scalex << " " << scaley << " scale\n";
    str << _work_x * _work_width / pointw << " "
        << _work_y * _work_height / pointh << " translate\n";

  }
  _file->write((char*)str,strlen((char*)str));
  _file->write((char*)ws_ps_header2,strlen((char*)ws_ps_header2));

  return WS_NO_ERR;
}
extern char* ws_ps_footer;
long WSDpsdraw::outputFooter(){
  WSCstring str;
  str << ws_ps_footer;
  _file->write((char*)str,strlen((char*)str));

  return WS_NO_ERR;
}

char* ws_ps_header = "\
/ws_dict 6 dict def\n\
ws_dict begin\n\
/copyfont {\n\
    dup maxlength 1 add dict begin\n\
    {\n\
        1 index /FID ne 2 index /UniqueID ne and\n\
        {def} {pop pop} ifelse\n\
    } forall\n\
    currentdict\n\
    end\n\
} bind def\n\
/eucfont {\n\
    12 dict begin\n\
        dup type /nametype eq { findfont } if\n\
        dup /WMode known {\n\
            dup /WMode get /WMode exch def\n\
            WMode 1 eq {\n\
                [0.0 1.0 -1.0 0.0 0.0 0.30] makefont\n\
            } if\n\
        } if\n\
        copyfont dup begin\n\
            /Encoding Encoding\n\
            FMapType dup 2 eq {\n\
                pop 128 128\n\
            } { 5 eq {\n\
                256 256\n\
            } {\n\
                /compositefont errordict /invalidfont get exec\n\
            } ifelse\n\
            } ifelse\n\
            getinterval def\n\
        end\n\
        /kanjifont exch definefont\n\
        exch\n\
        dup type /nametype eq { findfont } if\n\
        exch\n\
        /FDepVector [ 4 2 roll ] def\n\
        /FontType 0 def\n\
        /FMapType 4 def\n\
        /FontMatrix matrix def\n\
        /Encoding [ 0 1 ] def\n\
        /FontBBox {0 0 0 0} def\n\
        dup /FontName exch def\n\
        currentdict\n\
    end\n\
    definefont pop\n\
} def\n\
\n\
/ws_ellipsedict 6 dict def\n\
ws_ellipsedict /mtrx matrix put\n\
\n\
/ws_ellipse\n\
 { ws_ellipsedict begin\n\
      /yrad exch def\n\
      /xrad exch def\n\
      /y exch def\n\
      /x exch def\n\
      /savematrix mtrx currentmatrix def\n\
      x y translate\n\
      xrad yrad scale\n\
      0 0 1 0 360 arc\n\
      savematrix setmatrix\n\
   end\n\
 } def\n\
\n\
/ws_arcdict 8 dict def\n\
ws_arcdict /mtrx matrix put\n\
\n\
/ws_arcn\n\
 { ws_arcdict begin\n\
      /endangle exch def\n\
      /startangle exch def\n\
      /yrad exch def\n\
      /xrad exch def\n\
      /y exch def\n\
      /x exch def\n\
      /savematrix mtrx currentmatrix def\n\
      x y translate\n\
      xrad yrad scale\n\
      0 0 1 startangle endangle arc\n\
      savematrix setmatrix\n\
   end\n\
 } def\n\
\n\
/ws_arc\n\
 { ws_arcdict begin\n\
      /endangle exch def\n\
      /startangle exch def\n\
      /yrad exch def\n\
      /xrad exch def\n\
      /y exch def\n\
      /x exch def\n\
      /savematrix mtrx currentmatrix def\n\
      x y translate\n\
      xrad yrad scale\n\
      0 0 1 startangle endangle arcn\n\
      savematrix setmatrix\n\
   end\n\
 } def\n\
\n\
/ws_hatchdict 10 dict def\n\
\n\
/ws_hatchbyte\n\
 { currentdict /retstr get exch\n\
   hatch i cellsz mod get put\n\
 } def\n\
\n\
/ws_hatchproc\n\
 { 0 1 widthlim {ws_hatchbyte} for retstr\n\
   /i i 1 add def\n\
 } def\n\
\n\
/ws_hatchfill\n\
 { ws_hatchdict begin\n\
      /h exch def\n\
      /w exch def\n\
      /lty exch def\n\
      /ltx exch def\n\
      /cellsz exch def\n\
      /hatch exch def\n\
      /widthlim w cellsz div cvi 1 sub def\n\
      /retstr widthlim 1 add string def\n\
      /i 0 def\n\
      ws_origctm setmatrix\n\
      ltx lty translate\n\
      w h true [1 0 0 1 0 0] {ws_hatchproc} imagemask\n\
      ltx neg lty neg translate\n\
   end\n\
 } def\n\
\n\
/hatch1 <0102040810204080> def\n\
/hatch2 <8040201008040201> def\n\
/hatch3 <9999999999999999> def\n\
/hatch4 <ff0000ffff0000ff> def\n\
/hatch5 <9966669999666699> def\n\
/hatch6 <ff6666ffff6666ff> def\n\
/hatch7 <0066660000666600> def\n\
\n\
/ws_imgdict 4 dict def\n\
/ws_bwpicstr 1 string def\n\
/ws_colorpicstr 3 string def\n\
/ws_setpixels { ws_imgdict begin /pixels exch def end } def\n\
/ws_setpix { ws_imgdict begin pixels 3 1 roll putinterval end } def\n\
/ws_colorspot\n\
 { ws_imgdict begin\n\
      /index exch def\n\
      pixels index 3 mul 3 getinterval aload pop\n\
      255 mul cvi ws_colorpicstr 2 3 -1 roll put\n\
      255 mul cvi ws_colorpicstr 1 3 -1 roll put\n\
      255 mul cvi ws_colorpicstr 0 3 -1 roll put\n\
      ws_colorpicstr\n\
   end\n\
 } def\n\
/ws_newcolorspot\n\
 { ws_imgdict begin\n\
      /index exch def\n\
      pixels index 3 mul 3 getinterval aload pop setrgbcolor\n\
   end\n\
 } def\n\
/ws_colordict 4 dict def\n\
/colorimage where\n\
 { pop }\n\
 { /colorimage\n\
   { ws_colordict begin\n\
        pop pop pop pop pop\n\
        /ih exch def\n\
        /iw exch def\n\
        /x 0 def\n\
        /y 0 def\n\
        1 1 ih\n\
         { pop 1 1 iw\n\
            { pop currentfile\n\
              ws_bwpicstr readhexstring pop 0 get ws_newcolorspot\n\
              x y moveto 1 0 rlineto 0 1 rlineto -1 0 rlineto\n\
              closepath fill\n\
              /x x 1 add def\n\
            } for\n\
           /y y 1 add def\n\
           /x 0 def\n\
         } for\n\
     end\n\
   } def\n\
 } ifelse\n\
\n\
/ws_transcolorspot\n\
 { ws_imgdict begin\n\
      /index exch def\n\
      pixels index 3 mul 3 getinterval aload pop\n\
      dup 0 lt { pop pop pop false } { setrgbcolor true } ifelse\n\
   end\n\
 } def\n\
\n\
/ws_transcolorimage\n\
 { ws_colordict begin\n\
      pop pop pop pop pop\n\
      /ih exch def\n\
      /iw exch def\n\
      /x 0 def\n\
      /y 0 def\n\
      1 1 ih\n\
       { pop 1 1 iw\n\
          { pop currentfile\n\
            ws_bwpicstr readhexstring pop 0 get ws_transcolorspot\n\
            { x y moveto 1 0 rlineto 0 1 rlineto -1 0 rlineto\n\
              closepath fill\n\
            }\n\
            if\n\
            /x x 1 add def\n\
          } for\n\
         /y y 1 add def\n\
         /x 0 def\n\
       } for\n\
   end\n\
 } def\n\
\n\
\n\
end\n\
\n\
ws_dict begin\n\
/ws_savedpage save def\n\
1 setmiterlimit\n\
1 setlinewidth\n\
0 setgray\n";

char* ws_ps_header2 = "\
gsave\n\
/ws_origctm matrix currentmatrix def\n\n\n";

char* ws_ps_footer = "\n\
grestore\n\
ws_savedpage restore\n\
end\n\
showpage\n";

char* ws_ps_text2 = "\
 0 0 -";

char* ws_ps_text3 = "\
 0 0] makefont setfont\n\
   gsave\n";

char* ws_ps_text4 = "\
 moveto (";

char* ws_ps_text5 = "\
) show\n\
   grestore\n";


