Back to index

lightning-sunbird  0.9+nobinonly
nsHTMLReflowState.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 #ifndef nsHTMLReflowState_h___
00038 #define nsHTMLReflowState_h___
00039 
00040 #include "nsMargin.h"
00041 #include "nsStyleCoord.h"
00042 
00043 class nsIFrame;
00044 class nsPresContext;
00045 class nsReflowPath;
00046 class nsIRenderingContext;
00047 class nsSpaceManager;
00048 class nsLineLayout;
00049 class nsIPercentHeightObserver;
00050 
00051 struct nsStyleDisplay;
00052 struct nsStyleVisibility;
00053 struct nsStylePosition;
00054 struct nsStyleBorder;
00055 struct nsStyleMargin;
00056 struct nsStylePadding;
00057 struct nsStyleText;
00058 struct nsHypotheticalBox;
00059 
00065 #define NS_UNCONSTRAINEDSIZE NS_MAXSIZE
00066 
00075 enum nsReflowReason {
00076   eReflowReason_Initial = 0,       // initial reflow of a newly created frame
00077   eReflowReason_Incremental = 1,   // an incremental change has occured. see the reflow command for details
00078   eReflowReason_Resize = 2,        // general request to determine a desired size
00079   eReflowReason_StyleChange = 3,   // request to reflow because of a style change. Note: you must reflow
00080                                    // all your child frames
00081   eReflowReason_Dirty = 4          // request to reflow because you and/or your children are dirty
00082 };
00083 
00087 typedef PRUint32  nsCSSFrameType;
00088 
00089 #define NS_CSS_FRAME_TYPE_UNKNOWN         0
00090 #define NS_CSS_FRAME_TYPE_INLINE          1
00091 #define NS_CSS_FRAME_TYPE_BLOCK           2  /* block-level in normal flow */
00092 #define NS_CSS_FRAME_TYPE_FLOATING        3
00093 #define NS_CSS_FRAME_TYPE_ABSOLUTE        4
00094 #define NS_CSS_FRAME_TYPE_INTERNAL_TABLE  5  /* row group frame, row frame, cell frame, ... */
00095 
00100 #define NS_CSS_FRAME_TYPE_REPLACED        0x8000
00101 
00105 #define NS_FRAME_IS_REPLACED(_ft) \
00106   (NS_CSS_FRAME_TYPE_REPLACED == ((_ft) & NS_CSS_FRAME_TYPE_REPLACED))
00107 
00108 #define NS_FRAME_REPLACED(_ft) \
00109   (NS_CSS_FRAME_TYPE_REPLACED | (_ft))
00110 
00114 #define NS_FRAME_GET_TYPE(_ft) \
00115   ((_ft) & ~NS_CSS_FRAME_TYPE_REPLACED)
00116 
00117 #define NS_INTRINSICSIZE    NS_UNCONSTRAINEDSIZE
00118 #define NS_SHRINKWRAPWIDTH  NS_UNCONSTRAINEDSIZE
00119 #define NS_AUTOHEIGHT       NS_UNCONSTRAINEDSIZE
00120 #define NS_AUTOMARGIN       NS_UNCONSTRAINEDSIZE
00121 #define NS_AUTOOFFSET       NS_UNCONSTRAINEDSIZE
00122 // NOTE: there are assumptions all over that these have the same value, namely NS_UNCONSTRAINEDSIZE
00123 //       if any are changed to be a value other than NS_UNCONSTRAINEDSIZE
00124 //       at least update AdjustComputedHeight/Width and test ad nauseum
00125 
00131 struct nsHTMLReflowState {
00132   // the reflow states are linked together. this is the pointer to the
00133   // parent's reflow state
00134   const nsHTMLReflowState* parentReflowState;
00135 
00136   // the frame being reflowed
00137   nsIFrame*           frame;
00138 
00139   // the reason for the reflow
00140   nsReflowReason      reason;
00141 
00142   // the incremental reflow path, when the reflow reason is
00143   // eReflowReason_Incremental. Specifically, this corresponds to the
00144   // portion of the incremental reflow path from `frame' down. Note
00145   // that it is safe to assume that this is non-null: we maintain the
00146   // invariant that it contains a valid nsReflowPath pointer when
00147   // reason == eReflowReason_Incremental.
00148   nsReflowPath        *path;
00149 
00150   // the available width in which to reflow the frame. The space
00151   // represents the amount of room for the frame's border, padding,
00152   // and content area (not the margin area. The parent frame deals
00153   // with the child frame's margins). The frame size you choose should
00154   // fit within the available width.
00155   nscoord              availableWidth;
00156 
00157   // A value of NS_UNCONSTRAINEDSIZE for the available height means
00158   // you can choose whatever size you want. In galley mode the
00159   // available height is always NS_UNCONSTRAINEDSIZE, and only page
00160   // mode involves a constrained height. The element's the top border
00161   // and padding, and content, must fit. If the element is complete
00162   // after reflow then its bottom border, padding and margin (and
00163   // similar for its complete ancestors) will need to fit in this
00164   // height.
00165   nscoord              availableHeight;
00166 
00167   // rendering context to use for measurement
00168   nsIRenderingContext* rendContext;
00169 
00170   // The type of frame, from css's perspective. This value is
00171   // initialized by the Init method below.
00172   nsCSSFrameType   mFrameType;
00173 
00174   // pointer to the space manager associated with this area
00175   nsSpaceManager* mSpaceManager;
00176 
00177   // LineLayout object (only for inline reflow; set to NULL otherwise)
00178   nsLineLayout*    mLineLayout;
00179 
00180   // The appropriate reflow state for the containing block (for
00181   // percentage widths, etc.) of this reflow state's frame.
00182   const nsHTMLReflowState *mCBReflowState;
00183 
00184   // The computed width specifies the frame's content area width, and it does
00185   // not apply to inline non-replaced elements
00186   //
00187   // For replaced inline frames, a value of NS_INTRINSICSIZE means you should
00188   // use your intrinsic width as the computed width
00189   //
00190   // For block-level frames, the computed width is based on the width of the
00191   // containing block, the margin/border/padding areas, and the min/max width.
00192   // A value of NS_SHRINKWRAPWIDTH means that you should choose a width based
00193   // on your content. The width may be as large as the specified maximum width
00194   // (see mComputedMaxWidth).
00195   nscoord          mComputedWidth; 
00196 
00197   // The computed height specifies the frame's content height, and it does
00198   // not apply to inline non-replaced elements
00199   //
00200   // For replaced inline frames, a value of NS_INTRINSICSIZE means you should
00201   // use your intrinsic height as the computed height
00202   //
00203   // For non-replaced block-level frames in the flow and floated, a value of
00204   // NS_AUTOHEIGHT means you choose a height to shrink wrap around the normal
00205   // flow child frames. The height must be within the limit of the min/max
00206   // height if there is such a limit
00207   //
00208   // For replaced block-level frames, a value of NS_INTRINSICSIZE
00209   // means you use your intrinsic height as the computed height
00210   nscoord          mComputedHeight;
00211 
00212   // Computed margin values
00213   nsMargin         mComputedMargin;
00214 
00215   // Cached copy of the border values
00216   nsMargin         mComputedBorderPadding;
00217 
00218   // Computed padding values
00219   nsMargin         mComputedPadding;
00220 
00221   // Computed values for 'left/top/right/bottom' offsets. Only applies to
00222   // 'positioned' elements
00223   nsMargin         mComputedOffsets;
00224 
00225   // Computed values for 'min-width/max-width' and 'min-height/max-height'
00226   nscoord          mComputedMinWidth, mComputedMaxWidth;
00227   nscoord          mComputedMinHeight, mComputedMaxHeight;
00228 
00229   // Compact margin available space
00230   nscoord          mCompactMarginWidth;
00231 
00232   // Cached pointers to the various style structs used during intialization
00233   const nsStyleDisplay*    mStyleDisplay;
00234   const nsStyleVisibility* mStyleVisibility;
00235   const nsStylePosition*   mStylePosition;
00236   const nsStyleBorder*     mStyleBorder;
00237   const nsStyleMargin*     mStyleMargin;
00238   const nsStylePadding*    mStylePadding;
00239   const nsStyleText*       mStyleText;
00240 
00241   // a frame (e.g. nsTableCellFrame) which may need to generate a special 
00242   // reflow for percent height calculations 
00243   nsIPercentHeightObserver* mPercentHeightObserver;
00244 
00245   // a frame (e.g. nsTableFrame) which initiates a special reflow for percent height calculations 
00246   nsIFrame* mPercentHeightReflowInitiator;
00247 
00248   // CSS margin collapsing sometimes requires us to reflow
00249   // optimistically assuming that margins collapse to see if clearance
00250   // is required. When we discover that clearance is required, we
00251   // store the frame in which clearance was discovered to the location
00252   // requested here.
00253   nsIFrame** mDiscoveredClearance;
00254 
00255   // This value keeps track of how deeply nested a given reflow state
00256   // is from the top of the frame tree.
00257   PRInt16 mReflowDepth;
00258 
00259   struct ReflowStateFlags {
00260     PRUint16 mSpecialHeightReflow:1; // used by tables to communicate special reflow (in process) to handle
00261                                      // percent height frames inside cells which may not have computed heights
00262     PRUint16 mNextInFlowUntouched:1; // nothing in the frame's next-in-flow (or its descendants)
00263                                      // is changing
00264     PRUint16 mIsTopOfPage:1;         // is the current context at the top of a page?
00265     PRUint16 mBlinks:1;              // Keep track of text-decoration: blink
00266     PRUint16 mVisualBidiFormControl:1; // Keep track of descendants of form controls on Visual Bidi pages
00267     PRUint16 mHasClearance:1;        // Block has clearance
00268     PRUint16 mAssumingHScrollbar:1;  // parent frame is an nsIScrollableFrame and it
00269                                      // is assuming a horizontal scrollbar
00270     PRUint16 mAssumingVScrollbar:1;  // parent frame is an nsIScrollableFrame and it
00271                                      // is assuming a vertical scrollbar
00272   } mFlags;
00273 
00274 #ifdef IBMBIDI
00275   nscoord mRightEdge;
00276 #endif
00277 
00278 #ifdef DEBUG
00279   // hook for attaching debug info (e.g. tables may attach a timer during reflow)
00280   void* mDebugHook;
00281 
00282   static const char* ReasonToString(nsReflowReason aReason);
00283 #endif
00284 
00285   // Note: The copy constructor is written by the compiler automatically. You
00286   // can use that and then override specific values if you want, or you can
00287   // call Init as desired...
00288 
00289   // Initialize a <b>root</b> reflow state with a rendering context to
00290   // use for measuring things.
00291   nsHTMLReflowState(nsPresContext*          aPresContext,
00292                     nsIFrame*                aFrame,
00293                     nsReflowReason           aReason,
00294                     nsIRenderingContext*     aRenderingContext,
00295                     const nsSize&            aAvailableSpace);
00296 
00297   // Initialize a <b>root</b> reflow state for an <b>incremental</b>
00298   // reflow.
00299   nsHTMLReflowState(nsPresContext*          aPresContext,
00300                     nsIFrame*                aFrame,
00301                     nsReflowPath*            aReflowPath,
00302                     nsIRenderingContext*     aRenderingContext,
00303                     const nsSize&            aAvailableSpace);
00304 
00305   // Initialize a reflow state for a child frames reflow. Some state
00306   // is copied from the parent reflow state; the remaining state is
00307   // computed. 
00308   nsHTMLReflowState(nsPresContext*          aPresContext,
00309                     const nsHTMLReflowState& aParentReflowState,
00310                     nsIFrame*                aFrame,
00311                     const nsSize&            aAvailableSpace,
00312                     nsReflowReason           aReason, 
00313                     PRBool                   aInit = PR_TRUE);
00314 
00315   // Same as the previous except that the reason is taken from the
00316   // parent's reflow state.
00317   nsHTMLReflowState(nsPresContext*          aPresContext,
00318                     const nsHTMLReflowState& aParentReflowState,
00319                     nsIFrame*                aFrame,
00320                     const nsSize&            aAvailableSpace);
00321 
00322   // Used when you want to override the default containing block
00323   // width and height. Used by absolute positioning code
00324   nsHTMLReflowState(nsPresContext*          aPresContext,
00325                     const nsHTMLReflowState& aParentReflowState,
00326                     nsIFrame*                aFrame,
00327                     const nsSize&            aAvailableSpace,
00328                     nscoord                  aContainingBlockWidth,
00329                     nscoord                  aContainingBlockHeight,
00330                     nsReflowReason           aReason);
00331 
00332   // This method initializes various data members. It is automatically
00333   // called by the various constructors
00334   void Init(nsPresContext* aPresContext,
00335             nscoord         aContainingBlockWidth = -1,
00336             nscoord         aContainingBlockHeight = -1,
00337             nsMargin*       aBorder = nsnull,
00338             nsMargin*       aPadding = nsnull);
00342   static nscoord
00343     GetContainingBlockContentWidth(const nsHTMLReflowState* aReflowState);
00344 
00349   nscoord AdjustIntrinsicMinContentWidthForStyle(nscoord aWidth) const;
00354   nscoord AdjustIntrinsicContentWidthForStyle(nscoord aWidth) const;
00355 
00361   static nsIFrame* GetContainingBlockFor(const nsIFrame* aFrame);
00362 
00368   static const nsHTMLReflowState*
00369     GetPageBoxReflowState(const nsHTMLReflowState* aParentRS);
00370 
00379   static void ComputeBorderPaddingFor(nsIFrame* aFrame,
00380                                       const nsHTMLReflowState* aParentRS,
00381                                       nsMargin& aResult);
00382 
00388   static nscoord CalcLineHeight(nsPresContext* aPresContext,
00389                                 nsIRenderingContext* aRenderingContext,
00390                                 nsIFrame* aFrame);
00391 
00392   void InitFrameType();
00393 
00394   void ComputeContainingBlockRectangle(nsPresContext*          aPresContext,
00395                                        const nsHTMLReflowState* aContainingBlockRS,
00396                                        nscoord&                 aContainingBlockWidth,
00397                                        nscoord&                 aContainingBlockHeight);
00398 
00399   void CalculateBlockSideMargins(nscoord aAvailWidth,
00400                                  nscoord aComputedWidth);
00401 
00407   void ApplyMinMaxConstraints(nscoord* aContentWidth, nscoord* aContentHeight) const;
00408 
00409 protected:
00410 
00411   void InitCBReflowState();
00412 
00413   void InitConstraints(nsPresContext* aPresContext,
00414                        nscoord         aContainingBlockWidth,
00415                        nscoord         aContainingBlockHeight,
00416                        nsMargin*       aBorder,
00417                        nsMargin*       aPadding);
00418 
00419   void CalculateHypotheticalBox(nsPresContext*    aPresContext,
00420                                 nsIFrame*          aPlaceholderFrame,
00421                                 nsIFrame*          aContainingBlock,
00422                                 nsMargin&          aBlockContentArea,
00423                                 const nsHTMLReflowState* cbrs,
00424                                 nsHypotheticalBox& aHypotheticalBox);
00425 
00426   void InitAbsoluteConstraints(nsPresContext* aPresContext,
00427                                const nsHTMLReflowState* cbrs,
00428                                nscoord aContainingBlockWidth,
00429                                nscoord aContainingBlockHeight);
00430 
00431   void ComputeRelativeOffsets(const nsHTMLReflowState* cbrs,
00432                               nscoord aContainingBlockWidth,
00433                               nscoord aContainingBlockHeight);
00434 
00435   void ComputeBlockBoxData(nsPresContext* aPresContext,
00436                            const nsHTMLReflowState* cbrs,
00437                            nsStyleUnit aWidthUnit,
00438                            nsStyleUnit aHeightUnit,
00439                            nscoord aContainingBlockWidth,
00440                            nscoord aContainingBlockHeight);
00441 
00442   void ComputeHorizontalValue(nscoord aContainingBlockWidth,
00443                                      nsStyleUnit aUnit,
00444                                      const nsStyleCoord& aCoord,
00445                                      nscoord& aResult);
00446 
00447   void ComputeVerticalValue(nscoord aContainingBlockHeight,
00448                                    nsStyleUnit aUnit,
00449                                    const nsStyleCoord& aCoord,
00450                                    nscoord& aResult);
00451 
00452   // Computes margin values from the specified margin style information, and
00453   // fills in the mComputedMargin member
00454   void ComputeMargin(nscoord aContainingBlockWidth,
00455                      const nsHTMLReflowState* aContainingBlockRS);
00456   
00457   // Computes padding values from the specified padding style information, and
00458   // fills in the mComputedPadding member
00459   void ComputePadding(nscoord aContainingBlockWidth,
00460                       const nsHTMLReflowState* aContainingBlockRS);
00461 
00462   // Calculates the computed values for the 'min-Width', 'max-Width',
00463   // 'min-Height', and 'max-Height' properties, and stores them in the assorted
00464   // data members
00465   void ComputeMinMaxValues(nscoord                  aContainingBlockWidth,
00466                            nscoord                  aContainingBlockHeight,
00467                            const nsHTMLReflowState* aContainingBlockRS);
00468 
00469   nscoord CalculateHorizBorderPaddingMargin(nscoord aContainingBlockWidth);
00470 
00471   // Adjust Computed sizes for Min/Max Width and box-Sizing (if
00472   // aAdjustForBoxSizing is true)  
00473   // - guarantees that the computed height/width will be non-negative
00474   //   If the value goes negative (because the padding or border is greater than
00475   //   the width/height and it is removed due to box sizing) then it is driven to 0
00476   void AdjustComputedHeight(PRBool aAdjustForBoxSizing);
00477   void AdjustComputedWidth(PRBool aAdjustForBoxSizing);
00478 
00479 #ifdef IBMBIDI
00480 
00488   PRBool IsBidiFormControl(nsPresContext* aPresContext);
00489 #endif
00490 };
00491 
00492 #endif /* nsHTMLReflowState_h___ */
00493