RenderObject* RenderObjectChildList::beforePseudoElementRenderer(const RenderObject* owner) const { // An anonymous (generated) inline run-in that has PseudoId BEFORE must come from a grandparent. // Therefore we should skip these generated run-ins when checking our immediate children. // If we don't find our :before child immediately, then we should check if we own a // generated inline run-in in the next level of children. RenderObject* first = const_cast<RenderObject*>(owner); do { first = first->firstChild(); // Skip list markers and generated run-ins. while (first && (first->isListMarker() || (first->isRenderInline() && first->isRunIn()))) first = first->nextInPreOrderAfterChildren(owner); } while (first && first->isAnonymous() && first->style()->styleType() == NOPSEUDO); if (!first) return 0; if (first->isBeforeContent()) return first; // Check for a possible generated run-in, using run-in positioning rules. first = owner->firstChild(); if (!first->isRenderBlock()) return 0; first = first->firstChild(); // We still need to skip any list markers that could exist before the run-in. while (first && first->isListMarker()) first = first->nextSibling(); if (first && first->isBeforeContent() && first->isRenderInline() && first->isRunIn()) return first; return 0; }
LayoutUnit RenderMathMLUnderOver::baselinePosition(FontBaseline, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const { RenderObject* current = firstChild(); if (!current || linePositionMode == PositionOfInteriorLineBoxes) return RenderBlock::baselinePosition(AlphabeticBaseline, firstLine, direction, linePositionMode); LayoutUnit baseline = 0; switch (m_kind) { case UnderOver: case Over: baseline += getOffsetHeight(current); current = current->nextSibling(); if (current) { // actual base RenderObject* base = current->firstChild(); if (!base || !base->isBoxModelObject()) break; baseline += toRenderBoxModelObject(base)->baselinePosition(AlphabeticBaseline, firstLine, HorizontalLine, linePositionMode); // added the negative top margin baseline += current->style()->marginTop().value(); } break; case Under: RenderObject* base = current->firstChild(); if (base && base->isBoxModelObject()) baseline += toRenderBoxModelObject(base)->baselinePosition(AlphabeticBaseline, true, HorizontalLine); } return baseline; }
void RenderMathMLSubSup::layout() { RenderBlock::layout(); if (m_kind != SubSup || !m_scripts) return; RenderBoxModelObject* base = this->base(); RenderObject* superscriptWrapper = m_scripts->firstChild(); RenderObject* subscriptWrapper = m_scripts->lastChild(); if (!base || !superscriptWrapper || !subscriptWrapper || superscriptWrapper == subscriptWrapper) return; ASSERT(superscriptWrapper->isRenderMathMLBlock()); ASSERT(subscriptWrapper->isRenderMathMLBlock()); RenderObject* superscript = superscriptWrapper->firstChild(); RenderObject* subscript = subscriptWrapper->firstChild(); if (!superscript || !subscript) return; LineDirectionMode lineDirection = style()->isHorizontalWritingMode() ? HorizontalLine : VerticalLine; LayoutUnit baseBaseline = base->baselinePosition(AlphabeticBaseline, true, lineDirection); LayoutUnit baseExtendUnderBaseline = getBoxModelObjectHeight(base) - baseBaseline; LayoutUnit axis = style()->fontMetrics().xHeight() / 2; LayoutUnit superscriptHeight = getBoxModelObjectHeight(superscript); LayoutUnit subscriptHeight = getBoxModelObjectHeight(subscript); // Our layout rules are: Don't let the superscript go below the "axis" (half x-height above the // baseline), or the subscript above the axis. Also, don't let the superscript's top edge be // below the base's top edge, or the subscript's bottom edge above the base's bottom edge. // // FIXME: Check any subscriptshift or superscriptshift attributes, and maybe use more sophisticated // heuristics from TeX or elsewhere. See https://bugs.webkit.org/show_bug.cgi?id=79274#c5. // Above we did scriptsStyle->setVerticalAlign(TOP) for mscripts' style, so the superscript's // top edge will equal the top edge of the base's padding. LayoutUnit basePaddingTop = superscriptHeight + axis - baseBaseline; // If basePaddingTop is positive, it's indeed the base's padding-top that we need. If it's negative, // then we should instead use its absolute value to pad the bottom of the superscript, to get the // superscript's bottom edge down to the axis. First we compute how much more we need to shift the // subscript down, once its top edge is at the axis. LayoutUnit superPaddingBottom = max<LayoutUnit>(baseExtendUnderBaseline + axis - subscriptHeight, 0); if (basePaddingTop < 0) { superPaddingBottom += -basePaddingTop; basePaddingTop = 0; } setChildNeedsLayout(true, false); RenderObject* baseWrapper = firstChild(); baseWrapper->style()->setPaddingTop(Length(basePaddingTop, Fixed)); baseWrapper->setNeedsLayout(true, false); superscriptWrapper->style()->setPaddingBottom(Length(superPaddingBottom, Fixed)); superscriptWrapper->setNeedsLayout(true, false); m_scripts->setNeedsLayout(true, false); RenderBlock::layout(); }
static RenderObject* beforeAfterContainer(RenderObject* container, PseudoId type) { if (type == BEFORE) { // An anonymous (generated) inline run-in that has PseudoId BEFORE must come from a grandparent. // Therefore we should skip these generated run-ins when checking our immediate children. // If we don't find our :before child immediately, then we should check if we own a // generated inline run-in in the next level of children. RenderObject* first = container; do { // Skip list markers and generated run-ins first = first->firstChild(); while (first && (first->isListMarker() || (first->isRenderInline() && first->isRunIn() && first->isAnonymous()))) first = first->nextSibling(); } while (first && first->isAnonymous() && first->style()->styleType() == NOPSEUDO); if (!first) return 0; if (first->style()->styleType() == type) return first; // Check for a possible generated run-in, using run-in positioning rules. // Skip inlines and floating / positioned blocks, and place as the first child. first = container->firstChild(); if (!first->isRenderBlock()) return 0; while (first && first->isFloatingOrPositioned()) first = first->nextSibling(); if (first) { first = first->firstChild(); // We still need to skip any list markers that could exist before the run-in. while (first && first->isListMarker()) first = first->nextSibling(); if (first && first->style()->styleType() == type && first->isRenderInline() && first->isRunIn() && first->isAnonymous()) return first; } return 0; } if (type == AFTER) { RenderObject* last = container; do { last = last->lastChild(); } while (last && last->isAnonymous() && last->style()->styleType() == NOPSEUDO && !last->isListMarker()); if (last && last->style()->styleType() != type) return 0; return last; } ASSERT_NOT_REACHED(); return 0; }
int RenderMathMLUnderOver::nonOperatorHeight() const { int nonOperators = 0; for (RenderObject* current = firstChild(); current; current = current->nextSibling()) { if (current->firstChild() && current->firstChild()->isRenderMathMLBlock()) { RenderMathMLBlock* block = toRenderMathMLBlock(current->firstChild()); if (!block->isRenderMathMLOperator()) nonOperators += getOffsetHeight(current); } else nonOperators += getOffsetHeight(current); } return nonOperators; }
static void write(QTextStream &ts, const RenderObject &o, int indent = 0) { writeIndent(ts, indent); ts << o << "\n"; if (o.isText() && !o.isBR()) { const RenderText &text = static_cast<const RenderText &>(o); for (InlineTextBox* box = text.firstTextBox(); box; box = box->nextTextBox()) { writeIndent(ts, indent+1); writeTextRun(ts, text, *box); } } for (RenderObject *child = o.firstChild(); child; child = child->nextSibling()) { if (child->layer()) { continue; } write(ts, *child, indent + 1); } if (o.isWidget()) { QWidget *widget = static_cast<const RenderWidget &>(o).widget(); if (widget && widget->inherits("KHTMLView")) { KHTMLView *view = static_cast<KHTMLView *>(widget); RenderObject *root = KWQ(view->part())->renderer(); if (root) { view->layout(); RenderLayer* l = root->layer(); if (l) writeLayers(ts, l, l, QRect(l->xPos(), l->yPos(), l->width(), l->height()), indent+1); } } } }
VisiblePosition RenderContainer::positionForCoordinates(int _x, int _y) { // no children...return this render object's element, if there is one, and offset 0 if (!firstChild()) return VisiblePosition(element(), 0, DOWNSTREAM); // look for the geometrically-closest child and pass off to that child int min = INT_MAX; RenderObject *closestRenderer = 0; for (RenderObject *renderer = firstChild(); renderer; renderer = renderer->nextSibling()) { if (!renderer->firstChild() && !renderer->isInline() && !renderer->isBlockFlow()) continue; int absx, absy; renderer->absolutePosition(absx, absy); int top = absy + borderTop() + paddingTop(); int bottom = top + renderer->contentHeight(); int left = absx + borderLeft() + paddingLeft(); int right = left + renderer->contentWidth(); int cmp; cmp = abs(_y - top); if (cmp < min) { closestRenderer = renderer; min = cmp; } cmp = abs(_y - bottom); if (cmp < min) { closestRenderer = renderer; min = cmp; } cmp = abs(_x - left); if (cmp < min) { closestRenderer = renderer; min = cmp; } cmp = abs(_x - right); if (cmp < min) { closestRenderer = renderer; min = cmp; } } if (closestRenderer) return closestRenderer->positionForCoordinates(_x, _y); return VisiblePosition(element(), 0, DOWNSTREAM); }
void write(TextStream& ts, const RenderObject& o, int indent) { #if ENABLE(SVG) if (o.isRenderPath()) { write(ts, *toRenderPath(&o), indent); return; } if (o.isSVGContainer()) { writeSVGContainer(ts, o, indent); return; } if (o.isSVGRoot()) { write(ts, *toRenderSVGRoot(&o), indent); return; } if (o.isSVGText()) { if (!o.isText()) writeSVGText(ts, *toRenderBlock(&o), indent); else writeSVGInlineText(ts, *toRenderText(&o), indent); return; } if (o.isSVGImage()) { writeSVGImage(ts, *toRenderImage(&o), indent); return; } #endif writeIndent(ts, indent); ts << o << "\n"; if (o.isText() && !o.isBR()) { const RenderText& text = *toRenderText(&o); for (InlineTextBox* box = text.firstTextBox(); box; box = box->nextTextBox()) { writeIndent(ts, indent + 1); writeTextRun(ts, text, *box); } } for (RenderObject* child = o.firstChild(); child; child = child->nextSibling()) { if (child->hasLayer()) continue; write(ts, *child, indent + 1); } if (o.isWidget()) { Widget* widget = toRenderWidget(&o)->widget(); if (widget && widget->isFrameView()) { FrameView* view = static_cast<FrameView*>(widget); RenderView* root = view->frame()->contentRenderer(); if (root) { view->layout(); RenderLayer* l = root->layer(); if (l) writeLayers(ts, l, l, IntRect(l->x(), l->y(), l->width(), l->height()), indent + 1); } } } }
bool isEmptyTableCell(const Node* node) { // Returns true IFF the passed in node is one of: // .) a table cell with no children, // .) a table cell with a single BR child, and which has no other child renderers, including :before and :after renderers // .) the BR child of such a table cell // Find rendered node while (node && !node->renderer()) node = node->parentNode(); if (!node) return false; // Make sure the rendered node is a table cell or <br>. // If it's a <br>, then the parent node has to be a table cell. RenderObject* renderer = node->renderer(); if (renderer->isBR()) { renderer = renderer->parent(); if (!renderer) return false; } if (!renderer->isTableCell()) return false; // Check that the table cell contains no child renderers except for perhaps a single <br>. RenderObject* childRenderer = renderer->firstChild(); if (!childRenderer) return true; if (!childRenderer->isBR()) return false; return !childRenderer->nextSibling(); }
QRect RenderCanvas::selectionRect() const { RenderObject *r = m_selectionStart; if (!r) return QRect(); QRect selectionRect = enclosingPositionedRect(r); while (r && r != m_selectionEnd) { RenderObject* n; if ( !(n = r->firstChild()) ){ if ( !(n = r->nextSibling()) ) { n = r->parent(); while (n && !n->nextSibling()) n = n->parent(); if (n) n = n->nextSibling(); } } r = n; if (r) { selectionRect = selectionRect.unite(enclosingPositionedRect(r)); } } return selectionRect; }
void RenderListItem::updateMarkerLocation() { // Sanity check the location of our marker. if (m_marker) { RenderObject* markerPar = m_marker->parent(); RenderObject* lineBoxParent = getParentOfFirstLineBox(this, m_marker); if (!lineBoxParent) { // If the marker is currently contained inside an anonymous box, // then we are the only item in that anonymous box (since no line box // parent was found). It's ok to just leave the marker where it is // in this case. if (markerPar && markerPar->isAnonymousBlock()) lineBoxParent = markerPar; else lineBoxParent = this; } if (markerPar != lineBoxParent || m_marker->preferredLogicalWidthsDirty()) { // Removing and adding the marker can trigger repainting in // containers other than ourselves, so we need to disable LayoutState. LayoutStateDisabler layoutStateDisabler(view()); updateFirstLetter(); m_marker->remove(); if (!lineBoxParent) lineBoxParent = this; lineBoxParent->addChild(m_marker, firstNonMarkerChild(lineBoxParent)); m_marker->updateMarginsAndContent(); // If markerPar is an anonymous block that has lost all its children, destroy it. if (markerPar && markerPar->isAnonymousBlock() && !markerPar->firstChild() && !toRenderBlock(markerPar)->continuation()) markerPar->destroy(); } } }
void RenderMathMLSubSup::stretchToHeight(int height) { RenderObject* base = firstChild(); if (!base) return; if (base->isRenderMathMLBlock()) { RenderMathMLBlock* block = toRenderMathMLBlock(base); block->stretchToHeight(static_cast<int>(gSubSupStretch * height)); } if (height > 0 && m_kind == SubSup && m_scripts) { RenderObject* script = m_scripts->firstChild(); if (script) { // Calculate the script height without the container margins. RenderObject* top = script; int topHeight = getBoxModelObjectHeight(top->firstChild()); int topAdjust = topHeight / gTopAdjustDivisor; top->style()->setMarginTop(Length(-topAdjust, Fixed)); top->style()->setMarginBottom(Length(height - topHeight + topAdjust, Fixed)); if (top->isBoxModelObject()) { RenderBoxModelObject* topBox = toRenderBoxModelObject(top); topBox->updateBoxModelInfoFromStyle(); } m_scripts->setNeedsLayoutAndPrefWidthsRecalc(); m_scripts->markContainingBlocksForLayout(); } } updateBoxModelInfoFromStyle(); setNeedsLayoutAndPrefWidthsRecalc(); markContainingBlocksForLayout(); }
static RenderObject* beforeAfterContainer(RenderObject* container, PseudoId type) { if (type == BEFORE) { RenderObject* first = container; do { // Skip list markers. first = first->firstChild(); while (first && first->isListMarker()) first = first->nextSibling(); } while (first && first->isAnonymous() && first->style()->styleType() == NOPSEUDO); if (first && first->style()->styleType() != type) return 0; return first; } if (type == AFTER) { RenderObject* last = container; do { last = last->lastChild(); } while (last && last->isAnonymous() && last->style()->styleType() == NOPSEUDO && !last->isListMarker()); if (last && last->style()->styleType() != type) return 0; return last; } ASSERT_NOT_REACHED(); return 0; }
void RenderLayerStackingNode::rebuildZOrderLists(OwnPtr<Vector<RenderLayerStackingNode*> >& posZOrderList, OwnPtr<Vector<RenderLayerStackingNode*> >& negZOrderList, const RenderLayerStackingNode* nodeToForceAsStackingContainer, CollectLayersBehavior collectLayersBehavior) { for (RenderLayer* child = layer()->firstChild(); child; child = child->nextSibling()) { if (!layer()->reflectionInfo() || layer()->reflectionInfo()->reflectionLayer() != child) child->stackingNode()->collectLayers(posZOrderList, negZOrderList, nodeToForceAsStackingContainer, collectLayersBehavior); } // Sort the two lists. if (posZOrderList) std::stable_sort(posZOrderList->begin(), posZOrderList->end(), compareZIndex); if (negZOrderList) std::stable_sort(negZOrderList->begin(), negZOrderList->end(), compareZIndex); // Append layers for top layer elements after normal layer collection, to ensure they are on top regardless of z-indexes. // The renderers of top layer elements are children of the view, sorted in top layer stacking order. if (layer()->isRootLayer()) { RenderObject* view = renderer()->view(); for (RenderObject* child = view->firstChild(); child; child = child->nextSibling()) { Element* childElement = (child->node() && child->node()->isElementNode()) ? toElement(child->node()) : 0; if (childElement && childElement->isInTopLayer()) { RenderLayer* layer = toRenderLayerModelObject(child)->layer(); // Create the buffer if it doesn't exist yet. if (!posZOrderList) posZOrderList = adoptPtr(new Vector<RenderLayerStackingNode*>); posZOrderList->append(layer->stackingNode()); } } } }
void RenderListItem::updateMarkerLocation() { // Sanity check the location of our marker. if (m_marker) { RenderObject* markerPar = m_marker->parent(); RenderObject* lineBoxParent = getParentOfFirstLineBox(this, m_marker); if (!lineBoxParent) { // If the marker is currently contained inside an anonymous box, // then we are the only item in that anonymous box (since no line box // parent was found). It's ok to just leave the marker where it is // in this case. if (markerPar && markerPar->isAnonymousBlock()) lineBoxParent = markerPar; else lineBoxParent = this; } if (markerPar != lineBoxParent || !m_marker->minMaxKnown()) { m_marker->remove(); if (!lineBoxParent) lineBoxParent = this; lineBoxParent->addChild(m_marker, lineBoxParent->firstChild()); if (!m_marker->minMaxKnown()) m_marker->calcMinMaxWidth(); recalcMinMaxWidths(); } } }
void RenderMathMLUnderOver::stretchToHeight(int height) { RenderObject* base = firstChild(); if (!base) return; // For over or underover, the base is the sibling of the first child if (m_kind != Under) base = base->nextSibling(); if (!base) return; // use the child of the row which is the actual base base = base->firstChild(); if (base && base->isRenderMathMLBlock()) { RenderMathMLBlock* block = toRenderMathMLBlock(base); block->stretchToHeight(height); updateBoxModelInfoFromStyle(); setNeedsLayoutAndPrefWidthsRecalc(); markContainingBlocksForLayout(); } }
static inline bool findPreviousAndNextAttributes(RenderObject* root, RenderSVGInlineText* locateElement, SVGTextLayoutAttributes*& previous, SVGTextLayoutAttributes*& next) { ASSERT(root); ASSERT(locateElement); bool stopAfterNext = false; RenderObject* current = root->firstChild(); while (current) { if (current->isSVGInlineText()) { RenderSVGInlineText* text = toRenderSVGInlineText(current); if (locateElement != text) { if (stopAfterNext) { next = text->layoutAttributes(); return true; } previous = text->layoutAttributes(); } else { stopAfterNext = true; } } else if (current->isSVGInline()) { // Descend into text content (if possible). if (RenderObject* child = current->firstChild()) { current = child; continue; } } current = current->nextInPreOrderAfterChildren(root); } return false; }
void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild) { // Make sure we don't append things after :after-generated content if we have it. if (!beforeChild) beforeChild = findAfterContentRenderer(); if (!child->isTableCell()) { RenderObject* last = beforeChild; if (!last) last = lastChild(); if (last && last->isAnonymous() && last->isTableCell() && !last->isBeforeOrAfterContent()) { if (beforeChild == last) beforeChild = last->firstChild(); last->addChild(child, beforeChild); return; } if (beforeChild && !beforeChild->isAnonymous() && beforeChild->parent() == this) { RenderObject* cell = beforeChild->previousSibling(); if (cell && cell->isTableCell()) { ASSERT(cell->isAnonymous()); cell->addChild(child); return; } } // If beforeChild is inside an anonymous cell, insert into the cell. if (last && !last->isTableCell() && last->parent() && last->parent()->isAnonymous() && !last->parent()->isBeforeOrAfterContent()) { last->parent()->addChild(child, beforeChild); return; } RenderTableCell* cell = new (renderArena()) RenderTableCell(document() /* anonymous object */); RefPtr<RenderStyle> newStyle = RenderStyle::create(); newStyle->inheritFrom(style()); newStyle->setDisplay(TABLE_CELL); cell->setStyle(newStyle.release()); addChild(cell, beforeChild); cell->addChild(child); return; } // If the next renderer is actually wrapped in an anonymous table cell, we need to go up and find that. while (beforeChild && beforeChild->parent() != this) beforeChild = beforeChild->parent(); RenderTableCell* cell = toRenderTableCell(child); // Generated content can result in us having a null section so make sure to null check our parent. if (parent()) section()->addCell(cell, this); ASSERT(!beforeChild || beforeChild->isTableCell()); RenderBox::addChild(cell, beforeChild); if (beforeChild || nextSibling()) section()->setNeedsCellRecalc(); }
void AutoTableLayout::fullRecalc() { percentagesDirty = true; hasPercent = false; effWidthDirty = true; int nEffCols = table->numEffCols(); layoutStruct.resize( nEffCols ); layoutStruct.fill( Layout() ); spanCells.fill( 0 ); RenderObject *child = table->firstChild(); Length grpWidth; int cCol = 0; while ( child ) { if ( child->isTableCol() ) { RenderTableCol *col = static_cast<RenderTableCol *>(child); int span = col->span(); if ( col->firstChild() ) { grpWidth = col->style()->width(); } else { Length w = col->style()->width(); if ( w.isVariable() ) w = grpWidth; if ( (w.isFixed() && w.value() == 0) || (w.isPercent() && w.value() == 0) ) w = Length(); int cEffCol = table->colToEffCol( cCol ); #ifdef DEBUG_LAYOUT qDebug(" col element %d (eff=%d): Length=%d(%d), span=%d, effColSpan=%d", cCol, cEffCol, w.value(), w.type(), span, table->spanOfEffCol(cEffCol ) ); #endif if ( !w.isVariable() && span == 1 && cEffCol < nEffCols ) { if ( table->spanOfEffCol( cEffCol ) == 1 ) { layoutStruct[cEffCol].width = w; if (w.isFixed() && layoutStruct[cEffCol].maxWidth < w.value()) layoutStruct[cEffCol].maxWidth = w.value(); } } cCol += span; } } else { break; } RenderObject *next = child->firstChild(); if ( !next ) next = child->nextSibling(); if ( !next && child->parent()->isTableCol() ) { next = child->parent()->nextSibling(); grpWidth = Length(); } child = next; } for ( int i = 0; i < nEffCols; i++ ) recalcColumn( i ); }
Position RenderInline::positionForCoordinates(int x, int y) { for (RenderObject *c = continuation(); c; c = c->continuation()) { if (c->isInline() || c->firstChild()) return c->positionForCoordinates(x, y); } return RenderFlow::positionForCoordinates(x, y); }
RenderMathMLOperator* RenderMathMLFraction::unembellishedOperator() { RenderObject* numeratorWrapper = firstChild(); if (!numeratorWrapper) return 0; RenderObject* numerator = numeratorWrapper->firstChild(); if (!numerator || !numerator->isRenderMathMLBlock()) return 0; return toRenderMathMLBlock(numerator)->unembellishedOperator(); }
RenderBoxModelObject* RenderMathMLSubSup::base() const { RenderObject* baseWrapper = firstChild(); if (!baseWrapper) return 0; RenderObject* base = baseWrapper->firstChild(); if (!base || !base->isBoxModelObject()) return 0; return toRenderBoxModelObject(base); }
void RenderMathMLUnderOver::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) { RenderMathMLBlock::styleDidChange(diff, oldStyle); RenderObject* base = this->base(); for (RenderObject* child = firstChild(); child; child = child->nextSibling()) { ASSERT(child->isAnonymous() && child->style()->refCount() == 1); if (child->firstChild() != base) child->style()->setTextAlign(CENTER); } }
static RenderObject* findBeforeAfterParent(RenderObject* object) { // Only table parts need to search for the :before or :after parent if (!(object->isTable() || object->isTableSection() || object->isTableRow())) return object; RenderObject* beforeAfterParent = object; while (beforeAfterParent && !(beforeAfterParent->isText() || beforeAfterParent->isImage())) beforeAfterParent = beforeAfterParent->firstChild(); return beforeAfterParent; }
RenderBoxModelObject* RenderMathMLUnderOver::base() const { RenderObject* baseWrapper = firstChild(); if ((m_kind == Over || m_kind == UnderOver) && baseWrapper) baseWrapper = baseWrapper->nextSibling(); if (!baseWrapper) return 0; RenderObject* base = baseWrapper->firstChild(); if (!base || !base->isBoxModelObject()) return 0; return toRenderBoxModelObject(base); }
void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild) { // Make sure we don't append things after :after-generated content if we have it. if (!beforeChild) beforeChild = afterPseudoElementRenderer(); if (!child->isTableCell()) { RenderObject* last = beforeChild; if (!last) last = lastChild(); if (last && last->isAnonymous() && last->isTableCell() && !last->isBeforeOrAfterContent()) { if (beforeChild == last) beforeChild = last->firstChild(); last->addChild(child, beforeChild); return; } if (beforeChild && !beforeChild->isAnonymous() && beforeChild->parent() == this) { RenderObject* cell = beforeChild->previousSibling(); if (cell && cell->isTableCell() && cell->isAnonymous()) { cell->addChild(child); return; } } // If beforeChild is inside an anonymous cell, insert into the cell. if (last && !last->isTableCell() && last->parent() && last->parent()->isAnonymous() && !last->parent()->isBeforeOrAfterContent()) { last->parent()->addChild(child, beforeChild); return; } RenderTableCell* cell = RenderTableCell::createAnonymousWithParentRenderer(this); addChild(cell, beforeChild); cell->addChild(child); return; } // If the next renderer is actually wrapped in an anonymous table cell, we need to go up and find that. while (beforeChild && beforeChild->parent() != this) beforeChild = beforeChild->parent(); RenderTableCell* cell = toRenderTableCell(child); // Generated content can result in us having a null section so make sure to null check our parent. if (parent()) section()->addCell(cell, this); ASSERT(!beforeChild || beforeChild->isTableCell()); RenderBox::addChild(cell, beforeChild); if (beforeChild || nextSibling()) section()->setNeedsCellRecalc(); }
void RenderContainer::removeLeftoverAnonymousBoxes() { // we have to go over all child nodes and remove anonymous boxes, that do _not_ // have inline children to keep the tree flat RenderObject *child = firstChild(); while( child ) { RenderObject *next = child->nextSibling(); if ( child->isRenderBlock() && child->isAnonymousBlock() && !child->continuation() && !child->childrenInline() && !child->isTableCell() ) { RenderObject *firstAnChild = child->firstChild(); RenderObject *lastAnChild = child->lastChild(); if ( firstAnChild ) { RenderObject *o = firstAnChild; while( o ) { o->setParent( this ); o = o->nextSibling(); } firstAnChild->setPreviousSibling( child->previousSibling() ); lastAnChild->setNextSibling( child->nextSibling() ); if ( child->previousSibling() ) child->previousSibling()->setNextSibling( firstAnChild ); if ( child->nextSibling() ) child->nextSibling()->setPreviousSibling( lastAnChild ); } else { if ( child->previousSibling() ) child->previousSibling()->setNextSibling( child->nextSibling() ); if ( child->nextSibling() ) child->nextSibling()->setPreviousSibling( child->previousSibling() ); } if ( child == firstChild() ) m_first = firstAnChild; if ( child == lastChild() ) m_last = lastAnChild; child->setParent( 0 ); child->setPreviousSibling( 0 ); child->setNextSibling( 0 ); if ( !child->isText() ) { RenderContainer *c = static_cast<RenderContainer *>(child); c->m_first = 0; c->m_next = 0; } child->detach(); } child = next; } if ( parent() ) parent()->removeLeftoverAnonymousBoxes(); }
static RenderObject* findBeforeAfterParent(RenderObject* object) { // Only table parts need to search for the :before or :after parent if (!(object->isTable() || object->isTableSection() || object->isTableRow())) return object; // If there is a :first-letter style applied on the :before or :after content, // then we want the parent of the first-letter block RenderObject* beforeAfterParent = object; while (beforeAfterParent && !(beforeAfterParent->isText() || beforeAfterParent->isImage()) && (beforeAfterParent->style()->styleType() != FIRST_LETTER)) beforeAfterParent = beforeAfterParent->firstChild(); return beforeAfterParent ? beforeAfterParent->parent() : 0; }
void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild) { if (!child->isTableCell()) { RenderObject* last = beforeChild; if (!last) last = lastChild(); if (last && last->isAnonymous() && last->isTableCell() && !last->isBeforeOrAfterContent()) { if (beforeChild == last) beforeChild = last->firstChild(); last->addChild(child, beforeChild); return; } if (beforeChild && !beforeChild->isAnonymous() && beforeChild->parent() == this) { RenderObject* cell = beforeChild->previousSibling(); if (cell && cell->isTableCell() && cell->isAnonymous()) { cell->addChild(child); return; } } // If beforeChild is inside an anonymous cell, insert into the cell. if (last && !last->isTableCell() && last->parent() && last->parent()->isAnonymous() && !last->parent()->isBeforeOrAfterContent()) { last->parent()->addChild(child, beforeChild); return; } RenderTableCell* cell = RenderTableCell::createAnonymousWithParentRenderer(this); addChild(cell, beforeChild); cell->addChild(child); return; } if (beforeChild && beforeChild->parent() != this) beforeChild = splitAnonymousBoxesAroundChild(beforeChild); RenderTableCell* cell = toRenderTableCell(child); // Generated content can result in us having a null section so make sure to null check our parent. if (parent()) section()->addCell(cell, this); ASSERT(!beforeChild || beforeChild->isTableCell()); RenderBox::addChild(cell, beforeChild); if (beforeChild || nextSibling()) section()->setNeedsCellRecalc(); }
VisiblePosition RenderInline::positionForCoordinates(int x, int y) { // Translate the coords from the pre-anonymous block to the post-anonymous block. RenderBlock* cb = containingBlock(); int parentBlockX = cb->xPos() + x; int parentBlockY = cb->yPos() + y; for (RenderObject* c = continuation(); c; c = c->continuation()) { RenderObject* contBlock = c; if (c->isInline()) contBlock = c->containingBlock(); if (c->isInline() || c->firstChild()) return c->positionForCoordinates(parentBlockX - contBlock->xPos(), parentBlockY - contBlock->yPos()); } return RenderFlow::positionForCoordinates(x, y); }