mirror of
https://github.com/darlinghq/darling-WebCore.git
synced 2024-11-26 22:00:22 +00:00
675 lines
24 KiB
C++
675 lines
24 KiB
C++
/*
|
|
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
|
|
* (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
|
|
* Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
|
|
* Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
|
|
* Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
|
|
* Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
|
|
* Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
|
|
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
|
|
* Copyright (C) Research In Motion Limited 2011. All rights reserved.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public License
|
|
* along with this library; see the file COPYING.LIB. If not, write to
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "CSSToStyleMap.h"
|
|
|
|
#include "Animation.h"
|
|
#include "CSSBorderImageSliceValue.h"
|
|
#include "CSSImageGeneratorValue.h"
|
|
#include "CSSImageSetValue.h"
|
|
#include "CSSImageValue.h"
|
|
#include "CSSPrimitiveValue.h"
|
|
#include "CSSPrimitiveValueMappings.h"
|
|
#include "CSSTimingFunctionValue.h"
|
|
#include "CSSValueKeywords.h"
|
|
#include "FillLayer.h"
|
|
#include "Pair.h"
|
|
#include "Rect.h"
|
|
#include "StyleBuilderConverter.h"
|
|
#include "StyleResolver.h"
|
|
|
|
namespace WebCore {
|
|
|
|
CSSToStyleMap::CSSToStyleMap(Style::BuilderState& builderState)
|
|
: m_builderState(builderState)
|
|
{
|
|
}
|
|
|
|
RenderStyle* CSSToStyleMap::style() const
|
|
{
|
|
return &m_builderState.style();
|
|
}
|
|
|
|
bool CSSToStyleMap::useSVGZoomRules() const
|
|
{
|
|
return m_builderState.useSVGZoomRules();
|
|
}
|
|
|
|
RefPtr<StyleImage> CSSToStyleMap::styleImage(CSSValue& value)
|
|
{
|
|
return m_builderState.createStyleImage(value);
|
|
}
|
|
|
|
void CSSToStyleMap::mapFillAttachment(CSSPropertyID propertyID, FillLayer& layer, const CSSValue& value)
|
|
{
|
|
if (value.treatAsInitialValue(propertyID)) {
|
|
layer.setAttachment(FillLayer::initialFillAttachment(layer.type()));
|
|
return;
|
|
}
|
|
|
|
if (!is<CSSPrimitiveValue>(value))
|
|
return;
|
|
|
|
switch (downcast<CSSPrimitiveValue>(value).valueID()) {
|
|
case CSSValueFixed:
|
|
layer.setAttachment(FillAttachment::FixedBackground);
|
|
break;
|
|
case CSSValueScroll:
|
|
layer.setAttachment(FillAttachment::ScrollBackground);
|
|
break;
|
|
case CSSValueLocal:
|
|
layer.setAttachment(FillAttachment::LocalBackground);
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
|
|
void CSSToStyleMap::mapFillClip(CSSPropertyID propertyID, FillLayer& layer, const CSSValue& value)
|
|
{
|
|
if (value.treatAsInitialValue(propertyID)) {
|
|
layer.setClip(FillLayer::initialFillClip(layer.type()));
|
|
return;
|
|
}
|
|
|
|
if (!is<CSSPrimitiveValue>(value))
|
|
return;
|
|
|
|
layer.setClip(downcast<CSSPrimitiveValue>(value));
|
|
}
|
|
|
|
void CSSToStyleMap::mapFillComposite(CSSPropertyID propertyID, FillLayer& layer, const CSSValue& value)
|
|
{
|
|
if (value.treatAsInitialValue(propertyID)) {
|
|
layer.setComposite(FillLayer::initialFillComposite(layer.type()));
|
|
return;
|
|
}
|
|
|
|
if (!is<CSSPrimitiveValue>(value))
|
|
return;
|
|
|
|
layer.setComposite(downcast<CSSPrimitiveValue>(value));
|
|
}
|
|
|
|
void CSSToStyleMap::mapFillBlendMode(CSSPropertyID propertyID, FillLayer& layer, const CSSValue& value)
|
|
{
|
|
if (value.treatAsInitialValue(propertyID)) {
|
|
layer.setBlendMode(FillLayer::initialFillBlendMode(layer.type()));
|
|
return;
|
|
}
|
|
|
|
if (!is<CSSPrimitiveValue>(value))
|
|
return;
|
|
|
|
layer.setBlendMode(downcast<CSSPrimitiveValue>(value));
|
|
}
|
|
|
|
void CSSToStyleMap::mapFillOrigin(CSSPropertyID propertyID, FillLayer& layer, const CSSValue& value)
|
|
{
|
|
if (value.treatAsInitialValue(propertyID)) {
|
|
layer.setOrigin(FillLayer::initialFillOrigin(layer.type()));
|
|
return;
|
|
}
|
|
|
|
if (!is<CSSPrimitiveValue>(value))
|
|
return;
|
|
|
|
layer.setOrigin(downcast<CSSPrimitiveValue>(value));
|
|
}
|
|
|
|
void CSSToStyleMap::mapFillImage(CSSPropertyID propertyID, FillLayer& layer, CSSValue& value)
|
|
{
|
|
if (value.treatAsInitialValue(propertyID)) {
|
|
layer.setImage(FillLayer::initialFillImage(layer.type()));
|
|
return;
|
|
}
|
|
|
|
layer.setImage(styleImage(value));
|
|
}
|
|
|
|
void CSSToStyleMap::mapFillRepeatX(CSSPropertyID propertyID, FillLayer& layer, const CSSValue& value)
|
|
{
|
|
if (value.treatAsInitialValue(propertyID)) {
|
|
layer.setRepeatX(FillLayer::initialFillRepeatX(layer.type()));
|
|
return;
|
|
}
|
|
|
|
if (!is<CSSPrimitiveValue>(value))
|
|
return;
|
|
|
|
layer.setRepeatX(downcast<CSSPrimitiveValue>(value));
|
|
}
|
|
|
|
void CSSToStyleMap::mapFillRepeatY(CSSPropertyID propertyID, FillLayer& layer, const CSSValue& value)
|
|
{
|
|
if (value.treatAsInitialValue(propertyID)) {
|
|
layer.setRepeatY(FillLayer::initialFillRepeatY(layer.type()));
|
|
return;
|
|
}
|
|
|
|
if (!is<CSSPrimitiveValue>(value))
|
|
return;
|
|
|
|
layer.setRepeatY(downcast<CSSPrimitiveValue>(value));
|
|
}
|
|
|
|
static inline bool convertToLengthSize(const CSSPrimitiveValue& primitiveValue, CSSToLengthConversionData conversionData, LengthSize& size)
|
|
{
|
|
if (auto* pair = primitiveValue.pairValue()) {
|
|
size.width = pair->first()->convertToLength<AnyConversion>(conversionData);
|
|
size.height = pair->second()->convertToLength<AnyConversion>(conversionData);
|
|
} else
|
|
size.width = primitiveValue.convertToLength<AnyConversion>(conversionData);
|
|
return !size.width.isUndefined() && !size.height.isUndefined();
|
|
}
|
|
|
|
void CSSToStyleMap::mapFillSize(CSSPropertyID propertyID, FillLayer& layer, const CSSValue& value)
|
|
{
|
|
if (value.treatAsInitialValue(propertyID)) {
|
|
layer.setSize(FillLayer::initialFillSize(layer.type()));
|
|
return;
|
|
}
|
|
|
|
if (!is<CSSPrimitiveValue>(value))
|
|
return;
|
|
|
|
auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
|
|
FillSize fillSize;
|
|
switch (primitiveValue.valueID()) {
|
|
case CSSValueContain:
|
|
fillSize.type = FillSizeType::Contain;
|
|
break;
|
|
case CSSValueCover:
|
|
fillSize.type = FillSizeType::Cover;
|
|
break;
|
|
default:
|
|
ASSERT(fillSize.type == FillSizeType::Size);
|
|
if (!convertToLengthSize(primitiveValue, m_builderState.cssToLengthConversionData(), fillSize.size))
|
|
return;
|
|
break;
|
|
}
|
|
layer.setSize(fillSize);
|
|
}
|
|
|
|
void CSSToStyleMap::mapFillXPosition(CSSPropertyID propertyID, FillLayer& layer, const CSSValue& value)
|
|
{
|
|
if (value.treatAsInitialValue(propertyID)) {
|
|
layer.setXPosition(FillLayer::initialFillXPosition(layer.type()));
|
|
return;
|
|
}
|
|
|
|
if (!is<CSSPrimitiveValue>(value))
|
|
return;
|
|
|
|
auto* primitiveValue = &downcast<CSSPrimitiveValue>(value);
|
|
Pair* pair = primitiveValue->pairValue();
|
|
Length length;
|
|
if (pair) {
|
|
ASSERT_UNUSED(propertyID, propertyID == CSSPropertyBackgroundPositionX || propertyID == CSSPropertyWebkitMaskPositionX);
|
|
length = Style::BuilderConverter::convertLength(m_builderState, *pair->second());
|
|
} else
|
|
length = Style::BuilderConverter::convertPositionComponentX(m_builderState, value);
|
|
|
|
layer.setXPosition(length);
|
|
if (pair)
|
|
layer.setBackgroundXOrigin(*pair->first());
|
|
}
|
|
|
|
void CSSToStyleMap::mapFillYPosition(CSSPropertyID propertyID, FillLayer& layer, const CSSValue& value)
|
|
{
|
|
if (value.treatAsInitialValue(propertyID)) {
|
|
layer.setYPosition(FillLayer::initialFillYPosition(layer.type()));
|
|
return;
|
|
}
|
|
|
|
if (!is<CSSPrimitiveValue>(value))
|
|
return;
|
|
|
|
auto* primitiveValue = &downcast<CSSPrimitiveValue>(value);
|
|
Pair* pair = primitiveValue->pairValue();
|
|
Length length;
|
|
if (pair) {
|
|
ASSERT_UNUSED(propertyID, propertyID == CSSPropertyBackgroundPositionY || propertyID == CSSPropertyWebkitMaskPositionY);
|
|
length = Style::BuilderConverter::convertLength(m_builderState, *pair->second());
|
|
} else
|
|
length = Style::BuilderConverter::convertPositionComponentY(m_builderState, value);
|
|
|
|
layer.setYPosition(length);
|
|
if (pair)
|
|
layer.setBackgroundYOrigin(*pair->first());
|
|
}
|
|
|
|
void CSSToStyleMap::mapFillMaskSourceType(CSSPropertyID propertyID, FillLayer& layer, const CSSValue& value)
|
|
{
|
|
MaskSourceType type = FillLayer::initialFillMaskSourceType(layer.type());
|
|
if (value.treatAsInitialValue(propertyID)) {
|
|
layer.setMaskSourceType(type);
|
|
return;
|
|
}
|
|
|
|
if (!is<CSSPrimitiveValue>(value))
|
|
return;
|
|
|
|
switch (downcast<CSSPrimitiveValue>(value).valueID()) {
|
|
case CSSValueAlpha:
|
|
type = MaskSourceType::Alpha;
|
|
break;
|
|
case CSSValueLuminance:
|
|
type = MaskSourceType::Luminance;
|
|
break;
|
|
case CSSValueAuto:
|
|
break;
|
|
default:
|
|
ASSERT_NOT_REACHED();
|
|
}
|
|
|
|
layer.setMaskSourceType(type);
|
|
}
|
|
|
|
void CSSToStyleMap::mapAnimationDelay(Animation& animation, const CSSValue& value)
|
|
{
|
|
if (value.treatAsInitialValue(CSSPropertyAnimationDelay)) {
|
|
animation.setDelay(Animation::initialDelay());
|
|
return;
|
|
}
|
|
|
|
if (!is<CSSPrimitiveValue>(value))
|
|
return;
|
|
|
|
animation.setDelay(downcast<CSSPrimitiveValue>(value).computeTime<double, CSSPrimitiveValue::Seconds>());
|
|
}
|
|
|
|
void CSSToStyleMap::mapAnimationDirection(Animation& layer, const CSSValue& value)
|
|
{
|
|
if (value.treatAsInitialValue(CSSPropertyAnimationDirection)) {
|
|
layer.setDirection(Animation::initialDirection());
|
|
return;
|
|
}
|
|
|
|
if (!is<CSSPrimitiveValue>(value))
|
|
return;
|
|
|
|
switch (downcast<CSSPrimitiveValue>(value).valueID()) {
|
|
case CSSValueNormal:
|
|
layer.setDirection(Animation::AnimationDirectionNormal);
|
|
break;
|
|
case CSSValueAlternate:
|
|
layer.setDirection(Animation::AnimationDirectionAlternate);
|
|
break;
|
|
case CSSValueReverse:
|
|
layer.setDirection(Animation::AnimationDirectionReverse);
|
|
break;
|
|
case CSSValueAlternateReverse:
|
|
layer.setDirection(Animation::AnimationDirectionAlternateReverse);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CSSToStyleMap::mapAnimationDuration(Animation& animation, const CSSValue& value)
|
|
{
|
|
if (value.treatAsInitialValue(CSSPropertyAnimationDuration)) {
|
|
animation.setDuration(Animation::initialDuration());
|
|
return;
|
|
}
|
|
|
|
if (!is<CSSPrimitiveValue>(value))
|
|
return;
|
|
|
|
animation.setDuration(downcast<CSSPrimitiveValue>(value).computeTime<double, CSSPrimitiveValue::Seconds>());
|
|
}
|
|
|
|
void CSSToStyleMap::mapAnimationFillMode(Animation& layer, const CSSValue& value)
|
|
{
|
|
if (value.treatAsInitialValue(CSSPropertyAnimationFillMode)) {
|
|
layer.setFillMode(Animation::initialFillMode());
|
|
return;
|
|
}
|
|
|
|
if (!is<CSSPrimitiveValue>(value))
|
|
return;
|
|
|
|
switch (downcast<CSSPrimitiveValue>(value).valueID()) {
|
|
case CSSValueNone:
|
|
layer.setFillMode(AnimationFillMode::None);
|
|
break;
|
|
case CSSValueForwards:
|
|
layer.setFillMode(AnimationFillMode::Forwards);
|
|
break;
|
|
case CSSValueBackwards:
|
|
layer.setFillMode(AnimationFillMode::Backwards);
|
|
break;
|
|
case CSSValueBoth:
|
|
layer.setFillMode(AnimationFillMode::Both);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CSSToStyleMap::mapAnimationIterationCount(Animation& animation, const CSSValue& value)
|
|
{
|
|
if (value.treatAsInitialValue(CSSPropertyAnimationIterationCount)) {
|
|
animation.setIterationCount(Animation::initialIterationCount());
|
|
return;
|
|
}
|
|
|
|
if (!is<CSSPrimitiveValue>(value))
|
|
return;
|
|
|
|
auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
|
|
if (primitiveValue.valueID() == CSSValueInfinite)
|
|
animation.setIterationCount(Animation::IterationCountInfinite);
|
|
else
|
|
animation.setIterationCount(primitiveValue.floatValue());
|
|
}
|
|
|
|
void CSSToStyleMap::mapAnimationName(Animation& layer, const CSSValue& value)
|
|
{
|
|
if (value.treatAsInitialValue(CSSPropertyAnimationName)) {
|
|
layer.setName(Animation::initialName());
|
|
return;
|
|
}
|
|
|
|
if (!is<CSSPrimitiveValue>(value))
|
|
return;
|
|
|
|
auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
|
|
if (primitiveValue.valueID() == CSSValueNone)
|
|
layer.setIsNoneAnimation(true);
|
|
else
|
|
layer.setName(primitiveValue.stringValue(), m_builderState.styleScopeOrdinal());
|
|
}
|
|
|
|
void CSSToStyleMap::mapAnimationPlayState(Animation& layer, const CSSValue& value)
|
|
{
|
|
if (value.treatAsInitialValue(CSSPropertyAnimationPlayState)) {
|
|
layer.setPlayState(Animation::initialPlayState());
|
|
return;
|
|
}
|
|
|
|
if (!is<CSSPrimitiveValue>(value))
|
|
return;
|
|
|
|
AnimationPlayState playState = (downcast<CSSPrimitiveValue>(value).valueID() == CSSValuePaused) ? AnimationPlayState::Paused : AnimationPlayState::Playing;
|
|
layer.setPlayState(playState);
|
|
}
|
|
|
|
void CSSToStyleMap::mapAnimationProperty(Animation& animation, const CSSValue& value)
|
|
{
|
|
if (value.treatAsInitialValue(CSSPropertyAnimation)) {
|
|
animation.setProperty(Animation::initialProperty());
|
|
return;
|
|
}
|
|
|
|
if (!is<CSSPrimitiveValue>(value))
|
|
return;
|
|
|
|
auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
|
|
if (primitiveValue.valueID() == CSSValueAll) {
|
|
animation.setProperty({ Animation::TransitionMode::All, CSSPropertyInvalid });
|
|
return;
|
|
}
|
|
if (primitiveValue.valueID() == CSSValueNone) {
|
|
animation.setProperty({ Animation::TransitionMode::None, CSSPropertyInvalid });
|
|
return;
|
|
}
|
|
if (primitiveValue.propertyID() == CSSPropertyInvalid) {
|
|
animation.setProperty({ Animation::TransitionMode::UnknownProperty, CSSPropertyInvalid });
|
|
animation.setUnknownProperty(primitiveValue.stringValue());
|
|
return;
|
|
}
|
|
|
|
animation.setProperty({ Animation::TransitionMode::SingleProperty, primitiveValue.propertyID() });
|
|
}
|
|
|
|
void CSSToStyleMap::mapAnimationTimingFunction(Animation& animation, const CSSValue& value)
|
|
{
|
|
if (value.treatAsInitialValue(CSSPropertyAnimationTimingFunction)) {
|
|
animation.setTimingFunction(Animation::initialTimingFunction());
|
|
return;
|
|
}
|
|
|
|
if (is<CSSPrimitiveValue>(value)) {
|
|
switch (downcast<CSSPrimitiveValue>(value).valueID()) {
|
|
case CSSValueLinear:
|
|
animation.setTimingFunction(LinearTimingFunction::create());
|
|
break;
|
|
case CSSValueEase:
|
|
animation.setTimingFunction(CubicBezierTimingFunction::create());
|
|
break;
|
|
case CSSValueEaseIn:
|
|
animation.setTimingFunction(CubicBezierTimingFunction::create(CubicBezierTimingFunction::EaseIn));
|
|
break;
|
|
case CSSValueEaseOut:
|
|
animation.setTimingFunction(CubicBezierTimingFunction::create(CubicBezierTimingFunction::EaseOut));
|
|
break;
|
|
case CSSValueEaseInOut:
|
|
animation.setTimingFunction(CubicBezierTimingFunction::create(CubicBezierTimingFunction::EaseInOut));
|
|
break;
|
|
case CSSValueStepStart:
|
|
animation.setTimingFunction(StepsTimingFunction::create(1, StepsTimingFunction::StepPosition::Start));
|
|
break;
|
|
case CSSValueStepEnd:
|
|
animation.setTimingFunction(StepsTimingFunction::create(1, StepsTimingFunction::StepPosition::End));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (is<CSSCubicBezierTimingFunctionValue>(value)) {
|
|
auto& cubicTimingFunction = downcast<CSSCubicBezierTimingFunctionValue>(value);
|
|
animation.setTimingFunction(CubicBezierTimingFunction::create(cubicTimingFunction.x1(), cubicTimingFunction.y1(), cubicTimingFunction.x2(), cubicTimingFunction.y2()));
|
|
} else if (is<CSSStepsTimingFunctionValue>(value)) {
|
|
auto& stepsTimingFunction = downcast<CSSStepsTimingFunctionValue>(value);
|
|
animation.setTimingFunction(StepsTimingFunction::create(stepsTimingFunction.numberOfSteps(), stepsTimingFunction.stepPosition()));
|
|
} else if (is<CSSSpringTimingFunctionValue>(value)) {
|
|
auto& springTimingFunction = downcast<CSSSpringTimingFunctionValue>(value);
|
|
animation.setTimingFunction(SpringTimingFunction::create(springTimingFunction.mass(), springTimingFunction.stiffness(), springTimingFunction.damping(), springTimingFunction.initialVelocity()));
|
|
}
|
|
}
|
|
|
|
void CSSToStyleMap::mapNinePieceImage(CSSPropertyID property, CSSValue* value, NinePieceImage& image)
|
|
{
|
|
// If we're not a value list, then we are "none" and don't need to alter the empty image at all.
|
|
if (!is<CSSValueList>(value))
|
|
return;
|
|
|
|
// Retrieve the border image value.
|
|
CSSValueList& borderImage = downcast<CSSValueList>(*value);
|
|
|
|
for (auto& current : borderImage) {
|
|
if (is<CSSImageValue>(current) || is<CSSImageGeneratorValue>(current) || is<CSSImageSetValue>(current))
|
|
image.setImage(styleImage(current.get()));
|
|
else if (is<CSSBorderImageSliceValue>(current))
|
|
mapNinePieceImageSlice(current, image);
|
|
else if (is<CSSValueList>(current)) {
|
|
CSSValueList& slashList = downcast<CSSValueList>(current.get());
|
|
// Map in the image slices.
|
|
if (is<CSSBorderImageSliceValue>(slashList.item(0)))
|
|
mapNinePieceImageSlice(*slashList.item(0), image);
|
|
|
|
// Map in the border slices.
|
|
if (slashList.item(1))
|
|
image.setBorderSlices(mapNinePieceImageQuad(*slashList.item(1)));
|
|
|
|
// Map in the outset.
|
|
if (slashList.item(2))
|
|
image.setOutset(mapNinePieceImageQuad(*slashList.item(2)));
|
|
} else if (is<CSSPrimitiveValue>(current)) {
|
|
// Set the appropriate rules for stretch/round/repeat of the slices.
|
|
mapNinePieceImageRepeat(current, image);
|
|
}
|
|
}
|
|
|
|
if (property == CSSPropertyWebkitBorderImage) {
|
|
// We have to preserve the legacy behavior of -webkit-border-image and make the border slices
|
|
// also set the border widths. We don't need to worry about percentages, since we don't even support
|
|
// those on real borders yet.
|
|
if (image.borderSlices().top().isFixed())
|
|
style()->setBorderTopWidth(image.borderSlices().top().value());
|
|
if (image.borderSlices().right().isFixed())
|
|
style()->setBorderRightWidth(image.borderSlices().right().value());
|
|
if (image.borderSlices().bottom().isFixed())
|
|
style()->setBorderBottomWidth(image.borderSlices().bottom().value());
|
|
if (image.borderSlices().left().isFixed())
|
|
style()->setBorderLeftWidth(image.borderSlices().left().value());
|
|
}
|
|
}
|
|
|
|
void CSSToStyleMap::mapNinePieceImageSlice(CSSValue& value, NinePieceImage& image)
|
|
{
|
|
if (!is<CSSBorderImageSliceValue>(value))
|
|
return;
|
|
|
|
// Retrieve the border image value.
|
|
auto& borderImageSlice = downcast<CSSBorderImageSliceValue>(value);
|
|
|
|
// Set up a length box to represent our image slices.
|
|
LengthBox box;
|
|
Quad* slices = borderImageSlice.slices();
|
|
if (slices->top()->isPercentage())
|
|
box.top() = Length(slices->top()->doubleValue(), Percent);
|
|
else
|
|
box.top() = Length(slices->top()->intValue(CSSUnitType::CSS_NUMBER), Fixed);
|
|
if (slices->bottom()->isPercentage())
|
|
box.bottom() = Length(slices->bottom()->doubleValue(), Percent);
|
|
else
|
|
box.bottom() = Length((int)slices->bottom()->floatValue(CSSUnitType::CSS_NUMBER), Fixed);
|
|
if (slices->left()->isPercentage())
|
|
box.left() = Length(slices->left()->doubleValue(), Percent);
|
|
else
|
|
box.left() = Length(slices->left()->intValue(CSSUnitType::CSS_NUMBER), Fixed);
|
|
if (slices->right()->isPercentage())
|
|
box.right() = Length(slices->right()->doubleValue(), Percent);
|
|
else
|
|
box.right() = Length(slices->right()->intValue(CSSUnitType::CSS_NUMBER), Fixed);
|
|
image.setImageSlices(box);
|
|
|
|
// Set our fill mode.
|
|
image.setFill(borderImageSlice.m_fill);
|
|
}
|
|
|
|
LengthBox CSSToStyleMap::mapNinePieceImageQuad(CSSValue& value)
|
|
{
|
|
if (!is<CSSPrimitiveValue>(value))
|
|
return LengthBox();
|
|
|
|
// Get our zoom value.
|
|
CSSToLengthConversionData conversionData = useSVGZoomRules() ? m_builderState.cssToLengthConversionData().copyWithAdjustedZoom(1.0f) : m_builderState.cssToLengthConversionData();
|
|
|
|
// Retrieve the primitive value.
|
|
auto& borderWidths = downcast<CSSPrimitiveValue>(value);
|
|
|
|
// Set up a length box to represent our image slices.
|
|
LengthBox box; // Defaults to 'auto' so we don't have to handle that explicitly below.
|
|
Quad* slices = borderWidths.quadValue();
|
|
if (slices->top()->isNumber())
|
|
box.top() = Length(slices->top()->intValue(), Relative);
|
|
else if (slices->top()->isPercentage())
|
|
box.top() = Length(slices->top()->doubleValue(CSSUnitType::CSS_PERCENTAGE), Percent);
|
|
else if (slices->top()->valueID() != CSSValueAuto)
|
|
box.top() = slices->top()->computeLength<Length>(conversionData);
|
|
|
|
if (slices->right()->isNumber())
|
|
box.right() = Length(slices->right()->intValue(), Relative);
|
|
else if (slices->right()->isPercentage())
|
|
box.right() = Length(slices->right()->doubleValue(CSSUnitType::CSS_PERCENTAGE), Percent);
|
|
else if (slices->right()->valueID() != CSSValueAuto)
|
|
box.right() = slices->right()->computeLength<Length>(conversionData);
|
|
|
|
if (slices->bottom()->isNumber())
|
|
box.bottom() = Length(slices->bottom()->intValue(), Relative);
|
|
else if (slices->bottom()->isPercentage())
|
|
box.bottom() = Length(slices->bottom()->doubleValue(CSSUnitType::CSS_PERCENTAGE), Percent);
|
|
else if (slices->bottom()->valueID() != CSSValueAuto)
|
|
box.bottom() = slices->bottom()->computeLength<Length>(conversionData);
|
|
|
|
if (slices->left()->isNumber())
|
|
box.left() = Length(slices->left()->intValue(), Relative);
|
|
else if (slices->left()->isPercentage())
|
|
box.left() = Length(slices->left()->doubleValue(CSSUnitType::CSS_PERCENTAGE), Percent);
|
|
else if (slices->left()->valueID() != CSSValueAuto)
|
|
box.left() = slices->left()->computeLength<Length>(conversionData);
|
|
|
|
return box;
|
|
}
|
|
|
|
void CSSToStyleMap::mapNinePieceImageRepeat(CSSValue& value, NinePieceImage& image)
|
|
{
|
|
if (!is<CSSPrimitiveValue>(value))
|
|
return;
|
|
|
|
CSSPrimitiveValue& primitiveValue = downcast<CSSPrimitiveValue>(value);
|
|
Pair* pair = primitiveValue.pairValue();
|
|
if (!pair || !pair->first() || !pair->second())
|
|
return;
|
|
|
|
CSSValueID firstIdentifier = pair->first()->valueID();
|
|
CSSValueID secondIdentifier = pair->second()->valueID();
|
|
|
|
NinePieceImageRule horizontalRule;
|
|
switch (firstIdentifier) {
|
|
case CSSValueStretch:
|
|
horizontalRule = NinePieceImageRule::Stretch;
|
|
break;
|
|
case CSSValueRound:
|
|
horizontalRule = NinePieceImageRule::Round;
|
|
break;
|
|
case CSSValueSpace:
|
|
horizontalRule = NinePieceImageRule::Space;
|
|
break;
|
|
default: // CSSValueRepeat
|
|
horizontalRule = NinePieceImageRule::Repeat;
|
|
break;
|
|
}
|
|
image.setHorizontalRule(horizontalRule);
|
|
|
|
NinePieceImageRule verticalRule;
|
|
switch (secondIdentifier) {
|
|
case CSSValueStretch:
|
|
verticalRule = NinePieceImageRule::Stretch;
|
|
break;
|
|
case CSSValueRound:
|
|
verticalRule = NinePieceImageRule::Round;
|
|
break;
|
|
case CSSValueSpace:
|
|
verticalRule = NinePieceImageRule::Space;
|
|
break;
|
|
default: // CSSValueRepeat
|
|
verticalRule = NinePieceImageRule::Repeat;
|
|
break;
|
|
}
|
|
image.setVerticalRule(verticalRule);
|
|
}
|
|
|
|
};
|