| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2012 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Neither the name of Google Inc. nor the names of its | 10 * * Neither the name of Google Inc. nor the names of its |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 25 */ | 25 */ |
| 26 | 26 |
| 27 #include "config.h" | 27 #include "config.h" |
| 28 #include "core/dom/shadow/ElementShadow.h" | 28 #include "core/dom/shadow/ElementShadow.h" |
| 29 | 29 |
| 30 #include "core/dom/ContainerNodeAlgorithms.h" | 30 #include "core/dom/ContainerNodeAlgorithms.h" |
| 31 #include "core/dom/NodeTraversal.h" |
| 32 #include "core/dom/shadow/ContentDistribution.h" |
| 33 #include "core/dom/shadow/InsertionPoint.h" |
| 34 #include "core/dom/shadow/ScopeContentDistribution.h" |
| 35 #include "core/dom/shadow/ShadowRoot.h" |
| 36 #include "core/html/shadow/HTMLContentElement.h" |
| 37 #include "core/html/shadow/HTMLShadowElement.h" |
| 31 | 38 |
| 32 namespace WebCore { | 39 namespace WebCore { |
| 33 | 40 |
| 41 PassOwnPtr<ElementShadow> ElementShadow::create() |
| 42 { |
| 43 return adoptPtr(new ElementShadow()); |
| 44 } |
| 45 |
| 46 ElementShadow::ElementShadow() |
| 47 : m_needsDistributionRecalc(false) |
| 48 , m_applyAuthorStyles(false) |
| 49 , m_needsSelectFeatureSet(false) |
| 50 { |
| 51 } |
| 52 |
| 53 ElementShadow::~ElementShadow() |
| 54 { |
| 55 removeAllShadowRoots(); |
| 56 } |
| 57 |
| 34 ShadowRoot* ElementShadow::addShadowRoot(Element* shadowHost, ShadowRoot::Shadow
RootType type) | 58 ShadowRoot* ElementShadow::addShadowRoot(Element* shadowHost, ShadowRoot::Shadow
RootType type) |
| 35 { | 59 { |
| 36 RefPtr<ShadowRoot> shadowRoot = ShadowRoot::create(shadowHost->document(), t
ype); | 60 RefPtr<ShadowRoot> shadowRoot = ShadowRoot::create(shadowHost->document(), t
ype); |
| 37 | 61 |
| 38 shadowRoot->setParentOrShadowHostNode(shadowHost); | 62 shadowRoot->setParentOrShadowHostNode(shadowHost); |
| 39 shadowRoot->setParentTreeScope(shadowHost->treeScope()); | 63 shadowRoot->setParentTreeScope(shadowHost->treeScope()); |
| 40 m_shadowRoots.push(shadowRoot.get()); | 64 m_shadowRoots.push(shadowRoot.get()); |
| 41 ChildNodeInsertionNotifier(shadowHost).notify(shadowRoot.get()); | 65 ChildNodeInsertionNotifier(shadowHost).notify(shadowRoot.get()); |
| 42 setNeedsDistributionRecalc(); | 66 setNeedsDistributionRecalc(); |
| 43 | 67 |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 { | 163 { |
| 140 for (const ShadowRoot* shadowRoot = youngestShadowRoot(); shadowRoot; shadow
Root = shadowRoot->olderShadowRoot()) { | 164 for (const ShadowRoot* shadowRoot = youngestShadowRoot(); shadowRoot; shadow
Root = shadowRoot->olderShadowRoot()) { |
| 141 if (shadowRoot->applyAuthorStyles()) | 165 if (shadowRoot->applyAuthorStyles()) |
| 142 return true; | 166 return true; |
| 143 if (!shadowRoot->containsShadowElements()) | 167 if (!shadowRoot->containsShadowElements()) |
| 144 break; | 168 break; |
| 145 } | 169 } |
| 146 return false; | 170 return false; |
| 147 } | 171 } |
| 148 | 172 |
| 173 InsertionPoint* ElementShadow::findInsertionPointFor(const Node* key) const |
| 174 { |
| 175 return m_nodeToInsertionPoint.get(key); |
| 176 } |
| 177 |
| 178 void ElementShadow::populate(Node* node, Vector<Node*>& pool) |
| 179 { |
| 180 if (!isActiveInsertionPoint(node)) { |
| 181 pool.append(node); |
| 182 return; |
| 183 } |
| 184 |
| 185 InsertionPoint* insertionPoint = toInsertionPoint(node); |
| 186 if (insertionPoint->hasDistribution()) { |
| 187 for (size_t i = 0; i < insertionPoint->size(); ++i) |
| 188 populate(insertionPoint->at(i), pool); |
| 189 } else { |
| 190 for (Node* fallbackNode = insertionPoint->firstChild(); fallbackNode; fa
llbackNode = fallbackNode->nextSibling()) |
| 191 pool.append(fallbackNode); |
| 192 } |
| 193 } |
| 194 |
| 195 void ElementShadow::distribute() |
| 196 { |
| 197 Vector<Node*> pool; |
| 198 for (Node* node = host()->firstChild(); node; node = node->nextSibling()) |
| 199 populate(node, pool); |
| 200 |
| 201 host()->setNeedsStyleRecalc(); |
| 202 |
| 203 Vector<bool> distributed(pool.size()); |
| 204 distributed.fill(false); |
| 205 |
| 206 Vector<HTMLShadowElement*, 8> activeShadowInsertionPoints; |
| 207 for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadow
Root()) { |
| 208 HTMLShadowElement* firstActiveShadowInsertionPoint = 0; |
| 209 |
| 210 if (ScopeContentDistribution* scope = root->scopeDistribution()) { |
| 211 const Vector<RefPtr<InsertionPoint> >& insertionPoints = scope->ensu
reInsertionPointList(root); |
| 212 for (size_t i = 0; i < insertionPoints.size(); ++i) { |
| 213 InsertionPoint* point = insertionPoints[i].get(); |
| 214 if (!point->isActive()) |
| 215 continue; |
| 216 |
| 217 if (isHTMLShadowElement(point)) { |
| 218 if (!firstActiveShadowInsertionPoint) |
| 219 firstActiveShadowInsertionPoint = toHTMLShadowElement(po
int); |
| 220 } else { |
| 221 distributeSelectionsTo(point, pool, distributed); |
| 222 if (ElementShadow* shadow = shadowOfParentForDistribution(po
int)) |
| 223 shadow->setNeedsDistributionRecalc(); |
| 224 } |
| 225 } |
| 226 } |
| 227 |
| 228 if (firstActiveShadowInsertionPoint) |
| 229 activeShadowInsertionPoints.append(firstActiveShadowInsertionPoint); |
| 230 } |
| 231 |
| 232 for (size_t i = activeShadowInsertionPoints.size(); i > 0; --i) { |
| 233 HTMLShadowElement* shadowElement = activeShadowInsertionPoints[i - 1]; |
| 234 ShadowRoot* root = shadowElement->containingShadowRoot(); |
| 235 ASSERT(root); |
| 236 if (!shadowElement->shouldSelect()) { |
| 237 if (root->olderShadowRoot()) |
| 238 root->olderShadowRoot()->ensureScopeDistribution()->setInsertion
PointAssignedTo(shadowElement); |
| 239 } else if (root->olderShadowRoot()) { |
| 240 distributeNodeChildrenTo(shadowElement, root->olderShadowRoot()); |
| 241 root->olderShadowRoot()->ensureScopeDistribution()->setInsertionPoin
tAssignedTo(shadowElement); |
| 242 } else { |
| 243 distributeSelectionsTo(shadowElement, pool, distributed); |
| 244 } |
| 245 if (ElementShadow* shadow = shadowOfParentForDistribution(shadowElement)
) |
| 246 shadow->setNeedsDistributionRecalc(); |
| 247 } |
| 248 |
| 249 // Detach all nodes that were not distributed and have a renderer. |
| 250 for (size_t i = 0; i < pool.size(); ++i) { |
| 251 if (distributed[i]) |
| 252 continue; |
| 253 if (pool[i]->renderer()) |
| 254 pool[i]->lazyReattachIfAttached(); |
| 255 } |
| 256 } |
| 257 |
| 258 void ElementShadow::distributeSelectionsTo(InsertionPoint* insertionPoint, const
Vector<Node*>& pool, Vector<bool>& distributed) |
| 259 { |
| 260 ContentDistribution distribution; |
| 261 |
| 262 for (size_t i = 0; i < pool.size(); ++i) { |
| 263 if (distributed[i]) |
| 264 continue; |
| 265 |
| 266 if (isHTMLContentElement(insertionPoint) && !toHTMLContentElement(insert
ionPoint)->canSelectNode(pool, i)) |
| 267 continue; |
| 268 |
| 269 Node* child = pool[i]; |
| 270 distribution.append(child); |
| 271 m_nodeToInsertionPoint.add(child, insertionPoint); |
| 272 distributed[i] = true; |
| 273 } |
| 274 |
| 275 insertionPoint->setDistribution(distribution); |
| 276 } |
| 277 |
| 278 void ElementShadow::distributeNodeChildrenTo(InsertionPoint* insertionPoint, Con
tainerNode* containerNode) |
| 279 { |
| 280 ContentDistribution distribution; |
| 281 for (Node* node = containerNode->firstChild(); node; node = node->nextSiblin
g()) { |
| 282 if (isActiveInsertionPoint(node)) { |
| 283 InsertionPoint* innerInsertionPoint = toInsertionPoint(node); |
| 284 if (innerInsertionPoint->hasDistribution()) { |
| 285 for (size_t i = 0; i < innerInsertionPoint->size(); ++i) { |
| 286 distribution.append(innerInsertionPoint->at(i)); |
| 287 m_nodeToInsertionPoint.add(innerInsertionPoint->at(i), inser
tionPoint); |
| 288 } |
| 289 } else { |
| 290 for (Node* child = innerInsertionPoint->firstChild(); child; chi
ld = child->nextSibling()) { |
| 291 distribution.append(child); |
| 292 m_nodeToInsertionPoint.add(child, insertionPoint); |
| 293 } |
| 294 } |
| 295 } else { |
| 296 distribution.append(node); |
| 297 m_nodeToInsertionPoint.add(node, insertionPoint); |
| 298 } |
| 299 } |
| 300 |
| 301 insertionPoint->setDistribution(distribution); |
| 302 } |
| 303 |
| 304 const SelectRuleFeatureSet& ElementShadow::ensureSelectFeatureSet() |
| 305 { |
| 306 if (!m_needsSelectFeatureSet) |
| 307 return m_selectFeatures; |
| 308 |
| 309 m_selectFeatures.clear(); |
| 310 for (ShadowRoot* root = oldestShadowRoot(); root; root = root->youngerShadow
Root()) |
| 311 collectSelectFeatureSetFrom(root); |
| 312 m_needsSelectFeatureSet = false; |
| 313 return m_selectFeatures; |
| 314 } |
| 315 |
| 316 void ElementShadow::collectSelectFeatureSetFrom(ShadowRoot* root) |
| 317 { |
| 318 if (!root->containsShadowRoots() && !root->containsContentElements()) |
| 319 return; |
| 320 |
| 321 for (Element* element = ElementTraversal::firstWithin(root); element; elemen
t = ElementTraversal::next(element, root)) { |
| 322 if (ElementShadow* shadow = element->shadow()) |
| 323 m_selectFeatures.add(shadow->ensureSelectFeatureSet()); |
| 324 if (!isHTMLContentElement(element)) |
| 325 continue; |
| 326 const CSSSelectorList& list = toHTMLContentElement(element)->selectorLis
t(); |
| 327 for (const CSSSelector* selector = list.first(); selector; selector = CS
SSelectorList::next(selector)) { |
| 328 for (const CSSSelector* component = selector; component; component =
component->tagHistory()) |
| 329 m_selectFeatures.collectFeaturesFromSelector(component); |
| 330 } |
| 331 } |
| 332 } |
| 333 |
| 334 void ElementShadow::didAffectSelector(AffectedSelectorMask mask) |
| 335 { |
| 336 if (ensureSelectFeatureSet().hasSelectorFor(mask)) |
| 337 setNeedsDistributionRecalc(); |
| 338 } |
| 339 |
| 340 void ElementShadow::willAffectSelector() |
| 341 { |
| 342 for (ElementShadow* shadow = this; shadow; shadow = shadow->containingShadow
()) { |
| 343 if (shadow->needsSelectFeatureSet()) |
| 344 break; |
| 345 shadow->setNeedsSelectFeatureSet(); |
| 346 } |
| 347 setNeedsDistributionRecalc(); |
| 348 } |
| 349 |
| 350 void ElementShadow::clearDistribution() |
| 351 { |
| 352 m_nodeToInsertionPoint.clear(); |
| 353 |
| 354 for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadow
Root()) { |
| 355 if (ScopeContentDistribution* scope = root->scopeDistribution()) |
| 356 scope->setInsertionPointAssignedTo(0); |
| 357 } |
| 358 } |
| 359 |
| 149 } // namespace | 360 } // namespace |
| OLD | NEW |