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