1 /* 2 * pst.cc -- ePiX's pstricks output format 3 * 4 * This file is part of ePiX, a C++ library for creating high-quality 5 * figures in LaTeX 6 * 7 * Version 1.1.20 8 * Last Change: September 19, 2007 9 */ 10 11 /* 12 * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 13 * Andrew D. Hwang <rot 13 nujnat at zngupf dot ubylpebff dot rqh> 14 * Department of Mathematics and Computer Science 15 * College of the Holy Cross 16 * Worcester, MA, 01610-2395, USA 17 */ 18 19 /* 20 * ePiX is free software; you can redistribute it and/or modify it 21 * under the terms of the GNU General Public License as published by 22 * the Free Software Foundation; either version 2 of the License, or 23 * (at your option) any later version. 24 * 25 * ePiX is distributed in the hope that it will be useful, but WITHOUT 26 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 27 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 28 * License for more details. 29 * 30 * You should have received a copy of the GNU General Public License 31 * along with ePiX; if not, write to the Free Software Foundation, Inc., 32 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 33 */ 34 #include <list> 35 36 #include <string> 37 #include <sstream> 38 39 #include <set> 40 41 #include "constants.h" 42 43 #include "functions.h" 44 45 #include "pairs.h" 46 #include "edge_data.h" 47 48 #include "Color.h" 49 50 #include "path_style.h" 51 #include "pen_data.h" 52 53 #include "format.h" 54 #include "pst.h" 55 56 namespace ePiX { 57 pst()58 pst::pst() 59 : m_fill(Neutral()), m_line(Black()), m_base(Neutral()), 60 m_lwidth(PLAIN_WIDTH), m_bwidth("0pt") { } 61 clone() const62 pst* pst::clone() const 63 { 64 return new pst(*this); 65 } 66 print_fill(const std::list<edge2d> & edges,const pair & offset,const Color & fc,const pen_data & line,const std::string & len) const67 std::string pst::print_fill(const std::list<edge2d>& edges, 68 const pair& offset, 69 const Color& fc, 70 const pen_data& line, 71 const std::string& len) const 72 { 73 std::stringstream obuf; 74 75 // compute attribute string 76 std::string attribs("[fillstyle="); 77 78 if (fc.is_unset()) 79 attribs += "none"; 80 else 81 attribs += "solid"; 82 83 attribs += "]"; 84 85 obuf << set_fill_state(fc) << set_pen_state(line); // side effects 86 obuf << print_paths(edges, offset, attribs, len); 87 88 return obuf.str(); 89 } 90 91 print_line(const std::list<edge2d> & edges,const pair & offset,const pen_data & line,const pen_data & base,const path_state & style,const std::string & len) const92 std::string pst::print_line(const std::list<edge2d>& edges, 93 const pair& offset, 94 const pen_data& line, 95 const pen_data& base, 96 const path_state& style, 97 const std::string& len) const 98 { 99 std::stringstream value, obuf; 100 101 obuf << set_pen_state(line); 102 103 // update base 104 m_base = base.color(); 105 m_bwidth = base.width(); 106 107 std::string attribs; 108 109 // Generate string to pass as third argument to print_paths if need border 110 if (m_lwidth < m_bwidth && !m_base.is_unset()) 111 { 112 length tmp_b(m_bwidth), tmp_l(m_lwidth); 113 tmp_b += (tmp_l *= -1); 114 tmp_b *= 0.5; 115 116 std::stringstream bordbuf; 117 bordbuf << "[border=" << print(tmp_b) 118 << ",bordercolor=" << m_base.name() << "]"; 119 120 attribs = bordbuf.str(); 121 } 122 123 if (style.is_solid()) 124 obuf << print_paths(edges, offset, attribs, len); 125 126 else // not solid 127 { 128 // Use base to draw solid underlayer, line to draw top layer. 129 // Attempt to adjust PST pen alignment; m_bwidth too large. 130 if (m_lwidth < m_bwidth && !base.color().is_unset()) 131 obuf << set_pen_state(pen_data(base.color(), 132 0.5*(m_bwidth + m_lwidth))) 133 << print_paths(edges, offset, attribs, len); 134 135 obuf << format::print_line(edges, offset, line, style, "", len); 136 } 137 138 return obuf.str(); 139 } 140 141 print_color(const std::string & model,const std::string & name,double d1,double d2,double d3) const142 std::string pst::print_color(const std::string& model, 143 const std::string& name, 144 double d1, double d2, 145 double d3) const 146 { 147 // PSTricks declaration 148 std::stringstream obuf; 149 obuf << "\\new" << model; 150 if (model == "cmy") 151 obuf << "k"; 152 153 obuf << "color{" << name << "}"; 154 155 if (model == "cmy") 156 { 157 double bk(min(min(d1,d2),d3)); 158 159 obuf << "{" 160 << d1-bk << " " << d2-bk << " " << d3-bk << " " << bk 161 << "}%" << std::endl; 162 } 163 164 else 165 obuf << "{" 166 << d1 << " " << d2 << " " << d3 167 << "}%" << std::endl; 168 169 return obuf.str(); 170 } 171 print_color(const std::string & model,const std::string & name,double d1,double d2,double d3,double d4) const172 std::string pst::print_color(const std::string& model, 173 const std::string& name, 174 double d1, double d2, 175 double d3, double d4) const 176 { 177 // model presumably "cmyk" 178 std::stringstream obuf; 179 obuf << "\\newcmykcolor{" << name << "}{" 180 << d1 << " " << d2 << " " << d3 << " " << d4 << "}%" 181 << std::endl; 182 183 return obuf.str(); 184 } 185 186 print_comment(const std::string & msg) const187 std::string pst::print_comment(const std::string& msg) const 188 { 189 std::stringstream obuf; 190 obuf << "%% " << msg << std::endl; 191 192 return obuf.str(); 193 } 194 195 // verbatim text, %-protected newline print_verbatim(const std::string & msg) const196 std::string pst::print_verbatim(const std::string& msg) const 197 { 198 std::stringstream obuf; 199 obuf << msg << "%" << std::endl; 200 201 return obuf.str(); 202 } 203 reset_state() const204 void pst::reset_state() const 205 { 206 m_fill = Neutral(); 207 m_line = Neutral(); 208 m_base = Neutral(); 209 210 m_lwidth = length(0); 211 m_bwidth = length(0); 212 } 213 214 215 //// private member functions //// start_picture(const pair & sz,const pair & offset) const216 std::string pst::start_picture(const pair& sz, const pair& offset) const 217 { 218 std::stringstream obuf; 219 obuf << "\\begin{pspicture}" 220 << format::print(sz) << format::print(-offset) << "%" << std::endl; 221 222 return obuf.str(); 223 } 224 end_picture() const225 std::string pst::end_picture() const 226 { 227 std::stringstream obuf; 228 obuf << "\\end{pspicture}%" << std::endl; 229 return obuf.str(); 230 } 231 set_unitlength(const std::string & len) const232 std::string pst::set_unitlength(const std::string& len) const 233 { 234 std::stringstream obuf; 235 236 obuf << "\\psset{unit=1" << len 237 << ",linewidth=" << print(length(PLAIN_WIDTH)) << "}%" 238 << std::endl; 239 240 return obuf.str(); 241 } 242 243 usepackages() const244 std::string pst::usepackages() const 245 { 246 return "usepackages pstricks"; 247 } 248 start_open_path(const std::string & attribs) const249 std::string pst::start_open_path(const std::string& attribs) const 250 { 251 return "\\psline" + attribs; 252 } 253 end_open_path(const std::string & attribs) const254 std::string pst::end_open_path(const std::string& attribs) const 255 { 256 std::stringstream obuf; 257 obuf << std::endl; 258 return obuf.str(); 259 } 260 start_closed_path(const std::string & attribs) const261 std::string pst::start_closed_path(const std::string& attribs) const 262 { 263 return "\\pspolygon" + attribs; 264 } 265 end_closed_path(const std::string & attribs) const266 std::string pst::end_closed_path(const std::string& attribs) const 267 { 268 std::stringstream obuf; 269 obuf << std::endl; 270 return obuf.str(); 271 } 272 set_fill_state(const Color & col) const273 std::string pst::set_fill_state(const Color& col) const 274 { 275 if (m_fill == col) 276 return ""; 277 278 // else 279 m_fill = col; 280 281 std::stringstream obuf; 282 obuf << "\\psset{"; 283 284 // filled paths set fillstyle 285 if (m_fill.is_unset()) 286 obuf << "fillstyle=none"; 287 288 else 289 obuf << "fillcolor=" << m_fill.name(); 290 291 obuf << "}%" << std::endl; 292 293 return obuf.str(); 294 } 295 set_pen_state(const pen_data & pen) const296 std::string pst::set_pen_state(const pen_data& pen) const 297 { 298 std::stringstream obuf; 299 300 if (pen.color().is_unset()) 301 { 302 m_lwidth=length(0); 303 return "\\psset{linewidth=0pt}"; 304 } 305 306 // else 307 bool change_width(m_lwidth != pen.width()); 308 bool change_color(m_line != pen.color()); 309 310 if (change_width || change_color) 311 { 312 obuf << "\\psset{"; 313 314 if (change_width) 315 { 316 m_lwidth = pen.width(); 317 obuf << "linewidth=" << m_lwidth.name(); 318 319 if (change_color) // both true, need separator 320 obuf << ","; 321 } 322 323 if (change_color) 324 { 325 m_line = pen.color(); 326 obuf << "linecolor=" << m_line.name(); 327 } 328 329 obuf << "}%" << std::endl; 330 } 331 332 return obuf.str(); 333 } 334 335 // place a LaTeX box of width zero (containing string) at location (pair) put_box(const pair & loc,const std::string & msg) const336 std::string pst::put_box(const pair& loc, const std::string& msg) const 337 { 338 std::stringstream obuf; 339 obuf << "\\rput" << print(loc) << "{" << msg << "}" << std::endl; 340 341 return obuf.str(); 342 } 343 print_circle_marker(const pair & here,double diam,bool fill,const Color & color,const std::string & len) const344 std::string pst::print_circle_marker(const pair& here, double diam, 345 bool fill, const Color& color, 346 const std::string& len) const 347 { 348 std::stringstream obuf; 349 obuf << "\\pscircle"; 350 351 if (fill) 352 obuf << "*"; 353 354 obuf << "[linecolor=" << print(color) << "]" << print(here) 355 << "{" << 0.5*diam << "}%" << std::endl; 356 357 return obuf.str(); 358 } 359 } // end of namespace 360