[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-core-devel
Subject:    changing KGraphicsUtils?
From:       Matthew Woehlke <mw_triad () users ! sourceforge ! net>
Date:       2007-05-30 20:35:59
Message-ID: f3kn7g$7gc$1 () sea ! gmane ! org
[Download RAW message or body]

A number of people have expressed confusion/dissatisfaction over the 
implementation of blendColors that Thomas committed. In an attempt to 
address these comments, I would like to suggest supporting two methods 
for the moment; Zack's, and mine. To make it very clear which does what, 
I have adopted Hans Meine's suggestion of making the names mix() and 
overlayColors() (feel free to argue for mixColors() and/or overlay(), 
and/or paint[Colors]() as an alternative to overlay[Colors]()).

mix() does a basic linear blend, treating the alpha channel as 'just 
another channel', which is the correct behavior if one is calculating 
bands in a gradient. At least Ingo Klöcker also suggested this behavior. 
This signature is an exact match for what is in KDevelop 3.4 (which 
originated in Ion's predecessor) and can immediately replace 
alphaBlendColors in Plastik with only very minor effort (although it has 
been questioned whether Plastik will ultimately need this method or not).

Also, about the name... I don't like it. :-) (And IIRC there was exactly 
zero discussion about it.) Since I expect this namespace to ultimately 
hold a good chunk of the usability stuff, what about KColorUtils 
instead, since we are working with colors and not* images?

(* Hans mentioned a case where we might take an image as input and 
produce a color as output, but I think the outputs are always colors or 
related to color. IOW this is not kdefx :-).)

Patch attached. Please comment on any clean-up (naming, formatting, etc) 
needed as well. This also fixes some existing consistency problems (e.g. 
TestBlendColors not matching the naming scheme of other kdeui tests, the 
error in the blendColors example code). I would like to commit Monday if 
there are no (unresolved) issues at that time.

-- 
Matthew
Ideas in this e-mail are larger than they appear and the writer may be 
smarter than he appears.

["kcolorutils.patch" (text/x-patch)]

==== in kdelibs/kdeui ====
A  +   tests/kcolorutilstest.h
D      tests/TestBlendColors.cpp
D      tests/TestBlendColors.h
M      tests/CMakeLists.txt
A  +   tests/kcolorutilstest.cpp
M      CMakeLists.txt
D      colors/kgraphicsutils.h
A  +   colors/kcolorutils.cpp
A  +   colors/kcolorutils.h
D      colors/kgraphicsutils.cpp

Index: tests/kcolorutilstest.h
===================================================================
--- tests/kcolorutilstest.h	(revision 669663)
+++ tests/kcolorutilstest.h	(working copy)
@@ -1,14 +1,14 @@
-#ifndef TestBlendColors_H
-#define TestBlendColors_H
+#ifndef KCOLORUTILSTEST_H
+#define KCOLORUTILSTEST_H
 
 #include <QtTest/QtTest>
 
-class TestBlendColors : public QObject
+class tst_KColorUtils : public QObject
 {
     Q_OBJECT
 private slots:
-    // tests
-    void test();
+    void testOverlay();
+    void testMix();
 };
 
-#endif
+#endif // KCOLORUTILSTEST_H
Index: tests/CMakeLists.txt
===================================================================
--- tests/CMakeLists.txt        (revision 669663)
+++ tests/CMakeLists.txt        (working copy)
@@ -37,6 +37,7 @@
   kstandardshortcuttest
   kuniqueapptest
   kapplication_unittest
+  kcolorutilstest
 )

 KDEUI_BUILD_TESTS(
@@ -107,7 +108,6 @@
   kjobtrackerstest
   kdebugtest_gui
   ktitlewidgettest
-  TestBlendColors
 )

 if (Q_WS_X11)
Index: tests/kcolorutilstest.cpp
===================================================================
--- tests/kcolorutilstest.cpp	(revision 669663)
+++ tests/kcolorutilstest.cpp	(working copy)
@@ -1,11 +1,12 @@
-#include "TestBlendColors.h"
+#include "kcolorutilstest.h"
 
-#include <kgraphicsutils.h>
+#include <kcolorutils.h>
 
-void TestBlendColors::test() {
+void tst_KColorUtils::testOverlay()
+{
     QColor color1(10, 10, 100);
     QColor color2(10, 10, 160);
-    QColor blended = KGraphicsUtils::blendColor(color1, color2);
+    QColor blended = KColorUtils::overlayColors(color1, color2);
     QCOMPARE(blended, color2); // no transparacny.
 
     QColor previous;
@@ -13,7 +14,7 @@
     // means we are moving more and more towards color2
     for(int i= 10; i <= 255; i+=10) {
         color2.setAlpha(i);
-        blended = KGraphicsUtils::blendColor(color1, color2);
+        blended = KColorUtils::overlayColors(color1, color2);
         if(previous.isValid()) {
             QCOMPARE(previous.red(), 10);
             QCOMPARE(previous.green(), 10);
@@ -25,18 +26,22 @@
     // only the alpha of color 2 alters the output
     color2.setAlpha(255); //opaque
     color1.setAlpha(80); //opaque
-    blended = KGraphicsUtils::blendColor(color2, color2);
+    blended = KColorUtils::overlayColors(color2, color2);
     QCOMPARE(blended.red(), color2.red());
     QCOMPARE(blended.green(), color2.green());
     QCOMPARE(blended.blue(), color2.blue());
 
     // merge from itself to itself gives; TADA; itself again ;)
     color2.setAlpha(127);
-    blended = KGraphicsUtils::blendColor(color2, color2);
+    blended = KColorUtils::overlayColors(color2, color2);
     QCOMPARE(blended.red(), color2.red());
     QCOMPARE(blended.green(), color2.green());
     QCOMPARE(blended.blue(), color2.blue());
 }
 
-QTEST_MAIN(TestBlendColors)
-#include "TestBlendColors.moc"
+void tst_KColorUtils::testMix()
+{
+}
+
+QTEST_MAIN(tst_KColorUtils)
+#include "kcolorutilstest.moc"
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt	(revision 669663)
+++ CMakeLists.txt	(working copy)
@@ -53,13 +53,13 @@
  actions/ktoolbarlabelaction.cpp
  actions/ktoolbarpopupaction.cpp
  actions/ktoolbarspaceraction.cpp
+ colors/kcolorutils.cpp
  colors/kcolorbutton.cpp
  colors/kcolorcombo.cpp
  colors/kcolordialog.cpp
  colors/kcolormimedata.cpp
  colors/kcolorvalueselector.cpp
  colors/khuesaturationselect.cpp
- colors/kgraphicsutils.cpp
  config/kconfigskeleton.cpp
  config/kconfiggroupgui.cpp
  dialogs/kaboutkdedialog.cpp
@@ -295,6 +295,7 @@
  actions/ktoolbarlabelaction.h
  actions/ktoolbarpopupaction.h
  actions/ktoolbarspaceraction.h
+ colors/kcolorutils.h
  colors/kcolorbutton.h
  colors/kcolorchoosermode.h
  colors/kcolorcombo.h
@@ -302,7 +303,6 @@
  colors/kcolormimedata.h
  colors/kcolorvalueselector.h
  colors/khuesaturationselect.h
- colors/kgraphicsutils.h
  config/kconfigskeleton.h
  dialogs/kaboutapplicationdialog.h
  dialogs/kaboutkdedialog.h
Index: colors/kcolorutils.cpp
===================================================================
--- colors/kcolorutils.cpp	(revision 669663)
+++ colors/kcolorutils.cpp	(working copy)
@@ -1,7 +1,9 @@
 /* This file is part of the KDE project
- * Copyright (C) 2007 Thomas Zander <zander@kde.org>
- * Copyright (C) 2007 Zack Rusin <zack@kde.org>
+ * Copyright (C) 2007 Matthew Woehlke <mw_triad@users.sourceforge.net>
  *
+ * overlayColors() Copyright (C) 2007 Thomas Zander <zander@kde.org>
+ * overlayColors() Copyright (C) 2007 Zack Rusin <zack@kde.org>
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
  * License as published by the Free Software Foundation; either
@@ -17,20 +19,41 @@
  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301, USA.
  */
-#include <kgraphicsutils.h>
+#include <kcolorutils.h>
 
 #include <QColor>
 #include <QImage>
 
-QColor KGraphicsUtils::blendColor(const QColor &one, const QColor &two, \
                QPainter::CompositionMode comp) {
-    // This may not be super fast; but timing shows this is easilly fast enough.
+static inline qreal mixQreal(qreal a, qreal b, qreal bias)
+{
+    return a + (b - a) * bias;
+}
+
+QColor KColorUtils::mix(const QColor &c1, const QColor &c2, qreal bias)
+{
+    if (bias <= 0.0) return c1;
+    if (bias >= 1.0) return c2;
+    if (!(bias < 1.0)) return c1; // bias == NaN
+
+    register qreal r = mixQreal(c1.redF(),   c2.redF(),   bias);
+    register qreal g = mixQreal(c1.greenF(), c2.greenF(), bias);
+    register qreal b = mixQreal(c1.blueF(),  c2.blueF(),  bias);
+    register qreal a = mixQreal(c1.alphaF(), c2.alphaF(), bias);
+
+    return QColor::fromRgbF(r, g, b, a);
+}
+
+QColor KColorUtils::overlayColors(const QColor &base, const QColor &paint,
+                                  QPainter::CompositionMode comp)
+{
+    // This isn't exactly fast :-( but it's the only safe way to use \
QPainter::CompositionMode  QImage img(1, 1, QImage::Format_ARGB32_Premultiplied);
     QPainter p(&img);
-    QColor start = one;
+    QColor start = base;
     start.setAlpha(255); // opaque
     p.fillRect(0, 0, 1, 1, start);
     p.setCompositionMode(comp);
-    p.fillRect(0, 0, 1, 1, two);
+    p.fillRect(0, 0, 1, 1, paint);
     p.end();
     return img.pixel(0, 0);
 }
Index: colors/kcolorutils.h
===================================================================
--- colors/kcolorutils.h	(revision 669663)
+++ colors/kcolorutils.h	(working copy)
@@ -1,7 +1,9 @@
 /* This file is part of the KDE project
- * Copyright (C) 2007 Thomas Zander <zander@kde.org>
- * Copyright (C) 2007 Zack Rusin <zack@kde.org>
+ * Copyright (C) 2007 Matthew Woehlke <mw_triad@users.sourceforge.net>
  *
+ * overlayColors() Copyright (C) 2007 Thomas Zander <zander@kde.org>
+ * overlayColors() Copyright (C) 2007 Zack Rusin <zack@kde.org>
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
  * License as published by the Free Software Foundation; either
@@ -18,26 +20,48 @@
  * Boston, MA 02110-1301, USA.
  */
 
+#ifndef KCOLORUTILS_H
+#define KCOLORUTILS_H
+
 #include <kdeui_export.h>
 #include <QPainter>
 
 class QColor;
 
 /**
- * A set of methods used to do graphics operations, like blendColor.
+ * A set of methods used to work with colors.
  */
-namespace KGraphicsUtils {
+namespace KColorUtils {
     /**
-     * Blend 2 colors into a new color with the strength of the blend based on the \
alpha channel of the second color. +     * Blend two colors into a new color by \
                linear combination.
      * @code
-        QColor white(Qt::White);
-        white.setAlpha(130);
-        QColor lighter = KGraphicsUtils::blendColor(myColor, white);
+        QColor lighter = KColorUtils::mix(myColor, Qt::white)
+     * @endcode
+     * @param c1 first color.
+     * @param c2 second color.
+     * @param bias weight to be used for the mix. @p bias <= 0 gives @p c1,
+     * @p bias >= 1 gives @p c2. @p bias == 0.5 gives a 50% blend of @p c1
+     * and @p c2.
+     */
+    KDEUI_EXPORT QColor mix(const QColor &one, const QColor &two,
+                            qreal bias = 0.5);
+
+    /**
+     * Blend two colors into a new color by painting the second color over the
+     * first using the specified composition mode.
+     * @code
+        QColor white(Qt::white);
+        white.setAlphaF(0.5);
+        QColor lighter = KColorUtils::overlayColors(myColor, white);
        @endcode
-     * @param one the starting point
-     * @param two the end point where we blend towards.
+     * @param base the base color (alpha channel is ignored).
+     * @param paint the color to be overlayed onto the base color.
      * @param comp the CompositionMode used to do the blending.
      */
-    KDEUI_EXPORT QColor blendColor(const QColor &one, const QColor &two, \
QPainter::CompositionMode comp = QPainter::CompositionMode_SourceOver); +    \
KDEUI_EXPORT QColor overlayColors(const QColor &base, const QColor &paint, +          \
QPainter::CompositionMode comp = QPainter::CompositionMode_SourceOver);  
 }
+
+#endif // KCOLORUTILS_H



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic