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/Enum.h>
42#include <drain/image/AlignAnchorSVG.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 static
90 int radialBezierResolution;
91
92};
93
94}
95
96DRAIN_ENUM_DICT(image::FileSVG::IncludePolicy);
97DRAIN_ENUM_OSTREAM(image::FileSVG::IncludePolicy);
98
99DRAIN_ENUM_DICT(image::FileSVG::PathPolicy);
100DRAIN_ENUM_OSTREAM(image::FileSVG::PathPolicy);
101
102namespace image {
103
104struct svg {
105
106 typedef float coord_t;
107
108 enum tag_t {
109 UNDEFINED=XML::UNDEFINED,
110 COMMENT=XML::COMMENT,
111 CTEXT=XML::CTEXT,
112 SCRIPT=XML::SCRIPT,
113 STYLE=XML::STYLE,
114 STYLE_SELECT=XML::STYLE_SELECT,
115 JAVASCRIPT_SCOPE=XML::JAVASCRIPT_SCOPE,
116 SVG=10,
117 CIRCLE, CLIP_PATH, DEFS, DESC, GROUP, IMAGE, LINE, LINEAR_GRADIENT, MASK, METADATA, PATH, POLYGON, RECT, TEXT, TITLE, TSPAN };
118 // check CTEXT, maybe implement in XML
119
120};
121
122class NodeSVG;
123
124// typedef drain::UnorderedMultiTree<NodeSVG,false, NodeXML<svg::tag_t>::path_t> TreeSVG;
125typedef drain::UnorderedMultiTree<NodeSVG,false, NodeXML<>::path_t> TreeSVG;
126
127
128} // image::
129
130
131// const drain::Enum<image::svg::tag_t>::dict_t & getDict();
132
133
134// template <>
135// const Enum<image::svg::tag_t>::dict_t Enum<image::svg::tag_t>::dict;
136DRAIN_ENUM_DICT(image::svg::tag_t);
137
138DRAIN_ENUM_OSTREAM(image::svg::tag_t)
139
140
141
142namespace image {
143
144class BBoxSVG : public drain::Box<svg::coord_t> {
145
146public:
147
148 inline
149 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) {
150 }
151
152 inline
153 BBoxSVG(const BBoxSVG & bbox) : drain::Box<svg::coord_t>(bbox) {
154 }
155
156
157 // New
158
159
160
161 // Future option - also other units!
162 /*
163 bool x_PERCENTAGE = false;
164 bool y_PERCENTAGE = false;
165 bool width_PERCENTAGE = false;
166 bool height_PERCENTAGE = false;
167 */
168};
169
170
171//typedef drain::StyleSelectorXML<NodeSVG> SelectSVG;
172// typedef drain::SelectorXML SelectSVG;
173
175
181// class NodeSVG: public svg, public NodeXML<svg::tag_t>, public AlignAnchorSVG {
182class NodeSVG: public NodeXML<svg::tag_t>, public AlignSVG, public AlignAnchorSVG {
183public:
184
185 typedef svg::tag_t tag_t; // DRAIN_XML_... macros expect (NodeXML)::tag_t
186
188 static
189 std::string xlink;
190
192 static
193 std::string svg_decl;
194
195 /* -> FileSVG
196 static
197 const drain::FileInfo fileInfo;
198 */
199
201 NodeSVG(svg::tag_t t = svg::UNDEFINED);
202
204 NodeSVG(const NodeSVG & node);
205
206 inline virtual
207 ~NodeSVG(){};
208
209 inline
210 bool isAbstract() const {
211 return typeIs(
212 svg::tag_t::UNDEFINED,
213 svg::tag_t::STYLE,
214 svg::tag_t::CLIP_PATH, // Semi-abstract..
215 svg::tag_t::DESC,
216 svg::tag_t::DEFS,
217 svg::tag_t::METADATA,
218 svg::tag_t::SCRIPT,
219 svg::tag_t::TITLE,
220 svg::tag_t::TSPAN
221 );
222 }
223
225 virtual inline
226 bool isSingular() const override final {
227 return false;
228 }
229
230
232 inline
233 NodeSVG & operator=(const NodeSVG & node){
234 if (!typeIsSet()){
235 setType(node.getType());
236 handleType();
237 //handleType(node.getNativeType());
238 }
239 XML::xmlAssignNode(*this, node);
240 return *this;
241 }
242
244 inline
245 NodeSVG & operator=(const std::initializer_list<Variable::init_pair_t > &l){
246 set(l);
247 return *this;
248 }
249
250 template <class T>
251 inline
252 NodeSVG & operator=(const T & arg){
253 set(arg);
254 //assign(arg);
255 return *this;
256 }
257
258 inline
259 NodeSVG & operator=(xml_tag_t type){
260 setType(type);
261 return *this;
262 }
263
264 // Dangerous, if XML has codes not registered by SVG?
265 /*
266 inline
267 NodeSVG & operator=(xml_tag_t type){
268 setType(type);
269 return *this;
270 }
271 */
272
273
274 /* Well, every graphic obj may have DESC and TITLE?
275 virtual
276 bool isSingular() const override final;
277 */
278
280 virtual
281 void setAttribute(const std::string & key, const std::string &value) override;
282
284 virtual
285 void setAttribute(const std::string & key, const char *value) override;
286
287
288
290 inline
291 const BBoxSVG & getBoundingBox() const {
292 return box;
293 }
294 // Consider also with conversion: getBoundingBox(Box<T> &b)
295
297 inline
299 return box;
300 }
301
303 template <typename T>
304 inline
306 setLocation(b);
307 setFrame(b);
308 // setAttribute("data:bbox", StringBuilder<' '>(b.x, b.y, b.getWidth(), b.getHeight()));
309 }
310
311 template <typename T>
312 inline
313 void setViewBox(const drain::Box<T> & bb){
314 setViewBox(bb.x, bb.y, bb.width, bb.height);
315 //set("viewBox", drain::StringBuilder<' '>(bb.x, bb.y, bb.width, bb.height));
316 // setAttribute("data:bbox", StringBuilder<' '>(b.x, b.y, b.getWidth(), b.getHeight()));
317 }
318
319 template <typename T>
320 inline
321 void setViewBox(T & x, T & y, T & width, T & height){
322 set("viewBox", drain::StringBuilder<' '>(x, y, width, height).str());
323 }
324
326 template <typename T>
327 inline
328 void setLocation(const drain::Point2D<T> & point){
329 box.x = point.x;
330 box.y = point.y;
331 }
332
337 template <typename T>
338 inline
339 void setLocation(const T & x, const T & y){
340 box.setLocation(x, y);
341 }
342
343 template <typename T>
344 inline
345 void setFrame(const drain::Frame2D<T> & frame){
346 box.width = frame.width;
347 box.height = frame.height;
348 }
349
354 template <typename T>
355 inline
356 void setFrame(const T & w, const T & h){
357 box.setArea(w, h);
358 }
359
360
365 template <typename T>
366 inline
367 void setWidth(T w){
368 box.width = w;
369 }
370
371 inline
372 svg::coord_t getWidth(){
373 return box.width;
374 }
375
377
380 template <typename T>
381 inline
382 void setMargin(T w){
383 getMap()["data-margin"].link(box.width = w);
384 // link("data-margin", box.width);
385 box.width = w;
386 }
387
389
392 inline
393 svg::coord_t getMargin(){
394 return box.width;
395 }
396
397
402 template <typename T>
403 inline
404 void setHeight(T h){
405 if (typeIs(svg::TEXT)){
406 //link("data-height", box.height);
407 getMap()["data-height"].link(box.height = h);
408 }
409 box.height = h;
410 }
411
412 inline
413 svg::coord_t getHeight(){
414 return box.height;
415 }
416
418 void setFontSize(svg::coord_t size, svg::coord_t elemHeight = 0.0);
419
420 TransformSVG transform;
421
423
429 virtual
430 void specificAttributesToStream(std::ostream & ostr) const override;
431
432
433 void swapSVG(NodeSVG & node);
434
435protected:
436
437 virtual
438 void handleType() override final;
439
440
441 virtual
442 void updateAlign() override;
443
444 //drain::Box<coord_t> box;
445 BBoxSVG box;
446 // consider:
447 // bool x_PERCENTAGE = false;
448 // bool y_PERCENTAGE = false;
449 // svg:
450
451 // int radius = 0;
452
453};
454
455
456/*
457template <typename P, typename A,typename V>
458void NodeSVG::setAlign(const P & pos, const A & axis, const V &value){
459 alignments[p][a] = v;
460}
461*/
462
463
464// Utility (move to utils?)
466
467public:
468
469 inline
470 NodePrinter(const NodeSVG & node){
471 std::stringstream sstr;
472 sstr << "<" << node.getTag();
473 if (::atoi(node.getId().c_str())==0){
474 sstr << " id=" << node.getId();
475 }
476 if (node.getName().isValid()){
477 sstr << " name=" << node.getName();
478 }
479 if (!node.getClasses().empty()){
480 sstr << " class=[" << node.getClasses() << ']';
481 }
482 sstr << '>';
483 id = sstr.str();
484 }
485
486 const std::string & str() const {
487 return id;
488 }
489
490
491protected:
492
493 std::string id;
494
495};
496
497
498//typedef NodeSVG::xml_tree_t TreeSVG;
499
500
501} // image::
502
503
504/*
505inline
506std::ostream & operator<<(std::ostream &ostr, const image::NodeSVG & node){
507 return node.nodeToStream(ostr);
508}
509*/
510
511
512
513} // drain::
514
515
516inline
517std::ostream & operator<<(std::ostream &ostr, const drain::image::NodeSVG & node){
518 return node.nodeToStream(ostr);
519}
520
521
522
523inline
524std::ostream & operator<<(std::ostream &ostr, const drain::image::TreeSVG & tree){
525 return drain::image::NodeSVG::docToStream(ostr, tree);
526}
527
528
529
530namespace drain {
531
532DRAIN_TYPENAME(image::NodeSVG);
533DRAIN_TYPENAME(image::svg::tag_t);
534
535
536
537/*
538template <>
539template <typename K, typename V>
540image::TreeSVG & image::TreeSVG::operator=(std::initializer_list<std::pair<K,V> > args){
541 drain::Logger mout(__FILE__, __FUNCTION__);
542 mout.attention("initlist pair<K,V>: ", args);
543 data.set(args); // what about TreeSVG & arg
544 return *this;
545}
546*/
547
548
549template <> // referring to Tree<NodeSVG>
550template <> // referring to tparam T
551inline
552image::TreeSVG & image::TreeSVG::operator=(const std::string & arg){
553 UtilsXML::assignString(*this, arg);
554 return *this;
555}
556
557
558template <> // referring to Tree<NodeSVG>
559inline
560image::TreeSVG & image::TreeSVG::operator=(std::initializer_list<std::pair<const char *,const Variable> > l){
561 return UtilsXML::assign(*this, l);
562}
563
564
565template <>
566template <class T>
567image::TreeSVG & image::TreeSVG::operator=(const T & arg){
568 return UtilsXML::assign(*this, arg);
569}
570
572
584DRAIN_XML_EASY_TYPE(image::TreeSVG);
585
586DRAIN_XML_ENUM_KEY(image::TreeSVG, image::svg::tag_t);
587
588// NEW 2026/02/27 replacing many!?
589/*
590template <> // for T (Tree class)
591template <> // for K (path elem arg)
592inline
593const image::TreeSVG::key_t & image::TreeSVG::getKey(const image::svg::tag_t & type){
594 return Enum<image::svg::tag_t>::dict.getKey(type, false);
595}
596*/
597
598template <> // for T (Tree class)
599template <> // for K (path elem arg)
600inline
601const image::TreeSVG::key_t & image::TreeSVG::getKey(const ClassXML & cls){
602 return image::TreeSVG::getKey(cls.strPrefixed()); // const !
603}
604
605template <> // for T (Tree class)
606template <> // for K (path elem arg)
607inline
608const image::TreeSVG::key_t & image::TreeSVG::getKey(const drain::SelectXML<image::svg::tag_t> & sel){
609 return image::TreeSVG::getKey(sel.str()); // const !
610}
611
612
613
614/*
615template <> // for T (Tree class)
616template <> // for K (path elem arg)
617bool image::TreeSVG::hasChild(const image::svg::tag_t & type) const;
618*/
619
620/*
622template <> // for T (Tree class)
623template <> // for K (path elem arg)
624image::TreeSVG & image::TreeSVG::operator[](const image::svg::tag_t & type);
625
626
627
629template <> // for T (Tree class)
630template <> // for K (path elem arg)
631const image::TreeSVG & image::TreeSVG::operator[](const image::svg::tag_t & type) const ;
632
633
634template <> // for T (Tree class)
635template <> // for K (path elem arg)
636bool image::TreeSVG::hasChild(const ClassXML & cls) const;
637
638template <> // for T (Tree class)
639template <> // for K (path elem arg)
640image::TreeSVG & image::TreeSVG::operator[](const ClassXML & cls);
641
643template <> // for T (Tree class)
644template <> // for K (path elem arg)
645const image::TreeSVG & image::TreeSVG::operator[](const ClassXML & cls) const ;
646
647*/
648
649/*
650template <>
651inline
652image::TreeSVG & image::TreeSVG::addChild(){
653 return UtilsXML::addChild(*this);
654}
655*/
656
657
658DRAIN_XML_DEFAULT_ELEMS(image::TreeSVG);
659
660//template <>
661//const NodeXML<image::svg::tag_t>::xml_default_elem_map_t NodeXML<image::svg::tag_t>::xml_default_elems;
662
664
667DRAIN_XML_DEFAULT_INIT(image::TreeSVG);
668
669/*
670template <>
671inline
672void image::TreeSVG::initChild(image::TreeSVG & child) const {
673 UtilsXML::initChildWithDefaultType(*this, child);
674}
675*/
676
677
678
679/*
680template <>
681template <class K>
682const image::TreeSVG::key_t & image::TreeSVG::getKey(const K & key){
683 return Enum<K>::dict.getKey(key, false);
684}
685*/
686
687/* tested 2025/01/20 but caused problems with Hi5Tree("dataset2") etc.
688template <>
689template <typename K> // for K (path elem arg)
690const image::TreeSVG::key_t & image::TreeSVG::getKey(const K & key){
691 return Enum<K>::dict.getKey(key, false);
692}
693
694template <>
695template <> // for K (path elem arg)
696inline
697const image::TreeSVG::key_t & image::TreeSVG::getKey(const drain::StyleSelectorXML<image::NodeSVG> & selector){
698 return selector;
699}
700
701*/
702
703} // drain::
704
705#endif // DRAIN_TREE_SVG
706
A wrapper marking string an CSS effect.
Definition ClassXML.h:57
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:416
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 SelectorXML.h:73
Definition StringBuilder.h:58
static T & assign(T &dst, const T &src)
Assign another tree structure to another.
Definition UtilsXML.h:60
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:134
bool typeIsSet() const
Return true, if type is any of the arguments.
Definition XML.h:165
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:664
std::string id
Some general-purpose.
Definition TreeXML.h:95
Definition TreeSVG.h:144
Definition TreeSVG.h:61
Definition TreeSVG.h:465
Definition TreeSVG.h:182
void setBoundingBox(const drain::Box< T > &b)
Set position (x,y), width and height of an object.
Definition TreeSVG.h:305
void setLocation(const T &x, const T &y)
Definition TreeSVG.h:339
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:223
const BBoxSVG & getBoundingBox() const
Get position (x,y), width and height of an object.
Definition TreeSVG.h:291
NodeSVG & operator=(const NodeSVG &node)
Copy data from a node. (Does not copy subtree.)
Definition TreeSVG.h:233
static std::string xlink
In opening SVG tag, referred to by attribute "xmlns:xlink".
Definition TreeSVG.h:189
void setMargin(T w)
Set margin of a TEXT element (non-standard).
Definition TreeSVG.h:382
void setWidth(T w)
Definition TreeSVG.h:367
NodeSVG & operator=(const std::initializer_list< Variable::init_pair_t > &l)
Copy data from a node. (Does not copy subtree.)
Definition TreeSVG.h:245
virtual void specificAttributesToStream(std::ostream &ostr) const override
Write transform, in addition to XML::ClassList.
Definition TreeSVG.cpp:326
svg::coord_t getMargin()
Get margin of a TEXT element (non-standard).
Definition TreeSVG.h:393
void setFontSize(svg::coord_t size, svg::coord_t elemHeight=0.0)
Sets font size and also text elem "height".
Definition TreeSVG.cpp:232
void setHeight(T h)
Definition TreeSVG.h:404
virtual bool isSingular() const override final
If true, render always as single elem (without child elems)
Definition TreeSVG.h:226
void setLocation(const drain::Point2D< T > &point)
Set position (x,y) of an object.
Definition TreeSVG.h:328
BBoxSVG & getBoundingBox()
Get position (x,y), width and height of an object.
Definition TreeSVG.h:298
static std::string svg_decl
In opening SVG tag, referred to by attributes "xmlns" and "xmlns:svg".
Definition TreeSVG.h:193
void setFrame(const T &w, const T &h)
Definition TreeSVG.h:356
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:155
User-friendly programming interface for alignment considering two elements.
Definition AlignSVG.h:230
Definition TreeSVG.h:104