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.
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.
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.
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.
24
#include "RenderStyle.h"
26
#include "ContentData.h"
27
#include "CursorList.h"
28
#include "CSSPropertyNames.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"
42
#include "WebCoreMemoryInstrumentation.h"
43
#include <wtf/MemoryInstrumentationVector.h>
44
#include <wtf/MemoryObjectInfo.h>
45
#include <wtf/StdLibExtras.h>
48
#if ENABLE(TEXT_AUTOSIZING)
49
#include "TextAutosizer.h"
56
struct SameSizeAsBorderValue {
61
COMPILE_ASSERT(sizeof(BorderValue) == sizeof(SameSizeAsBorderValue), BorderValue_should_not_grow);
63
struct SameSizeAsRenderStyle : public RefCounted<SameSizeAsRenderStyle> {
67
void* dataRefSvgStyle;
69
struct InheritedFlags {
70
unsigned m_bitfields[2];
73
struct NonInheritedFlags {
74
unsigned m_bitfields[2];
78
COMPILE_ASSERT(sizeof(RenderStyle) == sizeof(SameSizeAsRenderStyle), RenderStyle_should_stay_small);
80
inline RenderStyle* defaultStyle()
82
static RenderStyle* s_defaultStyle = RenderStyle::createDefaultStyle().leakRef();
83
return s_defaultStyle;
86
PassRefPtr<RenderStyle> RenderStyle::create()
88
return adoptRef(new RenderStyle());
91
PassRefPtr<RenderStyle> RenderStyle::createDefaultStyle()
93
return adoptRef(new RenderStyle(true));
96
PassRefPtr<RenderStyle> RenderStyle::createAnonymousStyleWithDisplay(const RenderStyle* parentStyle, EDisplay display)
98
RefPtr<RenderStyle> newStyle = RenderStyle::create();
99
newStyle->inheritFrom(parentStyle);
100
newStyle->inheritUnicodeBidiFrom(parentStyle);
101
newStyle->setDisplay(display);
105
PassRefPtr<RenderStyle> RenderStyle::clone(const RenderStyle* other)
107
return adoptRef(new RenderStyle(*other));
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)
119
, m_svgStyle(defaultStyle()->m_svgStyle)
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);
127
ALWAYS_INLINE RenderStyle::RenderStyle(bool)
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();
144
rareNonInheritedData.access()->m_grid.init();
145
rareNonInheritedData.access()->m_gridItem.init();
146
rareInheritedData.init();
153
ALWAYS_INLINE RenderStyle::RenderStyle(const RenderStyle& o)
154
: RefCounted<RenderStyle>()
157
, m_background(o.m_background)
158
, surround(o.surround)
159
, rareNonInheritedData(o.rareNonInheritedData)
160
, rareInheritedData(o.rareInheritedData)
161
, inherited(o.inherited)
163
, m_svgStyle(o.m_svgStyle)
165
, inherited_flags(o.inherited_flags)
166
, noninherited_flags(o.noninherited_flags)
170
void RenderStyle::inheritFrom(const RenderStyle* inheritParent, IsAtShadowBoundary isAtShadowBoundary)
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);
178
rareInheritedData = inheritParent->rareInheritedData;
179
inherited = inheritParent->inherited;
180
inherited_flags = inheritParent->inherited_flags;
182
if (m_svgStyle != inheritParent->m_svgStyle)
183
m_svgStyle.access()->inheritFrom(inheritParent->m_svgStyle.get());
187
void RenderStyle::copyNonInheritedFrom(const RenderStyle* other)
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;
210
if (m_svgStyle != other->m_svgStyle)
211
m_svgStyle.access()->copyNonInheritedFrom(other->m_svgStyle.get());
213
ASSERT(zoom() == initialZoom());
216
bool RenderStyle::operator==(const RenderStyle& o) const
218
// compare everything except the pseudoStyle pointer
219
return inherited_flags == o.inherited_flags
220
&& noninherited_flags == o.noninherited_flags
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
229
&& m_svgStyle == o.m_svgStyle
234
bool RenderStyle::isStyleAvailable() const
236
return this != StyleResolver::styleNotYetAvailable();
239
static inline int pseudoBit(PseudoId pseudo)
241
return 1 << (pseudo - 1);
244
bool RenderStyle::hasAnyPublicPseudoStyles() const
246
return PUBLIC_PSEUDOID_MASK & noninherited_flags._pseudoBits;
249
bool RenderStyle::hasPseudoStyle(PseudoId pseudo) const
251
ASSERT(pseudo > NOPSEUDO);
252
ASSERT(pseudo < FIRST_INTERNAL_PSEUDOID);
253
return pseudoBit(pseudo) & noninherited_flags._pseudoBits;
256
void RenderStyle::setHasPseudoStyle(PseudoId pseudo)
258
ASSERT(pseudo > NOPSEUDO);
259
ASSERT(pseudo < FIRST_INTERNAL_PSEUDOID);
260
noninherited_flags._pseudoBits |= pseudoBit(pseudo);
263
RenderStyle* RenderStyle::getCachedPseudoStyle(PseudoId pid) const
265
if (!m_cachedPseudoStyles || !m_cachedPseudoStyles->size())
268
if (styleType() != NOPSEUDO)
271
for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
272
RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
273
if (pseudoStyle->styleType() == pid)
280
RenderStyle* RenderStyle::addCachedPseudoStyle(PassRefPtr<RenderStyle> pseudo)
285
ASSERT(pseudo->styleType() > NOPSEUDO);
287
RenderStyle* result = pseudo.get();
289
if (!m_cachedPseudoStyles)
290
m_cachedPseudoStyles = adoptPtr(new PseudoStyleCache);
292
m_cachedPseudoStyles->append(pseudo);
297
void RenderStyle::removeCachedPseudoStyle(PseudoId pid)
299
if (!m_cachedPseudoStyles)
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);
310
bool RenderStyle::inheritedNotEqual(const RenderStyle* other) const
312
return inherited_flags != other->inherited_flags
313
|| inherited != other->inherited
315
|| m_svgStyle->inheritedNotEqual(other->m_svgStyle.get())
317
|| rareInheritedData != other->rareInheritedData;
320
bool RenderStyle::inheritedDataShared(const RenderStyle* other) const
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()
326
&& m_svgStyle.get() == other->m_svgStyle.get()
328
&& rareInheritedData.get() == other->rareInheritedData.get();
331
static bool positionedObjectMoved(const LengthBox& a, const LengthBox& b)
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())
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())
346
if (!a.top().isIntrinsicOrAuto() && !a.bottom().isIntrinsicOrAuto())
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.
354
StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
356
changedContextSensitiveProperties = ContextSensitivePropertyNone;
359
StyleDifference svgChange = StyleDifferenceEqual;
360
if (m_svgStyle != other->m_svgStyle) {
361
svgChange = m_svgStyle->diff(other->m_svgStyle.get());
362
if (svgChange == StyleDifferenceLayout)
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;
375
if (m_box->verticalAlign() != other->m_box->verticalAlign() || noninherited_flags._vertical_align != other->noninherited_flags._vertical_align)
376
return StyleDifferenceLayout;
378
if (m_box->boxSizing() != other->m_box->boxSizing())
379
return StyleDifferenceLayout;
381
if (surround->margin != other->surround->margin)
382
return StyleDifferenceLayout;
384
if (surround->padding != other->surround->padding)
385
return StyleDifferenceLayout;
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;
395
if (rareNonInheritedData->m_regionOverflow != other->rareNonInheritedData->m_regionOverflow)
396
return StyleDifferenceLayout;
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;
404
if (rareNonInheritedData->m_deprecatedFlexibleBox.get() != other->rareNonInheritedData->m_deprecatedFlexibleBox.get()
405
&& *rareNonInheritedData->m_deprecatedFlexibleBox.get() != *other->rareNonInheritedData->m_deprecatedFlexibleBox.get())
406
return StyleDifferenceLayout;
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;
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;
422
if (!rareNonInheritedData->reflectionDataEquivalent(*other->rareNonInheritedData.get()))
423
return StyleDifferenceLayout;
425
if (rareNonInheritedData->m_multiCol.get() != other->rareNonInheritedData->m_multiCol.get()
426
&& *rareNonInheritedData->m_multiCol.get() != *other->rareNonInheritedData->m_multiCol.get())
427
return StyleDifferenceLayout;
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
435
return StyleDifferenceLayout;
439
if (rareNonInheritedData->m_grid.get() != other->rareNonInheritedData->m_grid.get()
440
&& rareNonInheritedData->m_gridItem.get() != other->rareNonInheritedData->m_gridItem.get())
441
return StyleDifferenceLayout;
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;
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;
460
#if ENABLE(CSS_EXCLUSIONS)
461
if (rareNonInheritedData->m_shapeInside != other->rareNonInheritedData->m_shapeInside)
462
return StyleDifferenceLayout;
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
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;
498
if (!rareInheritedData->shadowDataEquivalent(*other->rareInheritedData.get()))
499
return StyleDifferenceLayout;
501
if (textStrokeWidth() != other->textStrokeWidth())
502
return StyleDifferenceLayout;
505
#if ENABLE(TEXT_AUTOSIZING)
506
if (visual->m_textAutosizingMultiplier != other->visual->m_textAutosizingMultiplier)
507
return StyleDifferenceLayout;
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;
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;
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;
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;
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;
557
// Check block flow direction.
558
if (inherited_flags.m_writingMode != other->inherited_flags.m_writingMode)
559
return StyleDifferenceLayout;
561
// Check text combine mode.
562
if (rareNonInheritedData->m_textCombine != other->rareNonInheritedData->m_textCombine)
563
return StyleDifferenceLayout;
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;
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;
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;
584
if ((visibility() == COLLAPSE) != (other->visibility() == COLLAPSE))
585
return StyleDifferenceLayout;
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;
597
if (!QuotesData::equals(rareInheritedData->quotes.get(), other->rareInheritedData->quotes.get()))
598
return StyleDifferenceLayout;
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)
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;
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;
626
#if ENABLE(CSS_COMPOSITING)
627
if (rareNonInheritedData->m_effectiveBlendMode != other->rareNonInheritedData->m_effectiveBlendMode)
628
return StyleDifferenceRepaintLayer;
631
if (rareNonInheritedData->opacity != other->rareNonInheritedData->opacity) {
632
#if USE(ACCELERATED_COMPOSITING)
633
changedContextSensitiveProperties |= ContextSensitivePropertyOpacity;
634
// Don't return; keep looking for another change.
636
return StyleDifferenceRepaintLayer;
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.
647
return StyleDifferenceRepaintLayer;
652
if (rareNonInheritedData->m_mask != other->rareNonInheritedData->m_mask
653
|| rareNonInheritedData->m_maskBoxImage != other->rareNonInheritedData->m_maskBoxImage)
654
return StyleDifferenceRepaintLayer;
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
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;
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;
686
if (rareNonInheritedData->m_clipPath != other->rareNonInheritedData->m_clipPath)
687
return StyleDifferenceRepaint;
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;
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.
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;
709
void RenderStyle::setClip(Length top, Length right, Length bottom, Length left)
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;
718
void RenderStyle::addCursor(PassRefPtr<StyleImage> image, const IntPoint& hotSpot)
720
if (!rareInheritedData.access()->cursorData)
721
rareInheritedData.access()->cursorData = CursorList::create();
722
rareInheritedData.access()->cursorData->append(CursorData(image, hotSpot));
725
void RenderStyle::setCursorList(PassRefPtr<CursorList> other)
727
rareInheritedData.access()->cursorData = other;
730
void RenderStyle::setQuotes(PassRefPtr<QuotesData> q)
732
if (QuotesData::equals(rareInheritedData->quotes.get(), q.get()))
734
rareInheritedData.access()->quotes = q;
737
void RenderStyle::clearCursorList()
739
if (rareInheritedData->cursorData)
740
rareInheritedData.access()->cursorData = 0;
743
void RenderStyle::clearContent()
745
if (rareNonInheritedData->m_content)
746
rareNonInheritedData.access()->m_content = nullptr;
749
void RenderStyle::appendContent(PassOwnPtr<ContentData> contentData)
751
OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
752
ContentData* lastContent = content.get();
753
while (lastContent && lastContent->next())
754
lastContent = lastContent->next();
757
lastContent->setNext(contentData);
759
content = contentData;
762
void RenderStyle::setContent(PassRefPtr<StyleImage> image, bool add)
768
appendContent(ContentData::create(image));
772
rareNonInheritedData.access()->m_content = ContentData::create(image);
775
void RenderStyle::setContent(const String& string, bool add)
777
OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
779
ContentData* lastContent = content.get();
780
while (lastContent && lastContent->next())
781
lastContent = lastContent->next();
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);
789
lastContent->setNext(ContentData::create(string));
795
content = ContentData::create(string);
798
void RenderStyle::setContent(PassOwnPtr<CounterContent> counter, bool add)
804
appendContent(ContentData::create(counter));
808
rareNonInheritedData.access()->m_content = ContentData::create(counter);
811
void RenderStyle::setContent(QuoteType quote, bool add)
814
appendContent(ContentData::create(quote));
818
rareNonInheritedData.access()->m_content = ContentData::create(quote);
821
inline bool requireTransformOrigin(const Vector<RefPtr<TransformOperation> >& transformOperations, RenderStyle::ApplyTransformOrigin applyOrigin)
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
826
if (applyOrigin != RenderStyle::IncludeTransformOrigin)
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)
843
void RenderStyle::applyTransform(TransformationMatrix& transform, const LayoutSize& borderBoxSize, ApplyTransformOrigin applyOrigin) const
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);
848
const Vector<RefPtr<TransformOperation> >& transformOperations = rareNonInheritedData->m_transform->m_operations.operations();
849
bool applyTransformOrigin = requireTransformOrigin(transformOperations, applyOrigin);
851
if (applyTransformOrigin)
852
transform.translate3d(floatValueForLength(transformOriginX(), borderBoxSize.width()), floatValueForLength(transformOriginY(), borderBoxSize.height()), transformOriginZ());
854
unsigned size = transformOperations.size();
855
for (unsigned i = 0; i < size; ++i)
856
transformOperations[i]->apply(transform, borderBoxSize);
858
if (applyTransformOrigin)
859
transform.translate3d(-floatValueForLength(transformOriginX(), borderBoxSize.width()), -floatValueForLength(transformOriginY(), borderBoxSize.height()), -transformOriginZ());
862
void RenderStyle::applyTransform(TransformationMatrix& transform, const FloatRect& boundingBox, ApplyTransformOrigin applyOrigin) const
864
const Vector<RefPtr<TransformOperation> >& transformOperations = rareNonInheritedData->m_transform->m_operations.operations();
865
bool applyTransformOrigin = requireTransformOrigin(transformOperations, applyOrigin);
867
float offsetX = transformOriginX().type() == Percent ? boundingBox.x() : 0;
868
float offsetY = transformOriginY().type() == Percent ? boundingBox.y() : 0;
870
if (applyTransformOrigin) {
871
transform.translate3d(floatValueForLength(transformOriginX(), boundingBox.width()) + offsetX,
872
floatValueForLength(transformOriginY(), boundingBox.height()) + offsetY,
876
unsigned size = transformOperations.size();
877
for (unsigned i = 0; i < size; ++i)
878
transformOperations[i]->apply(transform, boundingBox.size());
880
if (applyTransformOrigin) {
881
transform.translate3d(-floatValueForLength(transformOriginX(), boundingBox.width()) - offsetX,
882
-floatValueForLength(transformOriginY(), boundingBox.height()) - offsetY,
883
-transformOriginZ());
887
void RenderStyle::setPageScaleTransform(float scale)
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));
898
void RenderStyle::setTextShadow(PassOwnPtr<ShadowData> shadowData, bool add)
900
ASSERT(!shadowData || (!shadowData->spread() && shadowData->style() == Normal));
902
StyleRareInheritedData* rareData = rareInheritedData.access();
904
rareData->textShadow = shadowData;
908
shadowData->setNext(rareData->textShadow.release());
909
rareData->textShadow = shadowData;
912
void RenderStyle::setBoxShadow(PassOwnPtr<ShadowData> shadowData, bool add)
914
StyleRareNonInheritedData* rareData = rareNonInheritedData.access();
916
rareData->m_boxShadow = shadowData;
920
shadowData->setNext(rareData->m_boxShadow.release());
921
rareData->m_boxShadow = shadowData;
924
static RoundedRect::Radii calcRadiiFor(const BorderData& border, IntSize size, RenderView* renderView)
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)));
937
static float calcConstraintScaleFor(const IntRect& rect, const RoundedRect::Radii& radii)
939
// Constrain corner radii using CSS3 rules:
940
// http://www.w3.org/TR/css3-background/#the-border-radius
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);
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);
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);
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);
969
StyleImage* RenderStyle::listStyleImage() const { return rareInheritedData->listStyleImage.get(); }
970
void RenderStyle::setListStyleImage(PassRefPtr<StyleImage> v)
972
if (rareInheritedData->listStyleImage != v)
973
rareInheritedData.access()->listStyleImage = v;
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) }
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) }
986
RoundedRect RenderStyle::getRoundedBorderFor(const LayoutRect& borderRect, RenderView* renderView, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
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);
998
RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
1000
bool horizontal = isHorizontalWritingMode();
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;
1007
return getRoundedInnerBorderFor(borderRect, topWidth, bottomWidth, leftWidth, rightWidth, includeLogicalLeftEdge, includeLogicalRightEdge);
1010
RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect,
1011
LayoutUnit topWidth, LayoutUnit bottomWidth, LayoutUnit leftWidth, LayoutUnit rightWidth, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
1013
LayoutRect innerRect(borderRect.x() + leftWidth,
1014
borderRect.y() + topWidth,
1015
borderRect.width() - leftWidth - rightWidth,
1016
borderRect.height() - topWidth - bottomWidth);
1018
RoundedRect roundedRect(pixelSnappedIntRect(innerRect));
1020
if (hasBorderRadius()) {
1021
RoundedRect::Radii radii = getRoundedBorderFor(borderRect).radii();
1022
radii.shrink(topWidth, bottomWidth, leftWidth, rightWidth);
1023
roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
1028
const CounterDirectiveMap* RenderStyle::counterDirectives() const
1030
return rareNonInheritedData->m_counterDirectives.get();
1033
CounterDirectiveMap& RenderStyle::accessCounterDirectives()
1035
OwnPtr<CounterDirectiveMap>& map = rareNonInheritedData.access()->m_counterDirectives;
1037
map = adoptPtr(new CounterDirectiveMap);
1041
const CounterDirectives RenderStyle::getCounterDirectives(const AtomicString& identifier) const
1043
if (const CounterDirectiveMap* directives = counterDirectives())
1044
return directives->get(identifier);
1045
return CounterDirectives();
1048
const AtomicString& RenderStyle::hyphenString() const
1050
ASSERT(hyphens() != HyphensNone);
1052
const AtomicString& hyphenationString = rareInheritedData.get()->hyphenationString;
1053
if (!hyphenationString.isNull())
1054
return hyphenationString;
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;
1062
const AtomicString& RenderStyle::textEmphasisMarkString() const
1064
switch (textEmphasisMark()) {
1065
case TextEmphasisMarkNone:
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;
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;
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;
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;
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;
1094
case TextEmphasisMarkAuto:
1095
ASSERT_NOT_REACHED();
1099
ASSERT_NOT_REACHED();
1103
#if ENABLE(DASHBOARD_SUPPORT)
1104
const Vector<StyleDashboardRegion>& RenderStyle::initialDashboardRegions()
1106
DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, emptyList, ());
1110
const Vector<StyleDashboardRegion>& RenderStyle::noneDashboardRegions()
1112
DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, noneList, ());
1113
static bool noneListInitialized = false;
1115
if (!noneListInitialized) {
1116
StyleDashboardRegion region;
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;
1130
void RenderStyle::adjustAnimations()
1132
AnimationList* animationList = rareNonInheritedData->m_animations.get();
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);
1144
if (animationList->isEmpty()) {
1149
// Repeat patterns into layers that don't have some properties set.
1150
animationList->fillUnsetProperties();
1153
void RenderStyle::adjustTransitions()
1155
AnimationList* transitionList = rareNonInheritedData->m_transitions.get();
1156
if (!transitionList)
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);
1167
if (transitionList->isEmpty()) {
1172
// Repeat patterns into layers that don't have some properties set.
1173
transitionList->fillUnsetProperties();
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()) {
1181
transitionList->remove(i);
1188
AnimationList* RenderStyle::accessAnimations()
1190
if (!rareNonInheritedData.access()->m_animations)
1191
rareNonInheritedData.access()->m_animations = adoptPtr(new AnimationList());
1192
return rareNonInheritedData->m_animations.get();
1195
AnimationList* RenderStyle::accessTransitions()
1197
if (!rareNonInheritedData.access()->m_transitions)
1198
rareNonInheritedData.access()->m_transitions = adoptPtr(new AnimationList());
1199
return rareNonInheritedData->m_transitions.get();
1202
const Animation* RenderStyle::transitionForProperty(CSSPropertyID property) const
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) {
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(); }
1222
int RenderStyle::wordSpacing() const { return inherited->font.wordSpacing(); }
1223
int RenderStyle::letterSpacing() const { return inherited->font.letterSpacing(); }
1225
bool RenderStyle::setFontDescription(const FontDescription& v)
1227
if (inherited->font.fontDescription() != v) {
1228
inherited.access()->font = Font(v, inherited->font.letterSpacing(), inherited->font.wordSpacing());
1234
Length RenderStyle::specifiedLineHeight() const { return inherited->line_height; }
1235
Length RenderStyle::lineHeight() const
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);
1249
void RenderStyle::setLineHeight(Length specifiedLineHeight) { SET_VAR(inherited, line_height, specifiedLineHeight); }
1251
int RenderStyle::computedLineHeight(RenderView* renderView) const
1253
const Length& lh = lineHeight();
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();
1260
return minimumValueForLength(lh, fontSize());
1262
if (lh.isViewportPercentage())
1263
return valueForLength(lh, 0, renderView);
1268
void RenderStyle::setWordSpacing(int v) { inherited.access()->font.setWordSpacing(v); }
1269
void RenderStyle::setLetterSpacing(int v) { inherited.access()->font.setLetterSpacing(v); }
1271
void RenderStyle::setFontSize(float size)
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).
1276
FontSelector* currentFontSelector = font().fontSelector();
1277
FontDescription desc(fontDescription());
1278
desc.setSpecifiedSize(size);
1279
desc.setComputedSize(size);
1281
#if ENABLE(TEXT_AUTOSIZING)
1282
float multiplier = textAutosizingMultiplier();
1283
if (multiplier > 1) {
1284
desc.setComputedSize(TextAutosizer::computeAutosizedFontSize(size, multiplier));
1288
setFontDescription(desc);
1289
font().update(currentFontSelector);
1292
void RenderStyle::getShadowExtent(const ShadowData* shadow, LayoutUnit &top, LayoutUnit &right, LayoutUnit &bottom, LayoutUnit &left) const
1299
for ( ; shadow; shadow = shadow->next()) {
1300
if (shadow->style() == Inset)
1302
int blurAndSpread = shadow->blur() + shadow->spread();
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);
1311
LayoutBoxExtent RenderStyle::getShadowInsetExtent(const ShadowData* shadow) const
1314
LayoutUnit right = 0;
1315
LayoutUnit bottom = 0;
1316
LayoutUnit left = 0;
1318
for ( ; shadow; shadow = shadow->next()) {
1319
if (shadow->style() == Normal)
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);
1328
return LayoutBoxExtent(top, right, bottom, left);
1331
void RenderStyle::getShadowHorizontalExtent(const ShadowData* shadow, LayoutUnit &left, LayoutUnit &right) const
1336
for ( ; shadow; shadow = shadow->next()) {
1337
if (shadow->style() == Inset)
1339
int blurAndSpread = shadow->blur() + shadow->spread();
1341
left = min<LayoutUnit>(left, shadow->x() - blurAndSpread);
1342
right = max<LayoutUnit>(right, shadow->x() + blurAndSpread);
1346
void RenderStyle::getShadowVerticalExtent(const ShadowData* shadow, LayoutUnit &top, LayoutUnit &bottom) const
1351
for ( ; shadow; shadow = shadow->next()) {
1352
if (shadow->style() == Inset)
1354
int blurAndSpread = shadow->blur() + shadow->spread();
1356
top = min<LayoutUnit>(top, shadow->y() - blurAndSpread);
1357
bottom = max<LayoutUnit>(bottom, shadow->y() + blurAndSpread);
1361
Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) const
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();
1372
case CSSPropertyBorderRightColor:
1373
result = visitedLink ? visitedLinkBorderRightColor() : borderRightColor();
1374
borderStyle = borderRightStyle();
1376
case CSSPropertyBorderTopColor:
1377
result = visitedLink ? visitedLinkBorderTopColor() : borderTopColor();
1378
borderStyle = borderTopStyle();
1380
case CSSPropertyBorderBottomColor:
1381
result = visitedLink ? visitedLinkBorderBottomColor() : borderBottomColor();
1382
borderStyle = borderBottomStyle();
1384
case CSSPropertyColor:
1385
result = visitedLink ? visitedLinkColor() : color();
1387
case CSSPropertyOutlineColor:
1388
result = visitedLink ? visitedLinkOutlineColor() : outlineColor();
1390
case CSSPropertyWebkitColumnRuleColor:
1391
result = visitedLink ? visitedLinkColumnRuleColor() : columnRuleColor();
1393
case CSSPropertyWebkitTextEmphasisColor:
1394
result = visitedLink ? visitedLinkTextEmphasisColor() : textEmphasisColor();
1396
case CSSPropertyWebkitTextFillColor:
1397
result = visitedLink ? visitedLinkTextFillColor() : textFillColor();
1399
case CSSPropertyWebkitTextStrokeColor:
1400
result = visitedLink ? visitedLinkTextStrokeColor() : textStrokeColor();
1403
ASSERT_NOT_REACHED();
1407
if (!result.isValid()) {
1408
if (!visitedLink && (borderStyle == INSET || borderStyle == OUTSET || borderStyle == RIDGE || borderStyle == GROOVE))
1409
result.setRGB(238, 238, 238);
1411
result = visitedLink ? visitedLinkColor() : color();
1416
Color RenderStyle::visitedDependentColor(int colorProperty) const
1418
Color unvisitedColor = colorIncludingFallback(colorProperty, false);
1419
if (insideLink() != InsideVisitedLink)
1420
return unvisitedColor;
1422
Color visitedColor = colorIncludingFallback(colorProperty, true);
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;
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());
1436
const BorderValue& RenderStyle::borderBefore() const
1438
switch (writingMode()) {
1439
case TopToBottomWritingMode:
1441
case BottomToTopWritingMode:
1442
return borderBottom();
1443
case LeftToRightWritingMode:
1444
return borderLeft();
1445
case RightToLeftWritingMode:
1446
return borderRight();
1448
ASSERT_NOT_REACHED();
1452
const BorderValue& RenderStyle::borderAfter() const
1454
switch (writingMode()) {
1455
case TopToBottomWritingMode:
1456
return borderBottom();
1457
case BottomToTopWritingMode:
1459
case LeftToRightWritingMode:
1460
return borderRight();
1461
case RightToLeftWritingMode:
1462
return borderLeft();
1464
ASSERT_NOT_REACHED();
1465
return borderBottom();
1468
const BorderValue& RenderStyle::borderStart() const
1470
if (isHorizontalWritingMode())
1471
return isLeftToRightDirection() ? borderLeft() : borderRight();
1472
return isLeftToRightDirection() ? borderTop() : borderBottom();
1475
const BorderValue& RenderStyle::borderEnd() const
1477
if (isHorizontalWritingMode())
1478
return isLeftToRightDirection() ? borderRight() : borderLeft();
1479
return isLeftToRightDirection() ? borderBottom() : borderTop();
1482
unsigned short RenderStyle::borderBeforeWidth() const
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();
1494
ASSERT_NOT_REACHED();
1495
return borderTopWidth();
1498
unsigned short RenderStyle::borderAfterWidth() const
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();
1510
ASSERT_NOT_REACHED();
1511
return borderBottomWidth();
1514
unsigned short RenderStyle::borderStartWidth() const
1516
if (isHorizontalWritingMode())
1517
return isLeftToRightDirection() ? borderLeftWidth() : borderRightWidth();
1518
return isLeftToRightDirection() ? borderTopWidth() : borderBottomWidth();
1521
unsigned short RenderStyle::borderEndWidth() const
1523
if (isHorizontalWritingMode())
1524
return isLeftToRightDirection() ? borderRightWidth() : borderLeftWidth();
1525
return isLeftToRightDirection() ? borderBottomWidth() : borderTopWidth();
1528
void RenderStyle::setMarginStart(Length margin)
1530
if (isHorizontalWritingMode()) {
1531
if (isLeftToRightDirection())
1532
setMarginLeft(margin);
1534
setMarginRight(margin);
1536
if (isLeftToRightDirection())
1537
setMarginTop(margin);
1539
setMarginBottom(margin);
1543
void RenderStyle::setMarginEnd(Length margin)
1545
if (isHorizontalWritingMode()) {
1546
if (isLeftToRightDirection())
1547
setMarginRight(margin);
1549
setMarginLeft(margin);
1551
if (isLeftToRightDirection())
1552
setMarginBottom(margin);
1554
setMarginTop(margin);
1558
TextEmphasisMark RenderStyle::textEmphasisMark() const
1560
TextEmphasisMark mark = static_cast<TextEmphasisMark>(rareInheritedData->textEmphasisMark);
1561
if (mark != TextEmphasisMarkAuto)
1564
if (isHorizontalWritingMode())
1565
return TextEmphasisMarkDot;
1567
return TextEmphasisMarkSesame;
1570
#if ENABLE(TOUCH_EVENTS)
1571
Color RenderStyle::initialTapHighlightColor()
1573
return RenderTheme::tapHighlightColor();
1577
LayoutBoxExtent RenderStyle::imageOutsets(const NinePieceImage& image) const
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()));
1585
void RenderStyle::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
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);
1600
info.addMember(m_svgStyle);
1604
} // namespace WebCore