tor-browser

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

nsTableCellFrame.h (11569B)


      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 nsTableCellFrame_h__
      6 #define nsTableCellFrame_h__
      7 
      8 #include "celldata.h"
      9 #include "mozilla/ComputedStyle.h"
     10 #include "mozilla/WritingModes.h"
     11 #include "nsContainerFrame.h"
     12 #include "nsIPercentBSizeObserver.h"
     13 #include "nsITableCellLayout.h"
     14 #include "nsTArray.h"
     15 #include "nsTableRowFrame.h"
     16 #include "nscore.h"
     17 
     18 namespace mozilla {
     19 class PresShell;
     20 class ScrollContainerFrame;
     21 }  // namespace mozilla
     22 
     23 enum class TableCellAlignment : uint8_t {
     24  Top,
     25  Middle,
     26  Bottom,
     27  Baseline,
     28 };
     29 
     30 /**
     31 * nsTableCellFrame
     32 * data structure to maintain information about a single table cell's frame
     33 *
     34 * NOTE:  frames are not ref counted.  We expose addref and release here
     35 * so we can change that decsion in the future.  Users of nsITableCellLayout
     36 * should refcount correctly as if this object is being ref counted, though
     37 * no actual support is under the hood.
     38 *
     39 * @author  sclark
     40 */
     41 class nsTableCellFrame : public nsContainerFrame,
     42                         public nsITableCellLayout,
     43                         public nsIPercentBSizeObserver {
     44  friend nsTableCellFrame* NS_NewTableCellFrame(mozilla::PresShell* aPresShell,
     45                                                ComputedStyle* aStyle,
     46                                                nsTableFrame* aTableFrame);
     47 
     48  nsTableCellFrame(ComputedStyle* aStyle, nsTableFrame* aTableFrame)
     49      : nsTableCellFrame(aStyle, aTableFrame, kClassID) {}
     50 
     51 public:
     52  NS_DECL_QUERYFRAME
     53  NS_DECL_FRAMEARENA_HELPERS(nsTableCellFrame)
     54 
     55  mozilla::ScrollContainerFrame* GetScrollTargetFrame() const final;
     56 
     57  nsTableRowFrame* GetTableRowFrame() const {
     58    nsIFrame* parent = GetParent();
     59    MOZ_ASSERT(parent && parent->IsTableRowFrame());
     60    return static_cast<nsTableRowFrame*>(parent);
     61  }
     62 
     63  nsTableFrame* GetTableFrame() const {
     64    return GetTableRowFrame()->GetTableFrame();
     65  }
     66 
     67  void Init(nsIContent* aContent, nsContainerFrame* aParent,
     68            nsIFrame* aPrevInFlow) override;
     69 
     70  void Destroy(DestroyContext&) override;
     71 
     72 #ifdef ACCESSIBILITY
     73  mozilla::a11y::AccType AccessibleType() override;
     74 #endif
     75 
     76  nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
     77                            AttrModType aModType) override;
     78 
     79  /** @see nsIFrame::DidSetComputedStyle */
     80  void DidSetComputedStyle(ComputedStyle* aOldComputedStyle) override;
     81 
     82 #ifdef DEBUG
     83  // Our anonymous block frame is the content insertion frame so these
     84  // methods should never be called:
     85  void AppendFrames(ChildListID aListID, nsFrameList&& aFrameList) override;
     86  void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
     87                    const nsLineList::iterator* aPrevFrameLine,
     88                    nsFrameList&& aFrameList) override;
     89  void RemoveFrame(DestroyContext&, ChildListID, nsIFrame*) override;
     90 #endif
     91 
     92  nsContainerFrame* GetContentInsertionFrame() override {
     93    return Inner()->GetContentInsertionFrame();
     94  }
     95 
     96  // Return our anonymous inner frame.
     97  nsIFrame* Inner() const;
     98 
     99  nsIFrame* CellContentFrame() const;
    100 
    101  nsMargin GetUsedMargin() const override;
    102 
    103  void NotifyPercentBSize(const ReflowInput& aReflowInput) override;
    104 
    105  bool NeedsToObserve(const ReflowInput& aReflowInput) override;
    106 
    107  void BuildDisplayList(nsDisplayListBuilder* aBuilder,
    108                        const nsDisplayListSet& aLists) override;
    109 
    110  virtual void ProcessBorders(nsTableFrame* aFrame,
    111                              nsDisplayListBuilder* aBuilder,
    112                              const nsDisplayListSet& aLists);
    113 
    114  nscoord IntrinsicISize(const mozilla::IntrinsicSizeInput& aInput,
    115                         mozilla::IntrinsicISizeType aType) override;
    116 
    117  IntrinsicSizeOffsetData IntrinsicISizeOffsets(
    118      nscoord aPercentageBasis = NS_UNCONSTRAINEDSIZE) override;
    119 
    120  void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
    121              const ReflowInput& aReflowInput,
    122              nsReflowStatus& aStatus) override;
    123 
    124 #ifdef DEBUG_FRAME_DUMP
    125  nsresult GetFrameName(nsAString& aResult) const override;
    126 #endif
    127 
    128  // Align the cell's anonymous-block child within the cell. This applies the
    129  // CSS `vertical-align` property to position the child frame appropriately
    130  // (in terms of the writing mode of the cell contents, which may be different
    131  // from the table's WM).
    132  // This also resets the child's inline position, which in the case of an
    133  // orthogonal child may have been based on an unknown container size when
    134  // it was initially reflowed.
    135  void AlignChildWithinCell(nscoord aMaxAscent,
    136                            mozilla::ForceAlignTopForTableCell aForceAlignTop);
    137 
    138  /*
    139   * Map the CSS vertical-align to the corresponding table cell alignment value.
    140   */
    141  virtual TableCellAlignment GetTableCellAlignment() const;
    142 
    143  bool HasTableCellAlignmentBaseline() const {
    144    return GetTableCellAlignment() == TableCellAlignment::Baseline &&
    145           !GetContentEmpty();
    146  }
    147 
    148  /**
    149   * Get the first-line baseline of the cell relative to its block-start border
    150   * edge, as if the cell were vertically aligned to the top of the row.
    151   */
    152  Maybe<nscoord> GetCellBaseline() const;
    153 
    154  /**
    155   * return the cell's specified row span. this is what was specified in the
    156   * content model or in the style info, and is always >= 0.
    157   * to get the effective row span (the actual value that applies), use
    158   * GetEffectiveRowSpan()
    159   * @see nsTableFrame::GetEffectiveRowSpan()
    160   */
    161  int32_t GetRowSpan();
    162 
    163  // there is no set row index because row index depends on the cell's parent
    164  // row only
    165 
    166  // Return our cell content frame.
    167  void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) override;
    168 
    169  /*---------------- nsITableCellLayout methods ------------------------*/
    170 
    171  /**
    172   * return the cell's starting row index (starting at 0 for the first row).
    173   * for continued cell frames the row index is that of the cell's first-in-flow
    174   * and the column index (starting at 0 for the first column
    175   */
    176  NS_IMETHOD GetCellIndexes(int32_t& aRowIndex, int32_t& aColIndex) override;
    177 
    178  /** return the mapped cell's row index (starting at 0 for the first row) */
    179  uint32_t RowIndex() const {
    180    return static_cast<nsTableRowFrame*>(GetParent())->GetRowIndex();
    181  }
    182 
    183  /**
    184   * return the cell's specified col span. this is what was specified in the
    185   * content model or in the style info, and is always >= 1.
    186   * to get the effective col span (the actual value that applies), use
    187   * GetEffectiveColSpan()
    188   * @see nsTableFrame::GetEffectiveColSpan()
    189   */
    190  int32_t GetColSpan();
    191 
    192  /** return the cell's column index (starting at 0 for the first column) */
    193  uint32_t ColIndex() const {
    194    // NOTE: We copy this from previous continuations, and we don't ever have
    195    // dynamic updates when tables split, so our mColIndex always matches our
    196    // first continuation's.
    197    MOZ_ASSERT(static_cast<nsTableCellFrame*>(FirstContinuation())->mColIndex ==
    198                   mColIndex,
    199               "mColIndex out of sync with first continuation");
    200    return mColIndex;
    201  }
    202 
    203  void SetColIndex(int32_t aColIndex);
    204 
    205  // Get or set the available isize given to this frame during its last reflow.
    206  nscoord GetPriorAvailISize() const { return mPriorAvailISize; }
    207  void SetPriorAvailISize(nscoord aPriorAvailISize) {
    208    mPriorAvailISize = aPriorAvailISize;
    209  }
    210 
    211  // Get or set the desired size returned by this frame during its last reflow.
    212  mozilla::LogicalSize GetDesiredSize() const { return mDesiredSize; }
    213  void SetDesiredSize(const ReflowOutput& aDesiredSize) {
    214    mDesiredSize = aDesiredSize.Size(GetWritingMode());
    215  }
    216 
    217  bool GetContentEmpty() const {
    218    return HasAnyStateBits(NS_TABLE_CELL_CONTENT_EMPTY);
    219  }
    220  void SetContentEmpty(bool aContentEmpty) {
    221    AddOrRemoveStateBits(NS_TABLE_CELL_CONTENT_EMPTY, aContentEmpty);
    222  }
    223 
    224  nsTableCellFrame* GetNextCell() const {
    225    nsIFrame* sibling = GetNextSibling();
    226    MOZ_ASSERT(
    227        !sibling || static_cast<nsTableCellFrame*>(do_QueryFrame(sibling)),
    228        "How do we have a non-cell sibling?");
    229    return static_cast<nsTableCellFrame*>(sibling);
    230  }
    231 
    232  virtual mozilla::LogicalMargin GetBorderWidth(mozilla::WritingMode aWM) const;
    233  virtual bool BCBordersChanged() const { return false; }
    234 
    235  void DecorateForSelection(DrawTarget* aDrawTarget, nsPoint aPt);
    236 
    237  bool ComputeCustomOverflow(mozilla::OverflowAreas& aOverflowAreas) override;
    238 
    239  void InvalidateFrame(uint32_t aDisplayItemKey = 0,
    240                       bool aRebuildDisplayItems = true) override;
    241  void InvalidateFrameWithRect(const nsRect& aRect,
    242                               uint32_t aDisplayItemKey = 0,
    243                               bool aRebuildDisplayItems = true) override;
    244  void InvalidateFrameForRemoval() override { InvalidateFrameSubtree(); }
    245 
    246  bool ShouldPaintBordersAndBackgrounds() const;
    247 
    248  bool ShouldPaintBackground(nsDisplayListBuilder* aBuilder);
    249 
    250 protected:
    251  nsTableCellFrame(ComputedStyle* aStyle, nsTableFrame* aTableFrame,
    252                   ClassID aID);
    253  ~nsTableCellFrame();
    254 
    255  LogicalSides GetLogicalSkipSides() const override;
    256 
    257  /**
    258   * GetBorderOverflow says how far the cell's own borders extend
    259   * outside its own bounds.  In the separated borders model this should
    260   * just be zero (as it is for most frames), but in the collapsed
    261   * borders model (for which nsBCTableCellFrame overrides this virtual
    262   * method), it considers the extents of the collapsed border.
    263   */
    264  virtual nsMargin GetBorderOverflow();
    265 
    266  friend class nsTableRowFrame;
    267 
    268  // The starting column for this cell
    269  uint32_t mColIndex = 0;
    270 
    271  // The avail isize during the last reflow
    272  nscoord mPriorAvailISize = 0;
    273 
    274  // The last desired inline and block size
    275  mozilla::LogicalSize mDesiredSize;
    276 };
    277 
    278 class nsBCTableCellFrame final : public nsTableCellFrame {
    279 public:
    280  NS_DECL_FRAMEARENA_HELPERS(nsBCTableCellFrame)
    281 
    282  nsBCTableCellFrame(ComputedStyle* aStyle, nsTableFrame* aTableFrame);
    283  void Reflow(nsPresContext*, ReflowOutput&, const ReflowInput&,
    284              nsReflowStatus&) override;
    285 
    286  ~nsBCTableCellFrame();
    287 
    288  nsMargin GetUsedBorder() const override;
    289  bool BCBordersChanged() const override {
    290    return GetUsedBorder() != mLastUsedBorder;
    291  }
    292 
    293  // Get the *inner half of the border only*, in twips.
    294  mozilla::LogicalMargin GetBorderWidth(
    295      mozilla::WritingMode aWM) const override;
    296 
    297  // Get the *inner half of the border only*
    298  nscoord GetBorderWidth(mozilla::LogicalSide aSide) const;
    299 
    300  // Set the full (both halves) width of the border
    301  void SetBorderWidth(mozilla::LogicalSide aSide, nscoord aValue);
    302 
    303  nsMargin GetBorderOverflow() override;
    304 
    305 #ifdef DEBUG_FRAME_DUMP
    306  nsresult GetFrameName(nsAString& aResult) const override;
    307 #endif
    308 
    309 private:
    310  // These are the entire width of the border (the cell edge contains only
    311  // the inner half).
    312  nscoord mBStartBorder = 0;
    313  nscoord mIEndBorder = 0;
    314  nscoord mBEndBorder = 0;
    315  nscoord mIStartBorder = 0;
    316 
    317  nsMargin mLastUsedBorder;
    318 };
    319 
    320 // Implemented here because that's a sane-ish way to make the includes work out.
    321 inline nsTableCellFrame* nsTableRowFrame::GetFirstCell() const {
    322  nsIFrame* firstChild = mFrames.FirstChild();
    323  MOZ_ASSERT(
    324      !firstChild || static_cast<nsTableCellFrame*>(do_QueryFrame(firstChild)),
    325      "How do we have a non-cell child?");
    326  return static_cast<nsTableCellFrame*>(firstChild);
    327 }
    328 
    329 #endif