// Module PI : Peida Interactive     PIGraphicX
// Trace graphiques- Implementation X11  R. Ansari  97
// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA

#include <stdio.h>
#include <math.h>

#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Xutil.h>

#include "pigraphx.h"


/*  Variables globales pour modifier les GC  */
#define NMAXCOL  32
static  PIXColor colpix[NMAXCOL];

/*  GC pour DrawPixmap   
    static GC dpxgc;   Pas utile ?? - Reza 02/05/2002 */

// #define DEBUG_PIBWDGX     Flag pour impression de debug etc ...

/* --Methode-- */
PIGraphicX::PIGraphicX(PIWdg* wdg)
: PIGraphicGen(wdg)
{

GlInit();

if (MyWdg()) {
  mDisp = XtDisplay(MyWdg());       // Structure Display X associe
  mWId = XtWindow(MyWdg());   // Le drawable X
  }
else mDisp = PIXDisplay();       // Structure Display X associe

XGCValues  xgv;
xgv.function = GXcopy;
xgv.plane_mask = ~0;
mDefGC = XCreateGC (PIXDisplay(), XtWindow(PIXtTopWdg()), GCFunction | GCPlaneMask, &xgv);
mMrkGC = XCreateGC (PIXDisplay(), XtWindow(PIXtTopWdg()), GCFunction | GCPlaneMask, &xgv);
mFgMrkGCOK = false;
Init();
}

/* --Methode-- */
PIGraphicX::PIGraphicX(PIScreenBuffer* grb)
: PIGraphicGen(grb)
{
GlInit();

mDisp = PIXDisplay();       // Structure Display X associe
mWId = grb->XScrBuffer();

XGCValues  xgv;
xgv.function = GXcopy;
xgv.plane_mask = ~0;
mDefGC = XCreateGC (mDisp, mWId, GCFunction | GCPlaneMask, &xgv);
mMrkGC = XCreateGC (PIXDisplay(), XtWindow(PIXtTopWdg()), GCFunction | GCPlaneMask, &xgv);
mFgMrkGCOK = false;
Init();
}


/* --Methode-- */
void PIGraphicX::Init()
{
mGOm = PI_GOCopy;
mFCol = mBCol = PI_Grey;
SelForeground(PI_Black);
SelBackground(PI_White);
mLAtt = PI_NotDefLineAtt;
 XSetFont(mDisp, DefGC(), myFont.GetXFontId());  // Pour initialiser la fonte ds le GC 
SelLine(PI_NormalLine);
SelMarker(1, PI_DotMarker);  
mFCfMap = colpix[PI_Black];  mBCfMap = colpix[PI_White];
mFgMrkGCOK = false;
}

/* --Methode-- */
PIGraphicX::~PIGraphicX()
{
XFreeGC(mDisp, mDefGC);
XFreeGC(mDisp, mMrkGC);
}

/* --Methode-- */
int PIGraphicX::kind()
{
if (myWdg != NULL) return (PI_ScrWindowGraphics);
else if (myGrb != NULL) return (PI_ScrBufferGraphics);
else return(PI_UnknownGraphics);
}

/* --Methode-- */
void PIGraphicX::TerminateInit()
{
if (MyWdg() == NULL)  { fprintf(stderr, "BUG/PIGraphicX::TerminateInit() for NULL Wdg \n"); return; }
mDisp = XtDisplay(MyWdg());       // Structure Display X associe
mWId = XtWindow(MyWdg());   // Le drawable X
}

/* --Methode-- */
void PIGraphicX::Erase(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
XClearArea (mDisp,mWId, (int)x0, (int)y0, (int)dx, (int)dy, False );
return;
}

/* --Methode-- */
void PIGraphicX::DrawString(PIGrCoord x, PIGrCoord y, const char* s, unsigned long pos)
{
int dx, dy, xi, yi;
xi = x;  yi = y;
bool fgcsps = CalcStringPositionShift(s, pos, dx, dy);
unsigned long txtdir = pos&PI_TextDirection;
if (txtdir == PI_TextDirectionHorizontal) {
  if (fgcsps) { xi -= dx;  yi -= dy; }
  XDrawString (mDisp, mWId, DefGC(), xi, yi, s, strlen(s));
}
else { 
  if (txtdir == PI_TextDirectionVerticalDown) { xi += dy; yi -= dx; }
  else {   xi -= dy; yi += dx; }
  DrawVerticalString(xi, yi, s, txtdir, false);
}
return;
}

/* --Methode-- */
void PIGraphicX::DrawOpaqueString(PIGrCoord x, PIGrCoord y, const char* s, unsigned long pos)
{
int dx, dy, xi, yi;
xi = x;  yi = y;
bool fgcsps = CalcStringPositionShift(s, pos, dx, dy);
unsigned long txtdir = pos&PI_TextDirection;
if (txtdir == PI_TextDirectionHorizontal) {
  if (fgcsps) { xi -= dx;  yi -= dy; }
  XDrawImageString (mDisp, mWId, DefGC(), xi, yi, s, strlen(s));
}
else { 
  if (txtdir == PI_TextDirectionVerticalDown) { xi += dy; yi -= dx; }
  else {   xi -= dy; yi += dx; }
  DrawVerticalString(xi, yi, s, txtdir, true);
}
return;
}

 
/* --Methode-- */
void PIGraphicX::DrawLine(PIGrCoord x1, PIGrCoord y1, PIGrCoord x2, PIGrCoord y2)
{
XDrawLine(mDisp, mWId, DefGC(), (int)x1, (int)y1, (int)x2, (int)y2);
return;
}


/* --Methode-- */
void PIGraphicX::DrawBox(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
int ix0 = x0;
int iy0 = y0;
int idx = dx;
int idy = dy;
if (idx < 0)  { ix0 += idx;  idx = -idx; }
if (idy < 0)  { iy0 += idy;  idy = -idy; }
XDrawRectangle(mDisp, mWId, 
               DefGC(), ix0, iy0, idx, idy);
return;
}

/* --Methode-- */
void PIGraphicX::DrawFBox(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
int ix0 = x0;
int iy0 = y0;
int idx = dx;
int idy = dy;
if (idx < 0)  { ix0 += idx;  idx = -idx; }
if (idy < 0)  { iy0 += idy;  idy = -idy; }
XFillRectangle(mDisp, mWId, 
               DefGC(), ix0, iy0, idx, idy);
return;
}

/* --Methode-- */
void PIGraphicX::DrawCircle(PIGrCoord x0, PIGrCoord y0, PIGrCoord r)
{
XDrawArc(mDisp, mWId, DefGC(),
         (int)x0-(int)r, (int)y0-(int)r, 2*(int)r, 2*(int)r, 0, 360*64);
return;
}

/* --Methode-- */
void PIGraphicX::DrawFCircle(PIGrCoord x0, PIGrCoord y0, PIGrCoord r)
{
XFillArc(mDisp, mWId, DefGC(),
         (int)x0-(int)r, (int)y0-(int)r, 2*(int)r, 2*(int)r, 0, 360*64);
return;
}

/* --Methode-- */
void PIGraphicX::DrawOval(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
XDrawArc(mDisp, mWId, DefGC(),
         (int)x0-(int)dx, (int)y0-(int)dy, (int)dx*2, (int)dy*2, 0, 360*64);
return;
}

/* --Methode-- */
void PIGraphicX::DrawFOval(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
XFillArc(mDisp, mWId, DefGC(),
         (int)x0-(int)dx, (int)y0-(int)dy, (int)dx*2, (int)dy*2, 0, 360*64);
return;
}

// Pour les fonctions de trace avec un plusieurs coordonnees
#define NMXXPOINTS  30 

/* --Methode-- */
void PIGraphicX::DrawPolygon(PIGrCoord *x, PIGrCoord *y, int n, bool cinc)
{
XPoint multipoint[NMXXPOINTS];
XPoint *pxp;
int i;

if (n <= 0)  return;
if (n > NMXXPOINTS)  pxp = new XPoint[n];
else pxp = multipoint;
for(i=0; i<n; i++)  { pxp[i].x = x[i];  pxp[i].y = y[i]; } 
int mode = CoordModeOrigin;
if (cinc) mode =  CoordModePrevious;
XDrawLines(mDisp, mWId, DefGC(), pxp, n, mode);
if (n > NMXXPOINTS)  delete[] pxp;

return;
}


/* --Methode-- */
void PIGraphicX::DrawFPolygon(PIGrCoord *x, PIGrCoord *y, int n, bool cinc)
{
XPoint multipoint[NMXXPOINTS];
XPoint *pxp;
int i;

if (n <= 0)  return;
if (n > NMXXPOINTS)  pxp = new XPoint[n];
else pxp = multipoint;
for(i=0; i<n; i++)  { pxp[i].x = x[i];  pxp[i].y = y[i]; } 
int mode = CoordModeOrigin;
if (cinc) mode =  CoordModePrevious;
XFillPolygon(mDisp, mWId, DefGC(), pxp, n, 
                        Complex, mode);
if (n > NMXXPOINTS)  delete[] pxp;

return;
}


/* --Methode-- */
void PIGraphicX::DrawArc(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy, 
                         double degdeb, double deltadeg)
{
// Convention X est ds le sens trigo inverse
degdeb = 360. - (degdeb+deltadeg);
XDrawArc(mDisp, mWId, DefGC(),
         (int)x0-(int)dx, (int)y0-(int)dy, (int)dx*2, (int)dy*2, (int)(degdeb*64.), (int)(deltadeg*64.));
return;
}

/* --Methode-- */
void PIGraphicX::DrawFArc(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy, 
                         double degdeb, double deltadeg)
{
degdeb = 360. - (degdeb+deltadeg);
XFillArc(mDisp, mWId, DefGC(),
         (int)x0-(int)dx, (int)y0-(int)dy, (int)dx*2, (int)dy*2, (int)(degdeb*64.), (int)(deltadeg*64.));
return;
}

// Coordonnees pour tracer une etoile a 5 branches 
static float starcoordx[10], starcoordy[10];

/* --Methode-- */
void PIGraphicX::DrawMarker(PIGrCoord x0, PIGrCoord y0)
{

if (mMrk == PI_DotMarker) {
  XDrawPoint(mDisp, mWId, DefGC(), (int)x0, (int)y0);
  return;
}
else  {
  int x1,x2,y1,y2,r;
  float hmsz = mMrkSz/2;
  float dmsz = mMrkSz-hmsz;
  XPoint pxp[12];
  int k;
  bool fgcgc = SetupMrkGC();
  switch (mMrk) {
    case  PI_PlusMarker :
      x1 = (float)x0-hmsz;   y1 = y0;
      x2 = (float)x0+dmsz;   y2 = y1;
      XDrawLine(mDisp, mWId, mMrkGC, x1, y1, x2, y2);
      x1 = x0;  y1 = (float)y0-hmsz;
      x2 = x1;  y2 = (float)y0+dmsz;
      XDrawLine(mDisp, mWId, mMrkGC, x1, y1, x2, y2);
      break;
    case  PI_CrossMarker :
      x1 = (float)x0-hmsz;   y1 = (float)y0-hmsz;
      x2 = (float)x0+dmsz;   y2 = (float)y0+dmsz;
      XDrawLine(mDisp, mWId, mMrkGC, x1, y1, x2, y2);
      XDrawLine(mDisp, mWId, mMrkGC, x1, y2, x2, y1);
      break;  
    case PI_CircleMarker :
    case PI_FCircleMarker :
      r = hmsz;
      x1 = (int)x0-r;  y1 = (int)y0-r;
      if (mMrk == PI_CircleMarker) 
	XDrawArc(mDisp, mWId, mMrkGC, x1, y1, 2*r, 2*r, 0, 360*64);
      else XFillArc(mDisp, mWId, mMrkGC, x1, y1, 2*r, 2*r, 0, 360*64);
      break;
    case PI_BoxMarker :
    case PI_FBoxMarker :
      pxp[0].x = (int)x0-hmsz;  pxp[0].y = (int)y0-hmsz;
      pxp[1].x = (int)x0+hmsz;  pxp[1].y = (int)y0-hmsz;
      pxp[2].x = (int)x0+hmsz;  pxp[2].y = (int)y0+hmsz;
      pxp[3].x = (int)x0-hmsz;  pxp[3].y = (int)y0+hmsz;
      pxp[4].x = (int)x0-hmsz;  pxp[4].y = (int)y0-hmsz;
      if (mMrk == PI_BoxMarker) MrkDrawPolygon(pxp, 5, false);
      else MrkDrawFPolygon(pxp, 5, false);
      break;
    case  PI_TriangleMarker :
    case  PI_FTriangleMarker :
      pxp[1].x = mMrkSz; pxp[1].y = 0; pxp[2].x = -hmsz; pxp[2].y = -mMrkSz;
      pxp[3].x = -dmsz;  pxp[3].y = +mMrkSz; pxp[0].x = (float)x0-hmsz; pxp[0].y = (float)y0+hmsz;
      if (mMrk == PI_TriangleMarker) MrkDrawPolygon(pxp, 4, true);
      else MrkDrawFPolygon(pxp, 4, true);
      break;
    case  PI_StarMarker :
    case  PI_FStarMarker :
      for(k=0; k<10; k++) {
        pxp[k].x = (int)(starcoordx[k]*hmsz+(float)x0+0.5);
        pxp[k].y = (int)(starcoordy[k]*hmsz+(float)y0+0.5);
        }
      pxp[10].x = pxp[0].x;   pxp[10].y = pxp[0].y;
      if (mMrk == PI_StarMarker)   MrkDrawPolygon(pxp, 11, false);
      else  MrkDrawFPolygon(pxp, 11, false);
      break;
    default :
      XDrawPoint(mDisp, mWId, DefGC(), x0, y0);
      break;
    }
  if (fgcgc) mFgMrkGCOK = false;
  }

return;
}

/* --Methode-- */
void PIGraphicX::DrawMarkers(PIGrCoord *x, PIGrCoord *y, int n)
{
int i;
if (n <= 0)  return;
if (mMrk == PI_DotMarker)
  {
  XPoint multipoint[NMXXPOINTS];
  XPoint *pxp;
  if (n > NMXXPOINTS)  pxp = new XPoint[n];
  else pxp = multipoint;
  for(i=0; i<n; i++)  { pxp[i].x = x[i];  pxp[i].y = y[i]; } 
  XDrawPoints(mDisp, mWId, DefGC(), pxp, n, CoordModeOrigin);
  if (n > NMXXPOINTS)  delete[] pxp;  
  }
else { 
  SetupMrkGC();
  for(i=0; i<n; i++) DrawMarker(x[i], y[i]);
  mFgMrkGCOK = false;
}
return;
}


/* --Methode-- */
void PIGraphicX::DrawPixmap(PIGrCoord x, PIGrCoord y, unsigned char *pix, 
                            int sx, int sy, PIColorMap* cmap)
{
Window xw;
Display * mdsp;
int scr;
int depth;
int pad;
int i,j;
XImage * ximg;

if ( (sx < 1) || (sy < 1) )  return;
if ((pix == NULL) || (cmap == NULL)) return; 

  
xw = mWId;
mdsp = PIXDisplay();
scr = PIXScreen();

depth = DefaultDepth(mdsp,scr);
pad = (depth > 8) ? 32 : 8;
ximg = XCreateImage (mdsp,DefaultVisual(mdsp,scr),
                     depth,ZPixmap,0,NULL, sx, sy, pad,0);
if (ximg == NULL)  return;
ximg->data = new char [sy*ximg->bytes_per_line];
if (ximg->data == NULL)  
  { XFree(ximg); return; }

for(j=0; j<sy; j++)
  for(i=0; i<sx; i++)
    { XPutPixel(ximg, i, j, cmap->Color(*pix) );  pix++; }

XPutImage(mdsp, xw, DefGC(), ximg, 0, 0, (int)x, (int)y, sx, sy);

delete[] ximg->data;
XFree(ximg); 
return;
}

/* --Methode-- */
bool PIGraphicX::SetupMrkGC()
{
if (mFgMrkGCOK) return(false);
XCopyGC(mDisp, DefGC(), GCFunction|GCForeground|GCBackground|GCPlaneMask, mMrkGC); 
XSetLineAttributes(mDisp, mMrkGC, 1, LineSolid, CapButt, JoinMiter);
mFgMrkGCOK = true;
return true;
}

/* --Methode-- */
void PIGraphicX::MrkDrawPolygon(XPoint *pxp, int n, bool cinc)
{

if (n <= 0)  return;
int mode = CoordModeOrigin;
if (cinc) mode =  CoordModePrevious;
XDrawLines(mDisp, mWId, mMrkGC, pxp, n, mode);

return;
}


/* --Methode-- */
void PIGraphicX::MrkDrawFPolygon(XPoint *pxp, int n, bool cinc)
{
int mode = CoordModeOrigin;
if (cinc) mode =  CoordModePrevious;
XFillPolygon(mDisp, mWId, mMrkGC, pxp, n, 
                        Complex, mode);
return;
}


/* --Methode-- */
void PIGraphicX::DrawVerticalString(int x, int y, const char* s, unsigned long pos, bool imgs)
{
  int fh, fasc, fdes;
  fh = GetFont().GetFontHeight(fasc, fdes); 
  int sw = GetFont().GetStringWidth(s);

  Display * dsx = mDisp;
  Window rw = DefaultRootWindow(dsx);
  Pixmap pxm = XCreatePixmap(dsx, rw, sw, fh, 1 );

  XGCValues  xgv;
  xgv.function = GXcopy;
  xgv.plane_mask = ~0;
  GC gcbm = XCreateGC (dsx, pxm, GCFunction | GCPlaneMask, &xgv);
  XSetForeground(dsx, gcbm, ~0); 
  XSetBackground(dsx, gcbm, 0);
  XSetFont(mDisp, gcbm, myFont.GetXFontId());
  
  XDrawImageString (dsx, pxm, gcbm, 0, fasc, s, strlen(s));
  XImage* ximg = XGetImage(dsx, pxm, 0, 0, sw, fh, 0xFFFFFFFF, ZPixmap);

  Pixmap pxm2 = XCreatePixmap(dsx, rw, fh, sw, 1 );
  XImage* ximg2 =  XGetImage(dsx, pxm2, 0, 0, fh, sw, 0xFFFFFFFF, ZPixmap);
  //  On recopie de ximg -> ximg2 en echangeant x,y
  int i,j;
  bool fgdown = ((pos&PI_TextDirection) == PI_TextDirectionVerticalDown);
  if (fgdown) {
    for(i=0; i<sw; i++)
      for(j=0; j<fh; j++)
	XPutPixel(ximg2, fh-j-1, i, XGetPixel(ximg, i, j));
  }
  else {
    for(i=0; i<sw; i++)
      for(j=0; j<fh; j++)
	XPutPixel(ximg2, j, sw-i-1, XGetPixel(ximg, i, j));
  }
  XPutImage(dsx, pxm2, gcbm, ximg2, 0, 0, 0, 0, fh, sw);
  GC gcvis;
  GC gcvs = XCreateGC (dsx, mWId, GCFunction | GCPlaneMask, &xgv);
  XCopyGC(dsx, DefGC(), ~0, gcvs); 
  XSetStipple(dsx, gcvs, pxm2);
  XSetFillStyle(dsx, gcvs, FillStippled);
  if (imgs) {
    gcvis = XCreateGC (dsx, mWId, GCFunction | GCPlaneMask, &xgv);
    XCopyGC(dsx, DefGC(), ~0, gcvis); 
    if (mBCol == PI_ColorFromMap)  XSetForeground(mDisp, gcvis, mBCfMap);
    else  XSetForeground(mDisp, gcvis, colpix[mBCol]); 
  }
  if (fgdown) {
    XSetTSOrigin(dsx, gcvs, x-fdes, y);
    if (imgs)  XFillRectangle(dsx, mWId, gcvis, x-fdes, y, fh, sw);
    XFillRectangle(dsx, mWId, gcvs, x-fdes, y, fh, sw);
  }
  else {
    XSetTSOrigin(dsx, gcvs, x-fasc, y-sw);
    if (imgs) XFillRectangle(dsx, mWId, gcvis, x-fasc, y-sw, fh, sw);
    XFillRectangle(dsx, mWId, gcvs, x-fasc, y-sw, fh, sw);
  }
  // Cleaning  
  XDestroyImage(ximg);
  XDestroyImage(ximg2);
  XFreeGC(dsx, gcbm);
  XFreeGC(dsx, gcvs);
  if (imgs) XFreeGC(dsx, gcvis);
  XFreePixmap(dsx, pxm);			     
  XFreePixmap(dsx, pxm2);			     
  
}


/* --Methode-- */
void PIGraphicX::SelForeground(PIColors col)
{
if (myLockFCol)  return;
if (col == mFCol)  return;
if ( (col < 0) || (col >= NMAXCOL))  return;
XSetForeground(mDisp, DefGC(), colpix[col]); 
mFCol = col;  
return;
}

/* --Methode-- */
void PIGraphicX::SelBackground(PIColors col)
{
if (col == mBCol)  return;
if ( (col < 0) || (col >= NMAXCOL))  return;
XSetBackground(mDisp, DefGC(), colpix[col]); 
mBCol = col;  
return;
}

/* --Methode-- */
void PIGraphicX::SelForeground(PIColorMap& cmap, int cid)
{
if (myLockFCol)  return;
SelectFCol(cmap.Color(cid));
}

/* --Methode-- */
void PIGraphicX::SelBackground(PIColorMap& cmap, int cid)
{
SelectBCol(cmap.Color(cid));
}

/* --Methode-- */
void PIGraphicX::SelGOMode(PIGOMode mod)
{
if (mod == mGOm)  return;
switch (mod)
  {
  case PI_GOCopy :
    XSetFunction(mDisp, DefGC(), GXcopy);
    mGOm = mod;
    break;
  case PI_GOXOR :
    XSetFunction(mDisp, DefGC(), GXxor);
    mGOm = mod;
    break;
  case PI_GOInvert :
    XSetFunction(mDisp, DefGC(), GXinvert);
    mGOm = mod;
    break;
  }
return;
}


/* --Methode-- */
void PIGraphicX::SelFont(PIFont & fnt)
{
if (myFont == fnt)  return;
myFont = fnt;
XSetFont(mDisp, DefGC(), myFont.GetXFontId());
}

/* --Methode-- */
void PIGraphicX::SelFont(PIFontSize sz, PIFontAtt att)
{
PIFont fnt(myFont.GetFontName());
fnt.SetFontAtt(att);
fnt.SetFontSz(sz);
SelFont(fnt);
}

/* --Methode-- */
void PIGraphicX::SelFontSzPt(int npt, PIFontAtt att)
{
PIFont fnt(npt, myFont.GetFontName(), att);
SelFont(fnt);
}



/* --Methode-- */
void PIGraphicX::SelLine(PILineAtt const& att)
{

if (att == mLAtt)  return;


unsigned int lw = att.GetLineWidth();
int lstyle=LineSolid;
int dashlen = 2;
char dash[4]= {3,3,3,3};   

switch (att.GetLineDash()) {
  case PI_LineSolid :
    lstyle = LineSolid;
     break;
  case PI_LineDashed :
    lstyle = LineOnOffDash;
    dash[0] = dash[1] = 6;     
    dashlen = 2;
    break;
  case PI_LineDotted :
    lstyle = LineOnOffDash;
    dash[0] = 2; dash[1] = 6;  
    dashlen = 2;
    break;
  case PI_LineDashDotted :
    lstyle = LineOnOffDash;
    dash[0] = 2; dash[1] = 2;  
    dash[2] = 4; dash[3] = 6;  
    dashlen = 4;
    break;
  default :
    lstyle = LineSolid;
    break;
  }
if (lstyle != LineSolid)   
  XSetDashes( mDisp, DefGC(), 0, dash, dashlen);


int ljoin = JoinMiter;
switch (att.GetLineJoin()) {
 case PI_JoinMiter :
   ljoin = JoinMiter;
   break;
 case PI_JoinRound :
   ljoin = JoinRound;
   break;
 case PI_JoinBevel :
   ljoin = JoinBevel;
   break;
 default :
   ljoin = JoinMiter;
   break;
}

int lcap = CapButt;
switch (att.GetLineCap()) {
 case PI_CapButt :
   lcap = CapButt;
   break;
 case PI_CapRound :
   lcap = CapRound;
   break;
 case PI_CapProjecting :
   lcap = CapProjecting;
   break;
 default :
   lcap = CapButt;
   break;
}

XSetLineAttributes(mDisp, DefGC(), lw, lstyle, lcap, ljoin);
mLAtt = att;
return;
}


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


/* --Methode-- */
void PIGraphicX::SetClipRectangle(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
XRectangle xr;
xr.x = x0;  xr.y = y0;
xr.width = dx;  xr.height = dy;
XSetClipRectangles(mDisp, DefGC(), 0, 0, &xr, 1, Unsorted);
XSetClipRectangles(mDisp, mMrkGC, 0, 0, &xr, 1, Unsorted);
return;
}

/* --Methode-- */
void PIGraphicX::ClearClipRectangle()
{ 
XSetClipMask(mDisp, DefGC(), None);
XSetClipMask(mDisp, mMrkGC, None);
return;
}

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

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


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

/* --Methode-- */
PIFontAtt  PIGraphicX::GetFontAtt()
{
return (mFAtt);
}

/* --Methode-- */
int        PIGraphicX::GetFontSize()
{
return (mFSize);
}

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

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

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


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

/* --Methode-- */
void PIGraphicX::RestoreGraphicAtt()
{
  if (sFCol != PI_ColorFromMap) SelForeground(sFCol);
  else SelectFCol(sFCfMap);
  if (sBCol != PI_ColorFromMap) SelBackground(sBCol);
  else SelectBCol(sBCfMap);
  SelGOMode(sGOm);
  SelFont(sFont);
  SelLine(sLAtt);
  SelMarker(sMrkSz, sMrk);
  return;
}


/* --Methode-- */
unsigned long PIGraphicX::GetPixelValueforColor(PIColors col)
{
if ( (col < 0) || (col >= NMAXCOL))  return(0);
GlInit();
return(colpix[col]); 
}


static bool fggrcx = false ;  // Flag init done


/* --Methode-- */
void PIGraphicX::GlInit()
{
if (fggrcx)  return;
fggrcx = true;

Display *mdsp;
int scr;
XColor exact,mycol;
Colormap  cmap;

mdsp = PIXDisplay();
scr = XDefaultScreen(mdsp);

/*  Les couleurs  */
cmap = XDefaultColormap (mdsp, scr);

for(int i=0; i<NMAXCOL; i++)  colpix[i] = XWhitePixel(mdsp, scr);
colpix[PI_Black] = XBlackPixel(mdsp, scr);
colpix[PI_White] = XWhitePixel(mdsp, scr);
colpix[PI_ColorAllBits0] = 0;
colpix[PI_ColorAllBits1] = ~colpix[PI_ColorAllBits0];
if ( XAllocNamedColor (mdsp, cmap, "LightGray", &mycol, &exact) )
  colpix[PI_Grey] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "red", &mycol, &exact) )
  colpix[PI_Red] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "blue", &mycol, &exact) )
  colpix[PI_Blue] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "green", &mycol, &exact) )
  colpix[PI_Green] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "yellow", &mycol, &exact) )
  colpix[PI_Yellow] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "magenta", &mycol, &exact) )
  colpix[PI_Magenta] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "cyan", &mycol, &exact) )
  colpix[PI_Cyan] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "turquoise", &mycol, &exact) )
  colpix[PI_Turquoise] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "NavyBlue", &mycol, &exact) )
  colpix[PI_NavyBlue] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "orange", &mycol, &exact) )
  colpix[PI_Orange] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "sienna", &mycol, &exact) )
  colpix[PI_SiennaRed] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "purple", &mycol, &exact) )
  colpix[PI_Purple] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "LimeGreen", &mycol, &exact) )
  colpix[PI_LimeGreen] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "gold", &mycol, &exact) )
  colpix[PI_Gold] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "violet", &mycol, &exact) )
  colpix[PI_Violet] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "VioletRed", &mycol, &exact) )
  colpix[PI_VioletRed] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "BlueViolet", &mycol, &exact) )
  colpix[PI_BlueViolet] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "DarkViolet", &mycol, &exact) )
  colpix[PI_DarkViolet] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "SkyBlue", &mycol, &exact) )
  colpix[PI_SkyBlue] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "RoyalBlue", &mycol, &exact) )
  colpix[PI_RoyalBlue] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "ForestGreen", &mycol, &exact) )
  colpix[PI_ForestGreen] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "OrangeRed", &mycol, &exact) )
  colpix[PI_OrangeRed] = mycol.pixel;
if ( XAllocNamedColor (mdsp, cmap, "brown", &mycol, &exact) )
  colpix[PI_Brown] = mycol.pixel;

mycol.red = 39000;
mycol.blue = 65535;
mycol.green = 49000;
if ( XAllocColor (mdsp, cmap, &mycol) )  colpix[PI_HighlightBlue] = mycol.pixel;

/*  le GC pour DrawPixmap  */
XGCValues  xgv;
xgv.function = GXcopy;
xgv.plane_mask = ~0;
/* dpxgc = XCreateGC(mdsp, DefaultRootWindow(mdsp), 
   GCFunction | GCPlaneMask, &xgv); Pas utile ?? - Reza 02/05/2002 */

/* Coordonnees pour une etoile a 5 branches */
double pio5 = M_PI/2.5;  
double pio52 = pio5/2.;
double cpi2 = M_PI/2.-pio5;  
// Pentagone inscrit dans un cercle de rayon R1 = 1
// les pointes de l'etoile seront inscrites dans un cercle 
// de rayon R2 = 2.61803 
double re = 1.;  // Rayon externe
double ri = 0.38; //  rayon interne pour rext=1.2
for(int k=0; k<5; k++) {
  starcoordx[2*k] = cos(k*pio5+cpi2)*re;
  starcoordy[2*k] = -sin(k*pio5+cpi2)*re;
  starcoordx[2*k+1] = cos(k*pio5+pio52+cpi2)*ri;
  starcoordy[2*k+1] = -sin(k*pio5+pio52+cpi2)*ri;
  }

}




