RenderStyle.cpp 75.2 KB
Newer Older
kocienda's avatar
kocienda committed
1 2
/*
 * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
3
 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
4
 * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
kocienda's avatar
kocienda committed
5 6 7 8 9 10 11 12 13 14 15 16 17
 *
 * 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
ddkilzer's avatar
ddkilzer committed
18 19
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
kocienda's avatar
kocienda committed
20 21 22
 *
 */

mjs's avatar
mjs committed
23
#include "config.h"
darin's avatar
darin committed
24
#include "RenderStyle.h"
kocienda's avatar
kocienda committed
25

26 27
#include "ContentData.h"
#include "CursorList.h"
28
#include "CSSPropertyNames.h"
29
#include "Font.h"
30
#include "FontSelector.h"
31
#include "Pagination.h"
32
#include "QuotesData.h"
33
#include "RenderObject.h"
34
#include "ScaleTransformOperation.h"
35
#include "ShadowData.h"
36
#include "StyleImage.h"
37
#include "StyleInheritedData.h"
38
#include "StyleResolver.h"
39 40 41
#if ENABLE(TOUCH_EVENTS)
#include "RenderTheme.h"
#endif
42
#include <wtf/MathExtras.h>
43
#include <wtf/StdLibExtras.h>
44
#include <algorithm>
eseidel's avatar
eseidel committed
45

46 47 48 49
#if ENABLE(IOS_TEXT_AUTOSIZING)
#include <wtf/text/StringHash.h>
#endif

50 51 52 53
#if ENABLE(TEXT_AUTOSIZING)
#include "TextAutosizer.h"
#endif

darin's avatar
darin committed
54
namespace WebCore {
darin's avatar
darin committed
55

56
struct SameSizeAsBorderValue {
kling@webkit.org's avatar
kling@webkit.org committed
57
    RGBA32 m_color;
58 59 60 61 62
    unsigned m_width;
};

COMPILE_ASSERT(sizeof(BorderValue) == sizeof(SameSizeAsBorderValue), BorderValue_should_not_grow);

63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
struct SameSizeAsRenderStyle : public RefCounted<SameSizeAsRenderStyle> {
    void* dataRefs[7];
    void* ownPtrs[1];
#if ENABLE(SVG)
    void* dataRefSvgStyle;
#endif
    struct InheritedFlags {
        unsigned m_bitfields[2];
    } inherited_flags;

    struct NonInheritedFlags {
        unsigned m_bitfields[2];
    } noninherited_flags;
};

COMPILE_ASSERT(sizeof(RenderStyle) == sizeof(SameSizeAsRenderStyle), RenderStyle_should_stay_small);

80
inline RenderStyle& defaultStyle()
81
{
82 83
    static RenderStyle& style = RenderStyle::createDefaultStyle().leakRef();
    return style;
84 85
}

86
PassRef<RenderStyle> RenderStyle::create()
87
{
88
    return adoptRef(*new RenderStyle());
89 90
}

91
PassRef<RenderStyle> RenderStyle::createDefaultStyle()
92
{
93
    return adoptRef(*new RenderStyle(true));
94 95
}

96
PassRef<RenderStyle> RenderStyle::createAnonymousStyleWithDisplay(const RenderStyle* parentStyle, EDisplay display)
97
{
98 99 100 101
    auto newStyle = RenderStyle::create();
    newStyle.get().inheritFrom(parentStyle);
    newStyle.get().inheritUnicodeBidiFrom(parentStyle);
    newStyle.get().setDisplay(display);
102 103 104
    return newStyle;
}

105
PassRef<RenderStyle> RenderStyle::clone(const RenderStyle* other)
kocienda's avatar
kocienda committed
106
{
107
    return adoptRef(*new RenderStyle(*other));
darin's avatar
darin committed
108
}
kocienda's avatar
kocienda committed
109

110
ALWAYS_INLINE RenderStyle::RenderStyle()
111 112 113 114 115 116 117
    : m_box(defaultStyle().m_box)
    , visual(defaultStyle().visual)
    , m_background(defaultStyle().m_background)
    , surround(defaultStyle().surround)
    , rareNonInheritedData(defaultStyle().rareNonInheritedData)
    , rareInheritedData(defaultStyle().rareInheritedData)
    , inherited(defaultStyle().inherited)
mjs's avatar
mjs committed
118
#if ENABLE(SVG)
119
    , m_svgStyle(defaultStyle().m_svgStyle)
eseidel's avatar
eseidel committed
120
#endif
darin's avatar
darin committed
121 122
{
    setBitDefaults(); // Would it be faster to copy this from the default style?
123 124
    COMPILE_ASSERT((sizeof(InheritedFlags) <= 8), InheritedFlags_does_not_grow);
    COMPILE_ASSERT((sizeof(NonInheritedFlags) <= 8), NonInheritedFlags_does_not_grow);
kocienda's avatar
kocienda committed
125 126
}

127
ALWAYS_INLINE RenderStyle::RenderStyle(bool)
128 129 130 131 132 133 134
    : m_box(StyleBoxData::create())
    , visual(StyleVisualData::create())
    , m_background(StyleBackgroundData::create())
    , surround(StyleSurroundData::create())
    , rareNonInheritedData(StyleRareNonInheritedData::create())
    , rareInheritedData(StyleRareInheritedData::create())
    , inherited(StyleInheritedData::create())
135
#if ENABLE(SVG)
136
    , m_svgStyle(SVGRenderStyle::create())
137
#endif
kocienda's avatar
kocienda committed
138 139 140 141
{
    setBitDefaults();
}

142
ALWAYS_INLINE RenderStyle::RenderStyle(const RenderStyle& o)
143
    : RefCounted<RenderStyle>()
144
    , m_box(o.m_box)
145
    , visual(o.visual)
146
    , m_background(o.m_background)
147 148 149 150
    , surround(o.surround)
    , rareNonInheritedData(o.rareNonInheritedData)
    , rareInheritedData(o.rareInheritedData)
    , inherited(o.inherited)
mjs's avatar
mjs committed
151
#if ENABLE(SVG)
darin's avatar
darin committed
152
    , m_svgStyle(o.m_svgStyle)
eseidel's avatar
eseidel committed
153
#endif
154 155
    , inherited_flags(o.inherited_flags)
    , noninherited_flags(o.noninherited_flags)
darin's avatar
darin committed
156
{
kocienda's avatar
kocienda committed
157 158
}

159
void RenderStyle::inheritFrom(const RenderStyle* inheritParent, IsAtShadowBoundary isAtShadowBoundary)
kocienda's avatar
kocienda committed
160
{
161 162 163 164 165 166 167
    if (isAtShadowBoundary == AtShadowBoundary) {
        // Even if surrounding content is user-editable, shadow DOM should act as a single unit, and not necessarily be editable
        EUserModify currentUserModify = userModify();
        rareInheritedData = inheritParent->rareInheritedData;
        setUserModify(currentUserModify);
    } else
        rareInheritedData = inheritParent->rareInheritedData;
kocienda's avatar
kocienda committed
168
    inherited = inheritParent->inherited;
169
    inherited_flags = inheritParent->inherited_flags;
mjs's avatar
mjs committed
170
#if ENABLE(SVG)
eseidel's avatar
eseidel committed
171 172
    if (m_svgStyle != inheritParent->m_svgStyle)
        m_svgStyle.access()->inheritFrom(inheritParent->m_svgStyle.get());
eseidel's avatar
eseidel committed
173
#endif
kocienda's avatar
kocienda committed
174 175
}

antti@apple.com's avatar
antti@apple.com committed
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
void RenderStyle::copyNonInheritedFrom(const RenderStyle* other)
{
    m_box = other->m_box;
    visual = other->visual;
    m_background = other->m_background;
    surround = other->surround;
    rareNonInheritedData = other->rareNonInheritedData;
    // The flags are copied one-by-one because noninherited_flags contains a bunch of stuff other than real style data.
    noninherited_flags._effectiveDisplay = other->noninherited_flags._effectiveDisplay;
    noninherited_flags._originalDisplay = other->noninherited_flags._originalDisplay;
    noninherited_flags._overflowX = other->noninherited_flags._overflowX;
    noninherited_flags._overflowY = other->noninherited_flags._overflowY;
    noninherited_flags._vertical_align = other->noninherited_flags._vertical_align;
    noninherited_flags._clear = other->noninherited_flags._clear;
    noninherited_flags._position = other->noninherited_flags._position;
    noninherited_flags._floating = other->noninherited_flags._floating;
    noninherited_flags._table_layout = other->noninherited_flags._table_layout;
193
    noninherited_flags._unicodeBidi = other->noninherited_flags._unicodeBidi;
antti@apple.com's avatar
antti@apple.com committed
194 195 196
    noninherited_flags._page_break_before = other->noninherited_flags._page_break_before;
    noninherited_flags._page_break_after = other->noninherited_flags._page_break_after;
    noninherited_flags._page_break_inside = other->noninherited_flags._page_break_inside;
197
    noninherited_flags.explicitInheritance = other->noninherited_flags.explicitInheritance;
antti@apple.com's avatar
antti@apple.com committed
198 199 200 201 202 203 204
#if ENABLE(SVG)
    if (m_svgStyle != other->m_svgStyle)
        m_svgStyle.access()->copyNonInheritedFrom(other->m_svgStyle.get());
#endif
    ASSERT(zoom() == initialZoom());
}

kocienda's avatar
kocienda committed
205 206
bool RenderStyle::operator==(const RenderStyle& o) const
{
darin's avatar
darin committed
207
    // compare everything except the pseudoStyle pointer
208 209 210 211 212 213 214 215 216
    return inherited_flags == o.inherited_flags
        && noninherited_flags == o.noninherited_flags
        && m_box == o.m_box
        && visual == o.visual
        && m_background == o.m_background
        && surround == o.surround
        && rareNonInheritedData == o.rareNonInheritedData
        && rareInheritedData == o.rareInheritedData
        && inherited == o.inherited
mjs's avatar
mjs committed
217
#if ENABLE(SVG)
218
        && m_svgStyle == o.m_svgStyle
eseidel's avatar
eseidel committed
219
#endif
darin's avatar
darin committed
220
            ;
221
}
kocienda's avatar
kocienda committed
222

223 224
bool RenderStyle::isStyleAvailable() const
{
225
    return this != StyleResolver::styleNotYetAvailable();
226 227
}

228 229 230 231 232 233 234 235 236 237 238 239 240 241
bool RenderStyle::hasUniquePseudoStyle() const
{
    if (!m_cachedPseudoStyles || styleType() != NOPSEUDO)
        return false;

    for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
        RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
        if (pseudoStyle->unique())
            return true;
    }

    return false;
}

242
RenderStyle* RenderStyle::getCachedPseudoStyle(PseudoId pid) const
kocienda's avatar
kocienda committed
243
{
244
    if (!m_cachedPseudoStyles || !m_cachedPseudoStyles->size())
245 246
        return 0;

247
    if (styleType() != NOPSEUDO) 
darin's avatar
darin committed
248
        return 0;
249

250 251 252 253 254 255 256
    for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
        RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
        if (pseudoStyle->styleType() == pid)
            return pseudoStyle;
    }

    return 0;
kocienda's avatar
kocienda committed
257 258
}

259
RenderStyle* RenderStyle::addCachedPseudoStyle(PassRefPtr<RenderStyle> pseudo)
kocienda's avatar
kocienda committed
260
{
darin's avatar
darin committed
261
    if (!pseudo)
262
        return 0;
263 264 265

    ASSERT(pseudo->styleType() > NOPSEUDO);

266
    RenderStyle* result = pseudo.get();
kocienda's avatar
kocienda committed
267

268
    if (!m_cachedPseudoStyles)
269
        m_cachedPseudoStyles = adoptPtr(new PseudoStyleCache);
270 271 272 273

    m_cachedPseudoStyles->append(pseudo);

    return result;
mitz@apple.com's avatar
mitz@apple.com committed
274 275
}

276 277 278 279 280 281 282 283 284 285 286 287 288
void RenderStyle::removeCachedPseudoStyle(PseudoId pid)
{
    if (!m_cachedPseudoStyles)
        return;
    for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
        RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
        if (pseudoStyle->styleType() == pid) {
            m_cachedPseudoStyles->remove(i);
            return;
        }
    }
}

289
bool RenderStyle::inheritedNotEqual(const RenderStyle* other) const
290
{
291 292
    return inherited_flags != other->inherited_flags
           || inherited != other->inherited
mjs's avatar
mjs committed
293
#if ENABLE(SVG)
294
           || m_svgStyle->inheritedNotEqual(other->m_svgStyle.get())
eseidel's avatar
eseidel committed
295
#endif
296
           || rareInheritedData != other->rareInheritedData;
297 298
}

299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
#if ENABLE(IOS_TEXT_AUTOSIZING)
inline unsigned computeFontHash(const Font& font)
{
    unsigned hashCodes[2] = {
        CaseFoldingHash::hash(font.fontDescription().firstFamily().impl()),
        static_cast<unsigned>(font.fontDescription().specifiedSize())
    };
    return StringHasher::computeHash(reinterpret_cast<UChar*>(hashCodes), 2 * sizeof(unsigned) / sizeof(UChar));
}

uint32_t RenderStyle::hashForTextAutosizing() const
{
    // FIXME: Not a very smart hash. Could be improved upon. See <https://bugs.webkit.org/show_bug.cgi?id=121131>.
    uint32_t hash = 0;
    
    hash ^= rareNonInheritedData->m_appearance;
    hash ^= rareNonInheritedData->marginBeforeCollapse;
    hash ^= rareNonInheritedData->marginAfterCollapse;
    hash ^= rareNonInheritedData->lineClamp.value();
    hash ^= rareInheritedData->overflowWrap;
    hash ^= rareInheritedData->nbspMode;
    hash ^= rareInheritedData->lineBreak;
    hash ^= WTF::FloatHash<float>::hash(inherited->specifiedLineHeight.value());
    hash ^= computeFontHash(inherited->font);
    hash ^= inherited->horizontal_border_spacing;
    hash ^= inherited->vertical_border_spacing;
    hash ^= inherited_flags._box_direction;
    hash ^= inherited_flags.m_rtlOrdering;
    hash ^= noninherited_flags._position;
    hash ^= noninherited_flags._floating;
    hash ^= rareNonInheritedData->textOverflow;
    hash ^= rareInheritedData->textSecurity;
    return hash;
}

bool RenderStyle::equalForTextAutosizing(const RenderStyle* other) const
{
    return rareNonInheritedData->m_appearance == other->rareNonInheritedData->m_appearance
        && rareNonInheritedData->marginBeforeCollapse == other->rareNonInheritedData->marginBeforeCollapse
        && rareNonInheritedData->marginAfterCollapse == other->rareNonInheritedData->marginAfterCollapse
        && rareNonInheritedData->lineClamp == other->rareNonInheritedData->lineClamp
        && rareInheritedData->textSizeAdjust == other->rareInheritedData->textSizeAdjust
        && rareInheritedData->overflowWrap == other->rareInheritedData->overflowWrap
        && rareInheritedData->nbspMode == other->rareInheritedData->nbspMode
        && rareInheritedData->lineBreak == other->rareInheritedData->lineBreak
        && rareInheritedData->textSecurity == other->rareInheritedData->textSecurity
        && inherited->specifiedLineHeight == other->inherited->specifiedLineHeight
        && inherited->font.equalForTextAutoSizing(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.m_rtlOrdering == other->inherited_flags.m_rtlOrdering
        && noninherited_flags._position == other->noninherited_flags._position
        && noninherited_flags._floating == other->noninherited_flags._floating
        && rareNonInheritedData->textOverflow == other->rareNonInheritedData->textOverflow;
}
#endif // ENABLE(IOS_TEXT_AUTOSIZING)

357 358 359 360 361 362 363 364 365 366 367
bool RenderStyle::inheritedDataShared(const RenderStyle* other) const
{
    // This is a fast check that only looks if the data structures are shared.
    return inherited_flags == other->inherited_flags
        && inherited.get() == other->inherited.get()
#if ENABLE(SVG)
        && m_svgStyle.get() == other->m_svgStyle.get()
#endif
        && rareInheritedData.get() == other->rareInheritedData.get();
}

368
static bool positionChangeIsMovementOnly(const LengthBox& a, const LengthBox& b, const Length& width)
369 370 371
{
    // If any unit types are different, then we can't guarantee
    // that this was just a movement.
372 373 374 375
    if (a.left().type() != b.left().type()
        || a.right().type() != b.right().type()
        || a.top().type() != b.top().type()
        || a.bottom().type() != b.bottom().type())
376
        return false;
377

378 379 380
    // Only one unit can be non-auto in the horizontal direction and
    // in the vertical direction.  Otherwise the adjustment of values
    // is changing the size of the box.
381
    if (!a.left().isIntrinsicOrAuto() && !a.right().isIntrinsicOrAuto())
382
        return false;
383
    if (!a.top().isIntrinsicOrAuto() && !a.bottom().isIntrinsicOrAuto())
384
        return false;
385 386 387 388
    // If our width is auto and left or right is specified then this 
    // is not just a movement - we need to resize to our container.
    if ((!a.left().isIntrinsicOrAuto() || !a.right().isIntrinsicOrAuto()) && width.isIntrinsicOrAuto())
        return false;
389

390 391 392 393 394
    // One of the units is fixed or percent in both directions and stayed
    // that way in the new style.  Therefore all we are doing is moving.
    return true;
}

395
bool RenderStyle::changeRequiresLayout(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
396
{
397 398 399 400 401 402
    if (m_box->width() != other->m_box->width()
        || m_box->minWidth() != other->m_box->minWidth()
        || m_box->maxWidth() != other->m_box->maxWidth()
        || m_box->height() != other->m_box->height()
        || m_box->minHeight() != other->m_box->minHeight()
        || m_box->maxHeight() != other->m_box->maxHeight())
403
        return true;
404

405
    if (m_box->verticalAlign() != other->m_box->verticalAlign() || noninherited_flags._vertical_align != other->noninherited_flags._vertical_align)
406
        return true;
407

408
    if (m_box->boxSizing() != other->m_box->boxSizing())
409
        return true;
410

411
    if (surround->margin != other->surround->margin)
412
        return true;
413

414
    if (surround->padding != other->surround->padding)
415
        return true;
416

417
    if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
418 419 420 421 422
        if (rareNonInheritedData->m_appearance != other->rareNonInheritedData->m_appearance 
            || rareNonInheritedData->marginBeforeCollapse != other->rareNonInheritedData->marginBeforeCollapse
            || rareNonInheritedData->marginAfterCollapse != other->rareNonInheritedData->marginAfterCollapse
            || rareNonInheritedData->lineClamp != other->rareNonInheritedData->lineClamp
            || rareNonInheritedData->textOverflow != other->rareNonInheritedData->textOverflow)
423
            return true;
424

425
        if (rareNonInheritedData->m_regionFragment != other->rareNonInheritedData->m_regionFragment)
426
            return true;
427

428
        if (rareNonInheritedData->m_wrapFlow != other->rareNonInheritedData->m_wrapFlow
429 430 431 432 433
            || rareNonInheritedData->m_wrapThrough != other->rareNonInheritedData->m_wrapThrough)
            return true;

#if ENABLE(CSS_SHAPES)
        if (rareNonInheritedData->m_shapeMargin != other->rareNonInheritedData->m_shapeMargin
434
            || rareNonInheritedData->m_shapePadding != other->rareNonInheritedData->m_shapePadding)
435
            return true;
436
#endif
437

438 439
        if (rareNonInheritedData->m_deprecatedFlexibleBox.get() != other->rareNonInheritedData->m_deprecatedFlexibleBox.get()
            && *rareNonInheritedData->m_deprecatedFlexibleBox.get() != *other->rareNonInheritedData->m_deprecatedFlexibleBox.get())
440
            return true;
441

442 443
        if (rareNonInheritedData->m_flexibleBox.get() != other->rareNonInheritedData->m_flexibleBox.get()
            && *rareNonInheritedData->m_flexibleBox.get() != *other->rareNonInheritedData->m_flexibleBox.get())
444
            return true;
445 446 447 448 449
        if (rareNonInheritedData->m_order != other->rareNonInheritedData->m_order
            || rareNonInheritedData->m_alignContent != other->rareNonInheritedData->m_alignContent
            || rareNonInheritedData->m_alignItems != other->rareNonInheritedData->m_alignItems
            || rareNonInheritedData->m_alignSelf != other->rareNonInheritedData->m_alignSelf
            || rareNonInheritedData->m_justifyContent != other->rareNonInheritedData->m_justifyContent)
450
            return true;
451

452
        // FIXME: We should add an optimized form of layout that just recomputes visual overflow.
453
        if (!rareNonInheritedData->shadowDataEquivalent(*other->rareNonInheritedData.get()))
454
            return true;
455

hyatt@apple.com's avatar
hyatt@apple.com committed
456
        if (!rareNonInheritedData->reflectionDataEquivalent(*other->rareNonInheritedData.get()))
457
            return true;
458

459 460
        if (rareNonInheritedData->m_multiCol.get() != other->rareNonInheritedData->m_multiCol.get()
            && *rareNonInheritedData->m_multiCol.get() != *other->rareNonInheritedData->m_multiCol.get())
461
            return true;
462

463 464
        if (rareNonInheritedData->m_transform.get() != other->rareNonInheritedData->m_transform.get()
            && *rareNonInheritedData->m_transform.get() != *other->rareNonInheritedData->m_transform.get()) {
465 466 467 468
#if USE(ACCELERATED_COMPOSITING)
            changedContextSensitiveProperties |= ContextSensitivePropertyTransform;
            // Don't return; keep looking for another change
#else
469
            UNUSED_PARAM(changedContextSensitiveProperties);
470
            return true;
471 472
#endif
        }
473

474
        if (rareNonInheritedData->m_grid.get() != other->rareNonInheritedData->m_grid.get()
475
            || rareNonInheritedData->m_gridItem.get() != other->rareNonInheritedData->m_gridItem.get())
476
            return true;
477

cmarrin@apple.com's avatar
cmarrin@apple.com committed
478 479
#if !USE(ACCELERATED_COMPOSITING)
        if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
480 481 482 483 484
            if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D
                || rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility
                || rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective
                || rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX
                || rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY)
485
                return true;
cmarrin@apple.com's avatar
cmarrin@apple.com committed
486 487 488
        }
#endif

489
#if ENABLE(DASHBOARD_SUPPORT)
490
        // If regions change, trigger a relayout to re-calc regions.
491
        if (rareNonInheritedData->m_dashboardRegions != other->rareNonInheritedData->m_dashboardRegions)
492
            return true;
ddkilzer@apple.com's avatar
ddkilzer@apple.com committed
493
#endif
494

495
#if ENABLE(CSS_SHAPES)
496
        if (rareNonInheritedData->m_shapeInside != other->rareNonInheritedData->m_shapeInside)
497
            return true;
498
#endif
499 500 501
    }

    if (rareInheritedData.get() != other->rareInheritedData.get()) {
502 503
        if (rareInheritedData->highlight != other->rareInheritedData->highlight
            || rareInheritedData->indent != other->rareInheritedData->indent
504
#if ENABLE(CSS3_TEXT)
505
            || rareInheritedData->m_textAlignLast != other->rareInheritedData->m_textAlignLast
506 507
            || rareInheritedData->m_textIndentLine != other->rareInheritedData->m_textIndentLine
#endif
508
            || rareInheritedData->m_effectiveZoom != other->rareInheritedData->m_effectiveZoom
509 510 511
#if ENABLE(IOS_TEXT_AUTOSIZING)
            || rareInheritedData->textSizeAdjust != other->rareInheritedData->textSizeAdjust
#endif
512
            || rareInheritedData->wordBreak != other->rareInheritedData->wordBreak
513
            || rareInheritedData->overflowWrap != other->rareInheritedData->overflowWrap
514
            || rareInheritedData->nbspMode != other->rareInheritedData->nbspMode
515
            || rareInheritedData->lineBreak != other->rareInheritedData->lineBreak
516 517 518 519 520 521
            || rareInheritedData->textSecurity != other->rareInheritedData->textSecurity
            || rareInheritedData->hyphens != other->rareInheritedData->hyphens
            || rareInheritedData->hyphenationLimitBefore != other->rareInheritedData->hyphenationLimitBefore
            || rareInheritedData->hyphenationLimitAfter != other->rareInheritedData->hyphenationLimitAfter
            || rareInheritedData->hyphenationString != other->rareInheritedData->hyphenationString
            || rareInheritedData->locale != other->rareInheritedData->locale
522
            || rareInheritedData->m_rubyPosition != other->rareInheritedData->m_rubyPosition
523 524 525
            || rareInheritedData->textEmphasisMark != other->rareInheritedData->textEmphasisMark
            || rareInheritedData->textEmphasisPosition != other->rareInheritedData->textEmphasisPosition
            || rareInheritedData->textEmphasisCustomMark != other->rareInheritedData->textEmphasisCustomMark
526
            || rareInheritedData->m_textOrientation != other->rareInheritedData->m_textOrientation
527
            || rareInheritedData->m_tabSize != other->rareInheritedData->m_tabSize
528 529
            || rareInheritedData->m_lineBoxContain != other->rareInheritedData->m_lineBoxContain
            || rareInheritedData->m_lineGrid != other->rareInheritedData->m_lineGrid
530 531 532
#if ENABLE(CSS_IMAGE_ORIENTATION)
            || rareInheritedData->m_imageOrientation != other->rareInheritedData->m_imageOrientation
#endif
533
#if ENABLE(CSS_IMAGE_RESOLUTION)
534
            || rareInheritedData->m_imageResolutionSource != other->rareInheritedData->m_imageResolutionSource
535
            || rareInheritedData->m_imageResolutionSnap != other->rareInheritedData->m_imageResolutionSnap
536 537
            || rareInheritedData->m_imageResolution != other->rareInheritedData->m_imageResolution
#endif
538
            || rareInheritedData->m_lineSnap != other->rareInheritedData->m_lineSnap
539
            || rareInheritedData->m_lineAlign != other->rareInheritedData->m_lineAlign
540 541 542
#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
            || rareInheritedData->useTouchOverflowScrolling != other->rareInheritedData->useTouchOverflowScrolling
#endif
543
            || rareInheritedData->listStyleImage != other->rareInheritedData->listStyleImage)
544
            return true;
545

546
        if (!rareInheritedData->shadowDataEquivalent(*other->rareInheritedData.get()))
547
            return true;
548

549
        if (textStrokeWidth() != other->textStrokeWidth())
550
            return true;
551 552
    }

553 554
#if ENABLE(TEXT_AUTOSIZING)
    if (visual->m_textAutosizingMultiplier != other->visual->m_textAutosizingMultiplier)
555
        return true;
556 557
#endif

558
    if (inherited->line_height != other->inherited->line_height
559 560 561
#if ENABLE(IOS_TEXT_AUTOSIZING)
        || inherited->specifiedLineHeight != other->inherited->specifiedLineHeight
#endif
562 563 564 565
        || 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
566
        || inherited_flags.m_rtlOrdering != other->inherited_flags.m_rtlOrdering
567 568 569
        || noninherited_flags._position != other->noninherited_flags._position
        || noninherited_flags._floating != other->noninherited_flags._floating
        || noninherited_flags._originalDisplay != other->noninherited_flags._originalDisplay)
570
        return true;
571

572

573
    if (((int)noninherited_flags._effectiveDisplay) >= TABLE) {
574 575 576 577
        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)
578
            return true;
579

darin's avatar
darin committed
580 581
        // In the collapsing border model, 'hidden' suppresses other borders, while 'none'
        // does not, so these style differences can be width differences.
582 583 584 585 586 587 588 589 590
        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)))
591
            return true;
592 593
    }

594
    if (noninherited_flags._effectiveDisplay == LIST_ITEM) {
595 596
        if (inherited_flags._list_style_type != other->inherited_flags._list_style_type
            || inherited_flags._list_style_position != other->inherited_flags._list_style_position)
597
            return true;
598 599
    }

600 601 602 603 604 605
    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
        || noninherited_flags._unicodeBidi != other->noninherited_flags._unicodeBidi)
606
        return true;
607

608
    // Check block flow direction.
609
    if (inherited_flags.m_writingMode != other->inherited_flags.m_writingMode)
610
        return true;
611

612 613
    // Check text combine mode.
    if (rareNonInheritedData->m_textCombine != other->rareNonInheritedData->m_textCombine)
614
        return true;
615

616
    // Overflow returns a layout hint.
617 618
    if (noninherited_flags._overflowX != other->noninherited_flags._overflowX
        || noninherited_flags._overflowY != other->noninherited_flags._overflowY)
619
        return true;
620

621 622
    // If our border widths change, then we need to layout.  Other changes to borders
    // only necessitate a repaint.
623 624 625 626
    if (borderLeftWidth() != other->borderLeftWidth()
        || borderTopWidth() != other->borderTopWidth()
        || borderBottomWidth() != other->borderBottomWidth()
        || borderRightWidth() != other->borderRightWidth())
627
        return true;
628

darin's avatar
darin committed
629
    // If the counter directives change, trigger a relayout to re-calculate counter values and rebuild the counter node tree.
eric@webkit.org's avatar
eric@webkit.org committed
630 631
    const CounterDirectiveMap* mapA = rareNonInheritedData->m_counterDirectives.get();
    const CounterDirectiveMap* mapB = other->rareNonInheritedData->m_counterDirectives.get();
darin's avatar
darin committed
632
    if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB)))
633
        return true;
634

635
    if ((visibility() == COLLAPSE) != (other->visibility() == COLLAPSE))
636
        return true;
637

638
    if (rareNonInheritedData->hasOpacity() != other->rareNonInheritedData->hasOpacity()) {
639 640 641 642 643
        // FIXME: We would like to use SimplifiedLayout here, but we can't quite do that yet.
        // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
        // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
        // In addition we need to solve the floating object issue when layers come and go. Right now
        // a full layout is necessary to keep floating object lists sane.
644
        return true;
645 646
    }

647 648 649 650 651
#if ENABLE(CSS_FILTERS)
    if (rareNonInheritedData->hasFilters() != other->rareNonInheritedData->hasFilters())
        return true;
#endif

652 653 654
    const QuotesData* quotesDataA = rareInheritedData->quotes.get();
    const QuotesData* quotesDataB = other->rareInheritedData->quotes.get();
    if (!(quotesDataA == quotesDataB || (quotesDataA && quotesDataB && *quotesDataA == *quotesDataB)))
655
        return true;
656

657
    if (position() != StaticPosition) {
658
        if (surround->offset != other->surround->offset) {
659 660 661
            // FIXME: We would like to use SimplifiedLayout for relative positioning, but we can't quite do that yet.
            // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
            // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682
            if (position() != AbsolutePosition)
                return true;

            // Optimize for the case where a positioned layer is moving but not changing size.
            if (!positionChangeIsMovementOnly(surround->offset, other->surround->offset, m_box->width()))
                return true;
        }
    }
    
    return false;
}

bool RenderStyle::changeRequiresPositionedLayoutOnly(const RenderStyle* other, unsigned&) const
{
    if (position() == StaticPosition)
        return false;

    if (surround->offset != other->surround->offset) {
        // Optimize for the case where a positioned layer is moving but not changing size.
        if (position() == AbsolutePosition && positionChangeIsMovementOnly(surround->offset, other->surround->offset, m_box->width()))
            return true;
683
    }
684
    
685 686 687 688 689 690 691 692 693 694 695 696 697
    return false;
}

bool RenderStyle::changeRequiresLayerRepaint(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
{
    if (position() != StaticPosition) {
        if (m_box->zIndex() != other->m_box->zIndex()
            || m_box->hasAutoZIndex() != other->m_box->hasAutoZIndex()
            || visual->clip != other->visual->clip
            || visual->hasClip != other->visual->hasClip)
            return true;
    }

698 699
#if ENABLE(CSS_COMPOSITING)
    if (rareNonInheritedData->m_effectiveBlendMode != other->rareNonInheritedData->m_effectiveBlendMode)
700
        return true;
701
#endif
702

703 704 705 706 707
    if (rareNonInheritedData->opacity != other->rareNonInheritedData->opacity) {
#if USE(ACCELERATED_COMPOSITING)
        changedContextSensitiveProperties |= ContextSensitivePropertyOpacity;
        // Don't return; keep looking for another change.
#else
708
        UNUSED_PARAM(changedContextSensitiveProperties);
709
        return true;
710 711 712
#endif
    }

713 714 715 716 717 718 719
#if ENABLE(CSS_FILTERS)
    if (rareNonInheritedData->m_filter.get() != other->rareNonInheritedData->m_filter.get()
        && *rareNonInheritedData->m_filter.get() != *other->rareNonInheritedData->m_filter.get()) {
#if USE(ACCELERATED_COMPOSITING)
        changedContextSensitiveProperties |= ContextSensitivePropertyFilter;
        // Don't return; keep looking for another change.
#else
720
        return true;
721 722 723 724
#endif
    }
#endif

725 726
    if (rareNonInheritedData->m_mask != other->rareNonInheritedData->m_mask
        || rareNonInheritedData->m_maskBoxImage != other->rareNonInheritedData->m_maskBoxImage)
727 728 729 730
        return true;

    return false;
}
731

732 733
bool RenderStyle::changeRequiresRepaint(const RenderStyle* other, unsigned&) const
{
734
    if (inherited_flags._visibility != other->inherited_flags._visibility
735
        || inherited_flags.m_printColorAdjust != other->inherited_flags.m_printColorAdjust
736 737
        || inherited_flags._insideLink != other->inherited_flags._insideLink
        || surround->border != other->surround->border
738
        || !m_background->isEquivalentForPainting(*other->m_background)
739 740 741 742
        || rareInheritedData->userModify != other->rareInheritedData->userModify
        || rareInheritedData->userSelect != other->rareInheritedData->userSelect
        || rareNonInheritedData->userDrag != other->rareNonInheritedData->userDrag
        || rareNonInheritedData->m_borderFit != other->rareNonInheritedData->m_borderFit
743
        || rareNonInheritedData->m_objectFit != other->rareNonInheritedData->m_objectFit
744
        || rareInheritedData->m_imageRendering != other->rareInheritedData->m_imageRendering)
745
        return true;
746 747

#if ENABLE(CSS_SHAPES)
748 749 750 751 752 753 754
    // FIXME: The current spec is being reworked to remove dependencies between exclusions and affected 
    // content. There's a proposal to use floats instead. In that case, wrap-shape should actually relayout 
    // the parent container. For sure, I will have to revisit this code, but for now I've added this in order 
    // to avoid having diff() == StyleDifferenceEqual where wrap-shapes actually differ.
    // Tracking bug: https://bugs.webkit.org/show_bug.cgi?id=62991
    if (rareNonInheritedData->m_shapeOutside != other->rareNonInheritedData->m_shapeOutside)
        return true;
755
#endif
rjw's avatar
rjw committed
756

757 758
    if (rareNonInheritedData->m_clipPath != other->rareNonInheritedData->m_clipPath)
        return true;
759

760 761
    return false;
}
cmarrin@apple.com's avatar
cmarrin@apple.com committed
762

763
bool RenderStyle::changeRequiresRepaintIfTextOrBorderOrOutline(const RenderStyle* other, unsigned&) const
764
{
765 766 767 768 769
    if (inherited->color != other->inherited->color
        || inherited_flags._text_decorations != other->inherited_flags._text_decorations
        || visual->textDecoration != other->visual->textDecoration
        || rareNonInheritedData->m_textDecorationStyle != other->rareNonInheritedData->m_textDecorationStyle
        || rareNonInheritedData->m_textDecorationColor != other->rareNonInheritedData->m_textDecorationColor
770
        || rareInheritedData->m_textDecorationSkip != other->rareInheritedData->m_textDecorationSkip
771 772 773 774
        || rareInheritedData->textFillColor != other->rareInheritedData->textFillColor
        || rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor
        || rareInheritedData->textEmphasisColor != other->rareInheritedData->textEmphasisColor
        || rareInheritedData->textEmphasisFill != other->rareInheritedData->textEmphasisFill)
775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790
        return true;

    return false;
}

bool RenderStyle::changeRequiresRecompositeLayer(const RenderStyle* other, unsigned&) const
{
#if USE(ACCELERATED_COMPOSITING)
    if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
        if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D
            || rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility
            || rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective
            || rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX
            || rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY)
            return true;
    }
791 792
#else
    UNUSED_PARAM(other);
793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835
#endif
    return false;
}

StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
{
    changedContextSensitiveProperties = ContextSensitivePropertyNone;

#if ENABLE(SVG)
    StyleDifference svgChange = StyleDifferenceEqual;
    if (m_svgStyle != other->m_svgStyle) {
        svgChange = m_svgStyle->diff(other->m_svgStyle.get());
        if (svgChange == StyleDifferenceLayout)
            return svgChange;
    }
#endif

    if (changeRequiresLayout(other, changedContextSensitiveProperties))
        return StyleDifferenceLayout;

#if ENABLE(SVG)
    // SVGRenderStyle::diff() might have returned StyleDifferenceRepaint, eg. if fill changes.
    // If eg. the font-size changed at the same time, we're not allowed to return StyleDifferenceRepaint,
    // but have to return StyleDifferenceLayout, that's why  this if branch comes after all branches
    // that are relevant for SVG and might return StyleDifferenceLayout.
    if (svgChange != StyleDifferenceEqual)
        return svgChange;
#endif

    if (changeRequiresPositionedLayoutOnly(other, changedContextSensitiveProperties))
        return StyleDifferenceLayoutPositionedMovementOnly;

    if (changeRequiresLayerRepaint(other, changedContextSensitiveProperties))
        return StyleDifferenceRepaintLayer;

    if (changeRequiresRepaint(other, changedContextSensitiveProperties))
        return StyleDifferenceRepaint;

#if USE(ACCELERATED_COMPOSITING)
    if (changeRequiresRecompositeLayer(other, changedContextSensitiveProperties))
        return StyleDifferenceRecompositeLayer;
#endif

836 837
    if (changeRequiresRepaintIfTextOrBorderOrOutline(other, changedContextSensitiveProperties))
        return StyleDifferenceRepaintIfTextOrBorderOrOutline;
838

839 840 841
    // 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.

842
    // Animations 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
843
    // the resulting transition properly.
844
    return StyleDifferenceEqual;
845 846
}

847 848 849 850 851 852
bool RenderStyle::diffRequiresRepaint(const RenderStyle* style) const
{
    unsigned changedContextSensitiveProperties = 0;
    return changeRequiresRepaint(style, changedContextSensitiveProperties);
}

853
void RenderStyle::setClip(Length top, Length right, Length bottom, Length left)
854
{
855
    StyleVisualData* data = visual.access();
856 857 858 859
    data->clip.m_top = top;
    data->clip.m_right = right;
    data->clip.m_bottom = bottom;
    data->clip.m_left = left;
860 861
}

862
void RenderStyle::addCursor(PassRefPtr<StyleImage> image, const IntPoint& hotSpot)
rwlbuis's avatar
rwlbuis committed
863
{
864 865 866
    if (!rareInheritedData.access()->cursorData)
        rareInheritedData.access()->cursorData = CursorList::create();
    rareInheritedData.access()->cursorData->append(CursorData(image, hotSpot));
rwlbuis's avatar
rwlbuis committed
867