~ubuntu-branches/ubuntu/raring/qtwebkit-source/raring-proposed

« back to all changes in this revision

Viewing changes to Source/WebCore/rendering/style/RenderStyle.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-02-18 14:24:18 UTC
  • Revision ID: package-import@ubuntu.com-20130218142418-eon0jmjg3nj438uy
Tags: upstream-2.3
ImportĀ upstreamĀ versionĀ 2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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.
 
5
 *
 
6
 * This library is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU Library General Public
 
8
 * License as published by the Free Software Foundation; either
 
9
 * version 2 of the License, or (at your option) any later version.
 
10
 *
 
11
 * This library is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
 * Library General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU Library General Public License
 
17
 * along with this library; see the file COPYING.LIB.  If not, write to
 
18
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
19
 * Boston, MA 02110-1301, USA.
 
20
 *
 
21
 */
 
22
 
 
23
#include "config.h"
 
24
#include "RenderStyle.h"
 
25
 
 
26
#include "ContentData.h"
 
27
#include "CursorList.h"
 
28
#include "CSSPropertyNames.h"
 
29
#include "Font.h"
 
30
#include "FontSelector.h"
 
31
#include "QuotesData.h"
 
32
#include "RenderArena.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
#if ENABLE(TOUCH_EVENTS)
 
40
#include "RenderTheme.h"
 
41
#endif
 
42
#include "WebCoreMemoryInstrumentation.h"
 
43
#include <wtf/MemoryInstrumentationVector.h>
 
44
#include <wtf/MemoryObjectInfo.h>
 
45
#include <wtf/StdLibExtras.h>
 
46
#include <algorithm>
 
47
 
 
48
#if ENABLE(TEXT_AUTOSIZING)
 
49
#include "TextAutosizer.h"
 
50
#endif
 
51
 
 
52
using namespace std;
 
53
 
 
54
namespace WebCore {
 
55
 
 
56
struct SameSizeAsBorderValue {
 
57
    RGBA32 m_color;
 
58
    unsigned m_width;
 
59
};
 
60
 
 
61
COMPILE_ASSERT(sizeof(BorderValue) == sizeof(SameSizeAsBorderValue), BorderValue_should_not_grow);
 
62
 
 
63
struct SameSizeAsRenderStyle : public RefCounted<SameSizeAsRenderStyle> {
 
64
    void* dataRefs[7];
 
65
    void* ownPtrs[1];
 
66
#if ENABLE(SVG)
 
67
    void* dataRefSvgStyle;
 
68
#endif
 
69
    struct InheritedFlags {
 
70
        unsigned m_bitfields[2];
 
71
    } inherited_flags;
 
72
 
 
73
    struct NonInheritedFlags {
 
74
        unsigned m_bitfields[2];
 
75
    } noninherited_flags;
 
76
};
 
77
 
 
78
COMPILE_ASSERT(sizeof(RenderStyle) == sizeof(SameSizeAsRenderStyle), RenderStyle_should_stay_small);
 
79
 
 
80
inline RenderStyle* defaultStyle()
 
81
{
 
82
    static RenderStyle* s_defaultStyle = RenderStyle::createDefaultStyle().leakRef();
 
83
    return s_defaultStyle;
 
84
}
 
85
 
 
86
PassRefPtr<RenderStyle> RenderStyle::create()
 
87
{
 
88
    return adoptRef(new RenderStyle());
 
89
}
 
90
 
 
91
PassRefPtr<RenderStyle> RenderStyle::createDefaultStyle()
 
92
{
 
93
    return adoptRef(new RenderStyle(true));
 
94
}
 
95
 
 
96
PassRefPtr<RenderStyle> RenderStyle::createAnonymousStyleWithDisplay(const RenderStyle* parentStyle, EDisplay display)
 
97
{
 
98
    RefPtr<RenderStyle> newStyle = RenderStyle::create();
 
99
    newStyle->inheritFrom(parentStyle);
 
100
    newStyle->inheritUnicodeBidiFrom(parentStyle);
 
101
    newStyle->setDisplay(display);
 
102
    return newStyle;
 
103
}
 
104
 
 
105
PassRefPtr<RenderStyle> RenderStyle::clone(const RenderStyle* other)
 
106
{
 
107
    return adoptRef(new RenderStyle(*other));
 
108
}
 
109
 
 
110
ALWAYS_INLINE RenderStyle::RenderStyle()
 
111
    : m_box(defaultStyle()->m_box)
 
112
    , visual(defaultStyle()->visual)
 
113
    , m_background(defaultStyle()->m_background)
 
114
    , surround(defaultStyle()->surround)
 
115
    , rareNonInheritedData(defaultStyle()->rareNonInheritedData)
 
116
    , rareInheritedData(defaultStyle()->rareInheritedData)
 
117
    , inherited(defaultStyle()->inherited)
 
118
#if ENABLE(SVG)
 
119
    , m_svgStyle(defaultStyle()->m_svgStyle)
 
120
#endif
 
121
{
 
122
    setBitDefaults(); // Would it be faster to copy this from the default style?
 
123
    COMPILE_ASSERT((sizeof(InheritedFlags) <= 8), InheritedFlags_does_not_grow);
 
124
    COMPILE_ASSERT((sizeof(NonInheritedFlags) <= 8), NonInheritedFlags_does_not_grow);
 
125
}
 
126
 
 
127
ALWAYS_INLINE RenderStyle::RenderStyle(bool)
 
128
{
 
129
    setBitDefaults();
 
130
 
 
131
    m_box.init();
 
132
    visual.init();
 
133
    m_background.init();
 
134
    surround.init();
 
135
    rareNonInheritedData.init();
 
136
    rareNonInheritedData.access()->m_deprecatedFlexibleBox.init();
 
137
    rareNonInheritedData.access()->m_flexibleBox.init();
 
138
    rareNonInheritedData.access()->m_marquee.init();
 
139
    rareNonInheritedData.access()->m_multiCol.init();
 
140
    rareNonInheritedData.access()->m_transform.init();
 
141
#if ENABLE(CSS_FILTERS)
 
142
    rareNonInheritedData.access()->m_filter.init();
 
143
#endif
 
144
    rareNonInheritedData.access()->m_grid.init();
 
145
    rareNonInheritedData.access()->m_gridItem.init();
 
146
    rareInheritedData.init();
 
147
    inherited.init();
 
148
#if ENABLE(SVG)
 
149
    m_svgStyle.init();
 
150
#endif
 
151
}
 
152
 
 
153
ALWAYS_INLINE RenderStyle::RenderStyle(const RenderStyle& o)
 
154
    : RefCounted<RenderStyle>()
 
155
    , m_box(o.m_box)
 
156
    , visual(o.visual)
 
157
    , m_background(o.m_background)
 
158
    , surround(o.surround)
 
159
    , rareNonInheritedData(o.rareNonInheritedData)
 
160
    , rareInheritedData(o.rareInheritedData)
 
161
    , inherited(o.inherited)
 
162
#if ENABLE(SVG)
 
163
    , m_svgStyle(o.m_svgStyle)
 
164
#endif
 
165
    , inherited_flags(o.inherited_flags)
 
166
    , noninherited_flags(o.noninherited_flags)
 
167
{
 
168
}
 
169
 
 
170
void RenderStyle::inheritFrom(const RenderStyle* inheritParent, IsAtShadowBoundary isAtShadowBoundary)
 
171
{
 
172
    if (isAtShadowBoundary == AtShadowBoundary) {
 
173
        // Even if surrounding content is user-editable, shadow DOM should act as a single unit, and not necessarily be editable
 
174
        EUserModify currentUserModify = userModify();
 
175
        rareInheritedData = inheritParent->rareInheritedData;
 
176
        setUserModify(currentUserModify);
 
177
    } else
 
178
        rareInheritedData = inheritParent->rareInheritedData;
 
179
    inherited = inheritParent->inherited;
 
180
    inherited_flags = inheritParent->inherited_flags;
 
181
#if ENABLE(SVG)
 
182
    if (m_svgStyle != inheritParent->m_svgStyle)
 
183
        m_svgStyle.access()->inheritFrom(inheritParent->m_svgStyle.get());
 
184
#endif
 
185
}
 
186
 
 
187
void RenderStyle::copyNonInheritedFrom(const RenderStyle* other)
 
188
{
 
189
    m_box = other->m_box;
 
190
    visual = other->visual;
 
191
    m_background = other->m_background;
 
192
    surround = other->surround;
 
193
    rareNonInheritedData = other->rareNonInheritedData;
 
194
    // The flags are copied one-by-one because noninherited_flags contains a bunch of stuff other than real style data.
 
195
    noninherited_flags._effectiveDisplay = other->noninherited_flags._effectiveDisplay;
 
196
    noninherited_flags._originalDisplay = other->noninherited_flags._originalDisplay;
 
197
    noninherited_flags._overflowX = other->noninherited_flags._overflowX;
 
198
    noninherited_flags._overflowY = other->noninherited_flags._overflowY;
 
199
    noninherited_flags._vertical_align = other->noninherited_flags._vertical_align;
 
200
    noninherited_flags._clear = other->noninherited_flags._clear;
 
201
    noninherited_flags._position = other->noninherited_flags._position;
 
202
    noninherited_flags._floating = other->noninherited_flags._floating;
 
203
    noninherited_flags._table_layout = other->noninherited_flags._table_layout;
 
204
    noninherited_flags._unicodeBidi = other->noninherited_flags._unicodeBidi;
 
205
    noninherited_flags._page_break_before = other->noninherited_flags._page_break_before;
 
206
    noninherited_flags._page_break_after = other->noninherited_flags._page_break_after;
 
207
    noninherited_flags._page_break_inside = other->noninherited_flags._page_break_inside;
 
208
    noninherited_flags.explicitInheritance = other->noninherited_flags.explicitInheritance;
 
209
#if ENABLE(SVG)
 
210
    if (m_svgStyle != other->m_svgStyle)
 
211
        m_svgStyle.access()->copyNonInheritedFrom(other->m_svgStyle.get());
 
212
#endif
 
213
    ASSERT(zoom() == initialZoom());
 
214
}
 
215
 
 
216
bool RenderStyle::operator==(const RenderStyle& o) const
 
217
{
 
218
    // compare everything except the pseudoStyle pointer
 
219
    return inherited_flags == o.inherited_flags
 
220
        && noninherited_flags == o.noninherited_flags
 
221
        && m_box == o.m_box
 
222
        && visual == o.visual
 
223
        && m_background == o.m_background
 
224
        && surround == o.surround
 
225
        && rareNonInheritedData == o.rareNonInheritedData
 
226
        && rareInheritedData == o.rareInheritedData
 
227
        && inherited == o.inherited
 
228
#if ENABLE(SVG)
 
229
        && m_svgStyle == o.m_svgStyle
 
230
#endif
 
231
            ;
 
232
}
 
233
 
 
234
bool RenderStyle::isStyleAvailable() const
 
235
{
 
236
    return this != StyleResolver::styleNotYetAvailable();
 
237
}
 
238
 
 
239
static inline int pseudoBit(PseudoId pseudo)
 
240
{
 
241
    return 1 << (pseudo - 1);
 
242
}
 
243
 
 
244
bool RenderStyle::hasAnyPublicPseudoStyles() const
 
245
{
 
246
    return PUBLIC_PSEUDOID_MASK & noninherited_flags._pseudoBits;
 
247
}
 
248
 
 
249
bool RenderStyle::hasPseudoStyle(PseudoId pseudo) const
 
250
{
 
251
    ASSERT(pseudo > NOPSEUDO);
 
252
    ASSERT(pseudo < FIRST_INTERNAL_PSEUDOID);
 
253
    return pseudoBit(pseudo) & noninherited_flags._pseudoBits;
 
254
}
 
255
 
 
256
void RenderStyle::setHasPseudoStyle(PseudoId pseudo)
 
257
{
 
258
    ASSERT(pseudo > NOPSEUDO);
 
259
    ASSERT(pseudo < FIRST_INTERNAL_PSEUDOID);
 
260
    noninherited_flags._pseudoBits |= pseudoBit(pseudo);
 
261
}
 
262
 
 
263
RenderStyle* RenderStyle::getCachedPseudoStyle(PseudoId pid) const
 
264
{
 
265
    if (!m_cachedPseudoStyles || !m_cachedPseudoStyles->size())
 
266
        return 0;
 
267
 
 
268
    if (styleType() != NOPSEUDO) 
 
269
        return 0;
 
270
 
 
271
    for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
 
272
        RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
 
273
        if (pseudoStyle->styleType() == pid)
 
274
            return pseudoStyle;
 
275
    }
 
276
 
 
277
    return 0;
 
278
}
 
279
 
 
280
RenderStyle* RenderStyle::addCachedPseudoStyle(PassRefPtr<RenderStyle> pseudo)
 
281
{
 
282
    if (!pseudo)
 
283
        return 0;
 
284
 
 
285
    ASSERT(pseudo->styleType() > NOPSEUDO);
 
286
 
 
287
    RenderStyle* result = pseudo.get();
 
288
 
 
289
    if (!m_cachedPseudoStyles)
 
290
        m_cachedPseudoStyles = adoptPtr(new PseudoStyleCache);
 
291
 
 
292
    m_cachedPseudoStyles->append(pseudo);
 
293
 
 
294
    return result;
 
295
}
 
296
 
 
297
void RenderStyle::removeCachedPseudoStyle(PseudoId pid)
 
298
{
 
299
    if (!m_cachedPseudoStyles)
 
300
        return;
 
301
    for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
 
302
        RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
 
303
        if (pseudoStyle->styleType() == pid) {
 
304
            m_cachedPseudoStyles->remove(i);
 
305
            return;
 
306
        }
 
307
    }
 
308
}
 
309
 
 
310
bool RenderStyle::inheritedNotEqual(const RenderStyle* other) const
 
311
{
 
312
    return inherited_flags != other->inherited_flags
 
313
           || inherited != other->inherited
 
314
#if ENABLE(SVG)
 
315
           || m_svgStyle->inheritedNotEqual(other->m_svgStyle.get())
 
316
#endif
 
317
           || rareInheritedData != other->rareInheritedData;
 
318
}
 
319
 
 
320
bool RenderStyle::inheritedDataShared(const RenderStyle* other) const
 
321
{
 
322
    // This is a fast check that only looks if the data structures are shared.
 
323
    return inherited_flags == other->inherited_flags
 
324
        && inherited.get() == other->inherited.get()
 
325
#if ENABLE(SVG)
 
326
        && m_svgStyle.get() == other->m_svgStyle.get()
 
327
#endif
 
328
        && rareInheritedData.get() == other->rareInheritedData.get();
 
329
}
 
330
 
 
331
static bool positionedObjectMoved(const LengthBox& a, const LengthBox& b)
 
332
{
 
333
    // If any unit types are different, then we can't guarantee
 
334
    // that this was just a movement.
 
335
    if (a.left().type() != b.left().type()
 
336
        || a.right().type() != b.right().type()
 
337
        || a.top().type() != b.top().type()
 
338
        || a.bottom().type() != b.bottom().type())
 
339
        return false;
 
340
 
 
341
    // Only one unit can be non-auto in the horizontal direction and
 
342
    // in the vertical direction.  Otherwise the adjustment of values
 
343
    // is changing the size of the box.
 
344
    if (!a.left().isIntrinsicOrAuto() && !a.right().isIntrinsicOrAuto())
 
345
        return false;
 
346
    if (!a.top().isIntrinsicOrAuto() && !a.bottom().isIntrinsicOrAuto())
 
347
        return false;
 
348
 
 
349
    // One of the units is fixed or percent in both directions and stayed
 
350
    // that way in the new style.  Therefore all we are doing is moving.
 
351
    return true;
 
352
}
 
353
 
 
354
StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
 
355
{
 
356
    changedContextSensitiveProperties = ContextSensitivePropertyNone;
 
357
 
 
358
#if ENABLE(SVG)
 
359
    StyleDifference svgChange = StyleDifferenceEqual;
 
360
    if (m_svgStyle != other->m_svgStyle) {
 
361
        svgChange = m_svgStyle->diff(other->m_svgStyle.get());
 
362
        if (svgChange == StyleDifferenceLayout)
 
363
            return svgChange;
 
364
    }
 
365
#endif
 
366
 
 
367
    if (m_box->width() != other->m_box->width()
 
368
        || m_box->minWidth() != other->m_box->minWidth()
 
369
        || m_box->maxWidth() != other->m_box->maxWidth()
 
370
        || m_box->height() != other->m_box->height()
 
371
        || m_box->minHeight() != other->m_box->minHeight()
 
372
        || m_box->maxHeight() != other->m_box->maxHeight())
 
373
        return StyleDifferenceLayout;
 
374
 
 
375
    if (m_box->verticalAlign() != other->m_box->verticalAlign() || noninherited_flags._vertical_align != other->noninherited_flags._vertical_align)
 
376
        return StyleDifferenceLayout;
 
377
 
 
378
    if (m_box->boxSizing() != other->m_box->boxSizing())
 
379
        return StyleDifferenceLayout;
 
380
 
 
381
    if (surround->margin != other->surround->margin)
 
382
        return StyleDifferenceLayout;
 
383
 
 
384
    if (surround->padding != other->surround->padding)
 
385
        return StyleDifferenceLayout;
 
386
 
 
387
    if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
 
388
        if (rareNonInheritedData->m_appearance != other->rareNonInheritedData->m_appearance 
 
389
            || rareNonInheritedData->marginBeforeCollapse != other->rareNonInheritedData->marginBeforeCollapse
 
390
            || rareNonInheritedData->marginAfterCollapse != other->rareNonInheritedData->marginAfterCollapse
 
391
            || rareNonInheritedData->lineClamp != other->rareNonInheritedData->lineClamp
 
392
            || rareNonInheritedData->textOverflow != other->rareNonInheritedData->textOverflow)
 
393
            return StyleDifferenceLayout;
 
394
 
 
395
        if (rareNonInheritedData->m_regionOverflow != other->rareNonInheritedData->m_regionOverflow)
 
396
            return StyleDifferenceLayout;
 
397
 
 
398
        if (rareNonInheritedData->m_wrapFlow != other->rareNonInheritedData->m_wrapFlow
 
399
            || rareNonInheritedData->m_wrapThrough != other->rareNonInheritedData->m_wrapThrough
 
400
            || rareNonInheritedData->m_shapeMargin != other->rareNonInheritedData->m_shapeMargin
 
401
            || rareNonInheritedData->m_shapePadding != other->rareNonInheritedData->m_shapePadding)
 
402
            return StyleDifferenceLayout;
 
403
 
 
404
        if (rareNonInheritedData->m_deprecatedFlexibleBox.get() != other->rareNonInheritedData->m_deprecatedFlexibleBox.get()
 
405
            && *rareNonInheritedData->m_deprecatedFlexibleBox.get() != *other->rareNonInheritedData->m_deprecatedFlexibleBox.get())
 
406
            return StyleDifferenceLayout;
 
407
 
 
408
        if (rareNonInheritedData->m_flexibleBox.get() != other->rareNonInheritedData->m_flexibleBox.get()
 
409
            && *rareNonInheritedData->m_flexibleBox.get() != *other->rareNonInheritedData->m_flexibleBox.get())
 
410
            return StyleDifferenceLayout;
 
411
        if (rareNonInheritedData->m_order != other->rareNonInheritedData->m_order
 
412
            || rareNonInheritedData->m_alignContent != other->rareNonInheritedData->m_alignContent
 
413
            || rareNonInheritedData->m_alignItems != other->rareNonInheritedData->m_alignItems
 
414
            || rareNonInheritedData->m_alignSelf != other->rareNonInheritedData->m_alignSelf
 
415
            || rareNonInheritedData->m_justifyContent != other->rareNonInheritedData->m_justifyContent)
 
416
            return StyleDifferenceLayout;
 
417
 
 
418
        // FIXME: We should add an optimized form of layout that just recomputes visual overflow.
 
419
        if (!rareNonInheritedData->shadowDataEquivalent(*other->rareNonInheritedData.get()))
 
420
            return StyleDifferenceLayout;
 
421
 
 
422
        if (!rareNonInheritedData->reflectionDataEquivalent(*other->rareNonInheritedData.get()))
 
423
            return StyleDifferenceLayout;
 
424
 
 
425
        if (rareNonInheritedData->m_multiCol.get() != other->rareNonInheritedData->m_multiCol.get()
 
426
            && *rareNonInheritedData->m_multiCol.get() != *other->rareNonInheritedData->m_multiCol.get())
 
427
            return StyleDifferenceLayout;
 
428
 
 
429
        if (rareNonInheritedData->m_transform.get() != other->rareNonInheritedData->m_transform.get()
 
430
            && *rareNonInheritedData->m_transform.get() != *other->rareNonInheritedData->m_transform.get()) {
 
431
#if USE(ACCELERATED_COMPOSITING)
 
432
            changedContextSensitiveProperties |= ContextSensitivePropertyTransform;
 
433
            // Don't return; keep looking for another change
 
434
#else
 
435
            return StyleDifferenceLayout;
 
436
#endif
 
437
        }
 
438
 
 
439
        if (rareNonInheritedData->m_grid.get() != other->rareNonInheritedData->m_grid.get()
 
440
            && rareNonInheritedData->m_gridItem.get() != other->rareNonInheritedData->m_gridItem.get())
 
441
            return StyleDifferenceLayout;
 
442
 
 
443
#if !USE(ACCELERATED_COMPOSITING)
 
444
        if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
 
445
            if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D
 
446
                || rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility
 
447
                || rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective
 
448
                || rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX
 
449
                || rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY)
 
450
                return StyleDifferenceLayout;
 
451
        }
 
452
#endif
 
453
 
 
454
#if ENABLE(DASHBOARD_SUPPORT)
 
455
        // If regions change, trigger a relayout to re-calc regions.
 
456
        if (rareNonInheritedData->m_dashboardRegions != other->rareNonInheritedData->m_dashboardRegions)
 
457
            return StyleDifferenceLayout;
 
458
#endif
 
459
 
 
460
#if ENABLE(CSS_EXCLUSIONS)
 
461
        if (rareNonInheritedData->m_shapeInside != other->rareNonInheritedData->m_shapeInside)
 
462
            return StyleDifferenceLayout;
 
463
#endif
 
464
    }
 
465
 
 
466
    if (rareInheritedData.get() != other->rareInheritedData.get()) {
 
467
        if (rareInheritedData->highlight != other->rareInheritedData->highlight
 
468
            || rareInheritedData->indent != other->rareInheritedData->indent
 
469
            || rareInheritedData->m_effectiveZoom != other->rareInheritedData->m_effectiveZoom
 
470
            || rareInheritedData->textSizeAdjust != other->rareInheritedData->textSizeAdjust
 
471
            || rareInheritedData->wordBreak != other->rareInheritedData->wordBreak
 
472
            || rareInheritedData->overflowWrap != other->rareInheritedData->overflowWrap
 
473
            || rareInheritedData->nbspMode != other->rareInheritedData->nbspMode
 
474
            || rareInheritedData->lineBreak != other->rareInheritedData->lineBreak
 
475
            || rareInheritedData->textSecurity != other->rareInheritedData->textSecurity
 
476
            || rareInheritedData->hyphens != other->rareInheritedData->hyphens
 
477
            || rareInheritedData->hyphenationLimitBefore != other->rareInheritedData->hyphenationLimitBefore
 
478
            || rareInheritedData->hyphenationLimitAfter != other->rareInheritedData->hyphenationLimitAfter
 
479
            || rareInheritedData->hyphenationString != other->rareInheritedData->hyphenationString
 
480
            || rareInheritedData->locale != other->rareInheritedData->locale
 
481
            || rareInheritedData->m_rubyPosition != other->rareInheritedData->m_rubyPosition
 
482
            || rareInheritedData->textEmphasisMark != other->rareInheritedData->textEmphasisMark
 
483
            || rareInheritedData->textEmphasisPosition != other->rareInheritedData->textEmphasisPosition
 
484
            || rareInheritedData->textEmphasisCustomMark != other->rareInheritedData->textEmphasisCustomMark
 
485
            || rareInheritedData->m_tabSize != other->rareInheritedData->m_tabSize
 
486
            || rareInheritedData->m_lineBoxContain != other->rareInheritedData->m_lineBoxContain
 
487
            || rareInheritedData->m_lineGrid != other->rareInheritedData->m_lineGrid
 
488
#if ENABLE(CSS_IMAGE_RESOLUTION)
 
489
            || rareInheritedData->m_imageResolutionSource != other->rareInheritedData->m_imageResolutionSource
 
490
            || rareInheritedData->m_imageResolutionSnap != other->rareInheritedData->m_imageResolutionSnap
 
491
            || rareInheritedData->m_imageResolution != other->rareInheritedData->m_imageResolution
 
492
#endif
 
493
            || rareInheritedData->m_lineSnap != other->rareInheritedData->m_lineSnap
 
494
            || rareInheritedData->m_lineAlign != other->rareInheritedData->m_lineAlign
 
495
            || rareInheritedData->listStyleImage != other->rareInheritedData->listStyleImage)
 
496
            return StyleDifferenceLayout;
 
497
 
 
498
        if (!rareInheritedData->shadowDataEquivalent(*other->rareInheritedData.get()))
 
499
            return StyleDifferenceLayout;
 
500
 
 
501
        if (textStrokeWidth() != other->textStrokeWidth())
 
502
            return StyleDifferenceLayout;
 
503
    }
 
504
 
 
505
#if ENABLE(TEXT_AUTOSIZING)
 
506
    if (visual->m_textAutosizingMultiplier != other->visual->m_textAutosizingMultiplier)
 
507
        return StyleDifferenceLayout;
 
508
#endif
 
509
 
 
510
    if (inherited->line_height != other->inherited->line_height
 
511
        || inherited->font != other->inherited->font
 
512
        || inherited->horizontal_border_spacing != other->inherited->horizontal_border_spacing
 
513
        || inherited->vertical_border_spacing != other->inherited->vertical_border_spacing
 
514
        || inherited_flags._box_direction != other->inherited_flags._box_direction
 
515
        || inherited_flags.m_rtlOrdering != other->inherited_flags.m_rtlOrdering
 
516
        || noninherited_flags._position != other->noninherited_flags._position
 
517
        || noninherited_flags._floating != other->noninherited_flags._floating
 
518
        || noninherited_flags._originalDisplay != other->noninherited_flags._originalDisplay)
 
519
        return StyleDifferenceLayout;
 
520
 
 
521
 
 
522
    if (((int)noninherited_flags._effectiveDisplay) >= TABLE) {
 
523
        if (inherited_flags._border_collapse != other->inherited_flags._border_collapse
 
524
            || inherited_flags._empty_cells != other->inherited_flags._empty_cells
 
525
            || inherited_flags._caption_side != other->inherited_flags._caption_side
 
526
            || noninherited_flags._table_layout != other->noninherited_flags._table_layout)
 
527
            return StyleDifferenceLayout;
 
528
 
 
529
        // In the collapsing border model, 'hidden' suppresses other borders, while 'none'
 
530
        // does not, so these style differences can be width differences.
 
531
        if (inherited_flags._border_collapse
 
532
            && ((borderTopStyle() == BHIDDEN && other->borderTopStyle() == BNONE)
 
533
                || (borderTopStyle() == BNONE && other->borderTopStyle() == BHIDDEN)
 
534
                || (borderBottomStyle() == BHIDDEN && other->borderBottomStyle() == BNONE)
 
535
                || (borderBottomStyle() == BNONE && other->borderBottomStyle() == BHIDDEN)
 
536
                || (borderLeftStyle() == BHIDDEN && other->borderLeftStyle() == BNONE)
 
537
                || (borderLeftStyle() == BNONE && other->borderLeftStyle() == BHIDDEN)
 
538
                || (borderRightStyle() == BHIDDEN && other->borderRightStyle() == BNONE)
 
539
                || (borderRightStyle() == BNONE && other->borderRightStyle() == BHIDDEN)))
 
540
            return StyleDifferenceLayout;
 
541
    }
 
542
 
 
543
    if (noninherited_flags._effectiveDisplay == LIST_ITEM) {
 
544
        if (inherited_flags._list_style_type != other->inherited_flags._list_style_type
 
545
            || inherited_flags._list_style_position != other->inherited_flags._list_style_position)
 
546
            return StyleDifferenceLayout;
 
547
    }
 
548
 
 
549
    if (inherited_flags._text_align != other->inherited_flags._text_align
 
550
        || inherited_flags._text_transform != other->inherited_flags._text_transform
 
551
        || inherited_flags._direction != other->inherited_flags._direction
 
552
        || inherited_flags._white_space != other->inherited_flags._white_space
 
553
        || noninherited_flags._clear != other->noninherited_flags._clear
 
554
        || noninherited_flags._unicodeBidi != other->noninherited_flags._unicodeBidi)
 
555
        return StyleDifferenceLayout;
 
556
 
 
557
    // Check block flow direction.
 
558
    if (inherited_flags.m_writingMode != other->inherited_flags.m_writingMode)
 
559
        return StyleDifferenceLayout;
 
560
 
 
561
    // Check text combine mode.
 
562
    if (rareNonInheritedData->m_textCombine != other->rareNonInheritedData->m_textCombine)
 
563
        return StyleDifferenceLayout;
 
564
 
 
565
    // Overflow returns a layout hint.
 
566
    if (noninherited_flags._overflowX != other->noninherited_flags._overflowX
 
567
        || noninherited_flags._overflowY != other->noninherited_flags._overflowY)
 
568
        return StyleDifferenceLayout;
 
569
 
 
570
    // If our border widths change, then we need to layout.  Other changes to borders
 
571
    // only necessitate a repaint.
 
572
    if (borderLeftWidth() != other->borderLeftWidth()
 
573
        || borderTopWidth() != other->borderTopWidth()
 
574
        || borderBottomWidth() != other->borderBottomWidth()
 
575
        || borderRightWidth() != other->borderRightWidth())
 
576
        return StyleDifferenceLayout;
 
577
 
 
578
    // If the counter directives change, trigger a relayout to re-calculate counter values and rebuild the counter node tree.
 
579
    const CounterDirectiveMap* mapA = rareNonInheritedData->m_counterDirectives.get();
 
580
    const CounterDirectiveMap* mapB = other->rareNonInheritedData->m_counterDirectives.get();
 
581
    if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB)))
 
582
        return StyleDifferenceLayout;
 
583
 
 
584
    if ((visibility() == COLLAPSE) != (other->visibility() == COLLAPSE))
 
585
        return StyleDifferenceLayout;
 
586
 
 
587
    if ((rareNonInheritedData->opacity == 1 && other->rareNonInheritedData->opacity < 1)
 
588
        || (rareNonInheritedData->opacity < 1 && other->rareNonInheritedData->opacity == 1)) {
 
589
        // FIXME: We would like to use SimplifiedLayout here, but we can't quite do that yet.
 
590
        // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
 
591
        // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
 
592
        // In addition we need to solve the floating object issue when layers come and go. Right now
 
593
        // a full layout is necessary to keep floating object lists sane.
 
594
        return StyleDifferenceLayout;
 
595
    }
 
596
 
 
597
    if (!QuotesData::equals(rareInheritedData->quotes.get(), other->rareInheritedData->quotes.get()))
 
598
        return StyleDifferenceLayout;
 
599
 
 
600
#if ENABLE(SVG)
 
601
    // SVGRenderStyle::diff() might have returned StyleDifferenceRepaint, eg. if fill changes.
 
602
    // If eg. the font-size changed at the same time, we're not allowed to return StyleDifferenceRepaint,
 
603
    // but have to return StyleDifferenceLayout, that's why  this if branch comes after all branches
 
604
    // that are relevant for SVG and might return StyleDifferenceLayout.
 
605
    if (svgChange != StyleDifferenceEqual)
 
606
        return svgChange;
 
607
#endif
 
608
 
 
609
    // Make sure these left/top/right/bottom checks stay below all layout checks and above
 
610
    // all visible checks.
 
611
    if (position() != StaticPosition) {
 
612
        if (surround->offset != other->surround->offset) {
 
613
             // Optimize for the case where a positioned layer is moving but not changing size.
 
614
            if (position() == AbsolutePosition && positionedObjectMoved(surround->offset, other->surround->offset))
 
615
                return StyleDifferenceLayoutPositionedMovementOnly;
 
616
 
 
617
            // FIXME: We would like to use SimplifiedLayout for relative positioning, but we can't quite do that yet.
 
618
            // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
 
619
            // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
 
620
            return StyleDifferenceLayout;
 
621
        } else if (m_box->zIndex() != other->m_box->zIndex() || m_box->hasAutoZIndex() != other->m_box->hasAutoZIndex()
 
622
                 || visual->clip != other->visual->clip || visual->hasClip != other->visual->hasClip)
 
623
            return StyleDifferenceRepaintLayer;
 
624
    }
 
625
    
 
626
#if ENABLE(CSS_COMPOSITING)
 
627
    if (rareNonInheritedData->m_effectiveBlendMode != other->rareNonInheritedData->m_effectiveBlendMode)
 
628
        return StyleDifferenceRepaintLayer;
 
629
#endif
 
630
 
 
631
    if (rareNonInheritedData->opacity != other->rareNonInheritedData->opacity) {
 
632
#if USE(ACCELERATED_COMPOSITING)
 
633
        changedContextSensitiveProperties |= ContextSensitivePropertyOpacity;
 
634
        // Don't return; keep looking for another change.
 
635
#else
 
636
        return StyleDifferenceRepaintLayer;
 
637
#endif
 
638
    }
 
639
 
 
640
#if ENABLE(CSS_FILTERS)
 
641
    if (rareNonInheritedData->m_filter.get() != other->rareNonInheritedData->m_filter.get()
 
642
        && *rareNonInheritedData->m_filter.get() != *other->rareNonInheritedData->m_filter.get()) {
 
643
#if USE(ACCELERATED_COMPOSITING)
 
644
        changedContextSensitiveProperties |= ContextSensitivePropertyFilter;
 
645
        // Don't return; keep looking for another change.
 
646
#else
 
647
        return StyleDifferenceRepaintLayer;
 
648
#endif
 
649
    }
 
650
#endif
 
651
 
 
652
    if (rareNonInheritedData->m_mask != other->rareNonInheritedData->m_mask
 
653
        || rareNonInheritedData->m_maskBoxImage != other->rareNonInheritedData->m_maskBoxImage)
 
654
        return StyleDifferenceRepaintLayer;
 
655
 
 
656
    if (inherited->color != other->inherited->color
 
657
        || inherited_flags._visibility != other->inherited_flags._visibility
 
658
        || inherited_flags._text_decorations != other->inherited_flags._text_decorations
 
659
        || inherited_flags.m_printColorAdjust != other->inherited_flags.m_printColorAdjust
 
660
        || inherited_flags._insideLink != other->inherited_flags._insideLink
 
661
        || surround->border != other->surround->border
 
662
        || *m_background.get() != *other->m_background.get()
 
663
        || visual->textDecoration != other->visual->textDecoration
 
664
        || rareInheritedData->userModify != other->rareInheritedData->userModify
 
665
        || rareInheritedData->userSelect != other->rareInheritedData->userSelect
 
666
        || rareNonInheritedData->userDrag != other->rareNonInheritedData->userDrag
 
667
        || rareNonInheritedData->m_borderFit != other->rareNonInheritedData->m_borderFit
 
668
#if ENABLE(CSS3_TEXT)
 
669
        || rareNonInheritedData->m_textDecorationStyle != other->rareNonInheritedData->m_textDecorationStyle
 
670
#endif // CSS3_TEXT
 
671
        || rareInheritedData->textFillColor != other->rareInheritedData->textFillColor
 
672
        || rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor
 
673
        || rareInheritedData->textEmphasisColor != other->rareInheritedData->textEmphasisColor
 
674
        || rareInheritedData->textEmphasisFill != other->rareInheritedData->textEmphasisFill
 
675
        || rareInheritedData->m_imageRendering != other->rareInheritedData->m_imageRendering)
 
676
        return StyleDifferenceRepaint;
 
677
        
 
678
        // FIXME: The current spec is being reworked to remove dependencies between exclusions and affected 
 
679
        // content. There's a proposal to use floats instead. In that case, wrap-shape should actually relayout 
 
680
        // the parent container. For sure, I will have to revisit this code, but for now I've added this in order 
 
681
        // to avoid having diff() == StyleDifferenceEqual where wrap-shapes actually differ.
 
682
        // Tracking bug: https://bugs.webkit.org/show_bug.cgi?id=62991
 
683
        if (rareNonInheritedData->m_shapeOutside != other->rareNonInheritedData->m_shapeOutside)
 
684
            return StyleDifferenceRepaint;
 
685
 
 
686
        if (rareNonInheritedData->m_clipPath != other->rareNonInheritedData->m_clipPath)
 
687
            return StyleDifferenceRepaint;
 
688
 
 
689
 
 
690
#if USE(ACCELERATED_COMPOSITING)
 
691
    if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
 
692
        if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D
 
693
            || rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility
 
694
            || rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective
 
695
            || rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX
 
696
            || rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY)
 
697
            return StyleDifferenceRecompositeLayer;
 
698
    }
 
699
#endif
 
700
 
 
701
    // Cursors are not checked, since they will be set appropriately in response to mouse events,
 
702
    // so they don't need to cause any repaint or layout.
 
703
 
 
704
    // 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
 
705
    // the resulting transition properly.
 
706
    return StyleDifferenceEqual;
 
707
}
 
708
 
 
709
void RenderStyle::setClip(Length top, Length right, Length bottom, Length left)
 
710
{
 
711
    StyleVisualData* data = visual.access();
 
712
    data->clip.m_top = top;
 
713
    data->clip.m_right = right;
 
714
    data->clip.m_bottom = bottom;
 
715
    data->clip.m_left = left;
 
716
}
 
717
 
 
718
void RenderStyle::addCursor(PassRefPtr<StyleImage> image, const IntPoint& hotSpot)
 
719
{
 
720
    if (!rareInheritedData.access()->cursorData)
 
721
        rareInheritedData.access()->cursorData = CursorList::create();
 
722
    rareInheritedData.access()->cursorData->append(CursorData(image, hotSpot));
 
723
}
 
724
 
 
725
void RenderStyle::setCursorList(PassRefPtr<CursorList> other)
 
726
{
 
727
    rareInheritedData.access()->cursorData = other;
 
728
}
 
729
 
 
730
void RenderStyle::setQuotes(PassRefPtr<QuotesData> q)
 
731
{
 
732
    if (QuotesData::equals(rareInheritedData->quotes.get(), q.get()))
 
733
        return;
 
734
    rareInheritedData.access()->quotes = q;
 
735
}
 
736
 
 
737
void RenderStyle::clearCursorList()
 
738
{
 
739
    if (rareInheritedData->cursorData)
 
740
        rareInheritedData.access()->cursorData = 0;
 
741
}
 
742
 
 
743
void RenderStyle::clearContent()
 
744
{
 
745
    if (rareNonInheritedData->m_content)
 
746
        rareNonInheritedData.access()->m_content = nullptr;
 
747
}
 
748
 
 
749
void RenderStyle::appendContent(PassOwnPtr<ContentData> contentData)
 
750
{
 
751
    OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
 
752
    ContentData* lastContent = content.get();
 
753
    while (lastContent && lastContent->next())
 
754
        lastContent = lastContent->next();
 
755
 
 
756
    if (lastContent)
 
757
        lastContent->setNext(contentData);
 
758
    else
 
759
        content = contentData;
 
760
}
 
761
 
 
762
void RenderStyle::setContent(PassRefPtr<StyleImage> image, bool add)
 
763
{
 
764
    if (!image)
 
765
        return;
 
766
        
 
767
    if (add) {
 
768
        appendContent(ContentData::create(image));
 
769
        return;
 
770
    }
 
771
 
 
772
    rareNonInheritedData.access()->m_content = ContentData::create(image);
 
773
}
 
774
 
 
775
void RenderStyle::setContent(const String& string, bool add)
 
776
{
 
777
    OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
 
778
    if (add) {
 
779
        ContentData* lastContent = content.get();
 
780
        while (lastContent && lastContent->next())
 
781
            lastContent = lastContent->next();
 
782
 
 
783
        if (lastContent) {
 
784
            // We attempt to merge with the last ContentData if possible.
 
785
            if (lastContent->isText()) {
 
786
                TextContentData* textContent = static_cast<TextContentData*>(lastContent);
 
787
                textContent->setText(textContent->text() + string);
 
788
            } else
 
789
                lastContent->setNext(ContentData::create(string));
 
790
 
 
791
            return;
 
792
        }
 
793
    }
 
794
 
 
795
    content = ContentData::create(string);
 
796
}
 
797
 
 
798
void RenderStyle::setContent(PassOwnPtr<CounterContent> counter, bool add)
 
799
{
 
800
    if (!counter)
 
801
        return;
 
802
 
 
803
    if (add) {
 
804
        appendContent(ContentData::create(counter));
 
805
        return;
 
806
    }
 
807
 
 
808
    rareNonInheritedData.access()->m_content = ContentData::create(counter);
 
809
}
 
810
 
 
811
void RenderStyle::setContent(QuoteType quote, bool add)
 
812
{
 
813
    if (add) {
 
814
        appendContent(ContentData::create(quote));
 
815
        return;
 
816
    }
 
817
 
 
818
    rareNonInheritedData.access()->m_content = ContentData::create(quote);
 
819
}
 
820
    
 
821
inline bool requireTransformOrigin(const Vector<RefPtr<TransformOperation> >& transformOperations, RenderStyle::ApplyTransformOrigin applyOrigin)
 
822
{
 
823
    // transform-origin brackets the transform with translate operations.
 
824
    // Optimize for the case where the only transform is a translation, since the transform-origin is irrelevant
 
825
    // in that case.
 
826
    if (applyOrigin != RenderStyle::IncludeTransformOrigin)
 
827
        return false;
 
828
 
 
829
    unsigned size = transformOperations.size();
 
830
    for (unsigned i = 0; i < size; ++i) {
 
831
        TransformOperation::OperationType type = transformOperations[i]->getOperationType();
 
832
        if (type != TransformOperation::TRANSLATE_X
 
833
            && type != TransformOperation::TRANSLATE_Y
 
834
            && type != TransformOperation::TRANSLATE 
 
835
            && type != TransformOperation::TRANSLATE_Z
 
836
            && type != TransformOperation::TRANSLATE_3D)
 
837
            return true;
 
838
    }
 
839
    
 
840
    return false;
 
841
}
 
842
 
 
843
void RenderStyle::applyTransform(TransformationMatrix& transform, const LayoutSize& borderBoxSize, ApplyTransformOrigin applyOrigin) const
 
844
{
 
845
    // FIXME: when subpixel layout is supported (bug 71143) the body of this function could be replaced by
 
846
    // applyTransform(transform, FloatRect(FloatPoint(), borderBoxSize), applyOrigin);
 
847
    
 
848
    const Vector<RefPtr<TransformOperation> >& transformOperations = rareNonInheritedData->m_transform->m_operations.operations();
 
849
    bool applyTransformOrigin = requireTransformOrigin(transformOperations, applyOrigin);
 
850
 
 
851
    if (applyTransformOrigin)
 
852
        transform.translate3d(floatValueForLength(transformOriginX(), borderBoxSize.width()), floatValueForLength(transformOriginY(), borderBoxSize.height()), transformOriginZ());
 
853
 
 
854
    unsigned size = transformOperations.size();
 
855
    for (unsigned i = 0; i < size; ++i)
 
856
        transformOperations[i]->apply(transform, borderBoxSize);
 
857
 
 
858
    if (applyTransformOrigin)
 
859
        transform.translate3d(-floatValueForLength(transformOriginX(), borderBoxSize.width()), -floatValueForLength(transformOriginY(), borderBoxSize.height()), -transformOriginZ()); 
 
860
}
 
861
 
 
862
void RenderStyle::applyTransform(TransformationMatrix& transform, const FloatRect& boundingBox, ApplyTransformOrigin applyOrigin) const
 
863
{
 
864
    const Vector<RefPtr<TransformOperation> >& transformOperations = rareNonInheritedData->m_transform->m_operations.operations();
 
865
    bool applyTransformOrigin = requireTransformOrigin(transformOperations, applyOrigin);
 
866
    
 
867
    float offsetX = transformOriginX().type() == Percent ? boundingBox.x() : 0;
 
868
    float offsetY = transformOriginY().type() == Percent ? boundingBox.y() : 0;
 
869
    
 
870
    if (applyTransformOrigin) {
 
871
        transform.translate3d(floatValueForLength(transformOriginX(), boundingBox.width()) + offsetX,
 
872
                              floatValueForLength(transformOriginY(), boundingBox.height()) + offsetY,
 
873
                              transformOriginZ());
 
874
    }
 
875
    
 
876
    unsigned size = transformOperations.size();
 
877
    for (unsigned i = 0; i < size; ++i)
 
878
        transformOperations[i]->apply(transform, boundingBox.size());
 
879
    
 
880
    if (applyTransformOrigin) {
 
881
        transform.translate3d(-floatValueForLength(transformOriginX(), boundingBox.width()) - offsetX,
 
882
                              -floatValueForLength(transformOriginY(), boundingBox.height()) - offsetY,
 
883
                              -transformOriginZ());
 
884
    }
 
885
}
 
886
 
 
887
void RenderStyle::setPageScaleTransform(float scale)
 
888
{
 
889
    if (scale == 1)
 
890
        return;
 
891
    TransformOperations transform;
 
892
    transform.operations().append(ScaleTransformOperation::create(scale, scale, ScaleTransformOperation::SCALE));
 
893
    setTransform(transform);
 
894
    setTransformOriginX(Length(0, Fixed));
 
895
    setTransformOriginY(Length(0, Fixed));
 
896
}
 
897
 
 
898
void RenderStyle::setTextShadow(PassOwnPtr<ShadowData> shadowData, bool add)
 
899
{
 
900
    ASSERT(!shadowData || (!shadowData->spread() && shadowData->style() == Normal));
 
901
 
 
902
    StyleRareInheritedData* rareData = rareInheritedData.access();
 
903
    if (!add) {
 
904
        rareData->textShadow = shadowData;
 
905
        return;
 
906
    }
 
907
 
 
908
    shadowData->setNext(rareData->textShadow.release());
 
909
    rareData->textShadow = shadowData;
 
910
}
 
911
 
 
912
void RenderStyle::setBoxShadow(PassOwnPtr<ShadowData> shadowData, bool add)
 
913
{
 
914
    StyleRareNonInheritedData* rareData = rareNonInheritedData.access();
 
915
    if (!add) {
 
916
        rareData->m_boxShadow = shadowData;
 
917
        return;
 
918
    }
 
919
 
 
920
    shadowData->setNext(rareData->m_boxShadow.release());
 
921
    rareData->m_boxShadow = shadowData;
 
922
}
 
923
 
 
924
static RoundedRect::Radii calcRadiiFor(const BorderData& border, IntSize size, RenderView* renderView)
 
925
{
 
926
    return RoundedRect::Radii(
 
927
        IntSize(valueForLength(border.topLeft().width(), size.width(), renderView), 
 
928
                valueForLength(border.topLeft().height(), size.height(), renderView)),
 
929
        IntSize(valueForLength(border.topRight().width(), size.width(), renderView),
 
930
                valueForLength(border.topRight().height(), size.height(), renderView)),
 
931
        IntSize(valueForLength(border.bottomLeft().width(), size.width(), renderView), 
 
932
                valueForLength(border.bottomLeft().height(), size.height(), renderView)),
 
933
        IntSize(valueForLength(border.bottomRight().width(), size.width(), renderView), 
 
934
                valueForLength(border.bottomRight().height(), size.height(), renderView)));
 
935
}
 
936
 
 
937
static float calcConstraintScaleFor(const IntRect& rect, const RoundedRect::Radii& radii)
 
938
{
 
939
    // Constrain corner radii using CSS3 rules:
 
940
    // http://www.w3.org/TR/css3-background/#the-border-radius
 
941
    
 
942
    float factor = 1;
 
943
    unsigned radiiSum;
 
944
 
 
945
    // top
 
946
    radiiSum = static_cast<unsigned>(radii.topLeft().width()) + static_cast<unsigned>(radii.topRight().width()); // Casts to avoid integer overflow.
 
947
    if (radiiSum > static_cast<unsigned>(rect.width()))
 
948
        factor = min(static_cast<float>(rect.width()) / radiiSum, factor);
 
949
 
 
950
    // bottom
 
951
    radiiSum = static_cast<unsigned>(radii.bottomLeft().width()) + static_cast<unsigned>(radii.bottomRight().width());
 
952
    if (radiiSum > static_cast<unsigned>(rect.width()))
 
953
        factor = min(static_cast<float>(rect.width()) / radiiSum, factor);
 
954
    
 
955
    // left
 
956
    radiiSum = static_cast<unsigned>(radii.topLeft().height()) + static_cast<unsigned>(radii.bottomLeft().height());
 
957
    if (radiiSum > static_cast<unsigned>(rect.height()))
 
958
        factor = min(static_cast<float>(rect.height()) / radiiSum, factor);
 
959
    
 
960
    // right
 
961
    radiiSum = static_cast<unsigned>(radii.topRight().height()) + static_cast<unsigned>(radii.bottomRight().height());
 
962
    if (radiiSum > static_cast<unsigned>(rect.height()))
 
963
        factor = min(static_cast<float>(rect.height()) / radiiSum, factor);
 
964
    
 
965
    ASSERT(factor <= 1);
 
966
    return factor;
 
967
}
 
968
 
 
969
StyleImage* RenderStyle::listStyleImage() const { return rareInheritedData->listStyleImage.get(); }
 
970
void RenderStyle::setListStyleImage(PassRefPtr<StyleImage> v)
 
971
{
 
972
    if (rareInheritedData->listStyleImage != v)
 
973
        rareInheritedData.access()->listStyleImage = v;
 
974
}
 
975
 
 
976
Color RenderStyle::color() const { return inherited->color; }
 
977
Color RenderStyle::visitedLinkColor() const { return inherited->visitedLinkColor; }
 
978
void RenderStyle::setColor(const Color& v) { SET_VAR(inherited, color, v) };
 
979
void RenderStyle::setVisitedLinkColor(const Color& v) { SET_VAR(inherited, visitedLinkColor, v) }
 
980
 
 
981
short RenderStyle::horizontalBorderSpacing() const { return inherited->horizontal_border_spacing; }
 
982
short RenderStyle::verticalBorderSpacing() const { return inherited->vertical_border_spacing; }
 
983
void RenderStyle::setHorizontalBorderSpacing(short v) { SET_VAR(inherited, horizontal_border_spacing, v) }
 
984
void RenderStyle::setVerticalBorderSpacing(short v) { SET_VAR(inherited, vertical_border_spacing, v) }
 
985
 
 
986
RoundedRect RenderStyle::getRoundedBorderFor(const LayoutRect& borderRect, RenderView* renderView, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
 
987
{
 
988
    IntRect snappedBorderRect(pixelSnappedIntRect(borderRect));
 
989
    RoundedRect roundedRect(snappedBorderRect);
 
990
    if (hasBorderRadius()) {
 
991
        RoundedRect::Radii radii = calcRadiiFor(surround->border, snappedBorderRect.size(), renderView);
 
992
        radii.scale(calcConstraintScaleFor(snappedBorderRect, radii));
 
993
        roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
 
994
    }
 
995
    return roundedRect;
 
996
}
 
997
 
 
998
RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
 
999
{
 
1000
    bool horizontal = isHorizontalWritingMode();
 
1001
 
 
1002
    LayoutUnit leftWidth = (!horizontal || includeLogicalLeftEdge) ? borderLeftWidth() : 0;
 
1003
    LayoutUnit rightWidth = (!horizontal || includeLogicalRightEdge) ? borderRightWidth() : 0;
 
1004
    LayoutUnit topWidth = (horizontal || includeLogicalLeftEdge) ? borderTopWidth() : 0;
 
1005
    LayoutUnit bottomWidth = (horizontal || includeLogicalRightEdge) ? borderBottomWidth() : 0;
 
1006
 
 
1007
    return getRoundedInnerBorderFor(borderRect, topWidth, bottomWidth, leftWidth, rightWidth, includeLogicalLeftEdge, includeLogicalRightEdge);
 
1008
}
 
1009
 
 
1010
RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect,
 
1011
    LayoutUnit topWidth, LayoutUnit bottomWidth, LayoutUnit leftWidth, LayoutUnit rightWidth, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
 
1012
{
 
1013
    LayoutRect innerRect(borderRect.x() + leftWidth, 
 
1014
               borderRect.y() + topWidth, 
 
1015
               borderRect.width() - leftWidth - rightWidth, 
 
1016
               borderRect.height() - topWidth - bottomWidth);
 
1017
 
 
1018
    RoundedRect roundedRect(pixelSnappedIntRect(innerRect));
 
1019
 
 
1020
    if (hasBorderRadius()) {
 
1021
        RoundedRect::Radii radii = getRoundedBorderFor(borderRect).radii();
 
1022
        radii.shrink(topWidth, bottomWidth, leftWidth, rightWidth);
 
1023
        roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
 
1024
    }
 
1025
    return roundedRect;
 
1026
}
 
1027
 
 
1028
const CounterDirectiveMap* RenderStyle::counterDirectives() const
 
1029
{
 
1030
    return rareNonInheritedData->m_counterDirectives.get();
 
1031
}
 
1032
 
 
1033
CounterDirectiveMap& RenderStyle::accessCounterDirectives()
 
1034
{
 
1035
    OwnPtr<CounterDirectiveMap>& map = rareNonInheritedData.access()->m_counterDirectives;
 
1036
    if (!map)
 
1037
        map = adoptPtr(new CounterDirectiveMap);
 
1038
    return *map;
 
1039
}
 
1040
 
 
1041
const CounterDirectives RenderStyle::getCounterDirectives(const AtomicString& identifier) const
 
1042
{
 
1043
    if (const CounterDirectiveMap* directives = counterDirectives())
 
1044
        return directives->get(identifier);
 
1045
    return CounterDirectives();
 
1046
}
 
1047
 
 
1048
const AtomicString& RenderStyle::hyphenString() const
 
1049
{
 
1050
    ASSERT(hyphens() != HyphensNone);
 
1051
 
 
1052
    const AtomicString& hyphenationString = rareInheritedData.get()->hyphenationString;
 
1053
    if (!hyphenationString.isNull())
 
1054
        return hyphenationString;
 
1055
 
 
1056
    // FIXME: This should depend on locale.
 
1057
    DEFINE_STATIC_LOCAL(AtomicString, hyphenMinusString, (&hyphenMinus, 1));
 
1058
    DEFINE_STATIC_LOCAL(AtomicString, hyphenString, (&hyphen, 1));
 
1059
    return font().primaryFontHasGlyphForCharacter(hyphen) ? hyphenString : hyphenMinusString;
 
1060
}
 
1061
 
 
1062
const AtomicString& RenderStyle::textEmphasisMarkString() const
 
1063
{
 
1064
    switch (textEmphasisMark()) {
 
1065
    case TextEmphasisMarkNone:
 
1066
        return nullAtom;
 
1067
    case TextEmphasisMarkCustom:
 
1068
        return textEmphasisCustomMark();
 
1069
    case TextEmphasisMarkDot: {
 
1070
        DEFINE_STATIC_LOCAL(AtomicString, filledDotString, (&bullet, 1));
 
1071
        DEFINE_STATIC_LOCAL(AtomicString, openDotString, (&whiteBullet, 1));
 
1072
        return textEmphasisFill() == TextEmphasisFillFilled ? filledDotString : openDotString;
 
1073
    }
 
1074
    case TextEmphasisMarkCircle: {
 
1075
        DEFINE_STATIC_LOCAL(AtomicString, filledCircleString, (&blackCircle, 1));
 
1076
        DEFINE_STATIC_LOCAL(AtomicString, openCircleString, (&whiteCircle, 1));
 
1077
        return textEmphasisFill() == TextEmphasisFillFilled ? filledCircleString : openCircleString;
 
1078
    }
 
1079
    case TextEmphasisMarkDoubleCircle: {
 
1080
        DEFINE_STATIC_LOCAL(AtomicString, filledDoubleCircleString, (&fisheye, 1));
 
1081
        DEFINE_STATIC_LOCAL(AtomicString, openDoubleCircleString, (&bullseye, 1));
 
1082
        return textEmphasisFill() == TextEmphasisFillFilled ? filledDoubleCircleString : openDoubleCircleString;
 
1083
    }
 
1084
    case TextEmphasisMarkTriangle: {
 
1085
        DEFINE_STATIC_LOCAL(AtomicString, filledTriangleString, (&blackUpPointingTriangle, 1));
 
1086
        DEFINE_STATIC_LOCAL(AtomicString, openTriangleString, (&whiteUpPointingTriangle, 1));
 
1087
        return textEmphasisFill() == TextEmphasisFillFilled ? filledTriangleString : openTriangleString;
 
1088
    }
 
1089
    case TextEmphasisMarkSesame: {
 
1090
        DEFINE_STATIC_LOCAL(AtomicString, filledSesameString, (&sesameDot, 1));
 
1091
        DEFINE_STATIC_LOCAL(AtomicString, openSesameString, (&whiteSesameDot, 1));
 
1092
        return textEmphasisFill() == TextEmphasisFillFilled ? filledSesameString : openSesameString;
 
1093
    }
 
1094
    case TextEmphasisMarkAuto:
 
1095
        ASSERT_NOT_REACHED();
 
1096
        return nullAtom;
 
1097
    }
 
1098
 
 
1099
    ASSERT_NOT_REACHED();
 
1100
    return nullAtom;
 
1101
}
 
1102
 
 
1103
#if ENABLE(DASHBOARD_SUPPORT)
 
1104
const Vector<StyleDashboardRegion>& RenderStyle::initialDashboardRegions()
 
1105
{
 
1106
    DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, emptyList, ());
 
1107
    return emptyList;
 
1108
}
 
1109
 
 
1110
const Vector<StyleDashboardRegion>& RenderStyle::noneDashboardRegions()
 
1111
{
 
1112
    DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, noneList, ());
 
1113
    static bool noneListInitialized = false;
 
1114
 
 
1115
    if (!noneListInitialized) {
 
1116
        StyleDashboardRegion region;
 
1117
        region.label = "";
 
1118
        region.offset.m_top  = Length();
 
1119
        region.offset.m_right = Length();
 
1120
        region.offset.m_bottom = Length();
 
1121
        region.offset.m_left = Length();
 
1122
        region.type = StyleDashboardRegion::None;
 
1123
        noneList.append(region);
 
1124
        noneListInitialized = true;
 
1125
    }
 
1126
    return noneList;
 
1127
}
 
1128
#endif
 
1129
 
 
1130
void RenderStyle::adjustAnimations()
 
1131
{
 
1132
    AnimationList* animationList = rareNonInheritedData->m_animations.get();
 
1133
    if (!animationList)
 
1134
        return;
 
1135
 
 
1136
    // Get rid of empty animations and anything beyond them
 
1137
    for (size_t i = 0; i < animationList->size(); ++i) {
 
1138
        if (animationList->animation(i)->isEmpty()) {
 
1139
            animationList->resize(i);
 
1140
            break;
 
1141
        }
 
1142
    }
 
1143
 
 
1144
    if (animationList->isEmpty()) {
 
1145
        clearAnimations();
 
1146
        return;
 
1147
    }
 
1148
 
 
1149
    // Repeat patterns into layers that don't have some properties set.
 
1150
    animationList->fillUnsetProperties();
 
1151
}
 
1152
 
 
1153
void RenderStyle::adjustTransitions()
 
1154
{
 
1155
    AnimationList* transitionList = rareNonInheritedData->m_transitions.get();
 
1156
    if (!transitionList)
 
1157
        return;
 
1158
 
 
1159
    // Get rid of empty transitions and anything beyond them
 
1160
    for (size_t i = 0; i < transitionList->size(); ++i) {
 
1161
        if (transitionList->animation(i)->isEmpty()) {
 
1162
            transitionList->resize(i);
 
1163
            break;
 
1164
        }
 
1165
    }
 
1166
 
 
1167
    if (transitionList->isEmpty()) {
 
1168
        clearTransitions();
 
1169
        return;
 
1170
    }
 
1171
 
 
1172
    // Repeat patterns into layers that don't have some properties set.
 
1173
    transitionList->fillUnsetProperties();
 
1174
 
 
1175
    // Make sure there are no duplicate properties. This is an O(n^2) algorithm
 
1176
    // but the lists tend to be very short, so it is probably ok
 
1177
    for (size_t i = 0; i < transitionList->size(); ++i) {
 
1178
        for (size_t j = i+1; j < transitionList->size(); ++j) {
 
1179
            if (transitionList->animation(i)->property() == transitionList->animation(j)->property()) {
 
1180
                // toss i
 
1181
                transitionList->remove(i);
 
1182
                j = i;
 
1183
            }
 
1184
        }
 
1185
    }
 
1186
}
 
1187
 
 
1188
AnimationList* RenderStyle::accessAnimations()
 
1189
{
 
1190
    if (!rareNonInheritedData.access()->m_animations)
 
1191
        rareNonInheritedData.access()->m_animations = adoptPtr(new AnimationList());
 
1192
    return rareNonInheritedData->m_animations.get();
 
1193
}
 
1194
 
 
1195
AnimationList* RenderStyle::accessTransitions()
 
1196
{
 
1197
    if (!rareNonInheritedData.access()->m_transitions)
 
1198
        rareNonInheritedData.access()->m_transitions = adoptPtr(new AnimationList());
 
1199
    return rareNonInheritedData->m_transitions.get();
 
1200
}
 
1201
 
 
1202
const Animation* RenderStyle::transitionForProperty(CSSPropertyID property) const
 
1203
{
 
1204
    if (transitions()) {
 
1205
        for (size_t i = 0; i < transitions()->size(); ++i) {
 
1206
            const Animation* p = transitions()->animation(i);
 
1207
            if (p->animationMode() == Animation::AnimateAll || p->property() == property) {
 
1208
                return p;
 
1209
            }
 
1210
        }
 
1211
    }
 
1212
    return 0;
 
1213
}
 
1214
 
 
1215
const Font& RenderStyle::font() const { return inherited->font; }
 
1216
const FontMetrics& RenderStyle::fontMetrics() const { return inherited->font.fontMetrics(); }
 
1217
const FontDescription& RenderStyle::fontDescription() const { return inherited->font.fontDescription(); }
 
1218
float RenderStyle::specifiedFontSize() const { return fontDescription().specifiedSize(); }
 
1219
float RenderStyle::computedFontSize() const { return fontDescription().computedSize(); }
 
1220
int RenderStyle::fontSize() const { return inherited->font.pixelSize(); }
 
1221
 
 
1222
int RenderStyle::wordSpacing() const { return inherited->font.wordSpacing(); }
 
1223
int RenderStyle::letterSpacing() const { return inherited->font.letterSpacing(); }
 
1224
 
 
1225
bool RenderStyle::setFontDescription(const FontDescription& v)
 
1226
{
 
1227
    if (inherited->font.fontDescription() != v) {
 
1228
        inherited.access()->font = Font(v, inherited->font.letterSpacing(), inherited->font.wordSpacing());
 
1229
        return true;
 
1230
    }
 
1231
    return false;
 
1232
}
 
1233
 
 
1234
Length RenderStyle::specifiedLineHeight() const { return inherited->line_height; }
 
1235
Length RenderStyle::lineHeight() const
 
1236
{
 
1237
    const Length& lh = inherited->line_height;
 
1238
#if ENABLE(TEXT_AUTOSIZING)
 
1239
    // Unlike fontDescription().computedSize() and hence fontSize(), this is
 
1240
    // recalculated on demand as we only store the specified line height.
 
1241
    // FIXME: Should consider scaling the fixed part of any calc expressions
 
1242
    // too, though this involves messily poking into CalcExpressionLength.
 
1243
    float multiplier = textAutosizingMultiplier();
 
1244
    if (multiplier > 1 && lh.isFixed())
 
1245
        return Length(TextAutosizer::computeAutosizedFontSize(lh.value(), multiplier), Fixed);
 
1246
#endif
 
1247
    return lh;
 
1248
}
 
1249
void RenderStyle::setLineHeight(Length specifiedLineHeight) { SET_VAR(inherited, line_height, specifiedLineHeight); }
 
1250
 
 
1251
int RenderStyle::computedLineHeight(RenderView* renderView) const
 
1252
{
 
1253
    const Length& lh = lineHeight();
 
1254
 
 
1255
    // Negative value means the line height is not set. Use the font's built-in spacing.
 
1256
    if (lh.isNegative())
 
1257
        return fontMetrics().lineSpacing();
 
1258
 
 
1259
    if (lh.isPercent())
 
1260
        return minimumValueForLength(lh, fontSize());
 
1261
 
 
1262
    if (lh.isViewportPercentage())
 
1263
        return valueForLength(lh, 0, renderView);
 
1264
 
 
1265
    return lh.value();
 
1266
}
 
1267
 
 
1268
void RenderStyle::setWordSpacing(int v) { inherited.access()->font.setWordSpacing(v); }
 
1269
void RenderStyle::setLetterSpacing(int v) { inherited.access()->font.setLetterSpacing(v); }
 
1270
 
 
1271
void RenderStyle::setFontSize(float size)
 
1272
{
 
1273
    // size must be specifiedSize if Text Autosizing is enabled, but computedSize if text
 
1274
    // zoom is enabled (if neither is enabled it's irrelevant as they're probably the same).
 
1275
 
 
1276
    FontSelector* currentFontSelector = font().fontSelector();
 
1277
    FontDescription desc(fontDescription());
 
1278
    desc.setSpecifiedSize(size);
 
1279
    desc.setComputedSize(size);
 
1280
 
 
1281
#if ENABLE(TEXT_AUTOSIZING)
 
1282
    float multiplier = textAutosizingMultiplier();
 
1283
    if (multiplier > 1) {
 
1284
        desc.setComputedSize(TextAutosizer::computeAutosizedFontSize(size, multiplier));
 
1285
    }
 
1286
#endif
 
1287
 
 
1288
    setFontDescription(desc);
 
1289
    font().update(currentFontSelector);
 
1290
}
 
1291
 
 
1292
void RenderStyle::getShadowExtent(const ShadowData* shadow, LayoutUnit &top, LayoutUnit &right, LayoutUnit &bottom, LayoutUnit &left) const
 
1293
{
 
1294
    top = 0;
 
1295
    right = 0;
 
1296
    bottom = 0;
 
1297
    left = 0;
 
1298
 
 
1299
    for ( ; shadow; shadow = shadow->next()) {
 
1300
        if (shadow->style() == Inset)
 
1301
            continue;
 
1302
        int blurAndSpread = shadow->blur() + shadow->spread();
 
1303
 
 
1304
        top = min<LayoutUnit>(top, shadow->y() - blurAndSpread);
 
1305
        right = max<LayoutUnit>(right, shadow->x() + blurAndSpread);
 
1306
        bottom = max<LayoutUnit>(bottom, shadow->y() + blurAndSpread);
 
1307
        left = min<LayoutUnit>(left, shadow->x() - blurAndSpread);
 
1308
    }
 
1309
}
 
1310
 
 
1311
LayoutBoxExtent RenderStyle::getShadowInsetExtent(const ShadowData* shadow) const
 
1312
{
 
1313
    LayoutUnit top = 0;
 
1314
    LayoutUnit right = 0;
 
1315
    LayoutUnit bottom = 0;
 
1316
    LayoutUnit left = 0;
 
1317
 
 
1318
    for ( ; shadow; shadow = shadow->next()) {
 
1319
        if (shadow->style() == Normal)
 
1320
            continue;
 
1321
        int blurAndSpread = shadow->blur() + shadow->spread();
 
1322
        top = max<LayoutUnit>(top, shadow->y() + blurAndSpread);
 
1323
        right = min<LayoutUnit>(right, shadow->x() - blurAndSpread);
 
1324
        bottom = min<LayoutUnit>(bottom, shadow->y() - blurAndSpread);
 
1325
        left = max<LayoutUnit>(left, shadow->x() + blurAndSpread);
 
1326
    }
 
1327
 
 
1328
    return LayoutBoxExtent(top, right, bottom, left);
 
1329
}
 
1330
 
 
1331
void RenderStyle::getShadowHorizontalExtent(const ShadowData* shadow, LayoutUnit &left, LayoutUnit &right) const
 
1332
{
 
1333
    left = 0;
 
1334
    right = 0;
 
1335
 
 
1336
    for ( ; shadow; shadow = shadow->next()) {
 
1337
        if (shadow->style() == Inset)
 
1338
            continue;
 
1339
        int blurAndSpread = shadow->blur() + shadow->spread();
 
1340
 
 
1341
        left = min<LayoutUnit>(left, shadow->x() - blurAndSpread);
 
1342
        right = max<LayoutUnit>(right, shadow->x() + blurAndSpread);
 
1343
    }
 
1344
}
 
1345
 
 
1346
void RenderStyle::getShadowVerticalExtent(const ShadowData* shadow, LayoutUnit &top, LayoutUnit &bottom) const
 
1347
{
 
1348
    top = 0;
 
1349
    bottom = 0;
 
1350
 
 
1351
    for ( ; shadow; shadow = shadow->next()) {
 
1352
        if (shadow->style() == Inset)
 
1353
            continue;
 
1354
        int blurAndSpread = shadow->blur() + shadow->spread();
 
1355
 
 
1356
        top = min<LayoutUnit>(top, shadow->y() - blurAndSpread);
 
1357
        bottom = max<LayoutUnit>(bottom, shadow->y() + blurAndSpread);
 
1358
    }
 
1359
}
 
1360
 
 
1361
Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) const
 
1362
{
 
1363
    Color result;
 
1364
    EBorderStyle borderStyle = BNONE;
 
1365
    switch (colorProperty) {
 
1366
    case CSSPropertyBackgroundColor:
 
1367
        return visitedLink ? visitedLinkBackgroundColor() : backgroundColor(); // Background color doesn't fall back.
 
1368
    case CSSPropertyBorderLeftColor:
 
1369
        result = visitedLink ? visitedLinkBorderLeftColor() : borderLeftColor();
 
1370
        borderStyle = borderLeftStyle();
 
1371
        break;
 
1372
    case CSSPropertyBorderRightColor:
 
1373
        result = visitedLink ? visitedLinkBorderRightColor() : borderRightColor();
 
1374
        borderStyle = borderRightStyle();
 
1375
        break;
 
1376
    case CSSPropertyBorderTopColor:
 
1377
        result = visitedLink ? visitedLinkBorderTopColor() : borderTopColor();
 
1378
        borderStyle = borderTopStyle();
 
1379
        break;
 
1380
    case CSSPropertyBorderBottomColor:
 
1381
        result = visitedLink ? visitedLinkBorderBottomColor() : borderBottomColor();
 
1382
        borderStyle = borderBottomStyle();
 
1383
        break;
 
1384
    case CSSPropertyColor:
 
1385
        result = visitedLink ? visitedLinkColor() : color();
 
1386
        break;
 
1387
    case CSSPropertyOutlineColor:
 
1388
        result = visitedLink ? visitedLinkOutlineColor() : outlineColor();
 
1389
        break;
 
1390
    case CSSPropertyWebkitColumnRuleColor:
 
1391
        result = visitedLink ? visitedLinkColumnRuleColor() : columnRuleColor();
 
1392
        break;
 
1393
    case CSSPropertyWebkitTextEmphasisColor:
 
1394
        result = visitedLink ? visitedLinkTextEmphasisColor() : textEmphasisColor();
 
1395
        break;
 
1396
    case CSSPropertyWebkitTextFillColor:
 
1397
        result = visitedLink ? visitedLinkTextFillColor() : textFillColor();
 
1398
        break;
 
1399
    case CSSPropertyWebkitTextStrokeColor:
 
1400
        result = visitedLink ? visitedLinkTextStrokeColor() : textStrokeColor();
 
1401
        break;
 
1402
    default:
 
1403
        ASSERT_NOT_REACHED();
 
1404
        break;
 
1405
    }
 
1406
 
 
1407
    if (!result.isValid()) {
 
1408
        if (!visitedLink && (borderStyle == INSET || borderStyle == OUTSET || borderStyle == RIDGE || borderStyle == GROOVE))
 
1409
            result.setRGB(238, 238, 238);
 
1410
        else
 
1411
            result = visitedLink ? visitedLinkColor() : color();
 
1412
    }
 
1413
    return result;
 
1414
}
 
1415
 
 
1416
Color RenderStyle::visitedDependentColor(int colorProperty) const
 
1417
{
 
1418
    Color unvisitedColor = colorIncludingFallback(colorProperty, false);
 
1419
    if (insideLink() != InsideVisitedLink)
 
1420
        return unvisitedColor;
 
1421
 
 
1422
    Color visitedColor = colorIncludingFallback(colorProperty, true);
 
1423
 
 
1424
    // FIXME: Technically someone could explicitly specify the color transparent, but for now we'll just
 
1425
    // assume that if the background color is transparent that it wasn't set. Note that it's weird that
 
1426
    // we're returning unvisited info for a visited link, but given our restriction that the alpha values
 
1427
    // have to match, it makes more sense to return the unvisited background color if specified than it
 
1428
    // does to return black. This behavior matches what Firefox 4 does as well.
 
1429
    if (colorProperty == CSSPropertyBackgroundColor && visitedColor == Color::transparent)
 
1430
        return unvisitedColor;
 
1431
 
 
1432
    // Take the alpha from the unvisited color, but get the RGB values from the visited color.
 
1433
    return Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), unvisitedColor.alpha());
 
1434
}
 
1435
 
 
1436
const BorderValue& RenderStyle::borderBefore() const
 
1437
{
 
1438
    switch (writingMode()) {
 
1439
    case TopToBottomWritingMode:
 
1440
        return borderTop();
 
1441
    case BottomToTopWritingMode:
 
1442
        return borderBottom();
 
1443
    case LeftToRightWritingMode:
 
1444
        return borderLeft();
 
1445
    case RightToLeftWritingMode:
 
1446
        return borderRight();
 
1447
    }
 
1448
    ASSERT_NOT_REACHED();
 
1449
    return borderTop();
 
1450
}
 
1451
 
 
1452
const BorderValue& RenderStyle::borderAfter() const
 
1453
{
 
1454
    switch (writingMode()) {
 
1455
    case TopToBottomWritingMode:
 
1456
        return borderBottom();
 
1457
    case BottomToTopWritingMode:
 
1458
        return borderTop();
 
1459
    case LeftToRightWritingMode:
 
1460
        return borderRight();
 
1461
    case RightToLeftWritingMode:
 
1462
        return borderLeft();
 
1463
    }
 
1464
    ASSERT_NOT_REACHED();
 
1465
    return borderBottom();
 
1466
}
 
1467
 
 
1468
const BorderValue& RenderStyle::borderStart() const
 
1469
{
 
1470
    if (isHorizontalWritingMode())
 
1471
        return isLeftToRightDirection() ? borderLeft() : borderRight();
 
1472
    return isLeftToRightDirection() ? borderTop() : borderBottom();
 
1473
}
 
1474
 
 
1475
const BorderValue& RenderStyle::borderEnd() const
 
1476
{
 
1477
    if (isHorizontalWritingMode())
 
1478
        return isLeftToRightDirection() ? borderRight() : borderLeft();
 
1479
    return isLeftToRightDirection() ? borderBottom() : borderTop();
 
1480
}
 
1481
 
 
1482
unsigned short RenderStyle::borderBeforeWidth() const
 
1483
{
 
1484
    switch (writingMode()) {
 
1485
    case TopToBottomWritingMode:
 
1486
        return borderTopWidth();
 
1487
    case BottomToTopWritingMode:
 
1488
        return borderBottomWidth();
 
1489
    case LeftToRightWritingMode:
 
1490
        return borderLeftWidth();
 
1491
    case RightToLeftWritingMode:
 
1492
        return borderRightWidth();
 
1493
    }
 
1494
    ASSERT_NOT_REACHED();
 
1495
    return borderTopWidth();
 
1496
}
 
1497
 
 
1498
unsigned short RenderStyle::borderAfterWidth() const
 
1499
{
 
1500
    switch (writingMode()) {
 
1501
    case TopToBottomWritingMode:
 
1502
        return borderBottomWidth();
 
1503
    case BottomToTopWritingMode:
 
1504
        return borderTopWidth();
 
1505
    case LeftToRightWritingMode:
 
1506
        return borderRightWidth();
 
1507
    case RightToLeftWritingMode:
 
1508
        return borderLeftWidth();
 
1509
    }
 
1510
    ASSERT_NOT_REACHED();
 
1511
    return borderBottomWidth();
 
1512
}
 
1513
 
 
1514
unsigned short RenderStyle::borderStartWidth() const
 
1515
{
 
1516
    if (isHorizontalWritingMode())
 
1517
        return isLeftToRightDirection() ? borderLeftWidth() : borderRightWidth();
 
1518
    return isLeftToRightDirection() ? borderTopWidth() : borderBottomWidth();
 
1519
}
 
1520
 
 
1521
unsigned short RenderStyle::borderEndWidth() const
 
1522
{
 
1523
    if (isHorizontalWritingMode())
 
1524
        return isLeftToRightDirection() ? borderRightWidth() : borderLeftWidth();
 
1525
    return isLeftToRightDirection() ? borderBottomWidth() : borderTopWidth();
 
1526
}
 
1527
 
 
1528
void RenderStyle::setMarginStart(Length margin)
 
1529
{
 
1530
    if (isHorizontalWritingMode()) {
 
1531
        if (isLeftToRightDirection())
 
1532
            setMarginLeft(margin);
 
1533
        else
 
1534
            setMarginRight(margin);
 
1535
    } else {
 
1536
        if (isLeftToRightDirection())
 
1537
            setMarginTop(margin);
 
1538
        else
 
1539
            setMarginBottom(margin);
 
1540
    }
 
1541
}
 
1542
 
 
1543
void RenderStyle::setMarginEnd(Length margin)
 
1544
{
 
1545
    if (isHorizontalWritingMode()) {
 
1546
        if (isLeftToRightDirection())
 
1547
            setMarginRight(margin);
 
1548
        else
 
1549
            setMarginLeft(margin);
 
1550
    } else {
 
1551
        if (isLeftToRightDirection())
 
1552
            setMarginBottom(margin);
 
1553
        else
 
1554
            setMarginTop(margin);
 
1555
    }
 
1556
}
 
1557
 
 
1558
TextEmphasisMark RenderStyle::textEmphasisMark() const
 
1559
{
 
1560
    TextEmphasisMark mark = static_cast<TextEmphasisMark>(rareInheritedData->textEmphasisMark);
 
1561
    if (mark != TextEmphasisMarkAuto)
 
1562
        return mark;
 
1563
 
 
1564
    if (isHorizontalWritingMode())
 
1565
        return TextEmphasisMarkDot;
 
1566
 
 
1567
    return TextEmphasisMarkSesame;
 
1568
}
 
1569
 
 
1570
#if ENABLE(TOUCH_EVENTS)
 
1571
Color RenderStyle::initialTapHighlightColor()
 
1572
{
 
1573
    return RenderTheme::tapHighlightColor();
 
1574
}
 
1575
#endif
 
1576
 
 
1577
LayoutBoxExtent RenderStyle::imageOutsets(const NinePieceImage& image) const
 
1578
{
 
1579
    return LayoutBoxExtent(NinePieceImage::computeOutset(image.outset().top(), borderTopWidth()),
 
1580
                           NinePieceImage::computeOutset(image.outset().right(), borderRightWidth()),
 
1581
                           NinePieceImage::computeOutset(image.outset().bottom(), borderBottomWidth()),
 
1582
                           NinePieceImage::computeOutset(image.outset().left(), borderLeftWidth()));
 
1583
}
 
1584
 
 
1585
void RenderStyle::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
 
1586
{
 
1587
    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS);
 
1588
    info.addMember(m_box);
 
1589
    info.addMember(visual);
 
1590
    // FIXME: m_background contains RefPtr<StyleImage> that might need to be instrumented.
 
1591
    info.addMember(m_background);
 
1592
    // FIXME: surrond contains some fields e.g. BorderData that might need to be instrumented.
 
1593
    info.addMember(surround);
 
1594
    info.addMember(rareNonInheritedData);
 
1595
    info.addMember(rareInheritedData);
 
1596
    // FIXME: inherited contains StyleImage and Font fields that might need to be instrumented.
 
1597
    info.addMember(inherited);
 
1598
    info.addMember(m_cachedPseudoStyles);
 
1599
#if ENABLE(SVG)
 
1600
    info.addMember(m_svgStyle);
 
1601
#endif
 
1602
}
 
1603
 
 
1604
} // namespace WebCore