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/util/EnumFlags.h"
42#include "drain/util/FileInfo.h"
43#include "drain/util/Frame.h"
44#include "drain/util/SelectorXML.h"
45#include "drain/util/TreeXML.h"
46#include "AlignSVG.h"
47
48namespace drain {
49
50namespace image {
51
52class NodeSVG;
53
54typedef drain::UnorderedMultiTree<NodeSVG,false, NodeXML<>::path_t> TreeSVG;
55
56struct svg {
57
58 typedef float coord_t;
59
60 enum tag_t {
61 UNDEFINED=XML::UNDEFINED,
62 COMMENT=XML::COMMENT,
63 CTEXT=XML::CTEXT,
64 SCRIPT=XML::SCRIPT,
65 STYLE=XML::STYLE,
66 STYLE_SELECT=XML::STYLE_SELECT,
67 SVG=10,
68 CIRCLE, DESC, GROUP, LINE, IMAGE, METADATA, POLYGON, RECT, TEXT, TITLE, TSPAN };
69 // check CTEXT, maybe implement in XML
70
71};
72
73} // image::
74
75
77
78
79template <>
81
82DRAIN_ENUM_OSTREAM(image::svg::tag_t)
83
84
85
86namespace image {
87
88class BBoxSVG : public drain::Box<svg::coord_t> {
89
90public:
91
92 inline
93 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) {
94 }
95
96 inline
97 BBoxSVG(const BBoxSVG & bbox) : drain::Box<svg::coord_t>(bbox) {
98 }
99
100 // Future option - also other units!
101 /*
102 bool x_PERCENTAGE = false;
103 bool y_PERCENTAGE = false;
104 bool width_PERCENTAGE = false;
105 bool height_PERCENTAGE = false;
106 */
107};
108
109
110template <size_t N>
111class Transform : public UniTuple<double,N> {
112
113public:
114
115 bool empty() const {
116 return (*this == 0.0);
117 }
118
119 virtual inline
120 void toStream(std::ostream & ostr) const override {
121 ostr << '(';
123 ostr << ')';
124 }
125
126};
127
128
129template <size_t N>
130std::ostream & operator<<(std::ostream & ostr, Transform<N> & tr){
131 tr.toStream(ostr);
132 return ostr;
133}
134
135
136// Future option
138
139public:
140
141 TransformSVG();
142
143 inline
144 bool empty() const {
145 return (rotate.empty() && scale.empty() && translate.empty() && matrix.empty()) ;
146 }
147
148 inline
149 void setTranslate(const svg::coord_t & x, const svg::coord_t & y){
150 // translate.ensureSize(2);
151 translate.set(x,y);
152 }
153
154 inline
155 void setTranslateX(const svg::coord_t & x){
156 // translate.ensureSize(1);
157 // translate.set(x);
158 translate[0] = x;
159 }
160
161 inline
162 void setTranslateY(const svg::coord_t & y){
163 // translate.ensureSize(2);
164 // svg::coord_t x = translate.get<svg::coord_t>(1);
165 translate[1] = y;
166 // translate.set(x, y);
167 }
168
170
172 Transform<2> scale;
173 Transform<2> translate;
174 Transform<6> matrix;
175
176 /*
177 Variable rotate;
178 Variable scale;
179 Variable translate;
180 Variable matrix;
181 */
182
183 // drain::Variable matrix;
184 // drain::Variable skewX;
185 // drain::Variable skewY;
186 void toStream(std::ostream & ostr) const;
187
188};
189
190//typedef drain::StyleSelectorXML<NodeSVG> SelectSVG;
192
194
200// class NodeSVG: public svg, public NodeXML<svg::tag_t>, public AlignAdapterSVG {
201class NodeSVG: public NodeXML<svg::tag_t>, public AlignAdapterSVG {
202public:
203
205 static
206 std::string xlink;
207
209 static
210 std::string svg;
211
212 static
213 const drain::FileInfo fileInfo;
214
215
217 NodeSVG(svg::tag_t t = svg::UNDEFINED);
218
220 NodeSVG(const NodeSVG & node);
221
222 inline virtual
223 ~NodeSVG(){};
224
225 inline
226 bool isAbstract(){
227 return typeIs(
228 svg::tag_t::STYLE,
229 svg::tag_t::DESC,
230 svg::tag_t::METADATA,
231 svg::tag_t::SCRIPT,
232 svg::tag_t::TITLE,
233 svg::tag_t::TSPAN
234 );
235 }
236
238 virtual inline
239 bool isSingular() const override final {
240 return false;
241 }
242
243
245 inline
246 NodeSVG & operator=(const NodeSVG & node){
247 XML::xmlAssignNode(*this, node);
248 return *this;
249 }
250
252 inline
253 NodeSVG & operator=(const std::initializer_list<Variable::init_pair_t > &l){
254 set(l);
255 return *this;
256 }
257
258 template <class T>
259 inline
260 NodeSVG & operator=(const T & arg){
261 set(arg);
262 //assign(arg);
263 return *this;
264 }
265
266
267
269 virtual
270 void setAttribute(const std::string & key, const std::string &value) override;
271
273 virtual
274 void setAttribute(const std::string & key, const char *value) override;
275
276
277
279 inline
280 const BBoxSVG & getBoundingBox() const {
281 return box;
282 }
283 // Consider also with conversion: getBoundingBox(Box<T> &b)
284
286 inline
288 return box;
289 }
290
292 template <typename T>
293 inline
295 setLocation(b);
296 setFrame(b);
297 // setAttribute("data:bbox", StringBuilder<' '>(b.x, b.y, b.getWidth(), b.getHeight()));
298 }
299
301 template <typename T>
302 inline
303 void setLocation(const drain::Point2D<T> & point){
304 box.x = point.x;
305 box.y = point.y;
306 }
307
312 template <typename T>
313 inline
314 void setLocation(const T & x, const T & y){
315 box.setLocation(x, y);
316 }
317
318 template <typename T>
319 inline
320 void setFrame(const drain::Frame2D<T> & frame){
321 box.width = frame.width;
322 box.height = frame.height;
323 }
324
329 template <typename T>
330 inline
331 void setFrame(const T & w, const T & h){
332 box.setArea(w, h);
333 }
334
335
340 template <typename T>
341 inline
342 void setWidth(T w){
343 box.width = w;
344 }
345
346 inline
347 svg::coord_t getWidth(){
348 return box.width;
349 }
350
352
355 template <typename T>
356 inline
357 void setMargin(T w){
358 link("data-margin", box.width);
359 box.width = w;
360 }
361
363
366 inline
367 svg::coord_t getMargin(){
368 return box.width;
369 }
370
371
376 template <typename T>
377 inline
378 void setHeight(T h){
379 if (typeIs(svg::TEXT)){
380 link("data-height", box.height);
381 }
382 box.height = h;
383 }
384
385 inline
386 svg::coord_t getHeight(){
387 return box.height;
388 }
389
391 void setFontSize(svg::coord_t size, svg::coord_t elemHeight = 0.0);
392
393 TransformSVG transform;
394
396
402 virtual
403 void specificAttributesToStream(std::ostream & ostr) const override;
404
405protected:
406
407
409
412 virtual
413 void handleType(const svg::tag_t & t) override final;
414
415 virtual
416 void updateAlign() override;
417
418 //drain::Box<coord_t> box;
419 BBoxSVG box;
420 // consider:
421 // bool x_PERCENTAGE = false;
422 // bool y_PERCENTAGE = false;
423 // svg:
424
425 int radius = 0;
426
427};
428
429
430/*
431template <typename P, typename A,typename V>
432void NodeSVG::setAlign(const P & pos, const A & axis, const V &value){
433 alignments[p][a] = v;
434}
435*/
436
437} // image::
438
439inline
440std::ostream & operator<<(std::ostream &ostr, const image::NodeSVG & node){
441 return node.nodeToStream(ostr);
442}
443
444
445} // drain::
446
447
448inline
449std::ostream & operator<<(std::ostream &ostr, const drain::image::TreeSVG & tree){
450 //return drain::NodeXML<const drain::image::NodeSVG>::docToStream(ostr, tree);
451 return drain::image::NodeSVG::docToStream(ostr, tree);
452 //return drain::image::TreeSVG::node_data_t::docToStream(ostr, tree);
453}
454
455
456
457namespace drain {
458
459DRAIN_TYPENAME(image::NodeSVG);
460DRAIN_TYPENAME(image::svg::tag_t);
461
462
463template <>
464const NodeXML<image::svg::tag_t>::xml_default_elem_map_t NodeXML<image::svg::tag_t>::xml_default_elems;
465
466/*
467template <>
468template <typename K, typename V>
469image::TreeSVG & image::TreeSVG::operator=(std::initializer_list<std::pair<K,V> > args){
470 drain::Logger mout(__FILE__, __FUNCTION__);
471 mout.attention("initlist pair<K,V>: ", args);
472 data.set(args); // what about TreeSVG & arg
473 return *this;
474}
475*/
476
477
478template <> // referring to Tree<NodeSVG>
479template <> // referring to tparam T
480inline
481image::TreeSVG & image::TreeSVG::operator=(const std::string & arg){
482 XML::xmlAssignString(*this, arg);
483 return *this;
484}
485
486
487template <> // referring to Tree<NodeSVG>
488inline
489image::TreeSVG & image::TreeSVG::operator=(std::initializer_list<std::pair<const char *,const Variable> > l){
490//image::TreeSVG & image::TreeSVG::operator=(std::initializer_list<std::pair<const char *,const char *> > l){
491 return XML::xmlAssign(*this, l);
492}
493
494
495template <>
496template <class T>
497image::TreeSVG & image::TreeSVG::operator=(const T & arg){
498 return XML::xmlAssign(*this, arg);
499 /*
500 data.set(arg); // what about TreeSVG & arg
501 return *this;
502 */
503}
504
505// Important! Useful and widely used – but fails with older C++ compilers ?
506template <>
507template <>
508inline
509image::TreeSVG & image::TreeSVG::operator()(const image::svg::tag_t & type){
510 return XML::xmlSetType(*this, type);
511}
512
513
514template <> // for T (Tree class)
515template <> // for K (path elem arg)
516image::TreeSVG & image::TreeSVG::operator[](const image::svg::tag_t & type);
517
518template <> // for T (Tree class)
519template <> // for K (path elem arg)
520const image::TreeSVG & image::TreeSVG::operator[](const image::svg::tag_t & type) const ;
521
522
523template <>
524inline
525image::TreeSVG & image::TreeSVG::addChild(const image::TreeSVG::key_t & key){
526 return XML::xmlAddChild(*this, key);
527}
528
529
530template <> // for T (Tree class)
531template <> // for K (path elem arg)
532bool image::TreeSVG::hasChild(const image::svg::tag_t & type) const;
533
534
535/*
536template <>
537template <class K>
538const image::TreeSVG::key_t & image::TreeSVG::getKey(const K & key){
539 return EnumDict<K>::dict.getKey(key, false);
540}
541*/
542
543/* tested 2025/01/20 but caused problems with Hi5Tree("dataset2") etc.
544template <>
545template <typename K> // for K (path elem arg)
546const image::TreeSVG::key_t & image::TreeSVG::getKey(const K & key){
547 return EnumDict<K>::dict.getKey(key, false);
548}
549
550template <>
551template <> // for K (path elem arg)
552inline
553const image::TreeSVG::key_t & image::TreeSVG::getKey(const drain::StyleSelectorXML<image::NodeSVG> & selector){
554 return selector;
555}
556
557*/
558
559} // drain::
560
561#endif // DRAIN_TREE_SVG
562
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
Currently used only as CSS element selector.
Definition SelectorXML.h:50
virtual void toStreamFormatted(std::ostream &ostr, char separator=',') const
Definition TupleBase.h:331
Tuple of N elements of type T.
Definition UniTuple.h:65
static TX & xmlAssignString(TX &tree, const std::string &s)
When assigning a string, create new element unless the element itself is of type CTEXT.
Definition XML.h:618
static TX & xmlSetType(TX &tree, const typename TX::node_data_t::xml_tag_t &type)
Definition XML.h:679
static T & xmlAddChild(T &tree, const std::string &key)
Definition XML.h:692
static X & xmlAssignNode(X &dst, const X &src)
Assign another tree structure to another.
Definition XML.h:554
static TX & xmlAssign(TX &dst, const TX &src)
Assign another tree structure to another.
Definition XML.h:513
Definition TreeSVG.h:88
Definition TreeSVG.h:201
virtual void handleType(const svg::tag_t &t) override final
Definition TreeSVG.cpp:190
void setBoundingBox(const drain::Box< T > &b)
Set position (x,y), width and height of an object.
Definition TreeSVG.h:294
void setLocation(const T &x, const T &y)
Definition TreeSVG.h:314
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:288
const BBoxSVG & getBoundingBox() const
Get position (x,y), width and height of an object.
Definition TreeSVG.h:280
NodeSVG & operator=(const NodeSVG &node)
Copy data from a node. (Does not copy subtree.)
Definition TreeSVG.h:246
static std::string xlink
In opening SVG tag, referred to by attribute "xmlns:xlink".
Definition TreeSVG.h:206
void setMargin(T w)
Set margin of a TEXT element (non-standard).
Definition TreeSVG.h:357
void setWidth(T w)
Definition TreeSVG.h:342
NodeSVG & operator=(const std::initializer_list< Variable::init_pair_t > &l)
Copy data from a node. (Does not copy subtree.)
Definition TreeSVG.h:253
virtual void specificAttributesToStream(std::ostream &ostr) const override
Write transform, in addition to XML::ClassList.
Definition TreeSVG.cpp:358
svg::coord_t getMargin()
Get margin of a TEXT element (non-standard).
Definition TreeSVG.h:367
void setFontSize(svg::coord_t size, svg::coord_t elemHeight=0.0)
Sets font size and also text elem "height".
Definition TreeSVG.cpp:297
void setHeight(T h)
Definition TreeSVG.h:378
virtual bool isSingular() const override final
If true, render always as single elem (without child elems)
Definition TreeSVG.h:239
void setLocation(const drain::Point2D< T > &point)
Set position (x,y) of an object.
Definition TreeSVG.h:303
BBoxSVG & getBoundingBox()
Get position (x,y), width and height of an object.
Definition TreeSVG.h:287
void setFrame(const T &w, const T &h)
Definition TreeSVG.h:331
static std::string svg
In opening SVG tag, referred to by attributes "xmlns" and "xmlns:svg".
Definition TreeSVG.h:210
Definition TreeSVG.h:137
Transform< 3 > rotate
Angle (deg), [x,y].
Definition TreeSVG.h:171
Definition TreeSVG.h:111
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: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:56