TreeSVG.h
1 /*
2 
3 MIT License
4 
5 Copyright (c) 2023 FMI Open Development / Markus Peura, first.last@fmi.fi
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13 
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 SOFTWARE.
24 
25 */
26 /*
27 Part of Rack development has been done in the BALTRAD projects part-financed
28 by the European Union (European Regional Development Fund and European
29 Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30 */
31 /*
32  * TreeSVG.h
33  *
34  * Created on: Jun 24, 2012
35  * Author: mpeura
36  */
37 
38 #ifndef DRAIN_TREE_SVG
39 #define DRAIN_TREE_SVG
40 
41 #include "drain/util/EnumFlags.h"
42 #include "drain/util/FileInfo.h"
43 #include "drain/util/Frame.h"
44 #include "drain/util/TreeXML.h"
45 #include "AlignSVG.h"
46 
47 namespace drain {
48 
49 namespace image {
50 
51 class NodeSVG;
52 
53 typedef drain::UnorderedMultiTree<NodeSVG,false, NodeXML<>::path_t> TreeSVG;
54 
55 struct svg {
56 
57  typedef float coord_t;
58 
59  enum tag_t {
60  UNDEFINED=XML::UNDEFINED,
61  COMMENT=XML::COMMENT,
62  CTEXT=XML::CTEXT,
63  SCRIPT=XML::SCRIPT,
64  STYLE=XML::STYLE,
65  STYLE_SELECT=XML::STYLE_SELECT,
66  SVG=10,
67  CIRCLE, DESC, GROUP, LINE, IMAGE, METADATA, POLYGON, RECT, TEXT, TITLE, TSPAN };
68  // check CTEXT, maybe implement in XML
69 
70 };
71 
72 } // image::
73 
74 
76 
77 
78 template <>
80 
81 DRAIN_ENUM_OSTREAM(image::svg::tag_t)
82 
83 
84 
85 namespace image {
86 
87 class BBoxSVG : public drain::Box<svg::coord_t> {
88 
89 public:
90 
91  inline
92  BBoxSVG(svg::coord_t x=0, svg::coord_t y=0, svg::coord_t width=0, svg::coord_t height=0) : drain::Box<svg::coord_t>(x, y, width, height) {
93  }
94 
95  inline
96  BBoxSVG(const BBoxSVG & bbox) : drain::Box<svg::coord_t>(bbox) {
97  }
98 
99  // Future option - also other units!
100  /*
101  bool x_PERCENTAGE = false;
102  bool y_PERCENTAGE = false;
103  bool width_PERCENTAGE = false;
104  bool height_PERCENTAGE = false;
105  */
106 };
107 
108 
109 template <size_t N>
110 class Transform : public UniTuple<double,N> {
111 
112 public:
113 
114  bool empty() const {
115  return (*this == 0.0);
116  }
117 
118  inline
119  void toStream(std::ostream & ostr) const {
120  ostr << '(';
122  ostr << ')';
123  }
124 
125 };
126 
127 
128 template <size_t N>
129 std::ostream & operator<<(std::ostream & ostr, Transform<N> & tr){
130  tr.toStream(ostr);
131  return ostr;
132 }
133 
134 
135 // Future option
137 
138 public:
139 
140  TransformSVG();
141 
142  inline
143  bool empty() const {
144  return (rotate.empty() && scale.empty() && translate.empty() && matrix.empty()) ;
145  }
146 
147  inline
148  void setTranslate(const svg::coord_t & x, const svg::coord_t & y){
149  // translate.ensureSize(2);
150  translate.set(x,y);
151  }
152 
153  inline
154  void setTranslateX(const svg::coord_t & x){
155  // translate.ensureSize(1);
156  // translate.set(x);
157  translate[0] = x;
158  }
159 
160  inline
161  void setTranslateY(const svg::coord_t & y){
162  // translate.ensureSize(2);
163  // svg::coord_t x = translate.get<svg::coord_t>(1);
164  translate[1] = y;
165  // translate.set(x, y);
166  }
167 
169 
171  Transform<2> scale;
172  Transform<2> translate;
173  Transform<6> matrix;
174 
175  /*
176  Variable rotate;
177  Variable scale;
178  Variable translate;
179  Variable matrix;
180  */
181 
182  // drain::Variable matrix;
183  // drain::Variable skewX;
184  // drain::Variable skewY;
185  void toStream(std::ostream & ostr) const;
186 
187 };
188 
189 //typedef drain::StyleSelectorXML<NodeSVG> SelectSVG;
191 
193 
199 // class NodeSVG: public svg, public NodeXML<svg::tag_t>, public AlignAdapterSVG {
200 class NodeSVG: public NodeXML<svg::tag_t>, public AlignAdapterSVG {
201 public:
202 
204  static
205  std::string xlink;
206 
208  static
209  std::string svg;
210 
211  static
212  const drain::FileInfo fileInfo;
213 
214 
216  NodeSVG(svg::tag_t t = svg::UNDEFINED);
217 
219  NodeSVG(const NodeSVG & node);
220 
221  inline virtual
222  ~NodeSVG(){};
223 
224  inline
225  bool isAbstract(){
226  return typeIs(
227  svg::tag_t::STYLE,
228  svg::tag_t::DESC,
229  svg::tag_t::METADATA,
230  svg::tag_t::SCRIPT,
231  svg::tag_t::TITLE,
232  svg::tag_t::TSPAN
233  );
234  }
235 
237  inline
238  NodeSVG & operator=(const NodeSVG & node){
239  XML::xmlAssignNode(*this, node);
240  /*
241  if (&node != this){
242  XML::xmlAssignNode(*this, node);
243  setType(n.getType()); // 2025
244  drain::SmartMapTools::setValues<map_t>((map_t &)*this, n);
245  }
246  */
247  return *this;
248  }
249 
251  inline
252  NodeSVG & operator=(const std::initializer_list<Variable::init_pair_t > &l){
253  set(l);
254  return *this;
255  }
256 
257  template <class T>
258  inline
259  NodeSVG & operator=(const T & arg){
260  set(arg);
261  //assign(arg);
262  return *this;
263  }
264 
265 
266 
268  virtual
269  void setAttribute(const std::string & key, const std::string &value) override;
270 
272  virtual
273  void setAttribute(const std::string & key, const char *value) override;
274 
275 
276 
278  inline
279  const BBoxSVG & getBoundingBox() const {
280  return box;
281  }
282  // Consider also with conversion: getBoundingBox(Box<T> &b)
283 
285  inline
287  return box;
288  }
289 
291  template <typename T>
292  inline
293  void setBoundingBox(const drain::Box<T> & b){
294  setLocation(b);
295  setFrame(b);
296  // setAttribute("data:bbox", StringBuilder<' '>(b.x, b.y, b.getWidth(), b.getHeight()));
297  }
298 
300  template <typename T>
301  inline
302  void setLocation(const drain::Point2D<T> & point){
303  box.x = point.x;
304  box.y = point.y;
305  }
306 
311  template <typename T>
312  inline
313  void setLocation(const T & x, const T & y){
314  box.setLocation(x, y);
315  }
316 
317  template <typename T>
318  inline
319  void setFrame(const drain::Frame2D<T> & frame){
320  box.width = frame.width;
321  box.height = frame.height;
322  }
323 
328  template <typename T>
329  inline
330  void setFrame(const T & w, const T & h){
331  box.setArea(w, h);
332  }
333 
334 
339  template <typename T>
340  inline
341  void setWidth(T w){
342  box.width = w;
343  }
344 
345  inline
346  svg::coord_t getWidth(){
347  return box.width;
348  }
349 
351 
354  template <typename T>
355  inline
356  void setMargin(T w){
357  link("data-margin", box.width);
358  box.width = w;
359  }
360 
362 
365  inline
366  svg::coord_t getMargin(){
367  return box.width;
368  }
369 
370 
375  template <typename T>
376  inline
377  void setHeight(T h){
378  if (typeIs(svg::TEXT)){
379  link("data-height", box.height);
380  }
381  box.height = h;
382  }
383 
384  inline
385  svg::coord_t getHeight(){
386  return box.height;
387  }
388 
390  void setFontSize(svg::coord_t size, svg::coord_t elemHeight = 0.0);
391 
392  TransformSVG transform;
393 
395 
401  virtual
402  void specificAttributesToStream(std::ostream & ostr) const override;
403 
404 protected:
405 
406 
408 
411  virtual
412  void handleType(const svg::tag_t & t) override final;
413 
414  virtual
415  void updateAlign() override;
416 
417  //drain::Box<coord_t> box;
418  BBoxSVG box;
419  // consider:
420  // bool x_PERCENTAGE = false;
421  // bool y_PERCENTAGE = false;
422  // svg:
423 
424  int radius = 0;
425 
426 };
427 
428 
429 /*
430 template <typename P, typename A,typename V>
431 void NodeSVG::setAlign(const P & pos, const A & axis, const V &value){
432  alignments[p][a] = v;
433 }
434 */
435 
436 } // image::
437 
438 inline
439 std::ostream & operator<<(std::ostream &ostr, const image::NodeSVG & node){
440  return node.nodeToStream(ostr);
441 }
442 
443 
444 } // drain::
445 
446 
447 inline
448 std::ostream & operator<<(std::ostream &ostr, const drain::image::TreeSVG & tree){
449  //return drain::NodeXML<const drain::image::NodeSVG>::docToStream(ostr, tree);
450  return drain::image::NodeSVG::docToStream(ostr, tree);
451  //return drain::image::TreeSVG::node_data_t::docToStream(ostr, tree);
452 }
453 
454 
455 
456 namespace drain {
457 
458 DRAIN_TYPENAME(image::NodeSVG);
459 DRAIN_TYPENAME(image::svg::tag_t);
460 
461 
462 template <>
463 const NodeXML<image::svg::tag_t>::xml_default_elem_map_t NodeXML<image::svg::tag_t>::xml_default_elems;
464 
465 /*
466 template <>
467 template <typename K, typename V>
468 image::TreeSVG & image::TreeSVG::operator=(std::initializer_list<std::pair<K,V> > args){
469  drain::Logger mout(__FILE__, __FUNCTION__);
470  mout.attention("initlist pair<K,V>: ", args);
471  data.set(args); // what about TreeSVG & arg
472  return *this;
473 }
474 */
475 
476 /*
477 template <> // referring to Tree<NodeSVG>
478 image::TreeSVG & image::TreeSVG::operator=(std::initializer_list<std::pair<const char *,const char *> > l);
479 */
480 
481 template <> // referring to Tree<NodeSVG>
482 inline
483 image::TreeSVG & image::TreeSVG::operator=(std::initializer_list<std::pair<const char *,const Variable> > l){
484 //image::TreeSVG & image::TreeSVG::operator=(std::initializer_list<std::pair<const char *,const char *> > l){
485  return XML::xmlAssign(*this, l);
486 }
487 
488 
489 template <>
490 template <class T>
491 image::TreeSVG & image::TreeSVG::operator=(const T & arg){
492  return XML::xmlAssign(*this, arg);
493  /*
494  data.set(arg); // what about TreeSVG & arg
495  return *this;
496  */
497 }
498 
499 // Important! Useful and widely used – but fails with older C++ compilers ?
500 template <>
501 template <>
502 inline
503 image::TreeSVG & image::TreeSVG::operator()(const image::svg::tag_t & type){
504  return XML::xmlSetType(*this, type);
505 }
506 
507 template <>
508 inline
509 image::TreeSVG & image::TreeSVG::addChild(const image::TreeSVG::key_t & key){
510  return XML::xmlAddChild(*this, key);
511 }
512 
513 /*
514 template <>
515 template <class K>
516 const image::TreeSVG::key_t & image::TreeSVG::getKey(const K & key){
517  return EnumDict<K>::dict.getKey(key, false);
518 }
519 */
520 
521 /* tested 2025/01/20 but caused problems with Hi5Tree("dataset2") etc.
522 template <>
523 template <typename K> // for K (path elem arg)
524 const image::TreeSVG::key_t & image::TreeSVG::getKey(const K & key){
525  return EnumDict<K>::dict.getKey(key, false);
526 }
527 
528 template <>
529 template <> // for K (path elem arg)
530 inline
531 const image::TreeSVG::key_t & image::TreeSVG::getKey(const drain::StyleSelectorXML<image::NodeSVG> & selector){
532  return selector;
533 }
534 
535 */
536 
537 template <> // for T (Tree class)
538 template <> // for K (path elem arg)
539 bool image::TreeSVG::hasChild(const image::svg::tag_t & type) const;
540 
541 
542 template <> // for T (Tree class)
543 template <> // for K (path elem arg)
544 image::TreeSVG & image::TreeSVG::operator[](const image::svg::tag_t & type);
545 
546 template <> // for T (Tree class)
547 template <> // for K (path elem arg)
548 const image::TreeSVG & image::TreeSVG::operator[](const image::svg::tag_t & type) const ;
549 
550 } // drain::
551 
552 #endif // DRAIN_TREE_SVG
553 
Two-way mapping between strings and objects of template class T.
Definition: Dictionary.h:63
Definition: FileInfo.h:48
Something that has width and height.
Definition: Frame.h:53
Definition: TreeXML.h:341
static std::ostream & docToStream(std::ostream &ostr, const V &tree)
Definition: TreeXML.h:733
ref_t & link(const std::string &key, F &x)
Associates a map entry with a variable.
Definition: ReferenceMap.h:84
Definition: TreeXML.h:777
virtual std::ostream & toStream(std::ostream &ostr, char separator=',') const
Definition: TupleBase.h:331
Tuple of N elements of type T.
Definition: UniTuple.h:65
static X & xmlAssignNode(X &dst, const X &src)
Assign another tree structure to another.
Definition: XML.h:497
static TX & xmlSetType(TX &tree, const typename TX::node_data_t::xml_tag_t &type)
Definition: XML.h:559
static T & xmlAddChild(T &tree, const std::string &key)
Definition: XML.h:573
static TX & xmlAssign(TX &dst, const TX &src)
Assign another tree structure to another.
Definition: XML.h:458
Definition: TreeSVG.h:87
Definition: TreeSVG.h:200
virtual void handleType(const svg::tag_t &t) override final
Definition: TreeSVG.cpp:206
void setBoundingBox(const drain::Box< T > &b)
Set position (x,y), width and height of an object.
Definition: TreeSVG.h:293
BBoxSVG & getBoundingBox()
Get position (x,y), width and height of an object.
Definition: TreeSVG.h:286
void setLocation(const T &x, const T &y)
Definition: TreeSVG.h:313
virtual void setAttribute(const std::string &key, const std::string &value) override
Set attribute value, handling units in string arguments, like in "50%" or "640px".
Definition: TreeSVG.cpp:303
static std::string xlink
In opening SVG tag, referred to by attribute "xmlns:xlink".
Definition: TreeSVG.h:205
NodeSVG(svg::tag_t t=svg::UNDEFINED)
Default constructor. Create a node of given type.
Definition: TreeSVG.cpp:181
void setMargin(T w)
Set margin of a TEXT element (non-standard).
Definition: TreeSVG.h:356
void setWidth(T w)
Definition: TreeSVG.h:341
NodeSVG & operator=(const NodeSVG &node)
Copy data from a node. (Does not copy subtree.)
Definition: TreeSVG.h:238
virtual void specificAttributesToStream(std::ostream &ostr) const override
Write transform, in addition to XML::ClassList.
Definition: TreeSVG.cpp:373
const BBoxSVG & getBoundingBox() const
Get position (x,y), width and height of an object.
Definition: TreeSVG.h:279
svg::coord_t getMargin()
Get margin of a TEXT element (non-standard).
Definition: TreeSVG.h:366
void setFontSize(svg::coord_t size, svg::coord_t elemHeight=0.0)
Sets font size and also text elem "height".
Definition: TreeSVG.cpp:312
void setHeight(T h)
Definition: TreeSVG.h:377
NodeSVG & operator=(const std::initializer_list< Variable::init_pair_t > &l)
Copy data from a node. (Does not copy subtree.)
Definition: TreeSVG.h:252
void setLocation(const drain::Point2D< T > &point)
Set position (x,y) of an object.
Definition: TreeSVG.h:302
void setFrame(const T &w, const T &h)
Definition: TreeSVG.h:330
static std::string svg
In opening SVG tag, referred to by attributes "xmlns" and "xmlns:svg".
Definition: TreeSVG.h:209
Definition: TreeSVG.h:136
Transform< 3 > rotate
Angle (deg), [x,y].
Definition: TreeSVG.h:170
Definition: TreeSVG.h:110
Definition: DataSelector.cpp:1277
Something that has coordinates (x,y) and dimensions (width, height).
Definition: Frame.h:160
Wrapper for unique (static) dictionary of enum values.
Definition: EnumFlags.h:66
Definition: Point.h:48
Adapter designed for NodeSVG.
Definition: AlignSVG.h:787
Definition: TreeSVG.h:55