bbb88c2cb12d2256209a6b34d035f88969cb67e1
[WebKit-https.git] / Source / WebCore / style / StyleResolveTree.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2001 Peter Kelly (pmk@post.com)
5  *           (C) 2001 Dirk Mueller (mueller@kde.org)
6  *           (C) 2007 David Smith (catfish.man@gmail.com)
7  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012, 2013 Apple Inc. All rights reserved.
8  *           (C) 2007 Eric Seidel (eric@webkit.org)
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  */
25
26 #include "config.h"
27 #include "StyleResolveTree.h"
28
29 #include "AXObjectCache.h"
30 #include "Element.h"
31 #include "ElementIterator.h"
32 #include "ElementRareData.h"
33 #include "ElementTraversal.h"
34 #include "FlowThreadController.h"
35 #include "NodeRenderStyle.h"
36 #include "NodeRenderingTraversal.h"
37 #include "NodeTraversal.h"
38 #include "RenderElement.h"
39 #include "RenderFullScreen.h"
40 #include "RenderNamedFlowThread.h"
41 #include "RenderText.h"
42 #include "RenderView.h"
43 #include "RenderWidget.h"
44 #include "Settings.h"
45 #include "ShadowRoot.h"
46 #include "StyleResolveForDocument.h"
47 #include "StyleResolver.h"
48 #include "Text.h"
49
50 #if PLATFORM(IOS)
51 #include "CSSFontSelector.h"
52 #include "WKContentObservation.h"
53 #endif
54
55 namespace WebCore {
56
57 namespace Style {
58
59 enum DetachType { NormalDetach, ReattachDetach };
60
61 static void attachRenderTree(Element&, RenderStyle* resolvedStyle);
62 static void detachRenderTree(Element&, DetachType);
63
64 Change determineChange(const RenderStyle* s1, const RenderStyle* s2, Settings* settings)
65 {
66     if (!s1 || !s2)
67         return Detach;
68     if (s1->display() != s2->display())
69         return Detach;
70     if (s1->hasPseudoStyle(FIRST_LETTER) != s2->hasPseudoStyle(FIRST_LETTER))
71         return Detach;
72     // We just detach if a renderer acquires or loses a column-span, since spanning elements
73     // typically won't contain much content.
74     if (s1->columnSpan() != s2->columnSpan())
75         return Detach;
76     if (settings->regionBasedColumnsEnabled()) {
77         bool specifiesColumns1 = !s1->hasAutoColumnCount() || !s1->hasAutoColumnWidth();
78         bool specifiesColumns2 = !s2->hasAutoColumnCount() || !s2->hasAutoColumnWidth();
79         if (specifiesColumns1 != specifiesColumns2)
80             return Detach;
81     }
82     if (!s1->contentDataEquivalent(s2))
83         return Detach;
84     // When text-combine property has been changed, we need to prepare a separate renderer object.
85     // When text-combine is on, we use RenderCombineText, otherwise RenderText.
86     // https://bugs.webkit.org/show_bug.cgi?id=55069
87     if (s1->hasTextCombine() != s2->hasTextCombine())
88         return Detach;
89     // We need to reattach the node, so that it is moved to the correct RenderFlowThread.
90     if (s1->flowThread() != s2->flowThread())
91         return Detach;
92     // When the region thread has changed, we need to prepare a separate render region object.
93     if (s1->regionThread() != s2->regionThread())
94         return Detach;
95
96     if (*s1 != *s2) {
97         if (s1->inheritedNotEqual(s2))
98             return Inherit;
99         if (s1->hasExplicitlyInheritedProperties() || s2->hasExplicitlyInheritedProperties())
100             return Inherit;
101
102         return NoInherit;
103     }
104     // If the pseudoStyles have changed, we want any StyleChange that is not NoChange
105     // because setStyle will do the right thing with anything else.
106     if (s1->hasAnyPublicPseudoStyles()) {
107         for (PseudoId pseudoId = FIRST_PUBLIC_PSEUDOID; pseudoId < FIRST_INTERNAL_PSEUDOID; pseudoId = static_cast<PseudoId>(pseudoId + 1)) {
108             if (s1->hasPseudoStyle(pseudoId)) {
109                 RenderStyle* ps2 = s2->getCachedPseudoStyle(pseudoId);
110                 if (!ps2)
111                     return NoInherit;
112                 RenderStyle* ps1 = s1->getCachedPseudoStyle(pseudoId);
113                 if (!ps1 || *ps1 != *ps2)
114                     return NoInherit;
115             }
116         }
117     }
118
119     return NoChange;
120 }
121
122 static bool isRendererReparented(const RenderObject* renderer)
123 {
124     if (!renderer->node()->isElementNode())
125         return false;
126     if (renderer->style() && !renderer->style()->flowThread().isEmpty())
127         return true;
128     return false;
129 }
130
131 static RenderObject* nextSiblingRenderer(const Element& element, const ContainerNode* renderingParentNode)
132 {
133     // Avoid an O(N^2) problem with this function by not checking for
134     // nextRenderer() when the parent element hasn't attached yet.
135     // FIXME: Why would we get here anyway if parent is not attached?
136     if (renderingParentNode && !renderingParentNode->attached())
137         return 0;
138     for (Node* sibling = NodeRenderingTraversal::nextSibling(&element); sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
139         RenderObject* renderer = sibling->renderer();
140         if (renderer && !isRendererReparented(renderer))
141             return renderer;
142     }
143     return 0;
144 }
145
146 static bool shouldCreateRenderer(const Element& element, const ContainerNode* renderingParent)
147 {
148     if (!element.document().shouldCreateRenderers())
149         return false;
150     if (!renderingParent)
151         return false;
152     RenderObject* parentRenderer = renderingParent->renderer();
153     if (!parentRenderer)
154         return false;
155     if (!parentRenderer->canHaveChildren() && !(element.isPseudoElement() && parentRenderer->canHaveGeneratedChildren()))
156         return false;
157     if (!renderingParent->childShouldCreateRenderer(&element))
158         return false;
159     return true;
160 }
161
162 // Check the specific case of elements that are children of regions but are flowed into a flow thread themselves.
163 static bool elementInsideRegionNeedsRenderer(Element& element, const ContainerNode* renderingParentNode, RefPtr<RenderStyle>& style)
164 {
165 #if ENABLE(CSS_REGIONS)
166     const RenderObject* parentRenderer = renderingParentNode ? renderingParentNode->renderer() : 0;
167
168     bool parentIsRegion = parentRenderer && !parentRenderer->canHaveChildren() && parentRenderer->isRenderRegion();
169     bool parentIsNonRenderedInsideRegion = !parentRenderer && element.parentElement() && element.parentElement()->isInsideRegion();
170     if (!parentIsRegion && !parentIsNonRenderedInsideRegion)
171         return false;
172
173     if (!style)
174         style = element.styleForRenderer();
175
176     // Children of this element will only be allowed to be flowed into other flow-threads if display is NOT none.
177     if (element.rendererIsNeeded(*style))
178         element.setIsInsideRegion(true);
179
180     if (element.shouldMoveToFlowThread(*style))
181         return true;
182 #endif
183     return false;
184 }
185
186 #if ENABLE(CSS_REGIONS)
187 static RenderNamedFlowThread* moveToFlowThreadIfNeeded(Element& element, const RenderStyle& style)
188 {
189     if (!element.shouldMoveToFlowThread(style))
190         return 0;
191     FlowThreadController& flowThreadController = element.document().renderView()->flowThreadController();
192     RenderNamedFlowThread& parentFlowRenderer = flowThreadController.ensureRenderFlowThreadWithName(style.flowThread());
193     flowThreadController.registerNamedFlowContentElement(element, parentFlowRenderer);
194     return &parentFlowRenderer;
195 }
196 #endif
197
198 static void createRendererIfNeeded(Element& element, RenderStyle* resolvedStyle)
199 {
200     ASSERT(!element.renderer());
201
202     Document& document = element.document();
203     ContainerNode* renderingParentNode = NodeRenderingTraversal::parent(&element);
204
205     RefPtr<RenderStyle> style = resolvedStyle;
206
207     element.setIsInsideRegion(false);
208
209     if (!shouldCreateRenderer(element, renderingParentNode) && !elementInsideRegionNeedsRenderer(element, renderingParentNode, style))
210         return;
211
212     if (!style)
213         style = element.styleForRenderer();
214
215     RenderNamedFlowThread* parentFlowRenderer = 0;
216 #if ENABLE(CSS_REGIONS)
217     parentFlowRenderer = moveToFlowThreadIfNeeded(element, *style);
218 #endif
219
220     if (!element.rendererIsNeeded(*style))
221         return;
222
223     RenderElement* parentRenderer;
224     RenderObject* nextRenderer;
225     if (parentFlowRenderer) {
226         parentRenderer = parentFlowRenderer;
227         nextRenderer = parentFlowRenderer->nextRendererForNode(&element);
228     } else {
229         // FIXME: Make this path Element only, handle the root special case separately.
230         parentRenderer = renderingParentNode->renderer();
231         nextRenderer = nextSiblingRenderer(element, renderingParentNode);
232     }
233
234     RenderElement* newRenderer = element.createRenderer(*document.renderArena(), *style);
235     if (!newRenderer)
236         return;
237     if (!parentRenderer->isChildAllowed(newRenderer, style.get())) {
238         newRenderer->destroy();
239         return;
240     }
241
242     // Make sure the RenderObject already knows it is going to be added to a RenderFlowThread before we set the style
243     // for the first time. Otherwise code using inRenderFlowThread() in the styleWillChange and styleDidChange will fail.
244     newRenderer->setFlowThreadState(parentRenderer->flowThreadState());
245
246     element.setRenderer(newRenderer);
247     newRenderer->setAnimatableStyle(style.release()); // setAnimatableStyle() can depend on renderer() already being set.
248
249 #if ENABLE(FULLSCREEN_API)
250     if (document.webkitIsFullScreen() && document.webkitCurrentFullScreenElement() == &element) {
251         newRenderer = RenderFullScreen::wrapRenderer(newRenderer, parentRenderer, document);
252         if (!newRenderer)
253             return;
254     }
255 #endif
256     // Note: Adding newRenderer instead of renderer(). renderer() may be a child of newRenderer.
257     parentRenderer->addChild(newRenderer, nextRenderer);
258 }
259
260 static RenderObject* previousSiblingRenderer(const Text& textNode)
261 {
262     if (textNode.renderer())
263         return textNode.renderer()->previousSibling();
264     for (Node* sibling = NodeRenderingTraversal::previousSibling(&textNode); sibling; sibling = NodeRenderingTraversal::previousSibling(sibling)) {
265         RenderObject* renderer = sibling->renderer();
266         if (renderer && !isRendererReparented(renderer))
267             return renderer;
268     }
269     return 0;
270 }
271
272 static RenderObject* nextSiblingRenderer(const Text& textNode)
273 {
274     if (textNode.renderer())
275         return textNode.renderer()->nextSibling();
276     for (Node* sibling = NodeRenderingTraversal::nextSibling(&textNode); sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
277         RenderObject* renderer = sibling->renderer();
278         if (renderer && !isRendererReparented(renderer))
279             return renderer;
280     }
281     return 0;
282 }
283
284 static void reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(Node& current)
285 {
286     if (current.isInsertionPoint())
287         return;
288     // This function finds sibling text renderers where the results of textRendererIsNeeded may have changed as a result of
289     // the current node gaining or losing the renderer. This can only affect white space text nodes.
290     for (Node* sibling = NodeRenderingTraversal::nextSibling(&current); sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
291         // Siblings haven't been attached yet. They will be handled normally when they are.
292         if (!sibling->attached())
293             return;
294         if (sibling->isElementNode()) {
295             // Text renderers beyond rendered elements can't be affected.
296             if (!sibling->renderer() || isRendererReparented(sibling->renderer()))
297                 continue;
298             return;
299         }
300         if (!sibling->isTextNode())
301             continue;
302         Text& textSibling = *toText(sibling);
303         if (!textSibling.length() || !textSibling.containsOnlyWhitespace())
304             return;
305         Text& whitespaceTextSibling = textSibling;
306         bool hadRenderer = whitespaceTextSibling.renderer();
307         detachTextRenderer(whitespaceTextSibling);
308         attachTextRenderer(whitespaceTextSibling);
309         // No changes, futher renderers can't be affected.
310         if (hadRenderer == !!whitespaceTextSibling.renderer())
311             return;
312     }
313 }
314
315 static bool textRendererIsNeeded(const Text& textNode, const RenderObject& parentRenderer, const RenderStyle& style)
316 {
317     if (textNode.isEditingText())
318         return true;
319     if (!textNode.length())
320         return false;
321     if (style.display() == NONE)
322         return false;
323     if (!textNode.containsOnlyWhitespace())
324         return true;
325     // This text node has nothing but white space. We may still need a renderer in some cases.
326     if (parentRenderer.isTable() || parentRenderer.isTableRow() || parentRenderer.isTableSection() || parentRenderer.isRenderTableCol() || parentRenderer.isFrameSet())
327         return false;
328     if (style.preserveNewline()) // pre/pre-wrap/pre-line always make renderers.
329         return true;
330
331     RenderObject* previousRenderer = previousSiblingRenderer(textNode);
332     if (previousRenderer && previousRenderer->isBR()) // <span><br/> <br/></span>
333         return false;
334         
335     if (parentRenderer.isRenderInline()) {
336         // <span><div/> <div/></span>
337         if (previousRenderer && !previousRenderer->isInline())
338             return false;
339     } else {
340         if (parentRenderer.isRenderBlock() && !parentRenderer.childrenInline() && (!previousRenderer || !previousRenderer->isInline()))
341             return false;
342         
343         RenderObject* first = toRenderElement(parentRenderer).firstChild();
344         while (first && first->isFloatingOrOutOfFlowPositioned())
345             first = first->nextSibling();
346         RenderObject* nextRenderer = nextSiblingRenderer(textNode);
347         if (!first || nextRenderer == first) {
348             // Whitespace at the start of a block just goes away. Don't even make a render object for this text.
349             return false;
350         }
351     }
352     return true;
353 }
354
355 static void createTextRendererIfNeeded(Text& textNode)
356 {
357     ASSERT(!textNode.renderer());
358
359     ContainerNode* renderingParentNode = NodeRenderingTraversal::parent(&textNode);
360     if (!renderingParentNode)
361         return;
362     RenderElement* parentRenderer = renderingParentNode->renderer();
363     if (!parentRenderer || !parentRenderer->canHaveChildren())
364         return;
365     if (!renderingParentNode->childShouldCreateRenderer(&textNode))
366         return;
367
368     Document& document = textNode.document();
369     RefPtr<RenderStyle> style = parentRenderer->style();
370
371     if (!textRendererIsNeeded(textNode, *parentRenderer, *style))
372         return;
373     RenderText* newRenderer = textNode.createTextRenderer(*document.renderArena(), *style);
374     if (!newRenderer)
375         return;
376     if (!parentRenderer->isChildAllowed(newRenderer, style.get())) {
377         newRenderer->destroy();
378         return;
379     }
380
381     // Make sure the RenderObject already knows it is going to be added to a RenderFlowThread before we set the style
382     // for the first time. Otherwise code using inRenderFlowThread() in the styleWillChange and styleDidChange will fail.
383     newRenderer->setFlowThreadState(parentRenderer->flowThreadState());
384
385     RenderObject* nextRenderer = nextSiblingRenderer(textNode);
386     textNode.setRenderer(newRenderer);
387     // Parent takes care of the animations, no need to call setAnimatableStyle.
388     parentRenderer->addChild(newRenderer, nextRenderer);
389 }
390
391 void attachTextRenderer(Text& textNode)
392 {
393     createTextRendererIfNeeded(textNode);
394
395     textNode.setAttached(true);
396     textNode.clearNeedsStyleRecalc();
397 }
398
399 void detachTextRenderer(Text& textNode)
400 {
401     if (textNode.renderer())
402         textNode.renderer()->destroyAndCleanupAnonymousWrappers();
403     textNode.setRenderer(0);
404     textNode.setAttached(false);
405 }
406
407 void updateTextRendererAfterContentChange(Text& textNode, unsigned offsetOfReplacedData, unsigned lengthOfReplacedData)
408 {
409     if (!textNode.attached())
410         return;
411     RenderText* textRenderer = toRenderText(textNode.renderer());
412     if (!textRenderer) {
413         attachTextRenderer(textNode);
414         reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(textNode);
415         return;
416     }
417     RenderObject* parentRenderer = NodeRenderingTraversal::parent(&textNode)->renderer();
418     if (!textRendererIsNeeded(textNode, *parentRenderer, *textRenderer->style())) {
419         detachTextRenderer(textNode);
420         attachTextRenderer(textNode);
421         reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(textNode);
422         return;
423     }
424     textRenderer->setTextWithOffset(textNode.dataImpl(), offsetOfReplacedData, lengthOfReplacedData);
425 }
426
427 static void attachChildren(ContainerNode& current)
428 {
429     for (Node* child = current.firstChild(); child; child = child->nextSibling()) {
430         ASSERT(!child->attached() || current.shadowRoot());
431         if (child->attached())
432             continue;
433         if (child->isTextNode()) {
434             attachTextRenderer(*toText(child));
435             continue;
436         }
437         if (child->isElementNode())
438             attachRenderTree(*toElement(child), nullptr);
439     }
440 }
441
442 static void attachShadowRoot(ShadowRoot& shadowRoot)
443 {
444     if (shadowRoot.attached())
445         return;
446     StyleResolver& styleResolver = shadowRoot.document().ensureStyleResolver();
447     styleResolver.pushParentShadowRoot(&shadowRoot);
448
449     attachChildren(shadowRoot);
450
451     styleResolver.popParentShadowRoot(&shadowRoot);
452
453     shadowRoot.clearNeedsStyleRecalc();
454     shadowRoot.setAttached(true);
455 }
456
457 static void attachRenderTree(Element& current, RenderStyle* resolvedStyle)
458 {
459     PostAttachCallbackDisabler callbackDisabler(current);
460     WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
461
462     if (current.hasCustomStyleResolveCallbacks())
463         current.willAttachRenderers();
464
465     createRendererIfNeeded(current, resolvedStyle);
466
467     if (current.parentElement() && current.parentElement()->isInCanvasSubtree())
468         current.setIsInCanvasSubtree(true);
469
470     current.updateBeforePseudoElement(NoChange);
471
472     StyleResolverParentPusher parentPusher(&current);
473
474     // When a shadow root exists, it does the work of attaching the children.
475     if (ShadowRoot* shadowRoot = current.shadowRoot()) {
476         parentPusher.push();
477         attachShadowRoot(*shadowRoot);
478     } else if (current.firstChild())
479         parentPusher.push();
480
481     attachChildren(current);
482
483     current.setAttached(true);
484     current.clearNeedsStyleRecalc();
485
486     if (AXObjectCache* cache = current.document().axObjectCache())
487         cache->updateCacheAfterNodeIsAttached(&current);
488
489     current.updateAfterPseudoElement(NoChange);
490
491     current.updateFocusAppearanceAfterAttachIfNeeded();
492     
493     if (current.hasCustomStyleResolveCallbacks())
494         current.didAttachRenderers();
495 }
496
497 static void detachChildren(ContainerNode& current, DetachType detachType)
498 {
499     for (Node* child = current.firstChild(); child; child = child->nextSibling()) {
500         if (child->isTextNode()) {
501             Style::detachTextRenderer(*toText(child));
502             continue;
503         }
504         if (child->isElementNode())
505             detachRenderTree(*toElement(child), detachType);
506     }
507     current.clearChildNeedsStyleRecalc();
508 }
509
510 static void detachShadowRoot(ShadowRoot& shadowRoot, DetachType detachType)
511 {
512     if (!shadowRoot.attached())
513         return;
514     detachChildren(shadowRoot, detachType);
515
516     shadowRoot.setAttached(false);
517 }
518
519 static void detachRenderTree(Element& current, DetachType detachType)
520 {
521     WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
522
523     if (current.hasCustomStyleResolveCallbacks())
524         current.willDetachRenderers();
525
526     current.clearStyleDerivedDataBeforeDetachingRenderer();
527
528     // Do not remove the element's hovered and active status
529     // if performing a reattach.
530     if (detachType != ReattachDetach)
531         current.clearHoverAndActiveStatusBeforeDetachingRenderer();
532
533     if (ShadowRoot* shadowRoot = current.shadowRoot())
534         detachShadowRoot(*shadowRoot, detachType);
535
536     detachChildren(current, detachType);
537
538     if (current.renderer())
539         current.renderer()->destroyAndCleanupAnonymousWrappers();
540     current.setRenderer(0);
541
542     current.setAttached(false);
543
544     if (current.hasCustomStyleResolveCallbacks())
545         current.didDetachRenderers();
546 }
547
548 static bool pseudoStyleCacheIsInvalid(RenderElement* renderer, RenderStyle* newStyle)
549 {
550     const RenderStyle* currentStyle = renderer->style();
551
552     const PseudoStyleCache* pseudoStyleCache = currentStyle->cachedPseudoStyles();
553     if (!pseudoStyleCache)
554         return false;
555
556     size_t cacheSize = pseudoStyleCache->size();
557     for (size_t i = 0; i < cacheSize; ++i) {
558         RefPtr<RenderStyle> newPseudoStyle;
559         PseudoId pseudoId = pseudoStyleCache->at(i)->styleType();
560         if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED)
561             newPseudoStyle = renderer->uncachedFirstLineStyle(newStyle);
562         else
563             newPseudoStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(pseudoId), newStyle, newStyle);
564         if (!newPseudoStyle)
565             return true;
566         if (*newPseudoStyle != *pseudoStyleCache->at(i)) {
567             if (pseudoId < FIRST_INTERNAL_PSEUDOID)
568                 newStyle->setHasPseudoStyle(pseudoId);
569             newStyle->addCachedPseudoStyle(newPseudoStyle);
570             if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED) {
571                 // FIXME: We should do an actual diff to determine whether a repaint vs. layout
572                 // is needed, but for now just assume a layout will be required. The diff code
573                 // in RenderObject::setStyle would need to be factored out so that it could be reused.
574                 renderer->setNeedsLayoutAndPrefWidthsRecalc();
575             }
576             return true;
577         }
578     }
579     return false;
580 }
581
582 static Change resolveLocal(Element& current, Change inheritedChange)
583 {
584     Change localChange = Detach;
585     RefPtr<RenderStyle> newStyle;
586     RefPtr<RenderStyle> currentStyle = current.renderStyle();
587
588     Document& document = current.document();
589     if (currentStyle) {
590         newStyle = current.styleForRenderer();
591         localChange = determineChange(currentStyle.get(), newStyle.get(), document.settings());
592     }
593     if (localChange == Detach) {
594         if (current.attached())
595             detachRenderTree(current, ReattachDetach);
596         attachRenderTree(current, newStyle.get());
597         reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(current);
598
599         return Detach;
600     }
601
602     if (RenderElement* renderer = current.renderer()) {
603         if (localChange != NoChange || pseudoStyleCacheIsInvalid(renderer, newStyle.get()) || (inheritedChange == Force && renderer->requiresForcedStyleRecalcPropagation()) || current.styleChangeType() == SyntheticStyleChange)
604             renderer->setAnimatableStyle(newStyle.get());
605         else if (current.needsStyleRecalc()) {
606             // Although no change occurred, we use the new style so that the cousin style sharing code won't get
607             // fooled into believing this style is the same.
608             renderer->setStyleInternal(newStyle.get());
609         }
610     }
611
612     // If "rem" units are used anywhere in the document, and if the document element's font size changes, then go ahead and force font updating
613     // all the way down the tree. This is simpler than having to maintain a cache of objects (and such font size changes should be rare anyway).
614     if (document.styleSheetCollection().usesRemUnits() && document.documentElement() == &current && localChange != NoChange && currentStyle && newStyle && currentStyle->fontSize() != newStyle->fontSize()) {
615         // Cached RenderStyles may depend on the re units.
616         if (StyleResolver* styleResolver = document.styleResolverIfExists())
617             styleResolver->invalidateMatchedPropertiesCache();
618         return Force;
619     }
620     if (inheritedChange == Force)
621         return Force;
622     if (current.styleChangeType() >= FullStyleChange)
623         return Force;
624
625     return localChange;
626 }
627
628 static void updateTextStyle(Text& text)
629 {
630     RenderText* renderer = toRenderText(text.renderer());
631
632     if (!text.needsStyleRecalc())
633         return;
634     if (renderer)
635         renderer->setText(text.dataImpl());
636     else {
637         attachTextRenderer(text);
638         reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(text);
639     }
640     text.clearNeedsStyleRecalc();
641 }
642
643 static void resolveShadowTree(ShadowRoot* shadowRoot, Style::Change change)
644 {
645     if (!shadowRoot)
646         return;
647     StyleResolver& styleResolver = shadowRoot->document().ensureStyleResolver();
648     styleResolver.pushParentShadowRoot(shadowRoot);
649
650     for (Node* child = shadowRoot->firstChild(); child; child = child->nextSibling()) {
651         if (child->isTextNode()) {
652             // Current user agent ShadowRoots don't have immediate text children so this branch is never actually taken.
653             updateTextStyle(*toText(child));
654             continue;
655         }
656         resolveTree(*toElement(child), change);
657     }
658
659     styleResolver.popParentShadowRoot(shadowRoot);
660     shadowRoot->clearNeedsStyleRecalc();
661     shadowRoot->clearChildNeedsStyleRecalc();
662 }
663
664 #if PLATFORM(IOS)
665 static EVisibility elementImplicitVisibility(const Element* element)
666 {
667     RenderObject* renderer = element->renderer();
668     if (!renderer)
669         return VISIBLE;
670
671     RenderStyle* style = renderer->style();
672     if (!style)
673         return VISIBLE;
674
675     Length width(style->width());
676     Length height(style->height());
677     if ((width.isFixed() && width.value() <= 0) || (height.isFixed() && height.value() <= 0))
678         return HIDDEN;
679
680     Length top(style->top());
681     Length left(style->left());
682     if (left.isFixed() && width.isFixed() && -left.value() >= width.value())
683         return HIDDEN;
684
685     if (top.isFixed() && height.isFixed() && -top.value() >= height.value())
686         return HIDDEN;
687     return VISIBLE;
688 }
689
690 class CheckForVisibilityChangeOnRecalcStyle {
691 public:
692     CheckForVisibilityChangeOnRecalcStyle(Element* element, RenderStyle* currentStyle)
693         : m_element(element)
694         , m_previousDisplay(currentStyle ? currentStyle->display() : NONE)
695         , m_previousVisibility(currentStyle ? currentStyle->visibility() : HIDDEN)
696         , m_previousImplicitVisibility(WKObservingContentChanges() && WKContentChange() != WKContentVisibilityChange ? elementImplicitVisibility(element) : VISIBLE)
697     {
698     }
699     ~CheckForVisibilityChangeOnRecalcStyle()
700     {
701         if (!WKObservingContentChanges())
702             return;
703         RenderStyle* style = m_element->renderStyle();
704         if (!style)
705             return;
706         if ((m_previousDisplay == NONE && style->display() != NONE) || (m_previousVisibility == HIDDEN && style->visibility() != HIDDEN)
707             || (m_previousImplicitVisibility == HIDDEN && elementImplicitVisibility(m_element.get()) == VISIBLE))
708             WKSetObservedContentChange(WKContentVisibilityChange);
709     }
710 private:
711     RefPtr<Element> m_element;
712     EDisplay m_previousDisplay;
713     EVisibility m_previousVisibility;
714     EVisibility m_previousImplicitVisibility;
715 };
716 #endif // PLATFORM(IOS)
717
718 void resolveTree(Element& current, Change change)
719 {
720     ASSERT(change != Detach);
721
722     if (current.hasCustomStyleResolveCallbacks()) {
723         if (!current.willRecalcStyle(change))
724             return;
725     }
726
727     ContainerNode* renderingParentNode = NodeRenderingTraversal::parent(&current);
728     bool hasParentStyle = renderingParentNode && renderingParentNode->renderStyle();
729     bool hasDirectAdjacentRules = current.childrenAffectedByDirectAdjacentRules();
730     bool hasIndirectAdjacentRules = current.childrenAffectedByForwardPositionalRules();
731
732 #if PLATFORM(IOS)
733     CheckForVisibilityChangeOnRecalcStyle checkForVisibilityChange(&current, current.renderStyle());
734 #endif
735
736     if (change > NoChange || current.needsStyleRecalc())
737         current.resetComputedStyle();
738
739     if (hasParentStyle && (change >= Inherit || current.needsStyleRecalc()))
740         change = resolveLocal(current, change);
741
742     if (change != Detach) {
743         StyleResolverParentPusher parentPusher(&current);
744
745         if (ShadowRoot* shadowRoot = current.shadowRoot()) {
746             if (change >= Inherit || shadowRoot->childNeedsStyleRecalc() || shadowRoot->needsStyleRecalc()) {
747                 parentPusher.push();
748                 resolveShadowTree(shadowRoot, change);
749             }
750         }
751
752         current.updateBeforePseudoElement(change);
753
754         // FIXME: This check is good enough for :hover + foo, but it is not good enough for :hover + foo + bar.
755         // For now we will just worry about the common case, since it's a lot trickier to get the second case right
756         // without doing way too much re-resolution.
757         bool forceCheckOfNextElementSibling = false;
758         bool forceCheckOfAnyElementSibling = false;
759         for (Node* child = current.firstChild(); child; child = child->nextSibling()) {
760             if (child->isTextNode()) {
761                 updateTextStyle(*toText(child));
762                 continue;
763             }
764             if (!child->isElementNode())
765                 continue;
766             Element* childElement = toElement(child);
767             bool childRulesChanged = childElement->needsStyleRecalc() && childElement->styleChangeType() == FullStyleChange;
768             if ((forceCheckOfNextElementSibling || forceCheckOfAnyElementSibling))
769                 childElement->setNeedsStyleRecalc();
770             if (change >= Inherit || childElement->childNeedsStyleRecalc() || childElement->needsStyleRecalc()) {
771                 parentPusher.push();
772                 resolveTree(*childElement, change);
773             }
774             forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentRules;
775             forceCheckOfAnyElementSibling = forceCheckOfAnyElementSibling || (childRulesChanged && hasIndirectAdjacentRules);
776         }
777
778         current.updateAfterPseudoElement(change);
779     }
780
781     current.clearNeedsStyleRecalc();
782     current.clearChildNeedsStyleRecalc();
783     
784     if (current.hasCustomStyleResolveCallbacks())
785         current.didRecalcStyle(change);
786 }
787
788 void resolveTree(Document& document, Change change)
789 {
790     bool resolveRootStyle = change == Force || (document.shouldDisplaySeamlesslyWithParent() && change >= Inherit);
791     if (resolveRootStyle) {
792         RefPtr<RenderStyle> documentStyle = resolveForDocument(document);
793
794 #if PLATFORM(IOS)
795         // Inserting the pictograph font at the end of the font fallback list is done by the
796         // font selector, so set a font selector if needed.
797         if (Settings* settings = document.settings()) {
798             StyleResolver* styleResolver = document.styleResolverIfExists();
799             if (settings->fontFallbackPrefersPictographs() && styleResolver)
800                 documentStyle->font().update(styleResolver->fontSelector());
801         }
802 #endif
803
804         Style::Change documentChange = determineChange(documentStyle.get(), document.renderView()->style(), document.settings());
805         if (documentChange != NoChange)
806             document.renderView()->setStyle(documentStyle.release());
807     }
808
809     Element* documentElement = document.documentElement();
810     if (!documentElement)
811         return;
812     if (change < Inherit && !documentElement->childNeedsStyleRecalc() && !documentElement->needsStyleRecalc())
813         return;
814     resolveTree(*documentElement, change);
815 }
816
817 void attachRenderTree(Element& element)
818 {
819     attachRenderTree(element, nullptr);
820     reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(element);
821 }
822
823 void detachRenderTree(Element& element)
824 {
825     detachRenderTree(element, NormalDetach);
826 }
827
828 void detachRenderTreeInReattachMode(Element& element)
829 {
830     detachRenderTree(element, ReattachDetach);
831 }
832
833 void reattachRenderTree(Element& current)
834 {
835     if (current.attached())
836         detachRenderTree(current, ReattachDetach);
837     attachRenderTree(current);
838 }
839
840 }
841 }