void HTMLStyleElement::registerWithScopingNode(bool scoped) { // Note: We cannot rely on the 'scoped' element already being present when this method is invoked. // Therefore we cannot rely on scoped()! ASSERT(m_scopedStyleRegistrationState == NotRegistered); ASSERT(inDocument()); if (m_scopedStyleRegistrationState != NotRegistered) return; ContainerNode* scope = scoped ? parentNode() : containingShadowRoot(); if (!scope) return; if (!scope->isElementNode() && !scope->isShadowRoot()) { // DocumentFragment nodes should never be inDocument, // <style> should not be a child of Document, PI or some such. ASSERT_NOT_REACHED(); return; } scope->registerScopedHTMLStyleChild(); if (scope->isShadowRoot()) scope->shadowHost()->setNeedsStyleRecalc(); else scope->setNeedsStyleRecalc(); if (inDocument() && !document()->parsing() && document()->renderer()) document()->styleResolverChanged(DeferRecalcStyle); m_scopedStyleRegistrationState = scoped ? RegisteredAsScoped : RegisteredInShadowRoot; }
NodeRenderingContext::NodeRenderingContext(Node* node) : m_location(LocationNotInTree) , m_phase(AttachStraight) , m_node(node) , m_parentNodeForRenderingAndStyle(0) , m_visualParentShadowRoot(0) , m_includer(0) , m_style(0) , m_parentFlowRenderer(0) { ContainerNode* parent = m_node->parentOrHostNode(); if (!parent) return; if (parent->isShadowRoot()) { m_location = LocationShadowChild; m_parentNodeForRenderingAndStyle = parent->shadowHost(); return; } m_location = LocationLightChild; if (parent->isElementNode()) { m_visualParentShadowRoot = toElement(parent)->shadowRoot(); if (m_visualParentShadowRoot) { if ((m_includer = m_visualParentShadowRoot->includerFor(m_node)) && m_visualParentShadowRoot->isInclusionSelectorActive()) { m_phase = AttachContentForwarded; m_parentNodeForRenderingAndStyle = NodeRenderingContext(m_includer).parentNodeForRenderingAndStyle(); return; } m_phase = AttachContentLight; m_parentNodeForRenderingAndStyle = parent; return; } if (parent->isContentElement()) { HTMLContentElement* shadowContentElement = toHTMLContentElement(parent); if (!shadowContentElement->hasInclusion()) { m_phase = AttachContentFallback; m_parentNodeForRenderingAndStyle = NodeRenderingContext(parent).parentNodeForRenderingAndStyle(); return; } } } m_parentNodeForRenderingAndStyle = parent; }
void VisibleSelection::adjustSelectionToAvoidCrossingEditingBoundaries() { if (m_base.isNull() || m_start.isNull() || m_end.isNull()) return; ContainerNode* baseRoot = highestEditableRoot(m_base); ContainerNode* startRoot = highestEditableRoot(m_start); ContainerNode* endRoot = highestEditableRoot(m_end); Element* baseEditableAncestor = lowestEditableAncestor(m_base.containerNode()); // The base, start and end are all in the same region. No adjustment necessary. if (baseRoot == startRoot && baseRoot == endRoot) return; // The selection is based in editable content. if (baseRoot) { // If the start is outside the base's editable root, cap it at the start of that root. // If the start is in non-editable content that is inside the base's editable root, put it // at the first editable position after start inside the base's editable root. if (startRoot != baseRoot) { VisiblePosition first = firstEditableVisiblePositionAfterPositionInRoot(m_start, baseRoot); m_start = first.deepEquivalent(); if (m_start.isNull()) { ASSERT_NOT_REACHED(); m_start = m_end; } } // If the end is outside the base's editable root, cap it at the end of that root. // If the end is in non-editable content that is inside the base's root, put it // at the last editable position before the end inside the base's root. if (endRoot != baseRoot) { VisiblePosition last = lastEditableVisiblePositionBeforePositionInRoot(m_end, baseRoot); m_end = last.deepEquivalent(); if (m_end.isNull()) m_end = m_start; } // The selection is based in non-editable content. } else { // FIXME: Non-editable pieces inside editable content should be atomic, in the same way that editable // pieces in non-editable content are atomic. // The selection ends in editable content or non-editable content inside a different editable ancestor, // move backward until non-editable content inside the same lowest editable ancestor is reached. Element* endEditableAncestor = lowestEditableAncestor(m_end.containerNode()); if (endRoot || endEditableAncestor != baseEditableAncestor) { Position p = previousVisuallyDistinctCandidate(m_end); Element* shadowAncestor = endRoot ? endRoot->shadowHost() : 0; if (p.isNull() && shadowAncestor) p = positionAfterNode(shadowAncestor); while (p.isNotNull() && !(lowestEditableAncestor(p.containerNode()) == baseEditableAncestor && !isEditablePosition(p))) { Element* root = editableRootForPosition(p); shadowAncestor = root ? root->shadowHost() : 0; p = isAtomicNode(p.containerNode()) ? positionInParentBeforeNode(*p.containerNode()) : previousVisuallyDistinctCandidate(p); if (p.isNull() && shadowAncestor) p = positionAfterNode(shadowAncestor); } VisiblePosition previous(p); if (previous.isNull()) { // The selection crosses an Editing boundary. This is a // programmer error in the editing code. Happy debugging! ASSERT_NOT_REACHED(); m_base = Position(); m_extent = Position(); validate(); return; } m_end = previous.deepEquivalent(); } // The selection starts in editable content or non-editable content inside a different editable ancestor, // move forward until non-editable content inside the same lowest editable ancestor is reached. Element* startEditableAncestor = lowestEditableAncestor(m_start.containerNode()); if (startRoot || startEditableAncestor != baseEditableAncestor) { Position p = nextVisuallyDistinctCandidate(m_start); Element* shadowAncestor = startRoot ? startRoot->shadowHost() : 0; if (p.isNull() && shadowAncestor) p = positionBeforeNode(shadowAncestor); while (p.isNotNull() && !(lowestEditableAncestor(p.containerNode()) == baseEditableAncestor && !isEditablePosition(p))) { Element* root = editableRootForPosition(p); shadowAncestor = root ? root->shadowHost() : 0; p = isAtomicNode(p.containerNode()) ? positionInParentAfterNode(*p.containerNode()) : nextVisuallyDistinctCandidate(p); if (p.isNull() && shadowAncestor) p = positionBeforeNode(shadowAncestor); } VisiblePosition next(p); if (next.isNull()) { // The selection crosses an Editing boundary. This is a // programmer error in the editing code. Happy debugging! ASSERT_NOT_REACHED(); m_base = Position(); m_extent = Position(); validate(); return; } m_start = next.deepEquivalent(); } } // Correct the extent if necessary. if (baseEditableAncestor != lowestEditableAncestor(m_extent.containerNode())) m_extent = m_baseIsFirst ? m_end : m_start; }