зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1322843 part 2 - Conditionally keep some floats in InlinePrefISizeData::ForceBreak. r=dbaron
This patch makes ForceBreak() partially clear floats according to the break type of the coming block. MozReview-Commit-ID: 71Gl9lBoTJ5 --HG-- extra : rebase_source : 5ca01565f607241df0c63a7cd64c35ac7ff7648f
This commit is contained in:
Родитель
0f9ff65fce
Коммит
0fe4f86e06
|
@ -838,9 +838,14 @@ nsBlockFrame::GetPrefISize(nsRenderingContext *aRenderingContext)
|
||||||
AutoNoisyIndenter lineindent(gNoisyIntrinsic);
|
AutoNoisyIndenter lineindent(gNoisyIntrinsic);
|
||||||
#endif
|
#endif
|
||||||
if (line->IsBlock()) {
|
if (line->IsBlock()) {
|
||||||
|
StyleClear breakType;
|
||||||
if (!data.mLineIsEmpty || BlockCanIntersectFloats(line->mFirstChild)) {
|
if (!data.mLineIsEmpty || BlockCanIntersectFloats(line->mFirstChild)) {
|
||||||
data.ForceBreak();
|
breakType = StyleClear::Both;
|
||||||
|
} else {
|
||||||
|
breakType = line->mFirstChild->
|
||||||
|
StyleDisplay()->PhysicalBreakType(data.mLineContainerWM);
|
||||||
}
|
}
|
||||||
|
data.ForceBreak(breakType);
|
||||||
data.mCurrentLine = nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
|
data.mCurrentLine = nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
|
||||||
line->mFirstChild, nsLayoutUtils::PREF_ISIZE);
|
line->mFirstChild, nsLayoutUtils::PREF_ISIZE);
|
||||||
data.ForceBreak();
|
data.ForceBreak();
|
||||||
|
|
|
@ -4512,9 +4512,17 @@ nsIFrame::InlineMinISizeData::OptionallyBreak(nscoord aHyphenWidth)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsIFrame::InlinePrefISizeData::ForceBreak()
|
nsIFrame::InlinePrefISizeData::ForceBreak(StyleClear aBreakType)
|
||||||
{
|
{
|
||||||
if (mFloats.Length() != 0) {
|
MOZ_ASSERT(aBreakType == StyleClear::None ||
|
||||||
|
aBreakType == StyleClear::Both ||
|
||||||
|
aBreakType == StyleClear::Left ||
|
||||||
|
aBreakType == StyleClear::Right,
|
||||||
|
"Must be a physical break type");
|
||||||
|
|
||||||
|
// If this force break is not clearing any float, we can leave all the
|
||||||
|
// floats to the next force break.
|
||||||
|
if (mFloats.Length() != 0 && aBreakType != StyleClear::None) {
|
||||||
// preferred widths accumulated for floats that have already
|
// preferred widths accumulated for floats that have already
|
||||||
// been cleared past
|
// been cleared past
|
||||||
nscoord floats_done = 0,
|
nscoord floats_done = 0,
|
||||||
|
@ -4522,11 +4530,12 @@ nsIFrame::InlinePrefISizeData::ForceBreak()
|
||||||
// been cleared past
|
// been cleared past
|
||||||
floats_cur_left = 0,
|
floats_cur_left = 0,
|
||||||
floats_cur_right = 0;
|
floats_cur_right = 0;
|
||||||
|
const WritingMode wm = mLineContainerWM;
|
||||||
|
|
||||||
for (uint32_t i = 0, i_end = mFloats.Length(); i != i_end; ++i) {
|
for (uint32_t i = 0, i_end = mFloats.Length(); i != i_end; ++i) {
|
||||||
const FloatInfo& floatInfo = mFloats[i];
|
const FloatInfo& floatInfo = mFloats[i];
|
||||||
const nsStyleDisplay* floatDisp = floatInfo.Frame()->StyleDisplay();
|
const nsStyleDisplay* floatDisp = floatInfo.Frame()->StyleDisplay();
|
||||||
StyleClear breakType = floatDisp->PhysicalBreakType(mLineContainerWM);
|
StyleClear breakType = floatDisp->PhysicalBreakType(wm);
|
||||||
if (breakType == StyleClear::Left ||
|
if (breakType == StyleClear::Left ||
|
||||||
breakType == StyleClear::Right ||
|
breakType == StyleClear::Right ||
|
||||||
breakType == StyleClear::Both) {
|
breakType == StyleClear::Both) {
|
||||||
|
@ -4543,7 +4552,7 @@ nsIFrame::InlinePrefISizeData::ForceBreak()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StyleFloat floatStyle = floatDisp->PhysicalFloats(mLineContainerWM);
|
StyleFloat floatStyle = floatDisp->PhysicalFloats(wm);
|
||||||
nscoord& floats_cur =
|
nscoord& floats_cur =
|
||||||
floatStyle == StyleFloat::Left ? floats_cur_left : floats_cur_right;
|
floatStyle == StyleFloat::Left ? floats_cur_left : floats_cur_right;
|
||||||
nscoord floatWidth = floatInfo.Width();
|
nscoord floatWidth = floatInfo.Width();
|
||||||
|
@ -4560,7 +4569,44 @@ nsIFrame::InlinePrefISizeData::ForceBreak()
|
||||||
|
|
||||||
mCurrentLine = NSCoordSaturatingAdd(mCurrentLine, floats_done);
|
mCurrentLine = NSCoordSaturatingAdd(mCurrentLine, floats_done);
|
||||||
|
|
||||||
mFloats.Clear();
|
if (aBreakType == StyleClear::Both) {
|
||||||
|
mFloats.Clear();
|
||||||
|
} else {
|
||||||
|
// If the break type does not clear all floats, it means there may
|
||||||
|
// be some floats whose isize should contribute to the intrinsic
|
||||||
|
// isize of the next line. The code here scans the current mFloats
|
||||||
|
// and keeps floats which are not cleared by this break. Note that
|
||||||
|
// floats may be cleared directly or indirectly. See below.
|
||||||
|
nsTArray<FloatInfo> newFloats;
|
||||||
|
MOZ_ASSERT(aBreakType == StyleClear::Left ||
|
||||||
|
aBreakType == StyleClear::Right,
|
||||||
|
"Other values should have been handled in other branches");
|
||||||
|
StyleFloat clearFloatType =
|
||||||
|
aBreakType == StyleClear::Left ? StyleFloat::Left : StyleFloat::Right;
|
||||||
|
// Iterate the array in reverse so that we can stop when there are
|
||||||
|
// no longer any floats we need to keep. See below.
|
||||||
|
for (FloatInfo& floatInfo : Reversed(mFloats)) {
|
||||||
|
const nsStyleDisplay* floatDisp = floatInfo.Frame()->StyleDisplay();
|
||||||
|
if (floatDisp->PhysicalFloats(wm) != clearFloatType) {
|
||||||
|
newFloats.AppendElement(floatInfo);
|
||||||
|
} else {
|
||||||
|
// This is a float on the side that this break directly clears
|
||||||
|
// which means we're not keeping it in mFloats. However, if
|
||||||
|
// this float clears floats on the opposite side (via a value
|
||||||
|
// of either 'both' or one of 'left'/'right'), any remaining
|
||||||
|
// (earlier) floats on that side would be indirectly cleared
|
||||||
|
// as well. Thus, we should break out of this loop and stop
|
||||||
|
// considering earlier floats to be kept in mFloats.
|
||||||
|
StyleClear floatBreakType = floatDisp->PhysicalBreakType(wm);
|
||||||
|
if (floatBreakType != aBreakType &&
|
||||||
|
floatBreakType != StyleClear::None) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newFloats.Reverse();
|
||||||
|
mFloats = Move(newFloats);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mCurrentLine =
|
mCurrentLine =
|
||||||
|
|
|
@ -2020,11 +2020,29 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InlinePrefISizeData : public InlineIntrinsicISizeData {
|
struct InlinePrefISizeData : public InlineIntrinsicISizeData {
|
||||||
|
typedef mozilla::StyleClear StyleClear;
|
||||||
|
|
||||||
InlinePrefISizeData()
|
InlinePrefISizeData()
|
||||||
: mLineIsEmpty(true)
|
: mLineIsEmpty(true)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void ForceBreak();
|
/**
|
||||||
|
* Finish the current line and start a new line.
|
||||||
|
*
|
||||||
|
* @param aBreakType controls whether isize of floats are considered
|
||||||
|
* and what floats are kept for the next line:
|
||||||
|
* * |None| skips handling floats, which means no floats are
|
||||||
|
* removed, and isizes of floats are not considered either.
|
||||||
|
* * |Both| takes floats into consideration when computing isize
|
||||||
|
* of the current line, and removes all floats after that.
|
||||||
|
* * |Left| and |Right| do the same as |Both| except that they only
|
||||||
|
* remove floats on the given side, and any floats on the other
|
||||||
|
* side that are prior to a float on the given side that has a
|
||||||
|
* 'clear' property that clears them.
|
||||||
|
* All other values of StyleClear must be converted to the four
|
||||||
|
* physical values above for this function.
|
||||||
|
*/
|
||||||
|
void ForceBreak(StyleClear aBreakType = StyleClear::Both);
|
||||||
|
|
||||||
// The default implementation for nsIFrame::AddInlinePrefISize.
|
// The default implementation for nsIFrame::AddInlinePrefISize.
|
||||||
void DefaultAddInlinePrefISize(nscoord aISize);
|
void DefaultAddInlinePrefISize(nscoord aISize);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче