KiCad PCB EDA Suite
Loading...
Searching...
No Matches
color4d.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KICAD, a free EDA CAD application.
3 *
4 * Copyright 2012 Torsten Hueter, torstenhtr <at> gmx.de
5 * Copyright 2017-2023 Kicad Developers, see AUTHORS.txt for contributors.
6 *
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include <map>
27#include <nlohmann/json.hpp>
28#include <gal/color4d.h>
29#include <i18n_utility.h>
30#include <wx/crt.h>
31#include <math/util.h>
32#include <core/kicad_algo.h>
33
34using namespace KIGFX;
35
36#define TS( string ) wxString( _HKI( string ) ).ToStdString()
37
38// We can't have this as a plain static variable, because it is referenced during the initialization
39// of other static variables, so we must initialize it explicitly on first use.
41{
42 static StructColors s_ColorRefs[NBCOLORS] =
43 {
44 { 0, 0, 0, BLACK, TS( "Black" ), DARKDARKGRAY },
45 { 72, 72, 72, DARKDARKGRAY, TS( "Gray 1" ), DARKGRAY },
46 { 132, 132, 132, DARKGRAY, TS( "Gray 2" ), LIGHTGRAY },
47 { 194, 194, 194, LIGHTGRAY, TS( "Gray 3" ), WHITE },
48 { 255, 255, 255, WHITE, TS( "White" ), WHITE },
49 { 194, 255, 255, LIGHTYELLOW, TS( "L.Yellow" ), WHITE },
50 { 191, 229, 255, LIGHTERORANGE, TS( "L.Orange" ), WHITE },
51 { 72, 0, 0, DARKBLUE, TS( "Blue 1" ), BLUE },
52 { 0, 72, 0, DARKGREEN, TS( "Green 1" ), GREEN },
53 { 72, 72, 0, DARKCYAN, TS( "Cyan 1" ), CYAN },
54 { 0, 0, 72, DARKRED, TS( "Red 1" ), RED },
55 { 72, 0, 72, DARKMAGENTA, TS( "Magenta 1" ), MAGENTA },
56 { 0, 72, 72, DARKBROWN, TS( "Brown 1" ), BROWN },
57 { 0, 77, 128, DARKORANGE, TS( "Orange 1" ), ORANGE },
58 { 132, 0, 0, BLUE, TS( "Blue 2" ), LIGHTBLUE },
59 { 0, 132, 0, GREEN, TS( "Green 2" ), LIGHTGREEN },
60 { 132, 132, 0, CYAN, TS( "Cyan 2" ), LIGHTCYAN },
61 { 0, 0, 132, RED, TS( "Red 2" ), LIGHTRED },
62 { 132, 0, 132, MAGENTA, TS( "Magenta 2" ), LIGHTMAGENTA },
63 { 0, 132, 132, BROWN, TS( "Brown 2" ), YELLOW },
64 { 0, 102, 204, ORANGE, TS( "Orange 2" ), LIGHTORANGE },
65 { 194, 0, 0, LIGHTBLUE, TS( "Blue 3" ), PUREBLUE, },
66 { 0, 194, 0, LIGHTGREEN, TS( "Green 3" ), PUREGREEN },
67 { 194, 194, 0, LIGHTCYAN, TS( "Cyan 3" ), PURECYAN },
68 { 0, 0, 194, LIGHTRED, TS( "Red 3" ), PURERED },
69 { 194, 0, 194, LIGHTMAGENTA, TS( "Magenta 3" ), PUREMAGENTA },
70 { 0, 194, 194, YELLOW, TS( "Yellow 3" ), PUREYELLOW },
71 { 0, 133, 221, LIGHTORANGE, TS( "Orange 3" ), PUREORANGE },
72 { 255, 0, 0, PUREBLUE, TS( "Blue 4" ), WHITE },
73 { 0, 255, 0, PUREGREEN, TS( "Green 4" ), WHITE },
74 { 255, 255, 0, PURECYAN, TS( "Cyan 4" ), WHITE },
75 { 0, 0, 255, PURERED, TS( "Red 4" ), WHITE },
76 { 255, 0, 255, PUREMAGENTA, TS( "Magenta 4" ), WHITE },
77 { 0, 255, 255, PUREYELLOW, TS( "Yellow 4" ), WHITE },
78 { 0, 153, 255, PUREORANGE, TS( "Orange 4" ), WHITE },
79 };
80 return s_ColorRefs;
81}
82
83
85{
86 if( aColor <= UNSPECIFIED_COLOR || aColor >= NBCOLORS )
87 {
89 return;
90 }
91
92 int candidate = 0;
93
94 for( ; candidate < NBCOLORS; ++candidate )
95 {
96 if( colorRefs()[candidate].m_Numcolor == aColor )
97 break;
98 }
99
100 if( candidate >= NBCOLORS )
101 {
102 *this = COLOR4D::UNSPECIFIED;
103 return;
104 }
105
106 r = colorRefs()[candidate].m_Red / 255.0;
107 g = colorRefs()[candidate].m_Green / 255.0;
108 b = colorRefs()[candidate].m_Blue / 255.0;
109 a = 1.0;
110}
111
112
113COLOR4D::COLOR4D( const wxString& aColorStr )
114{
115 if( !SetFromHexString( aColorStr ) )
116 SetFromWxString( aColorStr );
117}
118
119
120COLOR4D::COLOR4D( const wxColour& aColor )
121{
122 r = aColor.Red() / 255.0;
123 g = aColor.Green() / 255.0;
124 b = aColor.Blue() / 255.0;
125 a = aColor.Alpha() / 255.0;
126}
127
128
129bool COLOR4D::SetFromWxString( const wxString& aColorString )
130{
131 wxColour c;
132
133 if( c.Set( aColorString ) )
134 {
135 r = c.Red() / 255.0;
136 g = c.Green() / 255.0;
137 b = c.Blue() / 255.0;
138 a = c.Alpha() / 255.0;
139
140 return true;
141 }
142
143 return false;
144}
145
146
147wxString COLOR4D::ToCSSString() const
148{
149 wxColour c = ToColour();
150 wxString str;
151
152 const int red = c.Red();
153 const int green = c.Green();
154 const int blue = c.Blue();
155 const int alpha = c.Alpha();
156
157 if ( alpha == wxALPHA_OPAQUE )
158 {
159 str.Printf( wxT( "rgb(%d, %d, %d)" ), red, green, blue );
160 }
161 else // use rgba() form
162 {
163 wxString alpha_str = wxString::FromCDouble( alpha / 255.0, 3 );
164
165 // The wxC2S_CSS_SYNTAX is particularly sensitive to ','s (as it uses them for value
166 // delimiters), and wxWidgets is known to be buggy in this respect when dealing with
167 // Serbian and Russian locales (at least), so we enforce an extra level of safety.
168 alpha_str.Replace( wxT( "," ), wxT( "." ) );
169
170 str.Printf( wxT( "rgba(%d, %d, %d, %s)" ), red, green, blue, alpha_str );
171 }
172
173 return str;
174}
175
176
177bool COLOR4D::SetFromHexString( const wxString& aColorString )
178{
179 wxString str = aColorString;
180 str.Trim( true );
181 str.Trim( false );
182
183 if( str.length() < 7 || !str.StartsWith( '#' ) )
184 return false;
185
186 unsigned long tmp;
187
188 if( wxSscanf( str.wx_str() + 1, wxT( "%lx" ), &tmp ) != 1 )
189 return false;
190
191 if( str.length() >= 9 )
192 {
193 r = ( (tmp >> 24) & 0xFF ) / 255.0;
194 g = ( (tmp >> 16) & 0xFF ) / 255.0;
195 b = ( (tmp >> 8) & 0xFF ) / 255.0;
196 a = ( tmp & 0xFF ) / 255.0;
197 }
198 else
199 {
200 r = ( (tmp >> 16) & 0xFF ) / 255.0;
201 g = ( (tmp >> 8) & 0xFF ) / 255.0;
202 b = ( tmp & 0xFF ) / 255.0;
203 a = 1.0;
204 }
205
206 return true;
207}
208
209
210wxString COLOR4D::ToHexString() const
211{
212 return wxString::Format( wxT("#%02X%02X%02X%02X" ),
213 KiROUND( r * 255.0 ),
214 KiROUND( g * 255.0 ),
215 KiROUND( b * 255.0 ),
216 KiROUND( a * 255.0 ) );
217}
218
219
220wxColour COLOR4D::ToColour() const
221{
222 using CHAN_T = wxColourBase::ChannelType;
223
224 const wxColour colour(
225 static_cast<CHAN_T>( r * 255 + 0.5 ), static_cast<CHAN_T>( g * 255 + 0.5 ),
226 static_cast<CHAN_T>( b * 255 + 0.5 ), static_cast<CHAN_T>( a * 255 + 0.5 ) );
227 return colour;
228}
229
230
231COLOR4D COLOR4D::LegacyMix( const COLOR4D& aColor ) const
232{
233 COLOR4D candidate;
234
235 // Blend the two colors (i.e. OR the RGB values)
236 candidate.r = ( (unsigned) ( 255.0 * r ) | (unsigned) ( 255.0 * aColor.r ) ) / 255.0,
237 candidate.g = ( (unsigned) ( 255.0 * g ) | (unsigned) ( 255.0 * aColor.g ) ) / 255.0,
238 candidate.b = ( (unsigned) ( 255.0 * b ) | (unsigned) ( 255.0 * aColor.b ) ) / 255.0,
239
240 // the alpha channel can be reinitialized but what is the best value?
241 candidate.a = ( aColor.a + a ) / 2;
242
243 return candidate;
244}
245
246
247namespace KIGFX {
248
249bool operator==( const COLOR4D& lhs, const COLOR4D& rhs )
250{
251 return lhs.a == rhs.a && lhs.r == rhs.r && lhs.g == rhs.g && lhs.b == rhs.b;
252}
253
254
255bool operator!=( const COLOR4D& lhs, const COLOR4D& rhs )
256{
257 return !( lhs == rhs );
258}
259
260
261bool operator<( const COLOR4D& lhs, const COLOR4D& rhs )
262{
263 if( lhs.r < rhs.r )
264 return true;
265 else if( lhs.g < rhs.g )
266 return true;
267 else if( lhs.b < rhs.b )
268 return true;
269 else if( lhs.a < rhs.a )
270 return true;
271
272 return false;
273}
274
275
276std::ostream &operator<<( std::ostream &aStream, COLOR4D const &aColor )
277{
278 return aStream << aColor.ToCSSString();
279}
280
281
282void to_json( nlohmann::json& aJson, const COLOR4D& aColor )
283{
284 aJson = nlohmann::json( aColor.ToCSSString().ToStdString() );
285}
286
287
288void from_json( const nlohmann::json& aJson, COLOR4D& aColor )
289{
290 aColor.SetFromWxString( aJson.get<std::string>() );
291}
292
293}
294
295
296void COLOR4D::ToHSL( double& aOutHue, double& aOutSaturation, double& aOutLightness ) const
297{
298 auto min = std::min( r, std::min( g, b ) );
299 auto max = std::max( r, std::max( g, b ) );
300 auto diff = max - min;
301
302 aOutLightness = ( max + min ) / 2.0;
303
304 if( aOutLightness >= 1.0 )
305 aOutSaturation = 0.0;
306 else
307 aOutSaturation = diff / ( 1.0 - std::abs( 2.0 * aOutLightness - 1.0 ) );
308
309 double hue;
310
311 if( diff <= 0.0 )
312 hue = 0.0;
313 else if( max == r )
314 hue = ( g - b ) / diff;
315 else if( max == g )
316 hue = ( b - r ) / diff + 2.0;
317 else
318 hue = ( r - g ) / diff + 4.0;
319
320 aOutHue = hue > 0.0 ? hue * 60.0 : hue * 60.0 + 360.0;
321
322 while( aOutHue < 0.0 )
323 aOutHue += 360.0;
324}
325
326
327void COLOR4D::FromHSL( double aInHue, double aInSaturation, double aInLightness )
328{
329 const auto P = ( 1.0 - std::abs( 2.0 * aInLightness - 1.0 ) ) * aInSaturation;
330 const auto scaled_hue = aInHue / 60.0;
331 const auto Q = P * ( 1.0 - std::abs( std::fmod( scaled_hue, 2.0 ) - 1.0 ) );
332
333 r = g = b = aInLightness - P / 2.0;
334
335 if (scaled_hue < 1.0)
336 {
337 r += P;
338 g += Q;
339 }
340 else if (scaled_hue < 2.0)
341 {
342 r += Q;
343 g += P;
344 }
345 else if (scaled_hue < 3.0)
346 {
347 g += P;
348 b += Q;
349 }
350 else if (scaled_hue < 4.0)
351 {
352 g += Q;
353 b += P;
354 }
355 else if (scaled_hue < 5.0)
356 {
357 r += Q;
358 b += P;
359 }
360 else
361 {
362 r += P;
363 b += Q;
364 }
365}
366
367
368void COLOR4D::ToHSV( double& aOutHue, double& aOutSaturation, double& aOutValue,
369 bool aAlwaysDefineHue ) const
370{
371 double min, max, delta;
372
373 min = r < g ? r : g;
374 min = min < b ? min : b;
375
376 max = r > g ? r : g;
377 max = max > b ? max : b;
378
379 aOutValue = max; // value
380 delta = max - min;
381
382 if( max > 0.0 )
383 {
384 aOutSaturation = ( delta / max );
385 }
386 else // for black color (r = g = b = 0 ) saturation is set to 0.
387 {
388 aOutSaturation = 0.0;
389 aOutHue = aAlwaysDefineHue ? 0.0 : NAN;
390 return;
391 }
392
393 /* Hue in degrees (0...360) is coded according to this table
394 * 0 or 360 : red
395 * 60 : yellow
396 * 120 : green
397 * 180 : cyan
398 * 240 : blue
399 * 300 : magenta
400 */
401 if( delta != 0.0 )
402 {
403 if( r >= max )
404 aOutHue = ( g - b ) / delta; // between yellow & magenta
405 else if( g >= max )
406 aOutHue = 2.0 + ( b - r ) / delta; // between cyan & yellow
407 else
408 aOutHue = 4.0 + ( r - g ) / delta; // between magenta & cyan
409
410 aOutHue *= 60.0; // degrees
411
412 if( aOutHue < 0.0 )
413 aOutHue += 360.0;
414 }
415 else // delta = 0 means r = g = b. hue is set to 0.0
416 {
417 aOutHue = aAlwaysDefineHue ? 0.0 : NAN;
418 }
419}
420
421
422void COLOR4D::FromHSV( double aInH, double aInS, double aInV )
423{
424 if( aInS <= 0.0 )
425 {
426 r = aInV;
427 g = aInV;
428 b = aInV;
429 return;
430 }
431
432 double hh = aInH;
433
434 while( hh >= 360.0 )
435 hh -= 360.0;
436
437 /* Hue in degrees (0...360) is coded according to this table
438 * 0 or 360 : red
439 * 60 : yellow
440 * 120 : green
441 * 180 : cyan
442 * 240 : blue
443 * 300 : magenta
444 */
445 hh /= 60.0;
446
447 int i = (int) hh;
448 double ff = hh - i;
449
450 double p = aInV * ( 1.0 - aInS );
451 double q = aInV * ( 1.0 - ( aInS * ff ) );
452 double t = aInV * ( 1.0 - ( aInS * ( 1.0 - ff ) ) );
453
454 switch( i )
455 {
456 case 0:
457 r = aInV;
458 g = t;
459 b = p;
460 break;
461
462 case 1:
463 r = q;
464 g = aInV;
465 b = p;
466 break;
467
468 case 2:
469 r = p;
470 g = aInV;
471 b = t;
472 break;
473
474 case 3:
475 r = p;
476 g = q;
477 b = aInV;
478 break;
479
480 case 4:
481 r = t;
482 g = p;
483 b = aInV;
484 break;
485
486 case 5:
487 default:
488 r = aInV;
489 g = p;
490 b = q;
491 break;
492 }
493}
494
495
496COLOR4D& COLOR4D::Saturate( double aFactor )
497{
498 // One can saturate a color only when r, v, b are not equal
499 if( r == g && r == b )
500 return *this;
501
502 double h, s, v;
503
504 ToHSV( h, s, v, true );
505 FromHSV( h, aFactor, 1.0 );
506
507 return *this;
508}
509
510
512{
513 // One can desaturate a color only when r, v, b are not equal
514 if( r == g && r == b )
515 return *this;
516
517 double h, s, l;
518
519 ToHSL( h, s, l );
520 FromHSL( h, 0.0, l );
521
522 return *this;
523}
524
525
526const COLOR4D COLOR4D::UNSPECIFIED( 0, 0, 0, 0 );
527const COLOR4D COLOR4D::WHITE( 1, 1, 1, 1 );
528const COLOR4D COLOR4D::BLACK( 0, 0, 0, 1 );
529const COLOR4D COLOR4D::CLEAR( 1, 0, 1, 0 );
530
531
532double COLOR4D::Distance( const COLOR4D& other ) const
533{
534 return ( r - other.r ) * ( r - other.r )
535 + ( g - other.g ) * ( g - other.g )
536 + ( b - other.b ) * ( b - other.b );
537}
538
539
541{
542 EDA_COLOR_T candidate = EDA_COLOR_T::BLACK;
543
544 /* Find the 'nearest' color in the palette. This is fun. There is
545 a gazilion of metrics for the color space and no one of the
546 useful one is in the RGB color space. Who cares, this is a CAD,
547 not a photosomething...
548
549 I hereby declare that the distance is the sum of the square of the
550 component difference. Think about the RGB color cube. Now get the
551 euclidean distance, but without the square root... for ordering
552 purposes it's the same, obviously. Also each component can't be
553 less of the target one, since I found this currently work better...
554 */
555 int nearest_distance = 255 * 255 * 3 + 1; // Can't beat this
556
557 for( EDA_COLOR_T trying = EDA_COLOR_T::BLACK; trying < EDA_COLOR_T::NBCOLORS;
558 trying = static_cast<EDA_COLOR_T>( int( trying ) + 1 ) )
559 {
560 const StructColors &c = colorRefs()[trying];
561 int distance = ( aR - c.m_Red ) * ( aR - c.m_Red ) +
562 ( aG - c.m_Green ) * ( aG - c.m_Green ) +
563 ( aB - c.m_Blue ) * ( aB - c.m_Blue );
564
565 if( distance < nearest_distance && c.m_Red >= aR &&
566 c.m_Green >= aG && c.m_Blue >= aB )
567 {
568 nearest_distance = distance;
569 candidate = trying;
570 }
571 }
572
573 return candidate;
574}
575
576
577COLOR4D& COLOR4D::FromCSSRGBA( int aRed, int aGreen, int aBlue, double aAlpha )
578{
579 r = std::clamp( aRed, 0, 255 ) / 255.0;
580 g = std::clamp( aGreen, 0, 255 ) / 255.0;
581 b = std::clamp( aBlue, 0, 255 ) / 255.0;
582 a = std::clamp( aAlpha, 0.0, 1.0 );
583
584 return *this;
585}
586
587
588int COLOR4D::Compare( const COLOR4D& aRhs ) const
589{
590 if( r != aRhs.r )
591 return ( r < aRhs.r ) ? -1 : 1;
592
593 if( g != aRhs.g )
594 return ( g < aRhs.g ) ? -1 : 1;
595
596 if( b != aRhs.b )
597 return ( b < aRhs.b ) ? -1 : 1;
598
599 if( a != aRhs.a )
600 return ( a < aRhs.a ) ? -1 : 1;
601
602 return 0;
603}
604
605
607{
608 // Formula from https://www.w3.org/TR/WCAG21/#dfn-relative-luminance
609 double cr = ( r <= 0.04045 ) ? ( r / 12.92 ) : std::pow( ( r + 0.055 ) / 1.055, 2.4 );
610 double cg = ( g <= 0.04045 ) ? ( g / 12.92 ) : std::pow( ( g + 0.055 ) / 1.055, 2.4 );
611 double cb = ( b <= 0.04045 ) ? ( b / 12.92 ) : std::pow( ( b + 0.055 ) / 1.055, 2.4 );
612
613 return 0.2126 * cr + 0.7152 * cg + 0.0722 * cb;
614}
615
616
617double COLOR4D::ContrastRatio( const COLOR4D& aLeft, const COLOR4D& aRight )
618{
619 // Formula from https://www.w3.org/TR/WCAG21/#dfn-contrast-ratio
620 double aRL = aLeft.RelativeLuminance();
621 double bRL = aRight.RelativeLuminance();
622
623 if( aRL > bRL )
624 return ( aRL + 0.05 ) / ( bRL + 0.05 );
625 else
626 return ( bRL + 0.05 ) / ( aRL + 0.05 );
627}
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition: box2.h:990
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
double r
Red component.
Definition: color4d.h:392
double g
Green component.
Definition: color4d.h:393
static const COLOR4D CLEAR
Definition: color4d.h:403
void ToHSV(double &aOutHue, double &aOutSaturation, double &aOutValue, bool aAlwaysDefineHue=false) const
Convert current color (stored in RGB) to HSV format.
Definition: color4d.cpp:368
static double ContrastRatio(const COLOR4D &aLeft, const COLOR4D &aRight)
Compute the contrast ration between two colors using the formula from WCAG21.
Definition: color4d.cpp:617
void ToHSL(double &aOutHue, double &aOutSaturation, double &aOutLightness) const
Converts current color (stored in RGB) to HSL format.
Definition: color4d.cpp:296
bool SetFromWxString(const wxString &aColorString)
Set color values by parsing a string using wxColour::Set().
Definition: color4d.cpp:129
bool SetFromHexString(const wxString &aColorString)
Definition: color4d.cpp:177
COLOR4D LegacyMix(const COLOR4D &aColor) const
Mix this COLOR4D with an input COLOR4D using the OR-mixing of legacy canvas.
Definition: color4d.cpp:231
static EDA_COLOR_T FindNearestLegacyColor(int aR, int aG, int aB)
Returns a legacy color ID that is closest to the given 8-bit RGB values.
Definition: color4d.cpp:540
void FromHSV(double aInH, double aInS, double aInV)
Changes currently used color to the one given by hue, saturation and value parameters.
Definition: color4d.cpp:422
wxString ToHexString() const
Definition: color4d.cpp:210
wxString ToCSSString() const
Definition: color4d.cpp:147
int Compare(const COLOR4D &aRhs) const
Definition: color4d.cpp:588
static const COLOR4D WHITE
Definition: color4d.h:401
double a
Alpha component.
Definition: color4d.h:395
double RelativeLuminance() const
Compute the relative luminance of a color using the formula from WCAG21.
Definition: color4d.cpp:606
wxColour ToColour() const
Definition: color4d.cpp:220
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition: color4d.h:398
COLOR4D & Desaturate()
Removes color (in HSL model)
Definition: color4d.cpp:511
double Distance(const COLOR4D &other) const
Returns the distance (in RGB space) between two colors.
Definition: color4d.cpp:532
void FromHSL(double aInHue, double aInSaturation, double aInLightness)
Change currently used color to the one given by hue, saturation and lightness parameters.
Definition: color4d.cpp:327
static const COLOR4D BLACK
Definition: color4d.h:402
COLOR4D & FromCSSRGBA(int aRed, int aGreen, int aBlue, double aAlpha=1.0)
Initialize the color from a RGBA value with 0-255 red/green/blue and 0-1 alpha.
Definition: color4d.cpp:577
COLOR4D & Saturate(double aFactor)
Saturates the color to a given factor (in HSV model)
Definition: color4d.cpp:496
double b
Blue component.
Definition: color4d.h:394
const StructColors * colorRefs()
Global list of legacy color names, still used all over the place for constructing COLOR4D's.
Definition: color4d.cpp:40
#define TS(string)
Definition: color4d.cpp:36
EDA_COLOR_T
Legacy color enumeration.
Definition: color4d.h:42
@ LIGHTGREEN
Definition: color4d.h:63
@ PUREORANGE
Definition: color4d.h:78
@ BROWN
Definition: color4d.h:61
@ PURECYAN
Definition: color4d.h:70
@ LIGHTBLUE
Definition: color4d.h:62
@ WHITE
Definition: color4d.h:48
@ LIGHTERORANGE
Definition: color4d.h:74
@ LIGHTORANGE
Definition: color4d.h:77
@ BLUE
Definition: color4d.h:56
@ LIGHTGRAY
Definition: color4d.h:47
@ DARKGRAY
Definition: color4d.h:46
@ MAGENTA
Definition: color4d.h:60
@ DARKORANGE
Definition: color4d.h:75
@ DARKMAGENTA
Definition: color4d.h:54
@ LIGHTYELLOW
Definition: color4d.h:49
@ DARKCYAN
Definition: color4d.h:52
@ NBCOLORS
Number of colors.
Definition: color4d.h:79
@ PURERED
Definition: color4d.h:71
@ GREEN
Definition: color4d.h:57
@ CYAN
Definition: color4d.h:58
@ DARKRED
Definition: color4d.h:53
@ DARKBLUE
Definition: color4d.h:50
@ LIGHTCYAN
Definition: color4d.h:64
@ DARKDARKGRAY
Definition: color4d.h:45
@ ORANGE
Definition: color4d.h:76
@ PUREGREEN
Definition: color4d.h:69
@ LIGHTMAGENTA
Definition: color4d.h:66
@ PUREYELLOW
Definition: color4d.h:73
@ YELLOW
Definition: color4d.h:67
@ PUREBLUE
Definition: color4d.h:68
@ LIGHTRED
Definition: color4d.h:65
@ BLACK
Definition: color4d.h:44
@ DARKGREEN
Definition: color4d.h:51
@ PUREMAGENTA
Definition: color4d.h:72
@ RED
Definition: color4d.h:59
@ DARKBROWN
Definition: color4d.h:55
std::ostream & operator<<(std::ostream &aStream, const EDA_TEXT &aText)
Definition: eda_text.cpp:1210
Some functions to handle hotkeys in KiCad.
The Cairo implementation of the graphics abstraction layer.
Definition: color4d.cpp:247
void from_json(const nlohmann::json &aJson, COLOR4D &aColor)
Definition: color4d.cpp:288
bool operator==(const COLOR4D &lhs, const COLOR4D &rhs)
Equality operator, are two colors equal.
Definition: color4d.cpp:249
void to_json(nlohmann::json &aJson, const COLOR4D &aColor)
Definition: color4d.cpp:282
bool operator<(const COLOR4D &lhs, const COLOR4D &rhs)
Definition: color4d.cpp:261
bool operator!=(const COLOR4D &lhs, const COLOR4D &rhs)
Not equality operator, are two colors not equal.
Definition: color4d.cpp:255
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:390
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
unsigned char m_Blue
Definition: color4d.h:86
unsigned char m_Green
Definition: color4d.h:87
unsigned char m_Red
Definition: color4d.h:88
constexpr int delta