Loading...
Searching...
No Matches
TreeSVG.h
1/*
2
3MIT License
4
5Copyright (c) 2023 FMI Open Development / Markus Peura, first.last@fmi.fi
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26/*
27Part of Rack development has been done in the BALTRAD projects part-financed
28by the European Union (European Regional Development Fund and European
29Neighbourhood 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/image/AlignAnchorSVG.h>
42#include <drain/util/EnumUtils.h>
43#include "drain/util/FileInfo.h"
44#include "drain/util/Frame.h"
45#include "drain/util/SelectorXML.h"
46#include "drain/util/TreeXML.h"
47#include "drain/util/UtilsXML.h"
48#include "TransformSVG.h"
49
50namespace drain {
51
52namespace image {
53
54/*
55class NodeSVG;
56
57typedef drain::UnorderedMultiTree<NodeSVG,false, NodeXML<>::path_t> TreeSVG;
58//typedef NodeXML<NodeSVG>::xml_tree_t TreeSVG;
59*/
60
61class FileSVG {
62
63public:
64
65 static
66 const drain::FileInfo fileInfo;
67
68 enum PathPolicy {
69 ABSOLUTE = 1, // Else is relative, stripped away using inputPrefix?
70 PREFIXED = 2, // file:// is appended
71 };
72
73 // Rename IncludePolicy ?
74 enum IncludePolicy {
75 NONE = 0,
76 PNG = 1, // Main title in SVG image
77 SVG = 2,
78 TXT = 4,
79 SKIP = 16,
80 NEXT = 32,
81 ON = 64,
82 OFF = 128,
83 ALL = ON|(PNG|SVG|TXT),
84 UNKNOWN = 255,
85 // --- unused ? ---
86 // TITLE, // Default title
87 };
88
89};
90
91}
92
93DRAIN_ENUM_DICT(image::FileSVG::IncludePolicy);
94DRAIN_ENUM_OSTREAM(image::FileSVG::IncludePolicy);
95
96DRAIN_ENUM_DICT(image::FileSVG::PathPolicy);
97DRAIN_ENUM_OSTREAM(image::FileSVG::PathPolicy);
98
99namespace image {
100
101struct svg {
102
103 typedef float coord_t;
104
105 enum tag_t {
106 UNDEFINED=XML::UNDEFINED,
107 COMMENT=XML::COMMENT,
108 CTEXT=XML::CTEXT,
109 SCRIPT=XML::SCRIPT,
110 STYLE=XML::STYLE,
111 STYLE_SELECT=XML::STYLE_SELECT,
112 SVG=10,
113 CIRCLE, CLIP_PATH, DEFS, DESC, GROUP, IMAGE, LINE, LINEAR_GRADIENT, MASK, METADATA, PATH, POLYGON, RECT, TEXT, TITLE, TSPAN };
114 // check CTEXT, maybe implement in XML
115
116};
117
118class NodeSVG;
119
120// typedef drain::UnorderedMultiTree<NodeSVG,false, NodeXML<svg::tag_t>::path_t> TreeSVG;
121typedef drain::UnorderedMultiTree<NodeSVG,false, NodeXML<>::path_t> TreeSVG;
122
123
124} // image::
125
126
127// const drain::EnumDict<image::svg::tag_t>::dict_t & getDict();
128
129
130// template <>
131// const EnumDict<image::svg::tag_t>::dict_t EnumDict<image::svg::tag_t>::dict;
132DRAIN_ENUM_DICT(image::svg::tag_t);
133
134DRAIN_ENUM_OSTREAM(image::svg::tag_t)
135
136
137
138namespace image {
139
140class BBoxSVG : public drain::Box<svg::coord_t> {
141
142public:
143
144 inline
145 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) {
146 }
147
148 inline
149 BBoxSVG(const BBoxSVG & bbox) : drain::Box<svg::coord_t>(bbox) {
150 }
151
152
153 // New
154
155
156
157 // Future option - also other units!
158 /*
159 bool x_PERCENTAGE = false;
160 bool y_PERCENTAGE = false;
161 bool width_PERCENTAGE = false;
162 bool height_PERCENTAGE = false;
163 */
164};
165
166
167//typedef drain::StyleSelectorXML<NodeSVG> SelectSVG;
168// typedef drain::SelectorXML SelectSVG;
169
171
177// class NodeSVG: public svg, public NodeXML<svg::tag_t>, public AlignAnchorSVG {
178class NodeSVG: public NodeXML<svg::tag_t>, public AlignSVG, public AlignAnchorSVG {
179public:
180
182 static
183 std::string xlink;
184
186 static
187 std::string svg;
188
189 /* -> FileSVG
190 static
191 const drain::FileInfo fileInfo;
192 */
193
195 NodeSVG(svg::tag_t t = svg::UNDEFINED);
196
198 NodeSVG(const NodeSVG & node);
199
200 inline virtual
201 ~NodeSVG(){};
202
203 inline
204 bool isAbstract() const {
205 return typeIs(
206 svg::tag_t::UNDEFINED,
207 svg::tag_t::STYLE,
208 svg::tag_t::CLIP_PATH, // Semi-abstract..
209 svg::tag_t::DESC,
210 svg::tag_t::DEFS,
211 svg::tag_t::METADATA,
212 svg::tag_t::SCRIPT,
213 svg::tag_t::TITLE,
214 svg::tag_t::TSPAN
215 );
216 }
217
219 virtual inline
220 bool isSingular() const override final {
221 return false;
222 }
223
224
226 inline
227 NodeSVG & operator=(const NodeSVG & node){
228 if (!typeIsSet()){
229 setType(node.getType());
230 handleType();
231 //handleType(node.getNativeType());
232 }
233 XML::xmlAssignNode(*this, node);
234 return *this;
235 }
236
238 inline
239 NodeSVG & operator=(const std::initializer_list<Variable::init_pair_t > &l){
240 set(l);
241 return *this;
242 }
243
244 template <class T>
245 inline
246 NodeSVG & operator=(const T & arg){
247 set(arg);
248 //assign(arg);
249 return *this;
250 }
251
252 inline
253 NodeSVG & operator=(xml_tag_t type){
254 setType(type);
255 return *this;
256 }
257
258 // Dangerous, if XML has codes not registered by SVG?
259 /*
260 inline
261 NodeSVG & operator=(xml_tag_t type){
262 setType(type);
263 return *this;
264 }
265 */
266
267
268 /* Well, every graphic obj may have DESC and TITLE?
269 virtual
270 bool isSingular() const override final;
271 */
272
274 virtual
275 void setAttribute(const std::string & key, const std::string &value) override;
276
278 virtual
279 void setAttribute(const std::string & key, const char *value) override;
280
281
282
284 inline
285 const BBoxSVG & getBoundingBox() const {
286 return box;
287 }
288 // Consider also with conversion: getBoundingBox(Box<T> &b)
289
291 inline
293 return box;
294 }
295
297 template <typename T>
298 inline
300 setLocation(b);
301 setFrame(b);
302 // setAttribute("data:bbox", StringBuilder<' '>(b.x, b.y, b.getWidth(), b.getHeight()));
303 }
304
305 template <typename T>
306 inline
307 void setViewBox(const drain::Box<T> & bb){
308 setViewBox(bb.x, bb.y, bb.width, bb.height);
309 //set("viewBox", drain::StringBuilder<' '>(bb.x, bb.y, bb.width, bb.height));
310 // setAttribute("data:bbox", StringBuilder<' '>(b.x, b.y, b.getWidth(), b.getHeight()));
311 }
312
313 template <typename T>
314 inline
315 void setViewBox(T & x, T & y, T & width, T & height){
316 set("viewBox", drain::StringBuilder<' '>(x, y, width, height).str());
317 }
318
320 template <typename T>
321 inline
322 void setLocation(const drain::Point2D<T> & point){
323 box.x = point.x;
324 box.y = point.y;
325 }
326
331 template <typename T>
332 inline
333 void setLocation(const T & x, const T & y){
334 box.setLocation(x, y);
335 }
336
337 template <typename T>
338 inline
339 void setFrame(const drain::Frame2D<T> & frame){
340 box.width = frame.width;
341 box.height = frame.height;
342 }
343
348 template <typename T>
349 inline
350 void setFrame(const T & w, const T & h){
351 box.setArea(w, h);
352 }
353
354
359 template <typename T>
360 inline
361 void setWidth(T w){
362 box.width = w;
363 }
364
365 inline
366 svg::coord_t getWidth(){
367 return box.width;
368 }
369
371
374 template <typename T>
375 inline
376 void setMargin(T w){
377 link("data-margin", box.width);
378 box.width = w;
379 }
380
382
385 inline
386 svg::coord_t getMargin(){
387 return box.width;
388 }
389
390
395 template <typename T>
396 inline
397 void setHeight(T h){
398 if (typeIs(svg::TEXT)){
399 link("data-height", box.height);
400 }
401 box.height = h;
402 }
403
404 inline
405 svg::coord_t getHeight(){
406 return box.height;
407 }
408
410 void setFontSize(svg::coord_t size, svg::coord_t elemHeight = 0.0);
411
412 TransformSVG transform;
413
415
421 virtual
422 void specificAttributesToStream(std::ostream & ostr) const override;
423
424
425 void swapSVG(NodeSVG & node);
426
427protected:
428
429 virtual
430 void handleType() override final;
431
432
433 virtual
434 void updateAlign() override;
435
436 //drain::Box<coord_t> box;
437 BBoxSVG box;
438 // consider:
439 // bool x_PERCENTAGE = false;
440 // bool y_PERCENTAGE = false;
441 // svg:
442
443 // int radius = 0;
444
445};
446
447
448/*
449template <typename P, typename A,typename V>
450void NodeSVG::setAlign(const P & pos, const A & axis, const V &value){
451 alignments[p][a] = v;
452}
453*/
454
455
456// Utility (move to utils?)
458
459public:
460
461 inline
462 NodePrinter(const NodeSVG & node){
463 std::stringstream sstr;
464 sstr << "<" << node.getTag();
465 if (::atoi(node.getId().c_str())==0){
466 sstr << " id=" << node.getId();
467 }
468 if (node.getName().isValid()){
469 sstr << " name=" << node.getName();
470 }
471 if (!node.getClasses().empty()){
472 sstr << " class=[" << node.getClasses() << ']';
473 }
474 sstr << '>';
475 id = sstr.str();
476 }
477
478 const std::string & str() const {
479 return id;
480 }
481
482
483protected:
484
485 std::string id;
486
487};
488
489
490//typedef NodeSVG::xml_tree_t TreeSVG;
491
492
493} // image::
494
495
496/*
497inline
498std::ostream & operator<<(std::ostream &ostr, const image::NodeSVG & node){
499 return node.nodeToStream(ostr);
500}
501*/
502
503
504
505} // drain::
506
507
508inline
509std::ostream & operator<<(std::ostream &ostr, const drain::image::NodeSVG & node){
510 return node.nodeToStream(ostr);
511}
512
513
514
515inline
516std::ostream & operator<<(std::ostream &ostr, const drain::image::TreeSVG & tree){
517 return drain::image::NodeSVG::docToStream(ostr, tree);
518}
519
520
521
522namespace drain {
523
524DRAIN_TYPENAME(image::NodeSVG);
525DRAIN_TYPENAME(image::svg::tag_t);
526
527
528
529/*
530template <>
531template <typename K, typename V>
532image::TreeSVG & image::TreeSVG::operator=(std::initializer_list<std::pair<K,V> > args){
533 drain::Logger mout(__FILE__, __FUNCTION__);
534 mout.attention("initlist pair<K,V>: ", args);
535 data.set(args); // what about TreeSVG & arg
536 return *this;
537}
538*/
539
540
541template <> // referring to Tree<NodeSVG>
542template <> // referring to tparam T
543inline
544image::TreeSVG & image::TreeSVG::operator=(const std::string & arg){
545 UtilsXML::assignString(*this, arg);
546 return *this;
547}
548
549
550template <> // referring to Tree<NodeSVG>
551inline
552image::TreeSVG & image::TreeSVG::operator=(std::initializer_list<std::pair<const char *,const Variable> > l){
553 return UtilsXML::assign(*this, l);
554}
555
556
557template <>
558template <class T>
559image::TreeSVG & image::TreeSVG::operator=(const T & arg){
560 return UtilsXML::assign(*this, arg);
561}
562
564
571template <> // for T - Tree class
572template <> // for K - operator() argument
573image::TreeSVG & image::TreeSVG::operator()(const image::svg::tag_t & type);
574
575
576template <> // for T (Tree class)
577template <> // for K (path elem arg)
578bool image::TreeSVG::hasChild(const image::svg::tag_t & type) const;
579
581template <> // for T (Tree class)
582template <> // for K (path elem arg)
583image::TreeSVG & image::TreeSVG::operator[](const image::svg::tag_t & type);
584
585
586
588template <> // for T (Tree class)
589template <> // for K (path elem arg)
590const image::TreeSVG & image::TreeSVG::operator[](const image::svg::tag_t & type) const ;
591
592
593template <> // for T (Tree class)
594template <> // for K (path elem arg)
595bool image::TreeSVG::hasChild(const ClassXML & cls) const;
596
597template <> // for T (Tree class)
598template <> // for K (path elem arg)
599image::TreeSVG & image::TreeSVG::operator[](const ClassXML & cls);
600
602template <> // for T (Tree class)
603template <> // for K (path elem arg)
604const image::TreeSVG & image::TreeSVG::operator[](const ClassXML & cls) const ;
605
606
607/*
608template <>
609inline
610image::TreeSVG & image::TreeSVG::addChild(){
611 return UtilsXML::addChild(*this);
612}
613*/
614
615
616
617template <>
618const NodeXML<image::svg::tag_t>::xml_default_elem_map_t NodeXML<image::svg::tag_t>::xml_default_elems;
619
621
624template <>
625inline
626void image::TreeSVG::initChild(image::TreeSVG & child) const {
627 UtilsXML::initChildWithDefaultType(*this, child);
628 /*
629 const typename image::svg::tag_t type = UtilsXML::retrieveDefaultType(this->data);
630 if (type){
631 child->setType(type);
632 }
633 */
634}
635
636
637
638/*
639template <>
640template <class K>
641const image::TreeSVG::key_t & image::TreeSVG::getKey(const K & key){
642 return EnumDict<K>::dict.getKey(key, false);
643}
644*/
645
646/* tested 2025/01/20 but caused problems with Hi5Tree("dataset2") etc.
647template <>
648template <typename K> // for K (path elem arg)
649const image::TreeSVG::key_t & image::TreeSVG::getKey(const K & key){
650 return EnumDict<K>::dict.getKey(key, false);
651}
652
653template <>
654template <> // for K (path elem arg)
655inline
656const image::TreeSVG::key_t & image::TreeSVG::getKey(const drain::StyleSelectorXML<image::NodeSVG> & selector){
657 return selector;
658}
659
660*/
661
662} // drain::
663
664#endif // DRAIN_TREE_SVG
665
Definition FileInfo.h:48
Something that has width and height.
Definition Frame.h:55
Definition TreeXML.h:341
virtual std::ostream & nodeToStream(std::ostream &ostr, tag_display_mode mode=EMPTY_TAG) const override
Dumps info. Future option: outputs leading and ending tag.
Definition TreeXML.h:414
static std::ostream & docToStream(std::ostream &ostr, const V &tree)
Definition TreeXML.h:733
std::map< xml_tag_t, xml_tag_t > xml_default_elem_map_t
Helps creating child elements. Like children of HTML element UL should be LI.
Definition TreeXML.h:348
ref_t & link(const std::string &key, F &x)
Associates a map entry with a variable.
Definition ReferenceMap.h:84
Definition StringBuilder.h:58
static T & assign(T &dst, const T &src)
Assign another tree structure to another.
Definition UtilsXML.h:57
static TX & assignString(TX &tree, const std::string &s)
When assigning a string, create new element unless the element itself is of type CTEXT.
Definition UtilsXML.h:131
bool typeIsSet() const
Return true, if type is any of the arguments.
Definition XML.h:148
const std::string & getId() const
Returns ID of this element. Hopefully a unique ID...
Definition TreeXML.h:142
static N & xmlAssignNode(N &dst, const N &src)
Assign tree node (data) to another.
Definition XML.h:623
std::string id
Some general-purpose.
Definition TreeXML.h:95
Definition TreeSVG.h:140
Definition TreeSVG.h:61
Definition TreeSVG.h:457
Definition TreeSVG.h:178
void setBoundingBox(const drain::Box< T > &b)
Set position (x,y), width and height of an object.
Definition TreeSVG.h:299
void setLocation(const T &x, const T &y)
Definition TreeSVG.h:333
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:220
const BBoxSVG & getBoundingBox() const
Get position (x,y), width and height of an object.
Definition TreeSVG.h:285
NodeSVG & operator=(const NodeSVG &node)
Copy data from a node. (Does not copy subtree.)
Definition TreeSVG.h:227
static std::string xlink
In opening SVG tag, referred to by attribute "xmlns:xlink".
Definition TreeSVG.h:183
void setMargin(T w)
Set margin of a TEXT element (non-standard).
Definition TreeSVG.h:376
void setWidth(T w)
Definition TreeSVG.h:361
NodeSVG & operator=(const std::initializer_list< Variable::init_pair_t > &l)
Copy data from a node. (Does not copy subtree.)
Definition TreeSVG.h:239
virtual void specificAttributesToStream(std::ostream &ostr) const override
Write transform, in addition to XML::ClassList.
Definition TreeSVG.cpp:323
svg::coord_t getMargin()
Get margin of a TEXT element (non-standard).
Definition TreeSVG.h:386
void setFontSize(svg::coord_t size, svg::coord_t elemHeight=0.0)
Sets font size and also text elem "height".
Definition TreeSVG.cpp:229
void setHeight(T h)
Definition TreeSVG.h:397
virtual bool isSingular() const override final
If true, render always as single elem (without child elems)
Definition TreeSVG.h:220
void setLocation(const drain::Point2D< T > &point)
Set position (x,y) of an object.
Definition TreeSVG.h:322
BBoxSVG & getBoundingBox()
Get position (x,y), width and height of an object.
Definition TreeSVG.h:292
void setFrame(const T &w, const T &h)
Definition TreeSVG.h:350
static std::string svg
In opening SVG tag, referred to by attributes "xmlns" and "xmlns:svg".
Definition TreeSVG.h:187
Definition TransformSVG.h:90
Definition DataSelector.cpp:1277
DRAIN_TYPENAME(void)
Add a specialization for each type of those you want to support.
Something that has coordinates (x,y) and dimensions (width, height).
Definition Frame.h:221
Definition Point.h:48
Adapter designed for NodeSVG.
Definition AlignAnchorSVG.h:154
User-friendly programming interface for alignment considering two elements.
Definition AlignSVG.h:219
Definition TreeSVG.h:101