本文整理汇总了C++中InlineBox类的典型用法代码示例。如果您正苦于以下问题:C++ InlineBox类的具体用法?C++ InlineBox怎么用?C++ InlineBox使用的例子?那么, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了InlineBox类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: firstLeafChild
InlineBox* SVGRootInlineBox::closestLeafChildForPosition(const LayoutPoint& point)
{
InlineBox* firstLeaf = firstLeafChild();
InlineBox* lastLeaf = lastLeafChild();
if (firstLeaf == lastLeaf)
return firstLeaf;
// FIXME: Check for vertical text!
InlineBox* closestLeaf = 0;
for (InlineBox* leaf = firstLeaf; leaf; leaf = leaf->nextLeafChild()) {
if (!leaf->isSVGInlineTextBox())
continue;
if (point.y() < leaf->y())
continue;
if (point.y() > leaf->y() + leaf->virtualLogicalHeight())
continue;
closestLeaf = leaf;
if (point.x() < leaf->left() + leaf->logicalWidth())
return leaf;
}
return closestLeaf ? closestLeaf : lastLeaf;
}
示例2: findSVGRootObject
void RenderSVGText::absoluteQuads(Vector<FloatQuad>& quads)
{
RenderSVGRoot* root = findSVGRootObject(parent());
if (!root)
return;
// Don't use objectBoundingBox here, as it's unites the selection rects. Makes it hard
// to spot errors, if there are any using WebInspector. Individually feed them into 'rects'.
for (InlineFlowBox* flow = firstLineBox(); flow; flow = flow->nextLineBox()) {
for (InlineBox* box = flow->firstChild(); box; box = box->nextOnLine()) {
FloatRect boxRect(box->x(), box->y(), box->width(), box->height());
// FIXME: crawling up the parent chain to map each quad is very inefficient
// we should compute the absoluteTransform outside this loop first.
quads.append(localToAbsoluteQuad(boxRect));
}
}
}
示例3: ASSERT
FloatRect RenderSVGText::relativeBBox(bool includeStroke) const
{
FloatRect repaintRect;
for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) {
ASSERT(runBox->isInlineFlowBox());
InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox);
for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine())
repaintRect.unite(FloatRect(box->xPos(), box->yPos(), box->width(), box->height()));
}
// SVG needs to include the strokeWidth(), not the textStrokeWidth().
if (includeStroke && style()->svgStyle()->hasStroke())
repaintRect.inflate(narrowPrecisionToFloat(KSVGPainterFactory::cssPrimitiveToLength(this, style()->svgStyle()->strokeWidth(), 0.0)));
repaintRect.move(xPos(), yPos());
return repaintRect;
}
示例4: findSVGRootObject
void RenderSVGText::absoluteRects(Vector<IntRect>& rects, int, int)
{
RenderSVGRoot* root = findSVGRootObject(parent());
if (!root)
return;
// Don't use objectBoundingBox here, as it's unites the selection rects. Makes it hard
// to spot errors, if there are any using WebInspector. Individually feed them into 'rects'.
for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) {
ASSERT(runBox->isInlineFlowBox());
InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox);
for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) {
FloatRect boxRect(box->x(), box->y(), box->width(), box->height());
// FIXME: crawling up the parent chain to map each rect is very inefficient
// we should compute the absoluteTransform outside this loop first.
rects.append(enclosingIntRect(localToAbsoluteQuad(boxRect).boundingBox()));
}
}
}
示例5: ASSERT
void SVGRootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit, LayoutUnit)
{
ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
ASSERT(!paintInfo.context->paintingDisabled());
bool isPrinting = renderer().document().printing();
bool hasSelection = !isPrinting && selectionState() != RenderObject::SelectionNone;
PaintInfo childPaintInfo(paintInfo);
if (hasSelection) {
for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) {
if (child->isSVGInlineTextBox())
toSVGInlineTextBox(child)->paintSelectionBackground(childPaintInfo);
else if (child->isSVGInlineFlowBox())
toSVGInlineFlowBox(child)->paintSelectionBackground(childPaintInfo);
}
}
SVGRenderingContext renderingContext(&renderer(), paintInfo, SVGRenderingContext::SaveGraphicsContext);
if (renderingContext.isRenderingPrepared()) {
for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
child->paint(paintInfo, paintOffset, 0, 0);
}
}
示例6: applyTextAnchorToTextChunk
static void applyTextAnchorToTextChunk(SVGTextChunk& chunk)
{
// This method is not called for chunks containing chars aligned on a path.
// -> all characters are visible, no need to check for "isHidden()" anywhere.
if (chunk.anchor == TA_START)
return;
float shift = calculateTextAnchorShiftForTextChunk(chunk, chunk.anchor);
// Apply correction to chunk
Vector<SVGChar>::iterator chunkIt = chunk.start;
for (; chunkIt != chunk.end; ++chunkIt) {
SVGChar& curChar = *chunkIt;
if (chunk.isVerticalText)
curChar.y += shift;
else
curChar.x += shift;
}
// Move inline boxes
Vector<SVGInlineBoxCharacterRange>::iterator boxIt = chunk.boxes.begin();
Vector<SVGInlineBoxCharacterRange>::iterator boxEnd = chunk.boxes.end();
for (; boxIt != boxEnd; ++boxIt) {
SVGInlineBoxCharacterRange& range = *boxIt;
InlineBox* curBox = range.box;
ASSERT(curBox->isSVGInlineTextBox());
// Move target box
if (chunk.isVerticalText)
curBox->setY(curBox->y() + static_cast<int>(shift));
else
curBox->setX(curBox->x() + static_cast<int>(shift));
}
}
示例7: findSVGRootObject
void RenderSVGText::absoluteRects(Vector<IntRect>& rects, int, int, bool)
{
RenderSVGRoot* root = findSVGRootObject(parent());
if (!root)
return;
int x, y;
absolutePosition(x, y);
AffineTransform htmlParentCtm = root->RenderContainer::absoluteTransform();
// Don't use relativeBBox here, as it's unites the selection rects. Makes it hard
// to spot errors, if there are any using WebInspector. Individually feed them into 'rects'.
for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) {
ASSERT(runBox->isInlineFlowBox());
InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox);
for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) {
FloatRect boxRect(box->xPos(), box->yPos(), box->width(), box->height());
boxRect.move(narrowPrecisionToFloat(x - htmlParentCtm.e()), narrowPrecisionToFloat(y - htmlParentCtm.f()));
rects.append(enclosingIntRect(absoluteTransform().mapRect(boxRect)));
}
}
}
示例8: overflowRect
void InlineFlowBoxPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset, const LayoutUnit lineTop, const LayoutUnit lineBottom)
{
LayoutRect overflowRect(m_inlineFlowBox.visualOverflowRect(lineTop, lineBottom));
m_inlineFlowBox.flipForWritingMode(overflowRect);
overflowRect.moveBy(paintOffset);
if (!paintInfo.rect.intersects(pixelSnappedIntRect(overflowRect)))
return;
if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) {
// Add ourselves to the paint info struct's list of inlines that need to paint their
// outlines.
if (m_inlineFlowBox.layoutObject().style()->visibility() == VISIBLE && m_inlineFlowBox.layoutObject().style()->hasOutline() && !m_inlineFlowBox.isRootInlineBox()) {
LayoutInline& inlineFlow = toLayoutInline(m_inlineFlowBox.layoutObject());
LayoutBlock* cb = 0;
bool containingBlockPaintsContinuationOutline = inlineFlow.continuation() || inlineFlow.isInlineElementContinuation();
if (containingBlockPaintsContinuationOutline) {
// FIXME: See https://bugs.webkit.org/show_bug.cgi?id=54690. We currently don't reconnect inline continuations
// after a child removal. As a result, those merged inlines do not get seperated and hence not get enclosed by
// anonymous blocks. In this case, it is better to bail out and paint it ourself.
LayoutBlock* enclosingAnonymousBlock = m_inlineFlowBox.layoutObject().containingBlock();
if (!enclosingAnonymousBlock->isAnonymousBlock()) {
containingBlockPaintsContinuationOutline = false;
} else {
cb = enclosingAnonymousBlock->containingBlock();
for (LayoutBoxModelObject* box = m_inlineFlowBox.boxModelObject(); box != cb; box = box->parent()->enclosingBoxModelObject()) {
if (box->hasSelfPaintingLayer()) {
containingBlockPaintsContinuationOutline = false;
break;
}
}
}
}
if (containingBlockPaintsContinuationOutline) {
// Add ourselves to the containing block of the entire continuation so that it can
// paint us atomically.
cb->addContinuationWithOutline(toLayoutInline(m_inlineFlowBox.layoutObject().node()->layoutObject()));
} else if (!inlineFlow.isInlineElementContinuation()) {
paintInfo.outlineObjects()->add(&inlineFlow);
}
}
} else if (paintInfo.phase == PaintPhaseMask) {
DrawingRecorder recorder(*paintInfo.context, m_inlineFlowBox, DisplayItem::paintPhaseToDrawingType(paintInfo.phase), pixelSnappedIntRect(overflowRect));
if (!recorder.canUseCachedDrawing())
paintMask(paintInfo, paintOffset);
return;
} else if (paintInfo.phase == PaintPhaseForeground) {
// Paint our background, border and box-shadow.
paintBoxDecorationBackground(paintInfo, paintOffset);
}
// Paint our children.
if (paintInfo.phase != PaintPhaseSelfOutline) {
PaintInfo childInfo(paintInfo);
childInfo.phase = paintInfo.phase == PaintPhaseChildOutlines ? PaintPhaseOutline : paintInfo.phase;
if (childInfo.paintingRoot && childInfo.paintingRoot->isDescendantOf(&m_inlineFlowBox.layoutObject()))
childInfo.paintingRoot = 0;
else
childInfo.updatePaintingRootForChildren(&m_inlineFlowBox.layoutObject());
for (InlineBox* curr = m_inlineFlowBox.firstChild(); curr; curr = curr->nextOnLine()) {
if (curr->layoutObject().isText() || !curr->boxModelObject()->hasSelfPaintingLayer())
curr->paint(childInfo, paintOffset, lineTop, lineBottom);
}
}
}
示例9: atRightmostOffsetInBox
unsigned char RenderedPosition::bidiLevelOnRight() const
{
InlineBox* box = atRightmostOffsetInBox() ? nextLeafChild() : m_inlineBox;
return box ? box->bidiLevel() : 0;
}
示例10: paintBoxDecorations
//.........这里部分代码省略.........
QRect r(pix.rect());
r = r.intersect(QRect(0, 0, cWidth-4, cHeight-4));
p->drawPixmap( QPoint( _tx + leftBorder + leftPad+2, _ty + topBorder + topPad+2), pix, r );
}
if(!alt.isEmpty()) {
QString text = alt.string();
text.replace('\\', backslashAsCurrencySymbol());
p->setFont(style()->font());
p->setPen( style()->color() );
int ax = _tx + leftBorder + leftPad + 2;
int ay = _ty + topBorder + topPad + 2;
const QFontMetrics &fm = style()->fontMetrics();
if (cWidth>5 && cHeight>=fm.height())
p->drawText(ax, ay+1, cWidth - 4, cHeight - 4, Qt::WordBreak, text );
}
#endif /* APPLE_CHANGES not defined */
}
}
else if (image && !image->isTransparent())
{
#if APPLE_CHANGES
// Do the calculations to draw selections as tall as the line.
// Ignore the passed-in value for _ty.
// Use the bottom of the line above as the y position (if there is one,
// otherwise use the top of this renderer's line) and the height of the line as the height.
// This mimics Cocoa.
int selectionTop = -1;
int selectionHeight = -1;
int selectionLeft = -1;
int selectionRight = -1;
bool extendSelectionToLeft = false;
bool extendSelectionToRight = false;
if (drawSelectionTint) {
InlineBox *box = inlineBox();
if (box) {
// Get a value for selectionTop that is relative to the containing block.
// This value is used for determining left and right offset for the selection, if necessary,
// and for calculating the selection height.
if (box->root()->prevRootBox())
selectionTop = box->root()->prevRootBox()->bottomOverflow();
else
selectionTop = box->root()->topOverflow();
selectionHeight = box->root()->bottomOverflow() - selectionTop;
int absx, absy;
containingBlock()->absolutePosition(absx, absy);
if (selectionState() == SelectionInside && box->root()->firstLeafChild() == box) {
extendSelectionToLeft = true;
selectionLeft = absx + containingBlock()->leftOffset(selectionTop);
}
if (selectionState() == SelectionInside && box->root()->lastLeafChild() == box) {
extendSelectionToRight = true;
selectionRight = absx + containingBlock()->rightOffset(selectionTop);
}
// Now make the selectionTop an absolute coordinate.
selectionTop += absy;
}
}
#endif
if ( (cWidth != intrinsicWidth() || cHeight != intrinsicHeight()) &&
pix.width() > 0 && pix.height() > 0 && image->valid_rect().isValid())
{
示例11: nextLinePosition
VisiblePosition nextLinePosition(const VisiblePosition &visiblePosition, int x)
{
Position p = visiblePosition.deepEquivalent();
Node *node = p.node();
Node* highestRoot = highestEditableRoot(p);
if (!node)
return VisiblePosition();
node->document()->updateLayoutIgnorePendingStylesheets();
RenderObject *renderer = node->renderer();
if (!renderer)
return VisiblePosition();
RenderBlock *containingBlock = 0;
RootInlineBox *root = 0;
InlineBox* box;
int ignoredCaretOffset;
visiblePosition.getInlineBoxAndOffset(box, ignoredCaretOffset);
if (box) {
root = box->root()->nextRootBox();
if (root)
containingBlock = renderer->containingBlock();
}
if (!root) {
// This containing editable block does not have a next line.
// Need to move forward to next containing editable block in this root editable
// block and find the first root line box in that block.
Node* startBlock = enclosingNodeWithNonInlineRenderer(node);
Node* n = nextLeafWithSameEditability(node, p.deprecatedEditingOffset());
while (n && startBlock == enclosingNodeWithNonInlineRenderer(n))
n = nextLeafWithSameEditability(n);
while (n) {
if (highestEditableRoot(Position(n, 0)) != highestRoot)
break;
Position pos(n, caretMinOffset(n));
if (pos.isCandidate()) {
ASSERT(n->renderer());
pos.getInlineBoxAndOffset(DOWNSTREAM, box, ignoredCaretOffset);
if (box) {
// next root line box found
root = box->root();
containingBlock = n->renderer()->containingBlock();
break;
}
return VisiblePosition(pos, DOWNSTREAM);
}
n = nextLeafWithSameEditability(n);
}
}
if (root) {
// FIXME: Can be wrong for multi-column layout and with transforms.
FloatPoint absPos = containingBlock->localToAbsolute(FloatPoint());
if (containingBlock->hasOverflowClip())
absPos -= containingBlock->layer()->scrolledContentOffset();
RenderObject* renderer = root->closestLeafChildForXPos(x - absPos.x(), isEditablePosition(p))->renderer();
Node* node = renderer->node();
if (node && editingIgnoresContent(node))
return Position(node->parent(), node->nodeIndex());
return renderer->positionForPoint(IntPoint(x - absPos.x(), root->lineTop()));
}
// Could not find a next line. This means we must already be on the last line.
// Move to the end of the content in this block, which effectively moves us
// to the end of the line we're on.
Element* rootElement = node->isContentEditable() ? node->rootEditableElement() : node->document()->documentElement();
return VisiblePosition(rootElement, rootElement ? rootElement->childNodeCount() : 0, DOWNSTREAM);
}
示例12: ASSERT
void RenderLineBoxList::dirtyLinesFromChangedChild(RenderBoxModelObject& container, RenderObject& child)
{
ASSERT(is<RenderInline>(container) || is<RenderBlockFlow>(container));
if (!container.parent() || (is<RenderBlockFlow>(container) && container.selfNeedsLayout()))
return;
RenderInline* inlineContainer = is<RenderInline>(container) ? &downcast<RenderInline>(container) : nullptr;
InlineBox* firstBox = inlineContainer ? inlineContainer->firstLineBoxIncludingCulling() : firstLineBox();
// If we have no first line box, then just bail early.
if (!firstBox) {
// For an empty inline, propagate the check up to our parent, unless the parent is already dirty.
if (container.isInline() && !container.ancestorLineBoxDirty()) {
container.parent()->dirtyLinesFromChangedChild(container);
container.setAncestorLineBoxDirty(); // Mark the container to avoid dirtying the same lines again across multiple destroy() calls of the same subtree.
}
return;
}
// Try to figure out which line box we belong in. First try to find a previous
// line box by examining our siblings. If we didn't find a line box, then use our
// parent's first line box.
RootInlineBox* box = nullptr;
RenderObject* current;
for (current = child.previousSibling(); current; current = current->previousSibling()) {
if (current->isFloatingOrOutOfFlowPositioned())
continue;
if (current->isReplaced()) {
if (auto wrapper = downcast<RenderBox>(*current).inlineBoxWrapper())
box = &wrapper->root();
} if (is<RenderLineBreak>(*current)) {
if (auto wrapper = downcast<RenderLineBreak>(*current).inlineBoxWrapper())
box = &wrapper->root();
} else if (is<RenderText>(*current)) {
if (InlineTextBox* textBox = downcast<RenderText>(*current).lastTextBox())
box = &textBox->root();
} else if (is<RenderInline>(*current)) {
InlineBox* lastSiblingBox = downcast<RenderInline>(*current).lastLineBoxIncludingCulling();
if (lastSiblingBox)
box = &lastSiblingBox->root();
}
if (box)
break;
}
if (!box) {
if (inlineContainer && !inlineContainer->alwaysCreateLineBoxes()) {
// https://bugs.webkit.org/show_bug.cgi?id=60778
// We may have just removed a <br> with no line box that was our first child. In this case
// we won't find a previous sibling, but firstBox can be pointing to a following sibling.
// This isn't good enough, since we won't locate the root line box that encloses the removed
// <br>. We have to just over-invalidate a bit and go up to our parent.
if (!inlineContainer->ancestorLineBoxDirty()) {
inlineContainer->parent()->dirtyLinesFromChangedChild(*inlineContainer);
inlineContainer->setAncestorLineBoxDirty(); // Mark the container to avoid dirtying the same lines again across multiple destroy() calls of the same subtree.
}
return;
}
box = &firstBox->root();
}
// If we found a line box, then dirty it.
if (box) {
box->markDirty();
// Dirty the adjacent lines that might be affected.
// NOTE: we dirty the previous line because RootInlineBox objects cache
// the address of the first object on the next line after a BR, which we may be
// invalidating here. For more info, see how RenderBlock::layoutInlineChildren
// calls setLineBreakInfo with the result of findNextLineBreak. findNextLineBreak,
// despite the name, actually returns the first RenderObject after the BR.
// <rdar://problem/3849947> "Typing after pasting line does not appear until after window resize."
if (RootInlineBox* prevBox = box->prevRootBox())
prevBox->markDirty();
// FIXME: We shouldn't need to always dirty the next line. This is only strictly
// necessary some of the time, in situations involving BRs.
if (RootInlineBox* nextBox = box->nextRootBox()) {
nextBox->markDirty();
// Dedicated linebox for floats may be added as the last rootbox. If this occurs with BRs inside inlines that propagte their lineboxes to
// the parent flow, we need to invalidate it explicitly.
// FIXME: We should be able to figure out the actual "changed child" even when we are calling through empty inlines recursively.
if (is<RenderInline>(child) && !downcast<RenderInline>(child).firstLineBoxIncludingCulling()) {
auto* lastRootBox = nextBox->blockFlow().lastRootBox();
if (lastRootBox->isTrailingFloatsRootInlineBox() && !lastRootBox->isDirty())
lastRootBox->markDirty();
}
}
}
}
示例13: selectionState
GapRects RootInlineBox::fillLineSelectionGap(int selTop, int selHeight, RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty,
const RenderObject::PaintInfo* paintInfo)
{
RenderObject::SelectionState lineState = selectionState();
bool leftGap, rightGap;
block()->getHorizontalSelectionGapInfo(lineState, leftGap, rightGap);
GapRects result;
InlineBox* firstBox = firstSelectedBox();
InlineBox* lastBox = lastSelectedBox();
if (leftGap)
result.uniteLeft(block()->fillLeftSelectionGap(firstBox->parent()->object(),
firstBox->xPos(), selTop, selHeight,
rootBlock, blockX, blockY, tx, ty, paintInfo));
if (rightGap)
result.uniteRight(block()->fillRightSelectionGap(lastBox->parent()->object(),
lastBox->xPos() + lastBox->width(), selTop, selHeight,
rootBlock, blockX, blockY, tx, ty, paintInfo));
if (firstBox && firstBox != lastBox) {
// Now fill in any gaps on the line that occurred between two selected elements.
int lastX = firstBox->xPos() + firstBox->width();
for (InlineBox* box = firstBox->nextLeafChild(); box; box = box->nextLeafChild()) {
if (box->selectionState() != RenderObject::SelectionNone) {
result.uniteCenter(block()->fillHorizontalSelectionGap(box->parent()->object(),
lastX + tx, selTop + ty,
box->xPos() - lastX, selHeight, paintInfo));
lastX = box->xPos() + box->width();
}
if (box == lastBox)
break;
}
}
return result;
}
示例14: markDirty
void SVGRootInlineBox::markDirty()
{
for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
child->markDirty();
RootInlineBox::markDirty();
}
示例15: toRenderInline
void RenderLineBoxList::dirtyLinesFromChangedChild(RenderObject* container, RenderObject* child)
{
if (!container->parent() || (container->isRenderBlock() && (container->selfNeedsLayout() || !container->isBlockFlow())))
return;
RenderInline* inlineContainer = container->isRenderInline() ? toRenderInline(container) : 0;
InlineBox* firstBox = inlineContainer ? inlineContainer->firstLineBoxIncludingCulling() : firstLineBox();
// If we have no first line box, then just bail early.
if (!firstBox) {
// For an empty inline, go ahead and propagate the check up to our parent, unless the parent
// is already dirty.
if (container->isInline() && !container->ancestorLineBoxDirty()) {
container->parent()->dirtyLinesFromChangedChild(container);
container->setAncestorLineBoxDirty(); // Mark the container to avoid dirtying the same lines again across multiple destroy() calls of the same subtree.
}
return;
}
// Try to figure out which line box we belong in. First try to find a previous
// line box by examining our siblings. If we didn't find a line box, then use our
// parent's first line box.
RootInlineBox* box = 0;
RenderObject* curr = 0;
for (curr = child->previousSibling(); curr; curr = curr->previousSibling()) {
if (curr->isFloatingOrOutOfFlowPositioned())
continue;
if (curr->isReplaced()) {
InlineBox* wrapper = toRenderBox(curr)->inlineBoxWrapper();
if (wrapper)
box = wrapper->root();
} else if (curr->isText()) {
InlineTextBox* textBox = toRenderText(curr)->lastTextBox();
if (textBox)
box = textBox->root();
} else if (curr->isRenderInline()) {
InlineBox* lastSiblingBox = toRenderInline(curr)->lastLineBoxIncludingCulling();
if (lastSiblingBox)
box = lastSiblingBox->root();
}
if (box)
break;
}
if (!box) {
if (inlineContainer && !inlineContainer->alwaysCreateLineBoxes()) {
// https://bugs.webkit.org/show_bug.cgi?id=60778
// We may have just removed a <br> with no line box that was our first child. In this case
// we won't find a previous sibling, but firstBox can be pointing to a following sibling.
// This isn't good enough, since we won't locate the root line box that encloses the removed
// <br>. We have to just over-invalidate a bit and go up to our parent.
if (!inlineContainer->ancestorLineBoxDirty()) {
inlineContainer->parent()->dirtyLinesFromChangedChild(inlineContainer);
inlineContainer->setAncestorLineBoxDirty(); // Mark the container to avoid dirtying the same lines again across multiple destroy() calls of the same subtree.
}
return;
}
box = firstBox->root();
}
// If we found a line box, then dirty it.
if (box) {
RootInlineBox* adjacentBox;
box->markDirty();
// dirty the adjacent lines that might be affected
// NOTE: we dirty the previous line because RootInlineBox objects cache
// the address of the first object on the next line after a BR, which we may be
// invalidating here. For more info, see how RenderBlock::layoutInlineChildren
// calls setLineBreakInfo with the result of findNextLineBreak. findNextLineBreak,
// despite the name, actually returns the first RenderObject after the BR.
// <rdar://problem/3849947> "Typing after pasting line does not appear until after window resize."
adjacentBox = box->prevRootBox();
if (adjacentBox)
adjacentBox->markDirty();
adjacentBox = box->nextRootBox();
// If |child| has been inserted before the first element in the linebox, but after collapsed leading
// space, the search for |child|'s linebox will go past the leading space to the previous linebox and select that
// one as |box|. If we hit that situation here, dirty the |box| actually containing the child too.
bool insertedAfterLeadingSpace = box->lineBreakObj() == child->previousSibling();
if (adjacentBox && (adjacentBox->lineBreakObj() == child || child->isBR() || (curr && curr->isBR()) || insertedAfterLeadingSpace))
adjacentBox->markDirty();
}
}