blob: 8852d36016f30d39c58caf1315bfaf4aadf5ec43 [file] [log] [blame]
/*
* Copyright (C) 2004 Zack Rusin <zack@kde.org>
* Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
* Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
* Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
* Copyright (C) 2011 Sencha, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include "config.h"
#include "core/css/CSSComputedStyleDeclaration.h"
#include "CSSPropertyNames.h"
#include "FontFamilyNames.h"
#include "RuntimeEnabledFeatures.h"
#include "StylePropertyShorthand.h"
#include "bindings/v8/ExceptionState.h"
#include "core/css/BasicShapeFunctions.h"
#include "core/css/CSSArrayFunctionValue.h"
#include "core/css/CSSAspectRatioValue.h"
#include "core/css/CSSBorderImage.h"
#include "core/css/CSSFilterValue.h"
#include "core/css/CSSFontFeatureValue.h"
#include "core/css/CSSFontValue.h"
#include "core/css/CSSFunctionValue.h"
#include "core/css/CSSGridTemplateValue.h"
#include "core/css/CSSLineBoxContainValue.h"
#include "core/css/CSSMixFunctionValue.h"
#include "core/css/CSSParser.h"
#include "core/css/CSSPrimitiveValue.h"
#include "core/css/CSSPrimitiveValueMappings.h"
#include "core/css/CSSReflectValue.h"
#include "core/css/CSSSelector.h"
#include "core/css/CSSShadowValue.h"
#include "core/css/CSSTimingFunctionValue.h"
#include "core/css/CSSTransformValue.h"
#include "core/css/CSSValueList.h"
#include "core/css/CSSValuePool.h"
#include "core/css/Pair.h"
#include "core/css/Rect.h"
#include "core/css/StylePropertySet.h"
#include "core/css/resolver/StyleResolver.h"
#include "core/dom/Document.h"
#include "core/dom/ExceptionCode.h"
#include "core/dom/PseudoElement.h"
#include "core/page/RuntimeCSSEnabled.h"
#include "core/frame/animation/AnimationController.h"
#include "core/rendering/RenderBox.h"
#include "core/rendering/RenderView.h"
#include "core/rendering/style/ContentData.h"
#include "core/rendering/style/CounterContent.h"
#include "core/rendering/style/CursorList.h"
#include "core/rendering/style/RenderStyle.h"
#include "core/rendering/style/ShadowList.h"
#include "core/rendering/style/ShapeValue.h"
#include "platform/fonts/FontFeatureSettings.h"
#include "wtf/text/StringBuilder.h"
#include "core/platform/graphics/filters/custom/CustomFilterArrayParameter.h"
#include "core/platform/graphics/filters/custom/CustomFilterNumberParameter.h"
#include "core/platform/graphics/filters/custom/CustomFilterOperation.h"
#include "core/platform/graphics/filters/custom/CustomFilterParameter.h"
#include "core/platform/graphics/filters/custom/CustomFilterTransformParameter.h"
#include "core/rendering/style/StyleCustomFilterProgram.h"
namespace WebCore {
// List of all properties we know how to compute, omitting shorthands.
// NOTE: Do not use this list, use computableProperties() instead
// to respect runtime enabling of CSS properties.
static const CSSPropertyID staticComputableProperties[] = {
CSSPropertyAnimationDelay,
CSSPropertyAnimationDirection,
CSSPropertyAnimationDuration,
CSSPropertyAnimationFillMode,
CSSPropertyAnimationIterationCount,
CSSPropertyAnimationName,
CSSPropertyAnimationPlayState,
CSSPropertyAnimationTimingFunction,
CSSPropertyBackgroundAttachment,
CSSPropertyBackgroundBlendMode,
CSSPropertyBackgroundClip,
CSSPropertyBackgroundColor,
CSSPropertyBackgroundImage,
CSSPropertyBackgroundOrigin,
CSSPropertyBackgroundPosition, // more-specific background-position-x/y are non-standard
CSSPropertyBackgroundRepeat,
CSSPropertyBackgroundSize,
CSSPropertyBorderBottomColor,
CSSPropertyBorderBottomLeftRadius,
CSSPropertyBorderBottomRightRadius,
CSSPropertyBorderBottomStyle,
CSSPropertyBorderBottomWidth,
CSSPropertyBorderCollapse,
CSSPropertyBorderImageOutset,
CSSPropertyBorderImageRepeat,
CSSPropertyBorderImageSlice,
CSSPropertyBorderImageSource,
CSSPropertyBorderImageWidth,
CSSPropertyBorderLeftColor,
CSSPropertyBorderLeftStyle,
CSSPropertyBorderLeftWidth,
CSSPropertyBorderRightColor,
CSSPropertyBorderRightStyle,
CSSPropertyBorderRightWidth,
CSSPropertyBorderTopColor,
CSSPropertyBorderTopLeftRadius,
CSSPropertyBorderTopRightRadius,
CSSPropertyBorderTopStyle,
CSSPropertyBorderTopWidth,
CSSPropertyBottom,
CSSPropertyBoxShadow,
CSSPropertyBoxSizing,
CSSPropertyCaptionSide,
CSSPropertyClear,
CSSPropertyClip,
CSSPropertyColor,
CSSPropertyCursor,
CSSPropertyDirection,
CSSPropertyDisplay,
CSSPropertyEmptyCells,
CSSPropertyFloat,
CSSPropertyFontFamily,
CSSPropertyFontSize,
CSSPropertyFontStyle,
CSSPropertyFontVariant,
CSSPropertyFontWeight,
CSSPropertyHeight,
CSSPropertyImageRendering,
CSSPropertyIsolation,
CSSPropertyLeft,
CSSPropertyLetterSpacing,
CSSPropertyLineHeight,
CSSPropertyListStyleImage,
CSSPropertyListStylePosition,
CSSPropertyListStyleType,
CSSPropertyMarginBottom,
CSSPropertyMarginLeft,
CSSPropertyMarginRight,
CSSPropertyMarginTop,
CSSPropertyMaxHeight,
CSSPropertyMaxWidth,
CSSPropertyMinHeight,
CSSPropertyMinWidth,
CSSPropertyMixBlendMode,
CSSPropertyObjectFit,
CSSPropertyObjectPosition,
CSSPropertyOpacity,
CSSPropertyOrphans,
CSSPropertyOutlineColor,
CSSPropertyOutlineOffset,
CSSPropertyOutlineStyle,
CSSPropertyOutlineWidth,
CSSPropertyOverflowWrap,
CSSPropertyOverflowX,
CSSPropertyOverflowY,
CSSPropertyPaddingBottom,
CSSPropertyPaddingLeft,
CSSPropertyPaddingRight,
CSSPropertyPaddingTop,
CSSPropertyPageBreakAfter,
CSSPropertyPageBreakBefore,
CSSPropertyPageBreakInside,
CSSPropertyPointerEvents,
CSSPropertyPosition,
CSSPropertyResize,
CSSPropertyRight,
CSSPropertySpeak,
CSSPropertyTableLayout,
CSSPropertyTabSize,
CSSPropertyTextAlign,
CSSPropertyTextAlignLast,
CSSPropertyTextDecoration,
CSSPropertyTextDecorationLine,
CSSPropertyTextDecorationStyle,
CSSPropertyTextDecorationColor,
CSSPropertyTextJustify,
#if ENABLE(CSS3_TEXT)
CSSPropertyWebkitTextUnderlinePosition,
#endif // CSS3_TEXT
CSSPropertyTextIndent,
CSSPropertyTextRendering,
CSSPropertyTextShadow,
CSSPropertyTextOverflow,
CSSPropertyTextTransform,
CSSPropertyTop,
CSSPropertyTouchAction,
CSSPropertyTouchActionDelay,
CSSPropertyTransitionDelay,
CSSPropertyTransitionDuration,
CSSPropertyTransitionProperty,
CSSPropertyTransitionTimingFunction,
CSSPropertyUnicodeBidi,
CSSPropertyVerticalAlign,
CSSPropertyVisibility,
CSSPropertyWhiteSpace,
CSSPropertyWidows,
CSSPropertyWidth,
CSSPropertyWordBreak,
CSSPropertyWordSpacing,
CSSPropertyWordWrap,
CSSPropertyZIndex,
CSSPropertyZoom,
CSSPropertyWebkitAnimationDelay,
CSSPropertyWebkitAnimationDirection,
CSSPropertyWebkitAnimationDuration,
CSSPropertyWebkitAnimationFillMode,
CSSPropertyWebkitAnimationIterationCount,
CSSPropertyWebkitAnimationName,
CSSPropertyWebkitAnimationPlayState,
CSSPropertyWebkitAnimationTimingFunction,
CSSPropertyWebkitAppearance,
CSSPropertyWebkitBackfaceVisibility,
CSSPropertyWebkitBackgroundClip,
CSSPropertyWebkitBackgroundComposite,
CSSPropertyWebkitBackgroundOrigin,
CSSPropertyWebkitBackgroundSize,
CSSPropertyWebkitBorderFit,
CSSPropertyWebkitBorderHorizontalSpacing,
CSSPropertyWebkitBorderImage,
CSSPropertyWebkitBorderVerticalSpacing,
CSSPropertyWebkitBoxAlign,
CSSPropertyWebkitBoxDecorationBreak,
CSSPropertyWebkitBoxDirection,
CSSPropertyWebkitBoxFlex,
CSSPropertyWebkitBoxFlexGroup,
CSSPropertyWebkitBoxLines,
CSSPropertyWebkitBoxOrdinalGroup,
CSSPropertyWebkitBoxOrient,
CSSPropertyWebkitBoxPack,
CSSPropertyWebkitBoxReflect,
CSSPropertyWebkitBoxShadow,
CSSPropertyWebkitClipPath,
CSSPropertyWebkitColumnBreakAfter,
CSSPropertyWebkitColumnBreakBefore,
CSSPropertyWebkitColumnBreakInside,
CSSPropertyWebkitColumnAxis,
CSSPropertyWebkitColumnCount,
CSSPropertyWebkitColumnGap,
CSSPropertyWebkitColumnProgression,
CSSPropertyWebkitColumnRuleColor,
CSSPropertyWebkitColumnRuleStyle,
CSSPropertyWebkitColumnRuleWidth,
CSSPropertyWebkitColumnSpan,
CSSPropertyWebkitColumnWidth,
CSSPropertyWebkitFilter,
CSSPropertyAlignContent,
CSSPropertyAlignItems,
CSSPropertyAlignSelf,
CSSPropertyFlexBasis,
CSSPropertyFlexGrow,
CSSPropertyFlexShrink,
CSSPropertyFlexDirection,
CSSPropertyFlexWrap,
CSSPropertyJustifyContent,
CSSPropertyWebkitFontKerning,
CSSPropertyWebkitFontSmoothing,
CSSPropertyWebkitFontVariantLigatures,
CSSPropertyGridAutoColumns,
CSSPropertyGridAutoFlow,
CSSPropertyGridAutoRows,
CSSPropertyGridColumnEnd,
CSSPropertyGridColumnStart,
CSSPropertyGridDefinitionColumns,
CSSPropertyGridDefinitionRows,
CSSPropertyGridRowEnd,
CSSPropertyGridRowStart,
CSSPropertyWebkitHighlight,
CSSPropertyWebkitHyphenateCharacter,
CSSPropertyWebkitLineAlign,
CSSPropertyWebkitLineBoxContain,
CSSPropertyWebkitLineBreak,
CSSPropertyWebkitLineClamp,
CSSPropertyWebkitLineGrid,
CSSPropertyWebkitLineSnap,
CSSPropertyWebkitLocale,
CSSPropertyWebkitMarginBeforeCollapse,
CSSPropertyWebkitMarginAfterCollapse,
CSSPropertyWebkitMaskBoxImage,
CSSPropertyWebkitMaskBoxImageOutset,
CSSPropertyWebkitMaskBoxImageRepeat,
CSSPropertyWebkitMaskBoxImageSlice,
CSSPropertyWebkitMaskBoxImageSource,
CSSPropertyWebkitMaskBoxImageWidth,
CSSPropertyWebkitMaskClip,
CSSPropertyWebkitMaskComposite,
CSSPropertyWebkitMaskImage,
CSSPropertyWebkitMaskOrigin,
CSSPropertyWebkitMaskPosition,
CSSPropertyWebkitMaskRepeat,
CSSPropertyWebkitMaskSize,
CSSPropertyOrder,
CSSPropertyWebkitPerspective,
CSSPropertyWebkitPerspectiveOrigin,
CSSPropertyWebkitPrintColorAdjust,
CSSPropertyWebkitRtlOrdering,
CSSPropertyShapeInside,
CSSPropertyShapeOutside,
CSSPropertyShapePadding,
CSSPropertyShapeImageThreshold,
CSSPropertyShapeMargin,
CSSPropertyWebkitTapHighlightColor,
CSSPropertyWebkitTextCombine,
CSSPropertyWebkitTextDecorationsInEffect,
CSSPropertyWebkitTextEmphasisColor,
CSSPropertyWebkitTextEmphasisPosition,
CSSPropertyWebkitTextEmphasisStyle,
CSSPropertyWebkitTextFillColor,
CSSPropertyWebkitTextOrientation,
CSSPropertyWebkitTextSecurity,
CSSPropertyWebkitTextStrokeColor,
CSSPropertyWebkitTextStrokeWidth,
CSSPropertyWebkitTransform,
CSSPropertyWebkitTransformOrigin,
CSSPropertyWebkitTransformStyle,
CSSPropertyWebkitTransitionDelay,
CSSPropertyWebkitTransitionDuration,
CSSPropertyWebkitTransitionProperty,
CSSPropertyWebkitTransitionTimingFunction,
CSSPropertyWebkitUserDrag,
CSSPropertyWebkitUserModify,
CSSPropertyWebkitUserSelect,
CSSPropertyWebkitWritingMode,
CSSPropertyWebkitFlowInto,
CSSPropertyWebkitFlowFrom,
CSSPropertyWebkitRegionBreakAfter,
CSSPropertyWebkitRegionBreakBefore,
CSSPropertyWebkitRegionBreakInside,
CSSPropertyWebkitRegionFragment,
CSSPropertyWebkitAppRegion,
CSSPropertyWebkitWrapFlow,
CSSPropertyWebkitWrapThrough,
CSSPropertyBufferedRendering,
CSSPropertyClipPath,
CSSPropertyClipRule,
CSSPropertyMask,
CSSPropertyFilter,
CSSPropertyFloodColor,
CSSPropertyFloodOpacity,
CSSPropertyLightingColor,
CSSPropertyStopColor,
CSSPropertyStopOpacity,
CSSPropertyColorInterpolation,
CSSPropertyColorInterpolationFilters,
CSSPropertyColorRendering,
CSSPropertyFill,
CSSPropertyFillOpacity,
CSSPropertyFillRule,
CSSPropertyMarkerEnd,
CSSPropertyMarkerMid,
CSSPropertyMarkerStart,
CSSPropertyMaskType,
CSSPropertyMaskSourceType,
CSSPropertyShapeRendering,
CSSPropertyStroke,
CSSPropertyStrokeDasharray,
CSSPropertyStrokeDashoffset,
CSSPropertyStrokeLinecap,
CSSPropertyStrokeLinejoin,
CSSPropertyStrokeMiterlimit,
CSSPropertyStrokeOpacity,
CSSPropertyStrokeWidth,
CSSPropertyAlignmentBaseline,
CSSPropertyBaselineShift,
CSSPropertyDominantBaseline,
CSSPropertyKerning,
CSSPropertyTextAnchor,
CSSPropertyWritingMode,
CSSPropertyGlyphOrientationHorizontal,
CSSPropertyGlyphOrientationVertical,
CSSPropertyVectorEffect,
CSSPropertyPaintOrder
};
static const Vector<CSSPropertyID>& computableProperties()
{
DEFINE_STATIC_LOCAL(Vector<CSSPropertyID>, properties, ());
if (properties.isEmpty())
RuntimeCSSEnabled::filterEnabledCSSPropertiesIntoVector(staticComputableProperties, WTF_ARRAY_LENGTH(staticComputableProperties), properties);
return properties;
}
static CSSValueID valueForRepeatRule(int rule)
{
switch (rule) {
case RepeatImageRule:
return CSSValueRepeat;
case RoundImageRule:
return CSSValueRound;
case SpaceImageRule:
return CSSValueSpace;
default:
return CSSValueStretch;
}
}
static PassRefPtr<CSSBorderImageSliceValue> valueForNinePieceImageSlice(const NinePieceImage& image)
{
// Create the slices.
RefPtr<CSSPrimitiveValue> top;
RefPtr<CSSPrimitiveValue> right;
RefPtr<CSSPrimitiveValue> bottom;
RefPtr<CSSPrimitiveValue> left;
if (image.imageSlices().top().isPercent())
top = cssValuePool().createValue(image.imageSlices().top().value(), CSSPrimitiveValue::CSS_PERCENTAGE);
else
top = cssValuePool().createValue(image.imageSlices().top().value(), CSSPrimitiveValue::CSS_NUMBER);
if (image.imageSlices().right() == image.imageSlices().top() && image.imageSlices().bottom() == image.imageSlices().top()
&& image.imageSlices().left() == image.imageSlices().top()) {
right = top;
bottom = top;
left = top;
} else {
if (image.imageSlices().right().isPercent())
right = cssValuePool().createValue(image.imageSlices().right().value(), CSSPrimitiveValue::CSS_PERCENTAGE);
else
right = cssValuePool().createValue(image.imageSlices().right().value(), CSSPrimitiveValue::CSS_NUMBER);
if (image.imageSlices().bottom() == image.imageSlices().top() && image.imageSlices().right() == image.imageSlices().left()) {
bottom = top;
left = right;
} else {
if (image.imageSlices().bottom().isPercent())
bottom = cssValuePool().createValue(image.imageSlices().bottom().value(), CSSPrimitiveValue::CSS_PERCENTAGE);
else
bottom = cssValuePool().createValue(image.imageSlices().bottom().value(), CSSPrimitiveValue::CSS_NUMBER);
if (image.imageSlices().left() == image.imageSlices().right())
left = right;
else {
if (image.imageSlices().left().isPercent())
left = cssValuePool().createValue(image.imageSlices().left().value(), CSSPrimitiveValue::CSS_PERCENTAGE);
else
left = cssValuePool().createValue(image.imageSlices().left().value(), CSSPrimitiveValue::CSS_NUMBER);
}
}
}
RefPtr<Quad> quad = Quad::create();
quad->setTop(top);
quad->setRight(right);
quad->setBottom(bottom);
quad->setLeft(left);
return CSSBorderImageSliceValue::create(cssValuePool().createValue(quad.release()), image.fill());
}
static PassRefPtr<CSSPrimitiveValue> valueForNinePieceImageQuad(const LengthBox& box, const RenderStyle* style)
{
// Create the slices.
RefPtr<CSSPrimitiveValue> top;
RefPtr<CSSPrimitiveValue> right;
RefPtr<CSSPrimitiveValue> bottom;
RefPtr<CSSPrimitiveValue> left;
if (box.top().isRelative())
top = cssValuePool().createValue(box.top().value(), CSSPrimitiveValue::CSS_NUMBER);
else
top = cssValuePool().createValue(box.top(), style);
if (box.right() == box.top() && box.bottom() == box.top() && box.left() == box.top()) {
right = top;
bottom = top;
left = top;
} else {
if (box.right().isRelative())
right = cssValuePool().createValue(box.right().value(), CSSPrimitiveValue::CSS_NUMBER);
else
right = cssValuePool().createValue(box.right(), style);
if (box.bottom() == box.top() && box.right() == box.left()) {
bottom = top;
left = right;
} else {
if (box.bottom().isRelative())
bottom = cssValuePool().createValue(box.bottom().value(), CSSPrimitiveValue::CSS_NUMBER);
else
bottom = cssValuePool().createValue(box.bottom(), style);
if (box.left() == box.right())
left = right;
else {
if (box.left().isRelative())
left = cssValuePool().createValue(box.left().value(), CSSPrimitiveValue::CSS_NUMBER);
else
left = cssValuePool().createValue(box.left(), style);
}
}
}
RefPtr<Quad> quad = Quad::create();
quad->setTop(top);
quad->setRight(right);
quad->setBottom(bottom);
quad->setLeft(left);
return cssValuePool().createValue(quad.release());
}
static PassRefPtr<CSSValue> valueForNinePieceImageRepeat(const NinePieceImage& image)
{
RefPtr<CSSPrimitiveValue> horizontalRepeat;
RefPtr<CSSPrimitiveValue> verticalRepeat;
horizontalRepeat = cssValuePool().createIdentifierValue(valueForRepeatRule(image.horizontalRule()));
if (image.horizontalRule() == image.verticalRule())
verticalRepeat = horizontalRepeat;
else
verticalRepeat = cssValuePool().createIdentifierValue(valueForRepeatRule(image.verticalRule()));
return cssValuePool().createValue(Pair::create(horizontalRepeat.release(), verticalRepeat.release(), Pair::DropIdenticalValues));
}
static PassRefPtr<CSSValue> valueForNinePieceImage(const NinePieceImage& image, const RenderStyle* style)
{
if (!image.hasImage())
return cssValuePool().createIdentifierValue(CSSValueNone);
// Image first.
RefPtr<CSSValue> imageValue;
if (image.image())
imageValue = image.image()->cssValue();
// Create the image slice.
RefPtr<CSSBorderImageSliceValue> imageSlices = valueForNinePieceImageSlice(image);
// Create the border area slices.
RefPtr<CSSValue> borderSlices = valueForNinePieceImageQuad(image.borderSlices(), style);
// Create the border outset.
RefPtr<CSSValue> outset = valueForNinePieceImageQuad(image.outset(), style);
// Create the repeat rules.
RefPtr<CSSValue> repeat = valueForNinePieceImageRepeat(image);
return createBorderImageValue(imageValue.release(), imageSlices.release(), borderSlices.release(), outset.release(), repeat.release());
}
inline static PassRefPtr<CSSPrimitiveValue> zoomAdjustedPixelValue(double value, const RenderStyle* style)
{
return cssValuePool().createValue(adjustFloatForAbsoluteZoom(value, style), CSSPrimitiveValue::CSS_PX);
}
inline static PassRefPtr<CSSPrimitiveValue> zoomAdjustedNumberValue(double value, const RenderStyle* style)
{
return cssValuePool().createValue(value / style->effectiveZoom(), CSSPrimitiveValue::CSS_NUMBER);
}
static PassRefPtr<CSSPrimitiveValue> zoomAdjustedPixelValueForLength(const Length& length, const RenderStyle* style)
{
if (length.isFixed())
return zoomAdjustedPixelValue(length.value(), style);
return cssValuePool().createValue(length, style);
}
static PassRefPtr<CSSValue> valueForReflection(const StyleReflection* reflection, const RenderStyle* style)
{
if (!reflection)
return cssValuePool().createIdentifierValue(CSSValueNone);
RefPtr<CSSPrimitiveValue> offset;
if (reflection->offset().isPercent())
offset = cssValuePool().createValue(reflection->offset().percent(), CSSPrimitiveValue::CSS_PERCENTAGE);
else
offset = zoomAdjustedPixelValue(reflection->offset().value(), style);
RefPtr<CSSPrimitiveValue> direction;
switch (reflection->direction()) {
case ReflectionBelow:
direction = cssValuePool().createIdentifierValue(CSSValueBelow);
break;
case ReflectionAbove:
direction = cssValuePool().createIdentifierValue(CSSValueAbove);
break;
case ReflectionLeft:
direction = cssValuePool().createIdentifierValue(CSSValueLeft);
break;
case ReflectionRight:
direction = cssValuePool().createIdentifierValue(CSSValueRight);
break;
}
return CSSReflectValue::create(direction.release(), offset.release(), valueForNinePieceImage(reflection->mask(), style));
}
static PassRefPtr<CSSValueList> createPositionListForLayer(CSSPropertyID propertyID, const FillLayer* layer, const RenderStyle* style)
{
RefPtr<CSSValueList> positionList = CSSValueList::createSpaceSeparated();
if (layer->isBackgroundXOriginSet()) {
ASSERT_UNUSED(propertyID, propertyID == CSSPropertyBackgroundPosition || propertyID == CSSPropertyWebkitMaskPosition);
positionList->append(cssValuePool().createValue(layer->backgroundXOrigin()));
}
positionList->append(zoomAdjustedPixelValueForLength(layer->xPosition(), style));
if (layer->isBackgroundYOriginSet()) {
ASSERT(propertyID == CSSPropertyBackgroundPosition || propertyID == CSSPropertyWebkitMaskPosition);
positionList->append(cssValuePool().createValue(layer->backgroundYOrigin()));
}
positionList->append(zoomAdjustedPixelValueForLength(layer->yPosition(), style));
return positionList.release();
}
static PassRefPtr<CSSValue> valueForPositionOffset(RenderStyle* style, CSSPropertyID propertyID, const RenderObject* renderer, RenderView* renderView)
{
if (!style)
return 0;
Length l;
switch (propertyID) {
case CSSPropertyLeft:
l = style->left();
break;
case CSSPropertyRight:
l = style->right();
break;
case CSSPropertyTop:
l = style->top();
break;
case CSSPropertyBottom:
l = style->bottom();
break;
default:
return 0;
}
if (l.isPercent() && renderer && renderer->isBox()) {
LayoutUnit containingBlockSize = (propertyID == CSSPropertyLeft || propertyID == CSSPropertyRight) ?
toRenderBox(renderer)->containingBlockLogicalWidthForContent() :
toRenderBox(renderer)->containingBlockLogicalHeightForContent(ExcludeMarginBorderPadding);
return zoomAdjustedPixelValue(valueForLength(l, containingBlockSize, 0), style);
}
if (l.isViewportPercentage())
return zoomAdjustedPixelValue(valueForLength(l, 0, renderView), style);
if (l.isAuto()) {
// FIXME: It's not enough to simply return "auto" values for one offset if the other side is defined.
// In other words if left is auto and right is not auto, then left's computed value is negative right().
// So we should get the opposite length unit and see if it is auto.
return cssValuePool().createValue(l);
}
return zoomAdjustedPixelValueForLength(l, style);
}
PassRefPtr<CSSPrimitiveValue> CSSComputedStyleDeclaration::currentColorOrValidColor(const RenderStyle* style, const Color& color) const
{
// This function does NOT look at visited information, so that computed style doesn't expose that.
if (!color.isValid())
return cssValuePool().createColorValue(style->color().rgb());
return cssValuePool().createColorValue(color.rgb());
}
static PassRefPtr<CSSValueList> valuesForBorderRadiusCorner(LengthSize radius, const RenderStyle* style)
{
RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
if (radius.width().type() == Percent)
list->append(cssValuePool().createValue(radius.width().percent(), CSSPrimitiveValue::CSS_PERCENTAGE));
else
list->append(zoomAdjustedPixelValueForLength(radius.width(), style));
if (radius.height().type() == Percent)
list->append(cssValuePool().createValue(radius.height().percent(), CSSPrimitiveValue::CSS_PERCENTAGE));
else
list->append(zoomAdjustedPixelValueForLength(radius.height(), style));
return list.release();
}
static PassRefPtr<CSSValue> valueForBorderRadiusCorner(LengthSize radius, const RenderStyle* style)
{
RefPtr<CSSValueList> list = valuesForBorderRadiusCorner(radius, style);
if (list->item(0)->equals(*list->item(1)))
return list->item(0);
return list.release();
}
static PassRefPtr<CSSValueList> valueForBorderRadiusShorthand(const RenderStyle* style)
{
RefPtr<CSSValueList> list = CSSValueList::createSlashSeparated();
bool showHorizontalBottomLeft = style->borderTopRightRadius().width() != style->borderBottomLeftRadius().width();
bool showHorizontalBottomRight = showHorizontalBottomLeft || (style->borderBottomRightRadius().width() != style->borderTopLeftRadius().width());
bool showHorizontalTopRight = showHorizontalBottomRight || (style->borderTopRightRadius().width() != style->borderTopLeftRadius().width());
bool showVerticalBottomLeft = style->borderTopRightRadius().height() != style->borderBottomLeftRadius().height();
bool showVerticalBottomRight = showVerticalBottomLeft || (style->borderBottomRightRadius().height() != style->borderTopLeftRadius().height());
bool showVerticalTopRight = showVerticalBottomRight || (style->borderTopRightRadius().height() != style->borderTopLeftRadius().height());
RefPtr<CSSValueList> topLeftRadius = valuesForBorderRadiusCorner(style->borderTopLeftRadius(), style);
RefPtr<CSSValueList> topRightRadius = valuesForBorderRadiusCorner(style->borderTopRightRadius(), style);
RefPtr<CSSValueList> bottomRightRadius = valuesForBorderRadiusCorner(style->borderBottomRightRadius(), style);
RefPtr<CSSValueList> bottomLeftRadius = valuesForBorderRadiusCorner(style->borderBottomLeftRadius(), style);
RefPtr<CSSValueList> horizontalRadii = CSSValueList::createSpaceSeparated();
horizontalRadii->append(topLeftRadius->item(0));
if (showHorizontalTopRight)
horizontalRadii->append(topRightRadius->item(0));
if (showHorizontalBottomRight)
horizontalRadii->append(bottomRightRadius->item(0));
if (showHorizontalBottomLeft)
horizontalRadii->append(bottomLeftRadius->item(0));
list->append(horizontalRadii.release());
RefPtr<CSSValueList> verticalRadii = CSSValueList::createSpaceSeparated();
verticalRadii->append(topLeftRadius->item(1));
if (showVerticalTopRight)
verticalRadii->append(topRightRadius->item(1));
if (showVerticalBottomRight)
verticalRadii->append(bottomRightRadius->item(1));
if (showVerticalBottomLeft)
verticalRadii->append(bottomLeftRadius->item(1));
if (!verticalRadii->equals(*toCSSValueList(list->item(0))))
list->append(verticalRadii.release());
return list.release();
}
static LayoutRect sizingBox(RenderObject* renderer)
{
if (!renderer->isBox())
return LayoutRect();
RenderBox* box = toRenderBox(renderer);
return box->style()->boxSizing() == BORDER_BOX ? box->borderBoxRect() : box->computedCSSContentBoxRect();
}
static PassRefPtr<CSSTransformValue> valueForMatrixTransform(const TransformationMatrix& transform, const RenderStyle* style)
{
RefPtr<CSSTransformValue> transformValue;
if (transform.isAffine()) {
transformValue = CSSTransformValue::create(CSSTransformValue::MatrixTransformOperation);
transformValue->append(cssValuePool().createValue(transform.a(), CSSPrimitiveValue::CSS_NUMBER));
transformValue->append(cssValuePool().createValue(transform.b(), CSSPrimitiveValue::CSS_NUMBER));
transformValue->append(cssValuePool().createValue(transform.c(), CSSPrimitiveValue::CSS_NUMBER));
transformValue->append(cssValuePool().createValue(transform.d(), CSSPrimitiveValue::CSS_NUMBER));
transformValue->append(zoomAdjustedNumberValue(transform.e(), style));
transformValue->append(zoomAdjustedNumberValue(transform.f(), style));
} else {
transformValue = CSSTransformValue::create(CSSTransformValue::Matrix3DTransformOperation);
transformValue->append(cssValuePool().createValue(transform.m11(), CSSPrimitiveValue::CSS_NUMBER));
transformValue->append(cssValuePool().createValue(transform.m12(), CSSPrimitiveValue::CSS_NUMBER));
transformValue->append(cssValuePool().createValue(transform.m13(), CSSPrimitiveValue::CSS_NUMBER));
transformValue->append(cssValuePool().createValue(transform.m14(), CSSPrimitiveValue::CSS_NUMBER));
transformValue->append(cssValuePool().createValue(transform.m21(), CSSPrimitiveValue::CSS_NUMBER));
transformValue->append(cssValuePool().createValue(transform.m22(), CSSPrimitiveValue::CSS_NUMBER));
transformValue->append(cssValuePool().createValue(transform.m23(), CSSPrimitiveValue::CSS_NUMBER));
transformValue->append(cssValuePool().createValue(transform.m24(), CSSPrimitiveValue::CSS_NUMBER));
transformValue->append(cssValuePool().createValue(transform.m31(), CSSPrimitiveValue::CSS_NUMBER));
transformValue->append(cssValuePool().createValue(transform.m32(), CSSPrimitiveValue::CSS_NUMBER));
transformValue->append(cssValuePool().createValue(transform.m33(), CSSPrimitiveValue::CSS_NUMBER));
transformValue->append(cssValuePool().createValue(transform.m34(), CSSPrimitiveValue::CSS_NUMBER));
transformValue->append(zoomAdjustedNumberValue(transform.m41(), style));
transformValue->append(zoomAdjustedNumberValue(transform.m42(), style));
transformValue->append(zoomAdjustedNumberValue(transform.m43(), style));
transformValue->append(cssValuePool().createValue(transform.m44(), CSSPrimitiveValue::CSS_NUMBER));
}
return transformValue.release();
}
static PassRefPtr<CSSValue> computedTransform(RenderObject* renderer, const RenderStyle* style)
{
if (!renderer || !renderer->hasTransform() || !style->hasTransform())
return cssValuePool().createIdentifierValue(CSSValueNone);
IntRect box;
if (renderer->isBox())
box = pixelSnappedIntRect(toRenderBox(renderer)->borderBoxRect());
TransformationMatrix transform;
style->applyTransform(transform, box.size(), RenderStyle::ExcludeTransformOrigin);
// FIXME: Need to print out individual functions (https://bugs.webkit.org/show_bug.cgi?id=23924)
RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
list->append(valueForMatrixTransform(transform, style));
return list.release();
}
static PassRefPtr<CSSValue> valueForCustomFilterArrayParameter(const CustomFilterArrayParameter* arrayParameter)
{
RefPtr<CSSArrayFunctionValue> arrayParameterValue = CSSArrayFunctionValue::create();
for (unsigned i = 0, size = arrayParameter->size(); i < size; ++i)
arrayParameterValue->append(cssValuePool().createValue(arrayParameter->valueAt(i), CSSPrimitiveValue::CSS_NUMBER));
return arrayParameterValue.release();
}
static PassRefPtr<CSSValue> valueForCustomFilterNumberParameter(const CustomFilterNumberParameter* numberParameter)
{
RefPtr<CSSValueList> numberParameterValue = CSSValueList::createSpaceSeparated();
for (unsigned i = 0; i < numberParameter->size(); ++i)
numberParameterValue->append(cssValuePool().createValue(numberParameter->valueAt(i), CSSPrimitiveValue::CSS_NUMBER));
return numberParameterValue.release();
}
static PassRefPtr<CSSValue> valueForCustomFilterTransformParameter(const RenderObject* renderer, const RenderStyle* style, const CustomFilterTransformParameter* transformParameter)
{
IntSize size;
if (renderer && renderer->isBox())
size = pixelSnappedIntRect(toRenderBox(renderer)->borderBoxRect()).size();
TransformationMatrix transform;
transformParameter->applyTransform(transform, size);
// FIXME: Need to print out individual functions (https://bugs.webkit.org/show_bug.cgi?id=23924)
return valueForMatrixTransform(transform, style);
}
static PassRefPtr<CSSValue> valueForCustomFilterParameter(const RenderObject* renderer, const RenderStyle* style, const CustomFilterParameter* parameter)
{
// FIXME: Add here computed style for the other types: boolean, transform, matrix, texture.
ASSERT(parameter);
switch (parameter->parameterType()) {
case CustomFilterParameter::ARRAY:
return valueForCustomFilterArrayParameter(static_cast<const CustomFilterArrayParameter*>(parameter));
case CustomFilterParameter::NUMBER:
return valueForCustomFilterNumberParameter(static_cast<const CustomFilterNumberParameter*>(parameter));
case CustomFilterParameter::TRANSFORM:
return valueForCustomFilterTransformParameter(renderer, style, static_cast<const CustomFilterTransformParameter*>(parameter));
}
ASSERT_NOT_REACHED();
return 0;
}
PassRefPtr<CSSValue> CSSComputedStyleDeclaration::valueForFilter(const RenderObject* renderer, const RenderStyle* style) const
{
if (style->filter().operations().isEmpty())
return cssValuePool().createIdentifierValue(CSSValueNone);
RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
RefPtr<CSSFilterValue> filterValue;
Vector<RefPtr<FilterOperation> >::const_iterator end = style->filter().operations().end();
for (Vector<RefPtr<FilterOperation> >::const_iterator it = style->filter().operations().begin(); it != end; ++it) {
FilterOperation* filterOperation = (*it).get();
switch (filterOperation->getOperationType()) {
case FilterOperation::REFERENCE: {
ReferenceFilterOperation* referenceOperation = static_cast<ReferenceFilterOperation*>(filterOperation);
filterValue = CSSFilterValue::create(CSSFilterValue::ReferenceFilterOperation);
filterValue->append(cssValuePool().createValue(referenceOperation->url(), CSSPrimitiveValue::CSS_STRING));
break;
}
case FilterOperation::GRAYSCALE: {
BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation);
filterValue = CSSFilterValue::create(CSSFilterValue::GrayscaleFilterOperation);
filterValue->append(cssValuePool().createValue(colorMatrixOperation->amount(), CSSPrimitiveValue::CSS_NUMBER));
break;
}
case FilterOperation::SEPIA: {
BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation);
filterValue = CSSFilterValue::create(CSSFilterValue::SepiaFilterOperation);
filterValue->append(cssValuePool().createValue(colorMatrixOperation->amount(), CSSPrimitiveValue::CSS_NUMBER));
break;
}
case FilterOperation::SATURATE: {
BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation);
filterValue = CSSFilterValue::create(CSSFilterValue::SaturateFilterOperation);
filterValue->append(cssValuePool().createValue(colorMatrixOperation->amount(), CSSPrimitiveValue::CSS_NUMBER));
break;
}
case FilterOperation::HUE_ROTATE: {
BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation);
filterValue = CSSFilterValue::create(CSSFilterValue::HueRotateFilterOperation);
filterValue->append(cssValuePool().createValue(colorMatrixOperation->amount(), CSSPrimitiveValue::CSS_DEG));
break;
}
case FilterOperation::INVERT: {
BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation);
filterValue = CSSFilterValue::create(CSSFilterValue::InvertFilterOperation);
filterValue->append(cssValuePool().createValue(componentTransferOperation->amount(), CSSPrimitiveValue::CSS_NUMBER));
break;
}
case FilterOperation::OPACITY: {
BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation);
filterValue = CSSFilterValue::create(CSSFilterValue::OpacityFilterOperation);
filterValue->append(cssValuePool().createValue(componentTransferOperation->amount(), CSSPrimitiveValue::CSS_NUMBER));
break;
}
case FilterOperation::BRIGHTNESS: {
BasicComponentTransferFilterOperation* brightnessOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation);
filterValue = CSSFilterValue::create(CSSFilterValue::BrightnessFilterOperation);
filterValue->append(cssValuePool().createValue(brightnessOperation->amount(), CSSPrimitiveValue::CSS_NUMBER));
break;
}
case FilterOperation::CONTRAST: {
BasicComponentTransferFilterOperation* contrastOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation);
filterValue = CSSFilterValue::create(CSSFilterValue::ContrastFilterOperation);
filterValue->append(cssValuePool().createValue(contrastOperation->amount(), CSSPrimitiveValue::CSS_NUMBER));
break;
}
case FilterOperation::BLUR: {
BlurFilterOperation* blurOperation = static_cast<BlurFilterOperation*>(filterOperation);
filterValue = CSSFilterValue::create(CSSFilterValue::BlurFilterOperation);
filterValue->append(zoomAdjustedPixelValue(blurOperation->stdDeviation().value(), style));
break;
}
case FilterOperation::DROP_SHADOW: {
DropShadowFilterOperation* dropShadowOperation = static_cast<DropShadowFilterOperation*>(filterOperation);
filterValue = CSSFilterValue::create(CSSFilterValue::DropShadowFilterOperation);
// We want our computed style to look like that of a text shadow (has neither spread nor inset style).
ShadowData shadow(dropShadowOperation->location(), dropShadowOperation->stdDeviation(), 0, Normal, dropShadowOperation->color());
filterValue->append(valueForShadowData(shadow, style, false));
break;
}
case FilterOperation::VALIDATED_CUSTOM:
// ValidatedCustomFilterOperation is not supposed to end up in the RenderStyle.
ASSERT_NOT_REACHED();
break;
case FilterOperation::CUSTOM: {
CustomFilterOperation* customOperation = static_cast<CustomFilterOperation*>(filterOperation);
filterValue = CSSFilterValue::create(CSSFilterValue::CustomFilterOperation);
// The output should be verbose, even if the values are the default ones.
ASSERT(customOperation->program());
StyleCustomFilterProgram* program = static_cast<StyleCustomFilterProgram*>(customOperation->program());
RefPtr<CSSValueList> shadersList = CSSValueList::createSpaceSeparated();
if (program->vertexShader())
shadersList->append(program->vertexShader()->cssValue());
else
shadersList->append(cssValuePool().createIdentifierValue(CSSValueNone));
const CustomFilterProgramMixSettings mixSettings = program->mixSettings();
if (program->fragmentShader()) {
if (program->programType() == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE) {
RefPtr<CSSMixFunctionValue> mixFunction = CSSMixFunctionValue::create();
mixFunction->append(program->fragmentShader()->cssValue());
mixFunction->append(cssValuePool().createValue(mixSettings.blendMode));
mixFunction->append(cssValuePool().createValue(mixSettings.compositeOperator));
shadersList->append(mixFunction.release());
} else
shadersList->append(program->fragmentShader()->cssValue());
}
else
shadersList->append(cssValuePool().createIdentifierValue(CSSValueNone));
filterValue->append(shadersList.release());
RefPtr<CSSValueList> meshParameters = CSSValueList::createSpaceSeparated();
meshParameters->append(cssValuePool().createValue(customOperation->meshColumns(), CSSPrimitiveValue::CSS_NUMBER));
meshParameters->append(cssValuePool().createValue(customOperation->meshRows(), CSSPrimitiveValue::CSS_NUMBER));
// FIXME: The specification doesn't have any "attached" identifier. Should we add one?
// https://bugs.webkit.org/show_bug.cgi?id=72700
if (customOperation->meshType() == MeshTypeDetached)
meshParameters->append(cssValuePool().createIdentifierValue(CSSValueDetached));
filterValue->append(meshParameters.release());
const CustomFilterParameterList& parameters = customOperation->parameters();
size_t parametersSize = parameters.size();
if (!parametersSize)
break;
RefPtr<CSSValueList> parametersCSSValue = CSSValueList::createCommaSeparated();
for (size_t i = 0; i < parametersSize; ++i) {
const CustomFilterParameter* parameter = parameters.at(i).get();
RefPtr<CSSValueList> parameterCSSNameAndValue = CSSValueList::createSpaceSeparated();
parameterCSSNameAndValue->append(cssValuePool().createValue(parameter->name(), CSSPrimitiveValue::CSS_STRING));
parameterCSSNameAndValue->append(valueForCustomFilterParameter(renderer, style, parameter));
parametersCSSValue->append(parameterCSSNameAndValue.release());
}
filterValue->append(parametersCSSValue.release());
break;
}
default:
filterValue = CSSFilterValue::create(CSSFilterValue::UnknownFilterOperation);
break;
}
list->append(filterValue.release());
}
return list.release();
}
static PassRefPtr<CSSValue> valueForGridTrackBreadth(const GridLength& trackBreadth, const RenderStyle* style, RenderView* renderView)
{
if (!trackBreadth.isLength())
return cssValuePool().createValue(trackBreadth.flex(), CSSPrimitiveValue::CSS_FR);
const Length& trackBreadthLength = trackBreadth.length();
if (trackBreadthLength.isAuto())
return cssValuePool().createIdentifierValue(CSSValueAuto);
if (trackBreadthLength.isViewportPercentage())
return zoomAdjustedPixelValue(valueForLength(trackBreadthLength, 0, renderView), style);
return zoomAdjustedPixelValueForLength(trackBreadthLength, style);
}
static PassRefPtr<CSSValue> valueForGridTrackSize(const GridTrackSize& trackSize, const RenderStyle* style, RenderView* renderView)
{
switch (trackSize.type()) {
case LengthTrackSizing:
return valueForGridTrackBreadth(trackSize.length(), style, renderView);
case MinMaxTrackSizing:
RefPtr<CSSValueList> minMaxTrackBreadths = CSSValueList::createCommaSeparated();
minMaxTrackBreadths->append(valueForGridTrackBreadth(trackSize.minTrackBreadth(), style, renderView));
minMaxTrackBreadths->append(valueForGridTrackBreadth(trackSize.maxTrackBreadth(), style, renderView));
return CSSFunctionValue::create("minmax(", minMaxTrackBreadths);
}
ASSERT_NOT_REACHED();
return 0;
}
static void addValuesForNamedGridLinesAtIndex(const OrderedNamedGridLines& orderedNamedGridLines, size_t i, CSSValueList& list)
{
const Vector<String>& namedGridLines = orderedNamedGridLines.get(i);
for (size_t j = 0; j < namedGridLines.size(); ++j)
list.append(cssValuePool().createValue(namedGridLines[j], CSSPrimitiveValue::CSS_STRING));
}
static PassRefPtr<CSSValue> valueForGridTrackList(const Vector<GridTrackSize>& trackSizes, const OrderedNamedGridLines& orderedNamedGridLines, const RenderStyle* style, RenderView* renderView)
{
// Handle the 'none' case here.
if (!trackSizes.size()) {
ASSERT(orderedNamedGridLines.isEmpty());
return cssValuePool().createIdentifierValue(CSSValueNone);
}
RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
for (size_t i = 0; i < trackSizes.size(); ++i) {
addValuesForNamedGridLinesAtIndex(orderedNamedGridLines, i, *list);
list->append(valueForGridTrackSize(trackSizes[i], style, renderView));
}
// Those are the trailing <string>* allowed in the syntax.
addValuesForNamedGridLinesAtIndex(orderedNamedGridLines, trackSizes.size(), *list);
return list.release();
}
static PassRefPtr<CSSValue> valueForGridPosition(const GridPosition& position)
{
if (position.isAuto())
return cssValuePool().createIdentifierValue(CSSValueAuto);
if (position.isNamedGridArea())
return cssValuePool().createValue(position.namedGridLine(), CSSPrimitiveValue::CSS_STRING);
RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
if (position.isSpan()) {
list->append(cssValuePool().createIdentifierValue(CSSValueSpan));
list->append(cssValuePool().createValue(position.spanPosition(), CSSPrimitiveValue::CSS_NUMBER));
} else
list->append(cssValuePool().createValue(position.integerPosition(), CSSPrimitiveValue::CSS_NUMBER));
if (!position.namedGridLine().isNull())
list->append(cssValuePool().createValue(position.namedGridLine(), CSSPrimitiveValue::CSS_STRING));
return list;
}
static PassRefPtr<CSSValue> createTransitionPropertyValue(const CSSAnimationData* animation)
{
RefPtr<CSSValue> propertyValue;
if (animation->animationMode() == CSSAnimationData::AnimateNone)
propertyValue = cssValuePool().createIdentifierValue(CSSValueNone);
else if (animation->animationMode() == CSSAnimationData::AnimateAll)
propertyValue = cssValuePool().createIdentifierValue(CSSValueAll);
else
propertyValue = cssValuePool().createValue(getPropertyNameString(animation->property()), CSSPrimitiveValue::CSS_STRING);
return propertyValue.release();
}
static PassRefPtr<CSSValue> valueForTransitionProperty(const CSSAnimationDataList* animList)
{
RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
if (animList) {
for (size_t i = 0; i < animList->size(); ++i)
list->append(createTransitionPropertyValue(animList->animation(i)));
} else
list->append(cssValuePool().createIdentifierValue(CSSValueAll));
return list.release();
}
static PassRefPtr<CSSValue> valueForAnimationDelay(const CSSAnimationDataList* animList)
{
RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
if (animList) {
for (size_t i = 0; i < animList->size(); ++i)
list->append(cssValuePool().createValue(animList->animation(i)->delay(), CSSPrimitiveValue::CSS_S));
} else {
// Note that initialAnimationDelay() is used for both transitions and animations
list->append(cssValuePool().createValue(CSSAnimationData::initialAnimationDelay(), CSSPrimitiveValue::CSS_S));
}
return list.release();
}
static PassRefPtr<CSSValue> valueForAnimationDuration(const CSSAnimationDataList* animList)
{
RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
if (animList) {
for (size_t i = 0; i < animList->size(); ++i)
list->append(cssValuePool().createValue(animList->animation(i)->duration(), CSSPrimitiveValue::CSS_S));
} else {
// Note that initialAnimationDuration() is used for both transitions and animations
list->append(cssValuePool().createValue(CSSAnimationData::initialAnimationDuration(), CSSPrimitiveValue::CSS_S));
}
return list.release();
}
static PassRefPtr<CSSValue> createTimingFunctionValue(const TimingFunction* timingFunction)
{
switch (timingFunction->type()) {
case TimingFunction::CubicBezierFunction:
{
const CubicBezierTimingFunction* bezierTimingFunction = static_cast<const CubicBezierTimingFunction*>(timingFunction);
if (bezierTimingFunction->subType() != CubicBezierTimingFunction::Custom) {
CSSValueID valueId = CSSValueInvalid;
switch (bezierTimingFunction->subType()) {
case CubicBezierTimingFunction::Ease:
valueId = CSSValueEase;
break;
case CubicBezierTimingFunction::EaseIn:
valueId = CSSValueEaseIn;
break;
case CubicBezierTimingFunction::EaseOut:
valueId = CSSValueEaseOut;
break;
case CubicBezierTimingFunction::EaseInOut:
valueId = CSSValueEaseInOut;
break;
default:
ASSERT_NOT_REACHED();
return 0;
}
return cssValuePool().createIdentifierValue(valueId);
}
return CSSCubicBezierTimingFunctionValue::create(bezierTimingFunction->x1(), bezierTimingFunction->y1(), bezierTimingFunction->x2(), bezierTimingFunction->y2());
}
case TimingFunction::StepsFunction:
{
const StepsTimingFunction* stepsTimingFunction = static_cast<const StepsTimingFunction*>(timingFunction);
if (stepsTimingFunction->subType() == StepsTimingFunction::Custom)
return CSSStepsTimingFunctionValue::create(stepsTimingFunction->numberOfSteps(), stepsTimingFunction->stepAtStart());
CSSValueID valueId;
switch (stepsTimingFunction->subType()) {
case StepsTimingFunction::Start:
valueId = CSSValueStepStart;
break;
case StepsTimingFunction::End:
valueId = CSSValueStepEnd;
break;
default:
ASSERT_NOT_REACHED();
return 0;
}
return cssValuePool().createIdentifierValue(valueId);
}
default:
return cssValuePool().createIdentifierValue(CSSValueLinear);
}
}
static PassRefPtr<CSSValue> valueForAnimationTimingFunction(const CSSAnimationDataList* animList)
{
RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
if (animList) {
for (size_t i = 0; i < animList->size(); ++i)
list->append(createTimingFunctionValue(animList->animation(i)->timingFunction()));
} else
// Note that initialAnimationTimingFunction() is used for both transitions and animations
list->append(createTimingFunctionValue(CSSAnimationData::initialAnimationTimingFunction().get()));
return list.release();
}
static PassRefPtr<CSSValue> valueForAnimationFillMode(unsigned fillMode)
{
switch (fillMode) {
case AnimationFillModeNone:
return cssValuePool().createIdentifierValue(CSSValueNone);
case AnimationFillModeForwards:
return cssValuePool().createIdentifierValue(CSSValueForwards);
case AnimationFillModeBackwards:
return cssValuePool().createIdentifierValue(CSSValueBackwards);
case AnimationFillModeBoth:
return cssValuePool().createIdentifierValue(CSSValueBoth);
default:
ASSERT_NOT_REACHED();
return 0;
}
}
static PassRefPtr<CSSValue> valueForAnimationDirection(CSSAnimationData::AnimationDirection direction)
{
switch (direction) {
case CSSAnimationData::AnimationDirectionNormal:
return cssValuePool().createIdentifierValue(CSSValueNormal);
case CSSAnimationData::AnimationDirectionAlternate:
return cssValuePool().createIdentifierValue(CSSValueAlternate);
case CSSAnimationData::AnimationDirectionReverse:
return cssValuePool().createIdentifierValue(CSSValueReverse);
case CSSAnimationData::AnimationDirectionAlternateReverse:
return cssValuePool().createIdentifierValue(CSSValueAlternateReverse);
default:
ASSERT_NOT_REACHED();
return 0;
}
}
static PassRefPtr<CSSValue> createLineBoxContainValue(unsigned lineBoxContain)
{
if (!lineBoxContain)
return cssValuePool().createIdentifierValue(CSSValueNone);
return CSSLineBoxContainValue::create(lineBoxContain);
}
CSSComputedStyleDeclaration::CSSComputedStyleDeclaration(PassRefPtr<Node> n, bool allowVisitedStyle, const String& pseudoElementName)
: m_node(n)
, m_allowVisitedStyle(allowVisitedStyle)
, m_refCount(1)
{
unsigned nameWithoutColonsStart = pseudoElementName[0] == ':' ? (pseudoElementName[1] == ':' ? 2 : 1) : 0;
m_pseudoElementSpecifier = CSSSelector::pseudoId(CSSSelector::parsePseudoType(
AtomicString(pseudoElementName.substring(nameWithoutColonsStart))));
}
CSSComputedStyleDeclaration::~CSSComputedStyleDeclaration()
{
}
void CSSComputedStyleDeclaration::ref()
{
++m_refCount;
}
void CSSComputedStyleDeclaration::deref()
{
ASSERT(m_refCount);
if (!--m_refCount)
delete this;
}
String CSSComputedStyleDeclaration::cssText() const
{
StringBuilder result;
const Vector<CSSPropertyID>& properties = computableProperties();
for (unsigned i = 0; i < properties.size(); i++) {
if (i)
result.append(' ');
result.append(getPropertyName(properties[i]));
result.append(": ", 2);
result.append(getPropertyValue(properties[i]));
result.append(';');
}
return result.toString();
}
void CSSComputedStyleDeclaration::setCSSText(const String&, ExceptionState& es)
{
es.throwDOMException(NoModificationAllowedError, "Failed to set the 'cssText' property on a computed 'CSSStyleDeclaration': computed styles are read-only.");
}
static CSSValueID cssIdentifierForFontSizeKeyword(int keywordSize)
{
ASSERT_ARG(keywordSize, keywordSize);
ASSERT_ARG(keywordSize, keywordSize <= 8);
return static_cast<CSSValueID>(CSSValueXxSmall + keywordSize - 1);
}
PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getFontSizeCSSValuePreferringKeyword() const
{
if (!m_node)
return 0;
m_node->document().updateLayoutIgnorePendingStylesheets();
RefPtr<RenderStyle> style = m_node->computedStyle(m_pseudoElementSpecifier);
if (!style)
return 0;
if (int keywordSize = style->fontDescription().keywordSize())
return cssValuePool().createIdentifierValue(cssIdentifierForFontSizeKeyword(keywordSize));
return zoomAdjustedPixelValue(style->fontDescription().computedPixelSize(), style.get());
}
bool CSSComputedStyleDeclaration::useFixedFontDefaultSize() const
{
if (!m_node)
return false;
RefPtr<RenderStyle> style = m_node->computedStyle(m_pseudoElementSpecifier);
if (!style)
return false;
return style->fontDescription().useFixedDefaultSize();
}
PassRefPtr<CSSValue> CSSComputedStyleDeclaration::valueForShadowData(const ShadowData& shadow, const RenderStyle* style, bool useSpread) const
{
RefPtr<CSSPrimitiveValue> x = zoomAdjustedPixelValue(shadow.x(), style);
RefPtr<CSSPrimitiveValue> y = zoomAdjustedPixelValue(shadow.y(), style);
RefPtr<CSSPrimitiveValue> blur = zoomAdjustedPixelValue(shadow.blur(), style);
RefPtr<CSSPrimitiveValue> spread = useSpread ? zoomAdjustedPixelValue(shadow.spread(), style) : PassRefPtr<CSSPrimitiveValue>();
RefPtr<CSSPrimitiveValue> shadowStyle = shadow.style() == Normal ? PassRefPtr<CSSPrimitiveValue>() : cssValuePool().createIdentifierValue(CSSValueInset);
RefPtr<CSSPrimitiveValue> color = currentColorOrValidColor(style, shadow.color());
return CSSShadowValue::create(x.release(), y.release(), blur.release(), spread.release(), shadowStyle.release(), color.release());
}
PassRefPtr<CSSValue> CSSComputedStyleDeclaration::valueForShadowList(const ShadowList* shadowList, const RenderStyle* style, bool useSpread) const
{
if (!shadowList)
return cssValuePool().createIdentifierValue(CSSValueNone);
RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
size_t shadowCount = shadowList->shadows().size();
for (size_t i = 0; i < shadowCount; ++i)
list->append(valueForShadowData(shadowList->shadows()[i], style, useSpread));
return list.release();
}
PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropertyID propertyID) const
{
return getPropertyCSSValue(propertyID, UpdateLayout);
}
static CSSValueID identifierForFamily(const AtomicString& family)
{
if (family == FontFamilyNames::webkit_cursive)
return CSSValueCursive;
if (family == FontFamilyNames::webkit_fantasy)
return CSSValueFantasy;
if (family == FontFamilyNames::webkit_monospace)
return CSSValueMonospace;
if (family == FontFamilyNames::webkit_pictograph)
return CSSValueWebkitPictograph;
if (family == FontFamilyNames::webkit_sans_serif)
return CSSValueSansSerif;
if (family == FontFamilyNames::webkit_serif)
return CSSValueSerif;
return CSSValueInvalid;
}
static PassRefPtr<CSSPrimitiveValue> valueForFamily(const AtomicString& family)
{
if (CSSValueID familyIdentifier = identifierForFamily(family))
return cssValuePool().createIdentifierValue(familyIdentifier);
return cssValuePool().createValue(family.string(), CSSPrimitiveValue::CSS_STRING);
}
static PassRefPtr<CSSValue> renderTextDecorationFlagsToCSSValue(int textDecoration)
{
// Blink value is ignored.
RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
if (textDecoration & TextDecorationUnderline)
list->append(cssValuePool().createIdentifierValue(CSSValueUnderline));
if (textDecoration & TextDecorationOverline)
list->append(cssValuePool().createIdentifierValue(CSSValueOverline));
if (textDecoration & TextDecorationLineThrough)
list->append(cssValuePool().createIdentifierValue(CSSValueLineThrough));
if (!list->length())
return cssValuePool().createIdentifierValue(CSSValueNone);
return list.release();
}
static PassRefPtr<CSSValue> valueForTextDecorationStyle(TextDecorationStyle textDecorationStyle)
{
switch (textDecorationStyle) {
case TextDecorationStyleSolid:
return cssValuePool().createIdentifierValue(CSSValueSolid);
case TextDecorationStyleDouble:
return cssValuePool().createIdentifierValue(CSSValueDouble);
case TextDecorationStyleDotted:
return cssValuePool().createIdentifierValue(CSSValueDotted);
case TextDecorationStyleDashed:
return cssValuePool().createIdentifierValue(CSSValueDashed);
case TextDecorationStyleWavy:
return cssValuePool().createIdentifierValue(CSSValueWavy);
}
ASSERT_NOT_REACHED();
return cssValuePool().createExplicitInitialValue();
}
static PassRefPtr<CSSValue> valueForFillRepeat(EFillRepeat xRepeat, EFillRepeat yRepeat)
{
// For backwards compatibility, if both values are equal, just return one of them. And
// if the two values are equivalent to repeat-x or repeat-y, just return the shorthand.
if (xRepeat == yRepeat)
return cssValuePool().createValue(xRepeat);
if (xRepeat == RepeatFill && yRepeat == NoRepeatFill)
return cssValuePool().createIdentifierValue(CSSValueRepeatX);
if (xRepeat == NoRepeatFill && yRepeat == RepeatFill)
return cssValuePool().createIdentifierValue(CSSValueRepeatY);
RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
list->append(cssValuePool().createValue(xRepeat));
list->append(cssValuePool().createValue(yRepeat));
return list.release();
}
static PassRefPtr<CSSValue> valueForFillSourceType(EMaskSourceType type)
{
switch (type) {
case MaskAlpha:
return cssValuePool().createValue(CSSValueAlpha);
case MaskLuminance:
return cssValuePool().createValue(CSSValueLuminance);
}
ASSERT_NOT_REACHED();
return 0;
}
static PassRefPtr<CSSValue> valueForFillSize(const FillSize& fillSize, const RenderStyle* style)
{
if (fillSize.type == Contain)
return cssValuePool().createIdentifierValue(CSSValueContain);
if (fillSize.type == Cover)
return cssValuePool().createIdentifierValue(CSSValueCover);
if (fillSize.size.height().isAuto())
return zoomAdjustedPixelValueForLength(fillSize.size.width(), style);
RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
list->append(zoomAdjustedPixelValueForLength(fillSize.size.width(), style));
list->append(zoomAdjustedPixelValueForLength(fillSize.size.height(), style));
return list.release();
}
static PassRefPtr<CSSValue> valueForContentData(const RenderStyle* style)
{
RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
for (const ContentData* contentData = style->contentData(); contentData; contentData = contentData->next()) {
if (contentData->isCounter()) {
const CounterContent* counter = static_cast<const CounterContentData*>(contentData)->counter();
ASSERT(counter);
list->append(cssValuePool().createValue(counter->identifier(), CSSPrimitiveValue::CSS_COUNTER_NAME));
} else if (contentData->isImage()) {
const StyleImage* image = static_cast<const ImageContentData*>(contentData)->image();
ASSERT(image);
list->append(image->cssValue());
} else if (contentData->isText())
list->append(cssValuePool().createValue(static_cast<const TextContentData*>(contentData)->text(), CSSPrimitiveValue::CSS_STRING));
}
if (style->hasFlowFrom())
list->append(cssValuePool().createValue(style->regionThread(), CSSPrimitiveValue::CSS_STRING));
return list.release();
}
static PassRefPtr<CSSValue> valueForCounterDirectives(const RenderStyle* style, CSSPropertyID propertyID)
{
const CounterDirectiveMap* map = style->counterDirectives();
if (!map)
return 0;
RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
for (CounterDirectiveMap::const_iterator it = map->begin(); it != map->end(); ++it) {
list->append(cssValuePool().createValue(it->key, CSSPrimitiveValue::CSS_STRING));
short number = propertyID == CSSPropertyCounterIncrement ? it->value.incrementValue() : it->value.resetValue();
list->append(cssValuePool().createValue((double)number, CSSPrimitiveValue::CSS_NUMBER));
}
return list.release();
}
static void logUnimplementedPropertyID(CSSPropertyID propertyID)
{
DEFINE_STATIC_LOCAL(HashSet<CSSPropertyID>, propertyIDSet, ());
if (!propertyIDSet.add(propertyID).isNewEntry)
return;
LOG_ERROR("WebKit does not yet implement getComputedStyle for '%s'.", getPropertyName(propertyID));
}
static PassRefPtr<CSSValueList> valueForFontFamily(RenderStyle* style)
{
const FontFamily& firstFamily = style->fontDescription().family();
RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
for (const FontFamily* family = &firstFamily; family; family = family->next())
list->append(valueForFamily(family->family()));
return list.release();
}
static PassRefPtr<CSSPrimitiveValue> valueForLineHeight(RenderStyle* style, RenderView* renderView)
{
Length length = style->lineHeight();
if (length.isNegative())
return cssValuePool().createIdentifierValue(CSSValueNormal);
if (length.isPercent())
// This is imperfect, because it doesn't include the zoom factor and the real computation
// for how high to be in pixels does include things like minimum font size and the zoom factor.
// On the other hand, since font-size doesn't include the zoom factor, we really can't do
// that here either.
return zoomAdjustedPixelValue(static_cast<int>(length.percent() * style->fontDescription().specifiedSize()) / 100, style);
return zoomAdjustedPixelValue(floatValueForLength(length, 0, renderView), style);
}
static PassRefPtr<CSSPrimitiveValue> valueForFontSize(RenderStyle* style)
{
return zoomAdjustedPixelValue(style->fontDescription().computedPixelSize(), style);
}
static PassRefPtr<CSSPrimitiveValue> valueForFontStyle(RenderStyle* style)
{
if (style->fontDescription().italic())
return cssValuePool().createIdentifierValue(CSSValueItalic);
return cssValuePool().createIdentifierValue(CSSValueNormal);
}
static PassRefPtr<CSSPrimitiveValue> valueForFontVariant(RenderStyle* style)
{
if (style->fontDescription().smallCaps())
return cssValuePool().createIdentifierValue(CSSValueSmallCaps);
return cssValuePool().createIdentifierValue(CSSValueNormal);
}
static PassRefPtr<CSSPrimitiveValue> valueForFontWeight(RenderStyle* style)
{
switch (style->fontDescription().weight()) {
case FontWeight100:
return cssValuePool().createIdentifierValue(CSSValue100);
case FontWeight200:
return cssValuePool().createIdentifierValue(CSSValue200);
case FontWeight300:
return cssValuePool().createIdentifierValue(CSSValue300);
case FontWeightNormal:
return cssValuePool().createIdentifierValue(CSSValueNormal);
case FontWeight500:
return cssValuePool().createIdentifierValue(CSSValue500);
case FontWeight600:
return cssValuePool().createIdentifierValue(CSSValue600);
case FontWeightBold:
return cssValuePool().createIdentifierValue(CSSValueBold);
case FontWeight800:
return cssValuePool().createIdentifierValue(CSSValue800);
case FontWeight900:
return cssValuePool().createIdentifierValue(CSSValue900);
}
ASSERT_NOT_REACHED();
return cssValuePool().createIdentifierValue(CSSValueNormal);
}
static bool isLayoutDependent(CSSPropertyID propertyID, PassRefPtr<RenderStyle> style, RenderObject* renderer)
{
// Some properties only depend on layout in certain conditions which
// are specified in the main switch statement below. So we can avoid
// forcing layout in those conditions. The conditions in this switch
// statement must remain in sync with the conditions in the main switch.
// FIXME: Some of these cases could be narrowed down or optimized better.
switch (propertyID) {
case CSSPropertyBottom:
case CSSPropertyHeight:
case CSSPropertyLeft:
case CSSPropertyRight:
case CSSPropertyTop:
case CSSPropertyWebkitPerspectiveOrigin:
case CSSPropertyWebkitTransform:
case CSSPropertyWebkitTransformOrigin:
case CSSPropertyWidth:
case CSSPropertyWebkitFilter:
return true;
case CSSPropertyMargin:
return renderer && renderer->isBox() && (!style || !style->marginBottom().isFixed() || !style->marginTop().isFixed() || !style->marginLeft().isFixed() || !style->marginRight().isFixed());
case CSSPropertyMarginLeft:
return renderer && renderer->isBox() && (!style || !style->marginLeft().isFixed());
case CSSPropertyMarginRight:
return renderer && renderer->isBox() && (!style || !style->marginRight().isFixed());
case CSSPropertyMarginTop:
return renderer && renderer->isBox() && (!style || !style->marginTop().isFixed());
case CSSPropertyMarginBottom:
return renderer && renderer->isBox() && (!style || !style->marginBottom().isFixed());
case CSSPropertyPadding:
return renderer && renderer->isBox() && (!style || !style->paddingBottom().isFixed() || !style->paddingTop().isFixed() || !style->paddingLeft().isFixed() || !style->paddingRight().isFixed());
case CSSPropertyPaddingBottom:
return renderer && renderer->isBox() && (!style || !style->paddingBottom().isFixed());
case CSSPropertyPaddingLeft:
return renderer && renderer->isBox() && (!style || !style->paddingLeft().isFixed());
case CSSPropertyPaddingRight:
return renderer && renderer->isBox() && (!style || !style->paddingRight().isFixed());
case CSSPropertyPaddingTop:
return renderer && renderer->isBox() && (!style || !style->paddingTop().isFixed());
default:
return false;
}
}
PassRefPtr<RenderStyle> CSSComputedStyleDeclaration::computeRenderStyle(CSSPropertyID propertyID) const
{
Node* styledNode = this->styledNode();
ASSERT(styledNode);
RenderObject* renderer = styledNode->renderer();
if (renderer && renderer->compositingState() == PaintsIntoOwnBacking
&& !RuntimeEnabledFeatures::webAnimationsCSSEnabled() && AnimationController::supportsAcceleratedAnimationOfProperty(propertyID)) {
AnimationUpdateBlock animationUpdateBlock(renderer->animation());
if (m_pseudoElementSpecifier && !styledNode->isPseudoElement()) {
// FIXME: This cached pseudo style will only exist if the animation has been run at least once.
return renderer->animation().getAnimatedStyleForRenderer(renderer)->getCachedPseudoStyle(m_pseudoElementSpecifier);
}
return renderer->animation().getAnimatedStyleForRenderer(renderer);
}
return styledNode->computedStyle(styledNode->isPseudoElement() ? NOPSEUDO : m_pseudoElementSpecifier);
}
Node* CSSComputedStyleDeclaration::styledNode() const
{
if (!m_node)
return 0;
if (m_node->isElementNode()) {
if (PseudoElement* element = toElement(m_node)->pseudoElement(m_pseudoElementSpecifier))
return element;
}
return m_node.get();
}
PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropertyID propertyID, EUpdateLayout updateLayout) const
{
Node* styledNode = this->styledNode();
if (!styledNode)
return 0;
RenderObject* renderer = styledNode->renderer();
RefPtr<RenderStyle> style;
if (updateLayout) {
Document& document = styledNode->document();
document.updateStyleForNodeIfNeeded(styledNode);
// The style recalc could have caused the styled node to be discarded or replaced
// if it was a PseudoElement so we need to update it.
styledNode = this->styledNode();
renderer = styledNode->renderer();
style = computeRenderStyle(propertyID);
bool forceFullLayout = isLayoutDependent(propertyID, style, renderer)
|| styledNode->isInShadowTree()
|| (document.styleResolverIfExists() && document.styleResolverIfExists()->hasViewportDependentMediaQueries() && document.ownerElement())
|| document.seamlessParentIFrame();
if (forceFullLayout) {
document.updateLayoutIgnorePendingStylesheets();
styledNode = this->styledNode();
style = computeRenderStyle(propertyID);
renderer = styledNode->renderer();
}
} else {
style = computeRenderStyle(propertyID);
}
if (!style)
return 0;
propertyID = CSSProperty::resolveDirectionAwareProperty(propertyID, style->direction(), style->writingMode());
switch (propertyID) {
case CSSPropertyInvalid:
case CSSPropertyVariable:
break;
case CSSPropertyBackgroundColor:
return cssValuePool().createColorValue(m_allowVisitedStyle? style->visitedDependentColor(CSSPropertyBackgroundColor).rgb() : style->backgroundColor().rgb());
case CSSPropertyBackgroundImage:
case CSSPropertyWebkitMaskImage: {
const FillLayer* layers = propertyID == CSSPropertyWebkitMaskImage ? style->maskLayers() : style->backgroundLayers();
if (!layers)
return cssValuePool().createIdentifierValue(CSSValueNone);
if (!layers->next()) {
if (layers->image())
return layers->image()->cssValue();
return cssValuePool().createIdentifierValue(CSSValueNone);
}
RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next()) {
if (currLayer->image())
list->append(currLayer->image()->cssValue());
else
list->append(cssValuePool().createIdentifierValue(CSSValueNone));
}
return list.release();
}
case CSSPropertyBackgroundSize:
case CSSPropertyWebkitBackgroundSize:
case CSSPropertyWebkitMaskSize: {
const FillLayer* layers = propertyID == CSSPropertyWebkitMaskSize ? style->maskLayers() : style->backgroundLayers();
if (!layers->next())
return valueForFillSize(layers->size(), style.get());
RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next())
list->append(valueForFillSize(currLayer->size(), style.get()));
return list.release();
}
case CSSPropertyBackgroundRepeat:
case CSSPropertyWebkitMaskRepeat: {
const FillLayer* layers = propertyID == CSSPropertyWebkitMaskRepeat ? style->maskLayers() : style->backgroundLayers();
if (!layers->next())
return valueForFillRepeat(layers->repeatX(), layers->repeatY());
RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next())
list->append(valueForFillRepeat(currLayer->repeatX(), currLayer->repeatY()));
return list.release();
}
case CSSPropertyMaskSourceType: {
const FillLayer* layers = style->maskLayers();
if (!layers)
return cssValuePool().createIdentifierValue(CSSValueNone);
if (!layers->next())
return valueForFillSourceType(layers->maskSourceType());
RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next())
list->append(valueForFillSourceType(currLayer->maskSourceType()));
return list.release();
}
case CSSPropertyWebkitBackgroundComposite:
case CSSPropertyWebkitMaskComposite: {
const FillLayer* layers = propertyID == CSSPropertyWebkitMaskComposite ? style->maskLayers() : style->backgroundLayers();
if (!layers->next())
return cssValuePool().createValue(layers->composite());
RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next())
list->append(cssValuePool().createValue(currLayer->composite()));
return list.release();
}
case CSSPropertyBackgroundAttachment: {
const FillLayer* layers = style->backgroundLayers();
if (!layers->next())
return cssValuePool().createValue(layers->attachment());
RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next())
list->append(cssValuePool().createValue(currLayer->attachment()));
return list.release();
}
case CSSPropertyBackgroundClip:
case CSSPropertyBackgroundOrigin:
case CSSPropertyWebkitBackgroundClip:
case CSSPropertyWebkitBackgroundOrigin:
case CSSPropertyWebkitMaskClip:
case CSSPropertyWebkitMaskOrigin: {
const FillLayer* layers = (propertyID == CSSPropertyWebkitMaskClip || propertyID == CSSPropertyWebkitMaskOrigin) ? style->maskLayers() : style->backgroundLayers();
bool isClip = propertyID == CSSPropertyBackgroundClip || propertyID == CSSPropertyWebkitBackgroundClip || propertyID == CSSPropertyWebkitMaskClip;
if (!layers->next()) {
EFillBox box = isClip ? layers->clip() : layers->origin();
return cssValuePool().createValue(box);
}
RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next()) {
EFillBox box = isClip ? currLayer->clip() : currLayer->origin();
list->append(cssValuePool().createValue(box));
}
return list.release();
}
case CSSPropertyBackgroundPosition:
case CSSPropertyWebkitMaskPosition: {
const FillLayer* layers = propertyID == CSSPropertyWebkitMaskPosition ? style->maskLayers() : style->backgroundLayers();
if (!layers->next())
return createPositionListForLayer(propertyID, layers, style.get());
RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next())
list->append(createPositionListForLayer(propertyID, currLayer, style.get()));
return list.release();
}
case CSSPropertyBackgroundPositionX:
case CSSPropertyWebkitMaskPositionX: {
const FillLayer* layers = propertyID == CSSPropertyWebkitMaskPositionX ? style->maskLayers() : style->backgroundLayers();
if (!layers->next())
return cssValuePool().createValue(layers->xPosition());
RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next())
list->append(cssValuePool().createValue(currLayer->xPosition()));
return list.release();
}
case CSSPropertyBackgroundPositionY:
case CSSPropertyWebkitMaskPositionY: {
const FillLayer* layers = propertyID == CSSPropertyWebkitMaskPositionY ? style->maskLayers() : style->backgroundLayers();
if (!layers->next())
return cssValuePool().createValue(layers->yPosition());
RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next())
list->append(cssValuePool().createValue(currLayer->yPosition()));
return list.release();
}
case CSSPropertyBorderCollapse:
if (style->borderCollapse())
return cssValuePool().createIdentifierValue(CSSValueCollapse);
return cssValuePool().createIdentifierValue(CSSValueSeparate);
case CSSPropertyBorderSpacing: {
RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
list->append(zoomAdjustedPixelValue(style->horizontalBorderSpacing(), style.get()));
list->append(zoomAdjustedPixelValue(style->verticalBorderSpacing(), style.get()));
return list.release();
}
case CSSPropertyWebkitBorderHorizontalSpacing:
return zoomAdjustedPixelValue(style->horizontalBorderSpacing(), style.get());
case CSSPropertyWebkitBorderVerticalSpacing:
return zoomAdjustedPixelValue(style->verticalBorderSpacing(), style.get());
case CSSPropertyBorderImageSource:
if (style->borderImageSource())
return style->borderImageSource()->cssValue();
return cssValuePool().createIdentifierValue(CSSValueNone);
case CSSPropertyBorderTopColor:
return m_allowVisitedStyle ? cssValuePool().createColorValue(style->visitedDependentColor(CSSPropertyBorderTopColor).rgb()) : currentColorOrValidColor(style.get(), style->borderTopColor());
case CSSPropertyBorderRightColor:
return m_allowVisitedStyle ? cssValuePool().createColorValue(style->visitedDependentColor(CSSPropertyBorderRightColor).rgb()) : currentColorOrValidColor(style.get(), style->borderRightColor());
case CSSPropertyBorderBottomColor:
return m_allowVisitedStyle ? cssValuePool().createColorValue(style->visitedDependentColor(CSSPropertyBorderBottomColor).rgb()) : currentColorOrValidColor(style.get(), style->borderBottomColor());
case CSSPropertyBorderLeftColor:
return m_allowVisitedStyle ? cssValuePool().createColorValue(style->visitedDependentColor(CSSPropertyBorderLeftColor).rgb()) : currentColorOrValidColor(style.get(), style->borderLeftColor());
case CSSPropertyBorderTopStyle:
return cssValuePool().createValue(style->borderTopStyle());
case CSSPropertyBorderRightStyle:
return cssValuePool().createValue(style->borderRightStyle());
case CSSPropertyBorderBottomStyle:
return cssValuePool().createValue(style->borderBottomStyle());
case CSSPropertyBorderLeftStyle:
return cssValuePool().createValue(style->borderLeftStyle());
case CSSPropertyBorderTopWidth:
return zoomAdjustedPixelValue(style->borderTopWidth(), style.get());
case CSSPropertyBorderRightWidth:
return zoomAdjustedPixelValue(style->borderRightWidth(), style.get());
case CSSPropertyBorderBottomWidth:
return zoomAdjustedPixelValue(style->borderBottomWidth(), style.get());
case CSSPropertyBorderLeftWidth:
return zoomAdjustedPixelValue(style->borderLeftWidth(), style.get());
case CSSPropertyBottom:
return valueForPositionOffset(style.get(), CSSPropertyBottom, renderer, m_node->document().renderView());
case CSSPropertyWebkitBoxAlign:
return cssValuePool().createValue(style->boxAlign());
case CSSPropertyWebkitBoxDecorationBreak:
if (style->boxDecorationBreak() == DSLICE)
return cssValuePool().createIdentifierValue(CSSValueSlice);
return cssValuePool().createIdentifierValue(CSSValueClone);
case CSSPropertyWebkitBoxDirection:
return cssValuePool().createValue(style->boxDirection());
case CSSPropertyWebkitBoxFlex:
return cssValuePool().createValue(style->boxFlex(), CSSPrimitiveValue::CSS_NUMBER);
case CSSPropertyWebkitBoxFlexGroup:
return cssValuePool().createValue(style->boxFlexGroup(), CSSPrimitiveValue::CSS_NUMBER);
case CSSPropertyWebkitBoxLines:
return cssValuePool().createValue(style->boxLines());
case CSSPropertyWebkitBoxOrdinalGroup:
return cssValuePool().createValue(style->boxOrdinalGroup(), CSSPrimitiveValue::CSS_NUMBER);
case CSSPropertyWebkitBoxOrient:
return cssValuePool().createValue(style->boxOrient());
case CSSPropertyWebkitBoxPack:
return cssValuePool().createValue(style->boxPack());
case CSSPropertyWebkitBoxReflect:
return valueForReflection(style->boxReflect(), style.get());
case CSSPropertyBoxShadow:
case CSSPropertyWebkitBoxShadow:
return valueForShadowList(style->boxShadow(), style.get(), true);
case CSSPropertyCaptionSide:
return cssValuePool().createValue(style->captionSide());
case CSSPropertyClear:
return cssValuePool().createValue(style->clear());
case CSSPropertyColor:
return cssValuePool().createColorValue(m_allowVisitedStyle ? style->visitedDependentColor(CSSPropertyColor).rgb() : style->color().rgb());
case CSSPropertyWebkitPrintColorAdjust:
return cssValuePool().createValue(style->printColorAdjust());
case CSSPropertyWebkitColumnAxis:
return cssValuePool().createValue(style->columnAxis());
case CSSPropertyWebkitColumnCount:
if (style->hasAutoColumnCount())
return cssValuePool().createIdentifierValue(CSSValueAuto);
return cssValuePool().createValue(style->columnCount(), CSSPrimitiveValue::CSS_NUMBER);
case CSSPropertyColumnFill:
if (RuntimeEnabledFeatures::regionBasedColumnsEnabled())
return cssValuePool().createValue(style->columnFill());
return 0;
case CSSPropertyWebkitColumnGap:
if (style->hasNormalColumnGap())
return cssValuePool().createIdentifierValue(CSSValueNormal);
return zoomAdjustedPixelValue(style->columnGap(), style.get());
case CSSPropertyWebkitColumnProgression:
return cssValuePool().createValue(style->columnProgression());
case CSSPropertyWebkitColumnRuleColor:
return m_allowVisitedStyle ? cssValuePool().createColorValue(style->visitedDependentColor(CSSPropertyOutlineColor).rgb()) : currentColorOrValidColor(style.get(), style->columnRuleColor());
case CSSPropertyWebkitColumnRuleStyle:
return cssValuePool().createValue(style->columnRuleStyle());
case CSSPropertyWebkitColumnRuleWidth:
return zoomAdjustedPixelValue(style->columnRuleWidth(), style.get());
case CSSPropertyWebkitColumnSpan:
return cssValuePool().createIdentifierValue(style->columnSpan() ? CSSValueAll : CSSValueNone);
case CSSPropertyWebkitColumnBreakAfter:
return cssValuePool().createValue(style->columnBreakAfter());
case CSSPropertyWebkitColumnBreakBefore:
return cssValuePool().createValue(style->columnBreakBefore());
case CSSPropertyWebkitColumnBreakInside:
return cssValuePool().createValue(style->columnBreakInside());
case CSSPropertyWebkitColumnWidth:
if (style->hasAutoColumnWidth())
return cssValuePool().createIdentifierValue(CSSValueAuto);
return zoomAdjustedPixelValue(style->columnWidth(), style.get());
case CSSPropertyTabSize:
return cssValuePool().createValue(style->tabSize(), CSSPrimitiveValue::CSS_NUMBER);
case CSSPropertyWebkitRegionBreakAfter:
return cssValuePool().createValue(style->regionBreakAfter());
case CSSPropertyWebkitRegionBreakBefore:
return cssValuePool().createValue(style->regionBreakBefore());
case CSSPropertyWebkitRegionBreakInside:
return cssValuePool().createValue(style->regionBreakInside());
case CSSPropertyCursor: {
RefPtr<CSSValueList> list;
CursorList* cursors = style->cursors();
if (cursors && cursors->size() > 0) {
list = CSSValueList::createCommaSeparated();
for (unsigned i = 0; i < cursors->size(); ++i)
if (StyleImage* image = cursors->at(i).image())
list->append(image->cssValue());
}
RefPtr<CSSValue> value = cssValuePool().createValue(style->cursor());
if (list) {
list->append(value.release());
return list.release();
}
return value.release();
}
case CSSPropertyDirection:
return cssValuePool().createValue(style->direction());
case CSSPropertyDisplay:
return cssValuePool().createValue(style->display());
case CSSPropertyEmptyCells:
return cssValuePool().createValue(style->emptyCells());
case CSSPropertyAlignContent:
return cssValuePool().createValue(style->alignContent());
case CSSPropertyAlignItems:
return cssValuePool().createValue(style->alignItems());
case CSSPropertyAlignSelf:
if (style->alignSelf() == AlignAuto) {
Node* parent = styledNode->parentNode();
if (parent && parent->computedStyle())
return cssValuePool().createValue(parent->computedStyle()->alignItems());
return cssValuePool().createValue(AlignStretch);
}
return cssValuePool().createValue(style->alignSelf());
case CSSPropertyFlex:
return valuesForShorthandProperty(flexShorthand());
case CSSPropertyFlexBasis:
return cssValuePool().createValue(style->flexBasis());
case CSSPropertyFlexDirection:
return cssValuePool().createValue(style->flexDirection());
case CSSPropertyFlexFlow:
return valuesForShorthandProperty(flexFlowShorthand());
case CSSPropertyFlexGrow:
return cssValuePool().createValue(style->flexGrow());
case CSSPropertyFlexShrink:
return cssValuePool().createValue(style->flexShrink());
case CSSPropertyFlexWrap:
return cssValuePool().createValue(style->flexWrap());
case CSSPropertyJustifyContent:
return cssValuePool().createValue(style->justifyContent());
case CSSPropertyOrder:
return cssValuePool().createValue(style->order(), CSSPrimitiveValue::CSS_NUMBER);
case CSSPropertyFloat:
if (style->display() != NONE && style->hasOutOfFlowPosition())
return cssValuePool().createIdentifierValue(CSSValueNone);
return cssValuePool().createValue(style->floating());
case CSSPropertyFont: {
RefPtr<CSSFontValue> computedFont = CSSFontValue::create();
computedFont->style = valueForFontStyle(style.get());
computedFont->variant = valueForFontVariant(style.get());
computedFont->weight = valueForFontWeight(style.get());
computedFont->size = valueForFontSize(style.get());
computedFont->lineHeight = valueForLineHeight(style.get(), m_node->document().renderView());
computedFont->family = valueForFontFamily(style.get());
return computedFont.release();
}
case CSSPropertyFontFamily: {
RefPtr<CSSValueList> fontFamilyList = valueForFontFamily(style.get());
// If there's only a single family, return that as a CSSPrimitiveValue.
// NOTE: Gecko always returns this as a comma-separated CSSPrimitiveValue string.
if (fontFamilyList->length() == 1)
return fontFamilyList->item(0);
return fontFamilyList.release();
}
case CSSPropertyFontSize:
return valueForFontSize(style.get());
case CSSPropertyFontStyle:
return valueForFontStyle(style.get());
case CSSPropertyFontVariant:
return valueForFontVariant(style.get());
case CSSPropertyFontWeight:
return valueForFontWeight(style.get());
case CSSPropertyWebkitFontFeatureSettings: {
const FontFeatureSettings* featureSettings = style->fontDescription().featureSettings();
if (!featureSettings || !featureSettings->size())
return cssValuePool().createIdentifierValue(CSSValueNormal);
RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
for (unsigned i = 0; i < featureSettings->size(); ++i) {
const FontFeature& feature = featureSettings->at(i);
RefPtr<CSSFontFeatureValue> featureValue = CSSFontFeatureValue::create(feature.tag(), feature.value());
list->append(featureValue.release());
}
return list.release();
}
case CSSPropertyGridAutoColumns:
return valueForGridTrackSize(style->gridAutoColumns(), style.get(), m_node->document().renderView());
case CSSPropertyGridAutoFlow:
return cssValuePool().createValue(style->gridAutoFlow());
case CSSPropertyGridAutoRows:
return valueForGridTrackSize(style->gridAutoRows(), style.get(), m_node->document().renderView());
case CSSPropertyGridDefinitionColumns:
return valueForGridTrackList(style->gridDefinitionColumns(), style->orderedNamedGridColumnLines(), style.get(), m_node->document().renderView());
case CSSPropertyGridDefinitionRows:
return valueForGridTrackList(style->gridDefinitionRows(), style->orderedNamedGridRowLines(), style.get(), m_node->document().renderView());
case CSSPropertyGridColumnStart:
return valueForGridPosition(style->gridColumnStart());
case CSSPropertyGridColumnEnd:
return valueForGridPosition(style->gridColumnEnd());
case CSSPropertyGridRowStart:
return valueForGridPosition(style->gridRowStart());
case CSSPropertyGridRowEnd:
return valueForGridPosition(style->gridRowEnd());
case CSSPropertyGridColumn:
return valuesForGridShorthand(gridColumnShorthand());
case CSSPropertyGridRow:
return valuesForGridShorthand(gridRowShorthand());
case CSSPropertyGridArea:
return valuesForGridShorthand(gridAreaShorthand());
case CSSPropertyGridTemplate:
if (!style->namedGridAreaRowCount()) {
ASSERT(!style->namedGridAreaColumnCount());
return cssValuePool().createIdentifierValue(CSSValueNone);
}
return CSSGridTemplateValue::create(style->namedGridArea(), style->namedGridAreaRowCount(), style->namedGridAreaColumnCount());
case CSSPropertyHeight:
if (renderer) {
// According to http://www.w3.org/TR/CSS2/visudet.html#the-height-property,
// the "height" property does not apply for non-replaced inline elements.
if (!renderer->isReplaced() && renderer->isInline())
return cssValuePool().createIdentifierValue(CSSValueAuto);
return zoomAdjustedPixelValue(sizingBox(renderer).height(), style.get());
}
return zoomAdjustedPixelValueForLength(style->height(), style.get());
case CSSPropertyWebkitHighlight:
if (style->highlight() == nullAtom)
return cssValuePool().createIdentifierValue(CSSValueNone);
return cssValuePool().createValue(style->highlight(), CSSPrimitiveValue::CSS_STRING);
case CSSPropertyWebkitHyphenateCharacter:
if (style->hyphenationString().isNull())
return cssValuePool().createIdentifierValue(CSSValueAuto);
return cssValuePool().createValue(style->hyphenationString(), CSSPrimitiveValue::CSS_STRING);
case CSSPropertyWebkitBorderFit:
if (style->borderFit() == BorderFitBorder)
return cssValuePool().createIdentifierValue(CSSValueBorder);
return cssValuePool().createIdentifierValue(CSSValueLines);
case CSSPropertyImageRendering:
return CSSPrimitiveValue::create(style->imageRendering());
case CSSPropertyIsolation:
return cssValuePool().createValue(style->isolation());
case CSSPropertyLeft:
return valueForPositionOffset(style.get(), CSSPropertyLeft, renderer, m_node->document().renderView());
case CSSPropertyLetterSpacing:
if (!style->letterSpacing())
return cssValuePool().createIdentifierValue(CSSValueNormal);
return zoomAdjustedPixelValue(style->letterSpacing(), style.get());
case CSSPropertyWebkitLineClamp:
if (style->lineClamp().isNone())
return cssValuePool().createIdentifierValue(CSSValueNone);
return cssValuePool().createValue(style->lineClamp().value(), style->lineClamp().isPercentage() ? CSSPrimitiveValue::CSS_PERCENTAGE : CSSPrimitiveValue::CSS_NUMBER);
case CSSPropertyLineHeight:
return valueForLineHeight(style.get(), m_node->document().renderView());
case CSSPropertyListStyleImage:
if (style->listStyleImage())
return style->listStyleImage()->cssValue();
return cssValuePool().createIdentifierValue(CSSValueNone);
case CSSPropertyListStylePosition:
return cssValuePool().createValue(style->listStylePosition());
case CSSPropertyListStyleType:
return cssValuePool().createValue(style->listStyleType());
case CSSPropertyWebkitLocale:
if (style->locale().isNull())
return cssValuePool().createIdentifierValue(CSSValueAuto);
return cssValuePool().createValue(style->locale(), CSSPrimitiveValue::CSS_STRING);
case CSSPropertyMarginTop: {
Length marginTop = style->marginTop();
if (marginTop.isFixed() || !renderer || !renderer->isBox())
return zoomAdjustedPixelValueForLength(marginTop, style.get());
return zoomAdjustedPixelValue(toRenderBox(renderer)->marginTop(), style.get());
}
case CSSPropertyMarginRight: {
Length marginRight = style->marginRight();
if (marginRight.isFixed() || !renderer || !renderer->isBox())
return zoomAdjustedPixelValueForLength(marginRight, style.get());
float value;
if (marginRight.isPercent() || marginRight.isViewportPercentage()) {
// RenderBox gives a marginRight() that is the distance between the right-edge of the child box
// and the right-edge of the containing box, when display == BLOCK. Let's calculate the absolute
// value of the specified margin-right % instead of relying on RenderBox's marginRight() value.
value = minimumValueForLength(marginRight, toRenderBox(renderer)->containingBlockLogicalWidthForContent(), m_node->document().renderView());
} else {
value = toRenderBox(renderer)->marginRight();
}
return zoomAdjustedPixelValue(value, style.get());
}
case CSSPropertyMarginBottom: {
Length marginBottom = style->marginBottom();
if (marginBottom.isFixed() || !renderer || !renderer->isBox())
return zoomAdjustedPixelValueForLength(marginBottom, style.get());
return zoomAdjustedPixelValue(toRenderBox(renderer)->marginBottom(), style.get());
}
case CSSPropertyMarginLeft: {
Length marginLeft = style->marginLeft();
if (marginLeft.isFixed() || !renderer || !renderer->isBox())
return zoomAdjustedPixelValueForLength(marginLeft, style.get());
return zoomAdjustedPixelValue(toRenderBox(renderer)->marginLeft(), style.get());
}
case CSSPropertyWebkitUserModify:
return cssValuePool().createValue(style->userModify());
case CSSPropertyMaxHeight: {
const Length& maxHeight = style->maxHeight();
if (maxHeight.isUndefined())
return cssValuePool().createIdentifierValue(CSSValueNone);
return zoomAdjustedPixelValueForLength(maxHeight, style.get());
}
case CSSPropertyMaxWidth: {
const Length& maxWidth = style->maxWidth();
if (maxWidth.isUndefined())
return cssValuePool().createIdentifierValue(CSSValueNone);
return zoomAdjustedPixelValueForLength(maxWidth, style.get());
}
case CSSPropertyMinHeight:
// FIXME: For flex-items, min-height:auto should compute to min-content.
if (style->minHeight().isAuto())
return zoomAdjustedPixelValue(0, style.get());
return zoomAdjustedPixelValueForLength(style->minHeight(), style.get());
case CSSPropertyMinWidth:
// FIXME: For flex-items, min-width:auto should compute to min-content.
if (style->minWidth().isAuto())
return zoomAdjustedPixelValue(0, style.get());
return zoomAdjustedPixelValueForLength(style->minWidth(), style.get());
case CSSPropertyObjectFit:
return cssValuePool().createValue(style->objectFit());
case CSSPropertyObjectPosition:
return cssValuePool().createValue(
Pair::create(
zoomAdjustedPixelValueForLength(style->objectPosition().x(), style.get()),
zoomAdjustedPixelValueForLength(style->objectPosition().y(), style.get()),
Pair::KeepIdenticalValues));
case CSSPropertyOpacity:
return cssValuePool().createValue(style->opacity(), CSSPrimitiveValue::CSS_NUMBER);
case CSSPropertyOrphans:
if (style->hasAutoOrphans())
return cssValuePool().createIdentifierValue(CSSValueAuto);
return cssValuePool().createValue(style->orphans(), CSSPrimitiveValue::CSS_NUMBER);
case CSSPropertyOutlineColor:
return m_allowVisitedStyle ? cssValuePool().createColorValue(style->visitedDependentColor(CSSPropertyOutlineColor).rgb()) : currentColorOrValidColor(style.get(), style->outlineColor());
case CSSPropertyOutlineOffset:
return zoomAdjustedPixelValue(style->outlineOffset(), style.get());
case CSSPropertyOutlineStyle:
if (style->outlineStyleIsAuto())
return cssValuePool().createIdentifierValue(CSSValueAuto);
return cssValuePool().createValue(style->outlineStyle());
case CSSPropertyOutlineWidth:
return zoomAdjustedPixelValue(style->outlineWidth(), style.get());
case CSSPropertyOverflow:
return cssValuePool().createValue(max(style->overflowX(), style->overflowY()));
case CSSPropertyOverflowWrap:
return cssValuePool().createValue(style->overflowWrap());
case CSSPropertyOverflowX:
return cssValuePool().createValue(style->overflowX());
case CSSPropertyOverflowY:
return cssValuePool().createValue(style->overflowY());
case CSSPropertyPaddingTop: {
Length paddingTop = style->paddingTop();
if (paddingTop.isFixed() || !renderer || !renderer->isBox())
return zoomAdjustedPixelValueForLength(paddingTop, style.get());
return zoomAdjustedPixelValue(toRenderBox(renderer)->computedCSSPaddingTop(), style.get());
}
case CSSPropertyPaddingRight: {
Length paddingRight = style->paddingRight();
if (paddingRight.isFixed() || !renderer || !renderer->isBox())
return zoomAdjustedPixelValueForLength(paddingRight, style.get());
return zoomAdjustedPixelValue(toRenderBox(renderer)->computedCSSPaddingRight(), style.get());
}
case CSSPropertyPaddingBottom: {
Length paddingBottom = style->paddingBottom();
if (paddingBottom.isFixed() || !renderer || !renderer->isBox())
return zoomAdjustedPixelValueForLength(paddingBottom, style.get());
return zoomAdjustedPixelValue(toRenderBox(renderer)->computedCSSPaddingBottom(), style.get());
}
case CSSPropertyPaddingLeft: {
Length paddingLeft = style->paddingLeft();
if (paddingLeft.isFixed() || !renderer || !renderer->isBox())
return zoomAdjustedPixelValueForLength(paddingLeft, style.get());
return zoomAdjustedPixelValue(toRenderBox(renderer)->computedCSSPaddingLeft(), style.get());
}
case CSSPropertyPageBreakAfter:
return cssValuePool().createValue(style->pageBreakAfter());
case CSSPropertyPageBreakBefore:
return cssValuePool().createValue(style->pageBreakBefore());
case CSSPropertyPageBreakInside: {
EPageBreak pageBreak = style->pageBreakInside();
ASSERT(pageBreak != PBALWAYS);
if (pageBreak == PBALWAYS)
return 0;
return cssValuePool().createValue(style->pageBreakInside());
}
case CSSPropertyPosition:
return cssValuePool().createValue(style->position());
case CSSPropertyRight:
return valueForPositionOffset(style.get(), CSSPropertyRight, renderer, m_node->document().renderView());
case CSSPropertyWebkitRubyPosition:
return cssValuePool().createValue(style->rubyPosition());
case CSSPropertyTableLayout:
return cssValuePool().createValue(style->tableLayout());
case CSSPropertyTextAlign:
return cssValuePool().createValue(style->textAlign());
case CSSPropertyTextAlignLast:
return cssValuePool().createValue(style->textAlignLast());
case CSSPropertyTextDecoration:
return valuesForShorthandProperty(textDecorationShorthand());
case CSSPropertyTextDecorationLine:
return renderTextDecorationFlagsToCSSValue(style->textDecoration());
case CSSPropertyTextDecorationStyle:
return valueForTextDecorationStyle(style->textDecorationStyle());
case CSSPropertyTextDecorationColor:
return currentColorOrValidColor(style.get(), style->textDecorationColor());
case CSSPropertyTextJustify:
return cssValuePool().createValue(style->textJustify());
#if ENABLE(CSS3_TEXT)
case CSSPropertyWebkitTextUnderlinePosition:
return cssValuePool().createValue(style->textUnderlinePosition());
#endif // CSS3_TEXT
case CSSPropertyWebkitTextDecorationsInEffect:
return renderTextDecorationFlagsToCSSValue(style->textDecorationsInEffect());
case CSSPropertyWebkitTextFillColor:
return currentColorOrValidColor(style.get(), style->textFillColor());
case CSSPropertyWebkitTextEmphasisColor:
return currentColorOrValidColor(style.get(), style->textEmphasisColor());
case CSSPropertyWebkitTextEmphasisPosition:
return cssValuePool().createValue(style->textEmphasisPosition());
case CSSPropertyWebkitTextEmphasisStyle:
switch (style->textEmphasisMark()) {
case TextEmphasisMarkNone:
return cssValuePool().createIdentifierValue(CSSValueNone);
case TextEmphasisMarkCustom:
return cssValuePool().createValue(style->textEmphasisCustomMark(), CSSPrimitiveValue::CSS_STRING);
case TextEmphasisMarkAuto:
ASSERT_NOT_REACHED();
// Fall through
case TextEmphasisMarkDot:
case TextEmphasisMarkCircle:
case TextEmphasisMarkDoubleCircle:
case TextEmphasisMarkTriangle:
case TextEmphasisMarkSesame: {
RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
list->append(cssValuePool().createValue(style->textEmphasisFill()));
list->append(cssValuePool().createValue(style->textEmphasisMark()));
return list.release();
}
}
case CSSPropertyTextIndent: {
RefPtr<CSSValue> textIndent = zoomAdjustedPixelValueForLength(style->textIndent(), style.get());
if (RuntimeEnabledFeatures::css3TextEnabled() && style->textIndentLine() == TextIndentEachLine) {
RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
list->append(textIndent.release());
list->append(cssValuePool().createIdentifierValue(CSSValueEachLine));
return list.release();
}
return textIndent.release();
}
case CSSPropertyTextShadow:
return valueForShadowList(style->textShadow(), style.get(), false);
case CSSPropertyTextRendering:
return cssValuePool().createValue(style->fontDescription().textRenderingMode());
case CSSPropertyTextOverflow:
if (style->textOverflow())
return cssValuePool().createIdentifierValue(CSSValueEllipsis);
return cssValuePool().createIdentifierValue(CSSValueClip);
case CSSPropertyWebkitTextSecurity:
return cssValuePool().createValue(style->textSecurity());
case CSSPropertyWebkitTextStrokeColor:
return currentColorOrValidColor(style.get(), style->textStrokeColor());
case CSSPropertyWebkitTextStrokeWidth:
return zoomAdjustedPixelValue(style->textStrokeWidth(), style.get());
case CSSPropertyTextTransform:
return cssValuePool().createValue(style->textTransform());
case CSSPropertyTop:
return valueForPositionOffset(style.get(), CSSPropertyTop, renderer, m_node->document().renderView());
case CSSPropertyTouchAction:
return cssValuePool().createValue(style->touchAction());
case CSSPropertyTouchActionDelay:
return cssValuePool().createValue(style->touchActionDelay());
case CSSPropertyUnicodeBidi:
return cssValuePool().