summaryrefslogtreecommitdiff
path: root/common/colors.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'common/colors.cpp')
-rw-r--r--common/colors.cpp184
1 files changed, 184 insertions, 0 deletions
diff --git a/common/colors.cpp b/common/colors.cpp
new file mode 100644
index 0000000..0cc6042
--- /dev/null
+++ b/common/colors.cpp
@@ -0,0 +1,184 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2014 Jean-Pierre Charras, jp.charras at wanadoo.fr
+ * Copyright (C) 2014 KiCad Developers, see CHANGELOG.TXT for contributors.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <colors.h>
+#include <i18n_utility.h>
+
+
+/**
+ * The predefined colors used in KiCad.
+ * Please: if you change a value, remember these values are carefully chosen
+ * to have good results in Pcbnew, that uses the ORed value of basic colors
+ * when displaying superimposed objects
+ * This list must have exactly NBCOLORS items
+ */
+
+const StructColors g_ColorRefs[NBCOLORS] =
+{
+ { 0, 0, 0, BLACK, _HKI( "Black" ), DARKDARKGRAY },
+ { 72, 72, 72, DARKDARKGRAY, _HKI( "Gray 1" ), DARKGRAY },
+ { 132, 132, 132, DARKGRAY, _HKI( "Gray 2" ), LIGHTGRAY },
+ { 194, 194, 194, LIGHTGRAY, _HKI( "Gray 3" ), WHITE },
+ { 255, 255, 255, WHITE, _HKI( "White" ), WHITE },
+ { 194, 255, 255, LIGHTYELLOW, _HKI( "L.Yellow" ), WHITE },
+ { 72, 0, 0, DARKBLUE, _HKI( "Blue 1" ), BLUE },
+ { 0, 72, 0, DARKGREEN, _HKI( "Green 1" ), GREEN },
+ { 72, 72, 0, DARKCYAN, _HKI( "Cyan 1" ), CYAN },
+ { 0, 0, 72, DARKRED, _HKI( "Red 1" ), RED },
+ { 72, 0, 72, DARKMAGENTA, _HKI( "Magenta 1" ), MAGENTA },
+ { 0, 72, 72, DARKBROWN, _HKI( "Brown 1" ), BROWN },
+ { 132, 0, 0, BLUE, _HKI( "Blue 2" ), LIGHTBLUE },
+ { 0, 132, 0, GREEN, _HKI( "Green 2" ), LIGHTGREEN },
+ { 132, 132, 0, CYAN, _HKI( "Cyan 2" ), LIGHTCYAN },
+ { 0, 0, 132, RED, _HKI( "Red 2" ), LIGHTRED },
+ { 132, 0, 132, MAGENTA, _HKI( "Magenta 2" ), LIGHTMAGENTA },
+ { 0, 132, 132, BROWN, _HKI( "Brown 2" ), YELLOW },
+ { 194, 0, 0, LIGHTBLUE, _HKI( "Blue 3" ), PUREBLUE, },
+ { 0, 194, 0, LIGHTGREEN, _HKI( "Green 3" ), PUREGREEN },
+ { 194, 194, 0, LIGHTCYAN, _HKI( "Cyan 3" ), PURECYAN },
+ { 0, 0, 194, LIGHTRED, _HKI( "Red 3" ), PURERED },
+ { 194, 0, 194, LIGHTMAGENTA, _HKI( "Magenta 3" ), PUREMAGENTA },
+ { 0, 194, 194, YELLOW, _HKI( "Yellow 3" ), PUREYELLOW },
+ { 255, 0, 0, PUREBLUE, _HKI( "Blue 4" ), WHITE },
+ { 0, 255, 0, PUREGREEN, _HKI( "Green 4" ), WHITE },
+ { 255, 255, 0, PURECYAN, _HKI( "Cyan 4" ), WHITE },
+ { 0, 0, 255, PURERED, _HKI( "Red 4" ), WHITE },
+ { 255, 0, 255, PUREMAGENTA, _HKI( "Magenta 4" ), WHITE },
+ { 0, 255, 255, PUREYELLOW, _HKI( "Yellow 4" ), WHITE },
+};
+
+
+EDA_COLOR_T ColorByName( const wxString& aName )
+{
+ // look for a match in the palette itself
+ for( EDA_COLOR_T trying = BLACK; trying < NBCOLORS; trying = NextColor(trying) )
+ {
+ if( 0 == aName.CmpNoCase( ColorGetName( trying ) ) )
+ return trying;
+ }
+
+ // Not found, no idea...
+ return UNSPECIFIED_COLOR;
+}
+
+
+bool ColorIsLight( EDA_COLOR_T aColor )
+{
+ const StructColors &c = g_ColorRefs[ColorGetBase( aColor )];
+ int r = c.m_Red;
+ int g = c.m_Green;
+ int b = c.m_Blue;
+ return ((r * r) + (g * g) + (b * b)) > (128 * 128 * 3);
+}
+
+
+EDA_COLOR_T ColorFindNearest( const wxColour &aColor )
+{
+ return ColorFindNearest( aColor.Red(), aColor.Green(), aColor.Blue() );
+}
+
+
+EDA_COLOR_T ColorFindNearest( int aR, int aG, int aB )
+{
+ EDA_COLOR_T candidate = BLACK;
+
+ /* Find the 'nearest' color in the palette. This is fun. There is
+ a gazilion of metrics for the color space and no one of the
+ useful one is in the RGB color space. Who cares, this is a CAD,
+ not a photosomething...
+
+ I hereby declare that the distance is the sum of the square of the
+ component difference. Think about the RGB color cube. Now get the
+ euclidean distance, but without the square root... for ordering
+ purposes it's the same, obviously. Also each component can't be
+ less of the target one, since I found this currently work better...
+ */
+ int nearest_distance = 255 * 255 * 3 + 1; // Can't beat this
+
+ for( EDA_COLOR_T trying = BLACK; trying < NBCOLORS; trying = NextColor(trying) )
+ {
+ const StructColors &c = g_ColorRefs[trying];
+ int distance = (aR - c.m_Red) * (aR - c.m_Red) +
+ (aG - c.m_Green) * (aG - c.m_Green) +
+ (aB - c.m_Blue) * (aB - c.m_Blue);
+
+ if( distance < nearest_distance && c.m_Red >= aR &&
+ c.m_Green >= aG && c.m_Blue >= aB )
+ {
+ nearest_distance = distance;
+ candidate = trying;
+ }
+ }
+
+ return candidate;
+}
+
+
+EDA_COLOR_T ColorMix( EDA_COLOR_T aColor1, EDA_COLOR_T aColor2 )
+{
+ /* Memoization storage. This could be potentially called for each
+ * color merge so a cache is useful (there are few colours anyway) */
+ static EDA_COLOR_T mix_cache[NBCOLORS][NBCOLORS];
+
+ // TODO how is alpha used? it's a mac only thing, I have no idea
+ aColor1 = ColorGetBase( aColor1 );
+ aColor2 = ColorGetBase( aColor2 );
+
+ // First easy thing: a black gives always the other colour
+ if( aColor1 == BLACK )
+ return aColor2;
+
+ if( aColor2 == BLACK)
+ return aColor1;
+
+ /* Now we are sure that black can't occur, so the rule is:
+ * BLACK means not computed yet. If we're lucky we already have
+ * an answer */
+ EDA_COLOR_T candidate = mix_cache[aColor1][aColor2];
+
+ if( candidate != BLACK )
+ return candidate;
+
+ // Blend the two colors (i.e. OR the RGB values)
+ const StructColors &c1 = g_ColorRefs[aColor1];
+ const StructColors &c2 = g_ColorRefs[aColor2];
+
+ // Ask the palette for the nearest color to the mix
+ wxColour mixed( c1.m_Red | c2.m_Red,
+ c1.m_Green | c2.m_Green,
+ c1.m_Blue | c2.m_Blue );
+ candidate = ColorFindNearest( mixed );
+
+ /* Here, BLACK is *not* a good answer, since it would recompute the next time.
+ * Even theorically its not possible (with the current rules), but
+ * maybe the metric will change in the future */
+ if( candidate == BLACK )
+ candidate = DARKDARKGRAY;
+
+ // Store the result in the cache. The operation is commutative, too
+ mix_cache[aColor1][aColor2] = candidate;
+ mix_cache[aColor2][aColor1] = candidate;
+ return candidate;
+}
+