/** 
 *  Yudit Unicode Editor Source File
 *
 *  GNU Copyright (C) 1997-2023  Gaspar Sinai <gaspar@yudit.org>  
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License, version 2,
 *  dated June 1991. See file COPYYING for details.
 *
 *  This program 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
#include "swindow/SGPrimitive.h"
#include "stoolkit/SString.h"
#include "stoolkit/STypes.h" 

#define SS_SHORT_KEY 0


/**
 * This is the graphic primitives.
 * This is what happens between a SPen'ed newpath and stroke or fill.
 */
  
SGPrimitive::SGPrimitive (void)
{
  type = NONE;
}

SGPrimitive::SGPrimitive (const SGPrimitive& p)
{
  type = p.type;
  for (unsigned int i=0; i<MAX_SG_PARAMS; i++)
  {
    params[i] = p.params[i];
  }
}

SGPrimitive
SGPrimitive::operator = (const SGPrimitive& p)
{
  type = p.type;
  for (unsigned int i=0; i<MAX_SG_PARAMS; i++)
  {
    params[i] = p.params[i];
  }
  return *this;
}

SGPrimitive::~SGPrimitive ()
{
}

SObject*
SGPrimitive::clone() const
{
  SGPrimitive* p = new SGPrimitive();
  CHECK_NEW (p);
  p->type = type;
  for (unsigned int i=0; i<MAX_SG_PARAMS; i++)
  {
    p->params[i] = params[i];
  }
  return p;
}
  
/**
 * return  the keys, that is all the drawing parameters
 * moved to the origin
 */
SString
SGPrimitive::getKey (double originx, double originy) const
{
  char arr[256];
  arr[0] = 0;
#if SS_SHORT_KEY
  int  s[MAX_SG_PARAMS+1];
  unsigned int  sLen=0;
#endif
  switch (type)
  {
  case CURVETO:
#if SS_SHORT_KEY
    sLen = 7;
    s[0] = (int) type;
    s[1] = (int) (params[0] - originx); s[2] = (int) (params[1] - originy);
    s[3] = (int) (params[2] - originx); s[4] = (int) (params[3] - originy);
    s[5] = (int) (params[4] - originx); s[6] = (int) (params[5] - originy);
#else
    snprintf (arr, 256, "%d=%g,%g,%g,%g,%g,%g;", (int) type, 
         params[0] - originx, params[1] - originy,
         params[2] - originx, params[3] - originy,
         params[4] - originx, params[5] - originy);
#endif
    break;
  case TRANSLATE:
#if SS_SHORT_KEY
    sLen = 3;
    s[0] = (int) type;
    s[1] = (int) (params[0]); s[2] = (int) (params[1]);
#else
    snprintf (arr, 256, "%d=%g,%g;", (int) type, 
       params[0], params[1]);
#endif
    break;
  case LINETO:
  case MOVETO:
#if SS_SHORT_KEY
    sLen = 3;
    s[0] = (int) type;
    s[1] = (int) (params[0] - originx); s[2] = (int) (params[1] - originy);
#else
    snprintf (arr, 256, "%d=%g,%g;", (int) type, 
       params[0] - originx, params[1] - originy);
#endif
    break;
  case CLOSEPATH:
  case PUSHMATRIX:
  case POPMATRIX:
  case STROKE:
  case FILL:
  case SCALE:
  case NEWPATH:
#if SS_SHORT_KEY
    sLen = 1;
    s[0] = (int) type;
#else
    snprintf (arr, 256, "%d;", (int) type);
#endif
    break;
  /*  
   *  TODO: BUG: totate probably will not work because it can 
   *  not be tied to origin 
   */
  case ROTATE:
#if SS_SHORT_KEY
    sLen = 2;
    s[0] = (int) type;
    s[1] = (int) (params[0]); 
#else
    snprintf (arr, 256, "%d=%g;", (int) type, params[0]);
#endif
    break;
  default:
    break;
  }
#if SS_SHORT_KEY
#ifdef GASPAR
  SString a((char*) s, sLen * sizeof (int));
  fprintf (stderr, ">");
  for (unsigned int i=0; i<a.size(); i++)
  {
    fprintf (stderr, "0x%02x ", (int)(unsigned char)a[i]);
  }
  fprintf (stderr, "\n");
#endif
  return SString((char*) s, sLen * sizeof (int));
#else
  return SString(arr);
#endif
}

double
SGPrimitive::getOriginX (double originx)
{
  switch (type)
  {
  case MOVETO:
  case LINETO:
   if (params[0] < originx) return params[0];
   break;
  case CURVETO:
   if (params[0] < originx) return params[0];
   if (params[2] < originx) return params[2];
   if (params[4] < originx) return params[4];
   break;
   break;
  default:
    break;
  }
  return originx;
}

double
SGPrimitive::getOriginY (double originy)
{
  switch (type)
  {
  case MOVETO:
  case LINETO:
   if (params[1] < originy) return params[1];
   break;
  case CURVETO:
   if (params[1] < originy) return params[1];
   if (params[3] < originy) return params[3];
   if (params[5] < originy) return params[5];
   break;
   break;
  default:
    break;
  }
  return originy;
}

void
SGPrimitive::newpath ()
{
  type = NEWPATH;
}

void
SGPrimitive::moveto (double x, double y)
{
  type = MOVETO;
  params[0] = x;
  params[1] = y;
}

void
SGPrimitive::lineto (double x, double y)
{
  type = LINETO;
  params[0] = x;
  params[1] = y;
}

void
SGPrimitive::stroke (int x, int y, unsigned int w, unsigned int h)
{
  type = STROKE;
  params[0] = (double) w;
  params[1] = (double) h;
}

void
SGPrimitive::fill (int x, int y, unsigned int w, unsigned int h)
{
  type = FILL;
  params[0] = (double) w;
  params[1] = (double) h;
}

void
SGPrimitive::curveto (double x0, double y0, 
       double x1, double y1, double x2, double y2)
{
  type = CURVETO;
  params[0] = x0;
  params[1] = y0;
  params[2] = x1;
  params[3] = y1;
  params[4] = x2;
  params[5] = y2;
}
void
SGPrimitive::closepath()
{
  type = CLOSEPATH;
}

void
SGPrimitive::pushmatrix()
{
  type = PUSHMATRIX;
}

void
SGPrimitive::popmatrix()
{
  type = POPMATRIX;
}

void
SGPrimitive::scale (double x, double y)
{
  type = SCALE;
  params[0] = x;
  params[1] = y;
}

void
SGPrimitive::translate (double x, double y)
{
  type = TRANSLATE;
  params[0] = x;
  params[1] = y;
}

void
SGPrimitive::rotate (double angle)
{
  type = ROTATE;
  params[0] = angle;
}

