Bug 1388877. Fix insertions under a ::first-line in stylo. r=heycam

MozReview-Commit-ID: CDolJpTtGki
This commit is contained in:
Boris Zbarsky
2017-08-11 09:11:23 -04:00
parent 2b8dbcb8bd
commit e2ae165a46
21 changed files with 303 additions and 9 deletions

View File

@@ -7895,11 +7895,23 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer,
PullOutCaptionFrames(frameItems, captionItems);
}
bool dealtWithFirstLine = false;
if (haveFirstLineStyle && parentFrame == containingBlock) {
// It's possible that some of the new frames go into a
// first-line frame. Look at them and see...
AppendFirstLineFrames(state, containingBlock->GetContent(),
containingBlock, frameItems);
// That moved things into line frames as needed, reparenting their
// styles. Nothing else needs to be done.
dealtWithFirstLine = true;
}
if (!dealtWithFirstLine &&
parentFrame->StyleContext()->HasPseudoElementData()) {
// parentFrame might be inside a ::first-line frame. Check whether it is,
// and if so fix up our styles.
CheckForFirstLineInsertion(parentFrame, frameItems);
CheckForFirstLineInsertion(parentFrame, captionItems);
}
// Notify the parent frame passing it the list of new frames
@@ -8495,6 +8507,7 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer,
prevSibling = ::FindAppendPrevSibling(insertion.mParentFrame, appendAfterFrame);
}
bool dealtWithFirstLine = false;
if (haveFirstLineStyle && insertion.mParentFrame == containingBlock) {
// It's possible that the new frame goes into a first-line
// frame. Look at it and see...
@@ -8502,17 +8515,28 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer,
// Use append logic when appending
AppendFirstLineFrames(state, containingBlock->GetContent(),
containingBlock, frameItems);
// That moved things into line frames as needed, reparenting their
// styles. Nothing else needs to be done to handle ::first-line.
dealtWithFirstLine = true;
}
else {
// Use more complicated insert logic when inserting
// XXXbz this method is a no-op, so it's easy for the args being passed
// here to make no sense without anyone noticing... If it ever stops
// being a no-op, vet them carefully!
// XXXbz Can this code even get hit? I'd think/hope not, since any
// insert would go into an existing lineframe if we have them..
InsertFirstLineFrames(state, container, containingBlock, &insertion.mParentFrame,
prevSibling, frameItems);
}
}
if (!dealtWithFirstLine &&
insertion.mParentFrame->StyleContext()->HasPseudoElementData()) {
CheckForFirstLineInsertion(insertion.mParentFrame, frameItems);
CheckForFirstLineInsertion(insertion.mParentFrame, captionItems);
}
// We might have captions; put them into the caption list of the
// table wrapper frame.
if (captionItems.NotEmpty()) {
@@ -11708,6 +11732,56 @@ nsCSSFrameConstructor::InsertFirstLineFrames(
#endif
}
void
nsCSSFrameConstructor::CheckForFirstLineInsertion(nsIFrame* aParentFrame,
nsFrameItems& aFrameItems)
{
MOZ_ASSERT(aParentFrame->StyleContext()->HasPseudoElementData(),
"Why were we called?");
if (aFrameItems.IsEmpty()) {
// Happens often enough, with the caption stuff. No need to do the ancestor
// walk here.
return;
}
class RestyleManager* restyleManager = RestyleManager();
if (!restyleManager->IsServo()) {
// Gecko's style resolution is frame-based, so already has the right styles
// even in the ::first-line case.
return;
}
// Check whether there's a ::first-line on the path up from aParentFrame.
// Note that we can't stop until we've run out of ancestors with
// pseudo-element data, because the first-letter might be somewhere way up the
// tree; in particular it might be past our containing block.
nsIFrame* ancestor = aParentFrame;
while (ancestor) {
if (!ancestor->StyleContext()->HasPseudoElementData()) {
// We know we won't find a ::first-line now.
return;
}
if (!ancestor->IsLineFrame()) {
ancestor = ancestor->GetParent();
continue;
}
if (!ancestor->StyleContext()->IsPseudoElement()) {
// This is a continuation lineframe, not the first line; no need to do
// anything to the styles.
return;
}
// Fix up the styles of aFrameItems for ::first-line.
for (nsIFrame* f : aFrameItems) {
restyleManager->ReparentStyleContext(f);
}
return;
}
}
//----------------------------------------------------------------------
// First-letter support