зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1062963 patch 3: make nsFloatManager's origin a LogicalPoint, adapt GetFlowAreas, AddFloats, ClearFloats, etc. to use it and make nsFloatManager region functions work with logical region. r=jfkthame
This commit is contained in:
Родитель
7ed4ceb17c
Коммит
3f0d7f2fcc
|
@ -1846,8 +1846,9 @@ nsBlockFrame::PropagateFloatDamage(nsBlockReflowState& aState,
|
|||
nsRect overflow = aLine->GetOverflowArea(eScrollableOverflow);
|
||||
nscoord lineYCombinedA = overflow.y + aDeltaY;
|
||||
nscoord lineYCombinedB = lineYCombinedA + overflow.height;
|
||||
if (floatManager->IntersectsDamage(lineYA, lineYB) ||
|
||||
floatManager->IntersectsDamage(lineYCombinedA, lineYCombinedB)) {
|
||||
WritingMode wm = aState.mReflowState.GetWritingMode();
|
||||
if (floatManager->IntersectsDamage(wm, lineYA, lineYB) ||
|
||||
floatManager->IntersectsDamage(wm, lineYCombinedA, lineYCombinedB)) {
|
||||
aLine->MarkDirty();
|
||||
return;
|
||||
}
|
||||
|
@ -3184,7 +3185,8 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
|||
LogicalSize(frame->GetWritingMode(), availSpace.Size()));
|
||||
blockHtmlRS.mFlags.mHasClearance = aLine->HasClearance();
|
||||
|
||||
nsFloatManager::SavedState floatManagerState;
|
||||
nsFloatManager::SavedState
|
||||
floatManagerState(aState.mReflowState.GetWritingMode());
|
||||
if (mayNeedRetry) {
|
||||
blockHtmlRS.mDiscoveredClearance = &clearanceFrame;
|
||||
aState.mFloatManager->PushState(&floatManagerState);
|
||||
|
@ -3449,7 +3451,8 @@ nsBlockFrame::ReflowInlineFrames(nsBlockReflowState& aState,
|
|||
int32_t forceBreakOffset = -1;
|
||||
gfxBreakPriority forceBreakPriority = gfxBreakPriority::eNoBreak;
|
||||
do {
|
||||
nsFloatManager::SavedState floatManagerState;
|
||||
nsFloatManager::SavedState
|
||||
floatManagerState(aState.mReflowState.GetWritingMode());
|
||||
aState.mReflowState.mFloatManager->PushState(&floatManagerState);
|
||||
|
||||
// Once upon a time we allocated the first 30 nsLineLayout objects
|
||||
|
@ -5984,14 +5987,15 @@ nsBlockFrame::ReflowPushedFloats(nsBlockReflowState& aState,
|
|||
}
|
||||
|
||||
void
|
||||
nsBlockFrame::RecoverFloats(nsFloatManager& aFloatManager)
|
||||
nsBlockFrame::RecoverFloats(nsFloatManager& aFloatManager, WritingMode aWM,
|
||||
nscoord aContainerWidth)
|
||||
{
|
||||
// Recover our own floats
|
||||
nsIFrame* stop = nullptr; // Stop before we reach pushed floats that
|
||||
// belong to our next-in-flow
|
||||
for (nsIFrame* f = mFloats.FirstChild(); f && f != stop; f = f->GetNextSibling()) {
|
||||
nsRect region = nsFloatManager::GetRegionFor(f);
|
||||
aFloatManager.AddFloat(f, region);
|
||||
LogicalRect region = nsFloatManager::GetRegionFor(aWM, f, aContainerWidth);
|
||||
aFloatManager.AddFloat(f, region, aWM, aContainerWidth);
|
||||
if (!stop && f->GetNextInFlow())
|
||||
stop = f->GetNextInFlow();
|
||||
}
|
||||
|
@ -5999,20 +6003,22 @@ nsBlockFrame::RecoverFloats(nsFloatManager& aFloatManager)
|
|||
// Recurse into our overflow container children
|
||||
for (nsIFrame* oc = GetFirstChild(kOverflowContainersList);
|
||||
oc; oc = oc->GetNextSibling()) {
|
||||
RecoverFloatsFor(oc, aFloatManager);
|
||||
RecoverFloatsFor(oc, aFloatManager, aWM, aContainerWidth);
|
||||
}
|
||||
|
||||
// Recurse into our normal children
|
||||
for (nsBlockFrame::line_iterator line = begin_lines(); line != end_lines(); ++line) {
|
||||
if (line->IsBlock()) {
|
||||
RecoverFloatsFor(line->mFirstChild, aFloatManager);
|
||||
RecoverFloatsFor(line->mFirstChild, aFloatManager, aWM, aContainerWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsBlockFrame::RecoverFloatsFor(nsIFrame* aFrame,
|
||||
nsFloatManager& aFloatManager)
|
||||
nsFloatManager& aFloatManager,
|
||||
WritingMode aWM,
|
||||
nscoord aContainerWidth)
|
||||
{
|
||||
NS_PRECONDITION(aFrame, "null frame");
|
||||
// Only blocks have floats
|
||||
|
@ -6024,10 +6030,10 @@ nsBlockFrame::RecoverFloatsFor(nsIFrame* aFrame,
|
|||
// If the element is relatively positioned, then adjust x and y
|
||||
// accordingly so that we consider relatively positioned frames
|
||||
// at their original position.
|
||||
nsPoint pos = block->GetNormalPosition();
|
||||
aFloatManager.Translate(pos.x, pos.y);
|
||||
block->RecoverFloats(aFloatManager);
|
||||
aFloatManager.Translate(-pos.x, -pos.y);
|
||||
LogicalPoint pos = block->GetLogicalNormalPosition(aWM, aContainerWidth);
|
||||
WritingMode oldWM = aFloatManager.Translate(aWM, pos, aContainerWidth);
|
||||
block->RecoverFloats(aFloatManager, aWM, aContainerWidth);
|
||||
aFloatManager.Untranslate(oldWM, pos, aContainerWidth);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -476,8 +476,10 @@ public:
|
|||
* assumes float manager is in aFrame's parent's coord system.
|
||||
* Safe to call on non-blocks (does nothing).
|
||||
*/
|
||||
static void RecoverFloatsFor(nsIFrame* aFrame,
|
||||
nsFloatManager& aFloatManager);
|
||||
static void RecoverFloatsFor(nsIFrame* aFrame,
|
||||
nsFloatManager& aFloatManager,
|
||||
mozilla::WritingMode aWM,
|
||||
nscoord aContainerWidth);
|
||||
|
||||
/**
|
||||
* Determine if we have any pushed floats from a previous continuation.
|
||||
|
@ -541,7 +543,9 @@ protected:
|
|||
/** Load all our floats into the float manager (without reflowing them).
|
||||
* Assumes float manager is in our own coordinate system.
|
||||
*/
|
||||
void RecoverFloats(nsFloatManager& aFloatManager);
|
||||
void RecoverFloats(nsFloatManager& aFloatManager,
|
||||
mozilla::WritingMode aWM,
|
||||
nscoord aContainerWidth);
|
||||
|
||||
/** Reflow pushed floats
|
||||
*/
|
||||
|
|
|
@ -250,7 +250,7 @@ nsBlockReflowContext::ReflowBlock(const nsRect& aSpace,
|
|||
}
|
||||
}
|
||||
|
||||
nscoord tI = 0, tB = 0;
|
||||
LogicalPoint tPt(mWritingMode);
|
||||
// The values of x and y do not matter for floats, so don't bother
|
||||
// calculating them. Floats are guaranteed to have their own float
|
||||
// manager, so tI and tB don't matter. mICoord and mBCoord don't
|
||||
|
@ -262,16 +262,12 @@ nsBlockReflowContext::ReflowBlock(const nsRect& aSpace,
|
|||
// reflow auto inline-start/end margins will have a zero value.
|
||||
|
||||
WritingMode frameWM = aFrameRS.GetWritingMode();
|
||||
mICoord = tI =
|
||||
mICoord = tPt.I(mWritingMode) =
|
||||
mSpace.IStart(mWritingMode) +
|
||||
aFrameRS.ComputedLogicalMargin().ConvertTo(mWritingMode,
|
||||
frameWM).IStart(mWritingMode);
|
||||
mBCoord = tB = mSpace.BStart(mWritingMode) +
|
||||
mBStartMargin.get() + aClearance;
|
||||
|
||||
//XXX temporary until nsFloatManager is logicalized
|
||||
tI = aSpace.x + aFrameRS.ComputedPhysicalMargin().left;
|
||||
tB = aSpace.y + mBStartMargin.get() + aClearance;
|
||||
mBCoord = tPt.B(mWritingMode) = mSpace.BStart(mWritingMode) +
|
||||
mBStartMargin.get() + aClearance;
|
||||
|
||||
if ((mFrame->GetStateBits() & NS_BLOCK_FLOAT_MGR) == 0)
|
||||
aFrameRS.mBlockDelta =
|
||||
|
@ -286,9 +282,11 @@ nsBlockReflowContext::ReflowBlock(const nsRect& aSpace,
|
|||
mMetrics.BSize(mWritingMode) = nscoord(0xdeadbeef);
|
||||
#endif
|
||||
|
||||
mOuterReflowState.mFloatManager->Translate(tI, tB);
|
||||
WritingMode oldWM =
|
||||
mOuterReflowState.mFloatManager->Translate(mWritingMode, tPt,
|
||||
mContainerWidth);
|
||||
mFrame->Reflow(mPresContext, mMetrics, aFrameRS, aFrameReflowStatus);
|
||||
mOuterReflowState.mFloatManager->Translate(-tI, -tB);
|
||||
mOuterReflowState.mFloatManager->Untranslate(oldWM, tPt, mContainerWidth);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!NS_INLINE_IS_BREAK_BEFORE(aFrameReflowStatus)) {
|
||||
|
|
|
@ -34,6 +34,8 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
|||
: mBlock(aFrame),
|
||||
mPresContext(aPresContext),
|
||||
mReflowState(aReflowState),
|
||||
mFloatManagerOrigin(aReflowState.GetWritingMode()),
|
||||
mFloatManagerStateBefore(aReflowState.GetWritingMode()),
|
||||
mContentArea(aReflowState.GetWritingMode()),
|
||||
mPushedFloats(nullptr),
|
||||
mOverflowTracker(nullptr),
|
||||
|
@ -74,7 +76,7 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
|||
"FloatManager should be set in nsBlockReflowState" );
|
||||
if (mFloatManager) {
|
||||
// Save the coordinate system origin for later.
|
||||
mFloatManager->GetTranslation(mFloatManagerX, mFloatManagerY);
|
||||
mFloatManager->GetTranslation(mFloatManagerWM, mFloatManagerOrigin);
|
||||
mFloatManager->PushState(&mFloatManagerStateBefore); // never popped
|
||||
}
|
||||
|
||||
|
@ -279,21 +281,27 @@ nsBlockReflowState::GetFloatAvailableSpaceWithState(
|
|||
nscoord aBCoord,
|
||||
nsFloatManager::SavedState *aState) const
|
||||
{
|
||||
WritingMode wm = mReflowState.GetWritingMode();
|
||||
#ifdef DEBUG
|
||||
// Verify that the caller setup the coordinate system properly
|
||||
nscoord wx, wy;
|
||||
mFloatManager->GetTranslation(wx, wy);
|
||||
NS_ASSERTION((wx == mFloatManagerX) && (wy == mFloatManagerY),
|
||||
"bad coord system");
|
||||
WritingMode wWM;
|
||||
LogicalPoint wPt(wWM);
|
||||
mFloatManager->GetTranslation(wWM, wPt);
|
||||
|
||||
if (wWM == mFloatManagerWM) {
|
||||
NS_ASSERTION(wPt == mFloatManagerOrigin, "bad coord system");
|
||||
} else {
|
||||
//XXX if the writing modes are different we can't easily assert that
|
||||
// the origin is the same.
|
||||
}
|
||||
#endif
|
||||
|
||||
nsRect contentArea =
|
||||
mContentArea.GetPhysicalRect(mReflowState.GetWritingMode(), mContainerWidth);
|
||||
nscoord height = (contentArea.height == nscoord_MAX)
|
||||
? nscoord_MAX : std::max(contentArea.YMost() - aBCoord, 0);
|
||||
nscoord blockSize = (mContentArea.BSize(wm) == nscoord_MAX)
|
||||
? nscoord_MAX : std::max(mContentArea.BEnd(wm) - aBCoord, 0);
|
||||
nsFlowAreaRect result =
|
||||
mFloatManager->GetFlowArea(aBCoord, nsFloatManager::BAND_FROM_POINT,
|
||||
height, contentArea, aState);
|
||||
mFloatManager->GetFlowArea(wm, aBCoord, nsFloatManager::BAND_FROM_POINT,
|
||||
blockSize, mContentArea, aState,
|
||||
mContainerWidth);
|
||||
// Keep the width >= 0 for compatibility with nsSpaceManager.
|
||||
if (result.mRect.width < 0)
|
||||
result.mRect.width = 0;
|
||||
|
@ -314,18 +322,22 @@ nsBlockReflowState::GetFloatAvailableSpaceForBSize(
|
|||
nscoord aBCoord, nscoord aBSize,
|
||||
nsFloatManager::SavedState *aState) const
|
||||
{
|
||||
WritingMode wm = mReflowState.GetWritingMode();
|
||||
#ifdef DEBUG
|
||||
// Verify that the caller setup the coordinate system properly
|
||||
nscoord wx, wy;
|
||||
mFloatManager->GetTranslation(wx, wy);
|
||||
NS_ASSERTION((wx == mFloatManagerX) && (wy == mFloatManagerY),
|
||||
"bad coord system");
|
||||
WritingMode wWM;
|
||||
LogicalPoint wPt(wWM);
|
||||
mFloatManager->GetTranslation(wWM, wPt);
|
||||
if (wWM == mFloatManagerWM) {
|
||||
NS_ASSERTION(wPt == mFloatManagerOrigin, "bad coord system");
|
||||
} else {
|
||||
//XXX if the writing modes are different we can't easily assert that
|
||||
// the origin is the same.
|
||||
}
|
||||
#endif
|
||||
nsRect contentArea =
|
||||
mContentArea.GetPhysicalRect(mReflowState.GetWritingMode(), mContainerWidth);
|
||||
nsFlowAreaRect result =
|
||||
mFloatManager->GetFlowArea(aBCoord, nsFloatManager::WIDTH_WITHIN_HEIGHT,
|
||||
aBSize, contentArea, aState);
|
||||
mFloatManager->GetFlowArea(wm, aBCoord, nsFloatManager::WIDTH_WITHIN_HEIGHT,
|
||||
aBSize, mContentArea, aState, mContainerWidth);
|
||||
// Keep the width >= 0 for compatibility with nsSpaceManager.
|
||||
if (result.mRect.width < 0)
|
||||
result.mRect.width = 0;
|
||||
|
@ -419,6 +431,7 @@ void
|
|||
nsBlockReflowState::RecoverFloats(nsLineList::iterator aLine,
|
||||
nscoord aDeltaBCoord)
|
||||
{
|
||||
WritingMode wm = mReflowState.GetWritingMode();
|
||||
if (aLine->HasFloats()) {
|
||||
// Place the floats into the space-manager again. Also slide
|
||||
// them, just like the regular frames on the line.
|
||||
|
@ -432,23 +445,31 @@ nsBlockReflowState::RecoverFloats(nsLineList::iterator aLine,
|
|||
}
|
||||
#ifdef DEBUG
|
||||
if (nsBlockFrame::gNoisyReflow || nsBlockFrame::gNoisyFloatManager) {
|
||||
nscoord tx, ty;
|
||||
mFloatManager->GetTranslation(tx, ty);
|
||||
WritingMode tWM;
|
||||
LogicalPoint tPt(tWM);
|
||||
mFloatManager->GetTranslation(tWM, tPt);
|
||||
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
|
||||
printf("RecoverFloats: txy=%d,%d (%d,%d) ",
|
||||
tx, ty, mFloatManagerX, mFloatManagerY);
|
||||
tPt.I(tWM), tPt.B(tWM),
|
||||
mFloatManagerOrigin.I(mFloatManagerWM),
|
||||
mFloatManagerOrigin.B(mFloatManagerWM));
|
||||
nsFrame::ListTag(stdout, floatFrame);
|
||||
nsRect region = nsFloatManager::GetRegionFor(floatFrame);
|
||||
LogicalRect region = nsFloatManager::GetRegionFor(wm, floatFrame,
|
||||
mContainerWidth);
|
||||
printf(" aDeltaBCoord=%d region={%d,%d,%d,%d}\n",
|
||||
aDeltaBCoord, region.x, region.y, region.width, region.height);
|
||||
aDeltaBCoord, region.IStart(wm), region.BStart(wm),
|
||||
region.ISize(wm), region.BSize(wm));
|
||||
}
|
||||
#endif
|
||||
mFloatManager->AddFloat(floatFrame,
|
||||
nsFloatManager::GetRegionFor(floatFrame));
|
||||
nsFloatManager::GetRegionFor(wm, floatFrame,
|
||||
mContainerWidth),
|
||||
wm, mContainerWidth);
|
||||
fc = fc->Next();
|
||||
}
|
||||
} else if (aLine->IsBlock()) {
|
||||
nsBlockFrame::RecoverFloatsFor(aLine->mFirstChild, *mFloatManager);
|
||||
nsBlockFrame::RecoverFloatsFor(aLine->mFirstChild, *mFloatManager, wm,
|
||||
mContainerWidth);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -535,11 +556,10 @@ nsBlockReflowState::AddFloat(nsLineLayout* aLineLayout,
|
|||
// that's a child of our block) we need to restore the space
|
||||
// manager's translation to the space that the block resides in
|
||||
// before placing the float.
|
||||
nscoord ox, oy;
|
||||
mFloatManager->GetTranslation(ox, oy);
|
||||
nscoord dx = ox - mFloatManagerX;
|
||||
nscoord dy = oy - mFloatManagerY;
|
||||
mFloatManager->Translate(-dx, -dy);
|
||||
WritingMode oldWM;
|
||||
LogicalPoint oPt(oldWM);
|
||||
mFloatManager->GetTranslation(oldWM, oPt);
|
||||
mFloatManager->SetTranslation(mFloatManagerWM, mFloatManagerOrigin);
|
||||
|
||||
bool placed;
|
||||
|
||||
|
@ -577,7 +597,7 @@ nsBlockReflowState::AddFloat(nsLineLayout* aLineLayout,
|
|||
}
|
||||
|
||||
// Restore coordinate system
|
||||
mFloatManager->Translate(dx, dy);
|
||||
mFloatManager->SetTranslation(oldWM, oPt);
|
||||
|
||||
return placed;
|
||||
}
|
||||
|
@ -619,6 +639,7 @@ FloatMarginWidth(const nsHTMLReflowState& aCBReflowState,
|
|||
bool
|
||||
nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
|
||||
{
|
||||
WritingMode wm = mReflowState.GetWritingMode();
|
||||
// Save away the Y coordinate before placing the float. We will
|
||||
// restore mBCoord at the end after placing the float. This is
|
||||
// necessary because any adjustments to mBCoord during the float
|
||||
|
@ -632,11 +653,17 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
|
|||
const nsStyleDisplay* floatDisplay = aFloat->StyleDisplay();
|
||||
|
||||
// The float's old region, so we can propagate damage.
|
||||
nsRect oldRegion = nsFloatManager::GetRegionFor(aFloat);
|
||||
LogicalRect oldRegion = nsFloatManager::GetRegionFor(wm, aFloat,
|
||||
mContainerWidth);
|
||||
|
||||
// Enforce CSS2 9.5.1 rule [2], i.e., make sure that a float isn't
|
||||
// ``above'' another float that preceded it in the flow.
|
||||
mBCoord = std::max(mFloatManager->GetLowestFloatTop(), mBCoord);
|
||||
// "Translate" the float manager with an offset of (0, 0) in order to
|
||||
// set the origin to our writing mode
|
||||
LogicalPoint oPt(wm);
|
||||
WritingMode oldWM = mFloatManager->Translate(wm, oPt, mContainerWidth);
|
||||
mBCoord = std::max(mFloatManager->GetLowestFloatTop(wm, mContainerWidth),
|
||||
mBCoord);
|
||||
|
||||
// See if the float should clear any preceding floats...
|
||||
// XXX We need to mark this float somehow so that it gets reflowed
|
||||
|
@ -864,17 +891,20 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
|
|||
|
||||
// Place the float in the float manager
|
||||
// calculate region
|
||||
nsRect region = nsFloatManager::CalculateRegionFor(aFloat, floatMargin);
|
||||
LogicalRect region =
|
||||
nsFloatManager::CalculateRegionFor(wm, aFloat,
|
||||
LogicalMargin(wm, floatMargin),
|
||||
mContainerWidth);
|
||||
// if the float split, then take up all of the vertical height
|
||||
if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus) &&
|
||||
(NS_UNCONSTRAINEDSIZE != ContentBSize())) {
|
||||
region.height = std::max(region.height, ContentBSize() - floatY);
|
||||
region.BSize(wm) = std::max(region.BSize(wm), ContentBSize() - floatY);
|
||||
}
|
||||
DebugOnly<nsresult> rv =
|
||||
mFloatManager->AddFloat(aFloat, region);
|
||||
DebugOnly<nsresult> rv = mFloatManager->AddFloat(aFloat, region, wm,
|
||||
mContainerWidth);
|
||||
NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "bad float placement");
|
||||
// store region
|
||||
nsFloatManager::StoreRegionFor(aFloat, region);
|
||||
nsFloatManager::StoreRegionFor(wm, aFloat, region, mContainerWidth);
|
||||
|
||||
// If the float's dimensions have changed, note the damage in the
|
||||
// float manager.
|
||||
|
@ -883,9 +913,9 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
|
|||
// less damage; e.g., if only height has changed, then only note the
|
||||
// area into which the float has grown or from which the float has
|
||||
// shrunk.
|
||||
nscoord top = std::min(region.y, oldRegion.y);
|
||||
nscoord bottom = std::max(region.YMost(), oldRegion.YMost());
|
||||
mFloatManager->IncludeInDamage(top, bottom);
|
||||
nscoord blockStart = std::min(region.BStart(wm), oldRegion.BStart(wm));
|
||||
nscoord blockEnd = std::max(region.BEnd(wm), oldRegion.BEnd(wm));
|
||||
mFloatManager->IncludeInDamage(wm, blockStart, blockEnd);
|
||||
}
|
||||
|
||||
if (!NS_FRAME_IS_FULLY_COMPLETE(reflowStatus)) {
|
||||
|
@ -893,12 +923,16 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
|
|||
}
|
||||
|
||||
#ifdef NOISY_FLOATMANAGER
|
||||
nscoord tx, ty;
|
||||
mFloatManager->GetTranslation(tx, ty);
|
||||
WritingMode tWM;
|
||||
LogicalPoint tPt(wm);
|
||||
mFloatManager->GetTranslation(tWM, tPt);
|
||||
nsFrame::ListTag(stdout, mBlock);
|
||||
printf(": FlowAndPlaceFloat: AddFloat: txy=%d,%d (%d,%d) {%d,%d,%d,%d}\n",
|
||||
tx, ty, mFloatManagerX, mFloatManagerY,
|
||||
region.x, region.y, region.width, region.height);
|
||||
tPt.I(tWM), tPt.B(tWM),
|
||||
mFloatManagerOrigin.I(mFloatManagerWM),
|
||||
mFloatManagerOrigin.B(mFloatManagerWM),
|
||||
region.IStart(wm), region.BStart(wm),
|
||||
region.ISize(wm), region.BSize(wm));
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -911,6 +945,8 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
|
|||
}
|
||||
#endif
|
||||
|
||||
mFloatManager->Untranslate(oldWM, oPt, mContainerWidth);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -995,7 +1031,8 @@ nsBlockReflowState::ClearFloats(nscoord aBCoord, uint8_t aBreakType,
|
|||
WritingMode wm = mReflowState.GetWritingMode();
|
||||
|
||||
if (aBreakType != NS_STYLE_CLEAR_NONE) {
|
||||
newBCoord = mFloatManager->ClearFloats(newBCoord, aBreakType, aFlags);
|
||||
newBCoord = mFloatManager->ClearFloats(wm, newBCoord, aBreakType,
|
||||
mContainerWidth, aFlags);
|
||||
}
|
||||
|
||||
if (aReplacedBlock) {
|
||||
|
|
|
@ -157,7 +157,8 @@ public:
|
|||
// padding. This, therefore, represents the inner "content area" (in
|
||||
// spacemanager coordinates) where child frames will be placed,
|
||||
// including child blocks and floats.
|
||||
nscoord mFloatManagerX, mFloatManagerY;
|
||||
mozilla::WritingMode mFloatManagerWM;
|
||||
mozilla::LogicalPoint mFloatManagerOrigin;
|
||||
|
||||
// XXX get rid of this
|
||||
nsReflowStatus mReflowStatus;
|
||||
|
|
|
@ -1173,8 +1173,11 @@ nsContainerFrame::ReflowOverflowContainerChildren(nsPresContext* aPres
|
|||
}
|
||||
else {
|
||||
tracker.Skip(frame, aStatus);
|
||||
if (aReflowState.mFloatManager)
|
||||
nsBlockFrame::RecoverFloatsFor(frame, *aReflowState.mFloatManager);
|
||||
if (aReflowState.mFloatManager) {
|
||||
nsBlockFrame::RecoverFloatsFor(frame, *aReflowState.mFloatManager,
|
||||
aReflowState.GetWritingMode(),
|
||||
aReflowState.ComputedWidth());
|
||||
}
|
||||
}
|
||||
ConsiderChildOverflow(aOverflowRects, frame);
|
||||
}
|
||||
|
|
|
@ -37,8 +37,10 @@ PSArenaFreeCB(size_t aSize, void* aPtr, void* aClosure)
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// nsFloatManager
|
||||
|
||||
nsFloatManager::nsFloatManager(nsIPresShell* aPresShell)
|
||||
: mX(0), mY(0),
|
||||
nsFloatManager::nsFloatManager(nsIPresShell* aPresShell,
|
||||
mozilla::WritingMode aWM)
|
||||
: mWritingMode(aWM),
|
||||
mOrigin(aWM),
|
||||
mFloatDamage(PSArenaAllocCB, PSArenaFreeCB, aPresShell),
|
||||
mPushedLeftFloatPastBreak(false),
|
||||
mPushedRightFloatPastBreak(false),
|
||||
|
@ -110,17 +112,20 @@ void nsFloatManager::Shutdown()
|
|||
}
|
||||
|
||||
nsFlowAreaRect
|
||||
nsFloatManager::GetFlowArea(nscoord aYOffset, BandInfoType aInfoType,
|
||||
nscoord aHeight, nsRect aContentArea,
|
||||
SavedState* aState) const
|
||||
nsFloatManager::GetFlowArea(WritingMode aWM, nscoord aBOffset,
|
||||
BandInfoType aInfoType, nscoord aBSize,
|
||||
LogicalRect aContentArea, SavedState* aState,
|
||||
nscoord aContainerWidth) const
|
||||
{
|
||||
NS_ASSERTION(aHeight >= 0, "unexpected max height");
|
||||
NS_ASSERTION(aContentArea.width >= 0, "unexpected content area width");
|
||||
NS_ASSERTION(aBSize >= 0, "unexpected max block size");
|
||||
NS_ASSERTION(aContentArea.ISize(aWM) >= 0,
|
||||
"unexpected content area inline size");
|
||||
|
||||
nscoord top = aYOffset + mY;
|
||||
if (top < nscoord_MIN) {
|
||||
LogicalPoint origin = mOrigin.ConvertTo(aWM, mWritingMode, aContainerWidth);
|
||||
nscoord blockStart = aBOffset + origin.B(aWM);
|
||||
if (blockStart < nscoord_MIN) {
|
||||
NS_WARNING("bad value");
|
||||
top = nscoord_MIN;
|
||||
blockStart = nscoord_MIN;
|
||||
}
|
||||
|
||||
// Determine the last float that we should consider.
|
||||
|
@ -137,39 +142,42 @@ nsFloatManager::GetFlowArea(nscoord aYOffset, BandInfoType aInfoType,
|
|||
// If there are no floats at all, or we're below the last one, return
|
||||
// quickly.
|
||||
if (floatCount == 0 ||
|
||||
(mFloats[floatCount-1].mLeftYMost <= top &&
|
||||
mFloats[floatCount-1].mRightYMost <= top)) {
|
||||
return nsFlowAreaRect(aContentArea.x, aYOffset, aContentArea.width,
|
||||
aHeight, false);
|
||||
(mFloats[floatCount-1].mLeftBEnd <= blockStart &&
|
||||
mFloats[floatCount-1].mRightBEnd <= blockStart)) {
|
||||
//XXX temporary!
|
||||
LogicalRect rect(aWM, aContentArea.IStart(aWM), aBOffset,
|
||||
aContentArea.ISize(aWM), aBSize);
|
||||
nsRect phys = rect.GetPhysicalRect(aWM, aContainerWidth);
|
||||
return nsFlowAreaRect(phys.x, phys.y, phys.width, phys.height, false);
|
||||
}
|
||||
|
||||
nscoord bottom;
|
||||
if (aHeight == nscoord_MAX) {
|
||||
nscoord blockEnd;
|
||||
if (aBSize == nscoord_MAX) {
|
||||
// This warning (and the two below) are possible to hit on pages
|
||||
// with really large objects.
|
||||
NS_WARN_IF_FALSE(aInfoType == BAND_FROM_POINT,
|
||||
"bad height");
|
||||
bottom = nscoord_MAX;
|
||||
blockEnd = nscoord_MAX;
|
||||
} else {
|
||||
bottom = top + aHeight;
|
||||
if (bottom < top || bottom > nscoord_MAX) {
|
||||
blockEnd = blockStart + aBSize;
|
||||
if (blockEnd < blockStart || blockEnd > nscoord_MAX) {
|
||||
NS_WARNING("bad value");
|
||||
bottom = nscoord_MAX;
|
||||
blockEnd = nscoord_MAX;
|
||||
}
|
||||
}
|
||||
nscoord left = mX + aContentArea.x;
|
||||
nscoord right = mX + aContentArea.XMost();
|
||||
if (right < left) {
|
||||
nscoord inlineStart = origin.I(aWM) + aContentArea.IStart(aWM);
|
||||
nscoord inlineEnd = origin.I(aWM) + aContentArea.IEnd(aWM);
|
||||
if (inlineEnd < inlineStart) {
|
||||
NS_WARNING("bad value");
|
||||
right = left;
|
||||
inlineEnd = inlineStart;
|
||||
}
|
||||
|
||||
// Walk backwards through the floats until we either hit the front of
|
||||
// the list or we're above |top|.
|
||||
// the list or we're above |blockStart|.
|
||||
bool haveFloats = false;
|
||||
for (uint32_t i = floatCount; i > 0; --i) {
|
||||
const FloatInfo &fi = mFloats[i-1];
|
||||
if (fi.mLeftYMost <= top && fi.mRightYMost <= top) {
|
||||
if (fi.mLeftBEnd <= blockStart && fi.mRightBEnd <= blockStart) {
|
||||
// There aren't any more floats that could intersect this band.
|
||||
break;
|
||||
}
|
||||
|
@ -179,33 +187,39 @@ nsFloatManager::GetFlowArea(nscoord aYOffset, BandInfoType aInfoType,
|
|||
// future, though.)
|
||||
continue;
|
||||
}
|
||||
nscoord floatTop = fi.mRect.y, floatBottom = fi.mRect.YMost();
|
||||
if (top < floatTop && aInfoType == BAND_FROM_POINT) {
|
||||
|
||||
LogicalRect rect = fi.mRect.ConvertTo(aWM, fi.mWritingMode,
|
||||
aContainerWidth);
|
||||
nscoord floatBStart = rect.BStart(aWM);
|
||||
nscoord floatBEnd = rect.BEnd(aWM);
|
||||
if (blockStart < floatBStart && aInfoType == BAND_FROM_POINT) {
|
||||
// This float is below our band. Shrink our band's height if needed.
|
||||
if (floatTop < bottom) {
|
||||
bottom = floatTop;
|
||||
if (floatBStart < blockEnd) {
|
||||
blockEnd = floatBStart;
|
||||
}
|
||||
}
|
||||
// If top == bottom (which happens only with WIDTH_WITHIN_HEIGHT),
|
||||
// If blockStart == blockEnd (which happens only with WIDTH_WITHIN_HEIGHT),
|
||||
// we include floats that begin at our 0-height vertical area. We
|
||||
// need to to this to satisfy the invariant that a
|
||||
// WIDTH_WITHIN_HEIGHT call is at least as narrow on both sides as a
|
||||
// BAND_WITHIN_POINT call beginning at its top.
|
||||
else if (top < floatBottom &&
|
||||
(floatTop < bottom || (floatTop == bottom && top == bottom))) {
|
||||
// BAND_WITHIN_POINT call beginning at its blockStart.
|
||||
else if (blockStart < floatBEnd &&
|
||||
(floatBStart < blockEnd ||
|
||||
(floatBStart == blockEnd && blockStart == blockEnd))) {
|
||||
// This float is in our band.
|
||||
|
||||
// Shrink our band's height if needed.
|
||||
if (floatBottom < bottom && aInfoType == BAND_FROM_POINT) {
|
||||
bottom = floatBottom;
|
||||
if (floatBEnd < blockEnd && aInfoType == BAND_FROM_POINT) {
|
||||
blockEnd = floatBEnd;
|
||||
}
|
||||
|
||||
// Shrink our band's width if needed.
|
||||
if (fi.mFrame->StyleDisplay()->mFloats == NS_STYLE_FLOAT_LEFT) {
|
||||
// A left float.
|
||||
nscoord rightEdge = fi.mRect.XMost();
|
||||
if (rightEdge > left) {
|
||||
left = rightEdge;
|
||||
if ((fi.mFrame->StyleDisplay()->mFloats == NS_STYLE_FLOAT_LEFT) ==
|
||||
aWM.IsBidiLTR()) {
|
||||
// A left float in an ltr block or a right float in an rtl block
|
||||
nscoord inlineEndEdge = rect.IEnd(aWM);
|
||||
if (inlineEndEdge > inlineStart) {
|
||||
inlineStart = inlineEndEdge;
|
||||
// Only set haveFloats to true if the float is inside our
|
||||
// containing block. This matches the spec for what some
|
||||
// callers want and disagrees for other callers, so we should
|
||||
|
@ -213,10 +227,10 @@ nsFloatManager::GetFlowArea(nscoord aYOffset, BandInfoType aInfoType,
|
|||
haveFloats = true;
|
||||
}
|
||||
} else {
|
||||
// A right float.
|
||||
nscoord leftEdge = fi.mRect.x;
|
||||
if (leftEdge < right) {
|
||||
right = leftEdge;
|
||||
// A left float in an rtl block or a right float in an ltr block
|
||||
nscoord inlineStartEdge = rect.IStart(aWM);
|
||||
if (inlineStartEdge < inlineEnd) {
|
||||
inlineEnd = inlineStartEdge;
|
||||
// See above.
|
||||
haveFloats = true;
|
||||
}
|
||||
|
@ -224,35 +238,43 @@ nsFloatManager::GetFlowArea(nscoord aYOffset, BandInfoType aInfoType,
|
|||
}
|
||||
}
|
||||
|
||||
nscoord height = (bottom == nscoord_MAX) ? nscoord_MAX : (bottom - top);
|
||||
return nsFlowAreaRect(left - mX, top - mY, right - left, height, haveFloats);
|
||||
nscoord height = (blockEnd == nscoord_MAX) ?
|
||||
nscoord_MAX : (blockEnd - blockStart);
|
||||
//XXX temporary!
|
||||
LogicalRect rect(aWM,
|
||||
inlineStart - origin.I(aWM), blockStart - origin.B(aWM),
|
||||
inlineEnd - inlineStart, height);
|
||||
nsRect phys = rect.GetPhysicalRect(aWM, aContainerWidth);
|
||||
return nsFlowAreaRect(phys.x, phys.y, phys.width, phys.height, haveFloats);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFloatManager::AddFloat(nsIFrame* aFloatFrame, const nsRect& aMarginRect)
|
||||
nsFloatManager::AddFloat(nsIFrame* aFloatFrame, const LogicalRect& aMarginRect,
|
||||
WritingMode aWM, nscoord aContainerWidth)
|
||||
{
|
||||
NS_ASSERTION(aMarginRect.width >= 0, "negative width!");
|
||||
NS_ASSERTION(aMarginRect.height >= 0, "negative height!");
|
||||
NS_ASSERTION(aMarginRect.ISize(aWM) >= 0, "negative inline size!");
|
||||
NS_ASSERTION(aMarginRect.BSize(aWM) >= 0, "negative block size!");
|
||||
|
||||
FloatInfo info(aFloatFrame, aMarginRect + nsPoint(mX, mY));
|
||||
FloatInfo info(aFloatFrame, aWM, aMarginRect + mOrigin);
|
||||
|
||||
// Set mLeftYMost and mRightYMost.
|
||||
// Set mLeftBEnd and mRightBEnd.
|
||||
if (HasAnyFloats()) {
|
||||
FloatInfo &tail = mFloats[mFloats.Length() - 1];
|
||||
info.mLeftYMost = tail.mLeftYMost;
|
||||
info.mRightYMost = tail.mRightYMost;
|
||||
info.mLeftBEnd = tail.mLeftBEnd;
|
||||
info.mRightBEnd = tail.mRightBEnd;
|
||||
} else {
|
||||
info.mLeftYMost = nscoord_MIN;
|
||||
info.mRightYMost = nscoord_MIN;
|
||||
info.mLeftBEnd = nscoord_MIN;
|
||||
info.mRightBEnd = nscoord_MIN;
|
||||
}
|
||||
uint8_t floatStyle = aFloatFrame->StyleDisplay()->mFloats;
|
||||
NS_ASSERTION(floatStyle == NS_STYLE_FLOAT_LEFT ||
|
||||
floatStyle == NS_STYLE_FLOAT_RIGHT, "unexpected float");
|
||||
nscoord& sideYMost = (floatStyle == NS_STYLE_FLOAT_LEFT) ? info.mLeftYMost
|
||||
: info.mRightYMost;
|
||||
nscoord thisYMost = info.mRect.YMost();
|
||||
if (thisYMost > sideYMost)
|
||||
sideYMost = thisYMost;
|
||||
nscoord& sideBEnd =
|
||||
((floatStyle == NS_STYLE_FLOAT_LEFT) == aWM.IsBidiLTR()) ? info.mLeftBEnd
|
||||
: info.mRightBEnd;
|
||||
nscoord thisBEnd = info.mRect.BEnd(aWM);
|
||||
if (thisBEnd > sideBEnd)
|
||||
sideBEnd = thisBEnd;
|
||||
|
||||
if (!mFloats.AppendElement(info))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
@ -260,54 +282,61 @@ nsFloatManager::AddFloat(nsIFrame* aFloatFrame, const nsRect& aMarginRect)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRect
|
||||
nsFloatManager::CalculateRegionFor(nsIFrame* aFloat,
|
||||
const nsMargin& aMargin)
|
||||
LogicalRect
|
||||
nsFloatManager::CalculateRegionFor(WritingMode aWM,
|
||||
nsIFrame* aFloat,
|
||||
const LogicalMargin& aMargin,
|
||||
nscoord aContainerWidth)
|
||||
{
|
||||
// We consider relatively positioned frames at their original position.
|
||||
nsRect region(aFloat->GetNormalPosition(), aFloat->GetSize());
|
||||
LogicalRect region(aWM, nsRect(aFloat->GetNormalPosition(),
|
||||
aFloat->GetSize()),
|
||||
aContainerWidth);
|
||||
|
||||
// Float region includes its margin
|
||||
region.Inflate(aMargin);
|
||||
region.Inflate(aWM, aMargin);
|
||||
|
||||
// Don't store rectangles with negative margin-box width or height in
|
||||
// the float manager; it can't deal with them.
|
||||
if (region.width < 0) {
|
||||
if (region.ISize(aWM) < 0) {
|
||||
// Preserve the right margin-edge for left floats and the left
|
||||
// margin-edge for right floats
|
||||
const nsStyleDisplay* display = aFloat->StyleDisplay();
|
||||
if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
|
||||
region.x = region.XMost();
|
||||
if ((NS_STYLE_FLOAT_LEFT == display->mFloats) == aWM.IsBidiLTR()) {
|
||||
region.IStart(aWM) = region.IEnd(aWM);
|
||||
}
|
||||
region.width = 0;
|
||||
region.ISize(aWM) = 0;
|
||||
}
|
||||
if (region.height < 0) {
|
||||
region.height = 0;
|
||||
if (region.BSize(aWM) < 0) {
|
||||
region.BSize(aWM) = 0;
|
||||
}
|
||||
return region;
|
||||
}
|
||||
|
||||
NS_DECLARE_FRAME_PROPERTY(FloatRegionProperty, nsIFrame::DestroyMargin)
|
||||
|
||||
nsRect
|
||||
nsFloatManager::GetRegionFor(nsIFrame* aFloat)
|
||||
LogicalRect
|
||||
nsFloatManager::GetRegionFor(WritingMode aWM, nsIFrame* aFloat,
|
||||
nscoord aContainerWidth)
|
||||
{
|
||||
nsRect region = aFloat->GetRect();
|
||||
LogicalRect region = aFloat->GetLogicalRect(aWM, aContainerWidth);
|
||||
void* storedRegion = aFloat->Properties().Get(FloatRegionProperty());
|
||||
if (storedRegion) {
|
||||
nsMargin margin = *static_cast<nsMargin*>(storedRegion);
|
||||
region.Inflate(margin);
|
||||
region.Inflate(aWM, LogicalMargin(aWM, margin));
|
||||
}
|
||||
return region;
|
||||
}
|
||||
|
||||
void
|
||||
nsFloatManager::StoreRegionFor(nsIFrame* aFloat,
|
||||
nsRect& aRegion)
|
||||
nsFloatManager::StoreRegionFor(WritingMode aWM, nsIFrame* aFloat,
|
||||
const LogicalRect& aRegion,
|
||||
nscoord aContainerWidth)
|
||||
{
|
||||
nsRect region = aRegion.GetPhysicalRect(aWM, aContainerWidth);
|
||||
nsRect rect = aFloat->GetRect();
|
||||
FrameProperties props = aFloat->Properties();
|
||||
if (aRegion.IsEqualEdges(rect)) {
|
||||
if (region.IsEqualEdges(rect)) {
|
||||
props.Delete(FloatRegionProperty());
|
||||
}
|
||||
else {
|
||||
|
@ -317,7 +346,7 @@ nsFloatManager::StoreRegionFor(nsIFrame* aFloat,
|
|||
storedMargin = new nsMargin();
|
||||
props.Set(FloatRegionProperty(), storedMargin);
|
||||
}
|
||||
*storedMargin = aRegion - rect;
|
||||
*storedMargin = region - rect;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -378,8 +407,8 @@ nsFloatManager::PushState(SavedState* aState)
|
|||
// reflow. In the typical case A and C will be the same, but not always.
|
||||
// Allowing mFloatDamage to accumulate the damage incurred during both
|
||||
// reflows ensures that nothing gets missed.
|
||||
aState->mX = mX;
|
||||
aState->mY = mY;
|
||||
aState->mWritingMode = mWritingMode;
|
||||
aState->mOrigin = mOrigin;
|
||||
aState->mPushedLeftFloatPastBreak = mPushedLeftFloatPastBreak;
|
||||
aState->mPushedRightFloatPastBreak = mPushedRightFloatPastBreak;
|
||||
aState->mSplitLeftFloatAcrossBreak = mSplitLeftFloatAcrossBreak;
|
||||
|
@ -392,8 +421,8 @@ nsFloatManager::PopState(SavedState* aState)
|
|||
{
|
||||
NS_PRECONDITION(aState, "No state to restore?");
|
||||
|
||||
mX = aState->mX;
|
||||
mY = aState->mY;
|
||||
mWritingMode = aState->mWritingMode;
|
||||
mOrigin = aState->mOrigin;
|
||||
mPushedLeftFloatPastBreak = aState->mPushedLeftFloatPastBreak;
|
||||
mPushedRightFloatPastBreak = aState->mPushedRightFloatPastBreak;
|
||||
mSplitLeftFloatAcrossBreak = aState->mSplitLeftFloatAcrossBreak;
|
||||
|
@ -405,7 +434,8 @@ nsFloatManager::PopState(SavedState* aState)
|
|||
}
|
||||
|
||||
nscoord
|
||||
nsFloatManager::GetLowestFloatTop() const
|
||||
nsFloatManager::GetLowestFloatTop(WritingMode aWM,
|
||||
nscoord aContainerWidth) const
|
||||
{
|
||||
if (mPushedLeftFloatPastBreak || mPushedRightFloatPastBreak) {
|
||||
return nscoord_MAX;
|
||||
|
@ -413,7 +443,11 @@ nsFloatManager::GetLowestFloatTop() const
|
|||
if (!HasAnyFloats()) {
|
||||
return nscoord_MIN;
|
||||
}
|
||||
return mFloats[mFloats.Length() - 1].mRect.y - mY;
|
||||
FloatInfo fi = mFloats[mFloats.Length() - 1];
|
||||
LogicalRect rect = fi.mRect.ConvertTo(aWM, fi.mWritingMode, aContainerWidth);
|
||||
LogicalPoint origin = mOrigin.ConvertTo(aWM, mWritingMode, aContainerWidth);
|
||||
|
||||
return rect.BStart(aWM) - origin.B(aWM);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FRAME_DUMP
|
||||
|
@ -433,46 +467,53 @@ nsFloatManager::List(FILE* out) const
|
|||
const FloatInfo &fi = mFloats[i];
|
||||
fprintf_stderr(out, "Float %u: frame=%p rect={%d,%d,%d,%d} ymost={l:%d, r:%d}\n",
|
||||
i, static_cast<void*>(fi.mFrame),
|
||||
fi.mRect.x, fi.mRect.y, fi.mRect.width, fi.mRect.height,
|
||||
fi.mLeftYMost, fi.mRightYMost);
|
||||
fi.mRect.IStart(fi.mWritingMode),
|
||||
fi.mRect.BStart(fi.mWritingMode),
|
||||
fi.mRect.ISize(fi.mWritingMode),
|
||||
fi.mRect.BSize(fi.mWritingMode),
|
||||
fi.mLeftBEnd, fi.mRightBEnd);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
nscoord
|
||||
nsFloatManager::ClearFloats(nscoord aY, uint8_t aBreakType,
|
||||
nsFloatManager::ClearFloats(WritingMode aWM, nscoord aBCoord,
|
||||
uint8_t aBreakType, nscoord aContainerWidth,
|
||||
uint32_t aFlags) const
|
||||
{
|
||||
if (!(aFlags & DONT_CLEAR_PUSHED_FLOATS) && ClearContinues(aBreakType)) {
|
||||
return nscoord_MAX;
|
||||
}
|
||||
if (!HasAnyFloats()) {
|
||||
return aY;
|
||||
return aBCoord;
|
||||
}
|
||||
|
||||
nscoord bottom = aY + mY;
|
||||
LogicalPoint origin = mOrigin.ConvertTo(aWM, mWritingMode, aContainerWidth);
|
||||
nscoord blockEnd = aBCoord + origin.B(aWM);
|
||||
|
||||
const FloatInfo &tail = mFloats[mFloats.Length() - 1];
|
||||
switch (aBreakType) {
|
||||
case NS_STYLE_CLEAR_BOTH:
|
||||
bottom = std::max(bottom, tail.mLeftYMost);
|
||||
bottom = std::max(bottom, tail.mRightYMost);
|
||||
blockEnd = std::max(blockEnd, tail.mLeftBEnd);
|
||||
blockEnd = std::max(blockEnd, tail.mRightBEnd);
|
||||
break;
|
||||
case NS_STYLE_CLEAR_LEFT:
|
||||
bottom = std::max(bottom, tail.mLeftYMost);
|
||||
blockEnd = std::max(blockEnd, aWM.IsBidiLTR() ? tail.mLeftBEnd
|
||||
: tail.mRightBEnd);
|
||||
break;
|
||||
case NS_STYLE_CLEAR_RIGHT:
|
||||
bottom = std::max(bottom, tail.mRightYMost);
|
||||
blockEnd = std::max(blockEnd, aWM.IsBidiLTR() ? tail.mRightBEnd
|
||||
: tail.mLeftBEnd);
|
||||
break;
|
||||
default:
|
||||
// Do nothing
|
||||
break;
|
||||
}
|
||||
|
||||
bottom -= mY;
|
||||
blockEnd -= origin.B(aWM);
|
||||
|
||||
return bottom;
|
||||
return blockEnd;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -489,8 +530,9 @@ nsFloatManager::ClearContinues(uint8_t aBreakType) const
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// FloatInfo
|
||||
|
||||
nsFloatManager::FloatInfo::FloatInfo(nsIFrame* aFrame, const nsRect& aRect)
|
||||
: mFrame(aFrame), mRect(aRect)
|
||||
nsFloatManager::FloatInfo::FloatInfo(nsIFrame* aFrame, WritingMode aWM,
|
||||
const LogicalRect& aRect)
|
||||
: mFrame(aFrame), mRect(aRect), mWritingMode(aWM)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsFloatManager::FloatInfo);
|
||||
}
|
||||
|
@ -499,8 +541,9 @@ nsFloatManager::FloatInfo::FloatInfo(nsIFrame* aFrame, const nsRect& aRect)
|
|||
nsFloatManager::FloatInfo::FloatInfo(const FloatInfo& aOther)
|
||||
: mFrame(aOther.mFrame),
|
||||
mRect(aOther.mRect),
|
||||
mLeftYMost(aOther.mLeftYMost),
|
||||
mRightYMost(aOther.mRightYMost)
|
||||
mWritingMode(aOther.mWritingMode),
|
||||
mLeftBEnd(aOther.mLeftBEnd),
|
||||
mRightBEnd(aOther.mRightBEnd)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsFloatManager::FloatInfo);
|
||||
}
|
||||
|
@ -541,7 +584,8 @@ nsAutoFloatManager::CreateFloatManager(nsPresContext *aPresContext)
|
|||
// Create a new float manager and install it in the reflow
|
||||
// state. `Remember' the old float manager so we can restore it
|
||||
// later.
|
||||
mNew = new nsFloatManager(aPresContext->PresShell());
|
||||
mNew = new nsFloatManager(aPresContext->PresShell(),
|
||||
mReflowState.GetWritingMode());
|
||||
if (! mNew)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include "nsIntervalSet.h"
|
||||
#include "nsCoord.h"
|
||||
#include "nsRect.h"
|
||||
#include "WritingModes.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsFrameList.h" // for DEBUG_FRAME_DUMP
|
||||
|
||||
|
@ -24,25 +24,26 @@ class nsPresContext;
|
|||
|
||||
/**
|
||||
* The available space for content not occupied by floats is divided
|
||||
* into a (vertical) sequence of rectangles. However, we need to know
|
||||
* not only the rectangle, but also whether it was reduced (from the
|
||||
* content rectangle) by floats that actually intruded into the content
|
||||
* rectangle.
|
||||
* into a sequence of rectangles in the block direction. However, we
|
||||
* need to know not only the rectangle, but also whether it was reduced
|
||||
* (from the content rectangle) by floats that actually intruded into
|
||||
* the content rectangle.
|
||||
*/
|
||||
struct nsFlowAreaRect {
|
||||
nsRect mRect;
|
||||
bool mHasFloats;
|
||||
|
||||
nsFlowAreaRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight,
|
||||
nsFlowAreaRect(nscoord aICoord, nscoord aBCoord,
|
||||
nscoord aISize, nscoord aBSize,
|
||||
bool aHasFloats)
|
||||
: mRect(aX, aY, aWidth, aHeight), mHasFloats(aHasFloats) {}
|
||||
: mRect(aICoord, aBCoord, aISize, aBSize), mHasFloats(aHasFloats) {}
|
||||
};
|
||||
|
||||
#define NS_FLOAT_MANAGER_CACHE_SIZE 4
|
||||
|
||||
class nsFloatManager {
|
||||
public:
|
||||
explicit nsFloatManager(nsIPresShell* aPresShell);
|
||||
explicit nsFloatManager(nsIPresShell* aPresShell, mozilla::WritingMode aWM);
|
||||
~nsFloatManager();
|
||||
|
||||
void* operator new(size_t aSize) CPP_THROW_NEW;
|
||||
|
@ -55,7 +56,9 @@ public:
|
|||
* not there.) The float region is the area impacted by this float;
|
||||
* the coordinates are relative to the containing block frame.
|
||||
*/
|
||||
static nsRect GetRegionFor(nsIFrame* aFloatFrame);
|
||||
static mozilla::LogicalRect GetRegionFor(mozilla::WritingMode aWM,
|
||||
nsIFrame* aFloatFrame,
|
||||
nscoord aContainerWidth);
|
||||
/**
|
||||
* Calculate the float region for this frame using aMargin and the
|
||||
* frame's mRect. The region includes the margins around the float,
|
||||
|
@ -63,23 +66,32 @@ public:
|
|||
* Note that if the frame is or has a continuation, aMargin's top
|
||||
* and/or bottom must be zeroed by the caller.
|
||||
*/
|
||||
static nsRect CalculateRegionFor(nsIFrame* aFloatFrame,
|
||||
const nsMargin& aMargin);
|
||||
static mozilla::LogicalRect CalculateRegionFor(
|
||||
mozilla::WritingMode aWM,
|
||||
nsIFrame* aFloatFrame,
|
||||
const mozilla::LogicalMargin& aMargin,
|
||||
nscoord aContainerWidth);
|
||||
/**
|
||||
* Store the float region on the frame. The region is stored
|
||||
* as a delta against the mRect, so repositioning the frame will
|
||||
* also reposition the float region.
|
||||
*/
|
||||
static void StoreRegionFor(nsIFrame* aFloat, nsRect& aRegion);
|
||||
static void StoreRegionFor(mozilla::WritingMode aWM,
|
||||
nsIFrame* aFloat,
|
||||
const mozilla::LogicalRect& aRegion,
|
||||
nscoord aContainerWidth);
|
||||
|
||||
// Structure that stores the current state of a frame manager for
|
||||
// Save/Restore purposes.
|
||||
struct SavedState;
|
||||
friend struct SavedState;
|
||||
struct SavedState {
|
||||
SavedState(mozilla::WritingMode aWM)
|
||||
: mWritingMode(aWM)
|
||||
, mOrigin(aWM)
|
||||
{}
|
||||
private:
|
||||
uint32_t mFloatInfoCount;
|
||||
nscoord mX, mY;
|
||||
mozilla::WritingMode mWritingMode;
|
||||
mozilla::LogicalPoint mOrigin;
|
||||
bool mPushedLeftFloatPastBreak;
|
||||
bool mPushedRightFloatPastBreak;
|
||||
bool mSplitLeftFloatAcrossBreak;
|
||||
|
@ -89,69 +101,109 @@ public:
|
|||
};
|
||||
|
||||
/**
|
||||
* Translate the current origin by the specified (dx, dy). This
|
||||
* Translate the current origin by the specified (dICoord, dBCoord). This
|
||||
* creates a new local coordinate space relative to the current
|
||||
* coordinate space.
|
||||
* @returns previous writing mode
|
||||
*/
|
||||
void Translate(nscoord aDx, nscoord aDy) { mX += aDx; mY += aDy; }
|
||||
mozilla::WritingMode Translate(mozilla::WritingMode aWM,
|
||||
mozilla::LogicalPoint aDOrigin,
|
||||
nscoord aContainerWidth)
|
||||
{
|
||||
mozilla::WritingMode oldWM = mWritingMode;
|
||||
mOrigin = mOrigin.ConvertTo(aWM, oldWM, aContainerWidth);
|
||||
mWritingMode = aWM;
|
||||
mOrigin += aDOrigin;
|
||||
return oldWM;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the translation origin to a specified value instead of
|
||||
* translating by a delta.
|
||||
*/
|
||||
void SetTranslation(mozilla::WritingMode aWM,
|
||||
mozilla::LogicalPoint aOrigin)
|
||||
{
|
||||
mWritingMode = aWM;
|
||||
mOrigin = aOrigin;
|
||||
}
|
||||
|
||||
void Untranslate(mozilla::WritingMode aWM,
|
||||
mozilla::LogicalPoint aDOrigin,
|
||||
nscoord aContainerWidth)
|
||||
{
|
||||
mOrigin -= aDOrigin;
|
||||
mOrigin = mOrigin.ConvertTo(aWM, mWritingMode, aContainerWidth);
|
||||
mWritingMode = aWM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current translation from local coordinate space to
|
||||
* world coordinate space. This represents the accumulated calls to
|
||||
* Translate().
|
||||
*/
|
||||
void GetTranslation(nscoord& aX, nscoord& aY) const { aX = mX; aY = mY; }
|
||||
void GetTranslation(mozilla::WritingMode& aWM,
|
||||
mozilla::LogicalPoint& aOrigin) const
|
||||
{
|
||||
aWM = mWritingMode;
|
||||
aOrigin = mOrigin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information about the area available to content that flows
|
||||
* around floats. Two different types of space can be requested:
|
||||
* BAND_FROM_POINT: returns the band containing vertical coordinate
|
||||
* |aY| (though actually with the top truncated to begin at aY),
|
||||
* but up to at most |aHeight| (which may be nscoord_MAX).
|
||||
* This will return the tallest rectangle whose top is |aY| and in
|
||||
* which there are no changes in what floats are on the sides of
|
||||
* that rectangle, but will limit the height of the rectangle to
|
||||
* |aHeight|. The left and right edges of the rectangle give the
|
||||
* area available for line boxes in that space. The width of this
|
||||
* resulting rectangle will not be negative.
|
||||
* WIDTH_WITHIN_HEIGHT: This returns a rectangle whose top is aY and
|
||||
* whose height is exactly aHeight. Its left and right edges give
|
||||
* the left and right edges of the space that can be used for line
|
||||
* boxes *throughout* that space. (It is possible that more
|
||||
* horizontal space could be used in part of the space if a float
|
||||
* begins or ends in it.) The width of the resulting rectangle
|
||||
* can be negative.
|
||||
* BAND_FROM_POINT: returns the band containing block-dir coordinate
|
||||
* |aBCoord| (though actually with the top truncated to begin at
|
||||
* aBCoord), but up to at most |aBSize| (which may be nscoord_MAX).
|
||||
* This will return the tallest rectangle whose block start is
|
||||
* |aBCoord| and in which there are no changes in what floats are
|
||||
* on the sides of that rectangle, but will limit the block size
|
||||
* of the rectangle to |aBSize|. The inline start and end edges
|
||||
* of the rectangle give the area available for line boxes in that
|
||||
* space. The inline size of this resulting rectangle will not be
|
||||
* negative.
|
||||
* WIDTH_WITHIN_HEIGHT: This returns a rectangle whose block start
|
||||
* is aBCoord and whose block size is exactly aBSize. Its inline
|
||||
* start and end edges give the corresponding edges of the space
|
||||
* that can be used for line boxes *throughout* that space. (It
|
||||
* is possible that more inline space could be used in part of the
|
||||
* space if a float begins or ends in it.) The inline size of the
|
||||
* resulting rectangle can be negative.
|
||||
*
|
||||
* @param aY [in] vertical coordinate for top of available space
|
||||
* desired
|
||||
* @param aHeight [in] see above
|
||||
* @param aBCoord [in] block-dir coordinate for block start of
|
||||
* available space desired
|
||||
* @param aBSize [in] see above
|
||||
* @param aContentArea [in] an nsRect representing the content area
|
||||
* @param aState [in] If null, use the current state, otherwise, do
|
||||
* computation based only on floats present in the given
|
||||
* saved state.
|
||||
* @return An nsFlowAreaRect whose:
|
||||
* mRect is the resulting rectangle for line boxes. It will not
|
||||
* extend beyond aContentArea's horizontal bounds, but may be
|
||||
* extend beyond aContentArea's inline bounds, but may be
|
||||
* narrower when floats are present.
|
||||
* mBandHasFloats is whether there are floats at the sides of the
|
||||
* return value including those that do not reduce the line box
|
||||
* width at all (because they are entirely in the margins)
|
||||
* inline size at all (because they are entirely in the margins)
|
||||
*
|
||||
* aY and aAvailSpace are positioned relative to the current translation
|
||||
* aBCoord and aAvailSpace are positioned relative to the current translation
|
||||
*/
|
||||
enum BandInfoType { BAND_FROM_POINT, WIDTH_WITHIN_HEIGHT };
|
||||
nsFlowAreaRect GetFlowArea(nscoord aY, BandInfoType aInfoType,
|
||||
nscoord aHeight, nsRect aContentArea,
|
||||
SavedState* aState) const;
|
||||
nsFlowAreaRect GetFlowArea(mozilla::WritingMode aWM,
|
||||
nscoord aBCoord, BandInfoType aInfoType,
|
||||
nscoord aBSize, mozilla::LogicalRect aContentArea,
|
||||
SavedState* aState, nscoord mContainerWidth) const;
|
||||
|
||||
/**
|
||||
* Add a float that comes after all floats previously added. Its top
|
||||
* must be even with or below the top of all previous floats.
|
||||
* Add a float that comes after all floats previously added. Its
|
||||
* block start must be even with or below the top of all previous
|
||||
* floats.
|
||||
*
|
||||
* aMarginRect is relative to the current translation. The caller
|
||||
* must ensure aMarginRect.height >= 0 and aMarginRect.width >= 0.
|
||||
*/
|
||||
nsresult AddFloat(nsIFrame* aFloatFrame, const nsRect& aMarginRect);
|
||||
nsresult AddFloat(nsIFrame* aFloatFrame,
|
||||
const mozilla::LogicalRect& aMarginRect,
|
||||
mozilla::WritingMode aWM, nscoord aContainerWidth);
|
||||
|
||||
/**
|
||||
* Notify that we tried to place a float that could not fit at all and
|
||||
|
@ -200,14 +252,18 @@ public:
|
|||
return !mFloatDamage.IsEmpty();
|
||||
}
|
||||
|
||||
void IncludeInDamage(nscoord aIntervalBegin, nscoord aIntervalEnd)
|
||||
void IncludeInDamage(mozilla::WritingMode aWM,
|
||||
nscoord aIntervalBegin, nscoord aIntervalEnd)
|
||||
{
|
||||
mFloatDamage.IncludeInterval(aIntervalBegin + mY, aIntervalEnd + mY);
|
||||
mFloatDamage.IncludeInterval(aIntervalBegin + mOrigin.B(aWM),
|
||||
aIntervalEnd + mOrigin.B(aWM));
|
||||
}
|
||||
|
||||
bool IntersectsDamage(nscoord aIntervalBegin, nscoord aIntervalEnd) const
|
||||
bool IntersectsDamage(mozilla::WritingMode aWM,
|
||||
nscoord aIntervalBegin, nscoord aIntervalEnd) const
|
||||
{
|
||||
return mFloatDamage.Intersects(aIntervalBegin + mY, aIntervalEnd + mY);
|
||||
return mFloatDamage.Intersects(aIntervalBegin + mOrigin.B(aWM),
|
||||
aIntervalEnd + mOrigin.B(aWM));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -228,26 +284,30 @@ public:
|
|||
void PopState(SavedState* aState);
|
||||
|
||||
/**
|
||||
* Get the top of the last float placed into the float manager, to
|
||||
* enforce the rule that a float can't be above an earlier float.
|
||||
* Returns the minimum nscoord value if there are no floats.
|
||||
* Get the block start of the last float placed into the float
|
||||
* manager, to enforce the rule that a float can't be above an earlier
|
||||
* float. Returns the minimum nscoord value if there are no floats.
|
||||
*
|
||||
* The result is relative to the current translation.
|
||||
*/
|
||||
nscoord GetLowestFloatTop() const;
|
||||
nscoord GetLowestFloatTop(mozilla::WritingMode aWM,
|
||||
nscoord aContainerWidth) const;
|
||||
|
||||
/**
|
||||
* Return the coordinate of the lowest float matching aBreakType in this
|
||||
* float manager. Returns aY if there are no matching floats.
|
||||
* Return the coordinate of the lowest float matching aBreakType in
|
||||
* this float manager. Returns aBCoord if there are no matching
|
||||
* floats.
|
||||
*
|
||||
* Both aY and the result are relative to the current translation.
|
||||
* Both aBCoord and the result are relative to the current translation.
|
||||
*/
|
||||
enum {
|
||||
// Tell ClearFloats not to push to nscoord_MAX when floats have been
|
||||
// pushed to the next page/column.
|
||||
DONT_CLEAR_PUSHED_FLOATS = (1<<0)
|
||||
};
|
||||
nscoord ClearFloats(nscoord aY, uint8_t aBreakType, uint32_t aFlags = 0) const;
|
||||
nscoord ClearFloats(mozilla::WritingMode aWM, nscoord aBCoord,
|
||||
uint8_t aBreakType, nscoord aContainerWidth,
|
||||
uint32_t aFlags = 0) const;
|
||||
|
||||
/**
|
||||
* Checks if clear would pass into the floats' BFC's next-in-flow,
|
||||
|
@ -257,7 +317,8 @@ public:
|
|||
|
||||
void AssertStateMatches(SavedState *aState) const
|
||||
{
|
||||
NS_ASSERTION(aState->mX == mX && aState->mY == mY &&
|
||||
NS_ASSERTION(aState->mWritingMode == mWritingMode &&
|
||||
aState->mOrigin == mOrigin &&
|
||||
aState->mPushedLeftFloatPastBreak ==
|
||||
mPushedLeftFloatPastBreak &&
|
||||
aState->mPushedRightFloatPastBreak ==
|
||||
|
@ -281,18 +342,24 @@ private:
|
|||
|
||||
struct FloatInfo {
|
||||
nsIFrame *const mFrame;
|
||||
nsRect mRect;
|
||||
// The lowest bottoms of left/right floats up to and including this one.
|
||||
nscoord mLeftYMost, mRightYMost;
|
||||
mozilla::LogicalRect mRect;
|
||||
mozilla::WritingMode mWritingMode;
|
||||
// The lowest block-ends of left/right floats up to and including
|
||||
// this one.
|
||||
nscoord mLeftBEnd, mRightBEnd;
|
||||
|
||||
FloatInfo(nsIFrame* aFrame, const nsRect& aRect);
|
||||
FloatInfo(nsIFrame* aFrame, mozilla::WritingMode aWM,
|
||||
const mozilla::LogicalRect& aRect);
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
FloatInfo(const FloatInfo& aOther);
|
||||
~FloatInfo();
|
||||
#endif
|
||||
};
|
||||
|
||||
nscoord mX, mY; // translation from local to global coordinate space
|
||||
mozilla::WritingMode mWritingMode;
|
||||
mozilla::LogicalPoint mOrigin; // translation from local to global
|
||||
// coordinate space
|
||||
|
||||
nsTArray<FloatInfo> mFloats;
|
||||
nsIntervalSet mFloatDamage;
|
||||
|
||||
|
|
|
@ -841,10 +841,8 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
|||
metrics.ISize(lineWM) = nscoord(0xdeadbeef);
|
||||
metrics.BSize(lineWM) = nscoord(0xdeadbeef);
|
||||
#endif
|
||||
nsRect physicalBounds = pfd->mBounds.GetPhysicalRect(lineWM, mContainerWidth);
|
||||
nscoord tx = physicalBounds.x;
|
||||
nscoord ty = physicalBounds.y;
|
||||
mFloatManager->Translate(tx, ty);
|
||||
LogicalPoint tPt = pfd->mBounds.Origin(lineWM);
|
||||
WritingMode oldWM = mFloatManager->Translate(lineWM, tPt, mContainerWidth);
|
||||
|
||||
int32_t savedOptionalBreakOffset;
|
||||
gfxBreakPriority savedOptionalBreakPriority;
|
||||
|
@ -929,7 +927,7 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
|||
}
|
||||
}
|
||||
|
||||
mFloatManager->Translate(-tx, -ty);
|
||||
mFloatManager->Untranslate(oldWM, tPt, mContainerWidth);
|
||||
|
||||
NS_ASSERTION(metrics.ISize(lineWM) >= 0, "bad inline size");
|
||||
NS_ASSERTION(metrics.BSize(lineWM) >= 0,"bad block size");
|
||||
|
|
Загрузка…
Ссылка в новой задаче