layout/tables/nsTableRowGroupFrame.h

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rw-r--r--

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #ifndef nsTableRowGroupFrame_h__
     6 #define nsTableRowGroupFrame_h__
     8 #include "mozilla/Attributes.h"
     9 #include "nscore.h"
    10 #include "nsContainerFrame.h"
    11 #include "nsIAtom.h"
    12 #include "nsILineIterator.h"
    13 #include "nsTablePainter.h"
    14 #include "nsTArray.h"
    16 class nsTableFrame;
    17 class nsTableRowFrame;
    18 class nsTableCellFrame;
    20 struct nsRowGroupReflowState {
    21   const nsHTMLReflowState& reflowState;  // Our reflow state
    23   nsTableFrame* tableFrame;
    25   // The available size (computed from the parent)
    26   nsSize availSize;
    28   // Running y-offset
    29   nscoord y;
    31   nsRowGroupReflowState(const nsHTMLReflowState& aReflowState,
    32                         nsTableFrame*            aTableFrame)
    33       :reflowState(aReflowState), tableFrame(aTableFrame)
    34   {
    35     availSize.width  = reflowState.AvailableWidth();
    36     availSize.height = reflowState.AvailableHeight();
    37     y = 0;  
    38   }
    40   ~nsRowGroupReflowState() {}
    41 };
    43 #define MIN_ROWS_NEEDING_CURSOR 20
    45 /**
    46  * nsTableRowGroupFrame is the frame that maps row groups 
    47  * (HTML tags THEAD, TFOOT, and TBODY). This class cannot be reused
    48  * outside of an nsTableFrame.  It assumes that its parent is an nsTableFrame, and 
    49  * its children are nsTableRowFrames.
    50  * 
    51  * @see nsTableFrame
    52  * @see nsTableRowFrame
    53  */
    54 class nsTableRowGroupFrame
    55   : public nsContainerFrame
    56   , public nsILineIterator
    57 {
    58 public:
    59   NS_DECL_QUERYFRAME_TARGET(nsTableRowGroupFrame)
    60   NS_DECL_QUERYFRAME
    61   NS_DECL_FRAMEARENA_HELPERS
    63   /** instantiate a new instance of nsTableRowFrame.
    64     * @param aPresShell the pres shell for this frame
    65     *
    66     * @return           the frame that was created
    67     */
    68   friend nsIFrame* NS_NewTableRowGroupFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
    69   virtual ~nsTableRowGroupFrame();
    71   virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE;
    73   /** @see nsIFrame::DidSetStyleContext */
    74   virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) MOZ_OVERRIDE;
    76   virtual nsresult AppendFrames(ChildListID     aListID,
    77                                 nsFrameList&    aFrameList) MOZ_OVERRIDE;
    79   virtual nsresult InsertFrames(ChildListID     aListID,
    80                                 nsIFrame*       aPrevFrame,
    81                                 nsFrameList&    aFrameList) MOZ_OVERRIDE;
    83   virtual nsresult RemoveFrame(ChildListID     aListID,
    84                                nsIFrame*       aOldFrame) MOZ_OVERRIDE;
    86   virtual nsMargin GetUsedMargin() const MOZ_OVERRIDE;
    87   virtual nsMargin GetUsedBorder() const MOZ_OVERRIDE;
    88   virtual nsMargin GetUsedPadding() const MOZ_OVERRIDE;
    90   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
    91                                 const nsRect&           aDirtyRect,
    92                                 const nsDisplayListSet& aLists) MOZ_OVERRIDE;
    94    /** calls Reflow for all of its child rows.
    95     * Rows are all set to the same width and stacked vertically.
    96     * <P> rows are not split unless absolutely necessary.
    97     *
    98     * @param aDesiredSize width set to width of rows, height set to 
    99     *                     sum of height of rows that fit in aMaxSize.height.
   100     *
   101     * @see nsIFrame::Reflow
   102     */
   103   virtual nsresult Reflow(nsPresContext*           aPresContext,
   104                           nsHTMLReflowMetrics&     aDesiredSize,
   105                           const nsHTMLReflowState& aReflowState,
   106                           nsReflowStatus&          aStatus) MOZ_OVERRIDE;
   108   virtual bool UpdateOverflow() MOZ_OVERRIDE;
   110   /**
   111    * Get the "type" of the frame
   112    *
   113    * @see nsGkAtoms::tableRowGroupFrame
   114    */
   115   virtual nsIAtom* GetType() const MOZ_OVERRIDE;
   117   nsTableRowFrame* GetFirstRow();
   119 #ifdef DEBUG_FRAME_DUMP
   120   virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE;
   121 #endif
   123   /** return the number of child rows (not necessarily == number of child frames) */
   124   int32_t GetRowCount();
   126   /** return the table-relative row index of the first row in this rowgroup.
   127     * if there are no rows, -1 is returned.
   128     */
   129   int32_t GetStartRowIndex();
   131   /** Adjust the row indices of all rows  whose index is >= aRowIndex.  
   132     * @param aRowIndex   - start adjusting with this index
   133     * @param aAdjustment - shift the row index by this amount
   134     */
   135   void AdjustRowIndices(int32_t   aRowIndex,
   136                         int32_t   anAdjustment);
   138   /**
   139    * Used for header and footer row group frames that are repeated when
   140    * splitting a table frame.
   141    *
   142    * Performs any table specific initialization
   143    *
   144    * @param aHeaderFooterFrame the original header or footer row group frame
   145    * that was repeated
   146    */
   147   nsresult  InitRepeatedFrame(nsPresContext*        aPresContext,
   148                               nsTableRowGroupFrame* aHeaderFooterFrame);
   151   /**
   152    * Get the total height of all the row rects
   153    */
   154   nscoord GetHeightBasis(const nsHTMLReflowState& aReflowState);
   156   nsMargin* GetBCBorderWidth(nsMargin& aBorder);
   158   /**
   159    * Gets inner border widths before collapsing with cell borders
   160    * Caller must get top border from previous row group or from table
   161    * GetContinuousBCBorderWidth will not overwrite aBorder.top
   162    * see nsTablePainter about continuous borders
   163    */
   164   void GetContinuousBCBorderWidth(nsMargin& aBorder);
   165   /**
   166    * Sets full border widths before collapsing with cell borders
   167    * @param aForSide - side to set; only right, left, and bottom valid
   168    */
   169   void SetContinuousBCBorderWidth(uint8_t     aForSide,
   170                                   BCPixelSize aPixelValue);
   171   /**
   172     * Adjust to the effect of visibibility:collapse on the row group and
   173     * its children
   174     * @return              additional shift upward that should be applied to
   175     *                      subsequent rowgroups due to rows and this rowgroup
   176     *                      being collapsed
   177     * @param aYTotalOffset the total amount that the rowgroup is shifted up
   178     * @param aWidth        new width of the rowgroup
   179     */
   180   nscoord CollapseRowGroupIfNecessary(nscoord aYTotalOffset,
   181                                       nscoord aWidth);
   183 // nsILineIterator methods
   184 public:
   185   virtual void DisposeLineIterator() MOZ_OVERRIDE { }
   187   // The table row is the equivalent to a line in block layout. 
   188   // The nsILineIterator assumes that a line resides in a block, this role is
   189   // fullfilled by the row group. Rows in table are counted relative to the
   190   // table. The row index of row corresponds to the cellmap coordinates. The
   191   // line index with respect to a row group can be computed by substracting the
   192   // row index of the first row in the row group.
   194   /** Get the number of rows in a row group
   195     * @return the number of lines in a row group
   196     */
   197   virtual int32_t GetNumLines() MOZ_OVERRIDE;
   199   /** @see nsILineIterator.h GetDirection
   200     * @return true if the table is rtl
   201     */
   202   virtual bool GetDirection() MOZ_OVERRIDE;
   204   /** Return structural information about a line. 
   205     * @param aLineNumber       - the index of the row relative to the row group
   206     *                            If the line-number is invalid then
   207     *                            aFirstFrameOnLine will be nullptr and 
   208     *                            aNumFramesOnLine will be zero.
   209     * @param aFirstFrameOnLine - the first cell frame that originates in row
   210     *                            with a rowindex that matches a line number
   211     * @param aNumFramesOnLine  - return the numbers of cells originating in
   212     *                            this row
   213     * @param aLineBounds       - rect of the row
   214     * @param aLineFlags        - unused set to 0
   215     */
   216   NS_IMETHOD GetLine(int32_t aLineNumber,
   217                      nsIFrame** aFirstFrameOnLine,
   218                      int32_t* aNumFramesOnLine,
   219                      nsRect& aLineBounds,
   220                      uint32_t* aLineFlags) MOZ_OVERRIDE;
   222   /** Given a frame that's a child of the rowgroup, find which line its on.
   223     * @param aFrame       - frame, should be a row
   224     * @param aStartLine   - minimal index to return
   225     * @return               row index relative to the row group if this a row
   226     *                       frame and the index is at least aStartLine.
   227     *                       -1 if the frame cannot be found.
   228     */
   229   virtual int32_t FindLineContaining(nsIFrame* aFrame, int32_t aStartLine = 0) MOZ_OVERRIDE;
   231   /** Find the orginating cell frame on a row that is the nearest to the
   232     * coordinate X.
   233     * @param aLineNumber          - the index of the row relative to the row group
   234     * @param aX                   - X coordinate in twips relative to the
   235     *                               origin of the row group
   236     * @param aFrameFound          - pointer to the cellframe
   237     * @param aXIsBeforeFirstFrame - the point is before the first originating
   238     *                               cellframe
   239     * @param aXIsAfterLastFrame   - the point is after the last originating
   240     *                               cellframe
   241     */
   242   NS_IMETHOD FindFrameAt(int32_t aLineNumber,
   243                          nscoord aX,
   244                          nsIFrame** aFrameFound,
   245                          bool* aXIsBeforeFirstFrame,
   246                          bool* aXIsAfterLastFrame) MOZ_OVERRIDE;
   248    /** Check whether visual and logical order of cell frames within a line are
   249      * identical. As the layout will reorder them this is always the case
   250      * @param aLine        - the index of the row relative to the table
   251      * @param aIsReordered - returns false
   252      * @param aFirstVisual - if the table is rtl first originating cell frame
   253      * @param aLastVisual  - if the table is rtl last originating cell frame
   254      */
   256   NS_IMETHOD CheckLineOrder(int32_t                  aLine,
   257                             bool                     *aIsReordered,
   258                             nsIFrame                 **aFirstVisual,
   259                             nsIFrame                 **aLastVisual) MOZ_OVERRIDE;
   261   /** Find the next originating cell frame that originates in the row.    
   262     * @param aFrame      - cell frame to start with, will return the next cell
   263     *                      originating in a row
   264     * @param aLineNumber - the index of the row relative to the table
   265     */  
   266   NS_IMETHOD GetNextSiblingOnLine(nsIFrame*& aFrame, int32_t aLineNumber) MOZ_OVERRIDE;
   268   // row cursor methods to speed up searching for the row(s)
   269   // containing a point. The basic idea is that we set the cursor
   270   // property if the rows' y and yMosts are non-decreasing (considering only
   271   // rows with nonempty overflowAreas --- empty overflowAreas never participate
   272   // in event handling or painting), and the rowgroup has sufficient number of
   273   // rows. The cursor property points to a "recently used" row. If we get a
   274   // series of requests that work on rows "near" the cursor, then we can find
   275   // those nearby rows quickly by starting our search at the cursor.
   276   // This code is based on the line cursor code in nsBlockFrame. It's more general
   277   // though, and could be extracted and used elsewhere.
   278   struct FrameCursorData {
   279     nsTArray<nsIFrame*> mFrames;
   280     uint32_t            mCursorIndex;
   281     nscoord             mOverflowAbove;
   282     nscoord             mOverflowBelow;
   284     FrameCursorData()
   285       : mFrames(MIN_ROWS_NEEDING_CURSOR), mCursorIndex(0), mOverflowAbove(0),
   286         mOverflowBelow(0) {}
   288     bool AppendFrame(nsIFrame* aFrame);
   290     void FinishBuildingCursor() {
   291       mFrames.Compact();
   292     }
   293   };
   295   // Clear out row cursor because we're disturbing the rows (e.g., Reflow)
   296   void ClearRowCursor();
   298   /**
   299    * Get the first row that might contain y-coord 'aY', or nullptr if you must search
   300    * all rows.
   301    * The actual row returned might not contain 'aY', but if not, it is guaranteed
   302    * to be before any row which does contain 'aY'.
   303    * aOverflowAbove is the maximum over all rows of -row.GetOverflowRect().y.
   304    * To find all rows that intersect the vertical interval aY/aYMost, call
   305    * GetFirstRowContaining(aY, &overflowAbove), and then iterate through all
   306    * rows until reaching a row where row->GetRect().y - overflowAbove >= aYMost.
   307    * That row and all subsequent rows cannot intersect the interval.
   308    */
   309   nsIFrame* GetFirstRowContaining(nscoord aY, nscoord* aOverflowAbove);
   311   /**
   312    * Set up the row cursor. After this, call AppendFrame for every
   313    * child frame in sibling order. Ensure that the child frame y and YMost values
   314    * form non-decreasing sequences (should always be true for table rows);
   315    * if this is violated, call ClearRowCursor(). If we return nullptr, then we
   316    * decided not to use a cursor or we already have one set up.
   317    */
   318   FrameCursorData* SetupRowCursor();
   320   virtual nsILineIterator* GetLineIterator() MOZ_OVERRIDE { return this; }
   322   virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE
   323   {
   324     return nsContainerFrame::IsFrameOfType(aFlags & ~(nsIFrame::eTablePart));
   325   }
   327   virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0) MOZ_OVERRIDE;
   328   virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0) MOZ_OVERRIDE;
   329   virtual void InvalidateFrameForRemoval() MOZ_OVERRIDE { InvalidateFrameSubtree(); }
   331 protected:
   332   nsTableRowGroupFrame(nsStyleContext* aContext);
   334   void InitChildReflowState(nsPresContext&     aPresContext, 
   335                             bool               aBorderCollapse,
   336                             nsHTMLReflowState& aReflowState);
   338   virtual int GetLogicalSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const MOZ_OVERRIDE;
   340   void PlaceChild(nsPresContext*         aPresContext,
   341                   nsRowGroupReflowState& aReflowState,
   342                   nsIFrame*              aKidFrame,
   343                   nsHTMLReflowMetrics&   aDesiredSize,
   344                   const nsRect&          aOriginalKidRect,
   345                   const nsRect&          aOriginalKidVisualOverflow);
   347   void CalculateRowHeights(nsPresContext*           aPresContext, 
   348                            nsHTMLReflowMetrics&     aDesiredSize,
   349                            const nsHTMLReflowState& aReflowState);
   351   void DidResizeRows(nsHTMLReflowMetrics& aDesiredSize);
   353   void SlideChild(nsRowGroupReflowState& aReflowState,
   354                   nsIFrame*              aKidFrame);
   356   /**
   357    * Reflow the frames we've already created
   358    *
   359    * @param   aPresContext presentation context to use
   360    * @param   aReflowState current inline state
   361    * @return  true if we successfully reflowed all the mapped children and false
   362    *            otherwise, e.g. we pushed children to the next in flow
   363    */
   364   nsresult ReflowChildren(nsPresContext*         aPresContext,
   365                           nsHTMLReflowMetrics&   aDesiredSize,
   366                           nsRowGroupReflowState& aReflowState,
   367                           nsReflowStatus&        aStatus,
   368                           bool*                aPageBreakBeforeEnd = nullptr);
   370   nsresult SplitRowGroup(nsPresContext*           aPresContext,
   371                          nsHTMLReflowMetrics&     aDesiredSize,
   372                          const nsHTMLReflowState& aReflowState,
   373                          nsTableFrame*            aTableFrame,
   374                          nsReflowStatus&          aStatus,
   375                          bool                     aRowForcedPageBreak);
   377   void SplitSpanningCells(nsPresContext&           aPresContext,
   378                           const nsHTMLReflowState& aReflowState,
   379                           nsTableFrame&            aTableFrame,
   380                           nsTableRowFrame&         aFirstRow, 
   381                           nsTableRowFrame&         aLastRow,  
   382                           bool                     aFirstRowIsTopOfPage,
   383                           nscoord                  aSpanningRowBottom,
   384                           nsTableRowFrame*&        aContRowFrame,
   385                           nsTableRowFrame*&        aFirstTruncatedRow,
   386                           nscoord&                 aDesiredHeight);
   388   void CreateContinuingRowFrame(nsPresContext& aPresContext,
   389                                 nsIFrame&      aRowFrame,
   390                                 nsIFrame**     aContRowFrame);
   392   bool IsSimpleRowFrame(nsTableFrame* aTableFrame, 
   393                           nsIFrame*     aFrame);
   395   void GetNextRowSibling(nsIFrame** aRowFrame);
   397   void UndoContinuedRow(nsPresContext*   aPresContext,
   398                         nsTableRowFrame* aRow);
   400 private:
   401   // border widths in pixels in the collapsing border model
   402   BCPixelSize mRightContBorderWidth;
   403   BCPixelSize mBottomContBorderWidth;
   404   BCPixelSize mLeftContBorderWidth;
   406 public:
   407   bool IsRepeatable() const;
   408   void   SetRepeatable(bool aRepeatable);
   409   bool HasStyleHeight() const;
   410   void   SetHasStyleHeight(bool aValue);
   411   bool HasInternalBreakBefore() const;
   412   bool HasInternalBreakAfter() const;
   413 };
   416 inline bool nsTableRowGroupFrame::IsRepeatable() const
   417 {
   418   return (mState & NS_ROWGROUP_REPEATABLE) == NS_ROWGROUP_REPEATABLE;
   419 }
   421 inline void nsTableRowGroupFrame::SetRepeatable(bool aRepeatable)
   422 {
   423   if (aRepeatable) {
   424     mState |= NS_ROWGROUP_REPEATABLE;
   425   } else {
   426     mState &= ~NS_ROWGROUP_REPEATABLE;
   427   }
   428 }
   430 inline bool nsTableRowGroupFrame::HasStyleHeight() const
   431 {
   432   return (mState & NS_ROWGROUP_HAS_STYLE_HEIGHT) == NS_ROWGROUP_HAS_STYLE_HEIGHT;
   433 }
   435 inline void nsTableRowGroupFrame::SetHasStyleHeight(bool aValue)
   436 {
   437   if (aValue) {
   438     mState |= NS_ROWGROUP_HAS_STYLE_HEIGHT;
   439   } else {
   440     mState &= ~NS_ROWGROUP_HAS_STYLE_HEIGHT;
   441   }
   442 }
   444 inline void
   445 nsTableRowGroupFrame::GetContinuousBCBorderWidth(nsMargin& aBorder)
   446 {
   447   int32_t aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel();
   448   aBorder.right = BC_BORDER_LEFT_HALF_COORD(aPixelsToTwips,
   449                                             mRightContBorderWidth);
   450   aBorder.bottom = BC_BORDER_TOP_HALF_COORD(aPixelsToTwips,
   451                                             mBottomContBorderWidth);
   452   aBorder.left = BC_BORDER_RIGHT_HALF_COORD(aPixelsToTwips,
   453                                             mLeftContBorderWidth);
   454   return;
   455 }
   456 #endif

mercurial