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:
Simon Montagu 2014-10-19 12:32:17 -07:00
Родитель 7ed4ceb17c
Коммит 3f0d7f2fcc
9 изменённых файлов: 406 добавлений и 248 удалений

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

@ -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");