tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsTableRowGroupFrame.h (14700B)


      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__
      7 
      8 #include "mozilla/WritingModes.h"
      9 #include "nsAtom.h"
     10 #include "nsContainerFrame.h"
     11 #include "nsILineIterator.h"
     12 #include "nsTArray.h"
     13 #include "nsTableFrame.h"
     14 #include "nscore.h"
     15 
     16 class nsTableRowFrame;
     17 namespace mozilla {
     18 class PresShell;
     19 struct TableRowGroupReflowInput;
     20 }  // namespace mozilla
     21 
     22 #define MIN_ROWS_NEEDING_CURSOR 20
     23 
     24 /**
     25 * nsTableRowGroupFrame is the frame that maps row groups
     26 * (HTML tags THEAD, TFOOT, and TBODY). This class cannot be reused
     27 * outside of an nsTableFrame.  It assumes that its parent is an nsTableFrame,
     28 * and its children are nsTableRowFrames.
     29 *
     30 * @see nsTableFrame
     31 * @see nsTableRowFrame
     32 */
     33 class nsTableRowGroupFrame final : public nsContainerFrame,
     34                                   public nsILineIterator {
     35 public:
     36  NS_DECL_QUERYFRAME
     37  NS_DECL_FRAMEARENA_HELPERS(nsTableRowGroupFrame)
     38 
     39  /** instantiate a new instance of nsTableRowFrame.
     40   * @param aPresShell the pres shell for this frame
     41   *
     42   * @return           the frame that was created
     43   */
     44  friend nsTableRowGroupFrame* NS_NewTableRowGroupFrame(
     45      mozilla::PresShell* aPresShell, ComputedStyle* aStyle);
     46  virtual ~nsTableRowGroupFrame();
     47 
     48  // nsIFrame overrides
     49  void Init(nsIContent* aContent, nsContainerFrame* aParent,
     50            nsIFrame* aPrevInFlow) override {
     51    nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
     52    if (!aPrevInFlow) {
     53      mWritingMode = GetTableFrame()->GetWritingMode();
     54    }
     55  }
     56 
     57  void Destroy(DestroyContext&) override;
     58 
     59  /** @see nsIFrame::DidSetComputedStyle */
     60  void DidSetComputedStyle(ComputedStyle* aOldComputedStyle) override;
     61 
     62  void AppendFrames(ChildListID aListID, nsFrameList&& aFrameList) override;
     63  void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
     64                    const nsLineList::iterator* aPrevFrameLine,
     65                    nsFrameList&& aFrameList) override;
     66  void RemoveFrame(DestroyContext&, ChildListID, nsIFrame*) override;
     67 
     68  nsMargin GetUsedMargin() const override;
     69  nsMargin GetUsedBorder() const override;
     70  nsMargin GetUsedPadding() const override;
     71 
     72  void BuildDisplayList(nsDisplayListBuilder* aBuilder,
     73                        const nsDisplayListSet& aLists) override;
     74 
     75  /**
     76   * Calls Reflow for all of its child rows.
     77   *
     78   * Rows are all set to the same isize and stacked in the block direction.
     79   *
     80   * Rows are not split unless absolutely necessary.
     81   *
     82   * @param aDesiredSize isize set to isize of rows, bsize set to
     83   *                     sum of bsize of rows that fit in AvailableBSize.
     84   *
     85   * @see nsIFrame::Reflow
     86   */
     87  void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
     88              const ReflowInput& aReflowInput,
     89              nsReflowStatus& aStatus) override;
     90 
     91  bool ComputeCustomOverflow(mozilla::OverflowAreas& aOverflowAreas) override;
     92 
     93 #ifdef DEBUG_FRAME_DUMP
     94  nsresult GetFrameName(nsAString& aResult) const override;
     95 #endif
     96 
     97  nsTableRowFrame* GetFirstRow() const;
     98  nsTableRowFrame* GetLastRow() const;
     99 
    100  nsTableFrame* GetTableFrame() const {
    101    nsIFrame* parent = GetParent();
    102    MOZ_ASSERT(parent && parent->IsTableFrame());
    103    return static_cast<nsTableFrame*>(parent);
    104  }
    105 
    106  /** return the number of child rows (not necessarily == number of child
    107   * frames) */
    108  int32_t GetRowCount() const;
    109 
    110  /** return the table-relative row index of the first row in this rowgroup.
    111   * if there are no rows, -1 is returned.
    112   */
    113  int32_t GetStartRowIndex() const;
    114 
    115  /** Adjust the row indices of all rows  whose index is >= aRowIndex.
    116   * @param aRowIndex   - start adjusting with this index
    117   * @param aAdjustment - shift the row index by this amount
    118   */
    119  void AdjustRowIndices(int32_t aRowIndex, int32_t anAdjustment);
    120 
    121  // See nsTableFrame.h
    122  int32_t GetAdjustmentForStoredIndex(int32_t aStoredIndex);
    123 
    124  /* mark rows starting from aStartRowFrame to the next 'aNumRowsToRemove-1'
    125   * number of rows as deleted
    126   */
    127  void MarkRowsAsDeleted(nsTableRowFrame& aStartRowFrame,
    128                         int32_t aNumRowsToDelete);
    129 
    130  // See nsTableFrame.h
    131  void AddDeletedRowIndex(int32_t aDeletedRowStoredIndex);
    132 
    133  /**
    134   * Used for header and footer row group frames that are repeated when
    135   * splitting a table frame.
    136   *
    137   * Performs any table specific initialization
    138   *
    139   * @param aHeaderFooterFrame the original header or footer row group frame
    140   * that was repeated
    141   */
    142  void InitRepeatedFrame(nsTableRowGroupFrame* aHeaderFooterFrame);
    143 
    144  /**
    145   * Get the total bsize of all the row rects
    146   */
    147  nscoord GetBSizeBasis(const ReflowInput& aReflowInput);
    148 
    149  mozilla::LogicalMargin GetBCBorderWidth(mozilla::WritingMode aWM);
    150 
    151  /**
    152   * Adjust to the effect of visibility:collapse on the row group and
    153   * its children
    154   * @return              additional shift bstart-wards that should be applied
    155   *                      to subsequent rowgroups due to rows and this
    156   *                      rowgroup being collapsed
    157   * @param aBTotalOffset the total amount that the rowgroup is shifted
    158   * @param aISize        new isize of the rowgroup
    159   * @param aWM           the table's writing mode
    160   */
    161  nscoord CollapseRowGroupIfNecessary(nscoord aBTotalOffset, nscoord aISize,
    162                                      mozilla::WritingMode aWM);
    163 
    164  // nsILineIterator methods
    165 public:
    166  // The table row is the equivalent to a line in block layout.
    167  // The nsILineIterator assumes that a line resides in a block, this role is
    168  // fullfilled by the row group. Rows in table are counted relative to the
    169  // table. The row index of row corresponds to the cellmap coordinates. The
    170  // line index with respect to a row group can be computed by substracting the
    171  // row index of the first row in the row group.
    172 
    173  /** Get the number of rows in a row group
    174   * @return the number of lines in a row group
    175   */
    176  int32_t GetNumLines() const final;
    177 
    178  /** @see nsILineIterator.h IsLineIteratorFlowRTL */
    179  bool IsLineIteratorFlowRTL() final;
    180 
    181  /** Return structural information about a line. */
    182  Result<LineInfo, nsresult> GetLine(int32_t aLineNumber) final;
    183 
    184  /** Given a frame that's a child of the rowgroup, find which line its on.
    185   * @param aFrame       - frame, should be a row
    186   * @param aStartLine   - minimal index to return
    187   * @return               row index relative to the row group if this a row
    188   *                       frame and the index is at least aStartLine.
    189   *                       -1 if the frame cannot be found.
    190   */
    191  int32_t FindLineContaining(const nsIFrame* aFrame,
    192                             int32_t aStartLine = 0) final;
    193 
    194  /** Find the orginating cell frame on a row that is the nearest to the
    195   * inline-dir coordinate of aPos.
    196   * @param aLineNumber        - the index of the row relative to the row group
    197   * @param aPos               - coordinate in twips relative to the
    198   *                             origin of the row group
    199   * @param aFrameFound        - pointer to the cellframe
    200   * @param aPosIsBeforeFirstFrame - the point is before the first originating
    201   *                               cellframe
    202   * @param aPosIsAfterLastFrame   - the point is after the last originating
    203   *                               cellframe
    204   */
    205  NS_IMETHOD FindFrameAt(int32_t aLineNumber, nsPoint aPos,
    206                         nsIFrame** aFrameFound, bool* aPosIsBeforeFirstFrame,
    207                         bool* aPosIsAfterLastFrame) final;
    208 
    209  /** Check whether visual and logical order of cell frames within a line are
    210   * identical. As the layout will reorder them this is always the case
    211   * @param aLine        - the index of the row relative to the table
    212   * @param aIsReordered - returns false
    213   * @param aFirstVisual - if the table is rtl first originating cell frame
    214   * @param aLastVisual  - if the table is rtl last originating cell frame
    215   */
    216 
    217  NS_IMETHOD CheckLineOrder(int32_t aLine, bool* aIsReordered,
    218                            nsIFrame** aFirstVisual,
    219                            nsIFrame** aLastVisual) final;
    220 
    221  // row cursor methods to speed up searching for the row(s)
    222  // containing a point. The basic idea is that we set the cursor
    223  // property if the rows' y and yMosts are non-decreasing (considering only
    224  // rows with nonempty overflowAreas --- empty overflowAreas never participate
    225  // in event handling or painting), and the rowgroup has sufficient number of
    226  // rows. The cursor property points to a "recently used" row. If we get a
    227  // series of requests that work on rows "near" the cursor, then we can find
    228  // those nearby rows quickly by starting our search at the cursor.
    229  // This code is based on the line cursor code in nsBlockFrame. It's more
    230  // general though, and could be extracted and used elsewhere.
    231  struct FrameCursorData {
    232    nsTArray<nsIFrame*> mFrames;
    233    uint32_t mCursorIndex;
    234    nscoord mOverflowAbove;
    235    nscoord mOverflowBelow;
    236 
    237    FrameCursorData()
    238        : mFrames(MIN_ROWS_NEEDING_CURSOR),
    239          mCursorIndex(0),
    240          mOverflowAbove(0),
    241          mOverflowBelow(0) {}
    242 
    243    bool AppendFrame(nsIFrame* aFrame);
    244 
    245    void FinishBuildingCursor() { mFrames.Compact(); }
    246  };
    247 
    248  // Clear out row cursor because we're disturbing the rows (e.g., Reflow)
    249  void ClearRowCursor();
    250 
    251  /**
    252   * Get the first row that might contain y-coord 'aY', or nullptr if you must
    253   * search all rows.
    254   * The actual row returned might not contain 'aY', but if not, it is
    255   * guaranteed to be before any row which does contain 'aY'.
    256   * aOverflowAbove is the maximum over all rows of -row.GetOverflowRect().y.
    257   * To find all rows that intersect the vertical interval aY/aYMost, call
    258   * GetFirstRowContaining(aY, &overflowAbove), and then iterate through all
    259   * rows until reaching a row where row->GetRect().y - overflowAbove >= aYMost.
    260   * That row and all subsequent rows cannot intersect the interval.
    261   */
    262  nsIFrame* GetFirstRowContaining(nscoord aY, nscoord* aOverflowAbove);
    263 
    264  /**
    265   * Set up the row cursor. After this, call AppendFrame for every
    266   * child frame in sibling order. Ensure that the child frame y and YMost
    267   * values form non-decreasing sequences (should always be true for table
    268   * rows); if this is violated, call ClearRowCursor(). If we return nullptr,
    269   * then we decided not to use a cursor or we already have one set up.
    270   */
    271  FrameCursorData* SetupRowCursor();
    272 
    273  bool CanProvideLineIterator() const final { return true; }
    274  nsILineIterator* GetLineIterator() final { return this; }
    275 
    276  void InvalidateFrame(uint32_t aDisplayItemKey = 0,
    277                       bool aRebuildDisplayItems = true) override;
    278  void InvalidateFrameWithRect(const nsRect& aRect,
    279                               uint32_t aDisplayItemKey = 0,
    280                               bool aRebuildDisplayItems = true) override;
    281  void InvalidateFrameForRemoval() override { InvalidateFrameSubtree(); }
    282 
    283 protected:
    284  explicit nsTableRowGroupFrame(ComputedStyle* aStyle,
    285                                nsPresContext* aPresContext);
    286 
    287  void InitChildReflowInput(nsPresContext* aPresContext, bool aBorderCollapse,
    288                            ReflowInput& aReflowInput);
    289 
    290  LogicalSides GetLogicalSkipSides() const override;
    291 
    292  void PlaceChild(nsPresContext* aPresContext,
    293                  mozilla::TableRowGroupReflowInput& aReflowInput,
    294                  nsIFrame* aKidFrame, const ReflowInput& aKidReflowInput,
    295                  mozilla::WritingMode aWM,
    296                  const mozilla::LogicalPoint& aKidPosition,
    297                  const nsSize& aContainerSize, ReflowOutput& aDesiredSize,
    298                  const nsRect& aOriginalKidRect,
    299                  const nsRect& aOriginalKidInkOverflow);
    300 
    301  void CalculateRowBSizes(nsPresContext* aPresContext,
    302                          ReflowOutput& aDesiredSize,
    303                          const ReflowInput& aReflowInput);
    304 
    305  void DidResizeRows(ReflowOutput& aDesiredSize);
    306 
    307  /**
    308   * Reflow the frames we've already created
    309   *
    310   * @param   aPresContext presentation context to use
    311   * @param   aReflowInput current inline state
    312   */
    313  void ReflowChildren(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
    314                      mozilla::TableRowGroupReflowInput& aReflowInput,
    315                      nsReflowStatus& aStatus,
    316                      bool* aPageBreakBeforeEnd = nullptr);
    317 
    318  void SplitRowGroup(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
    319                     const ReflowInput& aReflowInput, nsTableFrame* aTableFrame,
    320                     nsReflowStatus& aStatus, bool aRowForcedPageBreak);
    321 
    322  void SplitSpanningCells(nsPresContext* aPresContext,
    323                          const ReflowInput& aReflowInput,
    324                          nsTableFrame* aTableFrame, nsTableRowFrame* aFirstRow,
    325                          nsTableRowFrame* aLastRow, bool aFirstRowIsTopOfPage,
    326                          nscoord aSpanningRowBEnd,
    327                          const nsSize& aContainerSize,
    328                          nsTableRowFrame*& aContRowFrame,
    329                          nsTableRowFrame*& aFirstTruncatedRow,
    330                          nscoord& aDesiredBSize);
    331 
    332  /**
    333   * Create a continuing table row frame, add it to the child list, and then
    334   * push it and its later siblings to our overflow frames list.
    335   */
    336  nsTableRowFrame* CreateContinuingRowFrame(nsIFrame* aRowFrame);
    337 
    338  bool IsSimpleRowFrame(nsTableFrame* aTableFrame, nsTableRowFrame* aRowFrame);
    339 
    340  void GetNextRowSibling(nsIFrame** aRowFrame);
    341 
    342  void UndoContinuedRow(nsPresContext* aPresContext, nsTableRowFrame* aRow);
    343 
    344 public:
    345  bool IsRepeatable() const;
    346  void SetRepeatable(bool aRepeatable);
    347  bool HasStyleBSize() const;
    348  void SetHasStyleBSize(bool aValue);
    349  bool HasInternalBreakBefore() const;
    350  bool HasInternalBreakAfter() const;
    351 };
    352 
    353 inline bool nsTableRowGroupFrame::IsRepeatable() const {
    354  return HasAnyStateBits(NS_ROWGROUP_REPEATABLE);
    355 }
    356 
    357 inline void nsTableRowGroupFrame::SetRepeatable(bool aRepeatable) {
    358  if (aRepeatable) {
    359    AddStateBits(NS_ROWGROUP_REPEATABLE);
    360  } else {
    361    RemoveStateBits(NS_ROWGROUP_REPEATABLE);
    362  }
    363 }
    364 
    365 inline bool nsTableRowGroupFrame::HasStyleBSize() const {
    366  return HasAnyStateBits(NS_ROWGROUP_HAS_STYLE_BSIZE);
    367 }
    368 
    369 inline void nsTableRowGroupFrame::SetHasStyleBSize(bool aValue) {
    370  if (aValue) {
    371    AddStateBits(NS_ROWGROUP_HAS_STYLE_BSIZE);
    372  } else {
    373    RemoveStateBits(NS_ROWGROUP_HAS_STYLE_BSIZE);
    374  }
    375 }
    376 
    377 #endif