00001
00025 #include "magic/mgdev-eps.h"
00026
00027 BEGIN_NAMESPACE (MagiC);
00028
00029
00031
00032
00033
00034
00035
00036
00037
00039
00040 EPSDevice::EPSDevice (const Coord2D& dimensions) {
00041 make ();
00042 mDimensions = dimensions;
00043 mBoundingBox.set (0,0, dimensions.x, dimensions.y);
00044 }
00045
00046 void EPSDevice::make () {
00047 mDimensions.moveTo (0,0);
00048 mBoundingBox.moveTo (Coord2D(0,0));
00049 mStr="";
00050 mScaling.moveTo (1,1);
00051 mOffset.moveTo (0,0);
00052 mArrowLines = false;
00053 mArrowHeadSize = 10.0;
00054 }
00055
00056 void EPSDevice::printFooter () {
00057 printHeader ();
00058 }
00059
00060 void EPSDevice::printHeader () {
00061 String header = "%!PS-Adobe-2.0 EPSF\n";
00062 header += format ("%%%%BoundingBox: 0 0 %f %f\n",
00063 mBoundingBox.upperRight().x, mBoundingBox.upperRight().y);
00064 header += "%% Author info: C++ EPSDevice driver by Marko Gronroos (magi@utu.fi)\n"
00065 "%%Pages: 0\n"
00066 "%%EndComments\n\n"
00067 "% Draws a line with an arrow head\n"
00068 "/arrowline { % x0 y1 x1 y1 headsize\n"
00069 " /headscale exch def % Store variables\n"
00070 " /y1 exch def /x1 exch def\n"
00071 " /y0 exch def /x0 exch def\n"
00072 " newpath x0 y0 moveto x1 y1 lineto % Draw basic line\n"
00073 " y1 y0 sub x1 x0 sub atan % Calculate angle\n"
00074 " 165 add % Change the angle\n"
00075 " dup\n"
00076 " cos headscale mul x1 add % Calc next point\n"
00077 " exch sin headscale mul y1 add\n"
00078 " lineto % Draw to it\n"
00079 " y1 y0 sub x1 x0 sub atan % Calculate angle\n"
00080 " 165 sub % Change the angle\n"
00081 " dup\n"
00082 " cos headscale mul x1 add\n"
00083 " exch sin headscale mul y1 add\n"
00084 " lineto x1 y1 lineto fill\n"
00085 "} def\n\n"
00086 "0 setlinecap 0 setlinejoin\n"
00087 "0.500 setlinewidth\n";
00088
00089
00090 header += mStr;
00091 mStr = header;
00092 }
00093
00094 EPSDevice& EPSDevice::line (const Coord2D& start, const Coord2D& end) {
00095 checkRange (start);
00096 checkRange (end);
00097 if (mArrowLines)
00098 mStr += format ("%f %f %f %f %f arrowline\n",
00099 start.x, start.y, end.x, end.y, mArrowHeadSize);
00100 else
00101 mStr += format ("newpath %f %f moveto %f %f lineto stroke\n",
00102 start.x, start.y, end.x, end.y);
00103 return *this;
00104 }
00105
00106 EPSDevice& EPSDevice::circle (const Coord2D& center, float r, bool fill) {
00107 checkRange (center+Coord2D(r,r));
00108 mStr += format ("newpath %f %f %f 0 360 arc gsave stroke grestore\n",
00109 center.x, center.y, r );
00110 if (fill)
00111 mStr += "fill\n";
00112 return *this;
00113 }
00114
00115 EPSDevice& EPSDevice::rect (const Rect& rect) {
00116 checkRange (rect.lowerLeft());
00117 checkRange (rect.upperRight());
00118 mStr += format ("newpath %f %f moveto %f %f lineto "
00119 "%f %f lineto %f %f lineto %f %f lineto closepath stroke\n",
00120 rect.lowerLeft().x, rect.lowerLeft().y,
00121 rect.lowerLeft().x, rect.upperRight().y,
00122 rect.upperRight().x, rect.upperRight().y,
00123 rect.upperRight().x, rect.lowerLeft().y,
00124 rect.lowerLeft().x, rect.lowerLeft().y);
00125 return *this;
00126 }
00127
00128 EPSDevice& EPSDevice::setClipping (const Rect& rect) {
00129 checkRange (rect.lowerLeft());
00130 checkRange (rect.upperRight());
00131 mStr += format ("%f %f %f %f rectclip %% Clipping ON\n",
00132 rect.lowerLeft().x, rect.lowerLeft().y, rect.width(), rect.height());
00133 return *this;
00134 }
00135
00136 EPSDevice& EPSDevice::endClipping () {
00137 mStr += "eoclip% End-Of-Clipping\n";
00138 return *this;
00139 }
00140
00141 EPSDevice& EPSDevice::lineStyle (const String& style, float scale) {
00142 if (style == "solid")
00143 mStr += "[ ] 0 setdash % solid\n";
00144 else if (style == "dashed")
00145 mStr += format ("[%f] 0 setdash %% dashed\n", 3*scale);
00146 else if (style == "dotted")
00147 mStr += format ("[%f] %f setdash %% dotted\n", 5*scale, scale);
00148 else if (style == "->")
00149 mArrowLines = true, mArrowHeadSize=scale;
00150 else if (style == "-")
00151 mArrowLines = false;
00152 else
00153 ASSERTWITH (false, format ("Unrecognized line style '%s'", (CONSTR) style));
00154 return *this;
00155 }
00156
00157 EPSDevice& EPSDevice::scaling (float x, float y) {
00158 mScaling.moveTo (x, y);
00159 mStr+=format("%f %f scale\n",x,y);
00160 return *this;
00161 }
00162
00163 EPSDevice& EPSDevice::origin (const Coord2D& pos) {
00164 mOffset.copy (pos);
00165 mStr+=format("%f %f translate\n",pos.x,pos.y);
00166 return *this;
00167 }
00168
00169 EPSDevice& EPSDevice::framedStyle (float xUserSize, float yUserSize) {
00170 flipCoordinates ();
00171 rect (Rect (-1,-1, mDimensions.x, mDimensions.y));
00172 setClipping (Rect (0,0, mDimensions.x-1, mDimensions.y-1));
00173 origin (Coord2D(1,1));
00174 scaling (mDimensions.x/xUserSize, mDimensions.y/yUserSize);
00175 return *this;
00176 }
00177
00178 EPSDevice& EPSDevice::flipCoordinates () {
00179 origin (Coord2D(0,mDimensions.y));
00180 scaling (1, -1);
00181 return *this;
00182 }
00183
00184 void EPSDevice::checkRange (const Coord2D& pos) {
00185 if (pos.x>mBoundingBox.upperRight().x) mBoundingBox.upperRight().x=pos.x;
00186 if (pos.y>mBoundingBox.upperRight().y) mBoundingBox.upperRight().y=pos.y;
00187 mStr.ensure_spontane (mStr.length()+200);
00188 }
00189
00190 EPSDevice& EPSDevice::directPrint (CONSTR str) {
00191 mStr += str;
00192 return *this;
00193 }
00194
00195 END_NAMESPACE;
00196