Main Page   Class Hierarchy   Compound List   File List   Compound Members  

mgdev-eps.cc

00001 /***************************************************************************
00002  *   This file is part of the MagiC++ library.                             *
00003  *                                                                         *
00004  *   Copyright (C) 1998-2001 Marko Grönroos <magi@iki.fi>                  *
00005  *                                                                         *
00006  ***************************************************************************
00007  *                                                                         *
00008  *  This library is free software; you can redistribute it and/or          *
00009  *  modify it under the terms of the GNU Library General Public            *
00010  *  License as published by the Free Software Foundation; either           *
00011  *  version 2 of the License, or (at your option) any later version.       *
00012  *                                                                         *
00013  *  This library is distributed in the hope that it will be useful,        *
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU      *
00016  *  Library General Public License for more details.                       *
00017  *                                                                         *
00018  *  You should have received a copy of the GNU Library General Public      *
00019  *  License along with this library; see the file COPYING.LIB.  If         *
00020  *  not, write to the Free Software Foundation, Inc., 59 Temple Place      *
00021  *  - Suite 330, Boston, MA 02111-1307, USA.                               *
00022  *                                                                         *
00023  ***************************************************************************/
00024 
00025 #include "magic/mgdev-eps.h"
00026 
00027 
00028 
00030 //                                                                           //
00031 //             ----- ----   ---- ___               o                         //
00032 //             |     |   ) (     |  \   ___           ___   ___              //
00033 //             |---  |---   ---  |   | /   ) |   | | |   \ /   )             //
00034 //             |     |         ) |   | |---   \ /  | |     |---              //
00035 //             |____ |     ___/  |__/   \__    V   |  \__/  \__              //
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     // Put the header into the drawing string
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));          // Picture border
00171     setClipping (Rect (0,0, mDimensions.x-1, mDimensions.y-1)); // Clipping inside the bordera
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));      // Move origin to previous upper-left corner
00179     scaling (1, -1);                        // Flip coordinates
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 }

Generated at Tue Dec 4 19:53:25 2001 for MagiC++ by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001