OLD | NEW |
| (Empty) |
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/layout/style/LayoutStyle.h" | |
25 | |
26 #include "core/css/resolver/StyleResolver.h" | |
27 #include "core/layout/LayoutTheme.h" | |
28 #include "core/layout/TextAutosizer.h" | |
29 #include "core/layout/style/AppliedTextDecoration.h" | |
30 #include "core/layout/style/BorderEdge.h" | |
31 #include "core/layout/style/ContentData.h" | |
32 #include "core/layout/style/DataEquivalency.h" | |
33 #include "core/layout/style/LayoutStyleConstants.h" | |
34 #include "core/layout/style/PathStyleMotionPath.h" | |
35 #include "core/layout/style/QuotesData.h" | |
36 #include "core/layout/style/ShadowList.h" | |
37 #include "core/layout/style/StyleImage.h" | |
38 #include "core/layout/style/StyleInheritedData.h" | |
39 #include "platform/LengthFunctions.h" | |
40 #include "platform/RuntimeEnabledFeatures.h" | |
41 #include "platform/fonts/Font.h" | |
42 #include "platform/fonts/FontSelector.h" | |
43 #include "platform/geometry/FloatRoundedRect.h" | |
44 #include "wtf/MathExtras.h" | |
45 | |
46 #include <algorithm> | |
47 | |
48 namespace blink { | |
49 | |
50 struct SameSizeAsBorderValue { | |
51 RGBA32 m_color; | |
52 unsigned m_width; | |
53 }; | |
54 | |
55 static_assert(sizeof(BorderValue) == sizeof(SameSizeAsBorderValue), "BorderValue
should stay small"); | |
56 | |
57 struct SameSizeAsLayoutStyle : public RefCounted<SameSizeAsLayoutStyle> { | |
58 void* dataRefs[7]; | |
59 void* ownPtrs[1]; | |
60 void* dataRefSvgStyle; | |
61 | |
62 struct InheritedFlags { | |
63 unsigned m_bitfields[2]; | |
64 } inherited_flags; | |
65 | |
66 struct NonInheritedFlags { | |
67 unsigned m_bitfields[2]; | |
68 } noninherited_flags; | |
69 }; | |
70 | |
71 static_assert(sizeof(LayoutStyle) == sizeof(SameSizeAsLayoutStyle), "LayoutStyle
should stay small"); | |
72 | |
73 PassRefPtr<LayoutStyle> LayoutStyle::create() | |
74 { | |
75 return adoptRef(new LayoutStyle()); | |
76 } | |
77 | |
78 PassRefPtr<LayoutStyle> LayoutStyle::createInitialStyle() | |
79 { | |
80 return adoptRef(new LayoutStyle(InitialStyle)); | |
81 } | |
82 | |
83 PassRefPtr<LayoutStyle> LayoutStyle::createAnonymousStyleWithDisplay(const Layou
tStyle& parentStyle, EDisplay display) | |
84 { | |
85 RefPtr<LayoutStyle> newStyle = LayoutStyle::create(); | |
86 newStyle->inheritFrom(parentStyle); | |
87 newStyle->inheritUnicodeBidiFrom(parentStyle); | |
88 newStyle->setDisplay(display); | |
89 return newStyle; | |
90 } | |
91 | |
92 PassRefPtr<LayoutStyle> LayoutStyle::clone(const LayoutStyle& other) | |
93 { | |
94 return adoptRef(new LayoutStyle(other)); | |
95 } | |
96 | |
97 ALWAYS_INLINE LayoutStyle::LayoutStyle() | |
98 : m_box(initialStyle()->m_box) | |
99 , visual(initialStyle()->visual) | |
100 , m_background(initialStyle()->m_background) | |
101 , surround(initialStyle()->surround) | |
102 , rareNonInheritedData(initialStyle()->rareNonInheritedData) | |
103 , rareInheritedData(initialStyle()->rareInheritedData) | |
104 , inherited(initialStyle()->inherited) | |
105 , m_svgStyle(initialStyle()->m_svgStyle) | |
106 { | |
107 setBitDefaults(); // Would it be faster to copy this from the default style? | |
108 static_assert((sizeof(InheritedFlags) <= 8), "InheritedFlags should not grow
"); | |
109 static_assert((sizeof(NonInheritedFlags) <= 8), "NonInheritedFlags should no
t grow"); | |
110 } | |
111 | |
112 ALWAYS_INLINE LayoutStyle::LayoutStyle(InitialStyleTag) | |
113 { | |
114 setBitDefaults(); | |
115 | |
116 m_box.init(); | |
117 visual.init(); | |
118 m_background.init(); | |
119 surround.init(); | |
120 rareNonInheritedData.init(); | |
121 rareNonInheritedData.access()->m_deprecatedFlexibleBox.init(); | |
122 rareNonInheritedData.access()->m_flexibleBox.init(); | |
123 rareNonInheritedData.access()->m_multiCol.init(); | |
124 rareNonInheritedData.access()->m_transform.init(); | |
125 rareNonInheritedData.access()->m_willChange.init(); | |
126 rareNonInheritedData.access()->m_filter.init(); | |
127 rareNonInheritedData.access()->m_grid.init(); | |
128 rareNonInheritedData.access()->m_gridItem.init(); | |
129 rareInheritedData.init(); | |
130 inherited.init(); | |
131 m_svgStyle.init(); | |
132 } | |
133 | |
134 ALWAYS_INLINE LayoutStyle::LayoutStyle(const LayoutStyle& o) | |
135 : RefCounted<LayoutStyle>() | |
136 , m_box(o.m_box) | |
137 , visual(o.visual) | |
138 , m_background(o.m_background) | |
139 , surround(o.surround) | |
140 , rareNonInheritedData(o.rareNonInheritedData) | |
141 , rareInheritedData(o.rareInheritedData) | |
142 , inherited(o.inherited) | |
143 , m_svgStyle(o.m_svgStyle) | |
144 , inherited_flags(o.inherited_flags) | |
145 , noninherited_flags(o.noninherited_flags) | |
146 { | |
147 } | |
148 | |
149 static StyleRecalcChange diffPseudoStyles(const LayoutStyle& oldStyle, const Lay
outStyle& newStyle) | |
150 { | |
151 // If the pseudoStyles have changed, we want any StyleRecalcChange that is n
ot NoChange | |
152 // because setStyle will do the right thing with anything else. | |
153 if (!oldStyle.hasAnyPublicPseudoStyles()) | |
154 return NoChange; | |
155 for (PseudoId pseudoId = FIRST_PUBLIC_PSEUDOID; pseudoId < FIRST_INTERNAL_PS
EUDOID; pseudoId = static_cast<PseudoId>(pseudoId + 1)) { | |
156 if (!oldStyle.hasPseudoStyle(pseudoId)) | |
157 continue; | |
158 const LayoutStyle* newPseudoStyle = newStyle.getCachedPseudoStyle(pseudo
Id); | |
159 if (!newPseudoStyle) | |
160 return NoInherit; | |
161 const LayoutStyle* oldPseudoStyle = oldStyle.getCachedPseudoStyle(pseudo
Id); | |
162 if (oldPseudoStyle && *oldPseudoStyle != *newPseudoStyle) | |
163 return NoInherit; | |
164 } | |
165 return NoChange; | |
166 } | |
167 | |
168 StyleRecalcChange LayoutStyle::stylePropagationDiff(const LayoutStyle* oldStyle,
const LayoutStyle* newStyle) | |
169 { | |
170 if ((!oldStyle && newStyle) || (oldStyle && !newStyle)) | |
171 return Reattach; | |
172 | |
173 if (!oldStyle && !newStyle) | |
174 return NoChange; | |
175 | |
176 if (oldStyle->display() != newStyle->display() | |
177 || oldStyle->hasPseudoStyle(FIRST_LETTER) != newStyle->hasPseudoStyle(FI
RST_LETTER) | |
178 || oldStyle->columnSpan() != newStyle->columnSpan() | |
179 || !oldStyle->contentDataEquivalent(newStyle) | |
180 || oldStyle->hasTextCombine() != newStyle->hasTextCombine() | |
181 || oldStyle->justifyItems() != newStyle->justifyItems() | |
182 || oldStyle->alignItems() != newStyle->alignItems()) | |
183 return Reattach; | |
184 | |
185 if (oldStyle->inheritedNotEqual(*newStyle)) | |
186 return Inherit; | |
187 | |
188 if (*oldStyle == *newStyle) | |
189 return diffPseudoStyles(*oldStyle, *newStyle); | |
190 | |
191 if (oldStyle->hasExplicitlyInheritedProperties()) | |
192 return Inherit; | |
193 | |
194 return NoInherit; | |
195 } | |
196 | |
197 ItemPosition LayoutStyle::resolveAlignment(const LayoutStyle& parentStyle, const
LayoutStyle& childStyle, ItemPosition resolvedAutoPositionForLayoutObject) | |
198 { | |
199 // The auto keyword computes to the parent's align-items computed value, or
to "stretch", if not set or "auto". | |
200 if (childStyle.alignSelf() == ItemPositionAuto) | |
201 return (parentStyle.alignItems() == ItemPositionAuto) ? resolvedAutoPosi
tionForLayoutObject : parentStyle.alignItems(); | |
202 return childStyle.alignSelf(); | |
203 } | |
204 | |
205 ItemPosition LayoutStyle::resolveJustification(const LayoutStyle& parentStyle, c
onst LayoutStyle& childStyle, ItemPosition resolvedAutoPositionForLayoutObject) | |
206 { | |
207 if (childStyle.justifySelf() == ItemPositionAuto) | |
208 return (parentStyle.justifyItems() == ItemPositionAuto) ? resolvedAutoPo
sitionForLayoutObject : parentStyle.justifyItems(); | |
209 return childStyle.justifySelf(); | |
210 } | |
211 | |
212 void LayoutStyle::inheritFrom(const LayoutStyle& inheritParent, IsAtShadowBounda
ry isAtShadowBoundary) | |
213 { | |
214 if (isAtShadowBoundary == AtShadowBoundary) { | |
215 // Even if surrounding content is user-editable, shadow DOM should act a
s a single unit, and not necessarily be editable | |
216 EUserModify currentUserModify = userModify(); | |
217 rareInheritedData = inheritParent.rareInheritedData; | |
218 setUserModify(currentUserModify); | |
219 } else { | |
220 rareInheritedData = inheritParent.rareInheritedData; | |
221 } | |
222 inherited = inheritParent.inherited; | |
223 inherited_flags = inheritParent.inherited_flags; | |
224 if (m_svgStyle != inheritParent.m_svgStyle) | |
225 m_svgStyle.access()->inheritFrom(inheritParent.m_svgStyle.get()); | |
226 } | |
227 | |
228 void LayoutStyle::copyNonInheritedFromCached(const LayoutStyle& other) | |
229 { | |
230 m_box = other.m_box; | |
231 visual = other.visual; | |
232 m_background = other.m_background; | |
233 surround = other.surround; | |
234 rareNonInheritedData = other.rareNonInheritedData; | |
235 | |
236 // The flags are copied one-by-one because noninherited_flags contains a bun
ch of stuff other than real style data. | |
237 // See comments for each skipped flag below. | |
238 noninherited_flags.effectiveDisplay = other.noninherited_flags.effectiveDisp
lay; | |
239 noninherited_flags.originalDisplay = other.noninherited_flags.originalDispla
y; | |
240 noninherited_flags.overflowX = other.noninherited_flags.overflowX; | |
241 noninherited_flags.overflowY = other.noninherited_flags.overflowY; | |
242 noninherited_flags.verticalAlign = other.noninherited_flags.verticalAlign; | |
243 noninherited_flags.clear = other.noninherited_flags.clear; | |
244 noninherited_flags.position = other.noninherited_flags.position; | |
245 noninherited_flags.floating = other.noninherited_flags.floating; | |
246 noninherited_flags.tableLayout = other.noninherited_flags.tableLayout; | |
247 noninherited_flags.unicodeBidi = other.noninherited_flags.unicodeBidi; | |
248 noninherited_flags.hasViewportUnits = other.noninherited_flags.hasViewportUn
its; | |
249 noninherited_flags.pageBreakBefore = other.noninherited_flags.pageBreakBefor
e; | |
250 noninherited_flags.pageBreakAfter = other.noninherited_flags.pageBreakAfter; | |
251 noninherited_flags.pageBreakInside = other.noninherited_flags.pageBreakInsid
e; | |
252 | |
253 // Correctly set during selector matching: | |
254 // noninherited_flags.styleType | |
255 // noninherited_flags.pseudoBits | |
256 | |
257 // Set correctly while computing style for children: | |
258 // noninherited_flags.explicitInheritance | |
259 | |
260 // unique() styles are not cacheable. | |
261 ASSERT(!other.noninherited_flags.unique); | |
262 | |
263 // The following flags are set during matching before we decide that we get
a | |
264 // match in the MatchedPropertiesCache which in turn calls this method. The | |
265 // reason why we don't copy these flags is that they're already correctly se
t | |
266 // and that they may differ between elements which have the same set of matc
hed | |
267 // properties. For instance, given the rule: | |
268 // | |
269 // :-webkit-any(:hover, :focus) { background-color: green }" | |
270 // | |
271 // A hovered element, and a focused element may use the same cached matched | |
272 // properties here, but the affectedBy flags will be set differently based o
n | |
273 // the matching order of the :-webkit-any components. | |
274 // | |
275 // noninherited_flags.emptyState | |
276 // noninherited_flags.affectedByFocus | |
277 // noninherited_flags.affectedByHover | |
278 // noninherited_flags.affectedByActive | |
279 // noninherited_flags.affectedByDrag | |
280 // noninherited_flags.isLink | |
281 | |
282 if (m_svgStyle != other.m_svgStyle) | |
283 m_svgStyle.access()->copyNonInheritedFromCached(other.m_svgStyle.get()); | |
284 ASSERT(zoom() == initialZoom()); | |
285 } | |
286 | |
287 bool LayoutStyle::operator==(const LayoutStyle& o) const | |
288 { | |
289 // compare everything except the pseudoStyle pointer | |
290 return inherited_flags == o.inherited_flags | |
291 && noninherited_flags == o.noninherited_flags | |
292 && m_box == o.m_box | |
293 && visual == o.visual | |
294 && m_background == o.m_background | |
295 && surround == o.surround | |
296 && rareNonInheritedData == o.rareNonInheritedData | |
297 && rareInheritedData == o.rareInheritedData | |
298 && inherited == o.inherited | |
299 && m_svgStyle == o.m_svgStyle; | |
300 } | |
301 | |
302 bool LayoutStyle::isStyleAvailable() const | |
303 { | |
304 return this != StyleResolver::styleNotYetAvailable(); | |
305 } | |
306 | |
307 bool LayoutStyle::hasUniquePseudoStyle() const | |
308 { | |
309 if (!m_cachedPseudoStyles || styleType() != NOPSEUDO) | |
310 return false; | |
311 | |
312 for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) { | |
313 const LayoutStyle& pseudoStyle = *m_cachedPseudoStyles->at(i); | |
314 if (pseudoStyle.unique()) | |
315 return true; | |
316 } | |
317 | |
318 return false; | |
319 } | |
320 | |
321 LayoutStyle* LayoutStyle::getCachedPseudoStyle(PseudoId pid) const | |
322 { | |
323 if (!m_cachedPseudoStyles || !m_cachedPseudoStyles->size()) | |
324 return 0; | |
325 | |
326 if (styleType() != NOPSEUDO) | |
327 return 0; | |
328 | |
329 for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) { | |
330 LayoutStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get(); | |
331 if (pseudoStyle->styleType() == pid) | |
332 return pseudoStyle; | |
333 } | |
334 | |
335 return 0; | |
336 } | |
337 | |
338 LayoutStyle* LayoutStyle::addCachedPseudoStyle(PassRefPtr<LayoutStyle> pseudo) | |
339 { | |
340 if (!pseudo) | |
341 return 0; | |
342 | |
343 ASSERT(pseudo->styleType() > NOPSEUDO); | |
344 | |
345 LayoutStyle* result = pseudo.get(); | |
346 | |
347 if (!m_cachedPseudoStyles) | |
348 m_cachedPseudoStyles = adoptPtr(new PseudoStyleCache); | |
349 | |
350 m_cachedPseudoStyles->append(pseudo); | |
351 | |
352 return result; | |
353 } | |
354 | |
355 void LayoutStyle::removeCachedPseudoStyle(PseudoId pid) | |
356 { | |
357 if (!m_cachedPseudoStyles) | |
358 return; | |
359 for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) { | |
360 LayoutStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get(); | |
361 if (pseudoStyle->styleType() == pid) { | |
362 m_cachedPseudoStyles->remove(i); | |
363 return; | |
364 } | |
365 } | |
366 } | |
367 | |
368 bool LayoutStyle::inheritedNotEqual(const LayoutStyle& other) const | |
369 { | |
370 return inherited_flags != other.inherited_flags | |
371 || inherited != other.inherited | |
372 || font().loadingCustomFonts() != other.font().loadingCustomFonts() | |
373 || m_svgStyle->inheritedNotEqual(other.m_svgStyle.get()) | |
374 || rareInheritedData != other.rareInheritedData; | |
375 } | |
376 | |
377 bool LayoutStyle::inheritedDataShared(const LayoutStyle& other) const | |
378 { | |
379 // This is a fast check that only looks if the data structures are shared. | |
380 return inherited_flags == other.inherited_flags | |
381 && inherited.get() == other.inherited.get() | |
382 && m_svgStyle.get() == other.m_svgStyle.get() | |
383 && rareInheritedData.get() == other.rareInheritedData.get(); | |
384 } | |
385 | |
386 static bool dependenceOnContentHeightHasChanged(const LayoutStyle& a, const Layo
utStyle& b) | |
387 { | |
388 // If top or bottom become auto/non-auto then it means we either have to sol
ve height based | |
389 // on the content or stop doing so (http://www.w3.org/TR/CSS2/visudet.html#a
bs-non-replaced-height) | |
390 // - either way requires a layout. | |
391 return a.logicalTop().isAuto() != b.logicalTop().isAuto() || a.logicalBottom
().isAuto() != b.logicalBottom().isAuto(); | |
392 } | |
393 | |
394 StyleDifference LayoutStyle::visualInvalidationDiff(const LayoutStyle& other) co
nst | |
395 { | |
396 // Note, we use .get() on each DataRef below because DataRef::operator== wil
l do a deep | |
397 // compare, which is duplicate work when we're going to compare each propert
y inside | |
398 // this function anyway. | |
399 | |
400 StyleDifference diff; | |
401 if (m_svgStyle.get() != other.m_svgStyle.get()) | |
402 diff = m_svgStyle->diff(other.m_svgStyle.get()); | |
403 | |
404 if ((!diff.needsFullLayout() || !diff.needsPaintInvalidation()) && diffNeeds
FullLayoutAndPaintInvalidation(other)) { | |
405 diff.setNeedsFullLayout(); | |
406 diff.setNeedsPaintInvalidationObject(); | |
407 } | |
408 | |
409 if (!diff.needsFullLayout() && diffNeedsFullLayout(other)) | |
410 diff.setNeedsFullLayout(); | |
411 | |
412 if (!diff.needsFullLayout() && surround->margin != other.surround->margin) { | |
413 // Relative-positioned elements collapse their margins so need a full la
yout. | |
414 if (position() == AbsolutePosition || position() == FixedPosition) | |
415 diff.setNeedsPositionedMovementLayout(); | |
416 else | |
417 diff.setNeedsFullLayout(); | |
418 } | |
419 | |
420 if (!diff.needsFullLayout() && position() != StaticPosition && surround->off
set != other.surround->offset) { | |
421 // Optimize for the case where a positioned layer is moving but not chan
ging size. | |
422 if (dependenceOnContentHeightHasChanged(*this, other)) | |
423 diff.setNeedsFullLayout(); | |
424 else | |
425 diff.setNeedsPositionedMovementLayout(); | |
426 } | |
427 | |
428 if (diffNeedsPaintInvalidationLayer(other)) | |
429 diff.setNeedsPaintInvalidationLayer(); | |
430 else if (diffNeedsPaintInvalidationObject(other)) | |
431 diff.setNeedsPaintInvalidationObject(); | |
432 | |
433 updatePropertySpecificDifferences(other, diff); | |
434 | |
435 // Cursors are not checked, since they will be set appropriately in response
to mouse events, | |
436 // so they don't need to cause any paint invalidation or layout. | |
437 | |
438 // Animations don't need to be checked either. We always set the new style o
n the layoutObject, so we will get a chance to fire off | |
439 // the resulting transition properly. | |
440 | |
441 return diff; | |
442 } | |
443 | |
444 bool LayoutStyle::diffNeedsFullLayoutAndPaintInvalidation(const LayoutStyle& oth
er) const | |
445 { | |
446 // FIXME: Not all cases in this method need both full layout and paint inval
idation. | |
447 // Should move cases into diffNeedsFullLayout() if | |
448 // - don't need paint invalidation at all; | |
449 // - or the layoutObject knows how to exactly invalidate paints caused by th
e layout change | |
450 // instead of forced full paint invalidation. | |
451 | |
452 if (surround.get() != other.surround.get()) { | |
453 // If our border widths change, then we need to layout. Other changes to
borders only necessitate a paint invalidation. | |
454 if (borderLeftWidth() != other.borderLeftWidth() | |
455 || borderTopWidth() != other.borderTopWidth() | |
456 || borderBottomWidth() != other.borderBottomWidth() | |
457 || borderRightWidth() != other.borderRightWidth()) | |
458 return true; | |
459 } | |
460 | |
461 if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) { | |
462 if (rareNonInheritedData->m_appearance != other.rareNonInheritedData->m_
appearance | |
463 || rareNonInheritedData->marginBeforeCollapse != other.rareNonInheri
tedData->marginBeforeCollapse | |
464 || rareNonInheritedData->marginAfterCollapse != other.rareNonInherit
edData->marginAfterCollapse | |
465 || rareNonInheritedData->lineClamp != other.rareNonInheritedData->li
neClamp | |
466 || rareNonInheritedData->textOverflow != other.rareNonInheritedData-
>textOverflow | |
467 || rareNonInheritedData->m_wrapFlow != other.rareNonInheritedData->m
_wrapFlow | |
468 || rareNonInheritedData->m_wrapThrough != other.rareNonInheritedData
->m_wrapThrough | |
469 || rareNonInheritedData->m_shapeMargin != other.rareNonInheritedData
->m_shapeMargin | |
470 || rareNonInheritedData->m_order != other.rareNonInheritedData->m_or
der | |
471 || rareNonInheritedData->m_justifyContent != other.rareNonInheritedD
ata->m_justifyContent | |
472 || rareNonInheritedData->m_grid.get() != other.rareNonInheritedData-
>m_grid.get() | |
473 || rareNonInheritedData->m_gridItem.get() != other.rareNonInheritedD
ata->m_gridItem.get() | |
474 || rareNonInheritedData->m_textCombine != other.rareNonInheritedData
->m_textCombine | |
475 || rareNonInheritedData->hasFilters() != other.rareNonInheritedData-
>hasFilters()) | |
476 return true; | |
477 | |
478 if (rareNonInheritedData->m_deprecatedFlexibleBox.get() != other.rareNon
InheritedData->m_deprecatedFlexibleBox.get() | |
479 && *rareNonInheritedData->m_deprecatedFlexibleBox.get() != *other.ra
reNonInheritedData->m_deprecatedFlexibleBox.get()) | |
480 return true; | |
481 | |
482 if (rareNonInheritedData->m_flexibleBox.get() != other.rareNonInheritedD
ata->m_flexibleBox.get() | |
483 && *rareNonInheritedData->m_flexibleBox.get() != *other.rareNonInher
itedData->m_flexibleBox.get()) | |
484 return true; | |
485 | |
486 // FIXME: We should add an optimized form of layout that just recomputes
visual overflow. | |
487 if (!rareNonInheritedData->shadowDataEquivalent(*other.rareNonInheritedD
ata.get())) | |
488 return true; | |
489 | |
490 if (!rareNonInheritedData->reflectionDataEquivalent(*other.rareNonInheri
tedData.get())) | |
491 return true; | |
492 | |
493 if (rareNonInheritedData->m_multiCol.get() != other.rareNonInheritedData
->m_multiCol.get() | |
494 && *rareNonInheritedData->m_multiCol.get() != *other.rareNonInherite
dData->m_multiCol.get()) | |
495 return true; | |
496 | |
497 // If the counter directives change, trigger a relayout to re-calculate
counter values and rebuild the counter node tree. | |
498 const CounterDirectiveMap* mapA = rareNonInheritedData->m_counterDirecti
ves.get(); | |
499 const CounterDirectiveMap* mapB = other.rareNonInheritedData->m_counterD
irectives.get(); | |
500 if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB))) | |
501 return true; | |
502 | |
503 // We only need do layout for opacity changes if adding or losing opacit
y could trigger a change | |
504 // in us being a stacking context. | |
505 if (hasAutoZIndex() != other.hasAutoZIndex() && rareNonInheritedData->ha
sOpacity() != other.rareNonInheritedData->hasOpacity()) { | |
506 // FIXME: We would like to use SimplifiedLayout here, but we can't q
uite do that yet. | |
507 // We need to make sure SimplifiedLayout can operate correctly on La
youtInlines (we will need | |
508 // to add a selfNeedsSimplifiedLayout bit in order to not get confus
ed and taint every line). | |
509 // In addition we need to solve the floating object issue when layer
s come and go. Right now | |
510 // a full layout is necessary to keep floating object lists sane. | |
511 return true; | |
512 } | |
513 } | |
514 | |
515 if (rareInheritedData.get() != other.rareInheritedData.get()) { | |
516 if (rareInheritedData->highlight != other.rareInheritedData->highlight | |
517 || rareInheritedData->indent != other.rareInheritedData->indent | |
518 || rareInheritedData->m_textAlignLast != other.rareInheritedData->m_
textAlignLast | |
519 || rareInheritedData->m_textIndentLine != other.rareInheritedData->m
_textIndentLine | |
520 || rareInheritedData->m_effectiveZoom != other.rareInheritedData->m_
effectiveZoom | |
521 || rareInheritedData->wordBreak != other.rareInheritedData->wordBrea
k | |
522 || rareInheritedData->overflowWrap != other.rareInheritedData->overf
lowWrap | |
523 || rareInheritedData->lineBreak != other.rareInheritedData->lineBrea
k | |
524 || rareInheritedData->textSecurity != other.rareInheritedData->textS
ecurity | |
525 || rareInheritedData->hyphens != other.rareInheritedData->hyphens | |
526 || rareInheritedData->hyphenationLimitBefore != other.rareInheritedD
ata->hyphenationLimitBefore | |
527 || rareInheritedData->hyphenationLimitAfter != other.rareInheritedDa
ta->hyphenationLimitAfter | |
528 || rareInheritedData->hyphenationString != other.rareInheritedData->
hyphenationString | |
529 || rareInheritedData->locale != other.rareInheritedData->locale | |
530 || rareInheritedData->m_rubyPosition != other.rareInheritedData->m_r
ubyPosition | |
531 || rareInheritedData->textEmphasisMark != other.rareInheritedData->t
extEmphasisMark | |
532 || rareInheritedData->textEmphasisPosition != other.rareInheritedDat
a->textEmphasisPosition | |
533 || rareInheritedData->textEmphasisCustomMark != other.rareInheritedD
ata->textEmphasisCustomMark | |
534 || rareInheritedData->m_textJustify != other.rareInheritedData->m_te
xtJustify | |
535 || rareInheritedData->m_textOrientation != other.rareInheritedData->
m_textOrientation | |
536 || rareInheritedData->m_tabSize != other.rareInheritedData->m_tabSiz
e | |
537 || rareInheritedData->m_lineBoxContain != other.rareInheritedData->m
_lineBoxContain | |
538 || rareInheritedData->listStyleImage != other.rareInheritedData->lis
tStyleImage | |
539 || rareInheritedData->textStrokeWidth != other.rareInheritedData->te
xtStrokeWidth) | |
540 return true; | |
541 | |
542 if (!rareInheritedData->shadowDataEquivalent(*other.rareInheritedData.ge
t())) | |
543 return true; | |
544 | |
545 if (!rareInheritedData->quotesDataEquivalent(*other.rareInheritedData.ge
t())) | |
546 return true; | |
547 } | |
548 | |
549 if (inherited->textAutosizingMultiplier != other.inherited->textAutosizingMu
ltiplier) | |
550 return true; | |
551 | |
552 if (inherited->font.loadingCustomFonts() != other.inherited->font.loadingCus
tomFonts()) | |
553 return true; | |
554 | |
555 if (inherited.get() != other.inherited.get()) { | |
556 if (inherited->line_height != other.inherited->line_height | |
557 || inherited->font != other.inherited->font | |
558 || inherited->horizontal_border_spacing != other.inherited->horizont
al_border_spacing | |
559 || inherited->vertical_border_spacing != other.inherited->vertical_b
order_spacing) | |
560 return true; | |
561 } | |
562 | |
563 if (inherited_flags._box_direction != other.inherited_flags._box_direction | |
564 || inherited_flags.m_rtlOrdering != other.inherited_flags.m_rtlOrdering | |
565 || inherited_flags._text_align != other.inherited_flags._text_align | |
566 || inherited_flags._text_transform != other.inherited_flags._text_transf
orm | |
567 || inherited_flags._direction != other.inherited_flags._direction | |
568 || inherited_flags._white_space != other.inherited_flags._white_space | |
569 || inherited_flags.m_writingMode != other.inherited_flags.m_writingMode) | |
570 return true; | |
571 | |
572 if (noninherited_flags.overflowX != other.noninherited_flags.overflowX | |
573 || noninherited_flags.overflowY != other.noninherited_flags.overflowY | |
574 || noninherited_flags.clear != other.noninherited_flags.clear | |
575 || noninherited_flags.unicodeBidi != other.noninherited_flags.unicodeBid
i | |
576 || noninherited_flags.floating != other.noninherited_flags.floating | |
577 || noninherited_flags.originalDisplay != other.noninherited_flags.origin
alDisplay) | |
578 return true; | |
579 | |
580 if (noninherited_flags.effectiveDisplay >= FIRST_TABLE_DISPLAY && noninherit
ed_flags.effectiveDisplay <= LAST_TABLE_DISPLAY) { | |
581 if (inherited_flags._border_collapse != other.inherited_flags._border_co
llapse | |
582 || inherited_flags._empty_cells != other.inherited_flags._empty_cell
s | |
583 || inherited_flags._caption_side != other.inherited_flags._caption_s
ide | |
584 || noninherited_flags.tableLayout != other.noninherited_flags.tableL
ayout) | |
585 return true; | |
586 | |
587 // In the collapsing border model, 'hidden' suppresses other borders, wh
ile 'none' | |
588 // does not, so these style differences can be width differences. | |
589 if (inherited_flags._border_collapse | |
590 && ((borderTopStyle() == BHIDDEN && other.borderTopStyle() == BNONE) | |
591 || (borderTopStyle() == BNONE && other.borderTopStyle() == BHIDD
EN) | |
592 || (borderBottomStyle() == BHIDDEN && other.borderBottomStyle()
== BNONE) | |
593 || (borderBottomStyle() == BNONE && other.borderBottomStyle() ==
BHIDDEN) | |
594 || (borderLeftStyle() == BHIDDEN && other.borderLeftStyle() == B
NONE) | |
595 || (borderLeftStyle() == BNONE && other.borderLeftStyle() == BHI
DDEN) | |
596 || (borderRightStyle() == BHIDDEN && other.borderRightStyle() ==
BNONE) | |
597 || (borderRightStyle() == BNONE && other.borderRightStyle() == B
HIDDEN))) | |
598 return true; | |
599 } else if (noninherited_flags.effectiveDisplay == LIST_ITEM) { | |
600 if (inherited_flags._list_style_type != other.inherited_flags._list_styl
e_type | |
601 || inherited_flags._list_style_position != other.inherited_flags._li
st_style_position) | |
602 return true; | |
603 } | |
604 | |
605 if ((visibility() == COLLAPSE) != (other.visibility() == COLLAPSE)) | |
606 return true; | |
607 | |
608 if (!m_background->outline().visuallyEqual(other.m_background->outline())) { | |
609 // FIXME: We only really need to recompute the overflow but we don't hav
e an optimized layout for it. | |
610 return true; | |
611 } | |
612 | |
613 if (hasPseudoStyle(SCROLLBAR) != other.hasPseudoStyle(SCROLLBAR)) | |
614 return true; | |
615 | |
616 // Movement of non-static-positioned object is special cased in LayoutStyle:
:visualInvalidationDiff(). | |
617 | |
618 return false; | |
619 } | |
620 | |
621 bool LayoutStyle::diffNeedsFullLayout(const LayoutStyle& other) const | |
622 { | |
623 if (m_box.get() != other.m_box.get()) { | |
624 if (m_box->width() != other.m_box->width() | |
625 || m_box->minWidth() != other.m_box->minWidth() | |
626 || m_box->maxWidth() != other.m_box->maxWidth() | |
627 || m_box->height() != other.m_box->height() | |
628 || m_box->minHeight() != other.m_box->minHeight() | |
629 || m_box->maxHeight() != other.m_box->maxHeight()) | |
630 return true; | |
631 | |
632 if (m_box->verticalAlign() != other.m_box->verticalAlign()) | |
633 return true; | |
634 | |
635 if (m_box->boxSizing() != other.m_box->boxSizing()) | |
636 return true; | |
637 } | |
638 | |
639 if (noninherited_flags.verticalAlign != other.noninherited_flags.verticalAli
gn | |
640 || noninherited_flags.position != other.noninherited_flags.position) | |
641 return true; | |
642 | |
643 if (surround.get() != other.surround.get()) { | |
644 if (surround->padding != other.surround->padding) | |
645 return true; | |
646 } | |
647 | |
648 if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) { | |
649 if (rareNonInheritedData->m_alignContent != other.rareNonInheritedData->
m_alignContent | |
650 || rareNonInheritedData->m_alignContentDistribution != other.rareNon
InheritedData->m_alignContentDistribution | |
651 || rareNonInheritedData->m_alignItems != other.rareNonInheritedData-
>m_alignItems | |
652 || rareNonInheritedData->m_alignSelf != other.rareNonInheritedData->
m_alignSelf) | |
653 return true; | |
654 } | |
655 | |
656 return false; | |
657 } | |
658 | |
659 bool LayoutStyle::diffNeedsPaintInvalidationLayer(const LayoutStyle& other) cons
t | |
660 { | |
661 if (position() != StaticPosition && (visual->clip != other.visual->clip || v
isual->hasAutoClip != other.visual->hasAutoClip)) | |
662 return true; | |
663 | |
664 if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) { | |
665 if (RuntimeEnabledFeatures::cssCompositingEnabled() | |
666 && (rareNonInheritedData->m_effectiveBlendMode != other.rareNonInher
itedData->m_effectiveBlendMode | |
667 || rareNonInheritedData->m_isolation != other.rareNonInheritedDa
ta->m_isolation)) | |
668 return true; | |
669 | |
670 if (rareNonInheritedData->m_mask != other.rareNonInheritedData->m_mask | |
671 || rareNonInheritedData->m_maskBoxImage != other.rareNonInheritedDat
a->m_maskBoxImage) | |
672 return true; | |
673 } | |
674 | |
675 return false; | |
676 } | |
677 | |
678 bool LayoutStyle::diffNeedsPaintInvalidationObject(const LayoutStyle& other) con
st | |
679 { | |
680 if (inherited_flags._visibility != other.inherited_flags._visibility | |
681 || inherited_flags.m_printColorAdjust != other.inherited_flags.m_printCo
lorAdjust | |
682 || inherited_flags._insideLink != other.inherited_flags._insideLink | |
683 || !surround->border.visuallyEqual(other.surround->border) | |
684 || !m_background->visuallyEqual(*other.m_background)) | |
685 return true; | |
686 | |
687 if (rareInheritedData.get() != other.rareInheritedData.get()) { | |
688 if (rareInheritedData->userModify != other.rareInheritedData->userModify | |
689 || rareInheritedData->userSelect != other.rareInheritedData->userSel
ect | |
690 || rareInheritedData->m_imageRendering != other.rareInheritedData->m
_imageRendering) | |
691 return true; | |
692 } | |
693 | |
694 if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) { | |
695 if (rareNonInheritedData->userDrag != other.rareNonInheritedData->userDr
ag | |
696 || rareNonInheritedData->m_objectFit != other.rareNonInheritedData->
m_objectFit | |
697 || rareNonInheritedData->m_objectPosition != other.rareNonInheritedD
ata->m_objectPosition | |
698 || !rareNonInheritedData->shapeOutsideDataEquivalent(*other.rareNonI
nheritedData.get()) | |
699 || !rareNonInheritedData->clipPathDataEquivalent(*other.rareNonInher
itedData.get()) | |
700 || (visitedLinkBorderLeftColor() != other.visitedLinkBorderLeftColor
() && borderLeftWidth()) | |
701 || (visitedLinkBorderRightColor() != other.visitedLinkBorderRightCol
or() && borderRightWidth()) | |
702 || (visitedLinkBorderBottomColor() != other.visitedLinkBorderBottomC
olor() && borderBottomWidth()) | |
703 || (visitedLinkBorderTopColor() != other.visitedLinkBorderTopColor()
&& borderTopWidth()) | |
704 || (visitedLinkOutlineColor() != other.visitedLinkOutlineColor() &&
outlineWidth()) | |
705 || (visitedLinkBackgroundColor() != other.visitedLinkBackgroundColor
())) | |
706 return true; | |
707 } | |
708 | |
709 if (resize() != other.resize()) | |
710 return true; | |
711 | |
712 return false; | |
713 } | |
714 | |
715 void LayoutStyle::updatePropertySpecificDifferences(const LayoutStyle& other, St
yleDifference& diff) const | |
716 { | |
717 // StyleAdjuster has ensured that zIndex is non-auto only if it's applicable
. | |
718 if (m_box->zIndex() != other.m_box->zIndex() || m_box->hasAutoZIndex() != ot
her.m_box->hasAutoZIndex()) | |
719 diff.setZIndexChanged(); | |
720 | |
721 if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) { | |
722 if (!transformDataEquivalent(other)) | |
723 diff.setTransformChanged(); | |
724 | |
725 if (rareNonInheritedData->opacity != other.rareNonInheritedData->opacity
) | |
726 diff.setOpacityChanged(); | |
727 | |
728 if (rareNonInheritedData->m_filter != other.rareNonInheritedData->m_filt
er) | |
729 diff.setFilterChanged(); | |
730 } | |
731 | |
732 if (!diff.needsPaintInvalidation()) { | |
733 if (inherited->color != other.inherited->color | |
734 || inherited->visitedLinkColor != other.inherited->visitedLinkColor | |
735 || inherited_flags.m_textUnderline != other.inherited_flags.m_textUn
derline | |
736 || visual->textDecoration != other.visual->textDecoration) { | |
737 diff.setTextOrColorChanged(); | |
738 } else if (rareNonInheritedData.get() != other.rareNonInheritedData.get(
) | |
739 && (rareNonInheritedData->m_textDecorationStyle != other.rareNonInhe
ritedData->m_textDecorationStyle | |
740 || rareNonInheritedData->m_textDecorationColor != other.rareNonI
nheritedData->m_textDecorationColor | |
741 || rareNonInheritedData->m_visitedLinkTextDecorationColor != oth
er.rareNonInheritedData->m_visitedLinkTextDecorationColor)) { | |
742 diff.setTextOrColorChanged(); | |
743 } else if (rareInheritedData.get() != other.rareInheritedData.get() | |
744 && (rareInheritedData->textFillColor() != other.rareInheritedData->t
extFillColor() | |
745 || rareInheritedData->textStrokeColor() != other.rareInheritedDa
ta->textStrokeColor() | |
746 || rareInheritedData->textEmphasisColor() != other.rareInherited
Data->textEmphasisColor() | |
747 || rareInheritedData->visitedLinkTextFillColor() != other.rareIn
heritedData->visitedLinkTextFillColor() | |
748 || rareInheritedData->visitedLinkTextStrokeColor() != other.rare
InheritedData->visitedLinkTextStrokeColor() | |
749 || rareInheritedData->visitedLinkTextEmphasisColor() != other.ra
reInheritedData->visitedLinkTextEmphasisColor() | |
750 || rareInheritedData->textEmphasisFill != other.rareInheritedDat
a->textEmphasisFill | |
751 || rareInheritedData->appliedTextDecorations != other.rareInheri
tedData->appliedTextDecorations)) { | |
752 diff.setTextOrColorChanged(); | |
753 } | |
754 } | |
755 } | |
756 | |
757 void LayoutStyle::addCursor(PassRefPtr<StyleImage> image, bool hotSpotSpecified,
const IntPoint& hotSpot) | |
758 { | |
759 if (!rareInheritedData.access()->cursorData) | |
760 rareInheritedData.access()->cursorData = CursorList::create(); | |
761 rareInheritedData.access()->cursorData->append(CursorData(image, hotSpotSpec
ified, hotSpot)); | |
762 } | |
763 | |
764 void LayoutStyle::setCursorList(PassRefPtr<CursorList> other) | |
765 { | |
766 rareInheritedData.access()->cursorData = other; | |
767 } | |
768 | |
769 void LayoutStyle::setQuotes(PassRefPtr<QuotesData> q) | |
770 { | |
771 rareInheritedData.access()->quotes = q; | |
772 } | |
773 | |
774 void LayoutStyle::clearCursorList() | |
775 { | |
776 if (rareInheritedData->cursorData) | |
777 rareInheritedData.access()->cursorData = nullptr; | |
778 } | |
779 | |
780 void LayoutStyle::addCallbackSelector(const String& selector) | |
781 { | |
782 if (!rareNonInheritedData->m_callbackSelectors.contains(selector)) | |
783 rareNonInheritedData.access()->m_callbackSelectors.append(selector); | |
784 } | |
785 | |
786 void LayoutStyle::clearContent() | |
787 { | |
788 if (rareNonInheritedData->m_content) | |
789 rareNonInheritedData.access()->m_content = nullptr; | |
790 } | |
791 | |
792 void LayoutStyle::appendContent(PassOwnPtr<ContentData> contentData) | |
793 { | |
794 OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content; | |
795 ContentData* lastContent = content.get(); | |
796 while (lastContent && lastContent->next()) | |
797 lastContent = lastContent->next(); | |
798 | |
799 if (lastContent) | |
800 lastContent->setNext(contentData); | |
801 else | |
802 content = contentData; | |
803 } | |
804 | |
805 void LayoutStyle::setContent(PassRefPtr<StyleImage> image, bool add) | |
806 { | |
807 if (!image) | |
808 return; | |
809 | |
810 if (add) { | |
811 appendContent(ContentData::create(image)); | |
812 return; | |
813 } | |
814 | |
815 rareNonInheritedData.access()->m_content = ContentData::create(image); | |
816 } | |
817 | |
818 void LayoutStyle::setContent(const String& string, bool add) | |
819 { | |
820 OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content; | |
821 if (add) { | |
822 ContentData* lastContent = content.get(); | |
823 while (lastContent && lastContent->next()) | |
824 lastContent = lastContent->next(); | |
825 | |
826 if (lastContent) { | |
827 // We attempt to merge with the last ContentData if possible. | |
828 if (lastContent->isText()) { | |
829 TextContentData* textContent = toTextContentData(lastContent); | |
830 textContent->setText(textContent->text() + string); | |
831 } else { | |
832 lastContent->setNext(ContentData::create(string)); | |
833 } | |
834 | |
835 return; | |
836 } | |
837 } | |
838 | |
839 content = ContentData::create(string); | |
840 } | |
841 | |
842 void LayoutStyle::setContent(PassOwnPtr<CounterContent> counter, bool add) | |
843 { | |
844 if (!counter) | |
845 return; | |
846 | |
847 if (add) { | |
848 appendContent(ContentData::create(counter)); | |
849 return; | |
850 } | |
851 | |
852 rareNonInheritedData.access()->m_content = ContentData::create(counter); | |
853 } | |
854 | |
855 void LayoutStyle::setContent(QuoteType quote, bool add) | |
856 { | |
857 if (add) { | |
858 appendContent(ContentData::create(quote)); | |
859 return; | |
860 } | |
861 | |
862 rareNonInheritedData.access()->m_content = ContentData::create(quote); | |
863 } | |
864 | |
865 bool LayoutStyle::hasWillChangeCompositingHint() const | |
866 { | |
867 for (size_t i = 0; i < rareNonInheritedData->m_willChange->m_properties.size
(); ++i) { | |
868 switch (rareNonInheritedData->m_willChange->m_properties[i]) { | |
869 case CSSPropertyOpacity: | |
870 case CSSPropertyTransform: | |
871 case CSSPropertyWebkitTransform: | |
872 case CSSPropertyTop: | |
873 case CSSPropertyLeft: | |
874 case CSSPropertyBottom: | |
875 case CSSPropertyRight: | |
876 return true; | |
877 default: | |
878 break; | |
879 } | |
880 } | |
881 return false; | |
882 } | |
883 | |
884 inline bool requireTransformOrigin(const Vector<RefPtr<TransformOperation>>& tra
nsformOperations, LayoutStyle::ApplyTransformOrigin applyOrigin, LayoutStyle::Ap
plyMotionPath applyMotionPath) | |
885 { | |
886 // transform-origin brackets the transform with translate operations. | |
887 // Optimize for the case where the only transform is a translation, since th
e transform-origin is irrelevant | |
888 // in that case. | |
889 if (applyOrigin != LayoutStyle::IncludeTransformOrigin) | |
890 return false; | |
891 | |
892 if (applyMotionPath == LayoutStyle::IncludeMotionPath) | |
893 return true; | |
894 | |
895 unsigned size = transformOperations.size(); | |
896 for (unsigned i = 0; i < size; ++i) { | |
897 TransformOperation::OperationType type = transformOperations[i]->type(); | |
898 if (type != TransformOperation::TranslateX | |
899 && type != TransformOperation::TranslateY | |
900 && type != TransformOperation::Translate | |
901 && type != TransformOperation::TranslateZ | |
902 && type != TransformOperation::Translate3D) | |
903 return true; | |
904 } | |
905 | |
906 return false; | |
907 } | |
908 | |
909 void LayoutStyle::applyTransform(TransformationMatrix& transform, const LayoutSi
ze& borderBoxSize, ApplyTransformOrigin applyOrigin, ApplyMotionPath applyMotion
Path) const | |
910 { | |
911 applyTransform(transform, FloatRect(FloatPoint(), FloatSize(borderBoxSize)),
applyOrigin, applyMotionPath); | |
912 } | |
913 | |
914 void LayoutStyle::applyTransform(TransformationMatrix& transform, const FloatRec
t& boundingBox, ApplyTransformOrigin applyOrigin, ApplyMotionPath applyMotionPat
h) const | |
915 { | |
916 if (!hasMotionPath()) | |
917 applyMotionPath = ExcludeMotionPath; | |
918 const Vector<RefPtr<TransformOperation>>& transformOperations = rareNonInher
itedData->m_transform->m_operations.operations(); | |
919 bool applyTransformOrigin = requireTransformOrigin(transformOperations, appl
yOrigin, applyMotionPath); | |
920 | |
921 float offsetX = transformOriginX().type() == Percent ? boundingBox.x() : 0; | |
922 float offsetY = transformOriginY().type() == Percent ? boundingBox.y() : 0; | |
923 | |
924 if (applyTransformOrigin) { | |
925 transform.translate3d(floatValueForLength(transformOriginX(), boundingBo
x.width()) + offsetX, | |
926 floatValueForLength(transformOriginY(), boundingBox.height()) + offs
etY, | |
927 transformOriginZ()); | |
928 } | |
929 | |
930 if (applyMotionPath == LayoutStyle::IncludeMotionPath) | |
931 applyMotionPathTransform(transform); | |
932 | |
933 unsigned size = transformOperations.size(); | |
934 for (unsigned i = 0; i < size; ++i) | |
935 transformOperations[i]->apply(transform, boundingBox.size()); | |
936 | |
937 if (applyTransformOrigin) { | |
938 transform.translate3d(-floatValueForLength(transformOriginX(), boundingB
ox.width()) - offsetX, | |
939 -floatValueForLength(transformOriginY(), boundingBox.height()) - off
setY, | |
940 -transformOriginZ()); | |
941 } | |
942 } | |
943 | |
944 void LayoutStyle::applyMotionPathTransform(TransformationMatrix& transform) cons
t | |
945 { | |
946 const StyleMotionData& motionData = rareNonInheritedData->m_transform->m_mot
ion; | |
947 ASSERT(motionData.m_path && motionData.m_path->isPathStyleMotionPath()); | |
948 const PathStyleMotionPath& motionPath = toPathStyleMotionPath(*motionData.m_
path); | |
949 float pathLength = motionPath.length(); | |
950 float distance = floatValueForLength(motionData.m_offset, pathLength); | |
951 float computedDistance; | |
952 if (motionPath.isClosed() && pathLength > 0) { | |
953 computedDistance = fmod(distance, pathLength); | |
954 if (computedDistance < 0) | |
955 computedDistance += pathLength; | |
956 } else { | |
957 computedDistance = clampTo<float>(distance, 0, pathLength); | |
958 } | |
959 | |
960 FloatPoint point; | |
961 float angle; | |
962 if (!motionPath.path().pointAndNormalAtLength(computedDistance, point, angle
)) | |
963 return; | |
964 if (motionData.m_rotationType == MotionRotationFixed) | |
965 angle = 0; | |
966 | |
967 transform.translate(point.x(), point.y()); | |
968 transform.rotate(angle + motionData.m_rotation); | |
969 } | |
970 | |
971 void LayoutStyle::setTextShadow(PassRefPtr<ShadowList> s) | |
972 { | |
973 rareInheritedData.access()->textShadow = s; | |
974 } | |
975 | |
976 void LayoutStyle::setBoxShadow(PassRefPtr<ShadowList> s) | |
977 { | |
978 rareNonInheritedData.access()->m_boxShadow = s; | |
979 } | |
980 | |
981 static FloatRoundedRect::Radii calcRadiiFor(const BorderData& border, LayoutSize
size) | |
982 { | |
983 return FloatRoundedRect::Radii( | |
984 IntSize(valueForLength(border.topLeft().width(), size.width()), | |
985 valueForLength(border.topLeft().height(), size.height())), | |
986 IntSize(valueForLength(border.topRight().width(), size.width()), | |
987 valueForLength(border.topRight().height(), size.height())), | |
988 IntSize(valueForLength(border.bottomLeft().width(), size.width()), | |
989 valueForLength(border.bottomLeft().height(), size.height())), | |
990 IntSize(valueForLength(border.bottomRight().width(), size.width()), | |
991 valueForLength(border.bottomRight().height(), size.height()))); | |
992 } | |
993 | |
994 StyleImage* LayoutStyle::listStyleImage() const { return rareInheritedData->list
StyleImage.get(); } | |
995 void LayoutStyle::setListStyleImage(PassRefPtr<StyleImage> v) | |
996 { | |
997 if (rareInheritedData->listStyleImage != v) | |
998 rareInheritedData.access()->listStyleImage = v; | |
999 } | |
1000 | |
1001 Color LayoutStyle::color() const { return inherited->color; } | |
1002 Color LayoutStyle::visitedLinkColor() const { return inherited->visitedLinkColor
; } | |
1003 void LayoutStyle::setColor(const Color& v) { SET_VAR(inherited, color, v); } | |
1004 void LayoutStyle::setVisitedLinkColor(const Color& v) { SET_VAR(inherited, visit
edLinkColor, v); } | |
1005 | |
1006 short LayoutStyle::horizontalBorderSpacing() const { return inherited->horizonta
l_border_spacing; } | |
1007 short LayoutStyle::verticalBorderSpacing() const { return inherited->vertical_bo
rder_spacing; } | |
1008 void LayoutStyle::setHorizontalBorderSpacing(short v) { SET_VAR(inherited, horiz
ontal_border_spacing, v); } | |
1009 void LayoutStyle::setVerticalBorderSpacing(short v) { SET_VAR(inherited, vertica
l_border_spacing, v); } | |
1010 | |
1011 FloatRoundedRect LayoutStyle::getRoundedBorderFor(const LayoutRect& borderRect,
bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const | |
1012 { | |
1013 FloatRoundedRect roundedRect(pixelSnappedIntRect(borderRect)); | |
1014 if (hasBorderRadius()) { | |
1015 FloatRoundedRect::Radii radii = calcRadiiFor(surround->border, borderRec
t.size()); | |
1016 roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includ
eLogicalLeftEdge, includeLogicalRightEdge); | |
1017 roundedRect.constrainRadii(); | |
1018 } | |
1019 return roundedRect; | |
1020 } | |
1021 | |
1022 FloatRoundedRect LayoutStyle::getRoundedInnerBorderFor(const LayoutRect& borderR
ect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const | |
1023 { | |
1024 bool horizontal = isHorizontalWritingMode(); | |
1025 | |
1026 int leftWidth = (!horizontal || includeLogicalLeftEdge) ? borderLeftWidth()
: 0; | |
1027 int rightWidth = (!horizontal || includeLogicalRightEdge) ? borderRightWidth
() : 0; | |
1028 int topWidth = (horizontal || includeLogicalLeftEdge) ? borderTopWidth() : 0
; | |
1029 int bottomWidth = (horizontal || includeLogicalRightEdge) ? borderBottomWidt
h() : 0; | |
1030 | |
1031 return getRoundedInnerBorderFor(borderRect, topWidth, bottomWidth, leftWidth
, rightWidth, includeLogicalLeftEdge, includeLogicalRightEdge); | |
1032 } | |
1033 | |
1034 FloatRoundedRect LayoutStyle::getRoundedInnerBorderFor(const LayoutRect& borderR
ect, | |
1035 int topWidth, int bottomWidth, int leftWidth, int rightWidth, bool includeLo
gicalLeftEdge, bool includeLogicalRightEdge) const | |
1036 { | |
1037 LayoutRect innerRect(borderRect.x() + leftWidth, | |
1038 borderRect.y() + topWidth, | |
1039 borderRect.width() - leftWidth - rightWidth, | |
1040 borderRect.height() - topWidth - bottomWidth); | |
1041 | |
1042 FloatRoundedRect roundedRect(pixelSnappedIntRect(innerRect)); | |
1043 | |
1044 if (hasBorderRadius()) { | |
1045 FloatRoundedRect::Radii radii = getRoundedBorderFor(borderRect).radii(); | |
1046 radii.shrink(topWidth, bottomWidth, leftWidth, rightWidth); | |
1047 roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includ
eLogicalLeftEdge, includeLogicalRightEdge); | |
1048 } | |
1049 return roundedRect; | |
1050 } | |
1051 | |
1052 static bool allLayersAreFixed(const FillLayer& layer) | |
1053 { | |
1054 for (const FillLayer* currLayer = &layer; currLayer; currLayer = currLayer->
next()) { | |
1055 if (!currLayer->image() || currLayer->attachment() != FixedBackgroundAtt
achment) | |
1056 return false; | |
1057 } | |
1058 | |
1059 return true; | |
1060 } | |
1061 | |
1062 bool LayoutStyle::hasEntirelyFixedBackground() const | |
1063 { | |
1064 return allLayersAreFixed(backgroundLayers()); | |
1065 } | |
1066 | |
1067 const CounterDirectiveMap* LayoutStyle::counterDirectives() const | |
1068 { | |
1069 return rareNonInheritedData->m_counterDirectives.get(); | |
1070 } | |
1071 | |
1072 CounterDirectiveMap& LayoutStyle::accessCounterDirectives() | |
1073 { | |
1074 OwnPtr<CounterDirectiveMap>& map = rareNonInheritedData.access()->m_counterD
irectives; | |
1075 if (!map) | |
1076 map = adoptPtr(new CounterDirectiveMap); | |
1077 return *map; | |
1078 } | |
1079 | |
1080 const CounterDirectives LayoutStyle::getCounterDirectives(const AtomicString& id
entifier) const | |
1081 { | |
1082 if (const CounterDirectiveMap* directives = counterDirectives()) | |
1083 return directives->get(identifier); | |
1084 return CounterDirectives(); | |
1085 } | |
1086 | |
1087 void LayoutStyle::clearIncrementDirectives() | |
1088 { | |
1089 if (!counterDirectives()) | |
1090 return; | |
1091 | |
1092 // This makes us copy even if we may not be removing any items. | |
1093 CounterDirectiveMap& map = accessCounterDirectives(); | |
1094 typedef CounterDirectiveMap::iterator Iterator; | |
1095 | |
1096 Iterator end = map.end(); | |
1097 for (Iterator it = map.begin(); it != end; ++it) | |
1098 it->value.clearIncrement(); | |
1099 } | |
1100 | |
1101 void LayoutStyle::clearResetDirectives() | |
1102 { | |
1103 if (!counterDirectives()) | |
1104 return; | |
1105 | |
1106 // This makes us copy even if we may not be removing any items. | |
1107 CounterDirectiveMap& map = accessCounterDirectives(); | |
1108 typedef CounterDirectiveMap::iterator Iterator; | |
1109 | |
1110 Iterator end = map.end(); | |
1111 for (Iterator it = map.begin(); it != end; ++it) | |
1112 it->value.clearReset(); | |
1113 } | |
1114 | |
1115 const AtomicString& LayoutStyle::hyphenString() const | |
1116 { | |
1117 const AtomicString& hyphenationString = rareInheritedData.get()->hyphenation
String; | |
1118 if (!hyphenationString.isNull()) | |
1119 return hyphenationString; | |
1120 | |
1121 // FIXME: This should depend on locale. | |
1122 DEFINE_STATIC_LOCAL(AtomicString, hyphenMinusString, (&hyphenMinus, 1)); | |
1123 DEFINE_STATIC_LOCAL(AtomicString, hyphenString, (&hyphen, 1)); | |
1124 return font().primaryFontHasGlyphForCharacter(hyphen) ? hyphenString : hyphe
nMinusString; | |
1125 } | |
1126 | |
1127 const AtomicString& LayoutStyle::textEmphasisMarkString() const | |
1128 { | |
1129 switch (textEmphasisMark()) { | |
1130 case TextEmphasisMarkNone: | |
1131 return nullAtom; | |
1132 case TextEmphasisMarkCustom: | |
1133 return textEmphasisCustomMark(); | |
1134 case TextEmphasisMarkDot: { | |
1135 DEFINE_STATIC_LOCAL(AtomicString, filledDotString, (&bullet, 1)); | |
1136 DEFINE_STATIC_LOCAL(AtomicString, openDotString, (&whiteBullet, 1)); | |
1137 return textEmphasisFill() == TextEmphasisFillFilled ? filledDotString :
openDotString; | |
1138 } | |
1139 case TextEmphasisMarkCircle: { | |
1140 DEFINE_STATIC_LOCAL(AtomicString, filledCircleString, (&blackCircle, 1))
; | |
1141 DEFINE_STATIC_LOCAL(AtomicString, openCircleString, (&whiteCircle, 1)); | |
1142 return textEmphasisFill() == TextEmphasisFillFilled ? filledCircleString
: openCircleString; | |
1143 } | |
1144 case TextEmphasisMarkDoubleCircle: { | |
1145 DEFINE_STATIC_LOCAL(AtomicString, filledDoubleCircleString, (&fisheye, 1
)); | |
1146 DEFINE_STATIC_LOCAL(AtomicString, openDoubleCircleString, (&bullseye, 1)
); | |
1147 return textEmphasisFill() == TextEmphasisFillFilled ? filledDoubleCircle
String : openDoubleCircleString; | |
1148 } | |
1149 case TextEmphasisMarkTriangle: { | |
1150 DEFINE_STATIC_LOCAL(AtomicString, filledTriangleString, (&blackUpPointin
gTriangle, 1)); | |
1151 DEFINE_STATIC_LOCAL(AtomicString, openTriangleString, (&whiteUpPointingT
riangle, 1)); | |
1152 return textEmphasisFill() == TextEmphasisFillFilled ? filledTriangleStri
ng : openTriangleString; | |
1153 } | |
1154 case TextEmphasisMarkSesame: { | |
1155 DEFINE_STATIC_LOCAL(AtomicString, filledSesameString, (&sesameDot, 1)); | |
1156 DEFINE_STATIC_LOCAL(AtomicString, openSesameString, (&whiteSesameDot, 1)
); | |
1157 return textEmphasisFill() == TextEmphasisFillFilled ? filledSesameString
: openSesameString; | |
1158 } | |
1159 case TextEmphasisMarkAuto: | |
1160 ASSERT_NOT_REACHED(); | |
1161 return nullAtom; | |
1162 } | |
1163 | |
1164 ASSERT_NOT_REACHED(); | |
1165 return nullAtom; | |
1166 } | |
1167 | |
1168 CSSAnimationData& LayoutStyle::accessAnimations() | |
1169 { | |
1170 if (!rareNonInheritedData.access()->m_animations) | |
1171 rareNonInheritedData.access()->m_animations = CSSAnimationData::create()
; | |
1172 return *rareNonInheritedData->m_animations; | |
1173 } | |
1174 | |
1175 CSSTransitionData& LayoutStyle::accessTransitions() | |
1176 { | |
1177 if (!rareNonInheritedData.access()->m_transitions) | |
1178 rareNonInheritedData.access()->m_transitions = CSSTransitionData::create
(); | |
1179 return *rareNonInheritedData->m_transitions; | |
1180 } | |
1181 | |
1182 const Font& LayoutStyle::font() const { return inherited->font; } | |
1183 const FontMetrics& LayoutStyle::fontMetrics() const { return inherited->font.fon
tMetrics(); } | |
1184 const FontDescription& LayoutStyle::fontDescription() const { return inherited->
font.fontDescription(); } | |
1185 float LayoutStyle::specifiedFontSize() const { return fontDescription().specifie
dSize(); } | |
1186 float LayoutStyle::computedFontSize() const { return fontDescription().computedS
ize(); } | |
1187 int LayoutStyle::fontSize() const { return fontDescription().computedPixelSize()
; } | |
1188 float LayoutStyle::fontSizeAdjust() const { return fontDescription().sizeAdjust(
); } | |
1189 bool LayoutStyle::hasFontSizeAdjust() const { return fontDescription().hasSizeAd
just(); } | |
1190 FontWeight LayoutStyle::fontWeight() const { return fontDescription().weight();
} | |
1191 FontStretch LayoutStyle::fontStretch() const { return fontDescription().stretch(
); } | |
1192 | |
1193 TextDecoration LayoutStyle::textDecorationsInEffect() const | |
1194 { | |
1195 int decorations = 0; | |
1196 | |
1197 const Vector<AppliedTextDecoration>& applied = appliedTextDecorations(); | |
1198 | |
1199 for (size_t i = 0; i < applied.size(); ++i) | |
1200 decorations |= applied[i].line(); | |
1201 | |
1202 return static_cast<TextDecoration>(decorations); | |
1203 } | |
1204 | |
1205 const Vector<AppliedTextDecoration>& LayoutStyle::appliedTextDecorations() const | |
1206 { | |
1207 if (!inherited_flags.m_textUnderline && !rareInheritedData->appliedTextDecor
ations) { | |
1208 DEFINE_STATIC_LOCAL(Vector<AppliedTextDecoration>, empty, ()); | |
1209 return empty; | |
1210 } | |
1211 if (inherited_flags.m_textUnderline) { | |
1212 DEFINE_STATIC_LOCAL(Vector<AppliedTextDecoration>, underline, (1, Applie
dTextDecoration(TextDecorationUnderline))); | |
1213 return underline; | |
1214 } | |
1215 | |
1216 return rareInheritedData->appliedTextDecorations->vector(); | |
1217 } | |
1218 | |
1219 float LayoutStyle::wordSpacing() const { return fontDescription().wordSpacing();
} | |
1220 float LayoutStyle::letterSpacing() const { return fontDescription().letterSpacin
g(); } | |
1221 | |
1222 bool LayoutStyle::setFontDescription(const FontDescription& v) | |
1223 { | |
1224 if (inherited->font.fontDescription() != v) { | |
1225 inherited.access()->font = Font(v); | |
1226 return true; | |
1227 } | |
1228 return false; | |
1229 } | |
1230 | |
1231 const Length& LayoutStyle::specifiedLineHeight() const { return inherited->line_
height; } | |
1232 Length LayoutStyle::lineHeight() const | |
1233 { | |
1234 const Length& lh = inherited->line_height; | |
1235 // Unlike fontDescription().computedSize() and hence fontSize(), this is | |
1236 // recalculated on demand as we only store the specified line height. | |
1237 // FIXME: Should consider scaling the fixed part of any calc expressions | |
1238 // too, though this involves messily poking into CalcExpressionLength. | |
1239 float multiplier = textAutosizingMultiplier(); | |
1240 if (multiplier > 1 && lh.isFixed()) | |
1241 return Length(TextAutosizer::computeAutosizedFontSize(lh.value(), multip
lier), Fixed); | |
1242 | |
1243 return lh; | |
1244 } | |
1245 | |
1246 void LayoutStyle::setLineHeight(const Length& specifiedLineHeight) { SET_VAR(inh
erited, line_height, specifiedLineHeight); } | |
1247 | |
1248 int LayoutStyle::computedLineHeight() const | |
1249 { | |
1250 const Length& lh = lineHeight(); | |
1251 | |
1252 // Negative value means the line height is not set. Use the font's built-in
spacing. | |
1253 if (lh.isNegative()) | |
1254 return fontMetrics().lineSpacing(); | |
1255 | |
1256 if (lh.isPercent()) | |
1257 return minimumValueForLength(lh, fontSize()); | |
1258 | |
1259 return lh.value(); | |
1260 } | |
1261 | |
1262 void LayoutStyle::setWordSpacing(float wordSpacing) | |
1263 { | |
1264 FontSelector* currentFontSelector = font().fontSelector(); | |
1265 FontDescription desc(fontDescription()); | |
1266 desc.setWordSpacing(wordSpacing); | |
1267 setFontDescription(desc); | |
1268 font().update(currentFontSelector); | |
1269 } | |
1270 | |
1271 void LayoutStyle::setLetterSpacing(float letterSpacing) | |
1272 { | |
1273 FontSelector* currentFontSelector = font().fontSelector(); | |
1274 FontDescription desc(fontDescription()); | |
1275 desc.setLetterSpacing(letterSpacing); | |
1276 setFontDescription(desc); | |
1277 font().update(currentFontSelector); | |
1278 } | |
1279 | |
1280 void LayoutStyle::setTextAutosizingMultiplier(float multiplier) | |
1281 { | |
1282 SET_VAR(inherited, textAutosizingMultiplier, multiplier); | |
1283 | |
1284 float size = specifiedFontSize(); | |
1285 | |
1286 ASSERT(std::isfinite(size)); | |
1287 if (!std::isfinite(size) || size < 0) | |
1288 size = 0; | |
1289 else | |
1290 size = std::min(maximumAllowedFontSize, size); | |
1291 | |
1292 FontSelector* currentFontSelector = font().fontSelector(); | |
1293 FontDescription desc(fontDescription()); | |
1294 desc.setSpecifiedSize(size); | |
1295 desc.setComputedSize(size); | |
1296 | |
1297 if (multiplier > 1) { | |
1298 float autosizedFontSize = TextAutosizer::computeAutosizedFontSize(size,
multiplier); | |
1299 desc.setComputedSize(std::min(maximumAllowedFontSize, autosizedFontSize)
); | |
1300 } | |
1301 | |
1302 setFontDescription(desc); | |
1303 font().update(currentFontSelector); | |
1304 } | |
1305 | |
1306 void LayoutStyle::addAppliedTextDecoration(const AppliedTextDecoration& decorati
on) | |
1307 { | |
1308 RefPtr<AppliedTextDecorationList>& list = rareInheritedData.access()->applie
dTextDecorations; | |
1309 | |
1310 if (!list) | |
1311 list = AppliedTextDecorationList::create(); | |
1312 else if (!list->hasOneRef()) | |
1313 list = list->copy(); | |
1314 | |
1315 if (inherited_flags.m_textUnderline) { | |
1316 inherited_flags.m_textUnderline = false; | |
1317 list->append(AppliedTextDecoration(TextDecorationUnderline)); | |
1318 } | |
1319 | |
1320 list->append(decoration); | |
1321 } | |
1322 | |
1323 void LayoutStyle::applyTextDecorations() | |
1324 { | |
1325 if (textDecoration() == TextDecorationNone) | |
1326 return; | |
1327 | |
1328 TextDecorationStyle style = textDecorationStyle(); | |
1329 StyleColor styleColor = decorationColorIncludingFallback(insideLink() == Ins
ideVisitedLink); | |
1330 | |
1331 int decorations = textDecoration(); | |
1332 | |
1333 if (decorations & TextDecorationUnderline) { | |
1334 // To save memory, we don't use AppliedTextDecoration objects in the | |
1335 // common case of a single simple underline. | |
1336 AppliedTextDecoration underline(TextDecorationUnderline, style, styleCol
or); | |
1337 | |
1338 if (!rareInheritedData->appliedTextDecorations && underline.isSimpleUnde
rline()) | |
1339 inherited_flags.m_textUnderline = true; | |
1340 else | |
1341 addAppliedTextDecoration(underline); | |
1342 } | |
1343 if (decorations & TextDecorationOverline) | |
1344 addAppliedTextDecoration(AppliedTextDecoration(TextDecorationOverline, s
tyle, styleColor)); | |
1345 if (decorations & TextDecorationLineThrough) | |
1346 addAppliedTextDecoration(AppliedTextDecoration(TextDecorationLineThrough
, style, styleColor)); | |
1347 } | |
1348 | |
1349 void LayoutStyle::clearAppliedTextDecorations() | |
1350 { | |
1351 inherited_flags.m_textUnderline = false; | |
1352 | |
1353 if (rareInheritedData->appliedTextDecorations) | |
1354 rareInheritedData.access()->appliedTextDecorations = nullptr; | |
1355 } | |
1356 | |
1357 void LayoutStyle::clearMultiCol() | |
1358 { | |
1359 rareNonInheritedData.access()->m_multiCol = nullptr; | |
1360 rareNonInheritedData.access()->m_multiCol.init(); | |
1361 } | |
1362 | |
1363 StyleColor LayoutStyle::decorationColorIncludingFallback(bool visitedLink) const | |
1364 { | |
1365 StyleColor styleColor = visitedLink ? visitedLinkTextDecorationColor() : tex
tDecorationColor(); | |
1366 | |
1367 if (!styleColor.isCurrentColor()) | |
1368 return styleColor; | |
1369 | |
1370 if (textStrokeWidth()) { | |
1371 // Prefer stroke color if possible, but not if it's fully transparent. | |
1372 StyleColor textStrokeStyleColor = visitedLink ? visitedLinkTextStrokeCol
or() : textStrokeColor(); | |
1373 if (!textStrokeStyleColor.isCurrentColor() && textStrokeStyleColor.color
().alpha()) | |
1374 return textStrokeStyleColor; | |
1375 } | |
1376 | |
1377 return visitedLink ? visitedLinkTextFillColor() : textFillColor(); | |
1378 } | |
1379 | |
1380 Color LayoutStyle::colorIncludingFallback(int colorProperty, bool visitedLink) c
onst | |
1381 { | |
1382 StyleColor result(StyleColor::currentColor()); | |
1383 EBorderStyle borderStyle = BNONE; | |
1384 switch (colorProperty) { | |
1385 case CSSPropertyBackgroundColor: | |
1386 result = visitedLink ? visitedLinkBackgroundColor() : backgroundColor(); | |
1387 break; | |
1388 case CSSPropertyBorderLeftColor: | |
1389 result = visitedLink ? visitedLinkBorderLeftColor() : borderLeftColor(); | |
1390 borderStyle = borderLeftStyle(); | |
1391 break; | |
1392 case CSSPropertyBorderRightColor: | |
1393 result = visitedLink ? visitedLinkBorderRightColor() : borderRightColor(
); | |
1394 borderStyle = borderRightStyle(); | |
1395 break; | |
1396 case CSSPropertyBorderTopColor: | |
1397 result = visitedLink ? visitedLinkBorderTopColor() : borderTopColor(); | |
1398 borderStyle = borderTopStyle(); | |
1399 break; | |
1400 case CSSPropertyBorderBottomColor: | |
1401 result = visitedLink ? visitedLinkBorderBottomColor() : borderBottomColo
r(); | |
1402 borderStyle = borderBottomStyle(); | |
1403 break; | |
1404 case CSSPropertyColor: | |
1405 result = visitedLink ? visitedLinkColor() : color(); | |
1406 break; | |
1407 case CSSPropertyOutlineColor: | |
1408 result = visitedLink ? visitedLinkOutlineColor() : outlineColor(); | |
1409 break; | |
1410 case CSSPropertyWebkitColumnRuleColor: | |
1411 result = visitedLink ? visitedLinkColumnRuleColor() : columnRuleColor(); | |
1412 break; | |
1413 case CSSPropertyWebkitTextEmphasisColor: | |
1414 result = visitedLink ? visitedLinkTextEmphasisColor() : textEmphasisColo
r(); | |
1415 break; | |
1416 case CSSPropertyWebkitTextFillColor: | |
1417 result = visitedLink ? visitedLinkTextFillColor() : textFillColor(); | |
1418 break; | |
1419 case CSSPropertyWebkitTextStrokeColor: | |
1420 result = visitedLink ? visitedLinkTextStrokeColor() : textStrokeColor(); | |
1421 break; | |
1422 case CSSPropertyFloodColor: | |
1423 result = floodColor(); | |
1424 break; | |
1425 case CSSPropertyLightingColor: | |
1426 result = lightingColor(); | |
1427 break; | |
1428 case CSSPropertyStopColor: | |
1429 result = stopColor(); | |
1430 break; | |
1431 case CSSPropertyWebkitTapHighlightColor: | |
1432 result = tapHighlightColor(); | |
1433 break; | |
1434 case CSSPropertyTextDecorationColor: | |
1435 result = decorationColorIncludingFallback(visitedLink); | |
1436 break; | |
1437 default: | |
1438 ASSERT_NOT_REACHED(); | |
1439 break; | |
1440 } | |
1441 | |
1442 if (!result.isCurrentColor()) | |
1443 return result.color(); | |
1444 | |
1445 // FIXME: Treating styled borders with initial color differently causes prob
lems | |
1446 // See crbug.com/316559, crbug.com/276231 | |
1447 if (!visitedLink && (borderStyle == INSET || borderStyle == OUTSET || border
Style == RIDGE || borderStyle == GROOVE)) | |
1448 return Color(238, 238, 238); | |
1449 return visitedLink ? visitedLinkColor() : color(); | |
1450 } | |
1451 | |
1452 Color LayoutStyle::visitedDependentColor(int colorProperty) const | |
1453 { | |
1454 Color unvisitedColor = colorIncludingFallback(colorProperty, false); | |
1455 if (insideLink() != InsideVisitedLink) | |
1456 return unvisitedColor; | |
1457 | |
1458 Color visitedColor = colorIncludingFallback(colorProperty, true); | |
1459 | |
1460 // FIXME: Technically someone could explicitly specify the color transparent
, but for now we'll just | |
1461 // assume that if the background color is transparent that it wasn't set. No
te that it's weird that | |
1462 // we're returning unvisited info for a visited link, but given our restrict
ion that the alpha values | |
1463 // have to match, it makes more sense to return the unvisited background col
or if specified than it | |
1464 // does to return black. This behavior matches what Firefox 4 does as well. | |
1465 if (colorProperty == CSSPropertyBackgroundColor && visitedColor == Color::tr
ansparent) | |
1466 return unvisitedColor; | |
1467 | |
1468 // Take the alpha from the unvisited color, but get the RGB values from the
visited color. | |
1469 return Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(),
unvisitedColor.alpha()); | |
1470 } | |
1471 | |
1472 const BorderValue& LayoutStyle::borderBefore() const | |
1473 { | |
1474 switch (writingMode()) { | |
1475 case TopToBottomWritingMode: | |
1476 return borderTop(); | |
1477 case BottomToTopWritingMode: | |
1478 return borderBottom(); | |
1479 case LeftToRightWritingMode: | |
1480 return borderLeft(); | |
1481 case RightToLeftWritingMode: | |
1482 return borderRight(); | |
1483 } | |
1484 ASSERT_NOT_REACHED(); | |
1485 return borderTop(); | |
1486 } | |
1487 | |
1488 const BorderValue& LayoutStyle::borderAfter() const | |
1489 { | |
1490 switch (writingMode()) { | |
1491 case TopToBottomWritingMode: | |
1492 return borderBottom(); | |
1493 case BottomToTopWritingMode: | |
1494 return borderTop(); | |
1495 case LeftToRightWritingMode: | |
1496 return borderRight(); | |
1497 case RightToLeftWritingMode: | |
1498 return borderLeft(); | |
1499 } | |
1500 ASSERT_NOT_REACHED(); | |
1501 return borderBottom(); | |
1502 } | |
1503 | |
1504 const BorderValue& LayoutStyle::borderStart() const | |
1505 { | |
1506 if (isHorizontalWritingMode()) | |
1507 return isLeftToRightDirection() ? borderLeft() : borderRight(); | |
1508 return isLeftToRightDirection() ? borderTop() : borderBottom(); | |
1509 } | |
1510 | |
1511 const BorderValue& LayoutStyle::borderEnd() const | |
1512 { | |
1513 if (isHorizontalWritingMode()) | |
1514 return isLeftToRightDirection() ? borderRight() : borderLeft(); | |
1515 return isLeftToRightDirection() ? borderBottom() : borderTop(); | |
1516 } | |
1517 | |
1518 unsigned short LayoutStyle::borderBeforeWidth() const | |
1519 { | |
1520 switch (writingMode()) { | |
1521 case TopToBottomWritingMode: | |
1522 return borderTopWidth(); | |
1523 case BottomToTopWritingMode: | |
1524 return borderBottomWidth(); | |
1525 case LeftToRightWritingMode: | |
1526 return borderLeftWidth(); | |
1527 case RightToLeftWritingMode: | |
1528 return borderRightWidth(); | |
1529 } | |
1530 ASSERT_NOT_REACHED(); | |
1531 return borderTopWidth(); | |
1532 } | |
1533 | |
1534 unsigned short LayoutStyle::borderAfterWidth() const | |
1535 { | |
1536 switch (writingMode()) { | |
1537 case TopToBottomWritingMode: | |
1538 return borderBottomWidth(); | |
1539 case BottomToTopWritingMode: | |
1540 return borderTopWidth(); | |
1541 case LeftToRightWritingMode: | |
1542 return borderRightWidth(); | |
1543 case RightToLeftWritingMode: | |
1544 return borderLeftWidth(); | |
1545 } | |
1546 ASSERT_NOT_REACHED(); | |
1547 return borderBottomWidth(); | |
1548 } | |
1549 | |
1550 unsigned short LayoutStyle::borderStartWidth() const | |
1551 { | |
1552 if (isHorizontalWritingMode()) | |
1553 return isLeftToRightDirection() ? borderLeftWidth() : borderRightWidth()
; | |
1554 return isLeftToRightDirection() ? borderTopWidth() : borderBottomWidth(); | |
1555 } | |
1556 | |
1557 unsigned short LayoutStyle::borderEndWidth() const | |
1558 { | |
1559 if (isHorizontalWritingMode()) | |
1560 return isLeftToRightDirection() ? borderRightWidth() : borderLeftWidth()
; | |
1561 return isLeftToRightDirection() ? borderBottomWidth() : borderTopWidth(); | |
1562 } | |
1563 | |
1564 void LayoutStyle::setMarginStart(const Length& margin) | |
1565 { | |
1566 if (isHorizontalWritingMode()) { | |
1567 if (isLeftToRightDirection()) | |
1568 setMarginLeft(margin); | |
1569 else | |
1570 setMarginRight(margin); | |
1571 } else { | |
1572 if (isLeftToRightDirection()) | |
1573 setMarginTop(margin); | |
1574 else | |
1575 setMarginBottom(margin); | |
1576 } | |
1577 } | |
1578 | |
1579 void LayoutStyle::setMarginEnd(const Length& margin) | |
1580 { | |
1581 if (isHorizontalWritingMode()) { | |
1582 if (isLeftToRightDirection()) | |
1583 setMarginRight(margin); | |
1584 else | |
1585 setMarginLeft(margin); | |
1586 } else { | |
1587 if (isLeftToRightDirection()) | |
1588 setMarginBottom(margin); | |
1589 else | |
1590 setMarginTop(margin); | |
1591 } | |
1592 } | |
1593 | |
1594 void LayoutStyle::setMotionPath(PassRefPtr<StyleMotionPath> path) | |
1595 { | |
1596 ASSERT(path); | |
1597 rareNonInheritedData.access()->m_transform.access()->m_motion.m_path = path; | |
1598 } | |
1599 | |
1600 void LayoutStyle::resetMotionPath() | |
1601 { | |
1602 rareNonInheritedData.access()->m_transform.access()->m_motion.m_path = nullp
tr; | |
1603 } | |
1604 | |
1605 bool LayoutStyle::columnRuleEquivalent(const LayoutStyle* otherStyle) const | |
1606 { | |
1607 return columnRuleStyle() == otherStyle->columnRuleStyle() | |
1608 && columnRuleWidth() == otherStyle->columnRuleWidth() | |
1609 && visitedDependentColor(CSSPropertyWebkitColumnRuleColor) == otherStyle
->visitedDependentColor(CSSPropertyWebkitColumnRuleColor); | |
1610 } | |
1611 | |
1612 TextEmphasisMark LayoutStyle::textEmphasisMark() const | |
1613 { | |
1614 TextEmphasisMark mark = static_cast<TextEmphasisMark>(rareInheritedData->tex
tEmphasisMark); | |
1615 if (mark != TextEmphasisMarkAuto) | |
1616 return mark; | |
1617 | |
1618 if (isHorizontalWritingMode()) | |
1619 return TextEmphasisMarkDot; | |
1620 | |
1621 return TextEmphasisMarkSesame; | |
1622 } | |
1623 | |
1624 Color LayoutStyle::initialTapHighlightColor() | |
1625 { | |
1626 return LayoutTheme::tapHighlightColor(); | |
1627 } | |
1628 | |
1629 #if ENABLE(OILPAN) | |
1630 const FilterOperations& LayoutStyle::initialFilter() | |
1631 { | |
1632 DEFINE_STATIC_LOCAL(Persistent<FilterOperationsWrapper>, ops, (FilterOperati
onsWrapper::create())); | |
1633 return ops->operations(); | |
1634 } | |
1635 #endif | |
1636 | |
1637 LayoutRectOutsets LayoutStyle::imageOutsets(const NinePieceImage& image) const | |
1638 { | |
1639 return LayoutRectOutsets( | |
1640 NinePieceImage::computeOutset(image.outset().top(), borderTopWidth()), | |
1641 NinePieceImage::computeOutset(image.outset().right(), borderRightWidth()
), | |
1642 NinePieceImage::computeOutset(image.outset().bottom(), borderBottomWidth
()), | |
1643 NinePieceImage::computeOutset(image.outset().left(), borderLeftWidth()))
; | |
1644 } | |
1645 | |
1646 void LayoutStyle::setBorderImageSource(PassRefPtr<StyleImage> image) | |
1647 { | |
1648 if (surround->border.m_image.image() == image.get()) | |
1649 return; | |
1650 surround.access()->border.m_image.setImage(image); | |
1651 } | |
1652 | |
1653 void LayoutStyle::setBorderImageSlices(const LengthBox& slices) | |
1654 { | |
1655 if (surround->border.m_image.imageSlices() == slices) | |
1656 return; | |
1657 surround.access()->border.m_image.setImageSlices(slices); | |
1658 } | |
1659 | |
1660 void LayoutStyle::setBorderImageSlicesFill(bool fill) | |
1661 { | |
1662 if (surround->border.m_image.fill() == fill) | |
1663 return; | |
1664 surround.access()->border.m_image.setFill(fill); | |
1665 } | |
1666 | |
1667 void LayoutStyle::setBorderImageWidth(const BorderImageLengthBox& slices) | |
1668 { | |
1669 if (surround->border.m_image.borderSlices() == slices) | |
1670 return; | |
1671 surround.access()->border.m_image.setBorderSlices(slices); | |
1672 } | |
1673 | |
1674 void LayoutStyle::setBorderImageOutset(const BorderImageLengthBox& outset) | |
1675 { | |
1676 if (surround->border.m_image.outset() == outset) | |
1677 return; | |
1678 surround.access()->border.m_image.setOutset(outset); | |
1679 } | |
1680 | |
1681 bool LayoutStyle::borderObscuresBackground() const | |
1682 { | |
1683 if (!hasBorder()) | |
1684 return false; | |
1685 | |
1686 // Bail if we have any border-image for now. We could look at the image alph
a to improve this. | |
1687 if (borderImage().image()) | |
1688 return false; | |
1689 | |
1690 BorderEdge edges[4]; | |
1691 getBorderEdgeInfo(edges); | |
1692 | |
1693 for (int i = BSTop; i <= BSLeft; ++i) { | |
1694 const BorderEdge& currEdge = edges[i]; | |
1695 if (!currEdge.obscuresBackground()) | |
1696 return false; | |
1697 } | |
1698 | |
1699 return true; | |
1700 } | |
1701 | |
1702 void LayoutStyle::getBorderEdgeInfo(BorderEdge edges[], bool includeLogicalLeftE
dge, bool includeLogicalRightEdge) const | |
1703 { | |
1704 bool horizontal = isHorizontalWritingMode(); | |
1705 | |
1706 edges[BSTop] = BorderEdge(borderTopWidth(), | |
1707 visitedDependentColor(CSSPropertyBorderTopColor), | |
1708 borderTopStyle(), | |
1709 borderTopIsTransparent(), | |
1710 horizontal || includeLogicalLeftEdge); | |
1711 | |
1712 edges[BSRight] = BorderEdge(borderRightWidth(), | |
1713 visitedDependentColor(CSSPropertyBorderRightColor), | |
1714 borderRightStyle(), | |
1715 borderRightIsTransparent(), | |
1716 !horizontal || includeLogicalRightEdge); | |
1717 | |
1718 edges[BSBottom] = BorderEdge(borderBottomWidth(), | |
1719 visitedDependentColor(CSSPropertyBorderBottomColor), | |
1720 borderBottomStyle(), | |
1721 borderBottomIsTransparent(), | |
1722 horizontal || includeLogicalRightEdge); | |
1723 | |
1724 edges[BSLeft] = BorderEdge(borderLeftWidth(), | |
1725 visitedDependentColor(CSSPropertyBorderLeftColor), | |
1726 borderLeftStyle(), | |
1727 borderLeftIsTransparent(), | |
1728 !horizontal || includeLogicalLeftEdge); | |
1729 } | |
1730 | |
1731 } // namespace blink | |
OLD | NEW |