blob: 96a93423342e31b37c646fe5c25e6685c5a8cdaa [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "config.h"
#include "core/animation/ColorStyleInterpolation.h"
#include "core/CSSValueKeywords.h"
#include "core/css/CSSPrimitiveValue.h"
#include "core/css/parser/CSSPropertyParser.h"
#include "core/css/resolver/StyleBuilder.h"
#include "core/layout/LayoutTheme.h"
#include "platform/graphics/Color.h"
#include "wtf/MathExtras.h"
#include <algorithm>
namespace blink {
bool ColorStyleInterpolation::canCreateFrom(const CSSValue& value)
{
return value.isPrimitiveValue() && (toCSSPrimitiveValue(value).isValueID() || toCSSPrimitiveValue(value).isRGBColor());
}
PassOwnPtr<InterpolableValue> ColorStyleInterpolation::colorToInterpolableValue(const CSSValue& value)
{
ASSERT(value.isPrimitiveValue());
const CSSPrimitiveValue& primitive = toCSSPrimitiveValue(value);
RGBA32 color;
if (primitive.isValueID()) {
if (CSSPropertyParser::isSystemColor(primitive.getValueID())) {
color = LayoutTheme::theme().systemColor(primitive.getValueID()).rgb();
} else {
Color colorFromID;
colorFromID.setNamedColor(getValueName(primitive.getValueID()));
color = colorFromID.rgb();
}
} else {
color = primitive.getRGBA32Value();
}
int alpha = alphaChannel(color);
OwnPtr<InterpolableList> list = InterpolableList::create(4);
list->set(0, InterpolableNumber::create(redChannel(color) * alpha));
list->set(1, InterpolableNumber::create(greenChannel(color) * alpha));
list->set(2, InterpolableNumber::create(blueChannel(color) * alpha));
list->set(3, InterpolableNumber::create(alpha));
return list->clone();
}
PassRefPtrWillBeRawPtr<CSSPrimitiveValue> ColorStyleInterpolation::interpolableValueToColor(const InterpolableValue& value)
{
ASSERT(value.isList());
const InterpolableList* list = toInterpolableList(&value);
double alpha = toInterpolableNumber(list->get(3))->value();
if (!alpha)
return CSSPrimitiveValue::createColor(Color::transparent);
// Clamping is inside makeRGBA.
unsigned rgba = makeRGBA(
round(toInterpolableNumber(list->get(0))->value() / alpha),
round(toInterpolableNumber(list->get(1))->value() / alpha),
round(toInterpolableNumber(list->get(2))->value() / alpha),
round(alpha));
return CSSPrimitiveValue::createColor(rgba);
}
void ColorStyleInterpolation::apply(StyleResolverState& state) const
{
StyleBuilder::applyProperty(m_id, state, interpolableValueToColor(*m_cachedValue).get());
}
PassRefPtr<ColorStyleInterpolation> ColorStyleInterpolation::maybeCreateFromColor(const CSSValue& start, const CSSValue& end, CSSPropertyID id)
{
if (canCreateFrom(start) && !toCSSPrimitiveValue(start).colorIsDerivedFromElement() && canCreateFrom(end) && !toCSSPrimitiveValue(end).colorIsDerivedFromElement())
return adoptRef(new ColorStyleInterpolation(colorToInterpolableValue(start), colorToInterpolableValue(end), id));
return nullptr;
}
bool ColorStyleInterpolation::shouldUseLegacyStyleInterpolation(const CSSValue& start, const CSSValue& end)
{
if (ColorStyleInterpolation::canCreateFrom(start) && ColorStyleInterpolation::canCreateFrom(end)) {
if (toCSSPrimitiveValue(start).colorIsDerivedFromElement() || toCSSPrimitiveValue(end).colorIsDerivedFromElement())
return true;
}
return false;
}
}