LCOV - code coverage report
Current view: directory - layout/generic - nsBlockFrame.h (source / functions) Found Hit Coverage
Test: app.info Lines: 69 0 0.0 %
Date: 2012-06-02 Functions: 34 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                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      27                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : /*
      40                 :  * rendering object for CSS display:block, inline-block, and list-item
      41                 :  * boxes, also used for various anonymous boxes
      42                 :  */
      43                 : 
      44                 : #ifndef nsBlockFrame_h___
      45                 : #define nsBlockFrame_h___
      46                 : 
      47                 : #include "nsContainerFrame.h"
      48                 : #include "nsHTMLParts.h"
      49                 : #include "nsAbsoluteContainingBlock.h"
      50                 : #include "nsLineBox.h"
      51                 : #include "nsCSSPseudoElements.h"
      52                 : #include "nsStyleSet.h"
      53                 : #include "nsFloatManager.h"
      54                 : 
      55                 : enum LineReflowStatus {
      56                 :   // The line was completely reflowed and fit in available width, and we should
      57                 :   // try to pull up content from the next line if possible.
      58                 :   LINE_REFLOW_OK,
      59                 :   // The line was completely reflowed and fit in available width, but we should
      60                 :   // not try to pull up content from the next line.
      61                 :   LINE_REFLOW_STOP,
      62                 :   // We need to reflow the line again at its current vertical position. The
      63                 :   // new reflow should not try to pull up any frames from the next line.
      64                 :   LINE_REFLOW_REDO_NO_PULL,
      65                 :   // We need to reflow the line again using the floats from its height
      66                 :   // this reflow, since its height made it hit floats that were not
      67                 :   // adjacent to its top.
      68                 :   LINE_REFLOW_REDO_MORE_FLOATS,
      69                 :   // We need to reflow the line again at a lower vertical postion where there
      70                 :   // may be more horizontal space due to different float configuration.
      71                 :   LINE_REFLOW_REDO_NEXT_BAND,
      72                 :   // The line did not fit in the available vertical space. Try pushing it to
      73                 :   // the next page or column if it's not the first line on the current page/column.
      74                 :   LINE_REFLOW_TRUNCATED
      75                 : };
      76                 : 
      77                 : class nsBlockReflowState;
      78                 : class nsBlockInFlowLineIterator;
      79                 : class nsBulletFrame;
      80                 : class nsLineBox;
      81                 : class nsFirstLineFrame;
      82                 : class nsIntervalSet;
      83                 : 
      84                 : /**
      85                 :  * Some invariants:
      86                 :  * -- The overflow out-of-flows list contains the out-of-
      87                 :  * flow frames whose placeholders are in the overflow list.
      88                 :  * -- A given piece of content has at most one placeholder
      89                 :  * frame in a block's normal child list.
      90                 :  * -- While a block is being reflowed, and from then until
      91                 :  * its next-in-flow is reflowed it may have a
      92                 :  * PushedFloatProperty frame property that points to
      93                 :  * an nsFrameList. This list contains continuations for
      94                 :  * floats whose prev-in-flow is in the block's regular float
      95                 :  * list and first-in-flows of floats that did not fit, but
      96                 :  * whose placeholders are in the block or one of its
      97                 :  * prev-in-flows.
      98                 :  * -- In all these frame lists, if there are two frames for
      99                 :  * the same content appearing in the list, then the frames
     100                 :  * appear with the prev-in-flow before the next-in-flow.
     101                 :  * -- While reflowing a block, its overflow line list
     102                 :  * will usually be empty but in some cases will have lines
     103                 :  * (while we reflow the block at its shrink-wrap width).
     104                 :  * In this case any new overflowing content must be
     105                 :  * prepended to the overflow lines.
     106                 :  */
     107                 : 
     108                 : // see nsHTMLParts.h for the public block state bits
     109                 : 
     110                 : /**
     111                 :  * Something in the block has changed that requires Bidi resolution to be
     112                 :  * performed on the block. This flag must be either set on all blocks in a 
     113                 :  * continuation chain or none of them.
     114                 :  */
     115                 : #define NS_BLOCK_NEEDS_BIDI_RESOLUTION      NS_FRAME_STATE_BIT(20)
     116                 : #define NS_BLOCK_HAS_PUSHED_FLOATS          NS_FRAME_STATE_BIT(21)
     117                 : #define NS_BLOCK_HAS_LINE_CURSOR            NS_FRAME_STATE_BIT(24)
     118                 : #define NS_BLOCK_HAS_OVERFLOW_LINES         NS_FRAME_STATE_BIT(25)
     119                 : #define NS_BLOCK_HAS_OVERFLOW_OUT_OF_FLOWS  NS_FRAME_STATE_BIT(26)
     120                 : 
     121                 : // Set on any block that has descendant frames in the normal
     122                 : // flow with 'clear' set to something other than 'none'
     123                 : // (including <BR CLEAR="..."> frames)
     124                 : #define NS_BLOCK_HAS_CLEAR_CHILDREN         NS_FRAME_STATE_BIT(27)
     125                 : 
     126                 : #define nsBlockFrameSuper nsContainerFrame
     127                 : 
     128                 : /*
     129                 :  * Base class for block and inline frames.
     130                 :  * The block frame has an additional child list, kAbsoluteList, which
     131                 :  * contains the absolutely positioned frames.
     132                 :  */ 
     133                 : class nsBlockFrame : public nsBlockFrameSuper
     134                 : {
     135                 : public:
     136                 :   NS_DECL_QUERYFRAME_TARGET(nsBlockFrame)
     137                 :   NS_DECL_FRAMEARENA_HELPERS
     138                 : 
     139                 :   typedef nsLineList::iterator                  line_iterator;
     140                 :   typedef nsLineList::const_iterator            const_line_iterator;
     141                 :   typedef nsLineList::reverse_iterator          reverse_line_iterator;
     142                 :   typedef nsLineList::const_reverse_iterator    const_reverse_line_iterator;
     143                 : 
     144               0 :   line_iterator begin_lines() { return mLines.begin(); }
     145               0 :   line_iterator end_lines() { return mLines.end(); }
     146               0 :   const_line_iterator begin_lines() const { return mLines.begin(); }
     147               0 :   const_line_iterator end_lines() const { return mLines.end(); }
     148                 :   reverse_line_iterator rbegin_lines() { return mLines.rbegin(); }
     149               0 :   reverse_line_iterator rend_lines() { return mLines.rend(); }
     150               0 :   const_reverse_line_iterator rbegin_lines() const { return mLines.rbegin(); }
     151               0 :   const_reverse_line_iterator rend_lines() const { return mLines.rend(); }
     152               0 :   line_iterator line(nsLineBox* aList) { return mLines.begin(aList); }
     153               0 :   reverse_line_iterator rline(nsLineBox* aList) { return mLines.rbegin(aList); }
     154                 : 
     155                 :   friend nsIFrame* NS_NewBlockFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, PRUint32 aFlags);
     156                 : 
     157                 :   // nsQueryFrame
     158                 :   NS_DECL_QUERYFRAME
     159                 : 
     160                 :   // nsIFrame
     161                 :   NS_IMETHOD Init(nsIContent*      aContent,
     162                 :                   nsIFrame*        aParent,
     163                 :                   nsIFrame*        aPrevInFlow);
     164                 :   NS_IMETHOD SetInitialChildList(ChildListID     aListID,
     165                 :                                  nsFrameList&    aChildList);
     166                 :   NS_IMETHOD  AppendFrames(ChildListID     aListID,
     167                 :                            nsFrameList&    aFrameList);
     168                 :   NS_IMETHOD  InsertFrames(ChildListID     aListID,
     169                 :                            nsIFrame*       aPrevFrame,
     170                 :                            nsFrameList&    aFrameList);
     171                 :   NS_IMETHOD  RemoveFrame(ChildListID     aListID,
     172                 :                           nsIFrame*       aOldFrame);
     173                 :   virtual const nsFrameList& GetChildList(ChildListID aListID) const;
     174                 :   virtual void GetChildLists(nsTArray<ChildList>* aLists) const;
     175                 :   virtual nscoord GetBaseline() const;
     176                 :   virtual nscoord GetCaretBaseline() const;
     177                 :   virtual void DestroyFrom(nsIFrame* aDestructRoot);
     178                 :   virtual nsSplittableType GetSplittableType() const;
     179                 :   virtual bool IsFloatContainingBlock() const;
     180                 :   NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
     181                 :                               const nsRect&           aDirtyRect,
     182                 :                               const nsDisplayListSet& aLists);
     183                 :   virtual void InvalidateInternal(const nsRect& aDamageRect,
     184                 :                                   nscoord aX, nscoord aY, nsIFrame* aForChild,
     185                 :                                   PRUint32 aFlags);
     186                 :   virtual nsIAtom* GetType() const;
     187               0 :   virtual bool IsFrameOfType(PRUint32 aFlags) const
     188                 :   {
     189                 :     return nsContainerFrame::IsFrameOfType(aFlags &
     190                 :              ~(nsIFrame::eCanContainOverflowContainers |
     191               0 :                nsIFrame::eBlockFrame));
     192                 :   }
     193                 : 
     194                 : #ifdef DEBUG
     195                 :   NS_IMETHOD List(FILE* out, PRInt32 aIndent) const;
     196                 :   NS_IMETHOD_(nsFrameState) GetDebugStateBits() const;
     197                 :   NS_IMETHOD GetFrameName(nsAString& aResult) const;
     198                 : #endif
     199                 : 
     200                 : #ifdef ACCESSIBILITY
     201                 :   virtual already_AddRefed<nsAccessible> CreateAccessible();
     202                 : #endif
     203                 : 
     204                 :   // line cursor methods to speed up searching for the line(s)
     205                 :   // containing a point. The basic idea is that we set the cursor
     206                 :   // property if the lines' overflowArea.VisualOverflow().ys and
     207                 :   // overflowArea.VisualOverflow().yMosts are non-decreasing
     208                 :   // (considering only non-empty overflowArea.VisualOverflow()s; empty
     209                 :   // overflowArea.VisualOverflow()s never participate in event handling
     210                 :   // or painting), and the block has sufficient number of lines. The
     211                 :   // cursor property points to a "recently used" line. If we get a
     212                 :   // series of requests that work on lines
     213                 :   // "near" the cursor, then we can find those nearby lines quickly by
     214                 :   // starting our search at the cursor.
     215                 : 
     216                 :   // Clear out line cursor because we're disturbing the lines (i.e., Reflow)
     217                 :   void ClearLineCursor();
     218                 :   // Get the first line that might contain y-coord 'y', or nsnull if you must search
     219                 :   // all lines. If nonnull is returned then we guarantee that the lines'
     220                 :   // combinedArea.ys and combinedArea.yMosts are non-decreasing.
     221                 :   // The actual line returned might not contain 'y', but if not, it is guaranteed
     222                 :   // to be before any line which does contain 'y'.
     223                 :   nsLineBox* GetFirstLineContaining(nscoord y);
     224                 :   // Set the line cursor to our first line. Only call this if you
     225                 :   // guarantee that the lines' combinedArea.ys and combinedArea.yMosts
     226                 :   // are non-decreasing.
     227                 :   void SetupLineCursor();
     228                 : 
     229                 :   virtual void ChildIsDirty(nsIFrame* aChild);
     230                 :   virtual bool IsVisibleInSelection(nsISelection* aSelection);
     231                 : 
     232                 :   virtual bool IsEmpty();
     233                 :   virtual bool CachedIsEmpty();
     234                 :   virtual bool IsSelfEmpty();
     235                 : 
     236                 :   // Given that we have a bullet, does it actually draw something, i.e.,
     237                 :   // do we have either a 'list-style-type' or 'list-style-image' that is
     238                 :   // not 'none'?
     239                 :   bool BulletIsEmpty() const;
     240                 : 
     241                 :   /**
     242                 :    * Return the bullet text equivalent.
     243                 :    */
     244                 :   void GetBulletText(nsAString& aText) const;
     245                 : 
     246                 :   /**
     247                 :    * Return true if there's a bullet.
     248                 :    */
     249               0 :   bool HasBullet() const {
     250               0 :     return HasOutsideBullet() || HasInsideBullet();
     251                 :   }
     252                 : 
     253                 :   virtual void MarkIntrinsicWidthsDirty();
     254                 :   virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext);
     255                 :   virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext);
     256                 : 
     257                 :   virtual nsRect ComputeTightBounds(gfxContext* aContext) const;
     258                 :   
     259                 :   NS_IMETHOD Reflow(nsPresContext*          aPresContext,
     260                 :                     nsHTMLReflowMetrics&     aDesiredSize,
     261                 :                     const nsHTMLReflowState& aReflowState,
     262                 :                     nsReflowStatus&          aStatus);
     263                 : 
     264                 :   NS_IMETHOD AttributeChanged(PRInt32         aNameSpaceID,
     265                 :                               nsIAtom*        aAttribute,
     266                 :                               PRInt32         aModType);
     267                 : 
     268                 :   virtual nsresult StealFrame(nsPresContext* aPresContext,
     269                 :                               nsIFrame*      aChild,
     270                 :                               bool           aForceNormal = false);
     271                 : 
     272                 :   virtual void DeleteNextInFlowChild(nsPresContext* aPresContext,
     273                 :                                      nsIFrame*      aNextInFlow,
     274                 :                                      bool           aDeletingEmptyFrames);
     275                 : 
     276                 :   /**
     277                 :    * Determines whether the collapsed margin carried out of the last
     278                 :    * line includes the margin-top of a line with clearance (in which
     279                 :    * case we must avoid collapsing that margin with our bottom margin)
     280                 :    */
     281                 :   bool CheckForCollapsedBottomMarginFromClearanceLine();
     282                 : 
     283                 :   static nsresult GetCurrentLine(nsBlockReflowState *aState, nsLineBox **aOutCurrentLine);
     284                 : 
     285                 :   static bool BlockIsMarginRoot(nsIFrame* aBlock);
     286                 :   static bool BlockNeedsFloatManager(nsIFrame* aBlock);
     287                 : 
     288                 :   /**
     289                 :    * Returns whether aFrame is a block frame that will wrap its contents
     290                 :    * around floats intruding on it from the outside.  (aFrame need not
     291                 :    * be a block frame, but if it's not, the result will be false.)
     292                 :    */
     293                 :   static bool BlockCanIntersectFloats(nsIFrame* aFrame);
     294                 : 
     295                 :   /**
     296                 :    * Returns the width that needs to be cleared past floats for blocks
     297                 :    * that cannot intersect floats.  aState must already have
     298                 :    * GetAvailableSpace called on it for the vertical position that we
     299                 :    * care about (which need not be its current mY)
     300                 :    */
     301                 :   struct ReplacedElementWidthToClear {
     302                 :     nscoord marginLeft, borderBoxWidth, marginRight;
     303                 :     nscoord MarginBoxWidth() const
     304                 :       { return marginLeft + borderBoxWidth + marginRight; }
     305                 :   };
     306                 :   static ReplacedElementWidthToClear
     307                 :     WidthToClearPastFloats(nsBlockReflowState& aState,
     308                 :                            const nsRect& aFloatAvailableSpace,
     309                 :                            nsIFrame* aFrame);
     310                 : 
     311                 :   /**
     312                 :    * Creates a contination for aFloat and adds it to the list of overflow floats.
     313                 :    * Also updates aState.mReflowStatus to include the float's incompleteness.
     314                 :    * Must only be called while this block frame is in reflow.
     315                 :    * aFloatStatus must be the float's true, unmodified reflow status.
     316                 :    * 
     317                 :    */
     318                 :   nsresult SplitFloat(nsBlockReflowState& aState,
     319                 :                       nsIFrame*           aFloat,
     320                 :                       nsReflowStatus      aFloatStatus);
     321                 : 
     322                 :   /**
     323                 :    * Walks up the frame tree, starting with aCandidate, and returns the first
     324                 :    * block frame that it encounters.
     325                 :    */
     326                 :   static nsBlockFrame* GetNearestAncestorBlock(nsIFrame* aCandidate);
     327                 :   
     328               0 :   struct FrameLines {
     329                 :     nsLineList mLines;
     330                 :     nsFrameList mFrames;
     331                 :   };
     332                 : 
     333                 : protected:
     334               0 :   nsBlockFrame(nsStyleContext* aContext)
     335                 :     : nsContainerFrame(aContext)
     336                 :     , mMinWidth(NS_INTRINSIC_WIDTH_UNKNOWN)
     337               0 :     , mPrefWidth(NS_INTRINSIC_WIDTH_UNKNOWN)
     338                 :   {
     339                 : #ifdef DEBUG
     340               0 :   InitDebugFlags();
     341                 : #endif
     342               0 :   }
     343                 :   virtual ~nsBlockFrame();
     344                 : 
     345                 : #ifdef DEBUG
     346                 : #ifdef _IMPL_NS_LAYOUT
     347               0 :   already_AddRefed<nsStyleContext> GetFirstLetterStyle(nsPresContext* aPresContext)
     348                 :   {
     349                 :     return aPresContext->StyleSet()->
     350                 :       ProbePseudoElementStyle(mContent->AsElement(),
     351                 :                               nsCSSPseudoElements::ePseudo_firstLetter,
     352               0 :                               mStyleContext);
     353                 :   }
     354                 : #endif
     355                 : #endif
     356                 : 
     357               0 :   NS_DECLARE_FRAME_PROPERTY(LineCursorProperty, nsnull)
     358               0 :   nsLineBox* GetLineCursor() {
     359               0 :     return (GetStateBits() & NS_BLOCK_HAS_LINE_CURSOR) ?
     360               0 :       static_cast<nsLineBox*>(Properties().Get(LineCursorProperty())) : nsnull;
     361                 :   }
     362                 : 
     363               0 :   nsLineBox* NewLineBox(nsIFrame* aFrame, bool aIsBlock) {
     364               0 :     return NS_NewLineBox(PresContext()->PresShell(), aFrame, aIsBlock);
     365                 :   }
     366               0 :   nsLineBox* NewLineBox(nsLineBox* aFromLine, nsIFrame* aFrame, PRInt32 aCount) {
     367               0 :     return NS_NewLineBox(PresContext()->PresShell(), aFromLine, aFrame, aCount);
     368                 :   }
     369               0 :   void FreeLineBox(nsLineBox* aLine) {
     370               0 :     if (aLine == GetLineCursor()) {
     371               0 :       ClearLineCursor();
     372                 :     }
     373               0 :     aLine->Destroy(PresContext()->PresShell());
     374               0 :   }
     375                 : 
     376                 :   void TryAllLines(nsLineList::iterator* aIterator,
     377                 :                    nsLineList::iterator* aStartIterator,
     378                 :                    nsLineList::iterator* aEndIterator,
     379                 :                    bool*        aInOverflowLines,
     380                 :                    FrameLines** aOverflowLines);
     381                 : 
     382               0 :   void SetFlags(nsFrameState aFlags) {
     383               0 :     mState &= ~NS_BLOCK_FLAGS_MASK;
     384               0 :     mState |= aFlags;
     385               0 :   }
     386                 : 
     387                 :   /** move the frames contained by aLine by aDY
     388                 :     * if aLine is a block, its child floats are added to the state manager
     389                 :     */
     390                 :   void SlideLine(nsBlockReflowState& aState,
     391                 :                  nsLineBox* aLine, nscoord aDY);
     392                 : 
     393                 :   virtual PRIntn GetSkipSides() const;
     394                 : 
     395                 :   virtual void ComputeFinalSize(const nsHTMLReflowState& aReflowState,
     396                 :                                 nsBlockReflowState&      aState,
     397                 :                                 nsHTMLReflowMetrics&     aMetrics,
     398                 :                                 nscoord*                 aBottomEdgeOfChildren);
     399                 : 
     400                 :   void ComputeOverflowAreas(const nsRect&         aBounds,
     401                 :                             const nsStyleDisplay* aDisplay,
     402                 :                             nscoord               aBottomEdgeOfChildren,
     403                 :                             nsOverflowAreas&      aOverflowAreas);
     404                 : 
     405                 :   /** add the frames in aFrameList to this block after aPrevSibling
     406                 :     * this block thinks in terms of lines, but the frame construction code
     407                 :     * knows nothing about lines at all. So we need to find the line that
     408                 :     * contains aPrevSibling and add aFrameList after aPrevSibling on that line.
     409                 :     * new lines are created as necessary to handle block data in aFrameList.
     410                 :     * This function will clear aFrameList.
     411                 :     */
     412                 :   virtual nsresult AddFrames(nsFrameList& aFrameList, nsIFrame* aPrevSibling);
     413                 : 
     414                 : #ifdef IBMBIDI
     415                 :   /**
     416                 :    * Perform Bidi resolution on this frame
     417                 :    */
     418                 :   nsresult ResolveBidi();
     419                 : 
     420                 :   /**
     421                 :    * Test whether the frame is a form control in a visual Bidi page.
     422                 :    * This is necessary for backwards-compatibility, because most visual
     423                 :    * pages use logical order for form controls so that they will
     424                 :    * display correctly on native widgets in OSs with Bidi support
     425                 :    * @param aPresContext the pres context
     426                 :    * @return whether the frame is a BIDI form control
     427                 :    */
     428                 :   bool IsVisualFormControl(nsPresContext* aPresContext);
     429                 : #endif
     430                 : 
     431                 : public:
     432                 :   /**
     433                 :    * Does all the real work for removing aDeletedFrame
     434                 :    * -- finds the line containing aDeletedFrame
     435                 :    * -- removes all aDeletedFrame next-in-flows (or all continuations,
     436                 :    * if REMOVE_FIXED_CONTINUATIONS is given)
     437                 :    * -- marks lines dirty as needed
     438                 :    * -- marks textruns dirty (unless FRAMES_ARE_EMPTY is given, in which
     439                 :    * case textruns do not need to be dirtied)
     440                 :    * -- destroys all removed frames
     441                 :    */
     442                 :   enum {
     443                 :     REMOVE_FIXED_CONTINUATIONS = 0x02,
     444                 :     FRAMES_ARE_EMPTY           = 0x04
     445                 :   };
     446                 :   nsresult DoRemoveFrame(nsIFrame* aDeletedFrame, PRUint32 aFlags);
     447                 : 
     448                 :   void ReparentFloats(nsIFrame* aFirstFrame,
     449                 :                       nsBlockFrame* aOldParent, bool aFromOverflow,
     450                 :                       bool aReparentSiblings);
     451                 : 
     452                 :   virtual bool UpdateOverflow();
     453                 : 
     454                 :   /** Load all of aFrame's floats into the float manager iff aFrame is not a
     455                 :    *  block formatting context. Handles all necessary float manager translations;
     456                 :    *  assumes float manager is in aFrame's parent's coord system.
     457                 :    *  Safe to call on non-blocks (does nothing).
     458                 :    */
     459                 :   static void RecoverFloatsFor(nsIFrame*       aFrame,
     460                 :                                nsFloatManager& aFloatManager);
     461                 : 
     462                 : protected:
     463                 : 
     464                 :   /** grab overflow lines from this block's prevInFlow, and make them
     465                 :     * part of this block's mLines list.
     466                 :     * @return true if any lines were drained.
     467                 :     */
     468                 :   bool DrainOverflowLines();
     469                 : 
     470                 :   /** grab pushed floats from this block's prevInFlow, and splice
     471                 :     * them into this block's mFloats list.
     472                 :     */
     473                 :   void DrainPushedFloats(nsBlockReflowState& aState);
     474                 : 
     475                 :   /** Load all our floats into the float manager (without reflowing them).
     476                 :    *  Assumes float manager is in our own coordinate system.
     477                 :    */
     478                 :   void RecoverFloats(nsFloatManager& aFloatManager);
     479                 : 
     480                 :   /** Reflow pushed floats
     481                 :    */
     482                 :   nsresult ReflowPushedFloats(nsBlockReflowState& aState,
     483                 :                               nsOverflowAreas&    aOverflowAreas,
     484                 :                               nsReflowStatus&     aStatus);
     485                 : 
     486                 :   /** Find any trailing BR clear from the last line of the block (or its PIFs)
     487                 :    */
     488                 :   PRUint8 FindTrailingClear();
     489                 : 
     490                 :   /**
     491                 :     * Remove a float from our float list and also the float cache
     492                 :     * for the line its placeholder is on.
     493                 :     */
     494                 :   line_iterator RemoveFloat(nsIFrame* aFloat);
     495                 : 
     496                 :   void CollectFloats(nsIFrame* aFrame, nsFrameList& aList,
     497                 :                      bool aFromOverflow, bool aCollectFromSiblings);
     498                 :   // Remove a float, abs, rel positioned frame from the appropriate block's list
     499                 :   static void DoRemoveOutOfFlowFrame(nsIFrame* aFrame);
     500                 : 
     501                 :   /** set up the conditions necessary for an resize reflow
     502                 :     * the primary task is to mark the minimumly sufficient lines dirty. 
     503                 :     */
     504                 :   nsresult PrepareResizeReflow(nsBlockReflowState& aState);
     505                 : 
     506                 :   /** reflow all lines that have been marked dirty */
     507                 :   nsresult ReflowDirtyLines(nsBlockReflowState& aState);
     508                 : 
     509                 :   /** Mark a given line dirty due to reflow being interrupted on or before it */
     510                 :   void MarkLineDirtyForInterrupt(nsLineBox* aLine);
     511                 : 
     512                 :   //----------------------------------------
     513                 :   // Methods for line reflow
     514                 :   /**
     515                 :    * Reflow a line.  
     516                 :    * @param aState           the current reflow state
     517                 :    * @param aLine            the line to reflow.  can contain a single block frame
     518                 :    *                         or contain 1 or more inline frames.
     519                 :    * @param aKeepReflowGoing [OUT] indicates whether the caller should continue to reflow more lines
     520                 :    */
     521                 :   nsresult ReflowLine(nsBlockReflowState& aState,
     522                 :                       line_iterator aLine,
     523                 :                       bool* aKeepReflowGoing);
     524                 : 
     525                 :   // Return false if it needs another reflow because of reduced space
     526                 :   // between floats that are next to it (but not next to its top), and
     527                 :   // return true otherwise.
     528                 :   bool PlaceLine(nsBlockReflowState& aState,
     529                 :                    nsLineLayout&       aLineLayout,
     530                 :                    line_iterator       aLine,
     531                 :                    nsFloatManager::SavedState* aFloatStateBeforeLine,
     532                 :                    nsRect&             aFloatAvailableSpace, /* in-out */
     533                 :                    nscoord&            aAvailableSpaceHeight, /* in-out */
     534                 :                    bool*             aKeepReflowGoing);
     535                 : 
     536                 :   /**
     537                 :    * Mark |aLine| dirty, and, if necessary because of possible
     538                 :    * pull-up, mark the previous line dirty as well. Also invalidates textruns
     539                 :    * on those lines because the text in the lines might have changed due to
     540                 :    * addition/removal of frames.
     541                 :    * @param aLine the line to mark dirty
     542                 :    * @param aLineList the line list containing that line, null means the line
     543                 :    *        is in 'mLines' of this frame.
     544                 :    */
     545                 :   nsresult MarkLineDirty(line_iterator aLine,
     546                 :                          const nsLineList* aLineList = nsnull);
     547                 : 
     548                 :   // XXX where to go
     549                 :   bool IsLastLine(nsBlockReflowState& aState,
     550                 :                   line_iterator aLine);
     551                 : 
     552                 :   void DeleteLine(nsBlockReflowState& aState,
     553                 :                   nsLineList::iterator aLine,
     554                 :                   nsLineList::iterator aLineEnd);
     555                 : 
     556                 :   //----------------------------------------
     557                 :   // Methods for individual frame reflow
     558                 : 
     559                 :   bool ShouldApplyTopMargin(nsBlockReflowState& aState,
     560                 :                               nsLineBox* aLine);
     561                 : 
     562                 :   nsresult ReflowBlockFrame(nsBlockReflowState& aState,
     563                 :                             line_iterator aLine,
     564                 :                             bool* aKeepGoing);
     565                 : 
     566                 :   nsresult ReflowInlineFrames(nsBlockReflowState& aState,
     567                 :                               line_iterator aLine,
     568                 :                               bool* aKeepLineGoing);
     569                 : 
     570                 :   nsresult DoReflowInlineFrames(nsBlockReflowState& aState,
     571                 :                                 nsLineLayout& aLineLayout,
     572                 :                                 line_iterator aLine,
     573                 :                                 nsFlowAreaRect& aFloatAvailableSpace,
     574                 :                                 nscoord& aAvailableSpaceHeight,
     575                 :                                 nsFloatManager::SavedState*
     576                 :                                   aFloatStateBeforeLine,
     577                 :                                 bool* aKeepReflowGoing,
     578                 :                                 LineReflowStatus* aLineReflowStatus,
     579                 :                                 bool aAllowPullUp);
     580                 : 
     581                 :   nsresult ReflowInlineFrame(nsBlockReflowState& aState,
     582                 :                              nsLineLayout& aLineLayout,
     583                 :                              line_iterator aLine,
     584                 :                              nsIFrame* aFrame,
     585                 :                              LineReflowStatus* aLineReflowStatus);
     586                 : 
     587                 :   // Compute the available width for a float. 
     588                 :   nsRect AdjustFloatAvailableSpace(nsBlockReflowState& aState,
     589                 :                                    const nsRect&       aFloatAvailableSpace,
     590                 :                                    nsIFrame*           aFloatFrame);
     591                 :   // Computes the border-box width of the float
     592                 :   nscoord ComputeFloatWidth(nsBlockReflowState& aState,
     593                 :                             const nsRect&       aFloatAvailableSpace,
     594                 :                             nsIFrame*           aFloat);
     595                 :   // An incomplete aReflowStatus indicates the float should be split
     596                 :   // but only if the available height is constrained.
     597                 :   // aAdjustedAvailableSpace is the result of calling
     598                 :   // nsBlockFrame::AdjustFloatAvailableSpace.
     599                 :   nsresult ReflowFloat(nsBlockReflowState& aState,
     600                 :                        const nsRect&       aAdjustedAvailableSpace,
     601                 :                        nsIFrame*           aFloat,
     602                 :                        nsMargin&           aFloatMargin,
     603                 :                        // Whether the float's position
     604                 :                        // (aAdjustedAvailableSpace) has been pushed down
     605                 :                        // due to the presence of other floats.
     606                 :                        bool                aFloatPushedDown,
     607                 :                        nsReflowStatus&     aReflowStatus);
     608                 : 
     609                 :   //----------------------------------------
     610                 :   // Methods for pushing/pulling lines/frames
     611                 : 
     612                 :   /**
     613                 :    * Create a next-in-flow, if necessary, for aFrame. If a new frame is
     614                 :    * created, place it in aLine if aLine is not null.
     615                 :    * @param aState the block reflow state
     616                 :    * @param aLine where to put a new frame
     617                 :    * @param aFrame the frame
     618                 :    * @param aMadeNewFrame true if a new frame was created, false if not
     619                 :    * @return NS_OK if a next-in-flow already exists or is successfully created
     620                 :    */
     621                 :   virtual nsresult CreateContinuationFor(nsBlockReflowState& aState,
     622                 :                                          nsLineBox*          aLine,
     623                 :                                          nsIFrame*           aFrame,
     624                 :                                          bool&             aMadeNewFrame);
     625                 : 
     626                 :   // Push aLine, which cannot be placed on this page/column but should
     627                 :   // fit on a future one.  Set aKeepReflowGoing to false.
     628                 :   void PushTruncatedLine(nsBlockReflowState& aState,
     629                 :                          line_iterator       aLine,
     630                 :                          bool&             aKeepReflowGoing);
     631                 : 
     632                 :   nsresult SplitLine(nsBlockReflowState& aState,
     633                 :                      nsLineLayout& aLineLayout,
     634                 :                      line_iterator aLine,
     635                 :                      nsIFrame* aFrame,
     636                 :                      LineReflowStatus* aLineReflowStatus);
     637                 : 
     638                 :   /**
     639                 :    * Pull a frame from the next available location (one of our lines or
     640                 :    * one of our next-in-flows lines).
     641                 :    * @return the pulled frame or nsnull
     642                 :    */
     643                 :   nsIFrame* PullFrame(nsBlockReflowState& aState,
     644                 :                       line_iterator       aLine);
     645                 : 
     646                 :   /**
     647                 :    * Try to pull a frame out of a line pointed at by aFromLine.
     648                 :    *
     649                 :    * Note: pulling a frame from a line that is a place-holder frame
     650                 :    * doesn't automatically remove the corresponding float from the
     651                 :    * line's float array. This happens indirectly: either the line gets
     652                 :    * emptied (and destroyed) or the line gets reflowed (because we mark
     653                 :    * it dirty) and the code at the top of ReflowLine empties the
     654                 :    * array. So eventually, it will be removed, just not right away.
     655                 :    *
     656                 :    * @return the pulled frame or nsnull
     657                 :    */
     658                 :   nsIFrame* PullFrameFrom(nsBlockReflowState&  aState,
     659                 :                           nsLineBox*           aLine,
     660                 :                           nsBlockFrame*        aFromContainer,
     661                 :                           bool                 aFromOverflowLine,
     662                 :                           nsFrameList&         aFromFrameList,
     663                 :                           nsLineList::iterator aFromLine);
     664                 : 
     665                 :   /**
     666                 :    * Push the line after aLineBefore to the overflow line list.
     667                 :    * @param aLineBefore a line in 'mLines' (or begin_lines() when
     668                 :    *        pushing the first line)
     669                 :    */
     670                 :   void PushLines(nsBlockReflowState& aState,
     671                 :                  nsLineList::iterator aLineBefore);
     672                 : 
     673                 :   void PropagateFloatDamage(nsBlockReflowState& aState,
     674                 :                             nsLineBox* aLine,
     675                 :                             nscoord aDeltaY);
     676                 : 
     677                 :   void CheckFloats(nsBlockReflowState& aState);
     678                 : 
     679                 :   //----------------------------------------
     680                 :   // List handling kludge
     681                 : 
     682                 :   // If this returns true, the block it's called on should get the
     683                 :   // NS_FRAME_HAS_DIRTY_CHILDREN bit set on it by the caller; either directly
     684                 :   // if it's already in reflow, or via calling FrameNeedsReflow() to schedule a
     685                 :   // reflow.
     686                 :   bool RenumberLists(nsPresContext* aPresContext);
     687                 : 
     688                 :   static bool RenumberListsInBlock(nsPresContext* aPresContext,
     689                 :                                      nsBlockFrame* aBlockFrame,
     690                 :                                      PRInt32* aOrdinal,
     691                 :                                      PRInt32 aDepth);
     692                 : 
     693                 :   static bool RenumberListsFor(nsPresContext* aPresContext, nsIFrame* aKid, PRInt32* aOrdinal, PRInt32 aDepth);
     694                 : 
     695                 :   static bool FrameStartsCounterScope(nsIFrame* aFrame);
     696                 : 
     697                 :   void ReflowBullet(nsIFrame* aBulletFrame,
     698                 :                     nsBlockReflowState& aState,
     699                 :                     nsHTMLReflowMetrics& aMetrics,
     700                 :                     nscoord aLineTop);
     701                 : 
     702                 :   //----------------------------------------
     703                 : 
     704                 :   virtual nsILineIterator* GetLineIterator();
     705                 : 
     706                 : public:
     707               0 :   bool HasOverflowLines() const {
     708               0 :     return 0 != (GetStateBits() & NS_BLOCK_HAS_OVERFLOW_LINES);
     709                 :   }
     710                 :   FrameLines* GetOverflowLines() const;
     711                 : protected:
     712                 :   FrameLines* RemoveOverflowLines();
     713                 :   void SetOverflowLines(FrameLines* aOverflowLines);
     714                 :   void DestroyOverflowLines();
     715                 : 
     716                 :   // Determine the computed height that's in effect for this block
     717                 :   // frame (that is, our computed height minus the heights of our
     718                 :   // previous in-flows).
     719                 :   // XXXbz this clearly makes laying out a block with N in-flows
     720                 :   // O(N^2)!  Good thing the constant is tiny.
     721                 :   nscoord GetEffectiveComputedHeight(const nsHTMLReflowState& aReflowState) const;
     722                 : 
     723                 :   /**
     724                 :    * This class is useful for efficiently modifying the out of flow
     725                 :    * overflow list. It gives the client direct writable access to
     726                 :    * the frame list temporarily but ensures that property is only
     727                 :    * written back if absolutely necessary.
     728                 :    */
     729                 :   struct nsAutoOOFFrameList {
     730                 :     nsFrameList mList;
     731                 : 
     732               0 :     nsAutoOOFFrameList(nsBlockFrame* aBlock)
     733               0 :       : mPropValue(aBlock->GetOverflowOutOfFlows())
     734               0 :       , mBlock(aBlock) {
     735               0 :       if (mPropValue) {
     736               0 :         mList = *mPropValue;
     737                 :       }
     738               0 :     }
     739               0 :     ~nsAutoOOFFrameList() {
     740               0 :       mBlock->SetOverflowOutOfFlows(mList, mPropValue);
     741               0 :     }
     742                 :   protected:
     743                 :     nsFrameList* const mPropValue;
     744                 :     nsBlockFrame* const mBlock;
     745                 :   };
     746                 :   friend struct nsAutoOOFFrameList;
     747                 : 
     748                 :   nsFrameList* GetOverflowOutOfFlows() const;
     749                 :   void SetOverflowOutOfFlows(const nsFrameList& aList, nsFrameList* aPropValue);
     750                 : 
     751                 :   /**
     752                 :    * @return true if this frame has an inside bullet frame.
     753                 :    */
     754               0 :   bool HasInsideBullet() const {
     755               0 :     return 0 != (mState & NS_BLOCK_FRAME_HAS_INSIDE_BULLET);
     756                 :   }
     757                 : 
     758                 :   /**
     759                 :    * @return the inside bullet frame or nsnull if we don't have one.
     760                 :    */
     761                 :   nsBulletFrame* GetInsideBullet() const;
     762                 : 
     763                 :   /**
     764                 :    * @return true if this frame has an outside bullet frame.
     765                 :    */
     766               0 :   bool HasOutsideBullet() const {
     767               0 :     return 0 != (mState & NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET);
     768                 :   }
     769                 : 
     770                 :   /**
     771                 :    * @return the outside bullet frame or nsnull if we don't have one.
     772                 :    */
     773                 :   nsBulletFrame* GetOutsideBullet() const;
     774                 : 
     775                 :   /**
     776                 :    * @return the outside bullet frame list frame property.
     777                 :    */
     778                 :   nsFrameList* GetOutsideBulletList() const;
     779                 : 
     780                 :   /**
     781                 :    * @return the bullet frame or nsnull if we don't have one.
     782                 :    */
     783               0 :   nsBulletFrame* GetBullet() const {
     784               0 :     nsBulletFrame* outside = GetOutsideBullet();
     785               0 :     return outside ? outside : GetInsideBullet();
     786                 :   }
     787                 :   
     788                 :   /**
     789                 :    * @return true if this frame has pushed floats.
     790                 :    */
     791               0 :   bool HasPushedFloats() const {
     792               0 :     return 0 != (GetStateBits() & NS_BLOCK_HAS_PUSHED_FLOATS);
     793                 :   }
     794                 : 
     795                 :   // Get the pushed floats list
     796                 :   nsFrameList* GetPushedFloats() const;
     797                 :   // Get the pushed floats list, or if there is not currently one,
     798                 :   // make a new empty one.
     799                 :   nsFrameList* EnsurePushedFloats();
     800                 :   // Remove and return the pushed floats list.
     801                 :   nsFrameList* RemovePushedFloats();
     802                 : 
     803                 : #ifdef NS_DEBUG
     804                 :   void VerifyLines(bool aFinalCheckOK);
     805                 :   void VerifyOverflowSituation();
     806                 :   PRInt32 GetDepth() const;
     807                 : #endif
     808                 : 
     809                 :   nscoord mMinWidth, mPrefWidth;
     810                 : 
     811                 :   nsLineList mLines;
     812                 : 
     813                 :   // List of all floats in this block
     814                 :   // XXXmats blocks rarely have floats, make it a frame property
     815                 :   nsFrameList mFloats;
     816                 : 
     817                 :   friend class nsBlockReflowState;
     818                 :   friend class nsBlockInFlowLineIterator;
     819                 : 
     820                 : #ifdef DEBUG
     821                 : public:
     822                 :   static bool gLamePaintMetrics;
     823                 :   static bool gLameReflowMetrics;
     824                 :   static bool gNoisy;
     825                 :   static bool gNoisyDamageRepair;
     826                 :   static bool gNoisyIntrinsic;
     827                 :   static bool gNoisyReflow;
     828                 :   static bool gReallyNoisyReflow;
     829                 :   static bool gNoisyFloatManager;
     830                 :   static bool gVerifyLines;
     831                 :   static bool gDisableResizeOpt;
     832                 : 
     833                 :   static PRInt32 gNoiseIndent;
     834                 : 
     835                 :   static const char* kReflowCommandType[];
     836                 : 
     837                 : protected:
     838                 :   static void InitDebugFlags();
     839                 : #endif
     840                 : };
     841                 : 
     842                 : #ifdef DEBUG
     843                 : class AutoNoisyIndenter {
     844                 : public:
     845               0 :   AutoNoisyIndenter(bool aDoIndent) : mIndented(aDoIndent) {
     846               0 :     if (mIndented) {
     847               0 :       nsBlockFrame::gNoiseIndent++;
     848                 :     }
     849               0 :   }
     850               0 :   ~AutoNoisyIndenter() {
     851               0 :     if (mIndented) {
     852               0 :       nsBlockFrame::gNoiseIndent--;
     853                 :     }
     854               0 :   }
     855                 : private:
     856                 :   bool mIndented;
     857                 : };
     858                 : #endif
     859                 : 
     860                 : /**
     861                 :  * Iterates over all lines in the prev-in-flows/next-in-flows of this block.
     862                 :  */
     863               0 : class nsBlockInFlowLineIterator {
     864                 : public:
     865                 :   typedef nsBlockFrame::line_iterator line_iterator;
     866                 :   /**
     867                 :    * Set up the iterator to point to aLine which must be a normal line
     868                 :    * in aFrame (not an overflow line).
     869                 :    */
     870                 :   nsBlockInFlowLineIterator(nsBlockFrame* aFrame, line_iterator aLine);
     871                 :   /**
     872                 :    * Set up the iterator to point to the first line found starting from
     873                 :    * aFrame. Sets aFoundValidLine to false if there is no such line.
     874                 :    * After aFoundValidLine has returned false, don't call any methods on this
     875                 :    * object again.
     876                 :    */
     877                 :   nsBlockInFlowLineIterator(nsBlockFrame* aFrame, bool* aFoundValidLine);
     878                 :   /**
     879                 :    * Set up the iterator to point to the line that contains aFindFrame (either
     880                 :    * directly or indirectly).  If aFrame is out of flow, or contained in an
     881                 :    * out-of-flow, finds the line containing the out-of-flow's placeholder. If
     882                 :    * the frame is not found, sets aFoundValidLine to false. After
     883                 :    * aFoundValidLine has returned false, don't call any methods on this
     884                 :    * object again.
     885                 :    */
     886                 :   nsBlockInFlowLineIterator(nsBlockFrame* aFrame, nsIFrame* aFindFrame,
     887                 :                             bool* aFoundValidLine);
     888                 : 
     889               0 :   line_iterator GetLine() { return mLine; }
     890                 :   bool IsLastLineInList();
     891               0 :   nsBlockFrame* GetContainer() { return mFrame; }
     892                 :   bool GetInOverflow() { return mInOverflowLines != nsnull; }
     893                 : 
     894                 :   /**
     895                 :    * Returns the current line list we're iterating, null means
     896                 :    * we're iterating |mLines| of the container.
     897                 :    */
     898               0 :   nsLineList* GetLineList() { return mInOverflowLines; }
     899                 : 
     900                 :   /**
     901                 :    * Returns the end-iterator of whatever line list we're in.
     902                 :    */
     903                 :   line_iterator End();
     904                 : 
     905                 :   /**
     906                 :    * Returns false if there are no more lines. After this has returned false,
     907                 :    * don't call any methods on this object again.
     908                 :    */
     909                 :   bool Next();
     910                 :   /**
     911                 :    * Returns false if there are no more lines. After this has returned false,
     912                 :    * don't call any methods on this object again.
     913                 :    */
     914                 :   bool Prev();
     915                 : 
     916                 : private:
     917                 :   friend class nsBlockFrame;
     918                 :   // XXX nsBlockFrame uses this internally in one place.  Try to remove it.
     919                 :   nsBlockInFlowLineIterator(nsBlockFrame* aFrame, line_iterator aLine, bool aInOverflow);
     920                 : 
     921                 :   nsBlockFrame* mFrame;
     922                 :   line_iterator mLine;
     923                 :   nsLineList*   mInOverflowLines;
     924                 : 
     925                 :   /**
     926                 :    * Moves iterator to next valid line reachable from the current block.
     927                 :    * Returns false if there are no valid lines.
     928                 :    */
     929                 :   bool FindValidLine();
     930                 : };
     931                 : 
     932                 : #endif /* nsBlockFrame_h___ */

Generated by: LCOV version 1.7