Support ::before/::after pseudo elements on elements with display:contents
[WebKit-https.git] / Source / WebCore / style / StyleRelations.cpp
1 /*
2  * Copyright (C) 2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "StyleRelations.h"
28
29 #include "Element.h"
30 #include "NodeRenderStyle.h"
31 #include "RenderStyle.h"
32 #include "StyleUpdate.h"
33
34 namespace WebCore {
35 namespace Style {
36
37 std::unique_ptr<Relations> commitRelationsToRenderStyle(RenderStyle& style, const Element& element, const Relations& relations)
38 {
39     std::unique_ptr<Relations> remainingRelations;
40
41     auto appendStyleRelation = [&remainingRelations] (const Relation& relation) {
42         if (!remainingRelations)
43             remainingRelations = std::make_unique<Relations>();
44         remainingRelations->append(relation);
45     };
46
47     for (auto& relation : relations) {
48         if (relation.element != &element) {
49             appendStyleRelation(relation);
50             continue;
51         }
52         switch (relation.type) {
53         case Relation::AffectedByActive:
54             style.setAffectedByActive();
55             appendStyleRelation(relation);
56             break;
57         case Relation::AffectedByDrag:
58             style.setAffectedByDrag();
59             break;
60         case Relation::AffectedByEmpty:
61             style.setEmptyState(relation.value);
62             appendStyleRelation(relation);
63             break;
64         case Relation::AffectedByHover:
65             style.setAffectedByHover();
66             break;
67         case Relation::FirstChild:
68             style.setFirstChildState();
69             break;
70         case Relation::LastChild:
71             style.setLastChildState();
72             break;
73         case Relation::Unique:
74             style.setUnique();
75             break;
76         case Relation::AffectedByFocusWithin:
77         case Relation::AffectedByPreviousSibling:
78         case Relation::AffectsNextSibling:
79         case Relation::ChildrenAffectedByBackwardPositionalRules:
80         case Relation::ChildrenAffectedByFirstChildRules:
81         case Relation::ChildrenAffectedByPropertyBasedBackwardPositionalRules:
82         case Relation::ChildrenAffectedByLastChildRules:
83         case Relation::NthChildIndex:
84             appendStyleRelation(relation);
85             break;
86         }
87     }
88     return remainingRelations;
89 }
90
91 void commitRelations(std::unique_ptr<Relations> relations, Update& update)
92 {
93     if (!relations)
94         return;
95     for (auto& relation : *relations) {
96         auto& element = const_cast<Element&>(*relation.element);
97         switch (relation.type) {
98         case Relation::AffectedByActive:
99             element.setStyleAffectedByActive();
100             break;
101         case Relation::AffectedByDrag:
102             element.setChildrenAffectedByDrag();
103             break;
104         case Relation::AffectedByEmpty:
105             element.setStyleAffectedByEmpty();
106             break;
107         case Relation::AffectedByFocusWithin:
108             element.setStyleAffectedByFocusWithin();
109             break;
110         case Relation::AffectedByHover:
111             element.setChildrenAffectedByHover();
112             break;
113         case Relation::AffectedByPreviousSibling:
114             element.setStyleIsAffectedByPreviousSibling();
115             break;
116         case Relation::AffectsNextSibling: {
117             auto* sibling = &element;
118             for (unsigned i = 0; i < relation.value && sibling; ++i, sibling = sibling->nextElementSibling())
119                 sibling->setAffectsNextSiblingElementStyle();
120             break;
121         }
122         case Relation::ChildrenAffectedByBackwardPositionalRules:
123             element.setChildrenAffectedByBackwardPositionalRules();
124             break;
125         case Relation::ChildrenAffectedByFirstChildRules:
126             element.setChildrenAffectedByFirstChildRules();
127             break;
128         case Relation::ChildrenAffectedByPropertyBasedBackwardPositionalRules:
129             element.setChildrenAffectedByBackwardPositionalRules();
130             element.setChildrenAffectedByPropertyBasedBackwardPositionalRules();
131             break;
132         case Relation::ChildrenAffectedByLastChildRules:
133             element.setChildrenAffectedByLastChildRules();
134             break;
135         case Relation::FirstChild:
136             if (auto* style = update.elementStyle(element))
137                 style->setFirstChildState();
138             break;
139         case Relation::LastChild:
140             if (auto* style = update.elementStyle(element))
141                 style->setLastChildState();
142             break;
143         case Relation::NthChildIndex:
144             if (auto* style = update.elementStyle(element))
145                 style->setUnique();
146             element.setChildIndex(relation.value);
147             break;
148         case Relation::Unique:
149             if (auto* style = update.elementStyle(element))
150                 style->setUnique();
151             break;
152         }
153     }
154 }
155
156 }
157 }