diff options
Diffstat (limited to 'WebCore/rendering/RenderStyle.cpp')
-rw-r--r-- | WebCore/rendering/RenderStyle.cpp | 1732 |
1 files changed, 1732 insertions, 0 deletions
diff --git a/WebCore/rendering/RenderStyle.cpp b/WebCore/rendering/RenderStyle.cpp new file mode 100644 index 0000000..734c0fd --- /dev/null +++ b/WebCore/rendering/RenderStyle.cpp @@ -0,0 +1,1732 @@ +/* + * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org) + * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "RenderStyle.h" + +#include "CSSStyleSelector.h" +#include "RenderArena.h" + +namespace WebCore { + +static RenderStyle* defaultStyle; + +StyleSurroundData::StyleSurroundData() + : margin(Fixed) + , padding(Fixed) +{ +} + +StyleSurroundData::StyleSurroundData(const StyleSurroundData& o) + : RefCounted<StyleSurroundData>() + , offset(o.offset) + , margin(o.margin) + , padding(o.padding) + , border(o.border) +{ +} + +bool StyleSurroundData::operator==(const StyleSurroundData& o) const +{ + return offset == o.offset && margin == o.margin && padding == o.padding && border == o.border; +} + +StyleBoxData::StyleBoxData() + : z_index(0) + , z_auto(true) + , boxSizing(CONTENT_BOX) +{ + // Initialize our min/max widths/heights. + min_width = min_height = RenderStyle::initialMinSize(); + max_width = max_height = RenderStyle::initialMaxSize(); +} + +StyleBoxData::StyleBoxData(const StyleBoxData& o) + : RefCounted<StyleBoxData>() + , width(o.width) + , height(o.height) + , min_width(o.min_width) + , max_width(o.max_width) + , min_height(o.min_height) + , max_height(o.max_height) + , z_index(o.z_index) + , z_auto(o.z_auto) + , boxSizing(o.boxSizing) +{ +} + +bool StyleBoxData::operator==(const StyleBoxData& o) const +{ + return width == o.width && + height == o.height && + min_width == o.min_width && + max_width == o.max_width && + min_height == o.min_height && + max_height == o.max_height && + z_index == o.z_index && + z_auto == o.z_auto && + boxSizing == o.boxSizing; +} + +StyleVisualData::StyleVisualData() + : hasClip(false) + , textDecoration(RenderStyle::initialTextDecoration()) + , counterIncrement(0) + , counterReset(0) +{ +} + +StyleVisualData::~StyleVisualData() +{ +} + +StyleVisualData::StyleVisualData(const StyleVisualData& o) + : RefCounted<StyleVisualData>() + , clip(o.clip) + , hasClip(o.hasClip) + , textDecoration(o.textDecoration) + , counterIncrement(o.counterIncrement) + , counterReset(o.counterReset) +{ +} + +BackgroundLayer::BackgroundLayer() + : m_image(RenderStyle::initialBackgroundImage()) + , m_xPosition(RenderStyle::initialBackgroundXPosition()) + , m_yPosition(RenderStyle::initialBackgroundYPosition()) + , m_bgAttachment(RenderStyle::initialBackgroundAttachment()) + , m_bgClip(RenderStyle::initialBackgroundClip()) + , m_bgOrigin(RenderStyle::initialBackgroundOrigin()) + , m_bgRepeat(RenderStyle::initialBackgroundRepeat()) + , m_bgComposite(RenderStyle::initialBackgroundComposite()) + , m_backgroundSize(RenderStyle::initialBackgroundSize()) + , m_imageSet(false) + , m_attachmentSet(false) + , m_clipSet(false) + , m_originSet(false) + , m_repeatSet(false) + , m_xPosSet(false) + , m_yPosSet(false) + , m_compositeSet(false) + , m_backgroundSizeSet(false) + , m_next(0) +{ +} + +BackgroundLayer::BackgroundLayer(const BackgroundLayer& o) + : m_image(o.m_image) + , m_xPosition(o.m_xPosition) + , m_yPosition(o.m_yPosition) + , m_bgAttachment(o.m_bgAttachment) + , m_bgClip(o.m_bgClip) + , m_bgOrigin(o.m_bgOrigin) + , m_bgRepeat(o.m_bgRepeat) + , m_bgComposite(o.m_bgComposite) + , m_backgroundSize(o.m_backgroundSize) + , m_imageSet(o.m_imageSet) + , m_attachmentSet(o.m_attachmentSet) + , m_clipSet(o.m_clipSet) + , m_originSet(o.m_originSet) + , m_repeatSet(o.m_repeatSet) + , m_xPosSet(o.m_xPosSet) + , m_yPosSet(o.m_yPosSet) + , m_compositeSet(o.m_compositeSet) + , m_backgroundSizeSet(o.m_backgroundSizeSet) + , m_next(o.m_next ? new BackgroundLayer(*o.m_next) : 0) +{ +} + +BackgroundLayer::~BackgroundLayer() +{ + delete m_next; +} + +BackgroundLayer& BackgroundLayer::operator=(const BackgroundLayer& o) +{ + if (m_next != o.m_next) { + delete m_next; + m_next = o.m_next ? new BackgroundLayer(*o.m_next) : 0; + } + + m_image = o.m_image; + m_xPosition = o.m_xPosition; + m_yPosition = o.m_yPosition; + m_bgAttachment = o.m_bgAttachment; + m_bgClip = o.m_bgClip; + m_bgComposite = o.m_bgComposite; + m_bgOrigin = o.m_bgOrigin; + m_bgRepeat = o.m_bgRepeat; + m_backgroundSize = o.m_backgroundSize; + + m_imageSet = o.m_imageSet; + m_attachmentSet = o.m_attachmentSet; + m_clipSet = o.m_clipSet; + m_compositeSet = o.m_compositeSet; + m_originSet = o.m_originSet; + m_repeatSet = o.m_repeatSet; + m_xPosSet = o.m_xPosSet; + m_yPosSet = o.m_yPosSet; + m_backgroundSizeSet = o.m_backgroundSizeSet; + + return *this; +} + +bool BackgroundLayer::operator==(const BackgroundLayer& o) const +{ + // We do not check the "isSet" booleans for each property, since those are only used during initial construction + // to propagate patterns into layers. All layer comparisons happen after values have all been filled in anyway. + return m_image == o.m_image && m_xPosition == o.m_xPosition && m_yPosition == o.m_yPosition && + m_bgAttachment == o.m_bgAttachment && m_bgClip == o.m_bgClip && + m_bgComposite == o.m_bgComposite && m_bgOrigin == o.m_bgOrigin && m_bgRepeat == o.m_bgRepeat && + m_backgroundSize.width == o.m_backgroundSize.width && m_backgroundSize.height == o.m_backgroundSize.height && + ((m_next && o.m_next) ? *m_next == *o.m_next : m_next == o.m_next); +} + +void BackgroundLayer::fillUnsetProperties() +{ + BackgroundLayer* curr; + for (curr = this; curr && curr->isBackgroundImageSet(); curr = curr->next()) { } + if (curr && curr != this) { + // We need to fill in the remaining values with the pattern specified. + for (BackgroundLayer* pattern = this; curr; curr = curr->next()) { + curr->m_image = pattern->m_image; + pattern = pattern->next(); + if (pattern == curr || !pattern) + pattern = this; + } + } + + for (curr = this; curr && curr->isBackgroundXPositionSet(); curr = curr->next()) { } + if (curr && curr != this) { + // We need to fill in the remaining values with the pattern specified. + for (BackgroundLayer* pattern = this; curr; curr = curr->next()) { + curr->m_xPosition = pattern->m_xPosition; + pattern = pattern->next(); + if (pattern == curr || !pattern) + pattern = this; + } + } + + for (curr = this; curr && curr->isBackgroundYPositionSet(); curr = curr->next()) { } + if (curr && curr != this) { + // We need to fill in the remaining values with the pattern specified. + for (BackgroundLayer* pattern = this; curr; curr = curr->next()) { + curr->m_yPosition = pattern->m_yPosition; + pattern = pattern->next(); + if (pattern == curr || !pattern) + pattern = this; + } + } + + for (curr = this; curr && curr->isBackgroundAttachmentSet(); curr = curr->next()) { } + if (curr && curr != this) { + // We need to fill in the remaining values with the pattern specified. + for (BackgroundLayer* pattern = this; curr; curr = curr->next()) { + curr->m_bgAttachment = pattern->m_bgAttachment; + pattern = pattern->next(); + if (pattern == curr || !pattern) + pattern = this; + } + } + + for (curr = this; curr && curr->isBackgroundClipSet(); curr = curr->next()) { } + if (curr && curr != this) { + // We need to fill in the remaining values with the pattern specified. + for (BackgroundLayer* pattern = this; curr; curr = curr->next()) { + curr->m_bgClip = pattern->m_bgClip; + pattern = pattern->next(); + if (pattern == curr || !pattern) + pattern = this; + } + } + + for (curr = this; curr && curr->isBackgroundCompositeSet(); curr = curr->next()) { } + if (curr && curr != this) { + // We need to fill in the remaining values with the pattern specified. + for (BackgroundLayer* pattern = this; curr; curr = curr->next()) { + curr->m_bgComposite = pattern->m_bgComposite; + pattern = pattern->next(); + if (pattern == curr || !pattern) + pattern = this; + } + } + + for (curr = this; curr && curr->isBackgroundOriginSet(); curr = curr->next()) { } + if (curr && curr != this) { + // We need to fill in the remaining values with the pattern specified. + for (BackgroundLayer* pattern = this; curr; curr = curr->next()) { + curr->m_bgOrigin = pattern->m_bgOrigin; + pattern = pattern->next(); + if (pattern == curr || !pattern) + pattern = this; + } + } + + for (curr = this; curr && curr->isBackgroundRepeatSet(); curr = curr->next()) { } + if (curr && curr != this) { + // We need to fill in the remaining values with the pattern specified. + for (BackgroundLayer* pattern = this; curr; curr = curr->next()) { + curr->m_bgRepeat = pattern->m_bgRepeat; + pattern = pattern->next(); + if (pattern == curr || !pattern) + pattern = this; + } + } + + for (curr = this; curr && curr->isBackgroundSizeSet(); curr = curr->next()) { } + if (curr && curr != this) { + // We need to fill in the remaining values with the pattern specified. + for (BackgroundLayer* pattern = this; curr; curr = curr->next()) { + curr->m_backgroundSize = pattern->m_backgroundSize; + pattern = pattern->next(); + if (pattern == curr || !pattern) + pattern = this; + } + } +} + +void BackgroundLayer::cullEmptyLayers() +{ + BackgroundLayer *next; + for (BackgroundLayer *p = this; p; p = next) { + next = p->m_next; + if (next && !next->isBackgroundImageSet() && + !next->isBackgroundXPositionSet() && !next->isBackgroundYPositionSet() && + !next->isBackgroundAttachmentSet() && !next->isBackgroundClipSet() && + !next->isBackgroundCompositeSet() && !next->isBackgroundOriginSet() && + !next->isBackgroundRepeatSet() && !next->isBackgroundSizeSet()) { + delete next; + p->m_next = 0; + break; + } + } +} + +StyleBackgroundData::StyleBackgroundData() +{ +} + +StyleBackgroundData::StyleBackgroundData(const StyleBackgroundData& o) + : RefCounted<StyleBackgroundData>() + , m_background(o.m_background) + , m_outline(o.m_outline) +{ +} + +bool StyleBackgroundData::operator==(const StyleBackgroundData& o) const +{ + return m_background == o.m_background && m_color == o.m_color && m_outline == o.m_outline; +} + +StyleMarqueeData::StyleMarqueeData() + : increment(RenderStyle::initialMarqueeIncrement()) + , speed(RenderStyle::initialMarqueeSpeed()) + , loops(RenderStyle::initialMarqueeLoopCount()) + , behavior(RenderStyle::initialMarqueeBehavior()) + , direction(RenderStyle::initialMarqueeDirection()) +{ +} + +StyleMarqueeData::StyleMarqueeData(const StyleMarqueeData& o) + : RefCounted<StyleMarqueeData>() + , increment(o.increment) + , speed(o.speed) + , loops(o.loops) + , behavior(o.behavior) + , direction(o.direction) +{ +} + +bool StyleMarqueeData::operator==(const StyleMarqueeData& o) const +{ + return increment == o.increment && speed == o.speed && direction == o.direction && + behavior == o.behavior && loops == o.loops; +} + +StyleFlexibleBoxData::StyleFlexibleBoxData() + : flex(RenderStyle::initialBoxFlex()) + , flex_group(RenderStyle::initialBoxFlexGroup()) + , ordinal_group(RenderStyle::initialBoxOrdinalGroup()) + , align(RenderStyle::initialBoxAlign()) + , pack(RenderStyle::initialBoxPack()) + , orient(RenderStyle::initialBoxOrient()) + , lines(RenderStyle::initialBoxLines()) +{ +} + +StyleFlexibleBoxData::StyleFlexibleBoxData(const StyleFlexibleBoxData& o) + : RefCounted<StyleFlexibleBoxData>() + , flex(o.flex) + , flex_group(o.flex_group) + , ordinal_group(o.ordinal_group) + , align(o.align) + , pack(o.pack) + , orient(o.orient) + , lines(o.lines) +{ +} + +bool StyleFlexibleBoxData::operator==(const StyleFlexibleBoxData& o) const +{ + return flex == o.flex && flex_group == o.flex_group && + ordinal_group == o.ordinal_group && align == o.align && + pack == o.pack && orient == o.orient && lines == o.lines; +} + +StyleMultiColData::StyleMultiColData() + : m_width(0) + , m_count(RenderStyle::initialColumnCount()) + , m_gap(0) + , m_autoWidth(true) + , m_autoCount(true) + , m_normalGap(true) + , m_breakBefore(RenderStyle::initialPageBreak()) + , m_breakAfter(RenderStyle::initialPageBreak()) + , m_breakInside(RenderStyle::initialPageBreak()) +{ +} + +StyleMultiColData::StyleMultiColData(const StyleMultiColData& o) + : RefCounted<StyleMultiColData>() + , m_width(o.m_width) + , m_count(o.m_count) + , m_gap(o.m_gap) + , m_rule(o.m_rule) + , m_autoWidth(o.m_autoWidth) + , m_autoCount(o.m_autoCount) + , m_normalGap(o.m_normalGap) + , m_breakBefore(o.m_breakBefore) + , m_breakAfter(o.m_breakAfter) + , m_breakInside(o.m_breakInside) +{ +} + +bool StyleMultiColData::operator==(const StyleMultiColData& o) const +{ + return m_width == o.m_width && m_count == o.m_count && m_gap == o.m_gap && + m_rule == o.m_rule && m_breakBefore == o.m_breakBefore && + m_autoWidth == o.m_autoWidth && m_autoCount == o.m_autoCount && m_normalGap == o.m_normalGap && + m_breakAfter == o.m_breakAfter && m_breakInside == o.m_breakInside; +} + +StyleTransformData::StyleTransformData() + : m_operations(RenderStyle::initialTransform()) + , m_x(RenderStyle::initialTransformOriginX()) + , m_y(RenderStyle::initialTransformOriginY()) +{ +} + +StyleTransformData::StyleTransformData(const StyleTransformData& o) + : RefCounted<StyleTransformData>() + , m_operations(o.m_operations) + , m_x(o.m_x) + , m_y(o.m_y) +{ +} + +bool StyleTransformData::operator==(const StyleTransformData& o) const +{ + return m_x == o.m_x && m_y == o.m_y && m_operations == o.m_operations; +} + +bool TransformOperations::operator==(const TransformOperations& o) const +{ + if (m_operations.size() != o.m_operations.size()) + return false; + + unsigned s = m_operations.size(); + for (unsigned i = 0; i < s; i++) { + if (*m_operations[i] != *o.m_operations[i]) + return false; + } + + return true; +} + +TransformOperation* ScaleTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity) +{ + if (from && !from->isScaleOperation()) + return this; + + if (blendToIdentity) + return new ScaleTransformOperation(m_x + (1. - m_x) * progress, m_y + (1. - m_y) * progress); + + const ScaleTransformOperation* fromOp = static_cast<const ScaleTransformOperation*>(from); + double fromX = fromOp ? fromOp->m_x : 1.; + double fromY = fromOp ? fromOp->m_y : 1.; + return new ScaleTransformOperation(fromX + (m_x - fromX) * progress, fromY + (m_y - fromY) * progress); +} + +TransformOperation* RotateTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity) +{ + if (from && !from->isRotateOperation()) + return this; + + if (blendToIdentity) + return new RotateTransformOperation(m_angle - m_angle * progress); + + const RotateTransformOperation* fromOp = static_cast<const RotateTransformOperation*>(from); + double fromAngle = fromOp ? fromOp->m_angle : 0; + return new RotateTransformOperation(fromAngle + (m_angle - fromAngle) * progress); +} + +TransformOperation* SkewTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity) +{ + if (from && !from->isSkewOperation()) + return this; + + if (blendToIdentity) + return new SkewTransformOperation(m_angleX - m_angleX * progress, m_angleY - m_angleY * progress); + + const SkewTransformOperation* fromOp = static_cast<const SkewTransformOperation*>(from); + double fromAngleX = fromOp ? fromOp->m_angleX : 0; + double fromAngleY = fromOp ? fromOp->m_angleY : 0; + return new SkewTransformOperation(fromAngleX + (m_angleX - fromAngleX) * progress, fromAngleY + (m_angleY - fromAngleY) * progress); +} + +TransformOperation* TranslateTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity) +{ + if (from && !from->isTranslateOperation()) + return this; + + if (blendToIdentity) + return new TranslateTransformOperation(Length(0, m_x.type()).blend(m_x, progress), Length(0, m_y.type()).blend(m_y, progress)); + + const TranslateTransformOperation* fromOp = static_cast<const TranslateTransformOperation*>(from); + Length fromX = fromOp ? fromOp->m_x : Length(0, m_x.type()); + Length fromY = fromOp ? fromOp->m_y : Length(0, m_y.type()); + return new TranslateTransformOperation(m_x.blend(fromX, progress), m_y.blend(fromY, progress)); +} + +TransformOperation* MatrixTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity) +{ + if (from && !from->isMatrixOperation()) + return this; + + if (blendToIdentity) + return new MatrixTransformOperation(m_a * (1. - progress) + progress, + m_b * (1. - progress), + m_c * (1. - progress), + m_d * (1. - progress) + progress, + m_e * (1. - progress), + m_f * (1. - progress)); + + const MatrixTransformOperation* fromOp = static_cast<const MatrixTransformOperation*>(from); + double fromA = fromOp ? fromOp->m_a : 1.; + double fromB = fromOp ? fromOp->m_b : 0; + double fromC = fromOp ? fromOp->m_c : 0; + double fromD = fromOp ? fromOp->m_d : 1.; + double fromE = fromOp ? fromOp->m_e : 0; + double fromF = fromOp ? fromOp->m_f : 0; + + return new MatrixTransformOperation(fromA + (m_a - fromA) * progress, + fromB + (m_b - fromB) * progress, + fromC + (m_c - fromC) * progress, + fromD + (m_d - fromD) * progress, + fromE + (m_e - fromE) * progress, + fromF + (m_f - fromF) * progress); +} + +Transition::Transition() + : m_duration(RenderStyle::initialTransitionDuration()) + , m_repeatCount(RenderStyle::initialTransitionRepeatCount()) + , m_timingFunction(RenderStyle::initialTransitionTimingFunction()) + , m_property(RenderStyle::initialTransitionProperty()) + , m_durationSet(false) + , m_repeatCountSet(false) + , m_timingFunctionSet(false) + , m_propertySet(false) + , m_next(0) +{ +} + +Transition::Transition(const Transition& o) + : m_duration(o.m_duration) + , m_repeatCount(o.m_repeatCount) + , m_timingFunction(o.m_timingFunction) + , m_property(o.m_property) + , m_durationSet(o.m_durationSet) + , m_repeatCountSet(o.m_repeatCountSet) + , m_timingFunctionSet(o.m_timingFunctionSet) + , m_propertySet(o.m_propertySet) + , m_next(o.m_next ? new Transition(*o.m_next) : 0) +{ +} + +Transition::~Transition() +{ + delete m_next; +} + +Transition& Transition::operator=(const Transition& o) +{ + if (m_next != o.m_next) { + delete m_next; + m_next = o.m_next ? new Transition(*o.m_next) : 0; + } + + m_duration = o.m_duration; + m_repeatCount = o.m_repeatCount; + m_timingFunction = o.m_timingFunction; + m_property = o.m_property; + + m_durationSet = o.m_durationSet; + m_repeatCountSet = o.m_repeatCountSet; + m_timingFunctionSet = o.m_timingFunctionSet; + m_propertySet = o.m_propertySet; + + return *this; +} + +bool Transition::operator==(const Transition& o) const +{ + return m_duration == o.m_duration && m_repeatCount == o.m_repeatCount && m_timingFunction == o.m_timingFunction && + m_property == o.m_property && m_durationSet == o.m_durationSet && m_repeatCountSet == o.m_repeatCountSet && + m_timingFunctionSet == o.m_timingFunctionSet && m_propertySet == o.m_propertySet && + ((m_next && o.m_next) ? *m_next == *o.m_next : m_next == o.m_next); +} + +void Transition::fillUnsetProperties() +{ + Transition* curr; + for (curr = this; curr && curr->isTransitionDurationSet(); curr = curr->next()) { } + if (curr && curr != this) { + // We need to fill in the remaining values with the pattern specified. + for (Transition* pattern = this; curr; curr = curr->next()) { + curr->m_duration = pattern->m_duration; + pattern = pattern->next(); + if (pattern == curr || !pattern) + pattern = this; + } + } + + for (curr = this; curr && curr->isTransitionRepeatCountSet(); curr = curr->next()) { } + if (curr && curr != this) { + // We need to fill in the remaining values with the pattern specified. + for (Transition* pattern = this; curr; curr = curr->next()) { + curr->m_repeatCount = pattern->m_repeatCount; + pattern = pattern->next(); + if (pattern == curr || !pattern) + pattern = this; + } + } + + for (curr = this; curr && curr->isTransitionTimingFunctionSet(); curr = curr->next()) { } + if (curr && curr != this) { + // We need to fill in the remaining values with the pattern specified. + for (Transition* pattern = this; curr; curr = curr->next()) { + curr->m_timingFunction = pattern->m_timingFunction; + pattern = pattern->next(); + if (pattern == curr || !pattern) + pattern = this; + } + } + + for (curr = this; curr && curr->isTransitionPropertySet(); curr = curr->next()) { } + if (curr && curr != this) { + // We need to fill in the remaining values with the pattern specified. + for (Transition* pattern = this; curr; curr = curr->next()) { + curr->m_property = pattern->m_property; + pattern = pattern->next(); + if (pattern == curr || !pattern) + pattern = this; + } + } +} + +StyleRareNonInheritedData::StyleRareNonInheritedData() + : lineClamp(RenderStyle::initialLineClamp()) + , opacity(RenderStyle::initialOpacity()) + , m_content(0) + , m_counterDirectives(0) + , userDrag(RenderStyle::initialUserDrag()) + , textOverflow(RenderStyle::initialTextOverflow()) + , marginTopCollapse(MCOLLAPSE) + , marginBottomCollapse(MCOLLAPSE) + , matchNearestMailBlockquoteColor(RenderStyle::initialMatchNearestMailBlockquoteColor()) + , m_appearance(RenderStyle::initialAppearance()) + , m_borderFit(RenderStyle::initialBorderFit()) + , m_boxShadow(0) + , m_transition(0) +#if ENABLE(XBL) + , bindingURI(0) +#endif +{ +} + +StyleRareNonInheritedData::StyleRareNonInheritedData(const StyleRareNonInheritedData& o) + : RefCounted<StyleRareNonInheritedData>() + , lineClamp(o.lineClamp) + , opacity(o.opacity) + , flexibleBox(o.flexibleBox) + , marquee(o.marquee) + , m_multiCol(o.m_multiCol) + , m_transform(o.m_transform) + , m_content(0) + , m_counterDirectives(0) + , userDrag(o.userDrag) + , textOverflow(o.textOverflow) + , marginTopCollapse(o.marginTopCollapse) + , marginBottomCollapse(o.marginBottomCollapse) + , matchNearestMailBlockquoteColor(o.matchNearestMailBlockquoteColor) + , m_appearance(o.m_appearance) + , m_borderFit(o.m_borderFit) + , m_boxShadow(o.m_boxShadow ? new ShadowData(*o.m_boxShadow) : 0) + , m_transition(o.m_transition ? new Transition(*o.m_transition) : 0) +#if ENABLE(XBL) + , bindingURI(o.bindingURI ? o.bindingURI->copy() : 0) +#endif +{ +} + +StyleRareNonInheritedData::~StyleRareNonInheritedData() +{ + delete m_content; + delete m_counterDirectives; + delete m_boxShadow; + delete m_transition; +#if ENABLE(XBL) + delete bindingURI; +#endif +} + +#if ENABLE(XBL) +bool StyleRareNonInheritedData::bindingsEquivalent(const StyleRareNonInheritedData& o) const +{ + if (this == &o) return true; + if (!bindingURI && o.bindingURI || bindingURI && !o.bindingURI) + return false; + if (bindingURI && o.bindingURI && (*bindingURI != *o.bindingURI)) + return false; + return true; +} +#endif + +bool StyleRareNonInheritedData::operator==(const StyleRareNonInheritedData& o) const +{ + return lineClamp == o.lineClamp + && m_dashboardRegions == o.m_dashboardRegions + && opacity == o.opacity + && flexibleBox == o.flexibleBox + && marquee == o.marquee + && m_multiCol == o.m_multiCol + && m_transform == o.m_transform + && m_content == o.m_content + && m_counterDirectives == o.m_counterDirectives + && userDrag == o.userDrag + && textOverflow == o.textOverflow + && marginTopCollapse == o.marginTopCollapse + && marginBottomCollapse == o.marginBottomCollapse + && matchNearestMailBlockquoteColor == o.matchNearestMailBlockquoteColor + && m_appearance == o.m_appearance + && m_borderFit == o.m_borderFit + && shadowDataEquivalent(o) + && transitionDataEquivalent(o) +#if ENABLE(XBL) + && bindingsEquivalent(o) +#endif + ; +} + +bool StyleRareNonInheritedData::shadowDataEquivalent(const StyleRareNonInheritedData& o) const +{ + if (!m_boxShadow && o.m_boxShadow || m_boxShadow && !o.m_boxShadow) + return false; + if (m_boxShadow && o.m_boxShadow && (*m_boxShadow != *o.m_boxShadow)) + return false; + return true; +} + +bool StyleRareNonInheritedData::transitionDataEquivalent(const StyleRareNonInheritedData& o) const +{ + if (!m_transition && o.m_transition || m_transition && !o.m_transition) + return false; + if (m_transition && o.m_transition && (*m_transition != *o.m_transition)) + return false; + return true; +} + +StyleRareInheritedData::StyleRareInheritedData() + : textStrokeWidth(RenderStyle::initialTextStrokeWidth()) + , textShadow(0) + , textSecurity(RenderStyle::initialTextSecurity()) + , userModify(READ_ONLY) + , wordBreak(RenderStyle::initialWordBreak()) + , wordWrap(RenderStyle::initialWordWrap()) + , nbspMode(NBNORMAL) + , khtmlLineBreak(LBNORMAL) + , textSizeAdjust(RenderStyle::initialTextSizeAdjust()) + , resize(RenderStyle::initialResize()) + , userSelect(RenderStyle::initialUserSelect()) +{ +} + +StyleRareInheritedData::StyleRareInheritedData(const StyleRareInheritedData& o) + : RefCounted<StyleRareInheritedData>() + , textStrokeColor(o.textStrokeColor) + , textStrokeWidth(o.textStrokeWidth) + , textFillColor(o.textFillColor) + , textShadow(o.textShadow ? new ShadowData(*o.textShadow) : 0) + , highlight(o.highlight) + , textSecurity(o.textSecurity) + , userModify(o.userModify) + , wordBreak(o.wordBreak) + , wordWrap(o.wordWrap) + , nbspMode(o.nbspMode) + , khtmlLineBreak(o.khtmlLineBreak) + , textSizeAdjust(o.textSizeAdjust) + , resize(o.resize) + , userSelect(o.userSelect) +{ +} + +StyleRareInheritedData::~StyleRareInheritedData() +{ + delete textShadow; +} + +bool StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const +{ + return textStrokeColor == o.textStrokeColor + && textStrokeWidth == o.textStrokeWidth + && textFillColor == o.textFillColor + && shadowDataEquivalent(o) + && highlight == o.highlight + && textSecurity == o.textSecurity + && userModify == o.userModify + && wordBreak == o.wordBreak + && wordWrap == o.wordWrap + && nbspMode == o.nbspMode + && khtmlLineBreak == o.khtmlLineBreak + && textSizeAdjust == o.textSizeAdjust + && userSelect == o.userSelect; +} + +bool StyleRareInheritedData::shadowDataEquivalent(const StyleRareInheritedData& o) const +{ + if (!textShadow && o.textShadow || textShadow && !o.textShadow) + return false; + if (textShadow && o.textShadow && (*textShadow != *o.textShadow)) + return false; + return true; +} + +StyleInheritedData::StyleInheritedData() + : indent(RenderStyle::initialTextIndent()) + , line_height(RenderStyle::initialLineHeight()) + , style_image(RenderStyle::initialListStyleImage()) + , color(RenderStyle::initialColor()) + , horizontal_border_spacing(RenderStyle::initialHorizontalBorderSpacing()) + , vertical_border_spacing(RenderStyle::initialVerticalBorderSpacing()) + , widows(RenderStyle::initialWidows()) + , orphans(RenderStyle::initialOrphans()) + , page_break_inside(RenderStyle::initialPageBreak()) +{ +} + +StyleInheritedData::~StyleInheritedData() +{ +} + +StyleInheritedData::StyleInheritedData(const StyleInheritedData& o) + : RefCounted<StyleInheritedData>() + , indent(o.indent) + , line_height(o.line_height) + , style_image(o.style_image) + , cursorData(o.cursorData) + , font(o.font) + , color(o.color) + , horizontal_border_spacing(o.horizontal_border_spacing) + , vertical_border_spacing(o.vertical_border_spacing) + , widows(o.widows) + , orphans(o.orphans) + , page_break_inside(o.page_break_inside) +{ +} + +static bool cursorDataEqvuialent(const CursorList* c1, const CursorList* c2) +{ + if (c1 == c2) + return true; + if (!c1 && c2 || c1 && !c2) + return false; + return (*c1 == *c2); +} + +bool StyleInheritedData::operator==(const StyleInheritedData& o) const +{ + return + indent == o.indent && + line_height == o.line_height && + style_image == o.style_image && + cursorDataEqvuialent(cursorData.get(), o.cursorData.get()) && + font == o.font && + color == o.color && + horizontal_border_spacing == o.horizontal_border_spacing && + vertical_border_spacing == o.vertical_border_spacing && + widows == o.widows && + orphans == o.orphans && + page_break_inside == o.page_break_inside; +} + +static inline bool operator!=(const CounterContent& a, const CounterContent& b) +{ + return a.identifier() != b.identifier() + || a.listStyle() != b.listStyle() + || a.separator() != b.separator(); +} + +// ---------------------------------------------------------- + +void* RenderStyle::operator new(size_t sz, RenderArena* renderArena) throw() +{ + return renderArena->allocate(sz); +} + +void RenderStyle::operator delete(void* ptr, size_t sz) +{ + // Stash size where destroy can find it. + *(size_t *)ptr = sz; +} + +void RenderStyle::arenaDelete(RenderArena *arena) +{ + RenderStyle *ps = pseudoStyle; + RenderStyle *prev = 0; + + while (ps) { + prev = ps; + ps = ps->pseudoStyle; + // to prevent a double deletion. + // this works only because the styles below aren't really shared + // Dirk said we need another construct as soon as these are shared + prev->pseudoStyle = 0; + prev->deref(arena); + } + delete this; + + // Recover the size left there for us by operator delete and free the memory. + arena->free(*(size_t *)this, this); +} + +inline RenderStyle *initDefaultStyle() +{ + if (!defaultStyle) + defaultStyle = ::new RenderStyle(true); + return defaultStyle; +} + +RenderStyle::RenderStyle() + : box(initDefaultStyle()->box) + , visual(defaultStyle->visual) + , background(defaultStyle->background) + , surround(defaultStyle->surround) + , rareNonInheritedData(defaultStyle->rareNonInheritedData) + , rareInheritedData(defaultStyle->rareInheritedData) + , inherited(defaultStyle->inherited) + , pseudoStyle(0) + , m_pseudoState(PseudoUnknown) + , m_affectedByAttributeSelectors(false) + , m_unique(false) + , m_affectedByEmpty(false) + , m_emptyState(false) + , m_childrenAffectedByFirstChildRules(false) + , m_childrenAffectedByLastChildRules(false) + , m_childrenAffectedByDirectAdjacentRules(false) + , m_childrenAffectedByForwardPositionalRules(false) + , m_childrenAffectedByBackwardPositionalRules(false) + , m_firstChildState(false) + , m_lastChildState(false) + , m_childIndex(0) + , m_ref(0) +#if ENABLE(SVG) + , m_svgStyle(defaultStyle->m_svgStyle) +#endif +{ + setBitDefaults(); // Would it be faster to copy this from the default style? +} + +RenderStyle::RenderStyle(bool) + : pseudoStyle(0) + , m_pseudoState(PseudoUnknown) + , m_affectedByAttributeSelectors(false) + , m_unique(false) + , m_affectedByEmpty(false) + , m_emptyState(false) + , m_childrenAffectedByFirstChildRules(false) + , m_childrenAffectedByLastChildRules(false) + , m_childrenAffectedByDirectAdjacentRules(false) + , m_childrenAffectedByForwardPositionalRules(false) + , m_childrenAffectedByBackwardPositionalRules(false) + , m_firstChildState(false) + , m_lastChildState(false) + , m_childIndex(0) + , m_ref(1) +{ + setBitDefaults(); + + box.init(); + visual.init(); + background.init(); + surround.init(); + rareNonInheritedData.init(); + rareNonInheritedData.access()->flexibleBox.init(); + rareNonInheritedData.access()->marquee.init(); + rareNonInheritedData.access()->m_multiCol.init(); + rareNonInheritedData.access()->m_transform.init(); + rareInheritedData.init(); + inherited.init(); + +#if ENABLE(SVG) + m_svgStyle.init(); +#endif +} + +RenderStyle::RenderStyle(const RenderStyle& o) + : inherited_flags(o.inherited_flags) + , noninherited_flags(o.noninherited_flags) + , box(o.box) + , visual(o.visual) + , background(o.background) + , surround(o.surround) + , rareNonInheritedData(o.rareNonInheritedData) + , rareInheritedData(o.rareInheritedData) + , inherited(o.inherited) + , pseudoStyle(0) + , m_pseudoState(o.m_pseudoState) + , m_affectedByAttributeSelectors(false) + , m_unique(false) + , m_affectedByEmpty(false) + , m_emptyState(false) + , m_childrenAffectedByFirstChildRules(false) + , m_childrenAffectedByLastChildRules(false) + , m_childrenAffectedByDirectAdjacentRules(false) + , m_childrenAffectedByForwardPositionalRules(false) + , m_childrenAffectedByBackwardPositionalRules(false) + , m_firstChildState(false) + , m_lastChildState(false) + , m_childIndex(0) + , m_ref(0) +#if ENABLE(SVG) + , m_svgStyle(o.m_svgStyle) +#endif +{ +} + +void RenderStyle::inheritFrom(const RenderStyle* inheritParent) +{ + rareInheritedData = inheritParent->rareInheritedData; + inherited = inheritParent->inherited; + inherited_flags = inheritParent->inherited_flags; +#if ENABLE(SVG) + if (m_svgStyle != inheritParent->m_svgStyle) + m_svgStyle.access()->inheritFrom(inheritParent->m_svgStyle.get()); +#endif +} + +RenderStyle::~RenderStyle() +{ +} + +bool RenderStyle::operator==(const RenderStyle& o) const +{ + // compare everything except the pseudoStyle pointer + return inherited_flags == o.inherited_flags && + noninherited_flags == o.noninherited_flags && + box == o.box && + visual == o.visual && + background == o.background && + surround == o.surround && + rareNonInheritedData == o.rareNonInheritedData && + rareInheritedData == o.rareInheritedData && + inherited == o.inherited +#if ENABLE(SVG) + && m_svgStyle == o.m_svgStyle +#endif + ; +} + +bool RenderStyle::isStyleAvailable() const +{ + return this != CSSStyleSelector::m_styleNotYetAvailable; +} + +static inline int pseudoBit(RenderStyle::PseudoId pseudo) +{ + return 1 << (pseudo - 1); +} + +bool RenderStyle::hasPseudoStyle(PseudoId pseudo) const +{ + ASSERT(pseudo > NOPSEUDO); + ASSERT(pseudo < FIRST_INTERNAL_PSEUDOID); + return pseudoBit(pseudo) & noninherited_flags._pseudoBits; +} + +void RenderStyle::setHasPseudoStyle(PseudoId pseudo) +{ + ASSERT(pseudo > NOPSEUDO); + ASSERT(pseudo < FIRST_INTERNAL_PSEUDOID); + noninherited_flags._pseudoBits |= pseudoBit(pseudo); +} + +RenderStyle* RenderStyle::getPseudoStyle(PseudoId pid) +{ + if (!pseudoStyle || styleType() != NOPSEUDO) + return 0; + RenderStyle* ps = pseudoStyle; + while (ps && ps->styleType() != pid) + ps = ps->pseudoStyle; + return ps; +} + +void RenderStyle::addPseudoStyle(RenderStyle* pseudo) +{ + if (!pseudo) + return; + pseudo->ref(); + pseudo->pseudoStyle = pseudoStyle; + pseudoStyle = pseudo; +} + +bool RenderStyle::inheritedNotEqual(RenderStyle* other) const +{ + return inherited_flags != other->inherited_flags || + inherited != other->inherited || +#if ENABLE(SVG) + m_svgStyle->inheritedNotEqual(other->m_svgStyle.get()) || +#endif + rareInheritedData != other->rareInheritedData; +} + +/* + compares two styles. The result gives an idea of the action that + needs to be taken when replacing the old style with a new one. + + CbLayout: The containing block of the object needs a relayout. + Layout: the RenderObject needs a relayout after the style change + Visible: The change is visible, but no relayout is needed + NonVisible: The object does need neither repaint nor relayout after + the change. + + ### TODO: + A lot can be optimised here based on the display type, lots of + optimisations are unimplemented, and currently result in the + worst case result causing a relayout of the containing block. +*/ +RenderStyle::Diff RenderStyle::diff(const RenderStyle* other) const +{ +#if ENABLE(SVG) + // This is horribly inefficient. Eventually we'll have to integrate + // this more directly by calling: Diff svgDiff = svgStyle->diff(other) + // and then checking svgDiff and returning from the appropriate places below. + if (m_svgStyle != other->m_svgStyle) + return Layout; +#endif + + if (box->width != other->box->width || + box->min_width != other->box->min_width || + box->max_width != other->box->max_width || + box->height != other->box->height || + box->min_height != other->box->min_height || + box->max_height != other->box->max_height) + return Layout; + + if (box->vertical_align != other->box->vertical_align || noninherited_flags._vertical_align != other->noninherited_flags._vertical_align) + return Layout; + + if (box->boxSizing != other->box->boxSizing) + return Layout; + + if (surround->margin != other->surround->margin) + return Layout; + + if (surround->padding != other->surround->padding) + return Layout; + + if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) { + if (rareNonInheritedData->m_appearance != other->rareNonInheritedData->m_appearance || + rareNonInheritedData->marginTopCollapse != other->rareNonInheritedData->marginTopCollapse || + rareNonInheritedData->marginBottomCollapse != other->rareNonInheritedData->marginBottomCollapse || + rareNonInheritedData->lineClamp != other->rareNonInheritedData->lineClamp || + rareNonInheritedData->textOverflow != other->rareNonInheritedData->textOverflow) + return Layout; + + if (rareNonInheritedData->flexibleBox.get() != other->rareNonInheritedData->flexibleBox.get() && + *rareNonInheritedData->flexibleBox.get() != *other->rareNonInheritedData->flexibleBox.get()) + return Layout; + + if (!rareNonInheritedData->shadowDataEquivalent(*other->rareNonInheritedData.get())) + return Layout; + + if (rareNonInheritedData->m_multiCol.get() != other->rareNonInheritedData->m_multiCol.get() && + *rareNonInheritedData->m_multiCol.get() != *other->rareNonInheritedData->m_multiCol.get()) + return Layout; + + if (rareNonInheritedData->m_transform.get() != other->rareNonInheritedData->m_transform.get() && + *rareNonInheritedData->m_transform.get() != *other->rareNonInheritedData->m_transform.get()) + return Layout; + + // If regions change, trigger a relayout to re-calc regions. + if (rareNonInheritedData->m_dashboardRegions != other->rareNonInheritedData->m_dashboardRegions) + return Layout; + } + + if (rareInheritedData.get() != other->rareInheritedData.get()) { + if (rareInheritedData->highlight != other->rareInheritedData->highlight || + rareInheritedData->textSizeAdjust != other->rareInheritedData->textSizeAdjust || + rareInheritedData->wordBreak != other->rareInheritedData->wordBreak || + rareInheritedData->wordWrap != other->rareInheritedData->wordWrap || + rareInheritedData->nbspMode != other->rareInheritedData->nbspMode || + rareInheritedData->khtmlLineBreak != other->rareInheritedData->khtmlLineBreak || + rareInheritedData->textSecurity != other->rareInheritedData->textSecurity) + return Layout; + + if (!rareInheritedData->shadowDataEquivalent(*other->rareInheritedData.get())) + return Layout; + + if (textStrokeWidth() != other->textStrokeWidth()) + return Layout; + } + + if (inherited->indent != other->inherited->indent || + inherited->line_height != other->inherited->line_height || + inherited->style_image != other->inherited->style_image || + inherited->font != other->inherited->font || + inherited->horizontal_border_spacing != other->inherited->horizontal_border_spacing || + inherited->vertical_border_spacing != other->inherited->vertical_border_spacing || + inherited_flags._box_direction != other->inherited_flags._box_direction || + inherited_flags._visuallyOrdered != other->inherited_flags._visuallyOrdered || + inherited_flags._htmlHacks != other->inherited_flags._htmlHacks || + noninherited_flags._position != other->noninherited_flags._position || + noninherited_flags._floating != other->noninherited_flags._floating || + noninherited_flags._originalDisplay != other->noninherited_flags._originalDisplay) + return Layout; + + + if (((int)noninherited_flags._effectiveDisplay) >= TABLE) { + if (inherited_flags._border_collapse != other->inherited_flags._border_collapse || + inherited_flags._empty_cells != other->inherited_flags._empty_cells || + inherited_flags._caption_side != other->inherited_flags._caption_side || + noninherited_flags._table_layout != other->noninherited_flags._table_layout) + return Layout; + + // In the collapsing border model, 'hidden' suppresses other borders, while 'none' + // does not, so these style differences can be width differences. + if (inherited_flags._border_collapse && + (borderTopStyle() == BHIDDEN && other->borderTopStyle() == BNONE || + borderTopStyle() == BNONE && other->borderTopStyle() == BHIDDEN || + borderBottomStyle() == BHIDDEN && other->borderBottomStyle() == BNONE || + borderBottomStyle() == BNONE && other->borderBottomStyle() == BHIDDEN || + borderLeftStyle() == BHIDDEN && other->borderLeftStyle() == BNONE || + borderLeftStyle() == BNONE && other->borderLeftStyle() == BHIDDEN || + borderRightStyle() == BHIDDEN && other->borderRightStyle() == BNONE || + borderRightStyle() == BNONE && other->borderRightStyle() == BHIDDEN)) + return Layout; + } + + if (noninherited_flags._effectiveDisplay == LIST_ITEM) { + if (inherited_flags._list_style_type != other->inherited_flags._list_style_type || + inherited_flags._list_style_position != other->inherited_flags._list_style_position) + return Layout; + } + + if (inherited_flags._text_align != other->inherited_flags._text_align || + inherited_flags._text_transform != other->inherited_flags._text_transform || + inherited_flags._direction != other->inherited_flags._direction || + inherited_flags._white_space != other->inherited_flags._white_space || + noninherited_flags._clear != other->noninherited_flags._clear) + return Layout; + + // Overflow returns a layout hint. + if (noninherited_flags._overflowX != other->noninherited_flags._overflowX || + noninherited_flags._overflowY != other->noninherited_flags._overflowY) + return Layout; + + // If our border widths change, then we need to layout. Other changes to borders + // only necessitate a repaint. + if (borderLeftWidth() != other->borderLeftWidth() || + borderTopWidth() != other->borderTopWidth() || + borderBottomWidth() != other->borderBottomWidth() || + borderRightWidth() != other->borderRightWidth()) + return Layout; + + // If the counter directives change, trigger a relayout to re-calculate counter values and rebuild the counter node tree. + const CounterDirectiveMap* mapA = rareNonInheritedData->m_counterDirectives; + const CounterDirectiveMap* mapB = other->rareNonInheritedData->m_counterDirectives; + if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB))) + return Layout; + if (visual->counterIncrement != other->visual->counterIncrement || + visual->counterReset != other->visual->counterReset) + return Layout; + + // Make sure these left/top/right/bottom checks stay below all layout checks and above + // all visible checks. + if (other->position() != StaticPosition) { + if (surround->offset != other->surround->offset) { + // FIXME: We will need to do a bit of work in RenderObject/Box::setStyle before we + // can stop doing a layout when relative positioned objects move. In particular, we'll need + // to update scrolling positions and figure out how to do a repaint properly of the updated layer. + //if (other->position() == RelativePosition) + // return RepaintLayer; + //else + return Layout; + } + else if (box->z_index != other->box->z_index || box->z_auto != other->box->z_auto || + visual->clip != other->visual->clip || visual->hasClip != other->visual->hasClip) + return RepaintLayer; + } + + if (rareNonInheritedData->opacity != other->rareNonInheritedData->opacity) + return RepaintLayer; + + if (inherited->color != other->inherited->color || + inherited_flags._visibility != other->inherited_flags._visibility || + inherited_flags._text_decorations != other->inherited_flags._text_decorations || + inherited_flags._force_backgrounds_to_white != other->inherited_flags._force_backgrounds_to_white || + surround->border != other->surround->border || + *background.get() != *other->background.get() || + visual->textDecoration != other->visual->textDecoration || + rareInheritedData->userModify != other->rareInheritedData->userModify || + rareInheritedData->userSelect != other->rareInheritedData->userSelect || + rareNonInheritedData->userDrag != other->rareNonInheritedData->userDrag || + rareNonInheritedData->m_borderFit != other->rareNonInheritedData->m_borderFit || + rareInheritedData->textFillColor != other->rareInheritedData->textFillColor || + rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor) + return Repaint; + + // Cursors are not checked, since they will be set appropriately in response to mouse events, + // so they don't need to cause any repaint or layout. + + // Transitions don't need to be checked either. We always set the new style on the RenderObject, so we will get a chance to fire off + // the resulting transition properly. + return Equal; +} + +void RenderStyle::adjustBackgroundLayers() +{ + if (backgroundLayers()->next()) { + // First we cull out layers that have no properties set. + accessBackgroundLayers()->cullEmptyLayers(); + + // Next we repeat patterns into layers that don't have some properties set. + accessBackgroundLayers()->fillUnsetProperties(); + } +} + +void RenderStyle::setClip( Length top, Length right, Length bottom, Length left ) +{ + StyleVisualData *data = visual.access(); + data->clip.top = top; + data->clip.right = right; + data->clip.bottom = bottom; + data->clip.left = left; +} + +void RenderStyle::addCursor(CachedImage* image, const IntPoint& hotSpot) +{ + CursorData data; + data.cursorImage = image; + data.hotSpot = hotSpot; + if (!inherited.access()->cursorData) + inherited.access()->cursorData = new CursorList; + inherited.access()->cursorData->append(data); +} + +void RenderStyle::setCursorList(PassRefPtr<CursorList> other) +{ + inherited.access()->cursorData = other; +} + +void RenderStyle::clearCursorList() +{ + inherited.access()->cursorData = new CursorList; +} + +bool RenderStyle::contentDataEquivalent(const RenderStyle* otherStyle) const +{ + ContentData* c1 = rareNonInheritedData->m_content; + ContentData* c2 = otherStyle->rareNonInheritedData->m_content; + + while (c1 && c2) { + if (c1->m_type != c2->m_type) + return false; + + switch (c1->m_type) { + case CONTENT_NONE: + break; + case CONTENT_TEXT: + if (!equal(c1->m_content.m_text, c2->m_content.m_text)) + return false; + break; + case CONTENT_OBJECT: + if (c1->m_content.m_object != c2->m_content.m_object) + return false; + break; + case CONTENT_COUNTER: + if (*c1->m_content.m_counter != *c2->m_content.m_counter) + return false; + break; + } + + c1 = c1->m_next; + c2 = c2->m_next; + } + + return !c1 && !c2; +} + +void RenderStyle::clearContent() +{ + if (rareNonInheritedData->m_content) + rareNonInheritedData->m_content->clear(); +} + +void RenderStyle::setContent(CachedResource* o, bool add) +{ + if (!o) + return; // The object is null. Nothing to do. Just bail. + + ContentData*& content = rareNonInheritedData.access()->m_content; + ContentData* lastContent = content; + while (lastContent && lastContent->m_next) + lastContent = lastContent->m_next; + + bool reuseContent = !add; + ContentData* newContentData = 0; + if (reuseContent && content) { + content->clear(); + newContentData = content; + } else + newContentData = new ContentData; + + if (lastContent && !reuseContent) + lastContent->m_next = newContentData; + else + content = newContentData; + + newContentData->m_content.m_object = o; + newContentData->m_type = CONTENT_OBJECT; +} + +void RenderStyle::setContent(StringImpl* s, bool add) +{ + if (!s) + return; // The string is null. Nothing to do. Just bail. + + ContentData*& content = rareNonInheritedData.access()->m_content; + ContentData* lastContent = content; + while (lastContent && lastContent->m_next) + lastContent = lastContent->m_next; + + bool reuseContent = !add; + if (add && lastContent) { + if (lastContent->m_type == CONTENT_TEXT) { + // We can augment the existing string and share this ContentData node. + StringImpl* oldStr = lastContent->m_content.m_text; + String newStr = oldStr; + newStr.append(s); + newStr.impl()->ref(); + oldStr->deref(); + lastContent->m_content.m_text = newStr.impl(); + return; + } + } + + ContentData* newContentData = 0; + if (reuseContent && content) { + content->clear(); + newContentData = content; + } else + newContentData = new ContentData; + + if (lastContent && !reuseContent) + lastContent->m_next = newContentData; + else + content = newContentData; + + newContentData->m_content.m_text = s; + newContentData->m_content.m_text->ref(); + newContentData->m_type = CONTENT_TEXT; +} + +void RenderStyle::setContent(CounterContent* c, bool add) +{ + if (!c) + return; + + ContentData*& content = rareNonInheritedData.access()->m_content; + ContentData* lastContent = content; + while (lastContent && lastContent->m_next) + lastContent = lastContent->m_next; + + bool reuseContent = !add; + ContentData* newContentData = 0; + if (reuseContent && content) { + content->clear(); + newContentData = content; + } else + newContentData = new ContentData; + + if (lastContent && !reuseContent) + lastContent->m_next = newContentData; + else + content = newContentData; + + newContentData->m_content.m_counter = c; + newContentData->m_type = CONTENT_COUNTER; +} + +void ContentData::clear() +{ + switch (m_type) { + case CONTENT_NONE: + case CONTENT_OBJECT: + break; + case CONTENT_TEXT: + m_content.m_text->deref(); + break; + case CONTENT_COUNTER: + delete m_content.m_counter; + break; + } + + ContentData* n = m_next; + m_type = CONTENT_NONE; + m_next = 0; + + // Reverse the list so we can delete without recursing. + ContentData* last = 0; + ContentData* c; + while ((c = n)) { + n = c->m_next; + c->m_next = last; + last = c; + } + for (c = last; c; c = n) { + n = c->m_next; + c->m_next = 0; + delete c; + } +} + +void RenderStyle::applyTransform(AffineTransform& transform, const IntSize& borderBoxSize) const +{ + // transform-origin brackets the transform with translate operations. + // Optimize for the case where the only transform is a translation, since the transform-origin is irrelevant + // in that case. + bool applyTransformOrigin = false; + unsigned s = rareNonInheritedData->m_transform->m_operations.size(); + unsigned i; + for (i = 0; i < s; i++) { + if (!rareNonInheritedData->m_transform->m_operations[i]->isTranslateOperation()) { + applyTransformOrigin = true; + break; + } + } + + if (applyTransformOrigin) + transform.translate(transformOriginX().calcValue(borderBoxSize.width()), transformOriginY().calcValue(borderBoxSize.height())); + + for (i = 0; i < s; i++) + rareNonInheritedData->m_transform->m_operations[i]->apply(transform, borderBoxSize); + + if (applyTransformOrigin) + transform.translate(-transformOriginX().calcValue(borderBoxSize.width()), -transformOriginY().calcValue(borderBoxSize.height())); +} + +#if ENABLE(XBL) +BindingURI::BindingURI(StringImpl* uri) +:m_next(0) +{ + m_uri = uri; + if (uri) uri->ref(); +} + +BindingURI::~BindingURI() +{ + if (m_uri) + m_uri->deref(); + delete m_next; +} + +BindingURI* BindingURI::copy() +{ + BindingURI* newBinding = new BindingURI(m_uri); + if (next()) { + BindingURI* nextCopy = next()->copy(); + newBinding->setNext(nextCopy); + } + + return newBinding; +} + +bool BindingURI::operator==(const BindingURI& o) const +{ + if ((m_next && !o.m_next) || (!m_next && o.m_next) || + (m_next && o.m_next && *m_next != *o.m_next)) + return false; + + if (m_uri == o.m_uri) + return true; + if (!m_uri || !o.m_uri) + return false; + + return String(m_uri) == String(o.m_uri); +} + +void RenderStyle::addBindingURI(StringImpl* uri) +{ + BindingURI* binding = new BindingURI(uri); + if (!bindingURIs()) + SET_VAR(rareNonInheritedData, bindingURI, binding) + else + for (BindingURI* b = bindingURIs(); b; b = b->next()) { + if (!b->next()) + b->setNext(binding); + } +} +#endif + +void RenderStyle::setTextShadow(ShadowData* val, bool add) +{ + StyleRareInheritedData* rareData = rareInheritedData.access(); + if (!add) { + delete rareData->textShadow; + rareData->textShadow = val; + return; + } + + ShadowData* last = rareData->textShadow; + while (last->next) last = last->next; + last->next = val; +} + +void RenderStyle::setBoxShadow(ShadowData* val, bool add) +{ + StyleRareNonInheritedData* rareData = rareNonInheritedData.access(); + if (!add) { + delete rareData->m_boxShadow; + rareData->m_boxShadow = val; + return; + } + + ShadowData* last = rareData->m_boxShadow; + while (last->next) last = last->next; + last->next = val; +} + +ShadowData::ShadowData(const ShadowData& o) +:x(o.x), y(o.y), blur(o.blur), color(o.color) +{ + next = o.next ? new ShadowData(*o.next) : 0; +} + +bool ShadowData::operator==(const ShadowData& o) const +{ + if ((next && !o.next) || (!next && o.next) || + (next && o.next && *next != *o.next)) + return false; + + return x == o.x && y == o.y && blur == o.blur && color == o.color; +} + +bool operator==(const CounterDirectives& a, const CounterDirectives& b) +{ + if (a.m_reset != b.m_reset || a.m_increment != b.m_increment) + return false; + if (a.m_reset && a.m_resetValue != b.m_resetValue) + return false; + if (a.m_increment && a.m_incrementValue != b.m_incrementValue) + return false; + return true; +} + +const CounterDirectiveMap* RenderStyle::counterDirectives() const +{ + return rareNonInheritedData->m_counterDirectives; +} + +CounterDirectiveMap& RenderStyle::accessCounterDirectives() +{ + CounterDirectiveMap*& map = rareNonInheritedData.access()->m_counterDirectives; + if (!map) + map = new CounterDirectiveMap; + return *map; +} + +const Vector<StyleDashboardRegion>& RenderStyle::initialDashboardRegions() +{ + static Vector<StyleDashboardRegion> emptyList; + return emptyList; +} + +const Vector<StyleDashboardRegion>& RenderStyle::noneDashboardRegions() +{ + static Vector<StyleDashboardRegion> noneList; + static bool noneListInitialized = false; + + if (!noneListInitialized) { + StyleDashboardRegion region; + region.label = ""; + region.offset.top = Length(); + region.offset.right = Length(); + region.offset.bottom = Length(); + region.offset.left = Length(); + region.type = StyleDashboardRegion::None; + noneList.append (region); + noneListInitialized = true; + } + return noneList; +} + +void RenderStyle::adjustTransitions() +{ + if (transitions()) { + if (transitions()->isEmpty()) { + clearTransitions(); + return; + } + + Transition* next; + for (Transition* p = accessTransitions(); p; p = next) { + next = p->m_next; + if (next && next->isEmpty()) { + delete next; + p->m_next = 0; + break; + } + } + + // Repeat patterns into layers that don't have some properties set. + accessTransitions()->fillUnsetProperties(); + } +} + +Transition* RenderStyle::accessTransitions() +{ + Transition* layer = rareNonInheritedData.access()->m_transition; + if (!layer) + rareNonInheritedData.access()->m_transition = new Transition(); + return rareNonInheritedData->m_transition; +} + +} |