#include "stdafx.h"
#include "EPSInterface.h"
namespace gfxinterface
{
CEPSInterface::CEPSInterface(const char* sFileName)
: CFileGfxInterface(sFileName)
{
InitState();
}
CEPSInterface::~CEPSInterface()
{
if (m_file.is_open())
Close();
}
void CEPSInterface::InitState()
{
memset(&m_state.curcol,0,sizeof(SRGBA));
memset(&m_state.strokecol,0,sizeof(SRGBA));
memset(&m_state.fillcol,1,sizeof(SRGBA));
m_state.curcol.a=1;
m_state.strokecol.a=1;
m_state.dash="";
m_state.linewidth=0;
m_lStates.clear();
}
void CEPSInterface::WriteHeader()
{
double sqrt3=sqrt(3.0);
_ASSERT(m_file.is_open());
m_file<<"%!PS_Adobe-3.0 EPSF-3.0\n";
m_file<<"%%Creator:"<<m_sCreator<<std::endl;
m_file<<"%%Title:"<<m_sTitle<<std::endl;
m_file<<"%%CreationDate:"<<m_sCreationDate<<std::endl;
m_file<<"%%BoundingBox:"<<GetWorldLeft()<<" "<<GetWorldBottom()<<" "
<<GetWorldRight()<<" "
<<GetWorldTop()<<std::endl;
m_file<<"%%LanguageLevel: 2\n";
m_file<<"% World Bounding Box : "<<GetWorldLeft()<<" "<<GetWorldBottom()<<" "
<<GetWorldRight()<<" "
<<GetWorldHeight()<<std::endl;
AddComment("Begin Operators Definitions:");
AddComment("Name, description, stack state");
AddComment("EWRightShow, right aligned text, text");
m_file<<"/EWRightShow { dup stringwidth pop -1 mul 0 rmoveto show } def\n";
AddComment("EWCenterShow, centered text, text");
m_file<<"/EWCenterShow { dup stringwidth pop -0.5 mul 0 rmoveto show } def\n";
AddComment("EWDownCenterShow, centered text down of cursor, text");
m_file<<"/EWDownCenterShow { dup stringwidth pop -0.5 mul exch neg rmoveto show } def\n";
AddComment("EWBox, startx starty dx dy");
m_file<<"/EWBox {/dy exch def /dx exch def newpath moveto 0 dy rlineto dx 0 rlineto 0 dy -1 mul rlineto closepath} def\n";
AddComment("EWCircle, no fill, centerx centery radius");
m_file<<"/EWCircle { 0 360 arc} def\n";
AddComment("EWTriangle, a triangle inside a circle, centerx centery radius");
m_file<<"/EWTriangle {dup "<<sqrt3<<" mul /c 2 1 roll def newpath add moveto\n c 2 div c -1 mul rlineto c -1 mul 0 rlineto closepath} def\n";
AddComment("EWSquare, square inside center, centerx centery radius");
m_file<<"/EWSquare {/r 2 1 roll def newpath moveto r 2 div r 2 div rmoveto\n 0 r -1 mul rlineto r -1 mul 0 rlineto 0 r rlineto closepath} def\n";
AddComment("EWArrow, an arrow, tailx taily tipx tipy tailthickness headthickness headlength");
AddComment("See Postscript language Cookbook, Program 4");
AddComment("Setting arrow dictionnary");
m_file<<"/EWArrowDict 14 dict def EWArrowDict begin /mtrx matrix def end\n";
AddComment("Defining arrow procedure");
m_file<<"/EWArrow { EWArrowDict begin "
<<"/headlength exch def /halfheadthickness exch 2 div def /halfthickness exch 2 div def "
<<"/tipy exch def /tipx exch def /taily exch def /tailx exch def "
<<"/dx tipx tailx sub def /dy tipy taily sub def "
<<"/arrowlength dx dx mul dy dy mul add sqrt def "
<<"/angle dy dx atan def /base arrowlength headlength sub def "
<<"/savematrix mtrx currentmatrix def "
<<"tailx taily translate angle rotate "
<<"0 halfthickness neg moveto base halfthickness neg lineto "
<<"base halfheadthickness neg lineto arrowlength 0 lineto "
<<"base halfheadthickness lineto base halfthickness lineto "
<<"0 halfthickness lineto closepath "
<<"savematrix setmatrix end }def ";
AddComment("End Preliminary Definitions");
m_file<<"gsave\n";
}
bool CEPSInterface::Open(const char* filename)
{
if (filename)
{
m_sFileName=filename;
if (m_sFileName.rfind(".eps") != m_sFileName.size() - 4)
{
m_sFileName+=".eps";
}
}
if (!CFileGfxInterface::Open())
return false;
InitState();
WriteHeader();
return true;
}
void CEPSInterface::Close()
{
_ASSERT(m_file.is_open());
m_file<<"grestore\n";
CFileGfxInterface::Close();
}
void CEPSInterface::DrawLineStrip(int n, double *pX, double *pY, bool open, bool filled)
{
int count=0;
m_file<<"newpath\n";
if (filled)
{
m_file<<WorldToBBx(pX[0])<<" "<<GetWorldBottom()<<std::endl;
count++;
}
for (int i=0;i<n;i++)
{
m_file<<WorldToBBx(pX[i])<<" "<<WorldToBBy(pY[i])<<std::endl;
count++;
}
if (filled)
{
m_file<<WorldToBBx(pX[n-1])<<" "<<GetWorldBottom()<<std::endl;
count++;
}
m_file<<"moveto "<<count-1<<" {lineto} repeat ";
if (open)
{
PutStrokeColorString();
m_file<<"stroke\n";
}
else if (filled)
{
m_file<<"closepath ";
PushState();
PutFillColorString();
m_file<<"fill ";
PopState();
PutStrokeColorString();
m_file<<" stroke\n";
}
else
{
PutStrokeColorString();
m_file<<"closepath stroke\n";
}
}
void CEPSInterface::DrawStepStrip(int n, double *pX, double *pY, bool open, bool filled)
{
int count=0;
m_file<<"newpath\n";
if (filled)
{
m_file<<WorldToBBx(pX[0])<<" "<<GetWorldBottom()<<std::endl;
count++;
}
for (int i=0;i<n-1;i++)
{
m_file<<WorldToBBx(pX[i])<<" "<<WorldToBBy(pY[i])<<" ";
m_file<<WorldToBBx(pX[i+1])<<" "<<WorldToBBy(pY[i])<<std::endl;
count+=2;
}
if (filled)
{
m_file<<WorldToBBx(pX[n-1])<<" "<<GetWorldBottom()<<std::endl;
count++;
}
m_file<<"moveto "<<count-1<<" {lineto} repeat ";
if (open)
{
PutStrokeColorString();
m_file<<"stroke\n";
}
else if (filled)
{
m_file<<"closepath ";
PushState();
PutFillColorString();
m_file<<"fill ";
PopState();
PutStrokeColorString();
m_file<<" stroke\n";
}
else
{
PutStrokeColorString();
m_file<<"closepath stroke\n";
}
}
void CEPSInterface::AddComment(const char *str)
{
#ifdef _DEBUG
m_file<<"%"<<str<<std::endl;
#endif
}
void CEPSInterface::SetColor(double r, double g, double b, double a)
{
m_state.strokecol.r = __max(0, __min( 1, r));
m_state.strokecol.g = __max(0, __min( 1, g));
m_state.strokecol.b = __max(0, __min( 1, b));
m_state.strokecol.a = __max(0, __min( 1, a));
}
void CEPSInterface::SetFillColor(double r, double g, double b, double a)
{
m_state.fillcol.r = __max(0, __min( 1, r));
m_state.fillcol.g = __max(0, __min( 1, g));
m_state.fillcol.b = __max(0, __min( 1, b));
m_state.fillcol.a = __max(0, __min( 1, a));
}
void CEPSInterface::SetDash(const char* dash)
{
if (dash!= m_state.dash)
{
m_state.dash=dash;
m_file<<"["<<dash<<"] 0 setdash\n";
}
}
void CEPSInterface::DrawLine(double x1, double y1, double x2, double y2)
{
PutStrokeColorString();
m_file<<"newpath "<<WorldToBBx(x1)<<" "<<WorldToBBy(y1)<<" moveto "
<<WorldToBBx(x2)<<" "<<WorldToBBy(y2)<<" lineto stroke\n";
}
void CEPSInterface::DrawTextLeft(double x, double y, const char* str, double angle)
{
PutStrokeColorString();
m_file<<WorldToBBx(x)<<" "<<WorldToBBy(y)<<" moveto ";
if (angle)
m_file<<angle<<" rotate ";
m_file<<"("<<str<<") show ";
if (angle)
m_file<<-angle<<" rotate ";
m_file<<std::endl;
}
void CEPSInterface::DrawTextRight(double x, double y, const char* str, double angle)
{
PutStrokeColorString();
m_file<<WorldToBBx(x)<<" "<<WorldToBBy(y)<<" moveto ";
if (angle)
m_file<<angle<<" rotate ";
m_file<<"("<<str<<") EWRightShow ";
if (angle)
m_file<<-angle<<" rotate ";
m_file<<std::endl;
}
void CEPSInterface::DrawTextCenter(double x, double y, const char* str, double angle)
{
PutStrokeColorString();
m_file<<WorldToBBx(x)<<" "<<WorldToBBy(y)<<" moveto ";
if (angle)
m_file<<angle<<" rotate ";
m_file<<"("<<str<<") EWCenterShow ";
if (angle)
m_file<<-angle<<" rotate ";
m_file<<std::endl;
}
void CEPSInterface::DrawTextStrip(const std::vector<SPointF>& vPoints, const std::vector<std::string>& vStrings, ETextAlignment ta, double angle)
{
ASSERT(vPoints.size() == vStrings.size());
PutStrokeColorString();
for (UINT i=0; i<vPoints.size();i++)
{
m_file<<WorldToBBx(vPoints[i].x)<<" "<<WorldToBBy(vPoints[i].y)<<" moveto ";
if (angle)
m_file<<angle<<" rotate ";
m_file<<"("<<vStrings[i]<<") ";
switch(ta)
{
case TextAlignmentLeft:
m_file<<"EWLeftShow ";
break;
case TextAlignmentCenter:
m_file<<"EWCenterShow ";
break;
case TextAlignmentRight:
m_file<<"EWRightShow ";
break;
}
if (angle)
m_file<<-angle<<" rotate ";
m_file<<std::endl;
}
};
void CEPSInterface::SetFont(long scale)
{
m_file<<"/Times-Roman findfont "<<abs(scale)<<" scalefont setfont\n";
}
void CEPSInterface::SetFont(const LOGFONT& logFont)
{
m_file<<"/Times-Roman findfont "<<fabs(logFont.lfHeight)<<" scalefont setfont\n";
}
void CEPSInterface::DrawBox(double llx, double lly, double dx, double dy, bool filled)
{
m_file<<WorldToBBx(llx)<<" "<<WorldToBBy(lly)<<" "<<dx<<" "<<dy<<" EWBox ";
if (filled)
{
PushState();
PutStrokeColorString();
m_file<<"fill ";
PopState();
}
PutStrokeColorString();
m_file<<"stroke ";
m_file<<std::endl;
}
void CEPSInterface::DrawCircle(double cx, double cy, double radius, bool filled)
{
m_file<<WorldToBBx(cx)<<" "<<WorldToBBy(cy)<<" "<<radius<<" EWCircle ";
if (filled)
{
PushState();
PutStrokeColorString();
m_file<<"fill ";
PopState();
}
PutStrokeColorString();
m_file<<"stroke ";
m_file<<std::endl;
}
void CEPSInterface::DrawTriangle(double cx, double cy, double radius, bool filled)
{
m_file<<WorldToBBx(cx)<<" "<<WorldToBBy(cy)<<" "<<radius<<" EWTriangle ";
if (filled)
{
PushState();
PutStrokeColorString();
m_file<<"fill ";
PopState();
}
PutStrokeColorString();
m_file<<"stroke ";
m_file<<std::endl;
}
void CEPSInterface::DrawSquare(double cx, double cy, double radius, bool filled)
{
m_file<<WorldToBBx(cx)<<" "<<WorldToBBy(cy)<<" "<<radius<<" EWSquare ";
if (filled)
{
PushState();
PutStrokeColorString();
m_file<<"fill ";
PopState();
}
PutStrokeColorString();
m_file<<"stroke ";
m_file<<std::endl;
}
void CEPSInterface::DrawBoxStrip(int n, double* pLlx, double* pLly, double dx, double dy, bool filled)
{
for (int i=0;i<n;i++)
{
m_file<<WorldToBBx(pLlx[i])<<" "<<WorldToBBy(pLly[i])<<" "<<dx<<" "<<dy<<std::endl;
}
m_file<<n<<" {EWBox ";
if (filled)
{
PushState();
PutStrokeColorString();
m_file<<"fill ";
PopState();
}
PutStrokeColorString();
m_file<<"stroke ";
m_file<<"} repeat\n";
}
void CEPSInterface::DrawCircleStrip(int n, double* pCx, double* pCy, double radius, bool filled)
{
for (int i=0;i<n;i++)
{
m_file<<WorldToBBx(pCx[i])<<" "<<WorldToBBy(pCy[i])<<" "<<radius<<std::endl;
}
m_file<<n<<" {EWCircle ";
if (filled)
{
PushState();
PutStrokeColorString();
m_file<<"fill ";
PopState();
}
PutStrokeColorString();
m_file<<"stroke ";
m_file<<"} repeat\n";
}
void CEPSInterface::DrawTriangleStrip(int n, double* pCx, double* pCy, double radius, bool filled)
{
for (int i=0;i<n;i++)
{
m_file<<WorldToBBx(pCx[i])<<" "<<WorldToBBy(pCy[i])<<" "<<radius<<std::endl;
}
m_file<<n<<" {EWTriangle ";
if (filled)
{
PushState();
PutStrokeColorString();
m_file<<"fill ";
PopState();
}
PutStrokeColorString();
m_file<<"stroke ";
m_file<<"} repeat\n";
}
void CEPSInterface::DrawSquareStrip(int n, double* pCx, double* pCy, double radius, bool filled)
{
for (int i=0;i<n;i++)
{
m_file<<WorldToBBx(pCx[i])<<" "<<WorldToBBy(pCy[i])<<" "<<radius<<std::endl;
}
m_file<<n<<" {EWSquare ";
if (filled)
{
PushState();
PutStrokeColorString();
m_file<<"fill ";
PopState();
}
PutStrokeColorString();
m_file<<"stroke ";
m_file<<"} repeat\n";
}
void CEPSInterface::SetLineWidth(double width)
{
if (width != m_state.linewidth)
{
m_state.linewidth=__max(0,width-1);
m_file<<m_state.linewidth<<" setlinewidth\n";
}
}
void CEPSInterface::DrawSurf(int nx, int ny, double llx, double lly, double dx, double dy, double* pColor)
{
double xCur,yCur;
int i,j,k;
AddComment("Drawing surface");
AddComment("Init shading dictionnary");
m_file<<"/DeviceRGB setcolorspace\n";
AddComment("Define the shading dictionary");
m_file<<"<<\n/ShadingType 5\n/ColorSpace /DeviceRGB\n"
<<"/VerticesPerRow "<<nx<<" \n/DataSource [\n";
yCur=lly+(ny-1)*dy;
k=0;
for (i=0;i<ny;i++)
{
xCur=llx;
for (j=0;j<nx;j++)
{
_ASSERT(k==i*nx+j);
m_file<<WorldToBBx(xCur)<<" "<<WorldToBBy(yCur)<<" "
<<pColor[k*3]<<" "
<<pColor[k*3+1]<<" "
<<pColor[k*3+2]<<std::endl;
xCur += dx;
k++;
}
yCur-=dy;
}
m_file<<"]\n>> shfill\n";
}
void CEPSInterface::DrawVectorField(int nx, int ny, double llx, double lly, double dx, double dy, double *pV, double lineWidth)
{
double xCur,yCur;
int i,j,k,lcount;
lineWidth = __max(1, lineWidth);
PutStrokeColorString();
AddComment("Vector field");
m_file<<"newpath\n";
yCur=lly+(ny-1)*dy;
k=0;
lcount=0;
for (i=0;i<ny;i++)
{
xCur=llx;
for (j=0;j<nx;j++)
{
_ASSERT(k==i*nx+j);
if (sqrt( pV[k*2]*pV[k*2]+pV[k*2+1]*pV[k*2+1] ) > 1e-10)
{
m_file<<WorldToBBx(xCur-pV[k*2]/2)<<" "<<WorldToBBy(yCur-pV[k*2+1]/2)<<" "
<<WorldToBBx(xCur+pV[k*2]/2)<<" "<<WorldToBBy(yCur+pV[k*2+1]/2)<<" "
<<lineWidth<<" 4.0 6.0"<<std::endl;
lcount++;
}
xCur+=dx;
k++;
}
yCur-=dy;
}
m_file<<lcount<<" {EWArrow} repeat fill"<<std::endl;
}
void CEPSInterface::PushClipWorld(double llx, double lly, double urx, double ury)
{
CFileGfxInterface::PushClipWorld(llx,lly,urx,ury);
m_file<<" gsave ";
m_file<<WorldToBBx(llx)<<" "
<<WorldToBBy(lly)<<" "
<<WorldToBBAbsx(urx-llx)<<" "
<<WorldToBBAbsy(ury-lly)<<" "
<<"rectclip\n";
}
void CEPSInterface::PopClipWorld()
{
CFileGfxInterface::PopClipWorld();
m_file<<" grestore\n";
}
void CEPSInterface::PushState()
{
m_file<<" gsave\n";
m_lStates.push_front(m_state);
}
void CEPSInterface::PopState()
{
_ASSERT(!m_lStates.empty());
m_state = m_lStates.front();
m_lStates.pop_front();
m_file<<" grestore\n";
}
void CEPSInterface::Fill()
{
m_file<<" fill\n";;
}
void CEPSInterface::DrawGridHor(double llx, double urx, double lly, double ury,double dy)
{
AddComment("Drawing horizontal grid");
double y=lly;
int count;
PutStrokeColorString();
m_file<<"newpath\n";
count=0;
y=lly;
m_file<<WorldToBBx(urx)<<" "<<WorldToBBy(y)<<" moveto"<<std::endl;
while (y<ury-dy)
{
m_file<<WorldToBBAbsx(urx-llx)<<" 0 "<<-WorldToBBAbsx(urx-llx)<<" "<<WorldToBBAbsy(dy)<<std::endl;
count++;
y+=dy;
}
m_file<<count<<" {rmoveto rlineto} repeat stroke\n";
}
void CEPSInterface::DrawGridVer(double llx, double urx, double lly, double ury,double dx)
{
AddComment("Drawing vertical grid");
double x=llx;
int count;
PutStrokeColorString();
m_file<<"newpath\n";
count=0;
x=llx;
m_file<<WorldToBBx(x)<<" "<<WorldToBBy(ury)<<" moveto"<<std::endl;
while (x<urx-dx)
{
m_file<<"0 "<<WorldToBBAbsy(ury-lly)<<" "<<WorldToBBAbsx(dx)<<" "<<-WorldToBBAbsy(ury-lly)<<std::endl;
count++;
x+=dx;
}
m_file<<count<<" {rmoveto rlineto} repeat stroke\n";
}
void CEPSInterface::DrawArrow(double tailx, double taily, double tipx, double tipy, double tailthickness, double headthickness, double headlength, bool filled)
{
m_file<<WorldToBBx(tailx)<<" "<<WorldToBBy(taily)<<" "<<WorldToBBx(tipx)<<" "<<WorldToBBy(tipy)<<" "<<tailthickness<<" "<<headthickness<<" "<<headlength<<" EWArrow ";
if (filled)
{
PushState();
PutFillColorString();
m_file<<"fill ";
PopState();
}
PutStrokeColorString();
m_file<<"stroke\n";
}
void CEPSInterface::DrawArrowAbs(double tailx, double taily, double dtipx, double dtipy, double tailthickness, double headthickness, double headlength, bool filled)
{
m_file<<WorldToBBx(tailx)<<" "<<WorldToBBy(taily)<<" "<<WorldToBBx(tailx)+dtipx<<" "<<WorldToBBy(taily)+dtipy<<" "<<tailthickness<<" "<<headthickness<<" "<<headlength<<" EWArrow ";
if (filled)
{
PushState();
PutFillColorString();
m_file<<"fill ";
PopState();
}
PutStrokeColorString();
m_file<<"stroke\n";
}
void CEPSInterface::DrawRect(double llx, double lly, double urx, double ury, bool filled)
{
m_file<<"newpath "<<WorldToBBx(llx)<<" "<<WorldToBBy(ury)<<" "
<<WorldToBBx(urx)<<" "<<WorldToBBy(ury)<<" "
<<WorldToBBx(urx)<<" "<<WorldToBBy(lly)<<" "
<<WorldToBBx(llx)<<" "<<WorldToBBy(lly)<<" moveto 3 {lineto} repeat closepath ";
if (filled)
{
PushState();
PutFillColorString();
m_file<<"fill ";
PopState();
}
PutStrokeColorString();
m_file<<"stroke\n";
}
void CEPSInterface::PutFillColorString()
{
if ( memcmp(&m_state.fillcol, &m_state.curcol , sizeof(SRGBA)))
{
m_state.curcol = m_state.fillcol;
m_file<<m_state.fillcol.r<<" "<<m_state.fillcol.g<<" "<<m_state.fillcol.b<<" setrgbcolor\n";
}
}
void CEPSInterface::PutStrokeColorString()
{
if ( memcmp(&m_state.strokecol, &m_state.curcol , sizeof(SRGBA) ))
{
m_state.curcol = m_state.strokecol;
m_file<<m_state.strokecol.r<<" "<<m_state.strokecol.g<<" "<<m_state.strokecol.b<<" setrgbcolor\n";
}
}
}