blob: c76c33f9baba92e5ba81ffd940e710ac048112af [file]
/**
* (C) 1999-2003 Lars Knoll (knoll@kde.org)
* Copyright (C) 2004-2021 Apple 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 "config.h"
#include "CSSProperty.h"
#include "CSSValueList.h"
#include "StylePropertyShorthand.h"
#include "StylePropertyShorthandFunctions.h"
#include <wtf/NeverDestroyed.h>
namespace WebCore {
struct SameSizeAsCSSProperty {
uint32_t bitfields;
void* value;
};
COMPILE_ASSERT(sizeof(CSSProperty) == sizeof(SameSizeAsCSSProperty), CSSProperty_should_stay_small);
CSSPropertyID StylePropertyMetadata::shorthandID() const
{
if (!m_isSetFromShorthand)
return CSSPropertyInvalid;
auto shorthands = matchingShorthandsForLonghand(static_cast<CSSPropertyID>(m_propertyID));
ASSERT(shorthands.size() && m_indexInShorthandsVector >= 0 && m_indexInShorthandsVector < shorthands.size());
return shorthands[m_indexInShorthandsVector].id();
}
void CSSProperty::wrapValueInCommaSeparatedList()
{
auto list = CSSValueList::createCommaSeparated();
list.get().append(m_value.releaseNonNull());
m_value = WTFMove(list);
}
static CSSPropertyID resolveToPhysicalProperty(TextDirection direction, WritingMode writingMode, LogicalBoxSide logicalSide, const StylePropertyShorthand& shorthand)
{
RELEASE_ASSERT(shorthand.length() == 4);
return shorthand.properties()[static_cast<size_t>(mapLogicalSideToPhysicalSide(makeTextFlow(writingMode, direction), logicalSide))];
}
static CSSPropertyID resolveToPhysicalProperty(TextDirection direction, WritingMode writingMode, LogicalBoxCorner logicalBoxCorner, const StylePropertyShorthand& shorthand)
{
RELEASE_ASSERT(shorthand.length() == 4);
return shorthand.properties()[static_cast<size_t>(mapLogicalCornerToPhysicalCorner(makeTextFlow(writingMode, direction), logicalBoxCorner))];
}
enum LogicalExtent { LogicalWidth, LogicalHeight };
static CSSPropertyID resolveToPhysicalProperty(WritingMode writingMode, LogicalExtent logicalSide, const CSSPropertyID (&properties)[2])
{
if (writingMode == WritingMode::TopToBottom || writingMode == WritingMode::BottomToTop)
return properties[logicalSide];
return logicalSide == LogicalWidth ? properties[1] : properties[0];
}
static const StylePropertyShorthand& borderDirections()
{
static const CSSPropertyID properties[4] = { CSSPropertyBorderTop, CSSPropertyBorderRight, CSSPropertyBorderBottom, CSSPropertyBorderLeft };
static const StylePropertyShorthand borderDirections(CSSPropertyBorder, properties);
return borderDirections;
}
CSSPropertyID CSSProperty::resolveDirectionAwareProperty(CSSPropertyID propertyID, TextDirection direction, WritingMode writingMode)
{
switch (propertyID) {
case CSSPropertyInsetInlineEnd:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::End, insetShorthand());
case CSSPropertyInsetInlineStart:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::Start, insetShorthand());
case CSSPropertyInsetBlockStart:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::Before, insetShorthand());
case CSSPropertyInsetBlockEnd:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::After, insetShorthand());
case CSSPropertyMarginInlineEnd:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::End, marginShorthand());
case CSSPropertyMarginInlineStart:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::Start, marginShorthand());
case CSSPropertyMarginBlockStart:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::Before, marginShorthand());
case CSSPropertyMarginBlockEnd:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::After, marginShorthand());
case CSSPropertyPaddingInlineEnd:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::End, paddingShorthand());
case CSSPropertyPaddingInlineStart:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::Start, paddingShorthand());
case CSSPropertyPaddingBlockStart:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::Before, paddingShorthand());
case CSSPropertyPaddingBlockEnd:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::After, paddingShorthand());
case CSSPropertyBorderInlineEnd:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::End, borderDirections());
case CSSPropertyBorderInlineStart:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::Start, borderDirections());
case CSSPropertyBorderBlockStart:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::Before, borderDirections());
case CSSPropertyBorderBlockEnd:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::After, borderDirections());
case CSSPropertyBorderInlineEndColor:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::End, borderColorShorthand());
case CSSPropertyBorderInlineStartColor:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::Start, borderColorShorthand());
case CSSPropertyBorderBlockStartColor:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::Before, borderColorShorthand());
case CSSPropertyBorderBlockEndColor:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::After, borderColorShorthand());
case CSSPropertyBorderInlineEndStyle:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::End, borderStyleShorthand());
case CSSPropertyBorderInlineStartStyle:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::Start, borderStyleShorthand());
case CSSPropertyBorderBlockStartStyle:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::Before, borderStyleShorthand());
case CSSPropertyBorderBlockEndStyle:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::After, borderStyleShorthand());
case CSSPropertyBorderInlineEndWidth:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::End, borderWidthShorthand());
case CSSPropertyBorderInlineStartWidth:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::Start, borderWidthShorthand());
case CSSPropertyBorderBlockStartWidth:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::Before, borderWidthShorthand());
case CSSPropertyBorderBlockEndWidth:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::After, borderWidthShorthand());
case CSSPropertyInlineSize: {
const CSSPropertyID properties[2] = { CSSPropertyWidth, CSSPropertyHeight };
return resolveToPhysicalProperty(writingMode, LogicalWidth, properties);
}
case CSSPropertyBlockSize: {
const CSSPropertyID properties[2] = { CSSPropertyWidth, CSSPropertyHeight };
return resolveToPhysicalProperty(writingMode, LogicalHeight, properties);
}
case CSSPropertyMinInlineSize: {
const CSSPropertyID properties[2] = { CSSPropertyMinWidth, CSSPropertyMinHeight };
return resolveToPhysicalProperty(writingMode, LogicalWidth, properties);
}
case CSSPropertyMinBlockSize: {
const CSSPropertyID properties[2] = { CSSPropertyMinWidth, CSSPropertyMinHeight };
return resolveToPhysicalProperty(writingMode, LogicalHeight, properties);
}
case CSSPropertyMaxInlineSize: {
const CSSPropertyID properties[2] = { CSSPropertyMaxWidth, CSSPropertyMaxHeight };
return resolveToPhysicalProperty(writingMode, LogicalWidth, properties);
}
case CSSPropertyMaxBlockSize: {
const CSSPropertyID properties[2] = { CSSPropertyMaxWidth, CSSPropertyMaxHeight };
return resolveToPhysicalProperty(writingMode, LogicalHeight, properties);
}
case CSSPropertyBorderStartStartRadius:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxCorner::StartStart, borderRadiusShorthand());
case CSSPropertyBorderStartEndRadius:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxCorner::StartEnd, borderRadiusShorthand());
case CSSPropertyBorderEndStartRadius:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxCorner::EndStart, borderRadiusShorthand());
case CSSPropertyBorderEndEndRadius:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxCorner::EndEnd, borderRadiusShorthand());
case CSSPropertyScrollMarginInlineStart:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::Start, scrollMarginShorthand());
case CSSPropertyScrollMarginInlineEnd:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::End, scrollMarginShorthand());
case CSSPropertyScrollMarginBlockStart:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::Before, scrollMarginShorthand());
case CSSPropertyScrollMarginBlockEnd:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::After, scrollMarginShorthand());
case CSSPropertyScrollPaddingInlineStart:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::Start, scrollPaddingShorthand());
case CSSPropertyScrollPaddingInlineEnd:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::End, scrollPaddingShorthand());
case CSSPropertyScrollPaddingBlockStart:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::Before, scrollPaddingShorthand());
case CSSPropertyScrollPaddingBlockEnd:
return resolveToPhysicalProperty(direction, writingMode, LogicalBoxSide::After, scrollPaddingShorthand());
default:
return propertyID;
}
}
} // namespace WebCore