blob: 54fb6514e7e67147baeb16944b9af1fb1123b2fc [file] [log] [blame]
/**
* (C) 1999-2003 Lars Knoll (knoll@kde.org)
* Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "core/css/CSSProperty.h"
#include "core/StylePropertyShorthand.h"
#include "core/style/ComputedStyleConstants.h"
namespace blink {
struct SameSizeAsCSSProperty {
uint32_t bitfields;
Member<void*> value;
};
static_assert(sizeof(CSSProperty) == sizeof(SameSizeAsCSSProperty),
"CSSProperty should stay small");
CSSPropertyID StylePropertyMetadata::shorthandID() const {
if (!m_isSetFromShorthand)
return CSSPropertyInvalid;
Vector<StylePropertyShorthand, 4> shorthands;
getMatchingShorthandsForLonghand(static_cast<CSSPropertyID>(m_propertyID),
&shorthands);
ASSERT(shorthands.size() && m_indexInShorthandsVector >= 0 &&
m_indexInShorthandsVector < shorthands.size());
return shorthands.at(m_indexInShorthandsVector).id();
}
enum LogicalBoxSide { BeforeSide, EndSide, AfterSide, StartSide };
enum PhysicalBoxSide { TopSide, RightSide, BottomSide, LeftSide };
static CSSPropertyID resolveToPhysicalProperty(
TextDirection direction,
WritingMode writingMode,
LogicalBoxSide logicalSide,
const StylePropertyShorthand& shorthand) {
if (direction == TextDirection::Ltr) {
if (isHorizontalWritingMode(writingMode)) {
// The common case. The logical and physical box sides match.
// Left = Start, Right = End, Before = Top, After = Bottom
return shorthand.properties()[logicalSide];
}
if (isFlippedLinesWritingMode(writingMode)) {
// Start = Top, End = Bottom, Before = Left, After = Right.
switch (logicalSide) {
case StartSide:
return shorthand.properties()[TopSide];
case EndSide:
return shorthand.properties()[BottomSide];
case BeforeSide:
return shorthand.properties()[LeftSide];
default:
return shorthand.properties()[RightSide];
}
}
// Start = Top, End = Bottom, Before = Right, After = Left
switch (logicalSide) {
case StartSide:
return shorthand.properties()[TopSide];
case EndSide:
return shorthand.properties()[BottomSide];
case BeforeSide:
return shorthand.properties()[RightSide];
default:
return shorthand.properties()[LeftSide];
}
}
if (isHorizontalWritingMode(writingMode)) {
// Start = Right, End = Left, Before = Top, After = Bottom
switch (logicalSide) {
case StartSide:
return shorthand.properties()[RightSide];
case EndSide:
return shorthand.properties()[LeftSide];
case BeforeSide:
return shorthand.properties()[TopSide];
default:
return shorthand.properties()[BottomSide];
}
}
if (isFlippedLinesWritingMode(writingMode)) {
// Start = Bottom, End = Top, Before = Left, After = Right
switch (logicalSide) {
case StartSide:
return shorthand.properties()[BottomSide];
case EndSide:
return shorthand.properties()[TopSide];
case BeforeSide:
return shorthand.properties()[LeftSide];
default:
return shorthand.properties()[RightSide];
}
}
// Start = Bottom, End = Top, Before = Right, After = Left
switch (logicalSide) {
case StartSide:
return shorthand.properties()[BottomSide];
case EndSide:
return shorthand.properties()[TopSide];
case BeforeSide:
return shorthand.properties()[RightSide];
default:
return shorthand.properties()[LeftSide];
}
}
enum LogicalExtent { LogicalWidth, LogicalHeight };
static CSSPropertyID resolveToPhysicalProperty(
WritingMode writingMode,
LogicalExtent logicalSide,
const CSSPropertyID* properties) {
if (isHorizontalWritingMode(writingMode))
return properties[logicalSide];
return logicalSide == LogicalWidth ? properties[1] : properties[0];
}
static const StylePropertyShorthand& borderDirections() {
static const CSSPropertyID properties[4] = {
CSSPropertyBorderTop, CSSPropertyBorderRight, CSSPropertyBorderBottom,
CSSPropertyBorderLeft};
DEFINE_STATIC_LOCAL(
StylePropertyShorthand, borderDirections,
(CSSPropertyBorder, properties, WTF_ARRAY_LENGTH(properties)));
return borderDirections;
}
CSSPropertyID CSSProperty::resolveDirectionAwareProperty(
CSSPropertyID propertyID,
TextDirection direction,
WritingMode writingMode) {
switch (propertyID) {
case CSSPropertyWebkitMarginEnd:
return resolveToPhysicalProperty(direction, writingMode, EndSide,
marginShorthand());
case CSSPropertyWebkitMarginStart:
return resolveToPhysicalProperty(direction, writingMode, StartSide,
marginShorthand());
case CSSPropertyWebkitMarginBefore:
return resolveToPhysicalProperty(direction, writingMode, BeforeSide,
marginShorthand());
case CSSPropertyWebkitMarginAfter:
return resolveToPhysicalProperty(direction, writingMode, AfterSide,
marginShorthand());
case CSSPropertyWebkitPaddingEnd:
return resolveToPhysicalProperty(direction, writingMode, EndSide,
paddingShorthand());
case CSSPropertyWebkitPaddingStart:
return resolveToPhysicalProperty(direction, writingMode, StartSide,
paddingShorthand());
case CSSPropertyWebkitPaddingBefore:
return resolveToPhysicalProperty(direction, writingMode, BeforeSide,
paddingShorthand());
case CSSPropertyWebkitPaddingAfter:
return resolveToPhysicalProperty(direction, writingMode, AfterSide,
paddingShorthand());
case CSSPropertyWebkitBorderEnd:
return resolveToPhysicalProperty(direction, writingMode, EndSide,
borderDirections());
case CSSPropertyWebkitBorderStart:
return resolveToPhysicalProperty(direction, writingMode, StartSide,
borderDirections());
case CSSPropertyWebkitBorderBefore:
return resolveToPhysicalProperty(direction, writingMode, BeforeSide,
borderDirections());
case CSSPropertyWebkitBorderAfter:
return resolveToPhysicalProperty(direction, writingMode, AfterSide,
borderDirections());
case CSSPropertyWebkitBorderEndColor:
return resolveToPhysicalProperty(direction, writingMode, EndSide,
borderColorShorthand());
case CSSPropertyWebkitBorderStartColor:
return resolveToPhysicalProperty(direction, writingMode, StartSide,
borderColorShorthand());
case CSSPropertyWebkitBorderBeforeColor:
return resolveToPhysicalProperty(direction, writingMode, BeforeSide,
borderColorShorthand());
case CSSPropertyWebkitBorderAfterColor:
return resolveToPhysicalProperty(direction, writingMode, AfterSide,
borderColorShorthand());
case CSSPropertyWebkitBorderEndStyle:
return resolveToPhysicalProperty(direction, writingMode, EndSide,
borderStyleShorthand());
case CSSPropertyWebkitBorderStartStyle:
return resolveToPhysicalProperty(direction, writingMode, StartSide,
borderStyleShorthand());
case CSSPropertyWebkitBorderBeforeStyle:
return resolveToPhysicalProperty(direction, writingMode, BeforeSide,
borderStyleShorthand());
case CSSPropertyWebkitBorderAfterStyle:
return resolveToPhysicalProperty(direction, writingMode, AfterSide,
borderStyleShorthand());
case CSSPropertyWebkitBorderEndWidth:
return resolveToPhysicalProperty(direction, writingMode, EndSide,
borderWidthShorthand());
case CSSPropertyWebkitBorderStartWidth:
return resolveToPhysicalProperty(direction, writingMode, StartSide,
borderWidthShorthand());
case CSSPropertyWebkitBorderBeforeWidth:
return resolveToPhysicalProperty(direction, writingMode, BeforeSide,
borderWidthShorthand());
case CSSPropertyWebkitBorderAfterWidth:
return resolveToPhysicalProperty(direction, writingMode, AfterSide,
borderWidthShorthand());
case CSSPropertyInlineSize:
case CSSPropertyWebkitLogicalWidth: {
const CSSPropertyID properties[2] = {CSSPropertyWidth, CSSPropertyHeight};
return resolveToPhysicalProperty(writingMode, LogicalWidth, properties);
}
case CSSPropertyBlockSize:
case CSSPropertyWebkitLogicalHeight: {
const CSSPropertyID properties[2] = {CSSPropertyWidth, CSSPropertyHeight};
return resolveToPhysicalProperty(writingMode, LogicalHeight, properties);
}
case CSSPropertyMinInlineSize:
case CSSPropertyWebkitMinLogicalWidth: {
const CSSPropertyID properties[2] = {CSSPropertyMinWidth,
CSSPropertyMinHeight};
return resolveToPhysicalProperty(writingMode, LogicalWidth, properties);
}
case CSSPropertyMinBlockSize:
case CSSPropertyWebkitMinLogicalHeight: {
const CSSPropertyID properties[2] = {CSSPropertyMinWidth,
CSSPropertyMinHeight};
return resolveToPhysicalProperty(writingMode, LogicalHeight, properties);
}
case CSSPropertyMaxInlineSize:
case CSSPropertyWebkitMaxLogicalWidth: {
const CSSPropertyID properties[2] = {CSSPropertyMaxWidth,
CSSPropertyMaxHeight};
return resolveToPhysicalProperty(writingMode, LogicalWidth, properties);
}
case CSSPropertyMaxBlockSize:
case CSSPropertyWebkitMaxLogicalHeight: {
const CSSPropertyID properties[2] = {CSSPropertyMaxWidth,
CSSPropertyMaxHeight};
return resolveToPhysicalProperty(writingMode, LogicalHeight, properties);
}
default:
return propertyID;
}
}
bool CSSProperty::isAffectedByAllProperty(CSSPropertyID propertyID) {
if (propertyID == CSSPropertyAll)
return false;
if (!CSSPropertyMetadata::isEnabledProperty(propertyID))
return false;
if (propertyID == CSSPropertyVariable)
return false;
if (CSSPropertyMetadata::isDescriptorOnly(propertyID))
return false;
// all shorthand spec says:
// The all property is a shorthand that resets all CSS properties except
// direction and unicode-bidi. It only accepts the CSS-wide keywords.
// c.f. http://dev.w3.org/csswg/css-cascade/#all-shorthand
// So CSSPropertyUnicodeBidi and CSSPropertyDirection are not
// affected by all property.
return propertyID != CSSPropertyUnicodeBidi &&
propertyID != CSSPropertyDirection;
}
bool CSSProperty::operator==(const CSSProperty& other) const {
return m_value->equals(*other.m_value) &&
isImportant() == other.isImportant();
}
} // namespace blink