#include <stdio.h>

#include "sopnamsp.h"
#include "pigraphmac.h"
#include "UDrawingState.h"



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

/* --Methode-- */
PIGraphicMac::PIGraphicMac(PIWdg* wdg)
: PIGraphicGen(wdg)
{
  mPane = wdg->mPane;
}

/* --Methode-- */
PIGraphicMac::~PIGraphicMac()
{
}

/* --Methode-- */
void PIGraphicMac::Erase(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
  if (mPane->FocusDraw()) {
    Rect theRect = {(int)y0, (int)x0, (int)y0+(int)dy, (int)x0+(int)dx};
    ::EraseRect(&theRect);
  }
}

/* --Methode-- */
void PIGraphicMac::DrawString(PIGrCoord x, PIGrCoord y, char const* s, int /*pos*/)
{
  if (!mPane->FocusDraw()) {
    ::MoveTo(x, y);
    LStr255 ps = s;
    StTextState saver;
    myFont.Apply();
    ::DrawString(ps);
  }
}

/* --Methode-- */
void PIGraphicMac::DrawOpaqueString(PIGrCoord x, PIGrCoord y, char const* s, int /*pos*/)
{
  if (mPane->FocusDraw()) {
    ::MoveTo(x, y);
    LStr255 ps = s;
    StTextState saver;
    myFont.Apply();
	Rect box;
	box.left = x;
	box.bottom = y;
	int iWidth = TextWidth(s,0,strlen(s));
	box.right = box.left + iWidth;
	int z;
	box.top = box.bottom + myFont.GetFontHeight(z,z);
    ::TETextBox(s,strlen(s),&box,teForceLeft);
  }
}

 
/* --Methode-- */
void PIGraphicMac::DrawLine(PIGrCoord x1, PIGrCoord y1, PIGrCoord x2, PIGrCoord y2)
{
  if (mPane->FocusDraw()) {
    ::MoveTo(x1,y1);
    ::LineTo(x2,y2);
  }
}


/* --Methode-- */
void PIGraphicMac::DrawBox(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
  if (mPane->FocusDraw()) {
    Rect r = {y0, x0, (int)y0+(int)dy, (int)x0+(int)dx};
    if (r.top  > r.bottom) swap(r.top,  r.bottom);
    if (r.left > r.right)  swap(r.left, r.right);
    r.right++; r.bottom++;
    ::FrameRect(&r);
  }
}

/* --Methode-- */
void PIGraphicMac::DrawFBox(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
  if (mPane->FocusDraw()) {
    Rect r = {y0, x0, (int)y0+(int)dy, (int)x0+(int)dx};
    if (r.top  > r.bottom) swap(r.top,  r.bottom);
    if (r.left > r.right)  swap(r.left, r.right);
    r.right++; r.bottom++;
    ::PaintRect(&r);
  }
}

/* --Methode-- */
void PIGraphicMac::DrawCircle(PIGrCoord x0, PIGrCoord y0, PIGrCoord r)
{
  if (mPane->FocusDraw()) {
    Rect rr = {(int)y0-(int)r, (int)x0-(int)r, (int)y0+(int)r, (int)x0+(int)r};
    if (rr.top  > rr.bottom) swap(rr.top,  rr.bottom);
    if (rr.left > rr.right)  swap(rr.left, rr.right);
    ::FrameOval(&rr);
  }
}

/* --Methode-- */
void PIGraphicMac::DrawFCircle(PIGrCoord x0, PIGrCoord y0, PIGrCoord r)
{
  if (mPane->FocusDraw()) {
    Rect rr = {(int)y0-(int)r, (int)x0-(int)r, (int)y0+(int)r, (int)x0+(int)r};
    if (rr.top  > rr.bottom) swap(rr.top,  rr.bottom);
    if (rr.left > rr.right)  swap(rr.left, rr.right);
    ::PaintOval(&rr);
  }
}

/* --Methode-- */
void PIGraphicMac::DrawOval(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
  if (mPane->FocusDraw()) {
    Rect rr = {(int)y0-(int)dy, (int)x0-(int)dx, (int)y0+(int)dy, (int)x0+(int)dx};
    if (rr.top  > rr.bottom) swap(rr.top,  rr.bottom);
    if (rr.left > rr.right)  swap(rr.left, rr.right);
    ::FrameOval(&rr);
  }
}

/* --Methode-- */
void PIGraphicMac::DrawFOval(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
  if (mPane->FocusDraw()) {
    Rect rr = {(int)y0-(int)dy, (int)x0-(int)dx, (int)y0+(int)dy, (int)x0+(int)dx};
    if (rr.top  > rr.bottom) swap(rr.top,  rr.bottom);
    if (rr.left > rr.right)  swap(rr.left, rr.right);
    ::PaintOval(&rr);
  }
}


/* --Methode-- */
void PIGraphicMac::DrawPolygon(PIGrCoord *x, PIGrCoord *y, int n, bool cinc)
{
  PolyHandle h = MakePoly(x,y,n);
  if (h) {
    ::FramePoly(h);
    ::KillPoly(h);
  }
  
}

/* --Methode-- */
void PIGraphicMac::DrawFPolygon(PIGrCoord *x, PIGrCoord *y, int n, bool cinc)
{
  PolyHandle h = MakePoly(x,y,n);
  if (h) {
    ::PaintPoly(h);
    ::KillPoly(h);
  }
}


/* --Methode-- */
void PIGraphicMac::DrawArc(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy, 
                         double degdeb, double deltadeg)
{
  if (mPane->FocusDraw()) {
    Rect rr = {(int)y0-(int)dy, (int)x0-(int)dx, (int)y0+(int)dy, (int)x0+(int)dx};
    if (rr.top  > rr.bottom) swap(rr.top,  rr.bottom);
    if (rr.left > rr.right)  swap(rr.left, rr.right);
    ::FrameArc(&rr, degdeb, deltadeg);
  }
}

/* --Methode-- */
void PIGraphicMac::DrawFArc(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy, 
                         double degdeb, double deltadeg)
{
  if (mPane->FocusDraw()) {
    Rect rr = {(int)y0-(int)dy, (int)x0-(int)dx, (int)y0+(int)dy, (int)x0+(int)dx};
    if (rr.top  > rr.bottom) swap(rr.top,  rr.bottom);
    if (rr.left > rr.right)  swap(rr.left, rr.right);
    ::PaintArc(&rr, degdeb, deltadeg);
  }
}


/* --Methode-- */
PolyHandle PIGraphicMac::MakePoly(PIGrCoord *x, PIGrCoord *y, int n)
{
  if (mPane->FocusDraw()) {
    PolyHandle h = ::OpenPoly();
    ::MoveTo(x[0], y[0]);
    for (int i=1; i<n; i++) {
      ::LineTo(x[i], y[i]);
    }
    ::MoveTo(x[0], y[0]);
    ClosePoly();
    return h;
  }
  return NULL;
}


/* --Methode-- */
void PIGraphicMac::DrawMarker(PIGrCoord x0, PIGrCoord y0)
{
int hmsz = mMrkSz/2;
int dmsz = mMrkSz-hmsz;
PIGrCoord x[4],y[4];
PILineAtt clatt;

if (mMrk == PI_DotMarker) {
  ::MoveTo( x0, y0);
  ::Line(0,0);
}

else
  {
  clatt = mLAtt;
  SelLine(PI_ThinLine);
  switch (mMrk)
    {
    case  PI_PlusMarker :
      DrawLine((int)x0-hmsz, y0, (int)x0+dmsz, y0);
      DrawLine(x0, (int)y0-hmsz, x0, (int)y0+dmsz);
      break;
    case  PI_CrossMarker :
      DrawLine((int)x0-hmsz, (int)y0-hmsz, (int)x0+dmsz, (int)y0+dmsz);
      DrawLine((int)x0-hmsz, (int)y0+dmsz, (int)x0+dmsz, (int)y0-hmsz);
      break;  
    case PI_CircleMarker :
      DrawCircle(x0, y0, hmsz);
      break;
    case PI_FCircleMarker :
      DrawFCircle(x0, y0, hmsz);
      break;
    case PI_BoxMarker :
      DrawBox((int)x0-hmsz, (int)y0-hmsz, mMrkSz, mMrkSz);
      break;
    case PI_FBoxMarker :
      DrawFBox((int)x0-hmsz, (int)y0-hmsz, mMrkSz, mMrkSz);
      break;
    case  PI_TriangleMarker :
      x[1] = mMrkSz; y[1] = 0; x[2] = -hmsz; y[2] = -mMrkSz; 
      x[3] = -dmsz; y[3] = +mMrkSz; x[0] = (int)x0-hmsz; y[0] = (int)y0+hmsz;  
      DrawPolygon(x, y, 4);
      break;
    case  PI_FTriangleMarker :
      x[1] = mMrkSz; y[1] = 0; x[2] = -hmsz; y[2] = -mMrkSz; 
      x[3] = -dmsz; y[3] = +mMrkSz; x[0] = (int)x0-hmsz; y[0] = (int)y0+hmsz;  
      DrawFPolygon(x, y, 4);
      break;
    default :
      ::MoveTo( x0, y0);
      ::Line(0,0);
      break;
    }
  SelLine(clatt);
  }
return;
}

/* --Methode-- */
void PIGraphicMac::DrawMarkers(PIGrCoord *x, PIGrCoord *y, int n)
{
int i;

if (n <= 0)  return;
for(i=0; i<n; i++) DrawMarker(x[i], y[i]);
}


/* --Methode-- */
void PIGraphicMac::DrawPixmap(PIGrCoord x, PIGrCoord y, unsigned char *pix, 
                            int sx, int sy, PIColorMap* cmap)
{
  Rect	frame;
  SetRect(&frame, 0, 0, sx, sy);
  Rect dstFrame;
  SetRect(&dstFrame, x, y, sx, sy);
  GWorldPtr gWorld;
  ThrowIfOSErr_(NewGWorld(&gWorld, 8, &frame, cmap->GetCTab(), nil, 0));
  PixMapHandle pmh = GetGWorldPixMap(gWorld);
  ::LockPixels (pmh);
  Ptr pmap = GetPixBaseAddr(pmh);
  memcpy(pmap, pix, sx*sy);
  ::ForeColor (blackColor);
  ::BackColor (whiteColor);
  ::CopyBits((BitMap *) (*pmh),
				&mPane->GetMacPort()->portBits,
				&frame, &dstFrame, srcCopy, nil);
  ::UnlockPixels (pmh);
  DisposeGWorld(gWorld);
}



/* --Methode-- */
void PIGraphicMac::SelForeground(PIColors col)
{
  if (mPane->FocusDraw()) {
    long color;
    switch (col) {
      case PI_Black:
        color = blackColor;
        break;
      case PI_White:
        color = whiteColor;
        break;
      case PI_Red:
        color = redColor;
        break;
      case PI_Blue:
        color = blueColor;
        break;
      case PI_Green:
        color = greenColor;
        break;
      case PI_Yellow:
        color = yellowColor;
        break;
      default:
        color = blackColor;
    }
    ::ForeColor(color);
    mFCol = col;
  }
}

/* --Methode-- */
void PIGraphicMac::SelBackground(PIColors col)
{
  if (mPane->FocusDraw()) {
    long color;
    switch (col) {
      case PI_Black:
        color = blackColor;
        break;
      case PI_White:
        color = whiteColor;
        break;
      case PI_Red:
        color = redColor;
        break;
      case PI_Blue:
        color = blueColor;
        break;
      case PI_Green:
        color = greenColor;
        break;
      case PI_Yellow:
        color = yellowColor;
        break;
      default:
        color = blackColor;
    }
    mBCol = col;
    ::BackColor(color);
  }
}

/* --Methode-- */
void PIGraphicMac::SelForeground(PIColorMap& cmap, int cid)
{
  if (mPane->FocusDraw()) {
    PIColor picol = cmap.GetColor(cid);
    RGBColor qdCol;
 
    qdCol.red   = picol.red;
    qdCol.green = picol.green;
    qdCol.blue  = picol.blue;

    ::RGBForeColor(&qdCol);
  }
}

/* --Methode-- */
void PIGraphicMac::SelBackground(PIColorMap& cmap, int cid)
{
  if (mPane->FocusDraw()) {
    PIColor picol = cmap.GetColor(cid);
    RGBColor qdCol;
 
    qdCol.red   = picol.red;
    qdCol.green = picol.green;
    qdCol.blue  = picol.blue;

    ::RGBBackColor(&qdCol);
  }
}

/* --Methode-- */
void PIGraphicMac::SelGOMode(PIGOMode mod)
{
if (mod == mGOm)  return;
  if (mPane->FocusDraw())
    switch (mod)
    {
      case PI_GOCopy :
        ::PenMode(patCopy);
        mGOm = mod;
        break;
      case PI_GOXOR :
        ::PenMode(patXor);
        mGOm = mod;
        break;
    }
return;
}


/* --Methode-- */
void PIGraphicMac::SelFontSzPt(int npt, PIFontAtt att)
{
  myFont.SetFontSzPt(npt);
  myFont.SetFontAtt(att);
}

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

/* --Methode-- */
void PIGraphicMac::SelFont(PIFont & fnt)
{
  myFont = fnt;
}


/* --Methode-- */
void PIGraphicMac::SelLine(PILineAtt const & att)
{
  if (mPane->FocusDraw()) {
    switch(att) {
      case PI_NormalLine:
        ::PenSize(1,1);
        break;
      case PI_ThinLine:
        ::PenSize(1,1);  // Mettre en pointille, ou bien commentaire pour Laser ?
        break;
      case PI_ThickLine:
        ::PenSize(2,2);
        break;
    }
  }
  mLAtt = att;
}


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


/* --Methode-- */
void PIGraphicMac::SetClipRectangle(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
//$CHECK
}

/* --Methode-- */
void PIGraphicMac::ClearClipRectangle()
{ 
//$CHECK
}

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

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


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

/* --Methode-- */
PIFontAtt  PIGraphicMac::GetFontAtt()
{
return (myFont.GetFontAtt());
}

/* --Methode-- */
int        PIGraphicMac::GetFontSize()
{
return (myFont.GetFontSize());
}

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

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

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


