| /* |
| * 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_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_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_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::addSVGCursor(const String& fragmentId) |
| { |
| CursorData data; |
| data.cursorFragmentId = fragmentId; |
| 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; |
| } |
| |
| } |