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