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