Implement basic color-mix() functionality, behind a pref, but exposed to chrome code.

This is straight-forward and builds on the color animation code. This
implements only the <percentage> syntax, not the whole <color-adjuster>
syntax, which seems fairly more complex.

Of course, this only uses sRGB because that's all the colors we support,
but it should be feasible to extend to lab() / lch() colors once we
support those.

I believe this subset of syntax is useful and worth implementing, so
people can play with it and say if it's useful.

Differential Revision: https://phabricator.services.mozilla.com/D106698

bugzilla-url: https://bugzilla.mozilla.org/show_bug.cgi?id=1695376
gecko-commit: cc24224fecd05d677b6b05dae540ebe8234e07a2
gecko-reviewers: boris
diff --git a/css/css-color/color-mix-basic-001.tentative.html b/css/css-color/color-mix-basic-001.tentative.html
new file mode 100644
index 0000000..a2bcc57
--- /dev/null
+++ b/css/css-color/color-mix-basic-001.tentative.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<!-- Tentative pending potential syntax changes in https://github.com/w3c/csswg-drafts/issues/6066 -->
+<link rel="help" href="https://drafts.csswg.org/css-color-5/#color-mix">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1695376">
+<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
+<link rel="author" href="https://mozilla.org" title="Mozilla">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+div { color: black }
+</style>
+<div id="test"></div>
+<div id="ref"></div>
+<script>
+const TEST_CASES = [
+  ["blue", "red"],
+  ["blue", "green"],
+  ["rgb(255, 0, 0, .2)", "red"],
+  ["blue", "red", 0.9],
+  ["blue", "red", 0],
+  ["currentColor", "white"],
+  ["currentColor", "rgba(0, 0, 0, .5)"],
+];
+
+const testElement = document.getElementById("test");
+const refElement = document.getElementById("ref");
+const testStyle = getComputedStyle(testElement);
+const refStyle = getComputedStyle(refElement);
+
+let animation = null;
+
+for (let [from, to, animationProgress] of TEST_CASES) {
+  const animationProgressExplicit = animationProgress !== undefined;
+  animationProgress = animationProgressExplicit ? animationProgress : 0.5;
+  test(function() {
+    // Set up the ref.
+    if (animation) {
+      animation.cancel();
+    }
+    animation = refElement.animate({
+      backgroundColor: [from, to],
+    }, { duration: 1000 });
+    animation.pause();
+    animation.currentTime = 1000 * animationProgress;
+
+    let value = "color-mix(in srgb, " + from;
+    if (animationProgressExplicit) {
+      value += " " + (animationProgress * 100) + "%";
+    }
+    value += ", " + to + ")";
+    testElement.style.backgroundColor = "";
+    testElement.style.backgroundColor = value;
+
+    assert_not_equals(testElement.style.backgroundColor, "", "Should parse " + value);
+    assert_equals(testStyle.backgroundColor, refStyle.backgroundColor, "Colors should match");
+  }, `From ${from} to ${to} at ${animationProgress}`);
+}
+</script>