bpp-core  2.2.0
PgfGraphicDevice.cpp
Go to the documentation of this file.
1 //
2 // File: PgfGraphicDevice.cpp
3 // Created by: Julien Dutheil
4 // Created on: Thu Jun 19 2008
5 //
6 
7 /*
8 Copyright or © or Copr. CNRS, (November 17, 2004)
9 
10 This software is a computer program whose purpose is to provide utilitary
11 classes. This file belongs to the Bio++ Project.
12 
13 This software is governed by the CeCILL license under French law and
14 abiding by the rules of distribution of free software. You can use,
15 modify and/ or redistribute the software under the terms of the CeCILL
16 license as circulated by CEA, CNRS and INRIA at the following URL
17 "http://www.cecill.info".
18 
19 As a counterpart to the access to the source code and rights to copy,
20 modify and redistribute granted by the license, users are provided only
21 with a limited warranty and the software's author, the holder of the
22 economic rights, and the successive licensors have only limited
23 liability.
24 
25 In this respect, the user's attention is drawn to the risks associated
26 with loading, using, modifying and/or developing or reproducing the
27 software by the user in light of its specific status of free software,
28 that may mean that it is complicated to manipulate, and that also
29 therefore means that it is reserved for developers and experienced
30 professionals having in-depth computer knowledge. Users are therefore
31 encouraged to load and test the software's suitability as regards their
32 requirements in conditions enabling the security of their systems and/or
33 data to be ensured and, more generally, to use and operate it in the
34 same conditions as regards security.
35 
36 The fact that you are presently reading this means that you have had
37 knowledge of the CeCILL license and that you accept its terms.
38 */
39 
40 #include "PgfGraphicDevice.h"
41 using namespace bpp;
42 
43 #include<algorithm>
44 using namespace std;
45 
46 
47 PgfGraphicDevice::PgfGraphicDevice(std::ostream& out, double unit) :
48  out_(out),
49  fgColorStr_("black"),
50  bgColorStr_("white"),
51  content_(),
52  layers_(),
53  colorIndex_(),
54  colorCount_(0),
55  useLayers_(false),
56  contentStarted_(false),
57  fontShapes_(),
58  fontSeries_()
59 {
60  colorIndex_[ColorTools::BLACK] = "black";
61  colorIndex_[ColorTools::WHITE] = "white";
62  colorIndex_[ColorTools::BLUE] = "blue";
64  colorIndex_[ColorTools::GREEN] = "green";
65  colorIndex_[ColorTools::YELLOW] = "yellow";
66  colorIndex_[ColorTools::CYAN] = "cyan";
67  colorIndex_[ColorTools::MAGENTA] = "magenta";
68 
73 
75  setXUnit(unit);
76  setYUnit(unit);
77 }
78 
80 {
81  content_.clear();
82  layers_.clear();
83  colorIndex_.clear();
84  colorCount_ = 0;
85  useLayers_ = false;
86  contentStarted_ = false;
87 }
88 
89 bool comp( int a, int b ) { return a > b; } ;
91 {
92  ostringstream oss;
93  if (useLayers_)
94  oss << "\\end{pgfonlayer}{" << TextTools::toString(getCurrentLayer()) << "}" << endl;
95  content_.push_back(oss.str());
96 
97  //Header:
98  out_ << "\\documentclass{article}" << endl;
99  out_ << "% This figure was generated by the Bio++ Pgf Graphic Device." << endl;
100  out_ << "% Althought this file can be compiled 'as is' it may not be displayed correctly, depending on the size of the picture." << endl;
101  out_ << "% You may consider copying the pgfpicture environment to your own LaTeX file and play with pgf settings (e.g. the pgfpages module)." << endl;
102  out_ << "% You can also use the geometry package, for instance:" << endl;
103  out_ << "% \\usepackage[a3paper]{geometry}" << endl;
104  out_ << "\\usepackage{pgf}" << endl;
105  for(map<const RGBColor, string>::iterator it = colorIndex_.begin(); it != colorIndex_.end(); it++)
106  {
107  if(it->second.substr(0,3) == "use")
108  out_ << "\\definecolor{" << it->second << "}{rgb}{" << it->first[0]/255. << "," << it->first[1]/255. << "," << it->first[2]/255. << "}" << endl;
109  }
110  out_ << "\\begin{document}" << endl;
111 
112  //Declare and set layers:
113  if (useLayers_)
114  {
115  string tmp;
116  sort(layers_.begin(), layers_.end(), comp);
117  for(unsigned int i = 0; i < layers_.size(); i++)
118  {
119  if(i > 0) tmp += ",";
120  tmp += TextTools::toString(layers_[i]);
121  out_ << "\\pgfdeclarelayer{" << layers_[i] << "}" << endl;
122  }
123  out_ << "\\pgfsetlayers{" << tmp << "}" << endl;
124  }
125 
126  //Start picture:
127  out_ << "\\begin{pgfpicture}" << endl;
128  out_ << "\\pgfsetxvec{\\pgfpoint{" << getXUnit() << "cm}{0cm}}" << endl;
129  out_ << "\\pgfsetyvec{\\pgfpoint{0cm}{-" << getYUnit() << "cm}}" << endl;
130 
131  for(unsigned int i = 0; i < content_.size(); i++)
132  {
133  out_ << content_[i] << endl;
134  }
135 
136  out_ << "\\end{pgfpicture}" << endl;
137  out_ << "\\end{document}" << endl;
138 }
139 
141 {
142  map<const RGBColor, string>::iterator it = colorIndex_.find(color);
143  if(it != colorIndex_.end())
144  {
145  fgColorStr_ = it->second;
146  }
147  else
148  {
149  colorCount_++;
151  colorIndex_[color] = fgColorStr_;
152  }
154  ostringstream oss;
155  oss << "\\pgfsetstrokecolor{" << fgColorStr_ << "}" << endl;
156  content_.push_back(oss.str());
157 }
158 
160 {
161  map<const RGBColor, string>::iterator it = colorIndex_.find(color);
162  if (it != colorIndex_.end())
163  {
164  bgColorStr_ = it->second;
165  }
166  else
167  {
168  colorCount_++;
170  colorIndex_[color] = bgColorStr_;
171  }
173  ostringstream oss;
174  oss << "\\pgfsetfillcolor{" << bgColorStr_ << "}" << endl;
175  content_.push_back(oss.str());
176 }
177 
179 {
181  ostringstream oss;
182  oss << "\\fontfamily{" << font.getFamily() << "}" << endl;
183  oss << "\\fontseries{" << fontSeries_[font.getSeries()] << "}" << endl;
184  oss << "\\fontshape{" << fontShapes_[font.getShape()] << "}" << endl;
185  oss << "\\fontsize{" << font.getSize() << "}{" << font.getSize() << "}" << endl;
186  oss << "\\selectfont" << endl;
187  content_.push_back(oss.str());
188 }
189 
191 {
193  ostringstream oss;
194  oss << "\\pgfsetlinewidth{" << x_(size) << "}" << endl;
195  content_.push_back(oss.str());
196 }
197 
199 {
201  if(type == LINE_SOLID)
202  {
203  ostringstream oss;
204  oss << "\\pgfsetdash{}{0pt}" << endl;
205  content_.push_back(oss.str());
206  }
207  else if(type == LINE_DASHED)
208  {
209  ostringstream oss;
210  oss << "\\pgfsetdash{{3mm}{2mm}}{0pt}" << endl;
211  content_.push_back(oss.str());
212  }
213  else if(type == LINE_DOTTED)
214  {
215  ostringstream oss;
216  oss << "\\pgfsetdash{{" << (x_(getCurrentPointSize())) << "}{" << (x_(getCurrentPointSize())) << "}}{0pt}" << endl;
217  content_.push_back(oss.str());
218  }
219  else throw Exception("PgfGraphicDevice::setCurrentLineType. Unknown line type: " + TextTools::toString(type));
220 }
221 
223 {
224  if (!useLayers_ && contentStarted_)
225  throw Exception("PgfGraphicDevice::setCurrentLayer. A layer is specified after some content has been already added, this would result in a corrupted display.");
226  ostringstream oss;
227  if (useLayers_)
228  oss << "\\end{pgfonlayer}{" << TextTools::toString(getCurrentLayer()) << "}" << endl;
229  oss << "\\begin{pgfonlayer}{" << TextTools::toString(layerIndex) << "}" << endl;
230  //We have to recall the current color values for this layer:
231  oss << "\\pgfsetstrokecolor{" << fgColorStr_ << "}" << endl;
232  oss << "\\pgfsetfillcolor{" << bgColorStr_ << "}" << endl;
233  content_.push_back(oss.str());
235  if (find(layers_.begin(), layers_.end(), layerIndex) == layers_.end())
236  layers_.push_back(layerIndex);
237  useLayers_ = true;
238 }
239 
240 void PgfGraphicDevice::drawLine(double x1, double y1, double x2, double y2)
241 {
242  ostringstream oss;
243  oss << "\\pgfpathmoveto{\\pgfpointxy{" << x1 << "}{" << y1 << "}}" << endl;
244  oss << "\\pgfpathlineto{\\pgfpointxy{" << x2 << "}{" << y2 << "}}" << endl;
245  oss << "\\pgfpathclose" << endl;
246  oss << "\\pgfusepath{stroke}" << endl;
247  content_.push_back(oss.str());
248  contentStarted_ = true;
249 }
250 
251 void PgfGraphicDevice::drawRect(double x, double y, double width, double height, short fill)
252 {
253  ostringstream oss;
254  oss << "\\pgfpathrectangle{\\pgfpointxy{" << x << "}{" << y << "}}{\\pgfpointxy{" << width << "}{" << height << "}}" << endl;
255  if(fill == FILL_FILLED)
256  oss << "\\pgfusepath{stroke,fill}" << endl;
257  else
258  oss << "\\pgfusepath{stroke}" << endl;
259  content_.push_back(oss.str());
260  contentStarted_ = true;
261 }
262 
263 void PgfGraphicDevice::drawCircle(double x, double y, double radius, short fill)
264 {
265  ostringstream oss;
266  oss << "\\pgfpathcircle{\\pgfpointxy{" << x << "}{" << y << "}}{" << radius << "}" << endl;
267  if(fill == FILL_FILLED)
268  oss << "\\pgfusepath{stroke,fill}" << endl;
269  else
270  oss << "\\pgfusepath{stroke}" << endl;
271  content_.push_back(oss.str());
272  contentStarted_ = true;
273 }
274 
275 void PgfGraphicDevice::drawText(double x, double y, const std::string& text, short hpos, short vpos, double angle) throw (UnvalidFlagException)
276 {
277  string anchor;
278  if(vpos == TEXT_VERTICAL_BOTTOM)
279  anchor = "bottom";
280  else if(vpos == TEXT_VERTICAL_TOP)
281  anchor = "top";
282  else if(vpos == TEXT_VERTICAL_CENTER)
283  anchor = "base";
284  else throw UnvalidFlagException("PgfGraphicDevice::drawText. Invalid vertical alignment option.");
285  if(hpos == TEXT_HORIZONTAL_LEFT)
286  anchor += ",left";
287  else if(hpos == TEXT_HORIZONTAL_RIGHT)
288  anchor += ",right";
289  else if(hpos == TEXT_HORIZONTAL_CENTER)
290  anchor += "";
291  else throw UnvalidFlagException("PgfGraphicDevice::drawText. Invalid horizontal alignment option.");
292 
293  ostringstream oss;
294  oss << "\\pgftransformrotate{" << angle << "}" << endl;
295  oss << "\\pgftext[" << anchor << ",at=\\pgfpointxy{" << x << "}{" << y << "}]{\\textcolor{" << fgColorStr_ << "}" << text << "}" << endl;
296  content_.push_back(oss.str());
297  contentStarted_ = true;
298 }
299 
void drawText(double x, double y, const std::string &text, short hpos=TEXT_HORIZONTAL_LEFT, short vpos=TEXT_VERTICAL_BOTTOM, double angle=0)
Draw some characters.
static const RGBColor CYAN
Definition: ColorTools.h:124
static const short int WEIGHT_NORMAL
Definition: Font.h:171
static const short int STYLE_NORMAL
Definition: Font.h:168
static const RGBColor BLUE
Definition: ColorTools.h:120
void drawRect(double x, double y, double width, double height, short fill=FILL_EMPTY)
Draw a rectangle.
Data structure for fonts.
Definition: Font.h:56
static const RGBColor RED
Definition: ColorTools.h:118
void end()
End the painting.
std::map< const RGBColor, std::string > colorIndex_
This class allows to perform a correspondence analysis.
static const RGBColor YELLOW
Definition: ColorTools.h:123
static const RGBColor BLACK
Definition: ColorTools.h:121
void drawCircle(double x, double y, double radius, short fill=FILL_EMPTY)
Draw a circle.
const short int getShape() const
Alias function for getStyle.
Definition: Font.h:108
std::map< short int, std::string > fontShapes_
void setCurrentFont(const Font &font)
void setCurrentForegroundColor(const RGBColor &color)
const short int getSeries() const
Alias function for getWeight.
Definition: Font.h:119
STL namespace.
void setCurrentBackgroundColor(const RGBColor &color)
Describe a color according to its red, green and blue componants.
Definition: RgbColor.h:56
static const short int STYLE_ITALIC
Definition: Font.h:169
static const RGBColor GREEN
Definition: ColorTools.h:119
static std::string toString(T t)
General template method to convert to a string.
Definition: TextTools.h:189
void setCurrentLineType(short type)
std::vector< std::string > content_
void setCurrentLayer(int layerIndex)
static const short int WEIGHT_BOLD
Definition: Font.h:172
void setCurrentPointSize(unsigned int size)
void setCurrentForegroundColor(const RGBColor &color)
const unsigned int & getSize() const
Definition: Font.h:124
void setCurrentLayer(int layerIndex)
std::map< short int, std::string > fontSeries_
static short FILL_FILLED
Exception base class.
Definition: Exceptions.h:57
bool comp(int a, int b)
void begin()
Start the painting.
static const RGBColor MAGENTA
Definition: ColorTools.h:125
std::vector< int > layers_
void setCurrentPointSize(unsigned int size)
static const RGBColor WHITE
Definition: ColorTools.h:122
PgfGraphicDevice(std::ostream &out, double unit)
Build a new Pgf device object.
const std::string & getFamily() const
Definition: Font.h:97
void setCurrentBackgroundColor(const RGBColor &color)
void drawLine(double x1, double y1, double x2, double y2)
Draw a line between two points.
void setCurrentFont(const Font &font)