|
bpp-core
2.1.0
|
00001 // 00002 // File: PgfGraphicDevice.cpp 00003 // Created by: Julien Dutheil 00004 // Created on: Thu Jun 19 2008 00005 // 00006 00007 /* 00008 Copyright or © or Copr. CNRS, (November 17, 2004) 00009 00010 This software is a computer program whose purpose is to provide utilitary 00011 classes. This file belongs to the Bio++ Project. 00012 00013 This software is governed by the CeCILL license under French law and 00014 abiding by the rules of distribution of free software. You can use, 00015 modify and/ or redistribute the software under the terms of the CeCILL 00016 license as circulated by CEA, CNRS and INRIA at the following URL 00017 "http://www.cecill.info". 00018 00019 As a counterpart to the access to the source code and rights to copy, 00020 modify and redistribute granted by the license, users are provided only 00021 with a limited warranty and the software's author, the holder of the 00022 economic rights, and the successive licensors have only limited 00023 liability. 00024 00025 In this respect, the user's attention is drawn to the risks associated 00026 with loading, using, modifying and/or developing or reproducing the 00027 software by the user in light of its specific status of free software, 00028 that may mean that it is complicated to manipulate, and that also 00029 therefore means that it is reserved for developers and experienced 00030 professionals having in-depth computer knowledge. Users are therefore 00031 encouraged to load and test the software's suitability as regards their 00032 requirements in conditions enabling the security of their systems and/or 00033 data to be ensured and, more generally, to use and operate it in the 00034 same conditions as regards security. 00035 00036 The fact that you are presently reading this means that you have had 00037 knowledge of the CeCILL license and that you accept its terms. 00038 */ 00039 00040 #include "PgfGraphicDevice.h" 00041 using namespace bpp; 00042 00043 #include<algorithm> 00044 using namespace std; 00045 00046 00047 PgfGraphicDevice::PgfGraphicDevice(std::ostream& out, double unit) : 00048 out_(out), 00049 fgColorStr_("black"), 00050 bgColorStr_("white"), 00051 content_(), 00052 layers_(), 00053 colorIndex_(), 00054 colorCount_(0), 00055 useLayers_(false), 00056 contentStarted_(false), 00057 fontShapes_(), 00058 fontSeries_() 00059 { 00060 colorIndex_[ColorTools::BLACK] = "black"; 00061 colorIndex_[ColorTools::WHITE] = "white"; 00062 colorIndex_[ColorTools::BLUE] = "blue"; 00063 colorIndex_[ColorTools::RED] = "red"; 00064 colorIndex_[ColorTools::GREEN] = "green"; 00065 colorIndex_[ColorTools::YELLOW] = "yellow"; 00066 colorIndex_[ColorTools::CYAN] = "cyan"; 00067 colorIndex_[ColorTools::MAGENTA] = "magenta"; 00068 00069 fontShapes_[Font::STYLE_NORMAL] = "n"; 00070 fontShapes_[Font::STYLE_ITALIC] = "it"; 00071 fontSeries_[Font::WEIGHT_NORMAL] = "m"; 00072 fontSeries_[Font::WEIGHT_BOLD] = "bx"; 00073 00074 setCurrentFont(Font("cmtt", Font::STYLE_NORMAL, Font::WEIGHT_NORMAL, 12)); 00075 setXUnit(unit); 00076 setYUnit(unit); 00077 } 00078 00079 void PgfGraphicDevice::begin() 00080 { 00081 content_.clear(); 00082 layers_.clear(); 00083 colorIndex_.clear(); 00084 colorCount_ = 0; 00085 useLayers_ = false; 00086 contentStarted_ = false; 00087 } 00088 00089 bool comp( int a, int b ) { return a > b; } ; 00090 void PgfGraphicDevice::end() 00091 { 00092 ostringstream oss; 00093 if (useLayers_) 00094 oss << "\\end{pgfonlayer}{" << TextTools::toString(getCurrentLayer()) << "}" << endl; 00095 content_.push_back(oss.str()); 00096 00097 //Header: 00098 out_ << "\\documentclass{article}" << endl; 00099 out_ << "% This figure was generated by the Bio++ Pgf Graphic Device." << endl; 00100 out_ << "% Althought this file can be compiled 'as is' it may not be displayed correctly, depending on the size of the picture." << endl; 00101 out_ << "% You may consider copying the pgfpicture environment to your own LaTeX file and play with pgf settings (e.g. the pgfpages module)." << endl; 00102 out_ << "% You can also use the geometry package, for instance:" << endl; 00103 out_ << "% \\usepackage[a3paper]{geometry}" << endl; 00104 out_ << "\\usepackage{pgf}" << endl; 00105 for(map<const RGBColor, string>::iterator it = colorIndex_.begin(); it != colorIndex_.end(); it++) 00106 { 00107 if(it->second.substr(0,3) == "use") 00108 out_ << "\\definecolor{" << it->second << "}{rgb}{" << it->first[0]/255. << "," << it->first[1]/255. << "," << it->first[2]/255. << "}" << endl; 00109 } 00110 out_ << "\\begin{document}" << endl; 00111 00112 //Declare and set layers: 00113 if (useLayers_) 00114 { 00115 string tmp; 00116 sort(layers_.begin(), layers_.end(), comp); 00117 for(unsigned int i = 0; i < layers_.size(); i++) 00118 { 00119 if(i > 0) tmp += ","; 00120 tmp += TextTools::toString(layers_[i]); 00121 out_ << "\\pgfdeclarelayer{" << layers_[i] << "}" << endl; 00122 } 00123 out_ << "\\pgfsetlayers{" << tmp << "}" << endl; 00124 } 00125 00126 //Start picture: 00127 out_ << "\\begin{pgfpicture}" << endl; 00128 out_ << "\\pgfsetxvec{\\pgfpoint{" << getXUnit() << "cm}{0cm}}" << endl; 00129 out_ << "\\pgfsetyvec{\\pgfpoint{0cm}{-" << getYUnit() << "cm}}" << endl; 00130 00131 for(unsigned int i = 0; i < content_.size(); i++) 00132 { 00133 out_ << content_[i] << endl; 00134 } 00135 00136 out_ << "\\end{pgfpicture}" << endl; 00137 out_ << "\\end{document}" << endl; 00138 } 00139 00140 void PgfGraphicDevice::setCurrentForegroundColor(const RGBColor& color) 00141 { 00142 map<const RGBColor, string>::iterator it = colorIndex_.find(color); 00143 if(it != colorIndex_.end()) 00144 { 00145 fgColorStr_ = it->second; 00146 } 00147 else 00148 { 00149 colorCount_++; 00150 fgColorStr_ = "usercolor" + TextTools::toString(colorCount_); 00151 colorIndex_[color] = fgColorStr_; 00152 } 00153 AbstractGraphicDevice::setCurrentForegroundColor(color); 00154 ostringstream oss; 00155 oss << "\\pgfsetstrokecolor{" << fgColorStr_ << "}" << endl; 00156 content_.push_back(oss.str()); 00157 } 00158 00159 void PgfGraphicDevice::setCurrentBackgroundColor(const RGBColor& color) 00160 { 00161 map<const RGBColor, string>::iterator it = colorIndex_.find(color); 00162 if (it != colorIndex_.end()) 00163 { 00164 bgColorStr_ = it->second; 00165 } 00166 else 00167 { 00168 colorCount_++; 00169 bgColorStr_ = "usercolor" + TextTools::toString(colorCount_); 00170 colorIndex_[color] = bgColorStr_; 00171 } 00172 AbstractGraphicDevice::setCurrentBackgroundColor(color); 00173 ostringstream oss; 00174 oss << "\\pgfsetfillcolor{" << bgColorStr_ << "}" << endl; 00175 content_.push_back(oss.str()); 00176 } 00177 00178 void PgfGraphicDevice::setCurrentFont(const Font& font) 00179 { 00180 AbstractGraphicDevice::setCurrentFont(font); 00181 ostringstream oss; 00182 oss << "\\fontfamily{" << font.getFamily() << "}" << endl; 00183 oss << "\\fontseries{" << fontSeries_[font.getSeries()] << "}" << endl; 00184 oss << "\\fontshape{" << fontShapes_[font.getShape()] << "}" << endl; 00185 oss << "\\fontsize{" << font.getSize() << "}{" << font.getSize() << "}" << endl; 00186 oss << "\\selectfont" << endl; 00187 content_.push_back(oss.str()); 00188 } 00189 00190 void PgfGraphicDevice::setCurrentPointSize(unsigned int size) 00191 { 00192 AbstractGraphicDevice::setCurrentPointSize(size); 00193 ostringstream oss; 00194 oss << "\\pgfsetlinewidth{" << x_(size) << "}" << endl; 00195 content_.push_back(oss.str()); 00196 } 00197 00198 void PgfGraphicDevice::setCurrentLineType(short type) throw (Exception) 00199 { 00200 AbstractGraphicDevice::setCurrentLineType(type); 00201 if(type == LINE_SOLID) 00202 { 00203 ostringstream oss; 00204 oss << "\\pgfsetdash{}{0pt}" << endl; 00205 content_.push_back(oss.str()); 00206 } 00207 else if(type == LINE_DASHED) 00208 { 00209 ostringstream oss; 00210 oss << "\\pgfsetdash{{3mm}{2mm}}{0pt}" << endl; 00211 content_.push_back(oss.str()); 00212 } 00213 else if(type == LINE_DOTTED) 00214 { 00215 ostringstream oss; 00216 oss << "\\pgfsetdash{{" << (x_(getCurrentPointSize())) << "}{" << (x_(getCurrentPointSize())) << "}}{0pt}" << endl; 00217 content_.push_back(oss.str()); 00218 } 00219 else throw Exception("PgfGraphicDevice::setCurrentLineType. Unknown line type: " + TextTools::toString(type)); 00220 } 00221 00222 void PgfGraphicDevice::setCurrentLayer(int layerIndex) 00223 { 00224 if (!useLayers_ && contentStarted_) 00225 throw Exception("PgfGraphicDevice::setCurrentLayer. A layer is specified after some content has been already added, this would result in a corrupted display."); 00226 ostringstream oss; 00227 if (useLayers_) 00228 oss << "\\end{pgfonlayer}{" << TextTools::toString(getCurrentLayer()) << "}" << endl; 00229 oss << "\\begin{pgfonlayer}{" << TextTools::toString(layerIndex) << "}" << endl; 00230 //We have to recall the current color values for this layer: 00231 oss << "\\pgfsetstrokecolor{" << fgColorStr_ << "}" << endl; 00232 oss << "\\pgfsetfillcolor{" << bgColorStr_ << "}" << endl; 00233 content_.push_back(oss.str()); 00234 AbstractGraphicDevice::setCurrentLayer(layerIndex); 00235 if (find(layers_.begin(), layers_.end(), layerIndex) == layers_.end()) 00236 layers_.push_back(layerIndex); 00237 useLayers_ = true; 00238 } 00239 00240 void PgfGraphicDevice::drawLine(double x1, double y1, double x2, double y2) 00241 { 00242 ostringstream oss; 00243 oss << "\\pgfpathmoveto{\\pgfpointxy{" << x1 << "}{" << y1 << "}}" << endl; 00244 oss << "\\pgfpathlineto{\\pgfpointxy{" << x2 << "}{" << y2 << "}}" << endl; 00245 oss << "\\pgfpathclose" << endl; 00246 oss << "\\pgfusepath{stroke}" << endl; 00247 content_.push_back(oss.str()); 00248 contentStarted_ = true; 00249 } 00250 00251 void PgfGraphicDevice::drawRect(double x, double y, double width, double height, short fill) 00252 { 00253 ostringstream oss; 00254 oss << "\\pgfpathrectangle{\\pgfpointxy{" << x << "}{" << y << "}}{\\pgfpointxy{" << width << "}{" << height << "}}" << endl; 00255 if(fill == FILL_FILLED) 00256 oss << "\\pgfusepath{stroke,fill}" << endl; 00257 else 00258 oss << "\\pgfusepath{stroke}" << endl; 00259 content_.push_back(oss.str()); 00260 contentStarted_ = true; 00261 } 00262 00263 void PgfGraphicDevice::drawCircle(double x, double y, double radius, short fill) 00264 { 00265 ostringstream oss; 00266 oss << "\\pgfpathcircle{\\pgfpointxy{" << x << "}{" << y << "}}{" << radius << "}" << endl; 00267 if(fill == FILL_FILLED) 00268 oss << "\\pgfusepath{stroke,fill}" << endl; 00269 else 00270 oss << "\\pgfusepath{stroke}" << endl; 00271 content_.push_back(oss.str()); 00272 contentStarted_ = true; 00273 } 00274 00275 void PgfGraphicDevice::drawText(double x, double y, const std::string& text, short hpos, short vpos, double angle) throw (UnvalidFlagException) 00276 { 00277 string anchor; 00278 if(vpos == TEXT_VERTICAL_BOTTOM) 00279 anchor = "bottom"; 00280 else if(vpos == TEXT_VERTICAL_TOP) 00281 anchor = "top"; 00282 else if(vpos == TEXT_VERTICAL_CENTER) 00283 anchor = "base"; 00284 else throw UnvalidFlagException("PgfGraphicDevice::drawText. Invalid vertical alignment option."); 00285 if(hpos == TEXT_HORIZONTAL_LEFT) 00286 anchor += ",left"; 00287 else if(hpos == TEXT_HORIZONTAL_RIGHT) 00288 anchor += ",right"; 00289 else if(hpos == TEXT_HORIZONTAL_CENTER) 00290 anchor += ""; 00291 else throw UnvalidFlagException("PgfGraphicDevice::drawText. Invalid horizontal alignment option."); 00292 00293 ostringstream oss; 00294 oss << "\\pgftransformrotate{" << angle << "}" << endl; 00295 oss << "\\pgftext[" << anchor << ",at=\\pgfpointxy{" << x << "}{" << y << "}]{\\textcolor{" << fgColorStr_ << "}" << text << "}" << endl; 00296 content_.push_back(oss.str()); 00297 contentStarted_ = true; 00298 } 00299