Bug 1359341 part 3 - Propagate AreAllEarlierInFlowFramesEmpty() state on placeholders down the line. We can stop iterating siblings if we find a placeholder with a stored state. r=jfkthame

MozReview-Commit-ID: DNtcNIEwA5P
This commit is contained in:
Mats Palmgren 2017-05-23 19:09:27 +02:00
Родитель e51607abe1
Коммит f9096282d3
2 изменённых файлов: 49 добавлений и 19 удалений

Просмотреть файл

@ -1224,20 +1224,29 @@ ReflowInput::CalculateBorderPaddingMargin(
* Returns true iff a pre-order traversal of the normal child
* frames rooted at aFrame finds no non-empty frame before aDescendant.
*/
static bool AreAllEarlierInFlowFramesEmpty(nsIFrame* aFrame,
nsIFrame* aDescendant, bool* aFound) {
static bool
AreAllEarlierInFlowFramesEmpty(nsIFrame* aFrame,
nsIFrame* aDescendant,
bool* aFound)
{
if (aFrame == aDescendant) {
*aFound = true;
return true;
}
if (!aFrame->IsSelfEmpty()) {
*aFound = false;
return false;
}
for (nsIFrame* f : aFrame->PrincipalChildList()) {
bool allEmpty = AreAllEarlierInFlowFramesEmpty(f, aDescendant, aFound);
if (*aFound || !allEmpty) {
return allEmpty;
if (aFrame->IsPlaceholderFrame()) {
auto ph = static_cast<nsPlaceholderFrame*>(aFrame);
MOZ_ASSERT(ph->IsSelfEmpty() && ph->PrincipalChildList().IsEmpty());
ph->SetLineIsEmptySoFar(true);
} else {
if (!aFrame->IsSelfEmpty()) {
*aFound = false;
return false;
}
for (nsIFrame* f : aFrame->PrincipalChildList()) {
bool allEmpty = AreAllEarlierInFlowFramesEmpty(f, aDescendant, aFound);
if (*aFound || !allEmpty) {
return allEmpty;
}
}
}
*aFound = false;
@ -1389,15 +1398,31 @@ ReflowInput::CalculateHypotheticalPosition(
// XXXbz the line box is not fully reflowed yet if our
// containing block is relatively positioned...
if (lineBox != iter.End()) {
nsIFrame * firstFrame = lineBox->mFirstChild;
bool found = false;
bool allEmpty = true;
while (firstFrame) { // See bug 223064
allEmpty = AreAllEarlierInFlowFramesEmpty(firstFrame,
aPlaceholderFrame, &found);
if (found || !allEmpty)
break;
firstFrame = firstFrame->GetNextSibling();
nsIFrame* firstFrame = lineBox->mFirstChild;
bool allEmpty = false;
if (firstFrame == aPlaceholderFrame) {
aPlaceholderFrame->SetLineIsEmptySoFar(true);
allEmpty = true;
} else {
auto prev = aPlaceholderFrame->GetPrevSibling();
if (prev && prev->IsPlaceholderFrame()) {
auto ph = static_cast<nsPlaceholderFrame*>(prev);
if (ph->GetLineIsEmptySoFar(&allEmpty)) {
aPlaceholderFrame->SetLineIsEmptySoFar(allEmpty);
}
}
}
if (!allEmpty) {
bool found = false;
while (firstFrame) { // See bug 223064
allEmpty = AreAllEarlierInFlowFramesEmpty(firstFrame,
aPlaceholderFrame, &found);
if (found || !allEmpty) {
break;
}
firstFrame = firstFrame->GetNextSibling();
}
aPlaceholderFrame->SetLineIsEmptySoFar(allEmpty);
}
NS_ASSERTION(firstFrame, "Couldn't find placeholder!");

Просмотреть файл

@ -4209,6 +4209,11 @@ nsBlockFrame::ReflowInlineFrame(BlockReflowInput& aState,
aLineLayout.GetFirstLetterStyleOK() ? "on" : "off");
#endif
if (aFrame->IsPlaceholderFrame()) {
auto ph = static_cast<nsPlaceholderFrame*>(aFrame);
ph->ForgetLineIsEmptySoFar();
}
// Reflow the inline frame
nsReflowStatus frameReflowStatus;
bool pushedFrame;