static inline void setupResolverToResumeInIsolate(InlineBidiResolver& resolver, LineLayoutItem root, LineLayoutItem startObject) { if (root != startObject) { LineLayoutItem parent = startObject.parent(); setupResolverToResumeInIsolate(resolver, root, parent); notifyObserverEnteredObject(&resolver, LineLayoutItem(startObject)); } }
void LineBoxList::dirtyLinesFromChangedChild(LineLayoutItem container, LineLayoutItem child) { if (!container.parent() || (container.isLayoutBlock() && (container.selfNeedsLayout() || !container.isLayoutBlockFlow()))) return; LineLayoutInline inlineContainer = container.isLayoutInline() ? LineLayoutInline(container) : LineLayoutInline(); 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 = nullptr; LineLayoutItem curr = nullptr; for (curr = child.previousSibling(); curr; curr = curr.previousSibling()) { if (curr.isFloatingOrOutOfFlowPositioned()) continue; if (curr.isAtomicInlineLevel()) { InlineBox* wrapper = toLayoutBox(curr)->inlineBoxWrapper(); if (wrapper) box = &wrapper->root(); } else if (curr.isText()) { InlineTextBox* textBox = toLayoutText(curr)->lastTextBox(); if (textBox) box = &textBox->root(); } else if (curr.isLayoutInline()) { InlineBox* lastSiblingBox = toLayoutInline(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) { 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 LayoutBlock::layoutInlineChildren // calls setLineBreakInfo with the result of findNextLineBreak. findNextLineBreak, // despite the name, actually returns the first LayoutObject after the BR. // <rdar://problem/3849947> "Typing after pasting line does not appear until after window resize." if (RootInlineBox* prevRootBox = box->prevRootBox()) prevRootBox->markDirty(); // If |child| or any of its immediately previous siblings with culled lineboxes is the object after a line-break in |box| or the linebox after it // then that means |child| actually sits on the linebox after |box| (or is its line-break object) and so we need to dirty it as well. if (RootInlineBox* nextRootBox = box->nextRootBox()) nextRootBox->markDirty(); } }