blob: fb46166972428224796b1e1a2172fd5830ffdfa8 [file] [log] [blame]
/*
* Copyright (C) 2015 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 INC. 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 INC. 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 "WillChangeData.h"
namespace WebCore {
bool WillChangeData::operator==(const WillChangeData& other) const
{
return m_animatableFeatures == other.m_animatableFeatures;
}
bool WillChangeData::containsScrollPosition() const
{
for (const auto& feature : m_animatableFeatures) {
if (feature.feature() == ScrollPosition)
return true;
}
return false;
}
bool WillChangeData::containsContents() const
{
for (const auto& feature : m_animatableFeatures) {
if (feature.feature() == Contents)
return true;
}
return false;
}
bool WillChangeData::containsProperty(CSSPropertyID property) const
{
for (const auto& feature : m_animatableFeatures) {
if (feature.property() == property)
return true;
}
return false;
}
bool WillChangeData::createsContainingBlockForAbsolutelyPositioned() const
{
return createsContainingBlockForOutOfFlowPositioned()
|| containsProperty(CSSPropertyPosition);
}
bool WillChangeData::createsContainingBlockForOutOfFlowPositioned() const
{
return containsProperty(CSSPropertyPerspective)
// CSS transforms
|| containsProperty(CSSPropertyTransform)
|| containsProperty(CSSPropertyTransformStyle)
|| containsProperty(CSSPropertyTranslate)
|| containsProperty(CSSPropertyRotate)
|| containsProperty(CSSPropertyScale)
|| containsProperty(CSSPropertyContain)
// CSS filter & backdrop-filter
// FIXME: exclude root element for those properties (bug 225034)
#if ENABLE(FILTERS_LEVEL_2)
|| containsProperty(CSSPropertyWebkitBackdropFilter)
#endif
|| containsProperty(CSSPropertyFilter);
}
// "If any non-initial value of a property would create a stacking context on the element,
// specifying that property in will-change must create a stacking context on the element."
bool WillChangeData::propertyCreatesStackingContext(CSSPropertyID property)
{
switch (property) {
case CSSPropertyPerspective:
case CSSPropertyScale:
case CSSPropertyRotate:
case CSSPropertyTranslate:
case CSSPropertyTransform:
case CSSPropertyTransformStyle:
case CSSPropertyWebkitTransformStyle:
case CSSPropertyClipPath:
case CSSPropertyMask:
case CSSPropertyOpacity:
case CSSPropertyPosition:
case CSSPropertyZIndex:
case CSSPropertyWebkitBoxReflect:
#if ENABLE(CSS_COMPOSITING)
case CSSPropertyMixBlendMode:
case CSSPropertyIsolation:
#endif
case CSSPropertyFilter:
#if ENABLE(FILTERS_LEVEL_2)
case CSSPropertyWebkitBackdropFilter:
#endif
case CSSPropertyWebkitMask:
case CSSPropertyWebkitMaskImage:
case CSSPropertyWebkitMaskBoxImage:
#if ENABLE(OVERFLOW_SCROLLING_TOUCH)
case CSSPropertyWebkitOverflowScrolling:
#endif
case CSSPropertyContain:
return true;
default:
return false;
}
}
static bool propertyTriggersCompositing(CSSPropertyID property)
{
switch (property) {
case CSSPropertyOpacity:
case CSSPropertyFilter:
#if ENABLE(FILTERS_LEVEL_2)
case CSSPropertyWebkitBackdropFilter:
#endif
return true;
default:
return false;
}
}
static bool propertyTriggersCompositingOnBoxesOnly(CSSPropertyID property)
{
// Don't trigger for perspective and transform-style, because those
// only do compositing if they have a 3d-transformed descendant and
// we don't want to do compositing all the time.
// Similarly, we don't want -webkit-overflow-scrolling-touch to
// always composite if there's no scrollable overflow.
switch (property) {
case CSSPropertyScale:
case CSSPropertyRotate:
case CSSPropertyTranslate:
case CSSPropertyTransform:
return true;
default:
return false;
}
}
void WillChangeData::addFeature(Feature feature, CSSPropertyID propertyID)
{
ASSERT(feature == Property || propertyID == CSSPropertyInvalid);
m_animatableFeatures.append(AnimatableFeature(feature, propertyID));
m_canCreateStackingContext |= propertyCreatesStackingContext(propertyID);
m_canTriggerCompositingOnInline |= propertyTriggersCompositing(propertyID);
m_canTriggerCompositing |= m_canTriggerCompositingOnInline | propertyTriggersCompositingOnBoxesOnly(propertyID);
}
WillChangeData::FeaturePropertyPair WillChangeData::featureAt(size_t index) const
{
if (index >= m_animatableFeatures.size())
return FeaturePropertyPair(Invalid, CSSPropertyInvalid);
return m_animatableFeatures[index].featurePropertyPair();
}
} // namespace WebCore