A library for working with phylogenetic and population genetic data.
v0.27.0
svg/document.cpp
Go to the documentation of this file.
1 /*
2  Genesis - A toolkit for working with phylogenetic data.
3  Copyright (C) 2014-2020 Lucas Czech
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  Contact:
19  Lucas Czech <lucas.czech@h-its.org>
20  Exelixis Lab, Heidelberg Institute for Theoretical Studies
21  Schloss-Wolfsbrunnenweg 35, D-69118 Heidelberg, Germany
22 */
23 
32 
39 
40 namespace genesis {
41 namespace utils {
42 
43 // =================================================================================================
44 // Svg Document
45 // =================================================================================================
46 
47 // -------------------------------------------------------------
48 // Static Members
49 // -------------------------------------------------------------
50 
51 std::string SvgDocument::indentation_string = " ";
52 
53 // -------------------------------------------------------------
54 // Members
55 // -------------------------------------------------------------
56 
58 {
59  // Get bounding box of all elements and the dimensions of the document.
60  SvgBox bbox;
61  for( auto const& elem : content_ ) {
62  bbox = SvgBox::combine( bbox, elem.bounding_box() );
63  }
64  return bbox;
65 }
66 
70 void SvgDocument::write( std::ostream& out ) const
71 {
72  // Get a box around all elements, and use it to measure doc dimensions and shifting.
73  auto bbox = bounding_box();
74  double doc_width = margin.left + bbox.width() + margin.right;
75  double doc_height = margin.top + bbox.height() + margin.bottom;
76 
77  // SVG header.
78  out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
79  out << "<svg";
80  out << svg_attribute( "xmlns", "http://www.w3.org/2000/svg" );
81  out << svg_attribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" );
82  out << svg_attribute( "width", doc_width );
83  out << svg_attribute( "height", doc_height );
84  out << svg_attribute( "style", "background:" + color_to_hex( background_color, "#", false, true ));
85  if( overflow != Overflow::kNone ) {
86  out << overflow_to_string( overflow );
87  }
88  out << ">\n";
89 
90  // Some metadata.
91  out << svg_comment(
92  "Created with genesis " + genesis_version() + " (" + genesis_url() + ") " +
93  "on " + current_date() + " at " + current_time()
94  ) << "\n";
95  if( Options::get().command_line_string() != "" ) {
96  out << svg_comment( "Program invocation: " + Options::get().command_line_string() ) << "\n";
97  }
98 
99  // Gradients and other definitions. Need to come before the content.
100  if( ! defs.empty() ) {
101  out << SvgDocument::indentation_string << "<defs>\n";
102  for( auto const& def : defs ) {
103  def.write( out, 2 );
104  }
105  out << SvgDocument::indentation_string << "</defs>\n";
106  }
107 
108  // Options to hand over to all elements. Currently not needed, because we do the shifting
109  // for the margin by using a group (see immediately below).
110  auto options = SvgDrawingOptions();
111  // options.offset_x = margin.top;
112  // options.offset_y = margin.top;
113  // options.offset_x = margin.left - bbox.top_left.x;
114  // options.offset_y = margin.top - bbox.top_left.y;
115 
116  // Main group for all elements. We use this to make the handling of the margin
117  // easier.
118  out << SvgDocument::indentation_string << "<g transform=\"translate( ";
119  out << margin.left - bbox.top_left.x << ", " << margin.top - bbox.top_left.y;
120  out << ")\" >\n";
121 
122  // Different approach, use inner svg element instead of group.
123  // Didn't work well with some viewers.
124  // out << SvgDocument::indentation_string << "<svg";
125  // out << svg_attribute( "x", margin.left - bbox.top_left.x );
126  // out << svg_attribute( "y", margin.top - bbox.top_left.y );
127  // out << ">\n";
128 
129  // Print content.
130  for( auto const& elem : content_ ) {
131  elem.write( out, 2, options );
132 
133  // Draw bounding boxes around all elements, for testing purposes.
134  // auto bb = elem.bounding_box();
135  // SvgRect( bb.top_left, bb.size(), SvgStroke(), SvgFill( Color(), 0.0 ) ).write( out, 1 );
136  }
137 
138  // Close main grouping.
139  // out << SvgDocument::indentation_string << "</svg>\n";
140  out << SvgDocument::indentation_string << "</g>\n";
141 
142  // Finish.
143  out << "</svg>\n";
144 }
145 
147 {
148  content_.push_back( object );
149  return *this;
150 }
151 
153 {
154  content_.push_back( std::move( object ));
155  return *this;
156 }
157 
159 {
160  return add( object );
161 }
162 
164 {
165  return add( std::move( object ));
166 }
167 
168 std::string SvgDocument::overflow_to_string( SvgDocument::Overflow value )
169 {
170  // switch( value ) {
171  // case Overflow::kNone:
172  // return std::string();
173  // case Overflow::kVisible:
174  // return svg_attribute( "style", "overflow: visible" );
175  // case Overflow::kHidden:
176  // return svg_attribute( "style", "overflow: hidden" );
177  // case Overflow::kScroll:
178  // return svg_attribute( "style", "overflow: scroll" );
179  // case Overflow::kAuto:
180  // return svg_attribute( "style", "overflow: auto" );
181  // case Overflow::kInherit:
182  // return svg_attribute( "style", "overflow: inherit" );
183  // default:
184  // throw std::invalid_argument(
185  // "Invalid Svg attribute Overflow for Svg Document."
186  // );
187  // }
188  switch( value ) {
189  case Overflow::kNone:
190  return std::string();
191  case Overflow::kVisible:
192  return svg_attribute( "overflow", "visible" );
193  case Overflow::kHidden:
194  return svg_attribute( "overflow", "hidden" );
195  case Overflow::kScroll:
196  return svg_attribute( "overflow", "scroll" );
197  case Overflow::kAuto:
198  return svg_attribute( "overflow", "auto" );
199  case Overflow::kInherit:
200  return svg_attribute( "overflow", "inherit" );
201  default:
202  throw std::invalid_argument(
203  "Invalid Svg attribute Overflow for Svg Document."
204  );
205  }
206 }
207 
208 } // namespace utils
209 } // namespace genesis
genesis::genesis_url
std::string genesis_url()
Return the URL of the genesis home page.
Definition: version.hpp:83
genesis::utils::SvgMargin::bottom
double bottom
Definition: utils/formats/svg/helper.hpp:108
helper.hpp
genesis::utils::SvgDocument::Overflow::kInherit
@ kInherit
genesis::utils::SvgBox::combine
static SvgBox combine(SvgBox const &lhs, SvgBox const &rhs)
Definition: utils/formats/svg/helper.hpp:170
genesis::utils::current_date
std::string current_date()
Returns the current date as a string in the format "2014-12-31".
Definition: date_time.cpp:68
genesis::utils::SvgDocument::margin
SvgMargin margin
Definition: svg/document.hpp:120
date_time.hpp
Provides functions for date and time access.
genesis::utils::svg_comment
std::string svg_comment(std::string const &content)
Definition: utils/formats/svg/helper.hpp:212
genesis::utils::SvgMargin::top
double top
Definition: utils/formats/svg/helper.hpp:106
version.hpp
Some stuff that is totally not imporatant, but nice.
genesis::utils::SvgBox
Definition: utils/formats/svg/helper.hpp:116
genesis::utils::current_time
std::string current_time()
Returns the current time as a string in the format "13:37:42".
Definition: date_time.cpp:88
genesis::utils::SvgDocument::write
void write(std::ostream &out) const
Write the SvgDocument to an output stream.
Definition: svg/document.cpp:70
genesis::utils::SvgDocument::overflow
Overflow overflow
Definition: svg/document.hpp:121
genesis::utils::SvgDocument::indentation_string
static std::string indentation_string
Definition: svg/document.hpp:59
string.hpp
Provides some commonly used string utility functions.
document.hpp
genesis::utils::SvgDocument::operator<<
self_type & operator<<(SvgObject const &object)
Shortcut operator for add(), which allows an even more fluent interface.
Definition: svg/document.cpp:158
genesis::utils::SvgDocument::add
self_type & add(SvgObject const &object)
Add an SvgObject to the document.
Definition: svg/document.cpp:146
genesis::utils::SvgDocument::background_color
Color background_color
Definition: svg/document.hpp:124
genesis
Container namespace for all symbols of genesis in order to keep them separate when used as a library.
Definition: placement/formats/edge_color.cpp:42
genesis::utils::SvgMargin::right
double right
Definition: utils/formats/svg/helper.hpp:107
genesis::utils::svg_attribute
std::string svg_attribute(std::string const &name, T const &value, std::string const &unit="")
Definition: utils/formats/svg/helper.hpp:218
genesis::utils::SvgDocument::Overflow::kAuto
@ kAuto
functions.hpp
Color operators and functions.
genesis::utils::SvgDocument
Definition: svg/document.hpp:49
genesis::utils::SvgDocument::defs
std::vector< SvgDefinitions > defs
Definition: svg/document.hpp:123
options.hpp
genesis::utils::SvgDocument::Overflow::kNone
@ kNone
genesis::utils::SvgDocument::bounding_box
SvgBox bounding_box() const
Definition: svg/document.cpp:57
genesis::utils::SvgDocument::Overflow::kVisible
@ kVisible
genesis::genesis_version
std::string genesis_version()
Return the current genesis version.
Definition: version.hpp:63
genesis::utils::Options::get
static Options & get()
Returns a single instance of this class.
Definition: options.hpp:60
genesis::utils::SvgDrawingOptions
Definition: utils/formats/svg/helper.hpp:202
genesis::utils::color_to_hex
std::string color_to_hex(Color const &c, std::string const &prefix, bool uppercase, bool with_alpha)
Return a hex string representation of a Color in the format "#003366[ff]".
Definition: utils/tools/color/functions.cpp:100
genesis::utils::SvgObject
Definition: object.hpp:46
genesis::utils::SvgDocument::Overflow::kScroll
@ kScroll
genesis::utils::SvgDocument::Overflow
Overflow
Definition: svg/document.hpp:61
genesis::utils::SvgMargin::left
double left
Definition: utils/formats/svg/helper.hpp:109
genesis::utils::SvgDocument::Overflow::kHidden
@ kHidden