bpp-core3  3.0.0
PgfGraphicDevice.cpp
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: The Bio++ Development Group
2 //
3 // SPDX-License-Identifier: CECILL-2.1
4 
5 #include "PgfGraphicDevice.h"
6 
7 using namespace bpp;
8 
9 #include <algorithm>
10 using namespace std;
11 
12 
13 PgfGraphicDevice::PgfGraphicDevice(std::ostream& out, double unit) :
14  out_(out),
15  fgColorStr_("black"),
16  bgColorStr_("white"),
17  content_(),
18  layers_(),
19  colorIndex_(),
20  colorCount_(0),
21  useLayers_(false),
22  contentStarted_(false),
23  fontShapes_(),
24  fontSeries_()
25 {
26  colorIndex_[ColorTools::BLACK] = "black";
27  colorIndex_[ColorTools::WHITE] = "white";
28  colorIndex_[ColorTools::BLUE] = "blue";
30  colorIndex_[ColorTools::GREEN] = "green";
31  colorIndex_[ColorTools::YELLOW] = "yellow";
32  colorIndex_[ColorTools::CYAN] = "cyan";
33  colorIndex_[ColorTools::MAGENTA] = "magenta";
34 
39 
41  setXUnit(unit);
42  setYUnit(unit);
43 }
44 
46 {
47  content_.clear();
48  layers_.clear();
49  colorIndex_.clear();
50  colorCount_ = 0;
51  useLayers_ = false;
52  contentStarted_ = false;
53 }
54 
55 bool comp( int a, int b ) { return a > b; }
57 {
58  ostringstream oss;
59  if (useLayers_)
60  oss << "\\end{pgfonlayer}{" << TextTools::toString(getCurrentLayer()) << "}" << endl;
61  content_.push_back(oss.str());
62 
63  // Header:
64  out_ << "\\documentclass{article}" << endl;
65  out_ << "% This figure was generated by the Bio++ Pgf Graphic Device." << endl;
66  out_ << "% Althought this file can be compiled 'as is' it may not be displayed correctly, depending on the size of the picture." << endl;
67  out_ << "% You may consider copying the pgfpicture environment to your own LaTeX file and play with pgf settings (e.g. the pgfpages module)." << endl;
68  out_ << "% You can also use the geometry package, for instance:" << endl;
69  out_ << "% \\usepackage[a3paper]{geometry}" << endl;
70  out_ << "\\usepackage{pgf}" << endl;
71  for (map<const RGBColor, string>::iterator it = colorIndex_.begin(); it != colorIndex_.end(); it++)
72  {
73  if (it->second.substr(0, 3) == "use")
74  out_ << "\\definecolor{" << it->second << "}{rgb}{" << it->first[0] / 255. << "," << it->first[1] / 255. << "," << it->first[2] / 255. << "}" << endl;
75  }
76  out_ << "\\begin{document}" << endl;
77 
78  // Declare and set layers:
79  if (useLayers_)
80  {
81  string tmp;
82  sort(layers_.begin(), layers_.end(), comp);
83  for (unsigned int i = 0; i < layers_.size(); i++)
84  {
85  if (i > 0)
86  tmp += ",";
87  tmp += TextTools::toString(layers_[i]);
88  out_ << "\\pgfdeclarelayer{" << layers_[i] << "}" << endl;
89  }
90  out_ << "\\pgfsetlayers{" << tmp << "}" << endl;
91  }
92 
93  // Start picture:
94  out_ << "\\begin{pgfpicture}" << endl;
95  out_ << "\\pgfsetxvec{\\pgfpoint{" << getXUnit() << "cm}{0cm}}" << endl;
96  out_ << "\\pgfsetyvec{\\pgfpoint{0cm}{-" << getYUnit() << "cm}}" << endl;
97 
98  for (unsigned int i = 0; i < content_.size(); i++)
99  {
100  out_ << content_[i] << endl;
101  }
102 
103  out_ << "\\end{pgfpicture}" << endl;
104  out_ << "\\end{document}" << endl;
105 }
106 
108 {
109  map<const RGBColor, string>::iterator it = colorIndex_.find(color);
110  if (it != colorIndex_.end())
111  {
112  fgColorStr_ = it->second;
113  }
114  else
115  {
116  colorCount_++;
118  colorIndex_[color] = fgColorStr_;
119  }
121  ostringstream oss;
122  oss << "\\pgfsetstrokecolor{" << fgColorStr_ << "}" << endl;
123  content_.push_back(oss.str());
124 }
125 
127 {
128  map<const RGBColor, string>::iterator it = colorIndex_.find(color);
129  if (it != colorIndex_.end())
130  {
131  bgColorStr_ = it->second;
132  }
133  else
134  {
135  colorCount_++;
137  colorIndex_[color] = bgColorStr_;
138  }
140  ostringstream oss;
141  oss << "\\pgfsetfillcolor{" << bgColorStr_ << "}" << endl;
142  content_.push_back(oss.str());
143 }
144 
146 {
148  ostringstream oss;
149  oss << "\\fontfamily{" << font.getFamily() << "}" << endl;
150  oss << "\\fontseries{" << fontSeries_[font.getSeries()] << "}" << endl;
151  oss << "\\fontshape{" << fontShapes_[font.getShape()] << "}" << endl;
152  oss << "\\fontsize{" << font.getSize() << "}{" << font.getSize() << "}" << endl;
153  oss << "\\selectfont" << endl;
154  content_.push_back(oss.str());
155 }
156 
158 {
160  ostringstream oss;
161  oss << "\\pgfsetlinewidth{" << x_(size) << "}" << endl;
162  content_.push_back(oss.str());
163 }
164 
166 {
168  if (type == LINE_SOLID)
169  {
170  ostringstream oss;
171  oss << "\\pgfsetdash{}{0pt}" << endl;
172  content_.push_back(oss.str());
173  }
174  else if (type == LINE_DASHED)
175  {
176  ostringstream oss;
177  oss << "\\pgfsetdash{{3mm}{2mm}}{0pt}" << endl;
178  content_.push_back(oss.str());
179  }
180  else if (type == LINE_DOTTED)
181  {
182  ostringstream oss;
183  oss << "\\pgfsetdash{{" << (x_(getCurrentPointSize())) << "}{" << (x_(getCurrentPointSize())) << "}}{0pt}" << endl;
184  content_.push_back(oss.str());
185  }
186  else
187  throw Exception("PgfGraphicDevice::setCurrentLineType. Unknown line type: " + TextTools::toString(type));
188 }
189 
191 {
192  if (!useLayers_ && contentStarted_)
193  throw Exception("PgfGraphicDevice::setCurrentLayer. A layer is specified after some content has been already added, this would result in a corrupted display.");
194  ostringstream oss;
195  if (useLayers_)
196  oss << "\\end{pgfonlayer}{" << TextTools::toString(getCurrentLayer()) << "}" << endl;
197  oss << "\\begin{pgfonlayer}{" << TextTools::toString(layerIndex) << "}" << endl;
198  // We have to recall the current color values for this layer:
199  oss << "\\pgfsetstrokecolor{" << fgColorStr_ << "}" << endl;
200  oss << "\\pgfsetfillcolor{" << bgColorStr_ << "}" << endl;
201  content_.push_back(oss.str());
203  if (find(layers_.begin(), layers_.end(), layerIndex) == layers_.end())
204  layers_.push_back(layerIndex);
205  useLayers_ = true;
206 }
207 
208 void PgfGraphicDevice::drawLine(double x1, double y1, double x2, double y2)
209 {
210  ostringstream oss;
211  oss << "\\pgfpathmoveto{\\pgfpointxy{" << x1 << "}{" << y1 << "}}" << endl;
212  oss << "\\pgfpathlineto{\\pgfpointxy{" << x2 << "}{" << y2 << "}}" << endl;
213  oss << "\\pgfpathclose" << endl;
214  oss << "\\pgfusepath{stroke}" << endl;
215  content_.push_back(oss.str());
216  contentStarted_ = true;
217 }
218 
219 void PgfGraphicDevice::drawRect(double x, double y, double width, double height, short fill)
220 {
221  ostringstream oss;
222  oss << "\\pgfpathrectangle{\\pgfpointxy{" << x << "}{" << y << "}}{\\pgfpointxy{" << width << "}{" << height << "}}" << endl;
223  if (fill == FILL_FILLED)
224  oss << "\\pgfusepath{stroke,fill}" << endl;
225  else
226  oss << "\\pgfusepath{stroke}" << endl;
227  content_.push_back(oss.str());
228  contentStarted_ = true;
229 }
230 
231 void PgfGraphicDevice::drawCircle(double x, double y, double radius, short fill)
232 {
233  ostringstream oss;
234  oss << "\\pgfpathcircle{\\pgfpointxy{" << x << "}{" << y << "}}{" << radius << "}" << endl;
235  if (fill == FILL_FILLED)
236  oss << "\\pgfusepath{stroke,fill}" << endl;
237  else
238  oss << "\\pgfusepath{stroke}" << endl;
239  content_.push_back(oss.str());
240  contentStarted_ = true;
241 }
242 
243 void PgfGraphicDevice::drawText(double x, double y, const std::string& text, short hpos, short vpos, double angle)
244 {
245  string anchor;
246  if (vpos == TEXT_VERTICAL_BOTTOM)
247  anchor = "bottom";
248  else if (vpos == TEXT_VERTICAL_TOP)
249  anchor = "top";
250  else if (vpos == TEXT_VERTICAL_CENTER)
251  anchor = "base";
252  else
253  throw UnvalidFlagException("PgfGraphicDevice::drawText. Invalid vertical alignment option.");
254  if (hpos == TEXT_HORIZONTAL_LEFT)
255  anchor += ",left";
256  else if (hpos == TEXT_HORIZONTAL_RIGHT)
257  anchor += ",right";
258  else if (hpos == TEXT_HORIZONTAL_CENTER)
259  anchor += "";
260  else
261  throw UnvalidFlagException("PgfGraphicDevice::drawText. Invalid horizontal alignment option.");
262 
263  ostringstream oss;
264  oss << "\\pgftransformrotate{" << angle << "}" << endl;
265  oss << "\\pgftext[" << anchor << ",at=\\pgfpointxy{" << x << "}{" << y << "}]{\\textcolor{" << fgColorStr_ << "}" << text << "}" << endl;
266  content_.push_back(oss.str());
267  contentStarted_ = true;
268 }
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:89
static const short int WEIGHT_NORMAL
Definition: Font.h:131
static const short int STYLE_NORMAL
Definition: Font.h:128
static const RGBColor BLUE
Definition: ColorTools.h:85
void drawRect(double x, double y, double width, double height, short fill=FILL_EMPTY)
Draw a rectangle.
Data structure for fonts.
Definition: Font.h:21
static const RGBColor RED
Definition: ColorTools.h:83
void end()
End the painting.
static short TEXT_VERTICAL_TOP
std::map< const RGBColor, std::string > colorIndex_
static const RGBColor YELLOW
Definition: ColorTools.h:88
static const RGBColor BLACK
Definition: ColorTools.h:86
void drawCircle(double x, double y, double radius, short fill=FILL_EMPTY)
Draw a circle.
std::map< short int, std::string > fontShapes_
void setCurrentFont(const Font &font)
static short LINE_SOLID
void setCurrentForegroundColor(const RGBColor &color)
STL namespace.
void setCurrentBackgroundColor(const RGBColor &color)
Describe a color according to its red, green and blue componants.
Definition: RgbColor.h:21
static const short int STYLE_ITALIC
Definition: Font.h:129
static short LINE_DOTTED
unsigned int getCurrentPointSize() const
static const RGBColor GREEN
Definition: ColorTools.h:84
static short TEXT_HORIZONTAL_RIGHT
void setCurrentLineType(short type)
static short LINE_DASHED
std::vector< std::string > content_
void setCurrentLayer(int layerIndex)
static const short int WEIGHT_BOLD
Definition: Font.h:132
void setCurrentPointSize(unsigned int size)
void setCurrentForegroundColor(const RGBColor &color)
static short TEXT_HORIZONTAL_CENTER
const unsigned int & getSize() const
Definition: Font.h:84
void setCurrentLayer(int layerIndex)
std::map< short int, std::string > fontSeries_
static short FILL_FILLED
Exception base class. Overload exception constructor (to control the exceptions mechanism). Destructor is already virtual (from std::exception)
Definition: Exceptions.h:20
bool comp(int a, int b)
short int getSeries() const
Alias function for getWeight.
Definition: Font.h:79
static short TEXT_VERTICAL_BOTTOM
void begin()
Start the painting.
static const RGBColor MAGENTA
Definition: ColorTools.h:90
std::vector< int > layers_
void setCurrentPointSize(unsigned int size)
static const RGBColor WHITE
Definition: ColorTools.h:87
short int getShape() const
Alias function for getStyle.
Definition: Font.h:68
std::string toString(T t)
General template method to convert to a string.
Definition: TextTools.h:115
PgfGraphicDevice(std::ostream &out, double unit)
Build a new Pgf device object.
const std::string & getFamily() const
Definition: Font.h:57
void setCurrentBackgroundColor(const RGBColor &color)
void drawLine(double x1, double y1, double x2, double y2)
Draw a line between two points.
static short TEXT_VERTICAL_CENTER
void setCurrentFont(const Font &font)
static short TEXT_HORIZONTAL_LEFT