A toolkit for working with phylogenetic data.
v0.18.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
svg/document.cpp
Go to the documentation of this file.
1 /*
2  Genesis - A toolkit for working with phylogenetic data.
3  Copyright (C) 2014-2017 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 
38 
39 namespace genesis {
40 namespace utils {
41 
42 // =================================================================================================
43 // Svg Document
44 // =================================================================================================
45 
46 // -------------------------------------------------------------
47 // Static Members
48 // -------------------------------------------------------------
49 
50 std::string SvgDocument::indentation_string = " ";
51 
52 // -------------------------------------------------------------
53 // Members
54 // -------------------------------------------------------------
55 
57 {
58  // Get bounding box of all elements and the dimensions of the document.
59  SvgBox bbox;
60  for( auto const& elem : content_ ) {
61  bbox = SvgBox::combine( bbox, elem.bounding_box() );
62  }
63  return bbox;
64 }
65 
69 void SvgDocument::write( std::ostream& out ) const
70 {
71  // Get a box around all elements, and use it to measure doc dimensions and shifting.
72  auto bbox = bounding_box();
73  double doc_width = margin.left + bbox.width() + margin.right;
74  double doc_height = margin.top + bbox.height() + margin.bottom;
75 
76  // SVG header.
77  out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
78  out << "<svg";
79  out << svg_attribute( "xmlns", "http://www.w3.org/2000/svg" );
80  out << svg_attribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" );
81  out << svg_attribute( "width", doc_width );
82  out << svg_attribute( "height", doc_height );
83  out << ">\n";
84 
85  // Some metadata.
86  out << svg_comment(
87  "Created with genesis " + genesis_version() + " (" + genesis_url() + ") " +
88  "on " + current_date() + " at " + current_time()
89  ) << "\n";
90  if( Options::get().command_line_string() != "" ) {
91  out << svg_comment( "Program invocation: " + Options::get().command_line_string() ) << "\n";
92  }
93 
94  // Gradients and other definitions. Need to come before the content.
95  if( ! defs.empty() ) {
96  out << SvgDocument::indentation_string << "<defs>\n";
97  for( auto const& def : defs ) {
98  def.write( out, 2 );
99  }
100  out << SvgDocument::indentation_string << "</defs>\n";
101  }
102 
103  // Options to hand over to all elements. Currently not needed, because we do the shifting
104  // for the margin by using a group (see immediately below).
105  auto options = SvgDrawingOptions();
106  // options.offset_x = margin.top;
107  // options.offset_y = margin.top;
108  // options.offset_x = margin.left - bbox.top_left.x;
109  // options.offset_y = margin.top - bbox.top_left.y;
110 
111  // Main group for all elements. We use this to make the handling of the margin
112  // easier.
113  out << SvgDocument::indentation_string << "<g transform=\"translate( ";
114  out << margin.left - bbox.top_left.x << ", " << margin.top - bbox.top_left.y;
115  out << ")\" >\n";
116 
117  // Different approach, use inner svg element instead of group.
118  // Didn't work well with some viewers.
119  // out << SvgDocument::indentation_string << "<svg";
120  // out << svg_attribute( "x", margin.left - bbox.top_left.x );
121  // out << svg_attribute( "y", margin.top - bbox.top_left.y );
122  // out << ">\n";
123 
124  // Print content.
125  for( auto const& elem : content_ ) {
126  elem.write( out, 2, options );
127 
128  // Draw bounding boxes around all elements, for testing purposes.
129  // auto bb = elem.bounding_box();
130  // SvgRect( bb.top_left, bb.size(), SvgStroke(), SvgFill( Color(), 0.0 ) ).write( out, 1 );
131  }
132 
133  // Close main grouping.
134  // out << SvgDocument::indentation_string << "</svg>\n";
135  out << SvgDocument::indentation_string << "</g>\n";
136 
137  // Finish.
138  out << "</svg>\n";
139 }
140 
142 {
143  content_.push_back( object );
144  return *this;
145 }
146 
148 {
149  content_.push_back( std::move( object ));
150  return *this;
151 }
152 
154 {
155  return add( object );
156 }
157 
159 {
160  return add( std::move( object ));
161 }
162 
163 } // namespace utils
164 } // namespace genesis
static SvgBox combine(SvgBox const &lhs, SvgBox const &rhs)
std::string current_date()
Returns the current date as a string in the format "2014-12-31".
Definition: date_time.cpp:39
std::string genesis_url()
Return the URL of the genesis home page.
Definition: version.hpp:82
std::vector< SvgDefinitions > defs
std::string svg_attribute(std::string const &name, T const &value, std::string const &unit="")
std::string svg_comment(std::string const &content)
self_type & add(SvgObject const &object)
Add an SvgObject to the document.
std::string current_time()
Returns the current time as a string in the format "13:37:42".
Definition: date_time.cpp:51
void write(std::ostream &out) const
Write the SvgDocument to an output stream.
Provides some commonly used string utility functions.
SvgBox bounding_box() const
Provides functions for date and time access.
self_type & operator<<(SvgObject const &object)
Shortcut operator for add(), which allows an even more fluent interface.
static std::string indentation_string
static Options & get()
Returns a single instance of this class.
Definition: options.hpp:59
Some stuff that is totally not imporatant, but nice.
std::string genesis_version()
Return the current genesis version.
Definition: version.hpp:62