// Module PI : Peida Interactive     PIGraphicPS
// Trace graphiques en PostScript    R. Ansari  97
// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA

#include <stdio.h>

#include "pigraphps.h"

//++
// Class	PIGraphicPS
// Lib		PI
// include	pigraphps.h
//
//   	Classe les services de tracé graphique avec sortie PostScript
//	Toutes les méthodes de tracé de "PIGraphic" sont redéfinies pour
//	produire du PostScript 
//--
//++
// Links	Parent
// PIGraphic
//--
//++
// Links	Voir aussi
// PSFile
//--

//++
// Titre	Constructeurs, méthodes
//--
//++
// PIGraphicPS(PSFile * psf, double x0, double y0, double dx, double dy)
//	Création d'un objet "PIGraphicPS" à partir d'un objet "PSFIle* psf".
//	"(x0, y0)" détermine l'origine du nouveau bloc rectangulaire sur 
//	la page et "dx, dy" l'extension du bloc. 
// PIGraphicPS(PSFile * psf, PIWdg* wdg, double ofx, double ofy, double scale_x, double scale_y)
//	Création d'un objet "PIGraphicPS" à partir d'un objet "PSFIle* psf"
//|	x0 = wdg->XPos()+ofx    y0 = wdg->YPos()+ofy
//|	Extension du bloc dans la page:
//|	Tx = wdg->XSize()*scale_x    Ty = wdg->YSize()*scale_y
//
// int kind()
//	 Renvoie le type ("= PI_PSFileGraphics")
//--

/* --Methode-- */
PIGraphicPS::PIGraphicPS(PSFile * psf, PIWdg* wdg, double ofx, double ofy, 
			 double scale_x, double scale_y)
: PIGraphicGen()
{
BuildFromPSFile(psf, (double)wdg->XPos()+ofx, (double)wdg->YPos()+ofy, 
		(double)wdg->XSize()*scale_x, (double)wdg->YSize()*scale_y, 
		(double)wdg->XSize(), (double)wdg->YSize());
}

/* --Methode-- */
PIGraphicPS::PIGraphicPS(PSFile * psf, double x0, double y0, double dx, double dy)
: PIGraphicGen()
{
BuildFromPSFile(psf, x0, y0, dx, dy, dx, dy);
}

/* --Methode-- */
PIGraphicPS::~PIGraphicPS()
{
mPSOut->EndBloc();
}

/* --Methode-- */
int PIGraphicPS::kind()
{
return PI_PSFileGraphics; 
}


/* --Methode-- */
void PIGraphicPS::BuildFromPSFile(PSFile * psf, double x0, double y0, double tx, double ty,
				  double dx, double dy)
{
mPSOut = psf;

mGOm = PI_GOCopy;

mFCol = mBCol = PI_Grey;
SelForeground(PI_Black);
SelBackground(PI_White);
mLAtt = PI_ThinLine;
SelLine(PI_NormalLine);
// mFAtt = PI_BoldFont;  mFSize = 0;  $CHECK$ Plus besoin 
SelFont();
SelMarker(1, PI_DotMarker);

if (psf) psf->NewBloc(x0, y0, tx, ty, dx, dy);
mXmin = mYmin = 0.;
mXmax = dx;  mYmax = dy;
mFCfMap.red = mFCfMap.blue = mFCfMap.blue = 0;
mBCfMap = mFCfMap; 
}

/* --Methode-- */
void PIGraphicPS::GetGrSpace(PIGrCoord& xmin, PIGrCoord& xmax, PIGrCoord& ymin, PIGrCoord& ymax)
{
xmin = ymin = 0;  
xmax = mXmax; ymax = mYmax;
}

/* --Methode-- */
void PIGraphicPS::Erase(PIGrCoord, PIGrCoord, PIGrCoord, PIGrCoord)
{
// A Faire ??? $CHECK$ 
return;
}

/* --Methode-- */
void PIGraphicPS::DrawString(PIGrCoord x, PIGrCoord y, const char* s, unsigned long pos)
{
if(mPSOut) {
  unsigned long txtdir = pos&PI_TextDirection;
  unsigned long posh = pos & PI_HorizontalPosition;
  unsigned long posv = pos & PI_VerticalPosition;
  int dx,dy;
  double xd = x;
  double yd = y;
  bool fgcsps = CalcStringPositionShift(s, posv, dx, dy);
  if (txtdir == PI_TextDirectionHorizontal) {
    if (fgcsps) yd -= dy;
  }
  else {
    if (txtdir == PI_TextDirectionVerticalDown) xd += dy; 
    else xd -= dy; 
  }
  mPSOut->DrawString(xd, yd, s, mFCol, myFont.GetFontName(), myFont.GetFontAtt(),
		     myFont.GetFontSize(), posh|txtdir); 
}
return;
}

/* --Methode-- */
void PIGraphicPS::DrawOpaqueString(PIGrCoord x, PIGrCoord y, const char* s, unsigned long pos)
{
if(mPSOut) {
  unsigned long txtdir = pos&PI_TextDirection;
  unsigned long posh = pos & PI_HorizontalPosition;
  unsigned long posv = pos & PI_VerticalPosition;
  int dx,dy;
  double xd = x;
  double yd = y;
  bool fgcsps = CalcStringPositionShift(s, posv, dx, dy);
  if (txtdir == PI_TextDirectionHorizontal) {
    if (fgcsps) yd -= dy;
  }
  else {
    if (txtdir == PI_TextDirectionVerticalDown) xd += dy; 
    else xd -= dy; 
  }
  mPSOut->DrawString(xd, yd, s, mFCol, myFont.GetFontName(), myFont.GetFontAtt(),
		     myFont.GetFontSize(), posh|txtdir); 
}
return;
}

 
/* --Methode-- */
void PIGraphicPS::DrawLine(PIGrCoord x1, PIGrCoord y1, PIGrCoord x2, PIGrCoord y2)
{
if(mPSOut)
  mPSOut->DrawLine((double)x1,(double)y1,(double)x2,(double)y2,mFCol,mLAtt);
return;
}


/* --Methode-- */
void PIGraphicPS::DrawBox(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
if(mPSOut)
  mPSOut->DrawBox((double)x0,(double)y0,(double)dx,(double)dy,mFCol,mLAtt);
return;
}

/* --Methode-- */
void PIGraphicPS::DrawFBox(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
if(mPSOut)
  mPSOut->DrawFBox((double)x0,(double)y0,(double)dx,(double)dy, mFCol, mFCol, mLAtt);
return;
}

/* --Methode-- */
void PIGraphicPS::DrawCircle(PIGrCoord x0, PIGrCoord y0, PIGrCoord r)
{
if(mPSOut)
  mPSOut->DrawCircle((double)x0,(double)y0,(double)r,mFCol,mLAtt);
return;
}

/* --Methode-- */
void PIGraphicPS::DrawFCircle(PIGrCoord x0, PIGrCoord y0, PIGrCoord r)
{
if(mPSOut)
  mPSOut->DrawFCircle((double)x0,(double)y0,(double)r,mFCol,mFCol);
return;
}

/* --Methode-- */
void PIGraphicPS::DrawOval(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
if(mPSOut)
  mPSOut->DrawArc((double)x0,(double)y0,(double)dx,(double)dy,0.,360.,mFCol,mLAtt);
return;
}

/* --Methode-- */
void PIGraphicPS::DrawFOval(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
if(mPSOut)
  mPSOut->DrawFArc((double)x0,(double)y0,(double)dx,(double)dy,0.,360.,mFCol,mFCol);
return;

}

/* --Methode-- */
void PIGraphicPS::DrawPolygon(PIGrCoord *x, PIGrCoord *y, int n, bool cinc)
{
int i;
double *xtmp;
double *ytmp;

if(! mPSOut) return;

xtmp = new double[n];
ytmp = new double[n];
for(i = 0 ; i < n ; i++) {xtmp[i] = (double)x[i] ; ytmp[i] = (double)y[i] ; }
//double xoff,yoff;
//if (cinc) { xoff=yoff=0.; }   // Coord en mode incremental
//else { xoff = (double)x[0];  yoff = (double)y[0]; }   //   Coord en mode absolu
//xtmp[0] = (double)x[0];
//ytmp[0] = (double)y[0];
//for(i=1;i<n;i++) {
//  xtmp[i] = (double)x[i]-xoff;
//  ytmp[i] = (double)y[i]-yoff;
//}
mPSOut->DrawPolygon(xtmp,ytmp,n,mFCol,mLAtt,cinc);
delete[] xtmp;
delete[] ytmp;

return;
}


/* --Methode-- */
void PIGraphicPS::DrawFPolygon(PIGrCoord *x, PIGrCoord *y, int n, bool cinc)
{
int i;
double *xtmp;
double *ytmp;

if(! mPSOut) return;

xtmp = new double[n];
ytmp = new double[n];
for(i = 0 ; i < n ; i++) {xtmp[i] = (double)x[i] ; ytmp[i] = (double)y[i] ; }
//double xoff,yoff;
//if (cinc) { xoff=yoff=0.; }   // Coord en mode incremental
//else { xoff = (double)x[0];  yoff = (double)y[0]; }   //   Coord en mode absolu
//xtmp[0] = (double)x[0];
//ytmp[0] = (double)y[0];
//for(i=1;i<n;i++) {
//  xtmp[i] = (double)x[i]-xoff;
//  ytmp[i] = (double)y[i]-yoff;
//}
mPSOut->DrawFPolygon(xtmp,ytmp,n,mFCol,mFCol,mLAtt,cinc);
delete[] xtmp;
delete[] ytmp;

return;
}

/* --Methode-- */
void PIGraphicPS::DrawArc(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy,double degdeb, double deltadeg)
{
if(mPSOut)
  mPSOut->DrawArc((double)x0,(double)y0,(double)dx,(double)dy,degdeb,deltadeg,mFCol,mLAtt);
return;
}

/* --Methode-- */
void PIGraphicPS::DrawFArc(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy,double degdeb, double deltadeg)
{
if(mPSOut)
  mPSOut->DrawFArc((double)x0,(double)y0,(double)dx,(double)dy,degdeb,deltadeg,mFCol,mFCol);
return;
}

/* --Methode-- */
void PIGraphicPS::DrawMarker(PIGrCoord x0, PIGrCoord y0)
{
if(mPSOut)
  mPSOut->DrawMarker((double)x0,(double)y0,mMrk,mFCol,mMrkSz);
return;
}

/* --Methode-- */
void PIGraphicPS::DrawMarkers(PIGrCoord *x, PIGrCoord *y, int n)
{
int i;
double *xtmp;
double *ytmp;

if( !mPSOut)  return;

xtmp = new double[n];
ytmp = new double[n];
for(i=0;i<n;i++){
  xtmp[i] = (double)x[i];
  ytmp[i] = (double)y[i];
}
mPSOut->DrawMarkers(xtmp,ytmp,n,mMrk,mFCol, mMrkSz);
delete[] xtmp;
delete[] ytmp;

return;
}


/* --Methode-- */
void PIGraphicPS::DrawPixmap(PIGrCoord x, PIGrCoord y, unsigned char *pix, 
                            int sx, int sy, PIColorMap* cmap)
{
if ( (sx < 1) || (sy < 1) )  return;
if ((pix == NULL) || (cmap == NULL)) return;
if(mPSOut) 
  mPSOut->Image((double)x, (double)y, (double)sx, (double)sy, sx, sy, pix, cmap);
return;
}

/* --Methode-- */
void PIGraphicPS::SelForeground(PIColors col)
{
mFCol = col;
return;
}

/* --Methode-- */
void PIGraphicPS::SelBackground(PIColors col)
{
mBCol = col;
return;
}

/* --Methode-- */
void PIGraphicPS::SelForeground(PIColorMap& cmap, int cid)
{
// A Faire Voir Nicolas  
mFCfMap = cmap.GetColor(cid);
mFCol = PI_ColorFromMap;
mPSOut->SelForeground(cmap, cid) ; 
return;
}

/* --Methode-- */
void PIGraphicPS::SelBackground(PIColorMap& cmap, int cid)
{
// A Faire Voir Nicolas  
mBCfMap = cmap.GetColor(cid);
mBCol = PI_ColorFromMap;
return;
}

/* --Methode-- */
void PIGraphicPS::SelGOMode(PIGOMode mod)
{
mGOm = mod;
return;
}
/* --Methode-- */
void PIGraphicPS::SelFont(PIFont & fnt)
{
//  $CHECK$   -  Reza 13/06/99
if (myFont == fnt)  return;
myFont = fnt;
  // C'est peu-etre mieux 
  // SelFontSzPt(fnt.GetFontSize(), fnt.GetFontAtt());
}


static int fntsz[5] = {8,10,12,14,16};

/* --Methode-- */
void PIGraphicPS::SelFont(PIFontSize sz, PIFontAtt att)
{
//  $CHECK$   -  Reza 13/06/99
PIFont fnt(myFont.GetFontName());
fnt.SetFontAtt(att);
fnt.SetFontSz(sz);
SelFont(fnt);
return;
}

/* --Methode-- */
void PIGraphicPS::SelFontSzPt(int npt, PIFontAtt att)
{
//  $CHECK$   -  Reza 13/06/99
PIFont fnt(npt, myFont.GetFontName(), att);
SelFont(fnt);
}



/* --Methode-- */
void PIGraphicPS::SelLine(PILineAtt const& att)
{
mLAtt = att;
return;
}


/* --Methode-- */
void PIGraphicPS::SelMarker(int msz, PIMarker mrk)
{
if (msz > 1)  { mMrk = mrk;  mMrkSz = msz; }
else  { mMrk = PI_DotMarker;  mMrkSz = 1; }
return;
}


/* --Methode-- */
void PIGraphicPS::SetClipRectangle(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
  mPSOut->SetClipRectangle((double)x0, (double)y0, (double)dx, (double)dy);
}

/* --Methode-- */
void PIGraphicPS::ClearClipRectangle()
{ 
  mPSOut->ClearClipRectangle();
}

/* --Methode-- */
PIColors  PIGraphicPS::GetForeground() 
{
return (mFCol);
}

/* --Methode-- */
PIColors  PIGraphicPS::GetBackground() 
{
return (mBCol);
}


/* --Methode-- */
PIGOMode   PIGraphicPS::GetGOMode()
{
return (mGOm);
}


/* --Methode-- */
PILineAtt  PIGraphicPS::GetLineAtt()
{
return (mLAtt);
}

/* --Methode-- */
PIMarker   PIGraphicPS::GetMarker()
{
return (mMrk);
}

/* --Methode-- */
int        PIGraphicPS::GetMarkerSize()
{
return (mMrkSz);
}

/* --Methode-- 
int        PIGraphicPS::GetFontHeight(int& asc, int& desc)   
{
  $CHECK$  A refaire , voir Nicolas  
asc = mFSize; desc = 0; 
return(asc+desc);
} 
*/


/* --Methode-- 
PIGrCoord PIGraphicPS::CalcStringWidth(char const* s)
{
return((double)(mFSize*strlen(s)*0.5));   
//  facteur 0.5 ad hoc $CHECK$  Voir Nicolas 
}
*/
 

/* --Methode-- */
void PIGraphicPS::SaveGraphicAtt()
{  
// Pour optimier l'implementation de PIBaseWdgGen
sFCol = mFCol;    sBCol = mBCol;
sGOm = mGOm;
sFont = myFont; 
sMrk = mMrk;   sMrkSz = mMrkSz;
return;
}


/* --Methode-- */
void PIGraphicPS::RestoreGraphicAtt()
{
  if (sFCol != PI_ColorFromMap) SelForeground(sFCol);  
// else    A faire Nicolas  
  if (sBCol != PI_ColorFromMap) SelBackground(sBCol);
// else    A faire Nicolas  
  SelGOMode(sGOm);
  SelFont(sFont);
  SelLine(sLAtt);
  SelMarker(sMrkSz, sMrk);
  return;
}





