1 /** \file
2  * \brief Declaration of basic types for graphics.
3  *
4  * \author Carsten Gutwenger
5  *
6  * \par License:
7  * This file is part of the Open Graph Drawing Framework (OGDF).
8  *
9  * \par
10  * Copyright (C)<br>
11  * See README.md in the OGDF root directory for details.
12  *
13  * \par
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * Version 2 or 3 as published by the Free Software Foundation;
17  * see the file LICENSE.txt included in the packaging of this file
18  * for details.
19  *
20  * \par
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * \par
27  * You should have received a copy of the GNU General Public
28  * License along with this program; if not, see
29  * http://www.gnu.org/copyleft/gpl.html
30  */
31 
32 #pragma once
33 
34 #include <ogdf/basic/basic.h>
35 #include <map>
36 #include <typeinfo>
37 #include <ogdf/basic/Logger.h>
38 
39 
40 namespace ogdf {
41 
42 //! Line types of strokes.
43 /**
44  * @ingroup graph-drawing
45  */
46 enum class StrokeType : unsigned char {
47 	None,      //!< no line
48 	Solid,     //!< solid line
49 	Dash,      //!< dashed line
50 	Dot,       //!< dotted line
51 	Dashdot,   //!< line style "dash dot dash dot ..."
52 	Dashdotdot //!< line style "dash dot dot dash dot dot ..."
53 };
54 
55 //! Output operator
56 OGDF_EXPORT std::ostream &operator<<(std::ostream &os, const StrokeType &st);
57 
58 //! Converts integer \p i to stroke type.
59 /**
60  * @ingroup graph-drawing
61  */
62 StrokeType intToStrokeType(int i);
63 
64 //! Converts string \p s to stroke type.
65 /**
66  * @ingroup graph-drawing
67  */
68 OGDF_EXPORT string strokeTypeToString(StrokeType st);
69 
70 //! Converts string \p s to stroke type.
71 /**
72  * @ingroup graph-drawing
73  */
74 OGDF_EXPORT StrokeType stringToStrokeType(string s);
75 
76 
77 //! Line cap types of strokes.
78 /**
79  * @ingroup graph-drawing
80  */
81 enum class StrokeLineCap : unsigned char{
82 	Butt,
83 	Round,
84 	Square
85 };
86 
87 
88 //! Line join types of strokes.
89 /**
90  * @ingroup graph-drawing
91  */
92 enum class StrokeLineJoin : unsigned char {
93 	Miter,
94 	Round,
95 	Bevel
96 };
97 
98 
99 //! Fill patterns.
100 /**
101  * @ingroup graph-drawing
102  */
103 enum class FillPattern {
104 	None,
105 	Solid,
106 	Dense1,
107 	Dense2,
108 	Dense3,
109 	Dense4,
110 	Dense5,
111 	Dense6,
112 	Dense7,
113 	Horizontal,
114 	Vertical,
115 	Cross,
116 	BackwardDiagonal,
117 	ForwardDiagonal,
118 	DiagonalCross
119 };
120 
121 void initFillPatternHashing();
122 
123 //! Converts fillpattern \p fp to string.
124 /**
125  * @ingroup graph-drawing
126  */
127 OGDF_EXPORT string fillPatternToString(FillPattern fp);
128 
129 //! Converts string \p s to fill pattern.
130 /**
131  * @ingroup graph-drawing
132  */
133 OGDF_EXPORT FillPattern stringToFillPattern(string s);
134 
135 //! Output operator
136 OGDF_EXPORT std::ostream &operator<<(std::ostream &os, const FillPattern &fp);
137 
138 //! Converts integer \p i to fill pattern.
139 /**
140  * @ingroup graph-drawing
141  */
142 FillPattern intToFillPattern(int i);
143 
144 
145 //! Types for node shapes.
146 /**
147  * @ingroup graph-drawing
148  */
149 enum class Shape {
150 	Rect,               //!< rectangle
151 	RoundedRect,        //!< rectangle with rounded corners
152 	Ellipse,            //!< ellipse
153 	Triangle,           //!< isosceles triangle (base side down)
154 	Pentagon,           //!< pentagon
155 	Hexagon,            //!< hexagon
156 	Octagon,            //!< octagon
157 	Rhomb,              //!< rhomb (=diamond)
158 	Trapeze,            //!< trapeze (upper side shorter)
159 	Parallelogram,      //!< parallelogram (slanted to the right)
160 	InvTriangle,        //!< isosceles triangle (base side up)
161 	InvTrapeze,         //!< inverted trapeze  (upper side longer)
162 	InvParallelogram,   //!< inverted parallelogram (slanted to the left)
163 	Image
164 };
165 
166 //! Converts shape \p s to string.
167 /**
168 * @ingroup graph-drawing
169 */
170 OGDF_EXPORT string shapeToString(Shape s);
171 
172 //! Converts string \p s to shape.
173 /**
174 * @ingroup graph-drawing
175 */
176 OGDF_EXPORT Shape stringToShape(string s);
177 
178 //! Output operator
179 OGDF_EXPORT std::ostream &operator<<(std::ostream &os, const FillPattern &fp);
180 
181 
182 //! Types for edge arrows.
183 /**
184  * @ingroup graph-drawing
185  */
186 enum class EdgeArrow {
187 	None, //!< no edge arrows
188 	Last, //!< edge arrow at target node of the edge
189 	First, //!< edge arrow at source node of the edge
190 	Both, //!< edge arrow at target and source node of the edge
191 	Undefined
192 };
193 
194 //! Output operator
195 OGDF_EXPORT std::ostream &operator<<(std::ostream &os, const EdgeArrow &ea);
196 
197 //! Colors represented as RGBA values.
198 /**
199  * @ingroup graph-drawing
200  *
201  * The Color class represents colors with four components: R (red), G (green), B (blue), and A (alpha channel).
202  * Each component has a value between and 255. The alpha channel controls tranparency, where an opaque color
203  * has an alpha channel of 255.
204  */
205 class OGDF_EXPORT Color {
206 	uint8_t m_red, m_green, m_blue, m_alpha;
207 
208 public:
209 	//! Named colors (same as SVG color keywords).
210 	enum class Name {
211 		Aliceblue,
212 		Antiquewhite,
213 		Aqua,
214 		Aquamarine,
215 		Azure,
216 		Beige,
217 		Bisque,
218 		Black,
219 		Blanchedalmond,
220 		Blue,
221 		Blueviolet,
222 		Brown,
223 		Burlywood,
224 		Cadetblue,
225 		Chartreuse,
226 		Chocolate,
227 		Coral,
228 		Cornflowerblue,
229 		Cornsilk,
230 		Crimson,
231 		Cyan,
232 		Darkblue,
233 		Darkcyan,
234 		Darkgoldenrod,
235 		Darkgray,
236 		Darkgreen,
237 		Darkgrey,
238 		Darkkhaki,
239 		Darkmagenta,
240 		Darkolivegreen,
241 		Darkorange,
242 		Darkorchid,
243 		Darkred,
244 		Darksalmon,
245 		Darkseagreen,
246 		Darkslateblue,
247 		Darkslategray,
248 		Darkslategrey,
249 		Darkturquoise,
250 		Darkviolet,
251 		Deeppink,
252 		Deepskyblue,
253 		Dimgray,
254 		Dimgrey,
255 		Dodgerblue,
256 		Firebrick,
257 		Floralwhite,
258 		Forestgreen,
259 		Fuchsia,
260 		Gainsboro,
261 		Ghostwhite,
262 		Gold,
263 		Goldenrod,
264 		Gray,
265 		Green,
266 		Greenyellow,
267 		Grey,
268 		Honeydew,
269 		Hotpink,
270 		Indianred,
271 		Indigo,
272 		Ivory,
273 		Khaki,
274 		Lavender,
275 		Lavenderblush,
276 		Lawngreen,
277 		Lemonchiffon,
278 		Lightblue,
279 		Lightcoral,
280 		Lightcyan,
281 		Lightgoldenrodyellow,
282 		Lightgray,
283 		Lightgreen,
284 		Lightgrey,
285 		Lightpink,
286 		Lightsalmon,
287 		Lightseagreen,
288 		Lightskyblue,
289 		Lightslategray,
290 		Lightslategrey,
291 		Lightsteelblue,
292 		Lightyellow,
293 		Lime,
294 		Limegreen,
295 		Linen,
296 		Magenta,
297 		Maroon,
298 		Mediumaquamarine,
299 		Mediumblue,
300 		Mediumorchid,
301 		Mediumpurple,
302 		Mediumseagreen,
303 		Mediumslateblue,
304 		Mediumspringgreen,
305 		Mediumturquoise,
306 		Mediumvioletred,
307 		Midnightblue,
308 		Mintcream,
309 		Mistyrose,
310 		Moccasin,
311 		Navajowhite,
312 		Navy,
313 		Oldlace,
314 		Olive,
315 		Olivedrab,
316 		Orange,
317 		Orangered,
318 		Orchid,
319 		Palegoldenrod,
320 		Palegreen,
321 		Paleturquoise,
322 		Palevioletred,
323 		Papayawhip,
324 		Peachpuff,
325 		Peru,
326 		Pink,
327 		Plum,
328 		Powderblue,
329 		Purple,
330 		Red,
331 		Rosybrown,
332 		Royalblue,
333 		Saddlebrown,
334 		Salmon,
335 		Sandybrown,
336 		Seagreen,
337 		Seashell,
338 		Sienna,
339 		Silver,
340 		Skyblue,
341 		Slateblue,
342 		Slategray,
343 		Slategrey,
344 		Snow,
345 		Springgreen,
346 		Steelblue,
347 		Tan,
348 		Teal,
349 		Thistle,
350 		Tomato,
351 		Turquoise,
352 		Violet,
353 		Wheat,
354 		White,
355 		Whitesmoke,
356 		Yellow,
357 		Yellowgreen
358 	};
359 
360 	//! Creates an opaque black color.
Color()361 	Color() : m_red(0), m_green(0), m_blue(0), m_alpha(255) { }
362 
363 	//! Creates a color from given RGBA-values.
m_red(r)364 	Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255) : m_red(r), m_green(g), m_blue(b), m_alpha(a) { }
365 
366 	//! Creates a color from given RGBA-values.
367 	Color(int r, int g, int b, int a = 255) : m_red((uint8_t)r), m_green((uint8_t)g), m_blue((uint8_t)b), m_alpha((uint8_t)a) { }
368 
369 	//! Creates a color from given color name \p name.
370 	Color(Color::Name name);
371 
372 	//! Crates a color from string \p str.
Color(const string & str)373 	Color(const string &str) { fromString(str); }
374 
375 	//! Crates a color from string \p str.
Color(const char * str)376 	Color(const char *str) { fromString(string(str)); }
377 
378 	//! Returns the red component.
red()379 	uint8_t red() const { return m_red; }
380 
381 	//! Returns the green component.
green()382 	uint8_t green() const { return m_green; }
383 
384 	//! Returns the blue component.
blue()385 	uint8_t blue() const { return m_blue; }
386 
387 	//! Returns the alpha channel.
alpha()388 	uint8_t alpha() const { return m_alpha; }
389 
390 	//! Sets the red component to \p r.
red(uint8_t r)391 	void red(uint8_t r) { m_red = r; }
392 
393 	//! Sets the green component to \p g.
green(uint8_t g)394 	void green(uint8_t g) { m_green = g; }
395 
396 	//! Sets the blue component to \p b.
blue(uint8_t b)397 	void blue(uint8_t b) { m_blue = b; }
398 
399 	//! Sets the alpha channel to \p a.
alpha(uint8_t a)400 	void alpha(uint8_t a) { m_alpha = a; }
401 
402 	//! Converts the color to a string and returns it.
403 	/**
404 	 * Colors as represented as strings using the \#RRGGBB hex notation.
405 	 * Please note that in this notation the alpha channel is not represented and
406 	 * is assumed to be 255 (an opaque color).
407 	 */
408 	string toString() const;
409 
410 	//! Sets the color the the color defined by \p str.
411 	bool fromString(const string &str);
412 
413 	//! Returns true iff \p c and this color are equal in every component.
414 	bool operator==(const Color &c) const {
415 		return m_red == c.m_red && m_green == c.m_green && m_blue == c.m_blue && m_alpha == c.m_alpha;
416 	}
417 
418 	//! Returns true iff \p c and this color differ in any component.
419 	bool operator!=(const Color &c) const {
420 		return !operator==(c);
421 	}
422 
423 	//! Writes the string representation of color \p c to output stream \p os.
424 	friend std::ostream &operator<<(std::ostream &os, const Color &c) {
425 		return os << c.toString();
426 	}
427 };
428 
429 
430 //! Properties of strokes.
431 /**
432  * @ingroup graph-drawing
433  */
434 struct OGDF_EXPORT Stroke {
435 	Color          m_color;    //!< stroke color
436 	float          m_width;    //!< stroke width
437 	StrokeType     m_type; //!< stroke type (e.g. solid or dashed)
438 	StrokeLineCap  m_cap; //!< line-cap of the stroke
439 	StrokeLineJoin m_join; //!< line-join of the stroke
440 
StrokeStroke441 	Stroke() : m_color(Color::Name::Black), m_width(1.0f), m_type(StrokeType::Solid), m_cap(StrokeLineCap::Butt), m_join(StrokeLineJoin::Miter) { }
StrokeStroke442 	Stroke(Color c) : m_color(c), m_width(1.0f), m_type(StrokeType::Solid), m_cap(StrokeLineCap::Butt), m_join(StrokeLineJoin::Miter) { }
443 };
444 
445 
446 //! Properties of fills.
447 /**
448  * @ingroup graph-drawing
449  */
450 struct OGDF_EXPORT Fill {
451 	Color       m_color;   //!< fill color
452 	Color       m_bgColor; //!< background color of fill pattern
453 	FillPattern m_pattern; //!< fill pattern
454 
FillFill455 	Fill() : m_color(Color::Name::White), m_bgColor(Color::Name::Black), m_pattern(FillPattern::Solid) { }
FillFill456 	Fill(Color c) : m_color(c), m_bgColor(Color::Name::Black), m_pattern(FillPattern::Solid) { }
FillFill457 	Fill(Color c, FillPattern pattern) : m_color(c), m_bgColor(Color::Name::Black), m_pattern(pattern) { }
FillFill458 	Fill(Color c, Color bgColor, FillPattern pattern) : m_color(c), m_bgColor(bgColor), m_pattern(pattern) { }
459 };
460 
461 namespace graphics {
462 	extern OGDF_EXPORT std::map<Shape, string> fromShape;
463 	extern OGDF_EXPORT std::map<string, Shape> toShape;
464 
465 	extern OGDF_EXPORT std::map<StrokeType, string> fromStrokeType;
466 	extern OGDF_EXPORT std::map<string, StrokeType> toStrokeType;
467 
468 	extern OGDF_EXPORT std::map<FillPattern, string> fromFillPattern;
469 	extern OGDF_EXPORT std::map<string, FillPattern> toFillPattern;
470 
471 	template<class Enum>
init()472 	inline void init() {};
473 
474 	template<class Enum>
initSecondMap(std::map<Enum,string> & fromMap,std::map<string,Enum> & toMap)475 	inline void initSecondMap(std::map<Enum, string> &fromMap, std::map<string, Enum> &toMap) {
476 		for(auto it : fromMap) {
477 			toMap.emplace(it.second, it.first);
478 		}
479 	}
480 
481 
482 	template<>
483 	inline void init<StrokeType>() {
484 		fromStrokeType.emplace(StrokeType::None,          "None");
485 		fromStrokeType.emplace(StrokeType::Solid,         "Solid");
486 		fromStrokeType.emplace(StrokeType::Dash,          "Dash");
487 		fromStrokeType.emplace(StrokeType::Dot,           "Dot");
488 		fromStrokeType.emplace(StrokeType::Dashdot,       "Dashdot");
489 		fromStrokeType.emplace(StrokeType::Dashdotdot,    "Dashdotdot");
490 
491 		initSecondMap<StrokeType>(fromStrokeType, toStrokeType);
492 	}
493 
494 	template<>
495 	inline void init<FillPattern>() {
496 		fromFillPattern.emplace(FillPattern::None,               "None");
497 		fromFillPattern.emplace(FillPattern::Solid,              "Solid");
498 		fromFillPattern.emplace(FillPattern::Dense1,             "Dense1");
499 		fromFillPattern.emplace(FillPattern::Dense2,             "Dense2");
500 		fromFillPattern.emplace(FillPattern::Dense3,             "Dense3");
501 		fromFillPattern.emplace(FillPattern::Dense4,             "Dense4");
502 		fromFillPattern.emplace(FillPattern::Dense5,             "Dense5");
503 		fromFillPattern.emplace(FillPattern::Dense6,             "Dense6");
504 		fromFillPattern.emplace(FillPattern::Dense7,             "Dense7");
505 		fromFillPattern.emplace(FillPattern::Horizontal,         "Horizontal");
506 		fromFillPattern.emplace(FillPattern::Vertical,           "Vertical");
507 		fromFillPattern.emplace(FillPattern::Cross,              "Cross");
508 		fromFillPattern.emplace(FillPattern::BackwardDiagonal,   "BackwardDiagonal");
509 		fromFillPattern.emplace(FillPattern::ForwardDiagonal,    "ForwardDiagonal");
510 		fromFillPattern.emplace(FillPattern::DiagonalCross,      "DiagonalCross");
511 
512 		initSecondMap<FillPattern>(fromFillPattern, toFillPattern);
513 	}
514 
515 	template<>
516 	inline void init<Shape>() {
517 		fromShape.emplace(Shape::Rect,                 "Rect");
518 		fromShape.emplace(Shape::RoundedRect,          "RoundedRect");
519 		fromShape.emplace(Shape::Ellipse,              "Ellipse");
520 		fromShape.emplace(Shape::Triangle,             "Triangle");
521 		fromShape.emplace(Shape::Pentagon,             "Pentagon");
522 		fromShape.emplace(Shape::Hexagon,              "Hexagon");
523 		fromShape.emplace(Shape::Octagon,              "Octagon");
524 		fromShape.emplace(Shape::Rhomb,                "Rhomb");
525 		fromShape.emplace(Shape::Trapeze,              "Trapeze");
526 		fromShape.emplace(Shape::Parallelogram,        "Parallelogram");
527 		fromShape.emplace(Shape::InvTriangle,          "InvTriangle");
528 		fromShape.emplace(Shape::InvTrapeze,           "InvTrapeze");
529 		fromShape.emplace(Shape::InvParallelogram,     "InvParallelogram");
530 		fromShape.emplace(Shape::Image,                "Image");
531 
532 		initSecondMap<Shape>(fromShape, toShape);
533 		toShape.emplace("rectangle",                    Shape::Rect);
534 		toShape.emplace("box",                          Shape::Image);
535 	}
536 
537 	template<class ToClass>
getMapToEnum()538 	inline std::map<string, ToClass>* getMapToEnum() {
539 		std::cout << "getMapToEnum was wrongly called\n";
540 		OGDF_ASSERT(false);
541 		return nullptr;
542 	};
543 
544 	template<class FromClass>
getMapToString()545 	inline std::map<FromClass, string>* getMapToString() {
546 		FromClass fc;
547 		std::cout << "getMapToString was wrongly called " << typeid(fc).name() << "\n";
548 		OGDF_ASSERT(false);
549 		return nullptr;
550 	};
551 
552 	template<>
getMapToEnum()553 	inline std::map<string, FillPattern> *getMapToEnum() {
554 		return &toFillPattern;
555 	};
556 
557 	template<>
getMapToEnum()558 	inline std::map<string, Shape> *getMapToEnum() {
559 		return &toShape;
560 	};
561 
562 	template<>
getMapToEnum()563 	inline std::map<string, StrokeType> *getMapToEnum() {
564 		return &toStrokeType;
565 	};
566 
567 	template<>
getMapToString()568 	inline std::map<FillPattern, string> *getMapToString() {
569 		return &fromFillPattern;
570 	};
571 
572 	template<>
getMapToString()573 	inline std::map<Shape, string> *getMapToString() {
574 		return &fromShape;
575 	};
576 
577 	template<>
getMapToString()578 	inline std::map<StrokeType, string> *getMapToString() {
579 		return &fromStrokeType;
580 	};
581 }
582 
583 template<class FromClass>
toString(FromClass key)584 inline string toString(FromClass key) {
585 	auto *map = graphics::getMapToString<FromClass>();
586 	if(map->empty()) {
587 		graphics::init<FromClass>();
588 	}
589 	auto it = map->find(key);
590 	OGDF_ASSERT(it != map->end());
591 	return (*it).second;
592 };
593 
594 template<class ToClass>
fromString(string key)595 inline ToClass fromString(string key) {
596 	auto map = graphics::getMapToEnum<ToClass>();
597 	if(map->empty()) {
598 		graphics::init<ToClass>();
599 	}
600 	auto it = map->find(key);
601 	if(it != map->end()) {
602 		return (*it).second;
603 	} else {
604 		Logger::slout() << "Encountered invalid " << typeid((*map->begin()).second).name()
605 						<< ": " << key << " " << map->size() << " " << map->empty() << std::endl;
606 		return static_cast<ToClass>(std::numeric_limits<int>::min());
607 	}
608 };
609 }
610