banshee r4451 - in trunk/banshee: . src/Libraries/Hyena.Gui src/Libraries/Hyena.Gui/Hyena.Gui src/Libraries/Hyena.Gui/Hyena.Gui.Theming



Author: abock
Date: Tue Sep  2 18:33:14 2008
New Revision: 4451
URL: http://svn.gnome.org/viewvc/banshee?rev=4451&view=rev

Log:
2008-09-02  Aaron Bockover  <abock gnome org>

    * src/Libraries/Hyena.Gui/Hyena.Gui.Theming/GtkTheme.cs: Change
    GetCairoTextMidColor to use AlphaBlend function (BGO #544840)

    * src/Libraries/Hyena.Gui/Hyena.Gui/CairoExtensions.cs: Implemented simple
    color alpha blending utility [P=(1-a)P_0 + aP_1]

    * src/Libraries/Hyena.Gui/Hyena.Gui/Contrast.cs: Add some color contrast
    utilities, copied from Tomboy and modified to work with Cairo colors



Added:
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui/Contrast.cs
Modified:
   trunk/banshee/ChangeLog
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.Theming/GtkTheme.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.mdp
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui/CairoExtensions.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Makefile.am

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.Theming/GtkTheme.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.Theming/GtkTheme.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.Theming/GtkTheme.cs	Tue Sep  2 18:33:14 2008
@@ -45,10 +45,7 @@
         {
             Cairo.Color text_color = CairoExtensions.GdkColorToCairoColor (widget.Style.Foreground (StateType.Normal));
             Cairo.Color background_color = CairoExtensions.GdkColorToCairoColor (widget.Style.Background (StateType.Normal));
-            // This is lame
-            Cairo.Color c = CairoExtensions.ColorAdjustBrightness (text_color, 
-                CairoExtensions.ColorIsDark (background_color) ? 0.65 : 0.5);
-            return c;
+            return CairoExtensions.AlphaBlend (text_color, background_color, 0.5);
         }
         
         public static Gdk.Color GetGdkTextMidColor (Widget widget)

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.mdp
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.mdp	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui.mdp	Tue Sep  2 18:33:14 2008
@@ -84,6 +84,7 @@
     <File name="Hyena.Gui/RatingRenderer.cs" subtype="Code" buildaction="Compile" />
     <File name="Hyena.Data.Gui/ListView/ListViewBase.cs" subtype="Code" buildaction="Compile" />
     <File name="Hyena.Gui/GtkWorkarounds.cs" subtype="Code" buildaction="Compile" />
+    <File name="Hyena.Gui/Contrast.cs" subtype="Code" buildaction="Compile" />
   </Contents>
   <References>
     <ProjectReference type="Gac" localcopy="True" refto="System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui/CairoExtensions.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui/CairoExtensions.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui/CairoExtensions.cs	Tue Sep  2 18:33:14 2008
@@ -74,7 +74,15 @@
             ((IDisposable)surface_cr).Dispose ();
             return surface;
         }
-    
+        
+        public static Cairo.Color AlphaBlend (Cairo.Color ca, Cairo.Color cb, double alpha)
+        {
+            return new Cairo.Color (
+                (1.0 - alpha) * ca.R + alpha * cb.R,
+                (1.0 - alpha) * ca.G + alpha * cb.G,
+                (1.0 - alpha) * ca.B + alpha * cb.B);
+        }
+        
         public static Cairo.Color GdkColorToCairoColor(Gdk.Color color)
         {
             return GdkColorToCairoColor(color, 1.0);

Added: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui/Contrast.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui/Contrast.cs	Tue Sep  2 18:33:14 2008
@@ -0,0 +1,331 @@
+//
+// Contrast.cs
+//
+// Authors:
+//   David Trowbridge
+//   Sebastian DrÃge <slomo circular-chaos org>
+//
+// Copyright (C) 2006-2007 David Trowbridge
+// Copyright (C) 2008 Sebastian DrÃge
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using Cairo;
+
+namespace Hyena.Gui
+{
+    /* Defined colors.  Keep this list alphabetized if you add new ones,
+     * but set the enum value to be at the end of the color_regions table
+     * in contrast.c to maintain binary compatibility
+     */
+    
+    public enum ContrastPaletteColor
+    {
+        Aqua        =  0,
+        Black       =  1,
+        Blue        =  2,
+        Brown       =  3,
+        Cyan        =  4,
+        DarkBlue    =  5,
+        DarkGreen   =  6,
+        DarkGrey    =  7,
+        DarkRed     =  8,
+        Green       =  9,
+        Grey        = 10,
+        LightBlue   = 11,
+        LightBrown  = 12,
+        LightGreen  = 13,
+        LightGrey   = 14,
+        LightRed    = 15,
+        Magenta     = 16,
+        Orange      = 17,
+        Purple      = 18,
+        Red         = 19,
+        Violet      = 20,
+        White       = 21,
+        Yellow      = 22,
+        Last        = 23
+    };
+    
+    public static class Contrast
+    {
+    
+        /* Data for color palette optimization.
+         * 
+         * These numbers are completely arbitrary decisions, uninformed by the experts
+         * at crayola.  These colors are defined as boxes within the CIE L*a*b* color
+         * space -- while they're not fully inclusive, they are "safe" in that anywhere
+         * within a given region is guaranteed to be the expected color.  The data here
+         * are endpoints in each dimension of CIELAB, from which the 8 corners of the
+         * region are created to test.
+         *
+         * Add new entries to the end of this list.
+         */
+        private static readonly float[,] color_regions = {
+            {40.0f,  60.0f, -100.0f, -80.0f,  -10.0f,  20.0f}, /* Aqua */
+            { 0.0f,  30.0f,    0.0f,   0.0f,    0.0f,   0.0f}, /* Black */
+            {25.0f,  35.0f, -100.0f,   0.0f, -100.0f, -50.0f}, /* Blue */
+            {30.0f,  60.0f,   30.0f,  50.0f,   70.0f, 100.0f}, /* Brown */
+            {50.0f,  65.0f, -100.0f, -30.0f, -100.0f, -50.0f}, /* Cyan */
+            { 0.0f,  20.0f,  -40.0f,  50.0f, -100.0f, -60.0f}, /* Dark Blue */
+            {20.0f,  35.0f, -100.0f, -70.0f,   60.0f, 100.0f}, /* Dark Green */
+            {20.0f,  40.0f,    0.0f,   0.0f,    0.0f,   0.0f}, /* Dark Grey */
+            {10.0f,  40.0f,   90.0f, 100.0f,   70.0f, 100.0f}, /* Dark Red */
+            {15.0f,  40.0f, -100.0f, -80.0f,   80.0f, 100.0f}, /* Green */
+            {35.0f,  60.0f,    0.0f,   0.0f,    0.0f,   0.0f}, /* Grey */
+            {40.0f,  50.0f, -100.0f,   0.0f, -100.0f, -60.0f}, /* Light Blue */
+            {60.0f,  75.0f,   30.0f,  50.0f,   80.0f, 100.0f}, /* Light Brown */
+            {80.0f,  90.0f, -100.0f, -70.0f,   70.0f, 100.0f}, /* Light Green */
+            {50.0f,  80.0f,    0.0f,   0.0f,    0.0f,   0.0f}, /* Light Grey */
+            {55.0f,  65.0f,   80.0f,  90.0f,   75.0f, 100.0f}, /* Light Red */
+            {40.0f,  55.0f,   90.0f, 100.0f,  -50.0f,   0.0f}, /* Magenta */
+            {65.0f,  80.0f,   20.0f,  65.0f,   90.0f, 100.0f}, /* Orange */
+            {35.0f,  45.0f,   85.0f, 100.0f,  -90.0f, -80.0f}, /* Purple */
+            {40.0f,  50.0f,   80.0f, 100.0f,   75.0f, 100.0f}, /* Red */
+            {70.0f,  95.0f,   90.0f, 100.0f, -100.0f,   0.0f}, /* Violet */
+            {75.0f, 100.0f,    0.0f,   0.0f,    0.0f,   0.0f}, /* White */
+            {90.0f, 100.0f,    5.0f,  15.0f,   92.5f, 105.0f}, /* Yellow */
+        };
+
+        /* This performs the non-linear transformation that accounts for the gamma curve
+         * in sRGB, but avoids numerical problems.
+         */
+
+        private static float srgb_to_xyz_g (float K)
+        {
+            const float a     = 0.055f;
+            const float gamma = 2.4f;
+
+            
+            if (K > 0.04045f)
+                return (float) Math.Pow((K + a) / (1 + a), gamma);
+            else
+                return K / 12.92f;
+        }
+
+        private static float xyz_to_lab_f(float t)
+        {
+            if (t > 0.008856f)
+                return (float) Math.Pow(t, 1.0f/3.0f);
+            else
+                return 7.787f*t + 16.0f/116.0f;
+        }
+
+        private static void rgb_to_lab(ushort R, ushort G, ushort B, out float L, out float a, out float b)
+        {
+            float x, y, z, gr, gg, gb, fy;
+            
+            /* This is the reference white point.  Since we're treating "RGB" as
+             * sRGB, this is the D65 point.
+             */
+            
+            const float Xn = 0.93819f;
+            const float Yn = 0.98705f;
+            const float Zn = 1.07475f;
+            
+            gr = srgb_to_xyz_g(R / 65535.0f);
+            gg = srgb_to_xyz_g(G / 65535.0f);
+            gb = srgb_to_xyz_g(B / 65535.0f);
+            
+            x = 0.412424f * gr + 0.357579f * gg + 0.180464f * gb;
+            y = 0.212656f * gr + 0.715158f * gg + 0.072186f * gb;
+            z = 0.019332f * gr + 0.119193f * gg + 0.950444f * gb;
+            
+            fy = xyz_to_lab_f(y / Yn);
+
+            L = 116.0f * fy - 16.0f;
+            a = 500.0f * (xyz_to_lab_f(x / Xn) - fy);
+            b = 200.0f * (fy - xyz_to_lab_f(z / Zn));
+        }
+
+        private static float xyz_to_srgb_C(float K)
+        {
+            const float a     = 0.055f;
+            const float gamma = 2.4f;
+
+            
+            if (K > 0.00304f)
+                return (1.0f + a) * ((float) Math.Pow(K, (1.0f / gamma))) - a;
+            else
+                return K * 12.92f;
+        }
+
+        private static void lab_to_rgb(float L, float a, float b, out ushort R, out ushort G, out ushort B)
+        {        
+            float x, y, z, fy, fx, fz, delta, delta2, rs, gs, bs;
+
+            const float Xn = 0.93819f;
+            const float Yn = 0.98705f;
+            const float Zn = 1.07475f;
+            
+            fy = (L + 16.0f) / 116.0f;
+            fx = fy + a / 500.0f;
+            fz = fy - b / 200.0f;
+            delta = 6.0f / 29.0f;
+            delta2 = (float) Math.Pow(delta, 2.0f);
+            
+            if (fx > delta)
+                x = Xn * ((float) Math.Pow(fx, 3.0f));
+            else
+                x = (fx - 16.0f/116.0f) * 3.0f * delta2 * Xn;
+
+            if (fy > delta)
+                y = Yn * ((float) Math.Pow(fy, 3.0f));
+            else
+                y = (fy - 16.0f/116.0f) * 3.0f * delta2 * Yn;
+
+            
+            if (fz > delta)
+                z = Zn * ((float) Math.Pow(fz, 3.0f));
+            else
+                z = (fz - 16.0f/116.0f) * 3.0f * delta2 * Zn;
+
+            
+            rs =  3.2410f * x - 1.5374f * y - 0.4986f * z;
+            gs = -0.9692f * x + 1.8760f * y + 0.0416f * z;
+            bs =  0.0556f * x - 0.2040f * y + 1.0570f * z;
+
+            float tmp;
+            tmp = (float) Math.Floor(xyz_to_srgb_C(rs) * 65535.0f + 0.5f);
+            if (tmp < 0.0f)
+                R = 0;
+            else if (tmp > 65535.0f)
+                R = 65535;
+            else
+                R = (ushort) tmp;
+            
+            tmp = (float) Math.Floor(xyz_to_srgb_C(gs) * 65535.0f + 0.5f);
+            if (tmp < 0.0f)
+                G = 0;
+            else if (tmp > 65535.0f)
+                G = 65535;
+            else
+                G = (ushort) tmp;
+
+            tmp = (float) Math.Floor(xyz_to_srgb_C(bs) * 65535.0f + 0.5f);
+            if (tmp < 0.0f)
+                B = 0;
+            else if (tmp > 65535.0f)
+                B = 65535;
+            else
+                B = (ushort) tmp;
+        }
+
+        private static float lab_distance(float La, float aa, float ba, float Lb, float ab, float bb)
+        {
+            float dL, da, db;
+
+            dL = Math.Abs(Lb - La);
+            da = Math.Abs(ab - aa);
+            db = Math.Abs(bb - ba);
+
+            return (float) Math.Sqrt(dL*dL + da*da + db*db);
+        }
+
+        /* Creates a specific color value for a foreground color, optimizing for
+         * maximum readability against the background.
+         */
+        
+        public static Color RenderForegroundColor(Color background, ContrastPaletteColor color)
+        {
+            float L, a, b;
+            int max_color;
+            float max_dist;
+            float[,] points = new float[8,3];
+            float ld, cd;
+            int i;
+            
+            rgb_to_lab((ushort)(background.R * 255), (ushort)(background.G * 255), 
+                (ushort)(background.B * 255), out L, out a, out b);
+            
+            points[0,0] = color_regions[(int)color,0];
+            points[0,1] = color_regions[(int)color,2];
+            points[0,2] = color_regions[(int)color,4];
+            
+            points[1,0] = color_regions[(int)color,0];
+            points[1,1] = color_regions[(int)color,2];
+            points[1,2] = color_regions[(int)color,5];
+            
+            points[2,0] = color_regions[(int)color,0];
+            points[2,1] = color_regions[(int)color,3];
+            points[2,2] = color_regions[(int)color,4];
+
+            points[3,0] = color_regions[(int)color,0];
+            points[3,1] = color_regions[(int)color,3];
+            points[3,2] = color_regions[(int)color,5];
+
+            points[4,0] = color_regions[(int)color,1];
+            points[4,1] = color_regions[(int)color,2];
+            points[4,2] = color_regions[(int)color,4];
+
+            points[5,0] = color_regions[(int)color,1];
+            points[5,1] = color_regions[(int)color,2];
+            points[5,2] = color_regions[(int)color,5];
+
+            points[6,0] = color_regions[(int)color,1];
+            points[6,1] = color_regions[(int)color,3];
+            points[6,2] = color_regions[(int)color,4];
+            
+            points[7,0] = color_regions[(int)color,1];
+            points[7,1] = color_regions[(int)color,3];
+            points[7,2] = color_regions[(int)color,5];
+            
+            max_dist = 0;
+            max_color = 0;
+            
+            for (i = 0; i < 8; i++) {
+                float dist = lab_distance(L, a, b, points[i,0], points[i,1], points[i,2]);
+                
+                if (dist > max_dist) {
+                    max_dist = dist;
+                    max_color = i;
+                }
+            }
+
+            /* If the luminosity distance is really short, extend the vector further
+             * out.  This may push it outside the bounds of the region that a color
+             * is specified in, but it keeps things readable when the background and
+             * foreground are really close.
+             */
+            
+            ld = Math.Abs(L - points[max_color,0]);
+            cd = (float) Math.Sqrt (Math.Pow (Math.Abs (a - points[max_color,1]), 2.0f) + Math.Pow (Math.Abs (b - points[max_color,2]), 2.0f));
+            
+            if ((ld < 10.0f) && (cd < 60.0f)) {
+                float dL, da, db;
+                
+                dL = points[max_color,0] - L;
+                da = points[max_color,1] - a;
+                db = points[max_color,2] - b;
+                points[max_color,0] = L + (dL * 4.0f);
+                points[max_color,1] = a + (da * 1.5f);
+                points[max_color,2] = b + (db * 1.5f);
+            }
+
+            ushort red, green, blue;
+            
+            lab_to_rgb(points[max_color,0], points[max_color,1], points[max_color,2], out red, out green, out blue);
+            
+            return new Color (red / 255.0, green / 255.0, blue / 255.0);
+        }
+    }
+}

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Makefile.am
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Makefile.am	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Makefile.am	Tue Sep  2 18:33:14 2008
@@ -39,6 +39,7 @@
 	Hyena.Gui/CairoExtensions.cs \
 	Hyena.Gui/CleanRoomStartup.cs \
 	Hyena.Gui/CompositeUtils.cs \
+	Hyena.Gui/Contrast.cs \
 	Hyena.Gui/EntryEraseAction.cs \
 	Hyena.Gui/EntryInsertAction.cs \
 	Hyena.Gui/EntryUndoAdapter.cs \



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]