cssvalue: Change color transitions to run premultiplied
authorBenjamin Otte <otte@redhat.com>
Fri, 26 Jun 2015 19:08:04 +0000 (21:08 +0200)
committerBenjamin Otte <otte@redhat.com>
Fri, 26 Jun 2015 19:12:50 +0000 (21:12 +0200)
Previously, the unpremultiplied values from the GdkRGBA were taken. Now
we premultiply the color values as specified by the CSS specs.
This is only relevant when transitioning with translucent colors.

An example is the halfway transition between transparent (0, 0, 0, 0)
and white (1, 1, 1, 1). Previously, all 4 values where transitioned
separately and the result was semi-transparent gray (0.5, 0.5, 0.5,
0.5).
By depending on the alpha value, the result is now semi-transparent
white (1, 1, 1, 0.5) which is what one would naively expect.

New reftest: color-transition

gtk/gtkcssrgbavalue.c
testsuite/reftests/Makefile.am
testsuite/reftests/color-transition.css [new file with mode: 0644]
testsuite/reftests/color-transition.ref.ui [new file with mode: 0644]
testsuite/reftests/color-transition.ui [new file with mode: 0644]

index 0b66f8a113806b6a869d9f19b7e46ad387432e1c..7005347e0e92df434d174558d66869b8914e53b7 100644 (file)
@@ -74,9 +74,15 @@ gtk_css_value_rgba_transition (GtkCssValue *start,
     }
   else
     {
-      result.red = transition (start->rgba.red, end->rgba.red, progress);
-      result.green = transition (start->rgba.green, end->rgba.green, progress);
-      result.blue = transition (start->rgba.blue, end->rgba.blue, progress);
+      result.red = transition (start->rgba.red * start->rgba.alpha,
+                               end->rgba.red * end->rgba.alpha,
+                               progress) / result.alpha;
+      result.green = transition (start->rgba.green * start->rgba.alpha,
+                                 end->rgba.green * end->rgba.alpha,
+                                 progress) / result.alpha;
+      result.blue = transition (start->rgba.blue * start->rgba.alpha,
+                                end->rgba.blue * end->rgba.alpha,
+                                progress) / result.alpha;
     }
 
   return _gtk_css_rgba_value_new_from_rgba (&result);
index 61cc0a233a2e50437dc460ac63ae30fc5e029a0b..3887acc95ed7eb56def1b6289362838905d2bf50 100644 (file)
@@ -185,6 +185,9 @@ testdata = \
        cellrenderer-pixbuf-stock-rtl.css \
        cellrenderer-pixbuf-stock-rtl.ui \
        cellrenderer-pixbuf-stock-rtl.ref.ui \
+       color-transition.css \
+       color-transition.ref.ui \
+       color-transition.ui \
        css-currentcolor-alpha.css \
        css-currentcolor-alpha.ui \
        css-currentcolor-alpha.ref.ui \
diff --git a/testsuite/reftests/color-transition.css b/testsuite/reftests/color-transition.css
new file mode 100644 (file)
index 0000000..ac964b0
--- /dev/null
@@ -0,0 +1,18 @@
+@import "reset-to-defaults.css";
+
+@keyframes foo {
+  100% { background-color: blue; }
+}
+
+GtkWindow {
+  background-color: #7F0080;
+}
+
+GtkBox {
+  background-color: red;
+}
+
+GtkBox GtkBox {
+  background-color: transparent;
+  animation: foo 100s steps(2);
+}
diff --git a/testsuite/reftests/color-transition.ref.ui b/testsuite/reftests/color-transition.ref.ui
new file mode 100644 (file)
index 0000000..fa28350
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkWindow" id="window1">
+    <property name="can_focus">False</property>
+    <property name="type">popup</property>
+  </object>
+</interface>
diff --git a/testsuite/reftests/color-transition.ui b/testsuite/reftests/color-transition.ui
new file mode 100644 (file)
index 0000000..47e01cb
--- /dev/null
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkWindow" id="window1">
+    <property name="can_focus">False</property>
+    <property name="type">popup</property>
+    <child>
+      <object class="GtkBox" id="box1">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <child>
+          <object class="GtkBox" id="box2">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="hexpand">True</property>
+            <property name="vexpand">True</property>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>