blob: babb5afa53cc1948b41a93f832d5ad55ed078cf6 [file] [log] [blame]
/*
* Copyright (C) 2021-2022 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "ColorInterpolation.h"
#include "Color.h"
namespace WebCore {
std::pair<float, float> fixupHueComponentsPriorToInterpolation(HueInterpolationMethod method, float component1, float component2)
{
auto normalizeAnglesUsingShorterAlgorithm = [] (auto theta1, auto theta2) -> std::pair<float, float> {
// https://drafts.csswg.org/css-color-4/#hue-shorter
auto difference = theta2 - theta1;
if (difference > 180.0)
return { theta1 + 360.0, theta2 };
if (difference < -180.0)
return { theta1, theta2 + 360.0 };
return { theta1, theta2 };
};
auto normalizeAnglesUsingLongerAlgorithm = [] (auto theta1, auto theta2) -> std::pair<float, float> {
// https://drafts.csswg.org/css-color-4/#hue-longer
auto difference = theta2 - theta1;
if (difference > 0.0 && difference < 180.0)
return { theta1 + 360.0, theta2 };
if (difference > -180.0 && difference < 0)
return { theta1, theta2 + 360.0 };
return { theta1, theta2 };
};
auto normalizeAnglesUsingIncreasingAlgorithm = [] (auto theta1, auto theta2) -> std::pair<float, float> {
// https://drafts.csswg.org/css-color-4/#hue-increasing
if (theta2 < theta1)
return { theta1, theta2 + 360.0 };
return { theta1, theta2 };
};
auto normalizeAnglesUsingDecreasingAlgorithm = [] (auto theta1, auto theta2) -> std::pair<float, float> {
// https://drafts.csswg.org/css-color-4/#hue-decreasing
if (theta1 < theta2)
return { theta1 + 360.0, theta2 };
return { theta1, theta2 };
};
auto normalizeAnglesUsingSpecifiedAlgorithm = [] (auto theta1, auto theta2) -> std::pair<float, float> {
// https://drafts.csswg.org/css-color-4/#hue-specified
return { theta1, theta2 };
};
switch (method) {
case HueInterpolationMethod::Shorter:
return normalizeAnglesUsingShorterAlgorithm(component1, component2);
case HueInterpolationMethod::Longer:
return normalizeAnglesUsingLongerAlgorithm(component1, component2);
case HueInterpolationMethod::Increasing:
return normalizeAnglesUsingIncreasingAlgorithm(component1, component2);
case HueInterpolationMethod::Decreasing:
return normalizeAnglesUsingDecreasingAlgorithm(component1, component2);
case HueInterpolationMethod::Specified:
return normalizeAnglesUsingSpecifiedAlgorithm(component1, component2);
}
RELEASE_ASSERT_NOT_REACHED();
}
Color interpolateColors(ColorInterpolationMethod colorInterpolationMethod, Color color1, double color1Multiplier, Color color2, double color2Multiplier)
{
return WTF::switchOn(colorInterpolationMethod.colorSpace,
[&] (auto& colorSpace) {
using ColorType = typename std::remove_reference_t<decltype(colorSpace)>::ColorType;
switch (colorInterpolationMethod.alphaPremultiplication) {
case AlphaPremultiplication::Premultiplied:
return makeCanonicalColor(interpolateColorComponents<AlphaPremultiplication::Premultiplied>(colorSpace, color1.toColorTypeLossy<ColorType>(), color1Multiplier, color2.toColorTypeLossy<ColorType>(), color2Multiplier));
case AlphaPremultiplication::Unpremultiplied:
return makeCanonicalColor(interpolateColorComponents<AlphaPremultiplication::Unpremultiplied>(colorSpace, color1.toColorTypeLossy<ColorType>(), color1Multiplier, color2.toColorTypeLossy<ColorType>(), color2Multiplier));
}
RELEASE_ASSERT_NOT_REACHED();
}
);
}
}