layout/tables/nsTableColFrame.h
author Csoregi Natalia <ncsoregi@mozilla.com>
Sat, 01 Oct 2022 04:22:22 +0300
changeset 636750 5144d608cc2f43bf6b35742773ef0c7d2579ec27
parent 566903 bf6cf886b9683288fa453a66f999875b6ff6d3eb
permissions -rw-r--r--
Backed out changeset 63fbc22d2223 (bug 1792741) for causing assertion failures on nsCSSFrameConstructor.cpp. CLOSED TREE

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsTableColFrame_h__
#define nsTableColFrame_h__

#include "mozilla/Attributes.h"
#include "celldata.h"
#include "nscore.h"
#include "nsContainerFrame.h"
#include "nsTArray.h"
#include "nsTableColGroupFrame.h"
#include "mozilla/WritingModes.h"

namespace mozilla {
class PresShell;
}  // namespace mozilla

class nsTableColFrame final : public nsSplittableFrame {
 public:
  NS_DECL_FRAMEARENA_HELPERS(nsTableColFrame)

  enum {
    eWIDTH_SOURCE_NONE = 0,  // no cell has contributed to the width style
    eWIDTH_SOURCE_CELL = 1,  // a cell specified a width
    eWIDTH_SOURCE_CELL_WITH_SPAN = 2  // a cell implicitly specified a width via
                                      // colspan
  };

  nsTableColType GetColType() const;
  void SetColType(nsTableColType aType);

  /**
   * instantiate a new instance of nsTableRowFrame.
   *
   * @param aPresShell the pres shell for this frame
   *
   * @return           the frame that was created
   */
  friend nsTableColFrame* NS_NewTableColFrame(mozilla::PresShell* aPresShell,
                                              ComputedStyle* aContext);

  // nsIFrame overrides
  virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
                    nsIFrame* aPrevInFlow) override {
    nsSplittableFrame::Init(aContent, aParent, aPrevInFlow);
    if (!aPrevInFlow) {
      mWritingMode = GetTableFrame()->GetWritingMode();
    }
  }

  /** @see nsIFrame::DidSetComputedStyle */
  virtual void DidSetComputedStyle(ComputedStyle* aOldComputedStyle) override;

  virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
                      const ReflowInput& aReflowInput,
                      nsReflowStatus& aStatus) override;

  virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
                                const nsDisplayListSet& aLists) override;

#ifdef DEBUG_FRAME_DUMP
  virtual nsresult GetFrameName(nsAString& aResult) const override;
#endif

  nsTableColGroupFrame* GetTableColGroupFrame() const {
    nsIFrame* parent = GetParent();
    MOZ_ASSERT(parent && parent->IsTableColGroupFrame());
    return static_cast<nsTableColGroupFrame*>(parent);
  }

  nsTableFrame* GetTableFrame() const {
    return GetTableColGroupFrame()->GetTableFrame();
  }

  int32_t GetColIndex() const;

  void SetColIndex(int32_t aColIndex);

  nsTableColFrame* GetNextCol() const;

  /** return the number of the columns the col represents.  always >= 1 */
  int32_t GetSpan();

  /** convenience method, calls into cellmap */
  int32_t Count() const;

  BCPixelSize GetIStartBorderWidth() const { return mIStartBorderWidth; }
  BCPixelSize GetIEndBorderWidth() const { return mIEndBorderWidth; }
  void SetIStartBorderWidth(BCPixelSize aWidth) { mIStartBorderWidth = aWidth; }
  void SetIEndBorderWidth(BCPixelSize aWidth) { mIEndBorderWidth = aWidth; }

  /**
   * Gets inner border widths before collapsing with cell borders
   * Caller must get istart border from previous column or from table
   * GetContinuousBCBorderWidth will not overwrite aBorder.IStart
   * see nsTablePainter about continuous borders
   *
   * @return outer iend border width (istart inner for next column)
   */
  nscoord GetContinuousBCBorderWidth(mozilla::WritingMode aWM,
                                     mozilla::LogicalMargin& aBorder);
  /**
   * Set full border widths before collapsing with cell borders
   * @param aForSide - side to set; only valid for bstart, iend, and bend
   */
  void SetContinuousBCBorderWidth(mozilla::LogicalSide aForSide,
                                  BCPixelSize aPixelValue);
#ifdef DEBUG
  void Dump(int32_t aIndent);
#endif

  /**
   * Restore the default values of the intrinsic widths, so that we can
   * re-accumulate intrinsic widths from the cells in the column.
   */
  void ResetIntrinsics() {
    mMinCoord = 0;
    mPrefCoord = 0;
    mPrefPercent = 0.0f;
    mHasSpecifiedCoord = false;
  }

  /**
   * Restore the default value of the preferred percentage width (the
   * only intrinsic width used by FixedTableLayoutStrategy.
   */
  void ResetPrefPercent() { mPrefPercent = 0.0f; }

  /**
   * Restore the default values of the temporary buffer for
   * spanning-cell intrinsic widths (as we process spanning cells).
   */
  void ResetSpanIntrinsics() {
    mSpanMinCoord = 0;
    mSpanPrefCoord = 0;
    mSpanPrefPercent = 0.0f;
  }

  /**
   * Add the widths for a cell or column element, or the contribution of
   * the widths from a column-spanning cell:
   * @param aMinCoord The minimum intrinsic width
   * @param aPrefCoord The preferred intrinsic width or, if there is a
   *   specified non-percentage width, max(specified width, minimum intrinsic
   *   width).
   * @param aHasSpecifiedCoord Whether there is a specified
   *   non-percentage width.
   *
   * Note that the implementation of this functions is a bit tricky
   * since mPrefCoord means different things depending on
   * whether mHasSpecifiedCoord is true (and likewise for aPrefCoord and
   * aHasSpecifiedCoord).  If mHasSpecifiedCoord is false, then
   * all widths added had aHasSpecifiedCoord false and mPrefCoord is the
   * largest of the pref widths.  But if mHasSpecifiedCoord is true,
   * then mPrefCoord is the largest of (1) the pref widths for cells
   * with aHasSpecifiedCoord true and (2) the min widths for cells with
   * aHasSpecifiedCoord false.
   */
  void AddCoords(nscoord aMinCoord, nscoord aPrefCoord,
                 bool aHasSpecifiedCoord) {
    NS_ASSERTION(aMinCoord <= aPrefCoord, "intrinsic widths out of order");

    if (aHasSpecifiedCoord && !mHasSpecifiedCoord) {
      mPrefCoord = mMinCoord;
      mHasSpecifiedCoord = true;
    }
    if (!aHasSpecifiedCoord && mHasSpecifiedCoord) {
      aPrefCoord = aMinCoord;  // NOTE: modifying argument
    }

    if (aMinCoord > mMinCoord) mMinCoord = aMinCoord;
    if (aPrefCoord > mPrefCoord) mPrefCoord = aPrefCoord;

    NS_ASSERTION(mMinCoord <= mPrefCoord, "min larger than pref");
  }

  /**
   * Add a percentage width specified on a cell or column element or the
   * contribution to this column of a percentage width specified on a
   * column-spanning cell.
   */
  void AddPrefPercent(float aPrefPercent) {
    if (aPrefPercent > mPrefPercent) mPrefPercent = aPrefPercent;
  }

  /**
   * Get the largest minimum intrinsic width for this column.
   */
  nscoord GetMinCoord() const { return mMinCoord; }
  /**
   * Get the largest preferred width for this column, or, if there were
   * any specified non-percentage widths (see GetHasSpecifiedCoord), the
   * largest minimum intrinsic width or specified width.
   */
  nscoord GetPrefCoord() const { return mPrefCoord; }
  /**
   * Get whether there were any specified widths contributing to this
   * column.
   */
  bool GetHasSpecifiedCoord() const { return mHasSpecifiedCoord; }

  /**
   * Get the largest specified percentage width contributing to this
   * column (returns 0 if there were none).
   */
  float GetPrefPercent() const { return mPrefPercent; }

  /**
   * Like AddCoords, but into a temporary buffer used for groups of
   * column-spanning cells.
   */
  void AddSpanCoords(nscoord aSpanMinCoord, nscoord aSpanPrefCoord,
                     bool aSpanHasSpecifiedCoord) {
    NS_ASSERTION(aSpanMinCoord <= aSpanPrefCoord,
                 "intrinsic widths out of order");

    if (!aSpanHasSpecifiedCoord && mHasSpecifiedCoord) {
      aSpanPrefCoord = aSpanMinCoord;  // NOTE: modifying argument
    }

    if (aSpanMinCoord > mSpanMinCoord) mSpanMinCoord = aSpanMinCoord;
    if (aSpanPrefCoord > mSpanPrefCoord) mSpanPrefCoord = aSpanPrefCoord;

    NS_ASSERTION(mSpanMinCoord <= mSpanPrefCoord, "min larger than pref");
  }

  /*
   * Accumulate percentage widths on column spanning cells into
   * temporary variables.
   */
  void AddSpanPrefPercent(float aSpanPrefPercent) {
    if (aSpanPrefPercent > mSpanPrefPercent)
      mSpanPrefPercent = aSpanPrefPercent;
  }

  /*
   * Accumulate the temporary variables for column spanning cells into
   * the primary variables.
   */
  void AccumulateSpanIntrinsics() {
    AddCoords(mSpanMinCoord, mSpanPrefCoord, mHasSpecifiedCoord);
    AddPrefPercent(mSpanPrefPercent);
  }

  // Used to adjust a column's pref percent so that the table's total
  // never exceeeds 100% (by only allowing percentages to be used,
  // starting at the first column, until they reach 100%).
  void AdjustPrefPercent(float* aTableTotalPercent) {
    float allowed = 1.0f - *aTableTotalPercent;
    if (mPrefPercent > allowed) mPrefPercent = allowed;
    *aTableTotalPercent += mPrefPercent;
  }

  // The final width of the column.
  void ResetFinalISize() {
    mFinalISize = nscoord_MIN;  // so we detect that it changed
  }
  void SetFinalISize(nscoord aFinalISize) { mFinalISize = aFinalISize; }
  nscoord GetFinalISize() { return mFinalISize; }

  virtual bool IsFrameOfType(uint32_t aFlags) const override {
    if (aFlags & (eSupportsContainLayoutAndPaint | eSupportsAspectRatio)) {
      return false;
    }

    return nsSplittableFrame::IsFrameOfType(aFlags & ~(nsIFrame::eTablePart));
  }

  virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0,
                               bool aRebuildDisplayItems = true) override;
  virtual void InvalidateFrameWithRect(
      const nsRect& aRect, uint32_t aDisplayItemKey = 0,
      bool aRebuildDisplayItems = true) override;
  virtual void InvalidateFrameForRemoval() override {
    InvalidateFrameSubtree();
  }

 protected:
  explicit nsTableColFrame(ComputedStyle* aStyle, nsPresContext* aPresContext);
  ~nsTableColFrame();

  nscoord mMinCoord;
  nscoord mPrefCoord;
  nscoord mSpanMinCoord;   // XXX...
  nscoord mSpanPrefCoord;  // XXX...
  float mPrefPercent;
  float mSpanPrefPercent;  // XXX...
  // ...XXX the four members marked above could be allocated as part of
  // a separate array allocated only during
  // BasicTableLayoutStrategy::ComputeColumnIntrinsicISizes (and only
  // when colspans were present).
  nscoord mFinalISize;

  // the index of the column with respect to the whole table (starting at 0)
  // it should never be smaller then the start column index of the parent
  // colgroup
  uint32_t mColIndex;

  // border width in pixels of the inner half of the border only
  BCPixelSize mIStartBorderWidth;
  BCPixelSize mIEndBorderWidth;
  BCPixelSize mBStartContBorderWidth;
  BCPixelSize mIEndContBorderWidth;
  BCPixelSize mBEndContBorderWidth;

  bool mHasSpecifiedCoord;
};

inline int32_t nsTableColFrame::GetColIndex() const { return mColIndex; }

inline void nsTableColFrame::SetColIndex(int32_t aColIndex) {
  mColIndex = aColIndex;
}

inline nscoord nsTableColFrame::GetContinuousBCBorderWidth(
    mozilla::WritingMode aWM, mozilla::LogicalMargin& aBorder) {
  int32_t d2a = PresContext()->AppUnitsPerDevPixel();
  aBorder.BStart(aWM) = BC_BORDER_END_HALF_COORD(d2a, mBStartContBorderWidth);
  aBorder.IEnd(aWM) = BC_BORDER_START_HALF_COORD(d2a, mIEndContBorderWidth);
  aBorder.BEnd(aWM) = BC_BORDER_START_HALF_COORD(d2a, mBEndContBorderWidth);
  return BC_BORDER_END_HALF_COORD(d2a, mIEndContBorderWidth);
}

#endif