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