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 getMap()["data-height"].link(box.height);
407 }
408 box.height = h;
409 }
410
411 inline
412 svg::coord_t getHeight(){
413 return box.height;
414 }
415
417 void setFontSize(svg::coord_t size, svg::coord_t elemHeight = 0.0);
418
419 TransformSVG transform;
420
422
428 virtual
429 void specificAttributesToStream(std::ostream & ostr) const override;
430
431
432 void swapSVG(NodeSVG & node);
433
434protected:
435
436 virtual
437 void handleType() override final;
438
439
440 virtual
441 void updateAlign() override;
442
443 // TODO: allowedUnits drain::Units
444 BBoxSVG box;
445
446};
447
448
449/*
450template <typename P, typename A,typename V>
451void NodeSVG::setAlign(const P & pos, const A & axis, const V &value){
452 alignments[p][a] = v;
453}
454*/
455
456
457// Utility (move to utils?)
459
460public:
461
462 inline
463 NodePrinter(const NodeSVG & node){
464 std::stringstream sstr;
465 sstr << "<" << node.getTag();
466 if (::atoi(node.getId().c_str())==0){
467 sstr << " id=" << node.getId();
468 }
469 if (node.getName().isValid()){
470 sstr << " name=" << node.getName();
471 }
472 if (!node.getClasses().empty()){
473 sstr << " class=[" << node.getClasses() << ']';
474 }
475 sstr << '>';
476 id = sstr.str();
477 }
478
479 const std::string & str() const {
480 return id;
481 }
482
483
484protected:
485
486 std::string id;
487
488};
489
490
491//typedef NodeSVG::xml_tree_t TreeSVG;
492
493
494} // image::
495
496
497/*
498inline
499std::ostream & operator<<(std::ostream &ostr, const image::NodeSVG & node){
500 return node.nodeToStream(ostr);
501}
502*/
503
504
505
506} // drain::
507
508
509inline
510std::ostream & operator<<(std::ostream &ostr, const drain::image::NodeSVG & node){
511 return node.nodeToStream(ostr);
512}
513
514
515
516inline
517std::ostream & operator<<(std::ostream &ostr, const drain::image::TreeSVG & tree){
518 return drain::image::NodeSVG::docToStream(ostr, tree);
519}
520
521
522
523namespace drain {
524
525DRAIN_TYPENAME(image::NodeSVG);
526DRAIN_TYPENAME(image::svg::tag_t);
527
528
529
530/*
531template <>
532template <typename K, typename V>
533image::TreeSVG & image::TreeSVG::operator=(std::initializer_list<std::pair<K,V> > args){
534 drain::Logger mout(__FILE__, __FUNCTION__);
535 mout.attention("initlist pair<K,V>: ", args);
536 data.set(args); // what about TreeSVG & arg
537 return *this;
538}
539*/
540
541
542template <> // referring to Tree<NodeSVG>
543template <> // referring to tparam T
544inline
545image::TreeSVG & image::TreeSVG::operator=(const std::string & arg){
546 UtilsXML::assignString(*this, arg);
547 return *this;
548}
549
550
551template <> // referring to Tree<NodeSVG>
552inline
553image::TreeSVG & image::TreeSVG::operator=(std::initializer_list<std::pair<const char *,const Variable> > l){
554 return UtilsXML::assign(*this, l);
555}
556
557
558template <>
559template <class T>
560image::TreeSVG & image::TreeSVG::operator=(const T & arg){
561 return UtilsXML::assign(*this, arg);
562}
563
565
576DRAIN_XML_EASY_TYPE(image::TreeSVG);
577
578DRAIN_XML_ENUM_KEY(image::TreeSVG, image::svg::tag_t);
579
580
581template <> // for T (Tree class)
582template <> // for K (path elem arg)
583inline
584const image::TreeSVG::key_t & image::TreeSVG::getKey(const ClassXML & cls){
585 return image::TreeSVG::getKey(cls.strPrefixed()); // const !
586}
587
588template <> // for T (Tree class)
589template <> // for K (path elem arg)
590inline
591const image::TreeSVG::key_t & image::TreeSVG::getKey(const drain::SelectXML<image::svg::tag_t> & sel){
592 return image::TreeSVG::getKey(sel.str()); // const !
593}
594
595
596
597DRAIN_XML_DEFAULT_ELEMS(image::TreeSVG);
598
600
603DRAIN_XML_DEFAULT_INIT(image::TreeSVG);
604
605
606} // drain::
607
608#endif // DRAIN_TREE_SVG
609
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:420
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:161
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:707
std::string id
Some general-purpose.
Definition TreeXML.h:95
Definition TreeSVG.h:144
Definition TreeSVG.h:61
Definition TreeSVG.h:458
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:319
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
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:369
Definition TreeSVG.h:104