tor-browser

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

ReflowOutput.h (9605B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 /* struct containing the output from nsIFrame::Reflow */
      8 
      9 #ifndef mozilla_ReflowOutput_h
     10 #define mozilla_ReflowOutput_h
     11 
     12 #include "mozilla/EnumeratedRange.h"
     13 #include "mozilla/WritingModes.h"
     14 #include "nsBoundingMetrics.h"
     15 #include "nsRect.h"
     16 
     17 //----------------------------------------------------------------------
     18 
     19 namespace mozilla {
     20 struct ReflowInput;
     21 
     22 enum class OverflowType : uint8_t { Ink, Scrollable };
     23 constexpr auto AllOverflowTypes() {
     24  return MakeInclusiveEnumeratedRange(OverflowType::Ink,
     25                                      OverflowType::Scrollable);
     26 }
     27 
     28 struct OverflowAreas {
     29 public:
     30  nsRect& InkOverflow() { return mInk; }
     31  const nsRect& InkOverflow() const { return mInk; }
     32 
     33  nsRect& ScrollableOverflow() { return mScrollable; }
     34  const nsRect& ScrollableOverflow() const { return mScrollable; }
     35 
     36  nsRect& Overflow(OverflowType aType) {
     37    return aType == OverflowType::Ink ? InkOverflow() : ScrollableOverflow();
     38  }
     39  const nsRect& Overflow(OverflowType aType) const {
     40    return aType == OverflowType::Ink ? InkOverflow() : ScrollableOverflow();
     41  }
     42 
     43  OverflowAreas() = default;
     44 
     45  OverflowAreas(const nsRect& aInkOverflow, const nsRect& aScrollableOverflow)
     46      : mInk(aInkOverflow), mScrollable(aScrollableOverflow) {}
     47 
     48  bool operator==(const OverflowAreas& aOther) const {
     49    // Scrollable overflow is a point-set rectangle and ink overflow
     50    // is a pixel-set rectangle.
     51    return InkOverflow().IsEqualInterior(aOther.InkOverflow()) &&
     52           ScrollableOverflow().IsEqualEdges(aOther.ScrollableOverflow());
     53  }
     54 
     55  bool operator!=(const OverflowAreas&) const = default;
     56 
     57  OverflowAreas operator+(const nsPoint& aPoint) const {
     58    OverflowAreas result(*this);
     59    result += aPoint;
     60    return result;
     61  }
     62 
     63  OverflowAreas& operator+=(const nsPoint& aPoint) {
     64    mInk += aPoint;
     65    mScrollable += aPoint;
     66    return *this;
     67  }
     68 
     69  void Clear() { SetAllTo(nsRect()); }
     70 
     71  // Mutates |this| by unioning both overflow areas with |aOther|.
     72  void UnionWith(const OverflowAreas& aOther);
     73 
     74  // Mutates |this| by unioning both overflow areas with |aRect|.
     75  void UnionAllWith(const nsRect& aRect);
     76 
     77  // Mutates |this| by setting both overflow areas to |aRect|.
     78  void SetAllTo(const nsRect& aRect);
     79 
     80  // Applies overflow clipping (for e.g. overflow: clip) as needed to both our
     81  // overflow rects.
     82  void ApplyClipping(const nsRect& aBounds, PhysicalAxes aClipAxes,
     83                     const nsMargin& aOverflowMargin) {
     84    ApplyOverflowClippingOnRect(InkOverflow(), aBounds, aClipAxes,
     85                                aOverflowMargin);
     86    ApplyOverflowClippingOnRect(ScrollableOverflow(), aBounds, aClipAxes,
     87                                aOverflowMargin);
     88  }
     89 
     90  // Gets the overflow clipping rect for a given element given a rect to clip,
     91  // the frame bounds, a set of axes, and the overflow margin.
     92  static nsRect GetOverflowClipRect(const nsRect& aRectToClip,
     93                                    const nsRect& aBounds,
     94                                    PhysicalAxes aClipAxes,
     95                                    const nsMargin& aOverflowMargin);
     96 
     97  // Applies the overflow clipping to a given overflow rect, given the frame
     98  // bounds, and the physical axes on which to apply the overflow clip.
     99  static void ApplyOverflowClippingOnRect(nsRect& aOverflowRect,
    100                                          const nsRect& aBounds,
    101                                          PhysicalAxes aClipAxes,
    102                                          const nsMargin& aOverflowMargin);
    103 
    104 private:
    105  nsRect mInk;
    106  nsRect mScrollable;
    107 };
    108 
    109 /**
    110 * CollapsingMargin represents a vertical collapsing margin between
    111 * blocks as described in section 8.3.1 of CSS2.
    112 * <https://www.w3.org/TR/CSS22/box.html#collapsing-margins>
    113 *
    114 * All adjacent vertical margins collapse, and the resulting margin is
    115 * the sum of the largest positive margin included and the smallest (most
    116 * negative) negative margin included.
    117 */
    118 class CollapsingMargin final {
    119 public:
    120  bool operator==(const CollapsingMargin&) const = default;
    121  bool operator!=(const CollapsingMargin&) const = default;
    122 
    123  void Include(nscoord aCoord) {
    124    if (aCoord > mMostPos) {
    125      mMostPos = aCoord;
    126    } else if (aCoord < mMostNeg) {
    127      mMostNeg = aCoord;
    128    }
    129  }
    130 
    131  void Include(const CollapsingMargin& aOther) {
    132    if (aOther.mMostPos > mMostPos) {
    133      mMostPos = aOther.mMostPos;
    134    }
    135    if (aOther.mMostNeg < mMostNeg) {
    136      mMostNeg = aOther.mMostNeg;
    137    }
    138  }
    139 
    140  void Zero() {
    141    mMostPos = 0;
    142    mMostNeg = 0;
    143  }
    144 
    145  bool IsZero() const { return mMostPos == 0 && mMostNeg == 0; }
    146 
    147  nscoord Get() const { return mMostPos + mMostNeg; }
    148 
    149 private:
    150  // The largest positive margin included.
    151  nscoord mMostPos = 0;
    152 
    153  // The smallest negative margin included.
    154  nscoord mMostNeg = 0;
    155 };
    156 
    157 /**
    158 * ReflowOutput is initialized by a parent frame as a parameter passing to
    159 * Reflow() to allow a child frame to return its desired size and alignment
    160 * information.
    161 *
    162 * ReflowOutput's constructor usually takes a parent frame's WritingMode (or
    163 * ReflowInput) because it is more convenient for the parent frame to use the
    164 * stored Size() after reflowing the child frame. However, it can actually
    165 * accept any WritingMode (or ReflowInput) because SetSize() knows how to
    166 * convert a size in any writing mode to the stored writing mode.
    167 *
    168 * @see nsIFrame::Reflow() for more information.
    169 */
    170 class ReflowOutput {
    171 public:
    172  explicit ReflowOutput(WritingMode aWritingMode)
    173      : mSize(aWritingMode), mWritingMode(aWritingMode) {}
    174 
    175  // A convenient constructor to get WritingMode in ReflowInput.
    176  explicit ReflowOutput(const ReflowInput& aReflowInput);
    177 
    178  nscoord ISize(WritingMode aWritingMode) const {
    179    return mSize.ISize(aWritingMode);
    180  }
    181  nscoord BSize(WritingMode aWritingMode) const {
    182    return mSize.BSize(aWritingMode);
    183  }
    184  LogicalSize Size(WritingMode aWritingMode) const {
    185    return mSize.ConvertTo(aWritingMode, mWritingMode);
    186  }
    187 
    188  nscoord& ISize(WritingMode aWritingMode) { return mSize.ISize(aWritingMode); }
    189  nscoord& BSize(WritingMode aWritingMode) { return mSize.BSize(aWritingMode); }
    190 
    191  // Set inline and block size from a LogicalSize, converting to our
    192  // writing mode as necessary.
    193  void SetSize(WritingMode aWM, const LogicalSize& aSize) {
    194    mSize = aSize.ConvertTo(mWritingMode, aWM);
    195  }
    196 
    197  // Set both inline and block size to zero -- no need for a writing mode!
    198  void ClearSize() { mSize.SizeTo(mWritingMode, 0, 0); }
    199 
    200  // Width and Height are physical dimensions, independent of writing mode.
    201  // Accessing these is slightly more expensive than accessing the logical
    202  // dimensions; as far as possible, client code should work purely with logical
    203  // dimensions.
    204  nscoord Width() const { return mSize.Width(mWritingMode); }
    205  nscoord Height() const { return mSize.Height(mWritingMode); }
    206  nscoord& Width() {
    207    return mWritingMode.IsVertical() ? mSize.BSize(mWritingMode)
    208                                     : mSize.ISize(mWritingMode);
    209  }
    210  nscoord& Height() {
    211    return mWritingMode.IsVertical() ? mSize.ISize(mWritingMode)
    212                                     : mSize.BSize(mWritingMode);
    213  }
    214 
    215  nsSize PhysicalSize() const { return mSize.GetPhysicalSize(mWritingMode); }
    216 
    217  // It's only meaningful to consider "ascent" on the block-start side of the
    218  // frame, so no need to pass a writing mode argument
    219  enum { ASK_FOR_BASELINE = nscoord_MAX };
    220  nscoord BlockStartAscent() const { return mBlockStartAscent; }
    221  void SetBlockStartAscent(nscoord aAscent) { mBlockStartAscent = aAscent; }
    222 
    223  // Metrics that _exactly_ enclose the text to allow precise MathML placements.
    224  nsBoundingMetrics mBoundingMetrics;  // [OUT]
    225 
    226  // Carried out block-end margin values. This is the collapsed
    227  // (generational) block-end margin value.
    228  CollapsingMargin mCarriedOutBEndMargin;
    229 
    230  // For frames that have content that overflow their content area
    231  // (HasOverflowAreas() is true) these rectangles represent the total
    232  // area of the frame including visible overflow, i.e., don't include
    233  // overflowing content that is hidden.  The rects are in the local
    234  // coordinate space of the frame, and should be at least as big as the
    235  // desired size. If there is no content that overflows, then the
    236  // overflow area is identical to the desired size and should be {0, 0,
    237  // width, height}.
    238  OverflowAreas mOverflowAreas;
    239 
    240  nsRect& InkOverflow() { return mOverflowAreas.InkOverflow(); }
    241  const nsRect& InkOverflow() const { return mOverflowAreas.InkOverflow(); }
    242  nsRect& ScrollableOverflow() { return mOverflowAreas.ScrollableOverflow(); }
    243  const nsRect& ScrollableOverflow() const {
    244    return mOverflowAreas.ScrollableOverflow();
    245  }
    246 
    247  // Set all of mOverflowAreas to (0, 0, width, height).
    248  void SetOverflowAreasToDesiredBounds();
    249 
    250  // Union all of mOverflowAreas with (0, 0, width, height).
    251  void UnionOverflowAreasWithDesiredBounds();
    252 
    253  WritingMode GetWritingMode() const { return mWritingMode; }
    254 
    255 private:
    256  // Desired size of a frame's border-box.
    257  LogicalSize mSize;
    258 
    259  // Baseline (in block direction), or the default value ASK_FOR_BASELINE.
    260  nscoord mBlockStartAscent = ASK_FOR_BASELINE;
    261 
    262  WritingMode mWritingMode;
    263 };
    264 
    265 }  // namespace mozilla
    266 
    267 #endif  // mozilla_ReflowOutput_h