This source file includes following definitions.
- isAtShadowBoundary
- addIntrinsicMargins
- equivalentBlockDisplay
- doesNotInheritTextDecoration
- isInTopLayer
- isDisplayFlexibleBox
- isDisplayGridBox
- parentStyleForcesZIndexToCreateStackingContext
- hasWillChangeThatCreatesStackingContext
- adjustRenderStyle
- adjustStyleForTagName
- adjustOverflow
- adjustStyleForDisplay
#include "config.h"
#include "core/css/resolver/StyleAdjuster.h"
#include "HTMLNames.h"
#include "SVGNames.h"
#include "core/dom/ContainerNode.h"
#include "core/dom/Document.h"
#include "core/dom/Element.h"
#include "core/dom/NodeRenderStyle.h"
#include "core/html/HTMLIFrameElement.h"
#include "core/html/HTMLInputElement.h"
#include "core/html/HTMLTableCellElement.h"
#include "core/html/HTMLTextAreaElement.h"
#include "core/frame/FrameView.h"
#include "core/frame/Settings.h"
#include "core/rendering/RenderTheme.h"
#include "core/rendering/style/GridPosition.h"
#include "core/rendering/style/RenderStyle.h"
#include "core/rendering/style/RenderStyleConstants.h"
#include "core/svg/SVGSVGElement.h"
#include "platform/Length.h"
#include "platform/transforms/TransformOperations.h"
#include "wtf/Assertions.h"
namespace WebCore {
using namespace HTMLNames;
static inline bool isAtShadowBoundary(const Element* element)
{
if (!element)
return false;
ContainerNode* parentNode = element->parentNode();
return parentNode && parentNode->isShadowRoot();
}
static void addIntrinsicMargins(RenderStyle* style)
{
const int intrinsicMargin = 2 * style->effectiveZoom();
if (style->width().isIntrinsicOrAuto()) {
if (style->marginLeft().quirk())
style->setMarginLeft(Length(intrinsicMargin, Fixed));
if (style->marginRight().quirk())
style->setMarginRight(Length(intrinsicMargin, Fixed));
}
if (style->height().isAuto()) {
if (style->marginTop().quirk())
style->setMarginTop(Length(intrinsicMargin, Fixed));
if (style->marginBottom().quirk())
style->setMarginBottom(Length(intrinsicMargin, Fixed));
}
}
static EDisplay equivalentBlockDisplay(EDisplay display, bool isFloating, bool strictParsing)
{
switch (display) {
case BLOCK:
case TABLE:
case BOX:
case FLEX:
case GRID:
return display;
case LIST_ITEM:
if (!strictParsing && isFloating)
return BLOCK;
return display;
case INLINE_TABLE:
return TABLE;
case INLINE_BOX:
return BOX;
case INLINE_FLEX:
return FLEX;
case INLINE_GRID:
return GRID;
case INLINE:
case INLINE_BLOCK:
case TABLE_ROW_GROUP:
case TABLE_HEADER_GROUP:
case TABLE_FOOTER_GROUP:
case TABLE_ROW:
case TABLE_COLUMN_GROUP:
case TABLE_COLUMN:
case TABLE_CELL:
case TABLE_CAPTION:
return BLOCK;
case NONE:
ASSERT_NOT_REACHED();
return NONE;
}
ASSERT_NOT_REACHED();
return BLOCK;
}
static bool doesNotInheritTextDecoration(const RenderStyle* style, const Element* e)
{
return style->display() == TABLE || style->display() == INLINE_TABLE
|| style->display() == INLINE_BLOCK || style->display() == INLINE_BOX || isAtShadowBoundary(e)
|| style->isFloating() || style->hasOutOfFlowPosition();
}
static bool isInTopLayer(const Element* element, const RenderStyle* style)
{
return (element && element->isInTopLayer()) || (style && style->styleType() == BACKDROP);
}
static bool isDisplayFlexibleBox(EDisplay display)
{
return display == FLEX || display == INLINE_FLEX;
}
static bool isDisplayGridBox(EDisplay display)
{
return display == GRID || display == INLINE_GRID;
}
static bool parentStyleForcesZIndexToCreateStackingContext(const RenderStyle* parentStyle)
{
return isDisplayFlexibleBox(parentStyle->display()) || isDisplayGridBox(parentStyle->display());
}
static bool hasWillChangeThatCreatesStackingContext(const RenderStyle* style, Element* e)
{
for (size_t i = 0; i < style->willChangeProperties().size(); ++i) {
switch (style->willChangeProperties()[i]) {
case CSSPropertyOpacity:
case CSSPropertyTransform:
case CSSPropertyWebkitTransform:
case CSSPropertyTransformStyle:
case CSSPropertyWebkitTransformStyle:
case CSSPropertyPerspective:
case CSSPropertyWebkitPerspective:
case CSSPropertyWebkitMask:
case CSSPropertyWebkitMaskBoxImage:
case CSSPropertyWebkitClipPath:
case CSSPropertyWebkitBoxReflect:
case CSSPropertyWebkitFilter:
case CSSPropertyZIndex:
case CSSPropertyPosition:
return true;
case CSSPropertyMixBlendMode:
case CSSPropertyIsolation:
if (RuntimeEnabledFeatures::cssCompositingEnabled())
return true;
break;
default:
break;
}
}
return false;
}
void StyleAdjuster::adjustRenderStyle(RenderStyle* style, RenderStyle* parentStyle, Element *e)
{
ASSERT(parentStyle);
style->setOriginalDisplay(style->display());
if (style->display() != NONE) {
if (e)
adjustStyleForTagName(style, parentStyle, *e);
if (isInTopLayer(e, style) && (style->position() == StaticPosition || style->position() == RelativePosition))
style->setPosition(AbsolutePosition);
if (style->hasOutOfFlowPosition() || style->isFloating() || (e && e->document().documentElement() == e))
style->setDisplay(equivalentBlockDisplay(style->display(), style->isFloating(), !m_useQuirksModeStyles));
adjustStyleForDisplay(style, parentStyle);
}
if (style->position() == StaticPosition && !parentStyleForcesZIndexToCreateStackingContext(parentStyle))
style->setHasAutoZIndex();
if (style->hasAutoZIndex() && ((e && e->document().documentElement() == e)
|| style->opacity() < 1.0f
|| style->hasTransformRelatedProperty()
|| style->hasMask()
|| style->clipPath()
|| style->boxReflect()
|| style->hasFilter()
|| style->hasBlendMode()
|| style->hasIsolation()
|| style->position() == StickyPosition
|| style->position() == FixedPosition
|| isInTopLayer(e, style)
|| hasWillChangeThatCreatesStackingContext(style, e)))
style->setZIndex(0);
if (!style->hasTransform() && (style->willChangeProperties().contains(CSSPropertyWebkitTransform) || style->willChangeProperties().contains(CSSPropertyTransform))) {
bool makeIdentity = true;
style->setTransform(TransformOperations(makeIdentity));
}
if (doesNotInheritTextDecoration(style, e))
style->setTextDecorationsInEffect(style->textDecoration());
else
style->addToTextDecorationsInEffect(style->textDecoration());
if (style->overflowX() != OVISIBLE || style->overflowY() != OVISIBLE)
adjustOverflow(style, e);
style->adjustBackgroundLayers();
style->adjustMaskLayers();
if (style->hasAppearance())
RenderTheme::theme().adjustStyle(style, e, m_cachedUAStyle);
if (style->hasPseudoStyle(FIRST_LETTER) || style->transitions() || style->animations())
style->setUnique();
if (style->preserves3D() && (style->overflowX() != OVISIBLE
|| style->overflowY() != OVISIBLE
|| style->hasFilter()))
style->setTransformStyle3D(TransformStyle3DFlat);
if (e && e->isSVGElement()) {
if (!(isSVGSVGElement(*e) && e->parentNode() && !e->parentNode()->isSVGElement()))
style->setPosition(RenderStyle::initialPosition());
if (isSVGForeignObjectElement(*e))
style->setEffectiveZoom(RenderStyle::initialZoom());
if ((isSVGForeignObjectElement(*e) || isSVGTextElement(*e)) && style->isDisplayInlineType())
style->setDisplay(BLOCK);
}
if (e && e->renderStyle() && e->renderStyle()->textAutosizingMultiplier() != 1) {
style->setTextAutosizingMultiplier(e->renderStyle()->textAutosizingMultiplier());
style->setUnique();
}
}
void StyleAdjuster::adjustStyleForTagName(RenderStyle* style, RenderStyle* parentStyle, Element& element)
{
if (isHTMLDivElement(element) || isHTMLSpanElement(element))
return;
if (isHTMLTableCellElement(element)) {
if (element.hasTagName(tdTag) && m_useQuirksModeStyles) {
style->setDisplay(TABLE_CELL);
style->setFloating(NoFloat);
}
if (element.hasTagName(thTag) && style->textAlign() == TASTART)
style->setTextAlign(CENTER);
if (style->whiteSpace() == KHTML_NOWRAP) {
if (style->width().isFixed())
style->setWhiteSpace(NORMAL);
else
style->setWhiteSpace(NOWRAP);
}
return;
}
if (isHTMLTableElement(element)) {
if (m_useQuirksModeStyles)
style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
if (style->textAlign() == WEBKIT_LEFT || style->textAlign() == WEBKIT_CENTER || style->textAlign() == WEBKIT_RIGHT)
style->setTextAlign(TASTART);
return;
}
if (isHTMLFrameElement(element) || isHTMLFrameSetElement(element)) {
style->setPosition(StaticPosition);
style->setDisplay(BLOCK);
return;
}
if (isHTMLRTElement(element)) {
style->setPosition(StaticPosition);
style->setFloating(NoFloat);
return;
}
if (isHTMLLegendElement(element)) {
style->setDisplay(BLOCK);
return;
}
if (isHTMLMarqueeElement(element)) {
style->setOverflowX(OHIDDEN);
style->setOverflowY(OHIDDEN);
return;
}
if (element.isFormControlElement()) {
if (isHTMLTextAreaElement(element)) {
style->setOverflowX(style->overflowX() == OVISIBLE ? OAUTO : style->overflowX());
style->setOverflowY(style->overflowY() == OVISIBLE ? OAUTO : style->overflowY());
}
if (style->fontSize() >= 11 && (!isHTMLInputElement(element) || !toHTMLInputElement(element).isImageButton()))
addIntrinsicMargins(style);
return;
}
}
void StyleAdjuster::adjustOverflow(RenderStyle* style, Element* element)
{
ASSERT(style->overflowX() != OVISIBLE || style->overflowY() != OVISIBLE);
if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE) {
style->setOverflowX(OAUTO);
} else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE) {
style->setOverflowY(OAUTO);
}
if (style->display() == TABLE || style->display() == INLINE_TABLE
|| style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) {
if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN)
style->setOverflowX(OVISIBLE);
if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN)
style->setOverflowY(OVISIBLE);
}
if (style->appearance() == MenulistPart) {
style->setOverflowX(OVISIBLE);
style->setOverflowY(OVISIBLE);
}
if (element && element->isSVGElement()) {
if (style->overflowY() == OSCROLL)
style->setOverflowY(OHIDDEN);
else if (style->overflowY() == OAUTO)
style->setOverflowY(OVISIBLE);
if (style->overflowX() == OSCROLL)
style->setOverflowX(OHIDDEN);
else if (style->overflowX() == OAUTO)
style->setOverflowX(OVISIBLE);
}
}
void StyleAdjuster::adjustStyleForDisplay(RenderStyle* style, RenderStyle* parentStyle)
{
if (style->display() == BLOCK && !style->isFloating())
return;
if (style->display() == INLINE && style->styleType() == NOPSEUDO && style->writingMode() != parentStyle->writingMode())
style->setDisplay(INLINE_BLOCK);
if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP
|| style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW)
&& style->position() == RelativePosition)
style->setPosition(StaticPosition);
if ((style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_COLUMN)
&& style->position() == StickyPosition)
style->setPosition(StaticPosition);
if (style->display() == TABLE_COLUMN || style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_FOOTER_GROUP
|| style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_ROW_GROUP
|| style->display() == TABLE_CELL)
style->setWritingMode(parentStyle->writingMode());
if (style->writingMode() != TopToBottomWritingMode && (style->display() == BOX || style->display() == INLINE_BOX))
style->setWritingMode(TopToBottomWritingMode);
if (isDisplayFlexibleBox(parentStyle->display()) || isDisplayGridBox(parentStyle->display())) {
style->setFloating(NoFloat);
style->setDisplay(equivalentBlockDisplay(style->display(), style->isFloating(), !m_useQuirksModeStyles));
}
}
}