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 if (!typeIsSet()){
248 setType(node.getType());
249 handleType();
250 //handleType(node.getNativeType());
251 }
252 XML::xmlAssignNode(*this, node);
253 return *this;
254 }
255
257 inline
258 NodeSVG & operator=(const std::initializer_list<Variable::init_pair_t > &l){
259 set(l);
260 return *this;
261 }
262
263 template <class T>
264 inline
265 NodeSVG & operator=(const T & arg){
266 set(arg);
267 //assign(arg);
268 return *this;
269 }
270
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
306 template <typename T>
307 inline
308 void setLocation(const drain::Point2D<T> & point){
309 box.x = point.x;
310 box.y = point.y;
311 }
312
317 template <typename T>
318 inline
319 void setLocation(const T & x, const T & y){
320 box.setLocation(x, y);
321 }
322
323 template <typename T>
324 inline
325 void setFrame(const drain::Frame2D<T> & frame){
326 box.width = frame.width;
327 box.height = frame.height;
328 }
329
334 template <typename T>
335 inline
336 void setFrame(const T & w, const T & h){
337 box.setArea(w, h);
338 }
339
340
345 template <typename T>
346 inline
347 void setWidth(T w){
348 box.width = w;
349 }
350
351 inline
352 svg::coord_t getWidth(){
353 return box.width;
354 }
355
357
360 template <typename T>
361 inline
362 void setMargin(T w){
363 link("data-margin", box.width);
364 box.width = w;
365 }
366
368
371 inline
372 svg::coord_t getMargin(){
373 return box.width;
374 }
375
376
381 template <typename T>
382 inline
383 void setHeight(T h){
384 if (typeIs(svg::TEXT)){
385 link("data-height", box.height);
386 }
387 box.height = h;
388 }
389
390 inline
391 svg::coord_t getHeight(){
392 return box.height;
393 }
394
396 void setFontSize(svg::coord_t size, svg::coord_t elemHeight = 0.0);
397
398 TransformSVG transform;
399
401
407 virtual
408 void specificAttributesToStream(std::ostream & ostr) const override;
409
410
411protected:
412
413 virtual
414 void handleType() override final;
415
416
417 virtual
418 void updateAlign() override;
419
420 //drain::Box<coord_t> box;
421 BBoxSVG box;
422 // consider:
423 // bool x_PERCENTAGE = false;
424 // bool y_PERCENTAGE = false;
425 // svg:
426
427 // int radius = 0;
428
429};
430
431
432/*
433template <typename P, typename A,typename V>
434void NodeSVG::setAlign(const P & pos, const A & axis, const V &value){
435 alignments[p][a] = v;
436}
437*/
438
439
440} // image::
441
442inline
443std::ostream & operator<<(std::ostream &ostr, const image::NodeSVG & node){
444 return node.nodeToStream(ostr);
445}
446
447/*
448template <>
449template <>
450class NodeXML<image::svg::tag_t>::Elem<image::svg::tag_t::RECT>{
451public:
452
453 inline
454 Elem(image::NodeSVG & node) : x(node.box.x), y(node.box.y), width(node.box.width), height(node.box.height){
455 };
456
457 float & x;
458 float & y;
459 double & width;
460 double & height;
461};
462*/
463
464template <>
465template <>
466class NodeXML<image::svg::tag_t>::Elem<image::svg::tag_t::RECT>{
467public:
468
469 inline
470 Elem(image::NodeSVG & node) : x(node["x"]), y(node["y"]), width(node["width"]), height(node["height"]){
471 node.setType(image::svg::tag_t::RECT);
472 };
473
476 FlexibleVariable & width;
477 FlexibleVariable & height;
478};
479
480
481
482template <>
483template <>
484class NodeXML<image::svg::tag_t>::Elem<image::svg::tag_t::CIRCLE>{
485public:
486
487 inline
488 Elem(image::NodeSVG & node) : x(node["x"]), y(node["y"]), radius(node["radius"]){
489 node.setType(image::svg::tag_t::CIRCLE);
490 };
491
494 FlexibleVariable & radius;
495
496 /*
497 inline
498 Elem(image::NodeSVG & node) : x(node.box.x), y(node.box.y), radius(node.radius){
499 };
500
501 float & x;
502 float & y;
503 int & radius;
504 // double radius; // FAILS! Upon exiting scope, link becomes invalidated
505 */
506};
507
508} // drain::
509
510
511inline
512std::ostream & operator<<(std::ostream &ostr, const drain::image::TreeSVG & tree){
513 //return drain::NodeXML<const drain::image::NodeSVG>::docToStream(ostr, tree);
514 return drain::image::NodeSVG::docToStream(ostr, tree);
515 //return drain::image::TreeSVG::node_data_t::docToStream(ostr, tree);
516}
517
518
519
520namespace drain {
521
522DRAIN_TYPENAME(image::NodeSVG);
523DRAIN_TYPENAME(image::svg::tag_t);
524
525
526template <>
527const NodeXML<image::svg::tag_t>::xml_default_elem_map_t NodeXML<image::svg::tag_t>::xml_default_elems;
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 XML::xmlAssignString(*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//image::TreeSVG & image::TreeSVG::operator=(std::initializer_list<std::pair<const char *,const char *> > l){
554 return XML::xmlAssign(*this, l);
555}
556
557
558template <>
559template <class T>
560image::TreeSVG & image::TreeSVG::operator=(const T & arg){
561 return XML::xmlAssign(*this, arg);
562 /*
563 data.set(arg); // what about TreeSVG & arg
564 return *this;
565 */
566}
567
569
576template <> // for T - Tree class
577template <> // for K - operator() argument
578// inline
579image::TreeSVG & image::TreeSVG::operator()(const image::svg::tag_t & type);
580/*
581{
582 return XML::xmlSetType(*this, type);
583}
584*/
585
586
588template <> // for T (Tree class)
589template <> // for K (path elem arg)
590image::TreeSVG & image::TreeSVG::operator[](const image::svg::tag_t & type);
591
593template <> // for T (Tree class)
594template <> // for K (path elem arg)
595const image::TreeSVG & image::TreeSVG::operator[](const image::svg::tag_t & type) const ;
596
597
598template <>
599inline
600image::TreeSVG & image::TreeSVG::addChild(const image::TreeSVG::key_t & key){
601 return XML::xmlAddChild(*this, key);
602}
603
604
605template <> // for T (Tree class)
606template <> // for K (path elem arg)
607bool image::TreeSVG::hasChild(const image::svg::tag_t & type) const;
608
609
610/*
611template <>
612template <class K>
613const image::TreeSVG::key_t & image::TreeSVG::getKey(const K & key){
614 return EnumDict<K>::dict.getKey(key, false);
615}
616*/
617
618/* tested 2025/01/20 but caused problems with Hi5Tree("dataset2") etc.
619template <>
620template <typename K> // for K (path elem arg)
621const image::TreeSVG::key_t & image::TreeSVG::getKey(const K & key){
622 return EnumDict<K>::dict.getKey(key, false);
623}
624
625template <>
626template <> // for K (path elem arg)
627inline
628const image::TreeSVG::key_t & image::TreeSVG::getKey(const drain::StyleSelectorXML<image::NodeSVG> & selector){
629 return selector;
630}
631
632*/
633
634} // drain::
635
636#endif // DRAIN_TREE_SVG
637
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
friend class Elem
Provides access to ReferenceMap2 of XML elements, to link FlexibleVariables.
Definition TreeXML.h:106
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
VariableT is a final class applied through typedefs Variable, Reference and FlexibleVariable.
Definition VariableT.h:87
bool typeIsSet() const
Return true, if type is any of the arguments.
Definition XML.h:144
static N & xmlAssignNode(N &dst, const N &src)
Assign tree node (data) to another.
Definition XML.h:654
Definition TreeSVG.h:88
Definition TreeSVG.h:201
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:319
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:240
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: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:362
void setWidth(T w)
Definition TreeSVG.h:347
NodeSVG & operator=(const std::initializer_list< Variable::init_pair_t > &l)
Copy data from a node. (Does not copy subtree.)
Definition TreeSVG.h:258
virtual void specificAttributesToStream(std::ostream &ostr) const override
Write transform, in addition to XML::ClassList.
Definition TreeSVG.cpp:310
svg::coord_t getMargin()
Get margin of a TEXT element (non-standard).
Definition TreeSVG.h:372
void setFontSize(svg::coord_t size, svg::coord_t elemHeight=0.0)
Sets font size and also text elem "height".
Definition TreeSVG.cpp:249
void setHeight(T h)
Definition TreeSVG.h:383
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:308
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:336
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
Something that has coordinates (x,y) and dimensions (width, height).
Definition Frame.h:160
A container for a static dictionary of enumeration values.
Definition EnumFlags.h:69
Definition Point.h:48
Adapter designed for NodeSVG.
Definition AlignSVG.h:730
Definition TreeSVG.h:56