bool Text::textLayoutObjectIsNeeded(const ComputedStyle& style, const LayoutObject& parent) { if (!parent.canHaveChildren()) return false; if (isEditingText()) return true; if (!length()) return false; if (style.display() == NONE) return false; if (!containsOnlyWhitespace()) return true; if (!canHaveWhitespaceChildren(parent, this)) return false; // pre-wrap in SVG never makes layoutObject. if (style.whiteSpace() == PRE_WRAP && parent.isSVG()) return false; // pre/pre-wrap/-bb-pre-wrap-text/pre-line always make layoutObjects. if (style.preserveNewline()) return true; // childNeedsDistributionRecalc() here is rare, only happens JS calling surroundContents() etc. from DOMNodeInsertedIntoDocument etc. if (document().childNeedsDistributionRecalc()) return true; const LayoutObject* prev = LayoutTreeBuilderTraversal::previousSiblingLayoutObject(*this); if (prev && prev->isBR()) // <span><br/> <br/></span> return false; if (parent.isLayoutInline()) { // <span><div/> <div/></span> if (prev && !prev->isInline() && !prev->isOutOfFlowPositioned()) return false; } else { if (parent.isLayoutBlock() && !parent.childrenInline() && (!prev || !prev->isInline())) return false; // Avoiding creation of a layoutObject for the text node is a non-essential memory optimization. // So to avoid blowing up on very wide DOMs, we limit the number of siblings to visit. unsigned maxSiblingsToVisit = 50; LayoutObject* first = parent.slowFirstChild(); while (first && first->isFloatingOrOutOfFlowPositioned() && maxSiblingsToVisit--) first = first->nextSibling(); if (!first || first == layoutObject() || LayoutTreeBuilderTraversal::nextSiblingLayoutObject(*this) == first) { // Whitespace at the start of a block just goes away. Don't even // make a layout object for this text. return false; } } return true; }
bool Text::textRendererIsNeeded(const RenderStyle& style, const RenderObject& parent) { if (!parent.canHaveChildren()) return false; if (isEditingText()) return true; if (!length()) return false; if (style.display() == NONE) return false; if (!containsOnlyWhitespace()) return true; if (!canHaveWhitespaceChildren(parent)) return false; if (style.preserveNewline()) // pre/pre-wrap/pre-line always make renderers. return true; const RenderObject* prev = NodeRenderingTraversal::previousSiblingRenderer(*this); if (prev && prev->isBR()) // <span><br/> <br/></span> return false; if (parent.isRenderInline()) { // <span><div/> <div/></span> if (prev && !prev->isInline()) return false; } else { if (parent.isRenderBlock() && !parent.childrenInline() && (!prev || !prev->isInline())) return false; // Avoiding creation of a Renderer for the text node is a non-essential memory optimization. // So to avoid blowing up on very wide DOMs, we limit the number of siblings to visit. unsigned maxSiblingsToVisit = 50; RenderObject* first = parent.slowFirstChild(); while (first && first->isFloatingOrOutOfFlowPositioned() && maxSiblingsToVisit--) first = first->nextSibling(); if (!first || first == renderer() || NodeRenderingTraversal::nextSiblingRenderer(*this) == first) // Whitespace at the start of a block just goes away. Don't even // make a render object for this text. return false; } return true; }
bool Text::textRendererIsNeeded(const NodeRenderingContext& context) { if (isEditingText()) return true; if (!length()) return false; if (context.style()->display() == NONE) return false; bool onlyWS = containsOnlyWhitespace(); if (!onlyWS) return true; RenderObject* parent = context.parentRenderer(); if (parent->isTable() || parent->isTableRow() || parent->isTableSection() || parent->isRenderTableCol() || parent->isFrameSet()) return false; if (context.style()->preserveNewline()) // pre/pre-wrap/pre-line always make renderers. return true; RenderObject* prev = context.previousRenderer(); if (prev && prev->isBR()) // <span><br/> <br/></span> return false; if (parent->isRenderInline()) { // <span><div/> <div/></span> if (prev && !prev->isInline()) return false; } else { if (parent->isRenderBlock() && !parent->childrenInline() && (!prev || !prev->isInline())) return false; RenderObject* first = parent->firstChild(); while (first && first->isFloatingOrOutOfFlowPositioned()) first = first->nextSibling(); if (!first || context.nextRenderer() == first) { // Whitespace at the start of a block just goes away. Don't even // make a render object for this text. return false; } } return true; }
void Text::attach() { #if ENABLE(WML) if (document()->isWMLDocument() && !containsOnlyWhitespace()) { String text = data(); ASSERT(!text.isEmpty()); text = substituteVariableReferences(text, document()); ExceptionCode code = 0; setData(text, code); ASSERT(!code); } #endif createRendererIfNeeded(); CharacterData::attach(); }
bool Text::rendererIsNeeded(RenderStyle *style) { if (!CharacterData::rendererIsNeeded(style)) return false; bool onlyWS = containsOnlyWhitespace(); if (!onlyWS) return true; RenderObject *par = parentNode()->renderer(); if (par->isTable() || par->isTableRow() || par->isTableSection() || par->isTableCol() || par->isFrameSet()) return false; if (style->preserveNewline()) // pre/pre-wrap/pre-line always make renderers. return true; RenderObject *prev = previousRenderer(); if (prev && prev->isBR()) // <span><br/> <br/></span> return false; if (par->isInlineFlow()) { // <span><div/> <div/></span> if (prev && !prev->isInline()) return false; } else { if (par->isRenderBlock() && !par->childrenInline() && (!prev || !prev->isInline())) return false; RenderObject *first = par->firstChild(); while (first && first->isFloatingOrPositioned()) first = first->nextSibling(); RenderObject *next = nextRenderer(); if (!first || next == first) // Whitespace at the start of a block just goes away. Don't even // make a render object for this text. return false; } return true; }
bool Text::textRendererIsNeeded(const RenderStyle& style, const RenderObject& parent) { if (isEditingText()) return true; if (!length()) return false; if (style.display() == NONE) return false; if (style.requiresOnlyBlockChildren()) return false; if (!containsOnlyWhitespace()) return true; if (!parent.canHaveWhitespaceChildren()) return false; if (style.preserveNewline()) // pre/pre-wrap/pre-line always make renderers. return true; RenderObject* prev; for (Node* sibling = this->previousSibling(); sibling; sibling = sibling->previousSibling()) { if ((prev = sibling->renderer())) break; } if (parent.isRenderInline()) { // <span><div/> <div/></span> if (prev && !prev->isInline()) return false; } else { if (parent.isRenderBlock() && !parent.isRenderParagraph() && (!prev || !prev->isInline())) return false; // Avoiding creation of a Renderer for the text node is a non-essential memory optimization. // So to avoid blowing up on very wide DOMs, we limit the number of siblings to visit. unsigned maxSiblingsToVisit = 50; RenderObject* first = parent.slowFirstChild(); while (first && first->isFloatingOrOutOfFlowPositioned() && maxSiblingsToVisit--) first = first->nextSibling(); if (!first) { // If the block has nothing but white-space we ignore it return false; } for (Node* sibling = this->nextSibling(); sibling; sibling = sibling->nextSibling()) { if (RenderObject* nextRenderer = sibling->renderer()) { if (nextRenderer == first) { // Whitespace at the start of a block just goes away. Don't even // make a render object for this text. return false; } break; } } } return true; }