1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/generic/nsFloatManager.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,557 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* class that manages rules for positioning floats */ 1.10 + 1.11 +#include "nsFloatManager.h" 1.12 +#include "nsIPresShell.h" 1.13 +#include "nsMemory.h" 1.14 +#include "nsHTMLReflowState.h" 1.15 +#include "nsBlockDebugFlags.h" 1.16 +#include "nsError.h" 1.17 +#include <algorithm> 1.18 + 1.19 +using namespace mozilla; 1.20 + 1.21 +int32_t nsFloatManager::sCachedFloatManagerCount = 0; 1.22 +void* nsFloatManager::sCachedFloatManagers[NS_FLOAT_MANAGER_CACHE_SIZE]; 1.23 + 1.24 +///////////////////////////////////////////////////////////////////////////// 1.25 + 1.26 +// PresShell Arena allocate callback (for nsIntervalSet use below) 1.27 +static void* 1.28 +PSArenaAllocCB(size_t aSize, void* aClosure) 1.29 +{ 1.30 + return static_cast<nsIPresShell*>(aClosure)->AllocateMisc(aSize); 1.31 +} 1.32 + 1.33 +// PresShell Arena free callback (for nsIntervalSet use below) 1.34 +static void 1.35 +PSArenaFreeCB(size_t aSize, void* aPtr, void* aClosure) 1.36 +{ 1.37 + static_cast<nsIPresShell*>(aClosure)->FreeMisc(aSize, aPtr); 1.38 +} 1.39 + 1.40 +///////////////////////////////////////////////////////////////////////////// 1.41 +// nsFloatManager 1.42 + 1.43 +nsFloatManager::nsFloatManager(nsIPresShell* aPresShell) 1.44 + : mX(0), mY(0), 1.45 + mFloatDamage(PSArenaAllocCB, PSArenaFreeCB, aPresShell), 1.46 + mPushedLeftFloatPastBreak(false), 1.47 + mPushedRightFloatPastBreak(false), 1.48 + mSplitLeftFloatAcrossBreak(false), 1.49 + mSplitRightFloatAcrossBreak(false) 1.50 +{ 1.51 + MOZ_COUNT_CTOR(nsFloatManager); 1.52 +} 1.53 + 1.54 +nsFloatManager::~nsFloatManager() 1.55 +{ 1.56 + MOZ_COUNT_DTOR(nsFloatManager); 1.57 +} 1.58 + 1.59 +// static 1.60 +void* nsFloatManager::operator new(size_t aSize) CPP_THROW_NEW 1.61 +{ 1.62 + if (sCachedFloatManagerCount > 0) { 1.63 + // We have cached unused instances of this class, return a cached 1.64 + // instance in stead of always creating a new one. 1.65 + return sCachedFloatManagers[--sCachedFloatManagerCount]; 1.66 + } 1.67 + 1.68 + // The cache is empty, this means we haveto create a new instance using 1.69 + // the global |operator new|. 1.70 + return nsMemory::Alloc(aSize); 1.71 +} 1.72 + 1.73 +void 1.74 +nsFloatManager::operator delete(void* aPtr, size_t aSize) 1.75 +{ 1.76 + if (!aPtr) 1.77 + return; 1.78 + // This float manager is no longer used, if there's still room in 1.79 + // the cache we'll cache this float manager, unless the layout 1.80 + // module was already shut down. 1.81 + 1.82 + if (sCachedFloatManagerCount < NS_FLOAT_MANAGER_CACHE_SIZE && 1.83 + sCachedFloatManagerCount >= 0) { 1.84 + // There's still space in the cache for more instances, put this 1.85 + // instance in the cache in stead of deleting it. 1.86 + 1.87 + sCachedFloatManagers[sCachedFloatManagerCount++] = aPtr; 1.88 + return; 1.89 + } 1.90 + 1.91 + // The cache is full, or the layout module has been shut down, 1.92 + // delete this float manager. 1.93 + nsMemory::Free(aPtr); 1.94 +} 1.95 + 1.96 + 1.97 +/* static */ 1.98 +void nsFloatManager::Shutdown() 1.99 +{ 1.100 + // The layout module is being shut down, clean up the cache and 1.101 + // disable further caching. 1.102 + 1.103 + int32_t i; 1.104 + 1.105 + for (i = 0; i < sCachedFloatManagerCount; i++) { 1.106 + void* floatManager = sCachedFloatManagers[i]; 1.107 + if (floatManager) 1.108 + nsMemory::Free(floatManager); 1.109 + } 1.110 + 1.111 + // Disable further caching. 1.112 + sCachedFloatManagerCount = -1; 1.113 +} 1.114 + 1.115 +nsFlowAreaRect 1.116 +nsFloatManager::GetFlowArea(nscoord aYOffset, BandInfoType aInfoType, 1.117 + nscoord aHeight, nsRect aContentArea, 1.118 + SavedState* aState) const 1.119 +{ 1.120 + NS_ASSERTION(aHeight >= 0, "unexpected max height"); 1.121 + NS_ASSERTION(aContentArea.width >= 0, "unexpected content area width"); 1.122 + 1.123 + nscoord top = aYOffset + mY; 1.124 + if (top < nscoord_MIN) { 1.125 + NS_WARNING("bad value"); 1.126 + top = nscoord_MIN; 1.127 + } 1.128 + 1.129 + // Determine the last float that we should consider. 1.130 + uint32_t floatCount; 1.131 + if (aState) { 1.132 + // Use the provided state. 1.133 + floatCount = aState->mFloatInfoCount; 1.134 + NS_ABORT_IF_FALSE(floatCount <= mFloats.Length(), "bad state"); 1.135 + } else { 1.136 + // Use our current state. 1.137 + floatCount = mFloats.Length(); 1.138 + } 1.139 + 1.140 + // If there are no floats at all, or we're below the last one, return 1.141 + // quickly. 1.142 + if (floatCount == 0 || 1.143 + (mFloats[floatCount-1].mLeftYMost <= top && 1.144 + mFloats[floatCount-1].mRightYMost <= top)) { 1.145 + return nsFlowAreaRect(aContentArea.x, aYOffset, aContentArea.width, 1.146 + aHeight, false); 1.147 + } 1.148 + 1.149 + nscoord bottom; 1.150 + if (aHeight == nscoord_MAX) { 1.151 + // This warning (and the two below) are possible to hit on pages 1.152 + // with really large objects. 1.153 + NS_WARN_IF_FALSE(aInfoType == BAND_FROM_POINT, 1.154 + "bad height"); 1.155 + bottom = nscoord_MAX; 1.156 + } else { 1.157 + bottom = top + aHeight; 1.158 + if (bottom < top || bottom > nscoord_MAX) { 1.159 + NS_WARNING("bad value"); 1.160 + bottom = nscoord_MAX; 1.161 + } 1.162 + } 1.163 + nscoord left = mX + aContentArea.x; 1.164 + nscoord right = mX + aContentArea.XMost(); 1.165 + if (right < left) { 1.166 + NS_WARNING("bad value"); 1.167 + right = left; 1.168 + } 1.169 + 1.170 + // Walk backwards through the floats until we either hit the front of 1.171 + // the list or we're above |top|. 1.172 + bool haveFloats = false; 1.173 + for (uint32_t i = floatCount; i > 0; --i) { 1.174 + const FloatInfo &fi = mFloats[i-1]; 1.175 + if (fi.mLeftYMost <= top && fi.mRightYMost <= top) { 1.176 + // There aren't any more floats that could intersect this band. 1.177 + break; 1.178 + } 1.179 + if (fi.mRect.IsEmpty()) { 1.180 + // For compatibility, ignore floats with empty rects, even though it 1.181 + // disagrees with the spec. (We might want to fix this in the 1.182 + // future, though.) 1.183 + continue; 1.184 + } 1.185 + nscoord floatTop = fi.mRect.y, floatBottom = fi.mRect.YMost(); 1.186 + if (top < floatTop && aInfoType == BAND_FROM_POINT) { 1.187 + // This float is below our band. Shrink our band's height if needed. 1.188 + if (floatTop < bottom) { 1.189 + bottom = floatTop; 1.190 + } 1.191 + } 1.192 + // If top == bottom (which happens only with WIDTH_WITHIN_HEIGHT), 1.193 + // we include floats that begin at our 0-height vertical area. We 1.194 + // need to to this to satisfy the invariant that a 1.195 + // WIDTH_WITHIN_HEIGHT call is at least as narrow on both sides as a 1.196 + // BAND_WITHIN_POINT call beginning at its top. 1.197 + else if (top < floatBottom && 1.198 + (floatTop < bottom || (floatTop == bottom && top == bottom))) { 1.199 + // This float is in our band. 1.200 + 1.201 + // Shrink our band's height if needed. 1.202 + if (floatBottom < bottom && aInfoType == BAND_FROM_POINT) { 1.203 + bottom = floatBottom; 1.204 + } 1.205 + 1.206 + // Shrink our band's width if needed. 1.207 + if (fi.mFrame->StyleDisplay()->mFloats == NS_STYLE_FLOAT_LEFT) { 1.208 + // A left float. 1.209 + nscoord rightEdge = fi.mRect.XMost(); 1.210 + if (rightEdge > left) { 1.211 + left = rightEdge; 1.212 + // Only set haveFloats to true if the float is inside our 1.213 + // containing block. This matches the spec for what some 1.214 + // callers want and disagrees for other callers, so we should 1.215 + // probably provide better information at some point. 1.216 + haveFloats = true; 1.217 + } 1.218 + } else { 1.219 + // A right float. 1.220 + nscoord leftEdge = fi.mRect.x; 1.221 + if (leftEdge < right) { 1.222 + right = leftEdge; 1.223 + // See above. 1.224 + haveFloats = true; 1.225 + } 1.226 + } 1.227 + } 1.228 + } 1.229 + 1.230 + nscoord height = (bottom == nscoord_MAX) ? nscoord_MAX : (bottom - top); 1.231 + return nsFlowAreaRect(left - mX, top - mY, right - left, height, haveFloats); 1.232 +} 1.233 + 1.234 +nsresult 1.235 +nsFloatManager::AddFloat(nsIFrame* aFloatFrame, const nsRect& aMarginRect) 1.236 +{ 1.237 + NS_ASSERTION(aMarginRect.width >= 0, "negative width!"); 1.238 + NS_ASSERTION(aMarginRect.height >= 0, "negative height!"); 1.239 + 1.240 + FloatInfo info(aFloatFrame, aMarginRect + nsPoint(mX, mY)); 1.241 + 1.242 + // Set mLeftYMost and mRightYMost. 1.243 + if (HasAnyFloats()) { 1.244 + FloatInfo &tail = mFloats[mFloats.Length() - 1]; 1.245 + info.mLeftYMost = tail.mLeftYMost; 1.246 + info.mRightYMost = tail.mRightYMost; 1.247 + } else { 1.248 + info.mLeftYMost = nscoord_MIN; 1.249 + info.mRightYMost = nscoord_MIN; 1.250 + } 1.251 + uint8_t floatStyle = aFloatFrame->StyleDisplay()->mFloats; 1.252 + NS_ASSERTION(floatStyle == NS_STYLE_FLOAT_LEFT || 1.253 + floatStyle == NS_STYLE_FLOAT_RIGHT, "unexpected float"); 1.254 + nscoord& sideYMost = (floatStyle == NS_STYLE_FLOAT_LEFT) ? info.mLeftYMost 1.255 + : info.mRightYMost; 1.256 + nscoord thisYMost = info.mRect.YMost(); 1.257 + if (thisYMost > sideYMost) 1.258 + sideYMost = thisYMost; 1.259 + 1.260 + if (!mFloats.AppendElement(info)) 1.261 + return NS_ERROR_OUT_OF_MEMORY; 1.262 + 1.263 + return NS_OK; 1.264 +} 1.265 + 1.266 +nsRect 1.267 +nsFloatManager::CalculateRegionFor(nsIFrame* aFloat, 1.268 + const nsMargin& aMargin) 1.269 +{ 1.270 + // We consider relatively positioned frames at their original position. 1.271 + nsRect region(aFloat->GetNormalPosition(), aFloat->GetSize()); 1.272 + 1.273 + // Float region includes its margin 1.274 + region.Inflate(aMargin); 1.275 + 1.276 + // Don't store rectangles with negative margin-box width or height in 1.277 + // the float manager; it can't deal with them. 1.278 + if (region.width < 0) { 1.279 + // Preserve the right margin-edge for left floats and the left 1.280 + // margin-edge for right floats 1.281 + const nsStyleDisplay* display = aFloat->StyleDisplay(); 1.282 + if (NS_STYLE_FLOAT_LEFT == display->mFloats) { 1.283 + region.x = region.XMost(); 1.284 + } 1.285 + region.width = 0; 1.286 + } 1.287 + if (region.height < 0) { 1.288 + region.height = 0; 1.289 + } 1.290 + return region; 1.291 +} 1.292 + 1.293 +NS_DECLARE_FRAME_PROPERTY(FloatRegionProperty, nsIFrame::DestroyMargin) 1.294 + 1.295 +nsRect 1.296 +nsFloatManager::GetRegionFor(nsIFrame* aFloat) 1.297 +{ 1.298 + nsRect region = aFloat->GetRect(); 1.299 + void* storedRegion = aFloat->Properties().Get(FloatRegionProperty()); 1.300 + if (storedRegion) { 1.301 + nsMargin margin = *static_cast<nsMargin*>(storedRegion); 1.302 + region.Inflate(margin); 1.303 + } 1.304 + return region; 1.305 +} 1.306 + 1.307 +void 1.308 +nsFloatManager::StoreRegionFor(nsIFrame* aFloat, 1.309 + nsRect& aRegion) 1.310 +{ 1.311 + nsRect rect = aFloat->GetRect(); 1.312 + FrameProperties props = aFloat->Properties(); 1.313 + if (aRegion.IsEqualEdges(rect)) { 1.314 + props.Delete(FloatRegionProperty()); 1.315 + } 1.316 + else { 1.317 + nsMargin* storedMargin = static_cast<nsMargin*> 1.318 + (props.Get(FloatRegionProperty())); 1.319 + if (!storedMargin) { 1.320 + storedMargin = new nsMargin(); 1.321 + props.Set(FloatRegionProperty(), storedMargin); 1.322 + } 1.323 + *storedMargin = aRegion - rect; 1.324 + } 1.325 +} 1.326 + 1.327 +nsresult 1.328 +nsFloatManager::RemoveTrailingRegions(nsIFrame* aFrameList) 1.329 +{ 1.330 + if (!aFrameList) { 1.331 + return NS_OK; 1.332 + } 1.333 + // This could be a good bit simpler if we could guarantee that the 1.334 + // floats given were at the end of our list, so we could just search 1.335 + // for the head of aFrameList. (But we can't; 1.336 + // layout/reftests/bugs/421710-1.html crashes.) 1.337 + nsTHashtable<nsPtrHashKey<nsIFrame> > frameSet(1); 1.338 + 1.339 + for (nsIFrame* f = aFrameList; f; f = f->GetNextSibling()) { 1.340 + frameSet.PutEntry(f); 1.341 + } 1.342 + 1.343 + uint32_t newLength = mFloats.Length(); 1.344 + while (newLength > 0) { 1.345 + if (!frameSet.Contains(mFloats[newLength - 1].mFrame)) { 1.346 + break; 1.347 + } 1.348 + --newLength; 1.349 + } 1.350 + mFloats.TruncateLength(newLength); 1.351 + 1.352 +#ifdef DEBUG 1.353 + for (uint32_t i = 0; i < mFloats.Length(); ++i) { 1.354 + NS_ASSERTION(!frameSet.Contains(mFloats[i].mFrame), 1.355 + "Frame region deletion was requested but we couldn't delete it"); 1.356 + } 1.357 +#endif 1.358 + 1.359 + return NS_OK; 1.360 +} 1.361 + 1.362 +void 1.363 +nsFloatManager::PushState(SavedState* aState) 1.364 +{ 1.365 + NS_PRECONDITION(aState, "Need a place to save state"); 1.366 + 1.367 + // This is a cheap push implementation, which 1.368 + // only saves the (x,y) and last frame in the mFrameInfoMap 1.369 + // which is enough info to get us back to where we should be 1.370 + // when pop is called. 1.371 + // 1.372 + // This push/pop mechanism is used to undo any 1.373 + // floats that were added during the unconstrained reflow 1.374 + // in nsBlockReflowContext::DoReflowBlock(). (See bug 96736) 1.375 + // 1.376 + // It should also be noted that the state for mFloatDamage is 1.377 + // intentionally not saved or restored in PushState() and PopState(), 1.378 + // since that could lead to bugs where damage is missed/dropped when 1.379 + // we move from position A to B (during the intermediate incremental 1.380 + // reflow mentioned above) and then from B to C during the subsequent 1.381 + // reflow. In the typical case A and C will be the same, but not always. 1.382 + // Allowing mFloatDamage to accumulate the damage incurred during both 1.383 + // reflows ensures that nothing gets missed. 1.384 + aState->mX = mX; 1.385 + aState->mY = mY; 1.386 + aState->mPushedLeftFloatPastBreak = mPushedLeftFloatPastBreak; 1.387 + aState->mPushedRightFloatPastBreak = mPushedRightFloatPastBreak; 1.388 + aState->mSplitLeftFloatAcrossBreak = mSplitLeftFloatAcrossBreak; 1.389 + aState->mSplitRightFloatAcrossBreak = mSplitRightFloatAcrossBreak; 1.390 + aState->mFloatInfoCount = mFloats.Length(); 1.391 +} 1.392 + 1.393 +void 1.394 +nsFloatManager::PopState(SavedState* aState) 1.395 +{ 1.396 + NS_PRECONDITION(aState, "No state to restore?"); 1.397 + 1.398 + mX = aState->mX; 1.399 + mY = aState->mY; 1.400 + mPushedLeftFloatPastBreak = aState->mPushedLeftFloatPastBreak; 1.401 + mPushedRightFloatPastBreak = aState->mPushedRightFloatPastBreak; 1.402 + mSplitLeftFloatAcrossBreak = aState->mSplitLeftFloatAcrossBreak; 1.403 + mSplitRightFloatAcrossBreak = aState->mSplitRightFloatAcrossBreak; 1.404 + 1.405 + NS_ASSERTION(aState->mFloatInfoCount <= mFloats.Length(), 1.406 + "somebody misused PushState/PopState"); 1.407 + mFloats.TruncateLength(aState->mFloatInfoCount); 1.408 +} 1.409 + 1.410 +nscoord 1.411 +nsFloatManager::GetLowestFloatTop() const 1.412 +{ 1.413 + if (mPushedLeftFloatPastBreak || mPushedRightFloatPastBreak) { 1.414 + return nscoord_MAX; 1.415 + } 1.416 + if (!HasAnyFloats()) { 1.417 + return nscoord_MIN; 1.418 + } 1.419 + return mFloats[mFloats.Length() - 1].mRect.y - mY; 1.420 +} 1.421 + 1.422 +#ifdef DEBUG_FRAME_DUMP 1.423 +void 1.424 +DebugListFloatManager(const nsFloatManager *aFloatManager) 1.425 +{ 1.426 + aFloatManager->List(stdout); 1.427 +} 1.428 + 1.429 +nsresult 1.430 +nsFloatManager::List(FILE* out) const 1.431 +{ 1.432 + if (!HasAnyFloats()) 1.433 + return NS_OK; 1.434 + 1.435 + for (uint32_t i = 0; i < mFloats.Length(); ++i) { 1.436 + const FloatInfo &fi = mFloats[i]; 1.437 + fprintf_stderr(out, "Float %u: frame=%p rect={%d,%d,%d,%d} ymost={l:%d, r:%d}\n", 1.438 + i, static_cast<void*>(fi.mFrame), 1.439 + fi.mRect.x, fi.mRect.y, fi.mRect.width, fi.mRect.height, 1.440 + fi.mLeftYMost, fi.mRightYMost); 1.441 + } 1.442 + return NS_OK; 1.443 +} 1.444 +#endif 1.445 + 1.446 +nscoord 1.447 +nsFloatManager::ClearFloats(nscoord aY, uint8_t aBreakType, 1.448 + uint32_t aFlags) const 1.449 +{ 1.450 + if (!(aFlags & DONT_CLEAR_PUSHED_FLOATS) && ClearContinues(aBreakType)) { 1.451 + return nscoord_MAX; 1.452 + } 1.453 + if (!HasAnyFloats()) { 1.454 + return aY; 1.455 + } 1.456 + 1.457 + nscoord bottom = aY + mY; 1.458 + 1.459 + const FloatInfo &tail = mFloats[mFloats.Length() - 1]; 1.460 + switch (aBreakType) { 1.461 + case NS_STYLE_CLEAR_BOTH: 1.462 + bottom = std::max(bottom, tail.mLeftYMost); 1.463 + bottom = std::max(bottom, tail.mRightYMost); 1.464 + break; 1.465 + case NS_STYLE_CLEAR_LEFT: 1.466 + bottom = std::max(bottom, tail.mLeftYMost); 1.467 + break; 1.468 + case NS_STYLE_CLEAR_RIGHT: 1.469 + bottom = std::max(bottom, tail.mRightYMost); 1.470 + break; 1.471 + default: 1.472 + // Do nothing 1.473 + break; 1.474 + } 1.475 + 1.476 + bottom -= mY; 1.477 + 1.478 + return bottom; 1.479 +} 1.480 + 1.481 +bool 1.482 +nsFloatManager::ClearContinues(uint8_t aBreakType) const 1.483 +{ 1.484 + return ((mPushedLeftFloatPastBreak || mSplitLeftFloatAcrossBreak) && 1.485 + (aBreakType == NS_STYLE_CLEAR_BOTH || 1.486 + aBreakType == NS_STYLE_CLEAR_LEFT)) || 1.487 + ((mPushedRightFloatPastBreak || mSplitRightFloatAcrossBreak) && 1.488 + (aBreakType == NS_STYLE_CLEAR_BOTH || 1.489 + aBreakType == NS_STYLE_CLEAR_RIGHT)); 1.490 +} 1.491 + 1.492 +///////////////////////////////////////////////////////////////////////////// 1.493 +// FloatInfo 1.494 + 1.495 +nsFloatManager::FloatInfo::FloatInfo(nsIFrame* aFrame, const nsRect& aRect) 1.496 + : mFrame(aFrame), mRect(aRect) 1.497 +{ 1.498 + MOZ_COUNT_CTOR(nsFloatManager::FloatInfo); 1.499 +} 1.500 + 1.501 +#ifdef NS_BUILD_REFCNT_LOGGING 1.502 +nsFloatManager::FloatInfo::FloatInfo(const FloatInfo& aOther) 1.503 + : mFrame(aOther.mFrame), 1.504 + mRect(aOther.mRect), 1.505 + mLeftYMost(aOther.mLeftYMost), 1.506 + mRightYMost(aOther.mRightYMost) 1.507 +{ 1.508 + MOZ_COUNT_CTOR(nsFloatManager::FloatInfo); 1.509 +} 1.510 + 1.511 +nsFloatManager::FloatInfo::~FloatInfo() 1.512 +{ 1.513 + MOZ_COUNT_DTOR(nsFloatManager::FloatInfo); 1.514 +} 1.515 +#endif 1.516 + 1.517 +//---------------------------------------------------------------------- 1.518 + 1.519 +nsAutoFloatManager::~nsAutoFloatManager() 1.520 +{ 1.521 + // Restore the old float manager in the reflow state if necessary. 1.522 + if (mNew) { 1.523 +#ifdef NOISY_FLOATMANAGER 1.524 + printf("restoring old float manager %p\n", mOld); 1.525 +#endif 1.526 + 1.527 + mReflowState.mFloatManager = mOld; 1.528 + 1.529 +#ifdef NOISY_FLOATMANAGER 1.530 + if (mOld) { 1.531 + static_cast<nsFrame *>(mReflowState.frame)->ListTag(stdout); 1.532 + printf(": space-manager %p after reflow\n", mOld); 1.533 + mOld->List(stdout); 1.534 + } 1.535 +#endif 1.536 + 1.537 + delete mNew; 1.538 + } 1.539 +} 1.540 + 1.541 +nsresult 1.542 +nsAutoFloatManager::CreateFloatManager(nsPresContext *aPresContext) 1.543 +{ 1.544 + // Create a new float manager and install it in the reflow 1.545 + // state. `Remember' the old float manager so we can restore it 1.546 + // later. 1.547 + mNew = new nsFloatManager(aPresContext->PresShell()); 1.548 + if (! mNew) 1.549 + return NS_ERROR_OUT_OF_MEMORY; 1.550 + 1.551 +#ifdef NOISY_FLOATMANAGER 1.552 + printf("constructed new float manager %p (replacing %p)\n", 1.553 + mNew, mReflowState.mFloatManager); 1.554 +#endif 1.555 + 1.556 + // Set the float manager in the existing reflow state 1.557 + mOld = mReflowState.mFloatManager; 1.558 + mReflowState.mFloatManager = mNew; 1.559 + return NS_OK; 1.560 +}