LCOV - app.info - layout/generic/nsBlockReflowState.cpp

LCOV - code coverage report
| Current view: | directory - layout/generic - nsBlockReflowState.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 340 | 0 | 0.0 %
| Date: | 2012-04-21 | Functions: | 16 | 0 | 0.0 %

           1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
           2                 : // vim:cindent:ts=2:et:sw=2:
           3                 : /* ***** BEGIN LICENSE BLOCK *****
           4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           5                 :  *
           6                 :  * The contents of this file are subject to the Mozilla Public License Version
           7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           8                 :  * the License. You may obtain a copy of the License at
           9                 :  * http://www.mozilla.org/MPL/
          10                 :  *
          11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          13                 :  * for the specific language governing rights and limitations under the
          14                 :  * License.
          15                 :  *
          16                 :  * The Original Code is Mozilla Communicator client code.
          17                 :  *
          18                 :  * The Initial Developer of the Original Code is
          19                 :  * Netscape Communications Corporation.
          20                 :  * Portions created by the Initial Developer are Copyright (C) 1998
          21                 :  * the Initial Developer. All Rights Reserved.
          22                 :  *
          23                 :  * Contributor(s):
          24                 :  *   Steve Clark <buster@netscape.com>
          25                 :  *   Robert O'Callahan <roc+moz@cs.cmu.edu>
          26                 :  *   L. David Baron <dbaron@dbaron.org>
          27                 :  *   Mats Palmgren <mats.palmgren@bredband.net>
          28                 :  *
          29                 :  * Alternatively, the contents of this file may be used under the terms of
          30                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
          31                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          32                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          33                 :  * of those above. If you wish to allow use of your version of this file only
          34                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          35                 :  * use your version of this file under the terms of the MPL, indicate your
          36                 :  * decision by deleting the provisions above and replace them with the notice
          37                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          38                 :  * the provisions above, a recipient may use your version of this file under
          39                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          40                 :  *
          41                 :  * ***** END LICENSE BLOCK ***** */
          42                 :
          43                 : /* state used in reflow of block frames */
          44                 :
          45                 : #include "nsBlockReflowContext.h"
          46                 : #include "nsBlockReflowState.h"
          47                 : #include "nsBlockFrame.h"
          48                 : #include "nsLineLayout.h"
          49                 : #include "nsPresContext.h"
          50                 : #include "nsGkAtoms.h"
          51                 : #include "nsIFrame.h"
          52                 : #include "nsFrameManager.h"
          53                 : #include "mozilla/AutoRestore.h"
          54                 : #include "FrameLayerBuilder.h"
          55                 :
          56                 : #include "nsINameSpaceManager.h"
          57                 :
          58                 : #include "mozilla/Util.h" // for DebugOnly
          59                 :
          60                 : #ifdef DEBUG
          61                 : #include "nsBlockDebugFlags.h"
          62                 : #endif
          63                 :
          64                 : using namespace mozilla;
          65                 : using namespace mozilla::layout;
          66                 :
          67               0 : nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
          68                 :                                        nsPresContext* aPresContext,
          69                 :                                        nsBlockFrame* aFrame,
          70                 :                                        const nsHTMLReflowMetrics& aMetrics,
          71                 :                                        bool aTopMarginRoot,
          72                 :                                        bool aBottomMarginRoot,
          73                 :                                        bool aBlockNeedsFloatManager)
          74                 :   : mBlock(aFrame),
          75                 :     mPresContext(aPresContext),
          76                 :     mReflowState(aReflowState),
          77                 :     mPushedFloats(nsnull),
          78                 :     mOverflowTracker(nsnull),
          79                 :     mPrevBottomMargin(),
          80                 :     mLineNumber(0),
          81                 :     mFlags(0),
          82               0 :     mFloatBreakType(NS_STYLE_CLEAR_NONE)
          83                 : {
          84               0 :   SetFlag(BRS_ISFIRSTINFLOW, aFrame->GetPrevInFlow() == nsnull);
          85                 :   SetFlag(BRS_ISOVERFLOWCONTAINER,
          86               0 :           IS_TRUE_OVERFLOW_CONTAINER(aFrame));
          87                 :
          88               0 :   const nsMargin& borderPadding = BorderPadding();
          89                 :
          90               0 :   if (aTopMarginRoot || 0 != aReflowState.mComputedBorderPadding.top) {
          91               0 :     SetFlag(BRS_ISTOPMARGINROOT, true);
          92                 :   }
          93               0 :   if (aBottomMarginRoot || 0 != aReflowState.mComputedBorderPadding.bottom) {
          94               0 :     SetFlag(BRS_ISBOTTOMMARGINROOT, true);
          95                 :   }
          96               0 :   if (GetFlag(BRS_ISTOPMARGINROOT)) {
          97               0 :     SetFlag(BRS_APPLYTOPMARGIN, true);
          98                 :   }
          99               0 :   if (aBlockNeedsFloatManager) {
         100               0 :     SetFlag(BRS_FLOAT_MGR, true);
         101                 :   }
         102                 :
         103               0 :   mFloatManager = aReflowState.mFloatManager;
         104                 :
         105               0 :   NS_ASSERTION(mFloatManager,
         106                 :                "FloatManager should be set in nsBlockReflowState" );
         107               0 :   if (mFloatManager) {
         108                 :     // Save the coordinate system origin for later.
         109               0 :     mFloatManager->GetTranslation(mFloatManagerX, mFloatManagerY);
         110               0 :     mFloatManager->PushState(&mFloatManagerStateBefore); // never popped
         111                 :   }
         112                 :
         113               0 :   mReflowStatus = NS_FRAME_COMPLETE;
         114                 :
         115               0 :   mPresContext = aPresContext;
         116               0 :   mNextInFlow = static_cast<nsBlockFrame*>(mBlock->GetNextInFlow());
         117                 :
         118               0 :   NS_WARN_IF_FALSE(NS_UNCONSTRAINEDSIZE != aReflowState.ComputedWidth(),
         119                 :                    "have unconstrained width; this should only result from "
         120                 :                    "very large sizes, not attempts at intrinsic width "
         121                 :                    "calculation");
         122               0 :   mContentArea.width = aReflowState.ComputedWidth();
         123                 :
         124                 :   // Compute content area height. Unlike the width, if we have a
         125                 :   // specified style height we ignore it since extra content is
         126                 :   // managed by the "overflow" property. When we don't have a
         127                 :   // specified style height then we may end up limiting our height if
         128                 :   // the availableHeight is constrained (this situation occurs when we
         129                 :   // are paginated).
         130               0 :   if (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight) {
         131                 :     // We are in a paginated situation. The bottom edge is just inside
         132                 :     // the bottom border and padding. The content area height doesn't
         133                 :     // include either border or padding edge.
         134               0 :     mBottomEdge = aReflowState.availableHeight - borderPadding.bottom;
         135               0 :     mContentArea.height = NS_MAX(0, mBottomEdge - borderPadding.top);
         136                 :   }
         137                 :   else {
         138                 :     // When we are not in a paginated situation then we always use
         139                 :     // an constrained height.
         140               0 :     SetFlag(BRS_UNCONSTRAINEDHEIGHT, true);
         141               0 :     mContentArea.height = mBottomEdge = NS_UNCONSTRAINEDSIZE;
         142                 :   }
         143               0 :   mContentArea.x = borderPadding.left;
         144               0 :   mY = mContentArea.y = borderPadding.top;
         145                 :
         146               0 :   mPrevChild = nsnull;
         147               0 :   mCurrentLine = aFrame->end_lines();
         148                 :
         149               0 :   mMinLineHeight = aReflowState.CalcLineHeight();
         150               0 : }
         151                 :
         152                 : void
         153               0 : nsBlockReflowState::ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
         154                 :                                                          const nsRect& aFloatAvailableSpace,
         155                 :                                                          nscoord& aLeftResult,
         156                 :                                                          nscoord& aRightResult)
         157                 : {
         158                 :   // The frame is clueless about the float manager and therefore we
         159                 :   // only give it free space. An example is a table frame - the
         160                 :   // tables do not flow around floats.
         161                 :   // However, we can let its margins intersect floats.
         162               0 :   NS_ASSERTION(aFloatAvailableSpace.x >= mContentArea.x, "bad avail space rect x");
         163               0 :   NS_ASSERTION(aFloatAvailableSpace.width == 0 ||
         164                 :                aFloatAvailableSpace.XMost() <= mContentArea.XMost(),
         165                 :                "bad avail space rect width");
         166                 :
         167                 :   nscoord leftOffset, rightOffset;
         168               0 :   if (aFloatAvailableSpace.width == mContentArea.width) {
         169                 :     // We don't need to compute margins when there are no floats around.
         170               0 :     leftOffset = 0;
         171               0 :     rightOffset = 0;
         172                 :   } else {
         173               0 :     nsMargin frameMargin;
         174               0 :     nsCSSOffsetState os(aFrame, mReflowState.rendContext, mContentArea.width);
         175               0 :     frameMargin = os.mComputedMargin;
         176                 :
         177               0 :     nscoord leftFloatXOffset = aFloatAvailableSpace.x - mContentArea.x;
         178               0 :     leftOffset = NS_MAX(leftFloatXOffset, frameMargin.left) -
         179               0 :                  frameMargin.left;
         180               0 :     leftOffset = NS_MAX(leftOffset, 0); // in case of negative margin
         181                 :     nscoord rightFloatXOffset =
         182               0 :       mContentArea.XMost() - aFloatAvailableSpace.XMost();
         183               0 :     rightOffset = NS_MAX(rightFloatXOffset, frameMargin.right) -
         184               0 :                   frameMargin.right;
         185               0 :     rightOffset = NS_MAX(rightOffset, 0); // in case of negative margin
         186                 :   }
         187               0 :   aLeftResult = leftOffset;
         188               0 :   aRightResult = rightOffset;
         189               0 : }
         190                 :
         191                 : // Compute the amount of available space for reflowing a block frame
         192                 : // at the current Y coordinate. This method assumes that
         193                 : // GetAvailableSpace has already been called.
         194                 : void
         195               0 : nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
         196                 :                                            const nsStyleDisplay* aDisplay,
         197                 :                                            const nsFlowAreaRect& aFloatAvailableSpace,
         198                 :                                            bool aBlockAvoidsFloats,
         199                 :                                            nsRect& aResult)
         200                 : {
         201                 : #ifdef REALLY_NOISY_REFLOW
         202                 :   printf("CBAS frame=%p has floats %d\n",
         203                 :          aFrame, aFloatAvailableSpace.mHasFloats);
         204                 : #endif
         205               0 :   aResult.y = mY;
         206               0 :   aResult.height = GetFlag(BRS_UNCONSTRAINEDHEIGHT)
         207                 :     ? NS_UNCONSTRAINEDSIZE
         208               0 :     : mReflowState.availableHeight - mY;
         209                 :   // mY might be greater than mBottomEdge if the block's top margin pushes
         210                 :   // it off the page/column. Negative available height can confuse other code
         211                 :   // and is nonsense in principle.
         212                 :
         213                 :   // XXX Do we really want this condition to be this restrictive (i.e.,
         214                 :   // more restrictive than it used to be)?  The |else| here is allowed
         215                 :   // by the CSS spec, but only out of desperation given implementations,
         216                 :   // and the behavior it leads to is quite undesirable (it can cause
         217                 :   // things to become extremely narrow when they'd fit quite well a
         218                 :   // little bit lower).  Should the else be a quirk or something that
         219                 :   // applies to a specific set of frame classes and no new ones?
         220                 :   // If we did that, then for those frames where the condition below is
         221                 :   // true but nsBlockFrame::BlockCanIntersectFloats is false,
         222                 :   // nsBlockFrame::WidthToClearPastFloats would need to use the
         223                 :   // shrink-wrap formula, max(MIN_WIDTH, min(avail width, PREF_WIDTH))
         224                 :   // rather than just using MIN_WIDTH.
         225               0 :   NS_ASSERTION(nsBlockFrame::BlockCanIntersectFloats(aFrame) ==
         226                 :                  !aBlockAvoidsFloats,
         227                 :                "unexpected replaced width");
         228               0 :   if (!aBlockAvoidsFloats) {
         229               0 :     if (aFloatAvailableSpace.mHasFloats) {
         230                 :       // Use the float-edge property to determine how the child block
         231                 :       // will interact with the float.
         232               0 :       const nsStyleBorder* borderStyle = aFrame->GetStyleBorder();
         233               0 :       switch (borderStyle->mFloatEdge) {
         234                 :         default:
         235                 :         case NS_STYLE_FLOAT_EDGE_CONTENT:  // content and only content does runaround of floats
         236                 :           // The child block will flow around the float. Therefore
         237                 :           // give it all of the available space.
         238               0 :           aResult.x = mContentArea.x;
         239               0 :           aResult.width = mContentArea.width;
         240               0 :           break;
         241                 :         case NS_STYLE_FLOAT_EDGE_MARGIN:
         242                 :           {
         243                 :             // The child block's margins should be placed adjacent to,
         244                 :             // but not overlap the float.
         245               0 :             aResult.x = aFloatAvailableSpace.mRect.x;
         246               0 :             aResult.width = aFloatAvailableSpace.mRect.width;
         247                 :           }
         248               0 :           break;
         249                 :       }
         250                 :     }
         251                 :     else {
         252                 :       // Since there are no floats present the float-edge property
         253                 :       // doesn't matter therefore give the block element all of the
         254                 :       // available space since it will flow around the float itself.
         255               0 :       aResult.x = mContentArea.x;
         256               0 :       aResult.width = mContentArea.width;
         257                 :     }
         258                 :   }
         259                 :   else {
         260                 :     nscoord leftOffset, rightOffset;
         261                 :     ComputeReplacedBlockOffsetsForFloats(aFrame, aFloatAvailableSpace.mRect,
         262               0 :                                          leftOffset, rightOffset);
         263               0 :     aResult.x = mContentArea.x + leftOffset;
         264               0 :     aResult.width = mContentArea.width - leftOffset - rightOffset;
         265                 :   }
         266                 :
         267                 : #ifdef REALLY_NOISY_REFLOW
         268                 :   printf("  CBAS: result %d %d %d %d\n", aResult.x, aResult.y, aResult.width, aResult.height);
         269                 : #endif
         270               0 : }
         271                 :
         272                 : nsFlowAreaRect
         273               0 : nsBlockReflowState::GetFloatAvailableSpaceWithState(
         274                 :                       nscoord aY,
         275                 :                       nsFloatManager::SavedState *aState) const
         276                 : {
         277                 : #ifdef DEBUG
         278                 :   // Verify that the caller setup the coordinate system properly
         279                 :   nscoord wx, wy;
         280               0 :   mFloatManager->GetTranslation(wx, wy);
         281               0 :   NS_ASSERTION((wx == mFloatManagerX) && (wy == mFloatManagerY),
         282                 :                "bad coord system");
         283                 : #endif
         284                 :
         285                 :   nscoord height = (mContentArea.height == nscoord_MAX)
         286               0 :                      ? nscoord_MAX : NS_MAX(mContentArea.YMost() - aY, 0);
         287                 :   nsFlowAreaRect result =
         288                 :     mFloatManager->GetFlowArea(aY, nsFloatManager::BAND_FROM_POINT,
         289               0 :                                height, mContentArea, aState);
         290                 :   // Keep the width >= 0 for compatibility with nsSpaceManager.
         291               0 :   if (result.mRect.width < 0)
         292               0 :     result.mRect.width = 0;
         293                 :
         294                 : #ifdef DEBUG
         295               0 :   if (nsBlockFrame::gNoisyReflow) {
         296               0 :     nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
         297                 :     printf("GetAvailableSpace: band=%d,%d,%d,%d hasfloats=%d\n",
         298                 :            result.mRect.x, result.mRect.y, result.mRect.width,
         299               0 :            result.mRect.height, result.mHasFloats);
         300                 :   }
         301                 : #endif
         302                 :   return result;
         303                 : }
         304                 :
         305                 : nsFlowAreaRect
         306               0 : nsBlockReflowState::GetFloatAvailableSpaceForHeight(
         307                 :                       nscoord aY, nscoord aHeight,
         308                 :                       nsFloatManager::SavedState *aState) const
         309                 : {
         310                 : #ifdef DEBUG
         311                 :   // Verify that the caller setup the coordinate system properly
         312                 :   nscoord wx, wy;
         313               0 :   mFloatManager->GetTranslation(wx, wy);
         314               0 :   NS_ASSERTION((wx == mFloatManagerX) && (wy == mFloatManagerY),
         315                 :                "bad coord system");
         316                 : #endif
         317                 :
         318                 :   nsFlowAreaRect result =
         319                 :     mFloatManager->GetFlowArea(aY, nsFloatManager::WIDTH_WITHIN_HEIGHT,
         320               0 :                                aHeight, mContentArea, aState);
         321                 :   // Keep the width >= 0 for compatibility with nsSpaceManager.
         322               0 :   if (result.mRect.width < 0)
         323               0 :     result.mRect.width = 0;
         324                 :
         325                 : #ifdef DEBUG
         326               0 :   if (nsBlockFrame::gNoisyReflow) {
         327               0 :     nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
         328                 :     printf("GetAvailableSpaceForHeight: space=%d,%d,%d,%d hasfloats=%d\n",
         329                 :            result.mRect.x, result.mRect.y, result.mRect.width,
         330               0 :            result.mRect.height, result.mHasFloats);
         331                 :   }
         332                 : #endif
         333                 :   return result;
         334                 : }
         335                 :
         336                 : /*
         337                 :  * Reconstruct the vertical margin before the line |aLine| in order to
         338                 :  * do an incremental reflow that begins with |aLine| without reflowing
         339                 :  * the line before it.  |aLine| may point to the fencepost at the end of
         340                 :  * the line list, and it is used this way since we (for now, anyway)
         341                 :  * always need to recover margins at the end of a block.
         342                 :  *
         343                 :  * The reconstruction involves walking backward through the line list to
         344                 :  * find any collapsed margins preceding the line that would have been in
         345                 :  * the reflow state's |mPrevBottomMargin| when we reflowed that line in
         346                 :  * a full reflow (under the rule in CSS2 that all adjacent vertical
         347                 :  * margins of blocks collapse).
         348                 :  */
         349                 : void
         350               0 : nsBlockReflowState::ReconstructMarginAbove(nsLineList::iterator aLine)
         351                 : {
         352               0 :   mPrevBottomMargin.Zero();
         353               0 :   nsBlockFrame *block = mBlock;
         354                 :
         355               0 :   nsLineList::iterator firstLine = block->begin_lines();
         356               0 :   for (;;) {
         357               0 :     --aLine;
         358               0 :     if (aLine->IsBlock()) {
         359               0 :       mPrevBottomMargin = aLine->GetCarriedOutBottomMargin();
         360               0 :       break;
         361                 :     }
         362               0 :     if (!aLine->IsEmpty()) {
         363               0 :       break;
         364                 :     }
         365               0 :     if (aLine == firstLine) {
         366                 :       // If the top margin was carried out (and thus already applied),
         367                 :       // set it to zero.  Either way, we're done.
         368               0 :       if (!GetFlag(BRS_ISTOPMARGINROOT)) {
         369               0 :         mPrevBottomMargin.Zero();
         370                 :       }
         371               0 :       break;
         372                 :     }
         373                 :   }
         374               0 : }
         375                 :
         376                 : void
         377               0 : nsBlockReflowState::SetupPushedFloatList()
         378                 : {
         379               0 :   NS_ABORT_IF_FALSE(!GetFlag(BRS_PROPTABLE_FLOATCLIST) == !mPushedFloats,
         380                 :                     "flag mismatch");
         381               0 :   if (!GetFlag(BRS_PROPTABLE_FLOATCLIST)) {
         382                 :     // If we're being re-Reflow'd without our next-in-flow having been
         383                 :     // reflowed, some pushed floats from our previous reflow might
         384                 :     // still be on our pushed floats list.  However, that's
         385                 :     // actually fine, since they'll all end up being stolen and
         386                 :     // reordered into the correct order again.
         387                 :     // (nsBlockFrame::ReflowDirtyLines ensures that any lines with
         388                 :     // pushed floats are reflowed.)
         389               0 :     mPushedFloats = mBlock->EnsurePushedFloats();
         390               0 :     SetFlag(BRS_PROPTABLE_FLOATCLIST, true);
         391                 :   }
         392               0 : }
         393                 :
         394                 : /**
         395                 :  * Restore information about floats into the float manager for an
         396                 :  * incremental reflow, and simultaneously push the floats by
         397                 :  * |aDeltaY|, which is the amount |aLine| was pushed relative to its
         398                 :  * parent.  The recovery of state is one of the things that makes
         399                 :  * incremental reflow O(N^2) and this state should really be kept
         400                 :  * around, attached to the frame tree.
         401                 :  */
         402                 : void
         403               0 : nsBlockReflowState::RecoverFloats(nsLineList::iterator aLine,
         404                 :                                   nscoord aDeltaY)
         405                 : {
         406               0 :   if (aLine->HasFloats()) {
         407                 :     // Place the floats into the space-manager again. Also slide
         408                 :     // them, just like the regular frames on the line.
         409               0 :     nsFloatCache* fc = aLine->GetFirstFloat();
         410               0 :     while (fc) {
         411               0 :       nsIFrame* floatFrame = fc->mFloat;
         412               0 :       if (aDeltaY != 0) {
         413               0 :         nsPoint p = floatFrame->GetPosition();
         414               0 :         floatFrame->SetPosition(nsPoint(p.x, p.y + aDeltaY));
         415               0 :         nsContainerFrame::PositionFrameView(floatFrame);
         416               0 :         nsContainerFrame::PositionChildViews(floatFrame);
         417                 :       }
         418                 : #ifdef DEBUG
         419               0 :       if (nsBlockFrame::gNoisyReflow || nsBlockFrame::gNoisyFloatManager) {
         420                 :         nscoord tx, ty;
         421               0 :         mFloatManager->GetTranslation(tx, ty);
         422               0 :         nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
         423                 :         printf("RecoverFloats: txy=%d,%d (%d,%d) ",
         424               0 :                tx, ty, mFloatManagerX, mFloatManagerY);
         425               0 :         nsFrame::ListTag(stdout, floatFrame);
         426               0 :         nsRect region = nsFloatManager::GetRegionFor(floatFrame);
         427                 :         printf(" aDeltaY=%d region={%d,%d,%d,%d}\n",
         428               0 :                aDeltaY, region.x, region.y, region.width, region.height);
         429                 :       }
         430                 : #endif
         431                 :       mFloatManager->AddFloat(floatFrame,
         432               0 :                               nsFloatManager::GetRegionFor(floatFrame));
         433               0 :       fc = fc->Next();
         434                 :     }
         435               0 :   } else if (aLine->IsBlock()) {
         436               0 :     nsBlockFrame::RecoverFloatsFor(aLine->mFirstChild, *mFloatManager);
         437                 :   }
         438               0 : }
         439                 :
         440                 : /**
         441                 :  * Everything done in this function is done O(N) times for each pass of
         442                 :  * reflow so it is O(N*M) where M is the number of incremental reflow
         443                 :  * passes.  That's bad.  Don't do stuff here.
         444                 :  *
         445                 :  * When this function is called, |aLine| has just been slid by |aDeltaY|
         446                 :  * and the purpose of RecoverStateFrom is to ensure that the
         447                 :  * nsBlockReflowState is in the same state that it would have been in
         448                 :  * had the line just been reflowed.
         449                 :  *
         450                 :  * Most of the state recovery that we have to do involves floats.
         451                 :  */
         452                 : void
         453               0 : nsBlockReflowState::RecoverStateFrom(nsLineList::iterator aLine,
         454                 :                                      nscoord aDeltaY)
         455                 : {
         456                 :   // Make the line being recovered the current line
         457               0 :   mCurrentLine = aLine;
         458                 :
         459                 :   // Place floats for this line into the float manager
         460               0 :   if (aLine->HasFloats() || aLine->IsBlock()) {
         461               0 :     RecoverFloats(aLine, aDeltaY);
         462                 :
         463                 : #ifdef DEBUG
         464               0 :     if (nsBlockFrame::gNoisyReflow || nsBlockFrame::gNoisyFloatManager) {
         465               0 :       mFloatManager->List(stdout);
         466                 :     }
         467                 : #endif
         468                 :   }
         469               0 : }
         470                 :
         471                 : // This is called by the line layout's AddFloat method when a
         472                 : // place-holder frame is reflowed in a line. If the float is a
         473                 : // left-most child (it's x coordinate is at the line's left margin)
         474                 : // then the float is place immediately, otherwise the float
         475                 : // placement is deferred until the line has been reflowed.
         476                 :
         477                 : // XXXldb This behavior doesn't quite fit with CSS1 and CSS2 --
         478                 : // technically we're supposed let the current line flow around the
         479                 : // float as well unless it won't fit next to what we already have.
         480                 : // But nobody else implements it that way...
         481                 : bool
         482               0 : nsBlockReflowState::AddFloat(nsLineLayout*       aLineLayout,
         483                 :                              nsIFrame*           aFloat,
         484                 :                              nscoord             aAvailableWidth)
         485                 : {
         486               0 :   NS_PRECONDITION(aLineLayout, "must have line layout");
         487               0 :   NS_PRECONDITION(mBlock->end_lines() != mCurrentLine, "null ptr");
         488               0 :   NS_PRECONDITION(aFloat->GetStateBits() & NS_FRAME_OUT_OF_FLOW,
         489                 :                   "aFloat must be an out-of-flow frame");
         490                 :
         491               0 :   NS_ABORT_IF_FALSE(aFloat->GetParent(), "float must have parent");
         492               0 :   NS_ABORT_IF_FALSE(aFloat->GetParent()->IsFrameOfType(nsIFrame::eBlockFrame),
         493                 :                     "float's parent must be block");
         494               0 :   NS_ABORT_IF_FALSE(aFloat->GetParent() == mBlock ||
         495                 :                     (aFloat->GetStateBits() & NS_FRAME_IS_PUSHED_FLOAT),
         496                 :                     "float should be in this block unless it was marked as "
         497                 :                     "pushed float");
         498               0 :   if (aFloat->GetStateBits() & NS_FRAME_IS_PUSHED_FLOAT) {
         499                 :     // If, in a previous reflow, the float was pushed entirely to
         500                 :     // another column/page, we need to steal it back.  (We might just
         501                 :     // push it again, though.)  Likewise, if that previous reflow
         502                 :     // reflowed this block but not its next continuation, we might need
         503                 :     // to steal it from our own float-continuations list.
         504                 :     nsBlockFrame *floatParent =
         505               0 :       static_cast<nsBlockFrame*>(aFloat->GetParent());
         506               0 :     floatParent->StealFrame(mPresContext, aFloat);
         507                 :
         508               0 :     aFloat->RemoveStateBits(NS_FRAME_IS_PUSHED_FLOAT);
         509                 :
         510                 :     // Appending is fine, since if a float was pushed to the next
         511                 :     // page/column, all later floats were also pushed.
         512               0 :     mBlock->mFloats.AppendFrame(mBlock, aFloat);
         513                 :   }
         514                 :
         515                 :   // Because we are in the middle of reflowing a placeholder frame
         516                 :   // within a line (and possibly nested in an inline frame or two
         517                 :   // that's a child of our block) we need to restore the space
         518                 :   // manager's translation to the space that the block resides in
         519                 :   // before placing the float.
         520                 :   nscoord ox, oy;
         521               0 :   mFloatManager->GetTranslation(ox, oy);
         522               0 :   nscoord dx = ox - mFloatManagerX;
         523               0 :   nscoord dy = oy - mFloatManagerY;
         524               0 :   mFloatManager->Translate(-dx, -dy);
         525                 :
         526                 :   bool placed;
         527                 :
         528                 :   // Now place the float immediately if possible. Otherwise stash it
         529                 :   // away in mPendingFloats and place it later.
         530                 :   // If one or more floats has already been pushed to the next line,
         531                 :   // don't let this one go on the current line, since that would violate
         532                 :   // float ordering.
         533               0 :   nsRect floatAvailableSpace = GetFloatAvailableSpace().mRect;
         534               0 :   if (mBelowCurrentLineFloats.IsEmpty() &&
         535               0 :       (aLineLayout->LineIsEmpty() ||
         536               0 :        mBlock->ComputeFloatWidth(*this, floatAvailableSpace, aFloat)
         537                 :        <= aAvailableWidth)) {
         538                 :     // And then place it
         539               0 :     placed = FlowAndPlaceFloat(aFloat);
         540               0 :     if (placed) {
         541                 :       // Pass on updated available space to the current inline reflow engine
         542               0 :       nsFlowAreaRect floatAvailSpace = GetFloatAvailableSpace(mY);
         543                 :       nsRect availSpace(nsPoint(floatAvailSpace.mRect.x, mY),
         544               0 :                         floatAvailSpace.mRect.Size());
         545               0 :       aLineLayout->UpdateBand(availSpace, aFloat);
         546                 :       // Record this float in the current-line list
         547               0 :       mCurrentLineFloats.Append(mFloatCacheFreeList.Alloc(aFloat));
         548                 :     } else {
         549               0 :       (*aLineLayout->GetLine())->SetHadFloatPushed();
         550                 :     }
         551                 :   }
         552                 :   else {
         553                 :     // Always claim to be placed; we don't know whether we fit yet, so we
         554                 :     // deal with this in PlaceBelowCurrentLineFloats
         555               0 :     placed = true;
         556                 :     // This float will be placed after the line is done (it is a
         557                 :     // below-current-line float).
         558               0 :     mBelowCurrentLineFloats.Append(mFloatCacheFreeList.Alloc(aFloat));
         559                 :   }
         560                 :
         561                 :   // Restore coordinate system
         562               0 :   mFloatManager->Translate(dx, dy);
         563                 :
         564               0 :   return placed;
         565                 : }
         566                 :
         567                 : bool
         568               0 : nsBlockReflowState::CanPlaceFloat(nscoord aFloatWidth,
         569                 :                                   const nsFlowAreaRect& aFloatAvailableSpace)
         570                 : {
         571                 :   // A float fits at a given vertical position if there are no floats at
         572                 :   // its horizontal position (no matter what its width) or if its width
         573                 :   // fits in the space remaining after prior floats have been placed.
         574                 :   // FIXME: We should allow overflow by up to half a pixel here (bug 21193).
         575               0 :   return !aFloatAvailableSpace.mHasFloats ||
         576               0 :          aFloatAvailableSpace.mRect.width >= aFloatWidth;
         577                 : }
         578                 :
         579                 : static nscoord
         580               0 : FloatMarginWidth(const nsHTMLReflowState& aCBReflowState,
         581                 :                  nscoord aFloatAvailableWidth,
         582                 :                  nsIFrame *aFloat,
         583                 :                  const nsCSSOffsetState& aFloatOffsetState)
         584                 : {
         585               0 :   AutoMaybeNullInflationContainer an(aFloat);
         586                 :   return aFloat->ComputeSize(
         587                 :     aCBReflowState.rendContext,
         588                 :     nsSize(aCBReflowState.ComputedWidth(),
         589                 :            aCBReflowState.ComputedHeight()),
         590                 :     aFloatAvailableWidth,
         591                 :     nsSize(aFloatOffsetState.mComputedMargin.LeftRight(),
         592                 :            aFloatOffsetState.mComputedMargin.TopBottom()),
         593               0 :     nsSize(aFloatOffsetState.mComputedBorderPadding.LeftRight() -
         594               0 :              aFloatOffsetState.mComputedPadding.LeftRight(),
         595               0 :            aFloatOffsetState.mComputedBorderPadding.TopBottom() -
         596               0 :              aFloatOffsetState.mComputedPadding.TopBottom()),
         597                 :     nsSize(aFloatOffsetState.mComputedPadding.LeftRight(),
         598                 :            aFloatOffsetState.mComputedPadding.TopBottom()),
         599               0 :     true).width +
         600               0 :   aFloatOffsetState.mComputedMargin.LeftRight() +
         601               0 :   aFloatOffsetState.mComputedBorderPadding.LeftRight();
         602                 : }
         603                 :
         604                 : bool
         605               0 : nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
         606                 : {
         607                 :   // Save away the Y coordinate before placing the float. We will
         608                 :   // restore mY at the end after placing the float. This is
         609                 :   // necessary because any adjustments to mY during the float
         610                 :   // placement are for the float only, not for any non-floating
         611                 :   // content.
         612               0 :   AutoRestore<nscoord> restoreY(mY);
         613                 :   // FIXME: Should give AutoRestore a getter for the value to avoid this.
         614               0 :   const nscoord saveY = mY;
         615                 :
         616                 :   // Grab the float's display information
         617               0 :   const nsStyleDisplay* floatDisplay = aFloat->GetStyleDisplay();
         618                 :
         619                 :   // The float's old region, so we can propagate damage.
         620               0 :   nsRect oldRegion = nsFloatManager::GetRegionFor(aFloat);
         621                 :
         622                 :   // Enforce CSS2 9.5.1 rule [2], i.e., make sure that a float isn't
         623                 :   // ``above'' another float that preceded it in the flow.
         624               0 :   mY = NS_MAX(mFloatManager->GetLowestFloatTop(), mY);
         625                 :
         626                 :   // See if the float should clear any preceding floats...
         627                 :   // XXX We need to mark this float somehow so that it gets reflowed
         628                 :   // when floats are inserted before it.
         629               0 :   if (NS_STYLE_CLEAR_NONE != floatDisplay->mBreakType) {
         630                 :     // XXXldb Does this handle vertical margins correctly?
         631               0 :     mY = ClearFloats(mY, floatDisplay->mBreakType);
         632                 :   }
         633                 :     // Get the band of available space
         634               0 :   nsFlowAreaRect floatAvailableSpace = GetFloatAvailableSpace(mY);
         635                 :   nsRect adjustedAvailableSpace = mBlock->AdjustFloatAvailableSpace(*this,
         636               0 :                                     floatAvailableSpace.mRect, aFloat);
         637                 :
         638               0 :   NS_ASSERTION(aFloat->GetParent() == mBlock,
         639                 :                "Float frame has wrong parent");
         640                 :
         641                 :   nsCSSOffsetState offsets(aFloat, mReflowState.rendContext,
         642               0 :                            mReflowState.ComputedWidth());
         643                 :
         644                 :   nscoord floatMarginWidth = FloatMarginWidth(mReflowState,
         645                 :                                               adjustedAvailableSpace.width,
         646               0 :                                               aFloat, offsets);
         647                 :
         648               0 :   nsMargin floatMargin; // computed margin
         649                 :   nsReflowStatus reflowStatus;
         650                 :
         651                 :   // If it's a floating first-letter, we need to reflow it before we
         652                 :   // know how wide it is (since we don't compute which letters are part
         653                 :   // of the first letter until reflow!).
         654               0 :   bool isLetter = aFloat->GetType() == nsGkAtoms::letterFrame;
         655               0 :   if (isLetter) {
         656                 :     mBlock->ReflowFloat(*this, adjustedAvailableSpace, aFloat,
         657               0 :                         floatMargin, false, reflowStatus);
         658               0 :     floatMarginWidth = aFloat->GetSize().width + floatMargin.LeftRight();
         659               0 :     NS_ASSERTION(NS_FRAME_IS_COMPLETE(reflowStatus),
         660                 :                  "letter frames shouldn't break, and if they do now, "
         661                 :                  "then they're breaking at the wrong point");
         662                 :   }
         663                 :
         664                 :   // Find a place to place the float. The CSS2 spec doesn't want
         665                 :   // floats overlapping each other or sticking out of the containing
         666                 :   // block if possible (CSS2 spec section 9.5.1, see the rule list).
         667               0 :   NS_ASSERTION((NS_STYLE_FLOAT_LEFT == floatDisplay->mFloats) ||
         668                 :                (NS_STYLE_FLOAT_RIGHT == floatDisplay->mFloats),
         669                 :                "invalid float type");
         670                 :
         671                 :   // Can the float fit here?
         672               0 :   bool keepFloatOnSameLine = false;
         673                 :
         674                 :   // Are we required to place at least part of the float because we're
         675                 :   // at the top of the page (to avoid an infinite loop of pushing and
         676                 :   // breaking).
         677                 :   bool mustPlaceFloat =
         678               0 :     mReflowState.mFlags.mIsTopOfPage && IsAdjacentWithTop();
         679                 :
         680               0 :   for (;;) {
         681               0 :     if (mReflowState.availableHeight != NS_UNCONSTRAINEDSIZE &&
         682                 :         floatAvailableSpace.mRect.height <= 0 &&
         683               0 :         !mustPlaceFloat) {
         684                 :       // No space, nowhere to put anything.
         685               0 :       PushFloatPastBreak(aFloat);
         686               0 :       return false;
         687                 :     }
         688                 :
         689               0 :     if (CanPlaceFloat(floatMarginWidth, floatAvailableSpace)) {
         690                 :       // We found an appropriate place.
         691               0 :       break;
         692                 :     }
         693                 :
         694                 :     // Nope. try to advance to the next band.
         695               0 :     if (NS_STYLE_DISPLAY_TABLE != floatDisplay->mDisplay ||
         696               0 :           eCompatibility_NavQuirks != mPresContext->CompatibilityMode() ) {
         697                 :
         698               0 :       mY += floatAvailableSpace.mRect.height;
         699               0 :       if (adjustedAvailableSpace.height != NS_UNCONSTRAINEDSIZE) {
         700               0 :         adjustedAvailableSpace.height -= floatAvailableSpace.mRect.height;
         701                 :       }
         702               0 :       floatAvailableSpace = GetFloatAvailableSpace(mY);
         703                 :     } else {
         704                 :       // This quirk matches the one in nsBlockFrame::AdjustFloatAvailableSpace
         705                 :       // IE handles float tables in a very special way
         706                 :
         707                 :       // see if the previous float is also a table and has "align"
         708               0 :       nsFloatCache* fc = mCurrentLineFloats.Head();
         709               0 :       nsIFrame* prevFrame = nsnull;
         710               0 :       while (fc) {
         711               0 :         if (fc->mFloat == aFloat) {
         712               0 :           break;
         713                 :         }
         714               0 :         prevFrame = fc->mFloat;
         715               0 :         fc = fc->Next();
         716                 :       }
         717                 :
         718               0 :       if(prevFrame) {
         719                 :         //get the frame type
         720               0 :         if (nsGkAtoms::tableOuterFrame == prevFrame->GetType()) {
         721                 :           //see if it has "align="
         722                 :           // IE makes a difference between align and he float property
         723               0 :           nsIContent* content = prevFrame->GetContent();
         724               0 :           if (content) {
         725                 :             // we're interested only if previous frame is align=left
         726                 :             // IE messes things up when "right" (overlapping frames)
         727               0 :             if (content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::align,
         728               0 :                                      NS_LITERAL_STRING("left"), eIgnoreCase)) {
         729               0 :               keepFloatOnSameLine = true;
         730                 :               // don't advance to next line (IE quirkie behaviour)
         731                 :               // it breaks rule CSS2/9.5.1/1, but what the hell
         732                 :               // since we cannot evangelize the world
         733               0 :               break;
         734                 :             }
         735                 :           }
         736                 :         }
         737                 :       }
         738                 :
         739                 :       // the table does not fit anymore in this line so advance to next band
         740               0 :       mY += floatAvailableSpace.mRect.height;
         741                 :       // To match nsBlockFrame::AdjustFloatAvailableSpace, we have to
         742                 :       // get a new width for the new band.
         743               0 :       floatAvailableSpace = GetFloatAvailableSpace(mY);
         744                 :       adjustedAvailableSpace = mBlock->AdjustFloatAvailableSpace(*this,
         745               0 :                                  floatAvailableSpace.mRect, aFloat);
         746                 :       floatMarginWidth = FloatMarginWidth(mReflowState,
         747                 :                                           adjustedAvailableSpace.width,
         748               0 :                                           aFloat, offsets);
         749                 :     }
         750                 :
         751               0 :     mustPlaceFloat = false;
         752                 :   }
         753                 :
         754                 :   // If the float is continued, it will get the same absolute x value as its prev-in-flow
         755                 :
         756                 :   // We don't worry about the geometry of the prev in flow, let the continuation
         757                 :   // place and size itself as required.
         758                 :
         759                 :   // Assign an x and y coordinate to the float.
         760                 :   nscoord floatX, floatY;
         761               0 :   if (NS_STYLE_FLOAT_LEFT == floatDisplay->mFloats) {
         762               0 :     floatX = floatAvailableSpace.mRect.x;
         763                 :   }
         764                 :   else {
         765               0 :     if (!keepFloatOnSameLine) {
         766               0 :       floatX = floatAvailableSpace.mRect.XMost() - floatMarginWidth;
         767                 :     }
         768                 :     else {
         769                 :       // this is the IE quirk (see few lines above)
         770                 :       // the table is kept in the same line: don't let it overlap the
         771                 :       // previous float
         772               0 :       floatX = floatAvailableSpace.mRect.x;
         773                 :     }
         774                 :   }
         775                 :   // CSS2 spec, 9.5.1 rule [4]: "A floating box's outer top may not
         776                 :   // be higher than the top of its containing block."  (Since the
         777                 :   // containing block is the content edge of the block box, this
         778                 :   // means the margin edge of the float can't be higher than the
         779                 :   // content edge of the block that contains it.)
         780               0 :   floatY = NS_MAX(mY, mContentArea.y);
         781                 :
         782                 :   // Reflow the float after computing its vertical position so it knows
         783                 :   // where to break.
         784               0 :   if (!isLetter) {
         785               0 :     bool pushedDown = mY != saveY;
         786                 :     mBlock->ReflowFloat(*this, adjustedAvailableSpace, aFloat,
         787               0 :                         floatMargin, pushedDown, reflowStatus);
         788                 :   }
         789               0 :   if (aFloat->GetPrevInFlow())
         790               0 :     floatMargin.top = 0;
         791               0 :   if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus))
         792               0 :     floatMargin.bottom = 0;
         793                 :
         794                 :   // In the case that we're in columns and not splitting floats, we need
         795                 :   // to check here that the float's height fit, and if it didn't, bail.
         796                 :   // (This code is only for DISABLE_FLOAT_BREAKING_IN_COLUMNS .)
         797                 :   //
         798                 :   // Likewise, if none of the float fit, and it needs to be pushed in
         799                 :   // its entirety to the next page (NS_FRAME_IS_TRUNCATED), we need to
         800                 :   // do the same.
         801               0 :   if ((mContentArea.height != NS_UNCONSTRAINEDSIZE &&
         802                 :        adjustedAvailableSpace.height == NS_UNCONSTRAINEDSIZE &&
         803               0 :        !mustPlaceFloat &&
         804               0 :        aFloat->GetSize().height + floatMargin.TopBottom() >
         805               0 :          mContentArea.YMost() - floatY) ||
         806                 :       NS_FRAME_IS_TRUNCATED(reflowStatus)) {
         807                 :
         808               0 :     PushFloatPastBreak(aFloat);
         809               0 :     return false;
         810                 :   }
         811                 :
         812                 :   // Calculate the actual origin of the float frame's border rect
         813                 :   // relative to the parent block; the margin must be added in
         814                 :   // to get the border rect
         815                 :   nsPoint origin(floatMargin.left + floatX,
         816               0 :                  floatMargin.top + floatY);
         817                 :
         818                 :   // If float is relatively positioned, factor that in as well
         819               0 :   origin += aFloat->GetRelativeOffset(floatDisplay);
         820                 :
         821                 :   // Position the float and make sure and views are properly
         822                 :   // positioned. We need to explicitly position its child views as
         823                 :   // well, since we're moving the float after flowing it.
         824               0 :   bool moved = aFloat->GetPosition() != origin;
         825               0 :   if (moved) {
         826               0 :     aFloat->SetPosition(origin);
         827               0 :     nsContainerFrame::PositionFrameView(aFloat);
         828               0 :     nsContainerFrame::PositionChildViews(aFloat);
         829               0 :     FrameLayerBuilder::InvalidateThebesLayersInSubtree(aFloat);
         830                 :   }
         831                 :
         832                 :   // Update the float combined area state
         833                 :   // XXX Floats should really just get invalidated here if necessary
         834               0 :   mFloatOverflowAreas.UnionWith(aFloat->GetOverflowAreas() + origin);
         835                 :
         836                 :   // Place the float in the float manager
         837                 :   // calculate region
         838               0 :   nsRect region = nsFloatManager::CalculateRegionFor(aFloat, floatMargin);
         839                 :   // if the float split, then take up all of the vertical height
         840               0 :   if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus) &&
         841                 :       (NS_UNCONSTRAINEDSIZE != mContentArea.height)) {
         842               0 :     region.height = NS_MAX(region.height, mContentArea.height - floatY);
         843                 :   }
         844                 :   nsresult rv =
         845               0 :   mFloatManager->AddFloat(aFloat, region);
         846               0 :   NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "bad float placement");
         847                 :   // store region
         848               0 :   nsFloatManager::StoreRegionFor(aFloat, region);
         849                 :
         850                 :   // If the float's dimensions have changed, note the damage in the
         851                 :   // float manager.
         852               0 :   if (!region.IsEqualEdges(oldRegion)) {
         853                 :     // XXXwaterson conservative: we could probably get away with noting
         854                 :     // less damage; e.g., if only height has changed, then only note the
         855                 :     // area into which the float has grown or from which the float has
         856                 :     // shrunk.
         857               0 :     nscoord top = NS_MIN(region.y, oldRegion.y);
         858               0 :     nscoord bottom = NS_MAX(region.YMost(), oldRegion.YMost());
         859               0 :     mFloatManager->IncludeInDamage(top, bottom);
         860                 :   }
         861                 :
         862               0 :   if (!NS_FRAME_IS_FULLY_COMPLETE(reflowStatus)) {
         863               0 :     mBlock->SplitFloat(*this, aFloat, reflowStatus);
         864                 :   }
         865                 :
         866                 : #ifdef NOISY_FLOATMANAGER
         867                 :   nscoord tx, ty;
         868                 :   mFloatManager->GetTranslation(tx, ty);
         869                 :   nsFrame::ListTag(stdout, mBlock);
         870                 :   printf(": FlowAndPlaceFloat: AddFloat: txy=%d,%d (%d,%d) {%d,%d,%d,%d}\n",
         871                 :          tx, ty, mFloatManagerX, mFloatManagerY,
         872                 :          region.x, region.y, region.width, region.height);
         873                 : #endif
         874                 :
         875                 : #ifdef DEBUG
         876               0 :   if (nsBlockFrame::gNoisyReflow) {
         877               0 :     nsRect r = aFloat->GetRect();
         878               0 :     nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
         879               0 :     printf("placed float: ");
         880               0 :     nsFrame::ListTag(stdout, aFloat);
         881               0 :     printf(" %d,%d,%d,%d\n", r.x, r.y, r.width, r.height);
         882                 :   }
         883                 : #endif
         884                 :
         885               0 :   return true;
         886                 : }
         887                 :
         888                 : void
         889               0 : nsBlockReflowState::PushFloatPastBreak(nsIFrame *aFloat)
         890                 : {
         891                 :   // This ensures that we:
         892                 :   //  * don't try to place later but smaller floats (which CSS says
         893                 :   //    must have their tops below the top of this float)
         894                 :   //  * don't waste much time trying to reflow this float again until
         895                 :   //    after the break
         896               0 :   if (aFloat->GetStyleDisplay()->mFloats == NS_STYLE_FLOAT_LEFT) {
         897               0 :     mFloatManager->SetPushedLeftFloatPastBreak();
         898                 :   } else {
         899               0 :     NS_ABORT_IF_FALSE(aFloat->GetStyleDisplay()->mFloats ==
         900                 :                         NS_STYLE_FLOAT_RIGHT,
         901                 :                       "unexpected float value");
         902               0 :     mFloatManager->SetPushedRightFloatPastBreak();
         903                 :   }
         904                 :
         905                 :   // Put the float on the pushed floats list, even though it
         906                 :   // isn't actually a continuation.
         907               0 :   DebugOnly<nsresult> rv = mBlock->StealFrame(mPresContext, aFloat);
         908               0 :   NS_ASSERTION(NS_SUCCEEDED(rv), "StealFrame should succeed");
         909               0 :   AppendPushedFloat(aFloat);
         910                 :
         911               0 :   NS_FRAME_SET_OVERFLOW_INCOMPLETE(mReflowStatus);
         912               0 : }
         913                 :
         914                 : /**
         915                 :  * Place below-current-line floats.
         916                 :  */
         917                 : void
         918               0 : nsBlockReflowState::PlaceBelowCurrentLineFloats(nsFloatCacheFreeList& aList,
         919                 :                                                 nsLineBox* aLine)
         920                 : {
         921               0 :   nsFloatCache* fc = aList.Head();
         922               0 :   while (fc) {
         923                 : #ifdef DEBUG
         924               0 :     if (nsBlockFrame::gNoisyReflow) {
         925               0 :       nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
         926               0 :       printf("placing bcl float: ");
         927               0 :       nsFrame::ListTag(stdout, fc->mFloat);
         928               0 :       printf("\n");
         929                 :     }
         930                 : #endif
         931                 :     // Place the float
         932               0 :     bool placed = FlowAndPlaceFloat(fc->mFloat);
         933               0 :     nsFloatCache *next = fc->Next();
         934               0 :     if (!placed) {
         935               0 :       aList.Remove(fc);
         936               0 :       delete fc;
         937               0 :       aLine->SetHadFloatPushed();
         938                 :     }
         939               0 :     fc = next;
         940                 :   }
         941               0 : }
         942                 :
         943                 : nscoord
         944               0 : nsBlockReflowState::ClearFloats(nscoord aY, PRUint8 aBreakType,
         945                 :                                 nsIFrame *aReplacedBlock,
         946                 :                                 PRUint32 aFlags)
         947                 : {
         948                 : #ifdef DEBUG
         949               0 :   if (nsBlockFrame::gNoisyReflow) {
         950               0 :     nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
         951               0 :     printf("clear floats: in: aY=%d\n", aY);
         952                 :   }
         953                 : #endif
         954                 :
         955                 : #ifdef NOISY_FLOAT_CLEARING
         956                 :   printf("nsBlockReflowState::ClearFloats: aY=%d breakType=%d\n",
         957                 :          aY, aBreakType);
         958                 :   mFloatManager->List(stdout);
         959                 : #endif
         960                 :
         961               0 :   nscoord newY = aY;
         962                 :
         963               0 :   if (aBreakType != NS_STYLE_CLEAR_NONE) {
         964               0 :     newY = mFloatManager->ClearFloats(newY, aBreakType, aFlags);
         965                 :   }
         966                 :
         967               0 :   if (aReplacedBlock) {
         968               0 :     for (;;) {
         969               0 :       nsFlowAreaRect floatAvailableSpace = GetFloatAvailableSpace(newY);
         970                 :       nsBlockFrame::ReplacedElementWidthToClear replacedWidth =
         971                 :         nsBlockFrame::WidthToClearPastFloats(*this, floatAvailableSpace.mRect,
         972               0 :                                              aReplacedBlock);
         973               0 :       if (!floatAvailableSpace.mHasFloats ||
         974                 :           NS_MAX(floatAvailableSpace.mRect.x - mContentArea.x,
         975               0 :                  replacedWidth.marginLeft) +
         976                 :             replacedWidth.borderBoxWidth +
         977               0 :             NS_MAX(mContentArea.XMost() - floatAvailableSpace.mRect.XMost(),
         978               0 :                    replacedWidth.marginRight) <=
         979                 :           mContentArea.width) {
         980                 :         break;
         981                 :       }
         982                 :       // See the analogous code for inlines in nsBlockFrame::DoReflowInlineFrames
         983               0 :       if (floatAvailableSpace.mRect.height > 0) {
         984                 :         // See if there's room in the next band.
         985               0 :         newY += floatAvailableSpace.mRect.height;
         986                 :       } else {
         987               0 :         if (mReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) {
         988                 :           // Stop trying to clear here; we'll just get pushed to the
         989                 :           // next column or page and try again there.
         990                 :           break;
         991                 :         }
         992               0 :         NS_NOTREACHED("avail space rect with zero height!");
         993               0 :         newY += 1;
         994                 :       }
         995                 :     }
         996                 :   }
         997                 :
         998                 : #ifdef DEBUG
         999               0 :   if (nsBlockFrame::gNoisyReflow) {
        1000               0 :     nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
        1001               0 :     printf("clear floats: out: y=%d\n", newY);
        1002                 :   }
        1003                 : #endif
        1004                 :
        1005               0 :   return newY;
        1006                 : }
        1007                 :

Generated by: LCOV version 1.7