1 /*
2  *    Copyright 2012, 2013 Thomas Schöps
3  *    Copyright 2013-2020 Kai Pastor
4  *
5  *    This file is part of OpenOrienteering.
6  *
7  *    OpenOrienteering is free software: you can redistribute it and/or modify
8  *    it under the terms of the GNU General Public License as published by
9  *    the Free Software Foundation, either version 3 of the License, or
10  *    (at your option) any later version.
11  *
12  *    OpenOrienteering is distributed in the hope that it will be useful,
13  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *    GNU General Public License for more details.
16  *
17  *    You should have received a copy of the GNU General Public License
18  *    along with OpenOrienteering.  If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 
22 #ifndef OPENORIENTEERING_MAP_COLOR_H
23 #define OPENORIENTEERING_MAP_COLOR_H
24 
25 #include <vector>
26 
27 #include <QtGlobal>
28 #include <QtMath>
29 #include <QColor>
30 #include <QHash>
31 #include <QMetaType>
32 #include <QRgb>
33 #include <QString>
34 
35 namespace OpenOrienteering {
36 
37 class MapColor;
38 
39 /**
40  * The MapColorCmyk class provides a datatype for storing and transferring
41  * opaque CMYK colors.
42  *
43  * Components (c, m, y, k) are floats in the range [0.0; 1.0].
44  */
45 struct MapColorCmyk
46 {
47 	/** The cyan component. */
48 	float c = 0;
49 	/** The magenta component. */
50 	float m = 0;
51 	/** The yellow component. */
52 	float y = 0;
53 	/** The black component (aka key). */
54 	float k = 1;
55 
56 	/** Constructs a black color. */
57 	MapColorCmyk() noexcept = default;
58 
59 	/** Constructs a color with the given components. */
60 	MapColorCmyk(float c, float m, float y, float k) noexcept;
61 
62 	/** Constructs a copy of the given CMYK color. */
63 	MapColorCmyk(const MapColorCmyk& other) noexcept = default;
64 
65 	/** Constructs a CMYK color of the given QColor. Used for type conversions. */
66 	MapColorCmyk(const QColor& other) noexcept;
67 
68 	/** Assigns another color's value to this color. */
69 	MapColorCmyk& operator=(const MapColorCmyk& other) = default;
70 
71 	/** Converts this color to a QColor. */
72 	operator QColor() const;
73 
74 	/** Returns true if this color is black. */
75 	bool isBlack() const;
76 
77 	/** Returns true if this color is white. */
78 	bool isWhite() const;
79 };
80 
81 /** Returns true iff the MapColorCmyk are equal in all components. */
82 bool operator==(const MapColorCmyk& lhs, const MapColorCmyk& rhs);
83 
84 /** Returns true iff the MapColorCmyk differ in at least one components. */
85 bool operator!=(const MapColorCmyk& lhs, const MapColorCmyk& rhs);
86 
87 
88 /**
89  * The MapColorRgb class provides a datatype for storing and transferring
90  * opaque RGB colors.
91  *
92  * Components (r, g, b) are floats in the range [0.0; 1.0].
93  */
94 struct MapColorRgb
95 {
96 	/** The red component. */
97 	float r = 0;
98 	/** The green component. */
99 	float g = 0;
100 	/** The blue component. */
101 	float b = 0;
102 
103 	/** Constructs a black color. */
104 	MapColorRgb() noexcept = default;
105 
106 	/** Constructs a color with the given components. */
107 	MapColorRgb(float r, float g, float b) noexcept;
108 
109 	/** Constructs a copy of the given RGB color. */
110 	MapColorRgb(const MapColorRgb& other) noexcept = default;
111 
112 	/** Constructs a RGB color of the given QColor. Used for type conversions. */
113 	MapColorRgb(const QColor& other) noexcept;
114 
115 	/** Assigns another color's value to this color. */
116 	MapColorRgb& operator=(const MapColorRgb& other) noexcept = default;
117 
118 	/** Converts this color to a QColor. */
119 	operator QColor() const;
120 
121 	/** Returns true if this color is black. */
122 	bool isBlack() const;
123 
124 	/** Returns true if this color is white. */
125 	bool isWhite() const;
126 };
127 
128 /** Returns true if both MapColorRgb are equal in all components. */
129 bool operator==(const MapColorRgb& lhs, const MapColorRgb& rhs);
130 
131 /** Returns true iff the MapColorRgb differ in at least one components. */
132 bool operator!=(const MapColorRgb& lhs, const MapColorRgb& rhs);
133 
134 
135 /**
136  * The SpotColorComponent datatype describes the use of a spot color in a
137  * screen or overprint to create another color.
138  */
139 struct SpotColorComponent
140 {
141 	/** A map color which is a spot color. */
142 	const MapColor* spot_color;
143 
144 	/** The factor describes the halftoning (screen).
145 	 *  It is a value in the range [0.0; 1.0]. */
146 	float factor;
147 
148 	/** Constructs a component with an undefined spot color and halftoning. */
149 	SpotColorComponent();
150 
151 	/** Constructs a component for the given spot color and halftoning. */
152 	SpotColorComponent(const MapColor* spot_color, float factor);
153 
154 	/** Returns true iff the spot color is defined. */
155 	bool isValid() const;
156 };
157 
158 
159 /**
160  * The SpotColorComponents type is a STL container that stores all
161  * SpotColorComponent elements which make up a particular map color.
162  */
163 typedef std::vector<SpotColorComponent> SpotColorComponents;
164 
165 /**
166  * Returns true if for each element in lhs, there is an element of equal color
167  * and factor in rhs. */
168 bool operator==(const SpotColorComponents &lhs, const SpotColorComponents& rhs);
169 
170 
171 /**
172  * The MapColor class provides colors which may be used by symbols (and
173  * objects). Apart from the mere color, it specifies how to output the color
174  * to different type of devices and optionally how the color was composed
175  * from other colors.
176  */
177 class MapColor
178 {
179 public:
180 	/**
181 	 * SpecialProperties provides identifiers for (pseudo-)colors serving
182 	 * particular purposes in the program.
183 	 */
184 	enum SpecialPriorities
185 	{
186 		CoveringRed   = -1005,  ///< Foreground color for tool helper lines
187 		CoveringWhite = -1000,  ///< Background color for tool helper lines
188 		Registration  = -900,   ///< Registration Black: all printed colors
189 		Undefined     = -500,   ///< Color for objects with undefined symbol
190 		Reserved      = -1      ///< Never drawn
191 	};
192 
193 	/**
194 	 * ColorMethod provides identifiers for methods on how to determine a
195 	 * particular realization of a color.
196 	 */
197 	enum ColorMethod
198 	{
199 		UndefinedMethod = 0,
200 		CustomColor     = 1,
201 		SpotColor       = 2,
202 		CmykColor       = 4,
203 		RgbColor        = 8,
204 		Knockout        = 16
205 	};
206 
207 	/** Constructs a black CMYK map color of undefined priority.*/
208 	MapColor();
209 
210 	/** Constructs a black CMYK map color with the given priority. */
211 	MapColor(int priority);
212 
213 	/** Constructs a black CMYK map color with the given name and priority. */
214 	MapColor(const QString& name, int priority);
215 
216 	/** Returns a copy of the color. */
217 	MapColor* duplicate() const;
218 
219 
220 	/** Returns a QColor representation (reference) of the map color.
221 	 *
222 	 * This color is based on the CMYK color unless the CMYK color method is
223 	 * RGB: In that case, the returned value is based on the RGB color.
224 	 */
225 	operator const QColor&() const;
226 
227 	/** Converts the current RGB values to a QRgb. */
228 	operator QRgb() const;
229 
230 
231 	/** Returns the color's name for the mapping context. */
232 	const QString& getName() const;
233 
234 	/** Sets the color's name for the mapping context. */
235 	void setName(const QString& name);
236 
237 	/** Returns the color's priority. */
238 	int getPriority() const;
239 
240 	/**
241 	 * Sets the color's priority.
242 	 * Normally you don't want to call this directly.
243 	 */
244 	void setPriority(int priority);
245 
246 	/** @deprecated Returns the color's opacity. */
247 	float getOpacity() const;
248 
249 	/** @deprecated Sets the color's opacity. */
250 	void setOpacity(float opacity);
251 
252 
253 	/**
254 	 * Returns how the spot color is to be created.
255 	 *
256 	 * Returns UndefinedMethod, SpotColor (for a full tone single color
257 	 * referenced by name), or CustomColor (for a color created from named
258 	 * colors using halftoning (screens) and overprint.
259 	 */
260 	ColorMethod getSpotColorMethod() const;
261 
262 	/**
263 	 * Returns the name for the single spot color or a label for the spot color
264 	 * composition which realizes this map color.
265 	 * Returns an empty string for an UndefinedMethod.
266 	 */
267 	const QString& getSpotColorName() const;
268 
269 	/**
270 	 * Sets the name of a single spot color which realizes this map color,
271 	 * and sets the spot color method to SpotColor.
272 	 */
273 	void setSpotColorName(const QString& spot_color_id);
274 
275 	/**
276 	 * Returns the spot color halftone screen frequency in lines per inch.
277 	 *
278 	 * This value is undefined for spot color methods other than SpotColor.
279 	 */
getScreenFrequency()280 	double getScreenFrequency() const { return screen_frequency; }
281 
282 	/**
283 	 * Sets the spot color halftone screen frequency in lines per inch.
284 	 *
285 	 * A negative or zero value indicates that the halftone screen is undefined.
286 	 *
287 	 * This function does nothing for spot color methods other than SpotColor.
288 	 */
289 	void setScreenFrequency(double value);
290 
291 	/**
292 	 * Returns the spot color halftone screen angle in lines per inch.
293 	 *
294 	 * This value is undefined for spot color methods other than SpotColor.
295 	 */
getScreenAngle()296 	double getScreenAngle() const { return screen_angle; }
297 
298 	/**
299 	 * Sets the spot color halftone screen angle in lines per inch.
300 	 *
301 	 * This function does nothing for spot color methods other than SpotColor.
302 	 */
303 	void setScreenAngle(double value);
304 
305 	/**
306 	 * Sets the given components (i.e. screens and/or overprint) for the color,
307 	 * and sets the spot color method to CustomColor.
308 	 */
309 	void setSpotColorComposition(const SpotColorComponents& components);
310 
311 	/**
312 	 * Returns the components of the spot color realization of this color.
313 	 * Returns an empty list if the spot color method is not CustomColor.
314 	 */
315 	const SpotColorComponents& getComponents() const;
316 
317 	/**
318 	 * Removes a component color.
319 	 *
320 	 * Returns true if components were removed.
321 	 * Returns false if the color was not part of the composition before.
322 	 */
323 	bool removeSpotColorComponent(const MapColor* color);
324 
325 	/**
326 	 * Sets the value of knockout flag for spot color printing.
327 	 *
328 	 * The color must have a spot color definition, or no change will be done.
329 	 */
330 	void setKnockout(bool flag);
331 
332 	/**
333 	 * Returns the value of the knockout flag.
334 	 */
335 	bool getKnockout() const;
336 
337 
338 	/**
339 	 * Returns how the CMYK color value is determined.
340 	 *
341 	 * Returns CustomColor (for custom CMYK values, e.g. for named spot colors),
342 	 * SpotColor (for values determined from evaluation the spot color composition),
343 	 * or RgbColor (for values directly derived from the current RGB values).
344 	 */
345 	ColorMethod getCmykColorMethod() const;
346 
347 	/** Returns the map color's CMYK values. */
348 	const MapColorCmyk& getCmyk() const;
349 
350 	/** Sets the CMYK values, and sets the CMYK color method to CustomColor. */
351 	void setCmyk(const MapColorCmyk& cmyk);
352 
353 	/**
354 	 * Determines the CMYK values from the spot color composition,
355 	 * and sets the CMYK color method to SpotColor.
356 	 *
357 	 * The spot color method must be CustomColor.
358 	 * If the spot color composition is empty, the spot color method is
359 	 * changed to CustomColor, and the CMYK color method is changed to
360 	 * CustomColor.
361 	 */
362 	void setCmykFromSpotColors();
363 
364 	/**
365 	 * Determines the CMYK from the current RGB value,
366 	 * and sets the CMYK color method to RgbColor.
367 	 *
368 	 * If the RGB color method is CmykColor, it is changed to CustomColor.
369 	 */
370 	void setCmykFromRgb();
371 
372 
373 	/**
374 	 * Returns how the RGB color value is determined.
375 	 *
376 	 * Returns CustomColor (for custom RGB values),
377 	 * SpotColor (for values determined from evaluation the spot color composition),
378 	 * or CmykColor (for values directly derived from the current CMYK value).
379 	 */
380 	ColorMethod getRgbColorMethod() const;
381 
382 	/** Returns the map color's RGB values. */
383 	const MapColorRgb& getRgb() const;
384 
385 	/** Sets the RGB values, and sets the RGB color method to CustomColor. */
386 	void setRgb(const MapColorRgb& rgb);
387 
388 	/**
389 	 * Determines the RGB values from the spot color composition,
390 	 * and sets the RGB color method to SpotColor.
391 	 *
392 	 * The spot color method must be CustomColor.
393 	 * If the spot color composition is empty, the spot color method is
394 	 * changed to CustomColor, and the RGB color method is changed to
395 	 * CustomColor.
396 	 */
397 	void setRgbFromSpotColors();
398 
399 	/**
400 	 * Determines the RGB from the current CMYK value,
401 	 * and sets the RGB color method to CmykColor.
402 	 *
403 	 * If the CMYK color method is RgbColor, it is changed to CustomColor.
404 	 */
405 	void setRgbFromCmyk();
406 
407 
408 	/** Returns true if this color is black. */
409 	bool isBlack() const;
410 
411 	/** Returns true if this color is white. */
412 	bool isWhite() const;
413 
414 
415 	/** Compares this color and another, without looking at priorities. */
416 	bool equals(const MapColor& other) const;
417 
418 	/**
419 	 * Compares two colors given by pointers, without looking at priorities.
420 	 *
421 	 * This functions adds handling of `nullptr`:
422 	 * It returns true if the colors are equal or if both pointers are nullptr.
423 	 */
424 	static bool equal(const MapColor* color, const MapColor* other);
425 
426 	/** Returns true if this color's priority is less than the other's. */
427 	bool comparePriority(const MapColor& other) const;
428 
429 protected:
430 	friend bool operator==(const MapColor& lhs, const MapColor& rhs);
431 
432 	/** Compares this color and another. */
433 	bool equals(const MapColor& other, bool compare_priority) const;
434 
435 	/** Compares this color's components and another. */
436 	bool componentsEqual(const MapColor& other, bool compare_priority) const;
437 
438 	/**
439 	 * Determines the composition name from the components.
440 	 *
441 	 * Does nothing it the spot color method is not CustomColor.
442 	 */
443 	void updateCompositionName();
444 
445 	/**
446 	 * Updates all calculated color values.
447 	 *
448 	 * If the spot color method is different from CustomColor, resets CMYK and
449 	 * RGB methods from SpotColor tp CustomColor.
450 	 */
451 	void updateCalculatedColors();
452 
453 	/**
454 	 * Returns a CMYK color determined from the cmyk color of the spot color
455 	 * components.
456 	 */
457 	MapColorCmyk cmykFromSpotColors() const;
458 
459 	/**
460 	 * Returns a RGB color determined from the cmyk color of the spot color
461 	 * components.
462 	 */
463 	MapColorRgb rgbFromSpotColors() const;
464 
465 
466 	QString name;
467 	int priority;
468 
469 	MapColorCmyk cmyk;
470 	MapColorRgb rgb;
471 	float opacity;
472 
473 	QColor q_color;
474 
475 	char spot_color_method;
476 	char cmyk_color_method;
477 	char rgb_color_method;
478 	char flags;
479 
480 	QString spot_color_name;
481 	double screen_frequency = -1;  ///< Halftone screen frequency in lines per inch.
482 	double screen_angle     =  0;  ///< Halftone screen angle in degrees.
483 	SpotColorComponents components;
484 };
485 
486 /** Returns true if both MapColor are equal in all components. */
487 bool operator==(const MapColor& lhs, const MapColor& rhs);
488 
489 /** Returns true iff the MapColor differ in at least one components. */
490 bool operator!=(const MapColor& lhs, const MapColor& rhs);
491 
492 
493 /**
494  * MapColorMap provides a mapping from one map color to another.
495  *
496  * In addition to explicitly user-defined key-value pairs of colors, it will
497  * (in const contexts) map colors with reserved priorities to themselves,
498  * assuming that there is only a single static instance of these colors.
499  */
500 class MapColorMap
501 {
502 public:
503 	/** Constructs a new MapColorMap. */
504 	MapColorMap();
505 
506 	/** Returns the size, i.e. the number of user-defined key-value pairs. */
507 	int size() const;
508 
509 	/** Clears the user-defined key-value pairs. */
510 	void clear();
511 
512 	/** Returns true if there is a user-defined value for the key color */
513 	bool contains(const MapColor* key) const;
514 
515 	/** Returns the mapped value for the key color.
516 	 *
517 	 * Returns the user-defined value for the key color if it is defined.
518 	 * Otherwise, if the key color's priority is from the RESERVED domain,
519 	 * returns key. Otherwise returns nullptr.
520 	 */
521 	const MapColor* value(const MapColor* key) const;
522 
523 	/** Returns the mapped value for the key color. Same as value().
524 	 *
525 	 * Returns the user-defined value for the key color if it is defined.
526 	 * Otherwise, if the key color's priority is from the RESERVED domain,
527 	 * returns key. Otherwise returns nullptr.
528 	 */
529 	const MapColor* operator[](const MapColor* key) const;
530 
531 	/** Returns a reference to pointer to the mapped value for the key color.
532 	 *  If a user-defined mapped value does not exist yet, a default-
533 	 *  constructed mapped value is created first.
534 	 */
535 	const MapColor* & operator[](const MapColor* key);
536 
537 private:
538 	/** The low-level mapping. */
539 	QHash<const MapColor*, const MapColor*> mapping;
540 };
541 
542 
543 /**
544  * Constructs a QColor with the alpha given by opacity from the prototype c.
545  *
546  * A QColor object must be constructible from c.
547  */
548 template <class T>
549 QColor colorWithOpacity(T c, float opacity);
550 
551 /**
552  * Constructs a QColor with opacity from the given MapColor.
553  */
554 QColor colorWithOpacity(const MapColor& c);
555 
556 
557 
558 // ### MapColorCmyk inline code ###
559 
560 inline
MapColorCmyk(float c,float m,float y,float k)561 MapColorCmyk::MapColorCmyk(float c, float m, float y, float k) noexcept
562  : c(c), m(m), y(y), k(k)
563 {
564 	// Nothing
565 }
566 
567 inline
MapColorCmyk(const QColor & other)568 MapColorCmyk::MapColorCmyk(const QColor& other) noexcept
569  : c(other.cyanF()), m(other.magentaF()), y(other.yellowF()), k(other.blackF())
570 {
571 	// Nothing
572 }
573 
574 inline
QColor()575 MapColorCmyk::operator QColor() const
576 {
577 	return QColor::fromCmykF(c, m, y, k);
578 }
579 
580 inline
isBlack()581 bool MapColorCmyk::isBlack() const
582 {
583 	return (1.0 == k) || (1.0 == c && 1.0 == m && 1.0 == y);
584 }
585 
586 inline
isWhite()587 bool MapColorCmyk::isWhite() const
588 {
589 	return (0.0 == c && 0.0 == m && 0.0 == y && 0.0 == k);
590 }
591 
592 inline
593 bool operator==(const MapColorCmyk& lhs, const MapColorCmyk& rhs)
594 {
595 	// The maximum difference of two floating point member values
596 	//  which are regarded as *equal*.
597 	static const float epsilon = 0.0005f;
598 	return ( qAbs(lhs.c - rhs.c) <= epsilon &&
599 	         qAbs(lhs.m - rhs.m) <= epsilon &&
600 	         qAbs(lhs.y - rhs.y) <= epsilon &&
601 	         qAbs(lhs.k - rhs.k) <= epsilon );
602 }
603 
604 inline
605 bool operator!=(const MapColorCmyk& lhs, const MapColorCmyk& rhs)
606 {
607 	return !(lhs == rhs);
608 }
609 
610 
611 // ### MapColorRgb inline code ###
612 
613 inline
MapColorRgb(float r,float g,float b)614 MapColorRgb::MapColorRgb(float r, float g, float b) noexcept
615  : r(r), g(g), b(b)
616 {
617 	// Nothing
618 }
619 
620 inline
MapColorRgb(const QColor & other)621 MapColorRgb::MapColorRgb(const QColor& other) noexcept
622  : r(other.redF()), g(other.greenF()), b(other.blueF())
623 {
624 	// Nothing
625 }
626 
627 inline
QColor()628 MapColorRgb::operator QColor() const
629 {
630 	return QColor::fromRgbF(r, g, b);
631 }
632 
633 inline
isBlack()634 bool MapColorRgb::isBlack() const
635 {
636 	return (0.0 == r && 0.0 == g && 0.0 == b);
637 }
638 
639 inline
isWhite()640 bool MapColorRgb::isWhite() const
641 {
642 	return (1.0 == r && 1.0 == g && 1.0 == b);
643 }
644 
645 inline
646 bool operator==(const MapColorRgb& lhs, const MapColorRgb& rhs)
647 {
648 	// The maximum difference of two floating point member values
649 	//  which are regarded as *equal*.
650 	static const float epsilon = 0.0005f;
651 	return ( qAbs(lhs.r - rhs.r) <= epsilon &&
652 	         qAbs(lhs.g - rhs.g) <= epsilon &&
653 	         qAbs(lhs.b - rhs.b) <= epsilon );
654 }
655 
656 inline
657 bool operator!=(const MapColorRgb& lhs, const MapColorRgb& rhs)
658 {
659 	return !(lhs == rhs);
660 }
661 
662 
663 // ### SpotColorComponent inline code ###
664 
665 inline
SpotColorComponent()666 SpotColorComponent::SpotColorComponent()
667  : spot_color(nullptr),
668    factor(0.0f)
669 {
670 	// Nothing
671 }
672 
673 inline
SpotColorComponent(const MapColor * spot_color,float factor)674 SpotColorComponent::SpotColorComponent(const MapColor* spot_color, float factor)
675  : spot_color(spot_color),
676    factor(factor)
677 {
678 	// Nothing
679 }
680 
681 inline
isValid()682 bool SpotColorComponent::isValid() const
683 {
684 	return spot_color;
685 }
686 
687 
688 // ### MapColor inline code ###
689 
690 inline
691 MapColor::operator const QColor&() const
692 {
693 	return q_color;
694 }
695 
696 inline
QRgb()697 MapColor::operator QRgb() const
698 {
699 	return qRgba(qFloor(255.9 * rgb.r), qFloor(255.9 * rgb.g), qFloor(255.9 * rgb.b), qFloor(255.9 * opacity));
700 }
701 
702 inline
getName()703 const QString& MapColor::getName() const
704 {
705 	return name;
706 }
707 
708 inline
setName(const QString & name)709 void MapColor::setName(const QString& name)
710 {
711 	this->name = name;
712 }
713 
714 inline
getPriority()715 int MapColor::getPriority() const
716 {
717 	return priority;
718 }
719 
720 inline
setPriority(int priority)721 void MapColor::setPriority(int priority)
722 {
723 	this->priority = priority;
724 }
725 
726 inline
getOpacity()727 float MapColor::getOpacity() const
728 {
729 	return opacity;
730 }
731 
732 inline
setOpacity(float opacity)733 void MapColor::setOpacity(float opacity)
734 {
735 	this->opacity = opacity;
736 }
737 
738 inline
getSpotColorMethod()739 MapColor::ColorMethod MapColor::getSpotColorMethod() const
740 {
741 	return (ColorMethod)spot_color_method;
742 }
743 
744 inline
getSpotColorName()745 const QString& MapColor::getSpotColorName() const
746 {
747 	return spot_color_name;
748 }
749 
750 inline
getComponents()751 const SpotColorComponents& MapColor::getComponents() const
752 {
753 	return components;
754 }
755 
756 inline
getCmykColorMethod()757 MapColor::ColorMethod MapColor::getCmykColorMethod() const
758 {
759 	return (ColorMethod)cmyk_color_method;
760 }
761 
762 inline
getCmyk()763 const MapColorCmyk& MapColor::getCmyk() const
764 {
765 	return cmyk;
766 }
767 
768 inline
getRgbColorMethod()769 MapColor::ColorMethod MapColor::getRgbColorMethod() const
770 {
771 	return (ColorMethod)rgb_color_method;
772 }
773 
774 inline
getRgb()775 const MapColorRgb& MapColor::getRgb() const
776 {
777 	return rgb;
778 }
779 
780 inline
comparePriority(const MapColor & other)781 bool MapColor::comparePriority(const MapColor& other) const
782 {
783 	return priority < other.priority;
784 }
785 
786 inline
equal(const MapColor * color,const MapColor * other)787 bool MapColor::equal(const MapColor* color, const MapColor* other)
788 {
789 	if (color == other)
790 		return true;
791 	else if (color && other)
792 		return color->equals(*other, false);
793 	else
794 		return false;
795 }
796 
797 inline
798 bool operator==(const MapColor& lhs, const MapColor& rhs)
799 {
800 	return lhs.equals(rhs, true);
801 }
802 
803 inline
804 bool operator!=(const MapColor& lhs, const MapColor& rhs)
805 {
806 	return !(lhs == rhs);
807 }
808 
809 
810 // ### MapColorMap inline code ###
811 
812 inline
MapColorMap()813 MapColorMap::MapColorMap()
814  : mapping()
815 {
816 	// Nothing.
817 }
818 
819 inline
size()820 int MapColorMap::size() const
821 {
822 	return mapping.size();
823 }
824 
825 inline
clear()826 void MapColorMap::clear()
827 {
828 	mapping.clear();
829 }
830 
831 inline
contains(const MapColor * key)832 bool MapColorMap::contains(const MapColor* key) const
833 {
834 	return mapping.contains(key);
835 }
836 
837 inline
value(const MapColor * key)838 const MapColor* MapColorMap::value(const MapColor* key) const
839 {
840 	if (mapping.contains(key))
841 	{
842 		return mapping.value(key);
843 	}
844 	else if (key && key->getPriority() < 0)
845 	{
846 		return key;
847 	}
848 	else
849 	{
850 		return nullptr;
851 	}
852 }
853 
854 inline
855 const MapColor* MapColorMap::operator[](const MapColor* key) const
856 {
857 	return value(key);
858 }
859 
860 inline
861 const MapColor* & MapColorMap::operator[](const MapColor* key)
862 {
863 	return mapping[key];
864 }
865 
866 template <class T>
colorWithOpacity(T c,float opacity)867 QColor colorWithOpacity(T c, float opacity)
868 {
869 	auto color = static_cast<QColor>(c);
870 	color.setAlphaF(opacity);
871 	return color;
872 }
873 
874 inline
colorWithOpacity(const MapColor & c)875 QColor colorWithOpacity(const MapColor& c)
876 {
877 	return colorWithOpacity(static_cast<const QColor&>(c), c.getOpacity());
878 }
879 
880 
881 }  // namespace OpenOrienteering
882 
883 
884 // Allow explicit use of MapColor pointers in QVariant
885 Q_DECLARE_METATYPE(const OpenOrienteering::MapColor*)
886 
887 
888 #endif
889