tor-browser

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

DisplayListClipState.h (11298B)


      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 #ifndef DISPLAYLISTCLIPSTATE_H_
      8 #define DISPLAYLISTCLIPSTATE_H_
      9 
     10 #include "DisplayItemClip.h"
     11 #include "DisplayItemClipChain.h"
     12 
     13 class nsIFrame;
     14 
     15 namespace mozilla {
     16 
     17 class nsDisplayListBuilder;
     18 
     19 /**
     20 * All clip coordinates are in appunits relative to the reference frame
     21 * for the display item we're building.
     22 */
     23 class DisplayListClipState {
     24 public:
     25  DisplayListClipState()
     26      : mClipChainContentDescendants(nullptr),
     27        mClipChainContainingBlockDescendants(nullptr),
     28        mCurrentCombinedClipChain(nullptr),
     29        mCurrentCombinedClipChainIsValid(false) {}
     30 
     31  /**
     32   * Returns intersection of mClipChainContainingBlockDescendants and
     33   * mClipChainContentDescendants, allocated on aBuilder's arena.
     34   */
     35  const DisplayItemClipChain* GetCurrentCombinedClipChain(
     36      nsDisplayListBuilder* aBuilder);
     37 
     38  const DisplayItemClipChain* GetClipChainForContainingBlockDescendants()
     39      const {
     40    return mClipChainContainingBlockDescendants;
     41  }
     42  const DisplayItemClipChain* GetClipChainForContentDescendants() const {
     43    return mClipChainContentDescendants;
     44  }
     45 
     46  const ActiveScrolledRoot* GetContentClipASR() const {
     47    return mClipChainContentDescendants ? mClipChainContentDescendants->mASR
     48                                        : nullptr;
     49  }
     50 
     51  class AutoSaveRestore;
     52 
     53  class AutoClipContainingBlockDescendantsToContentBox;
     54 
     55  class AutoClipMultiple;
     56 
     57  enum { ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT = 0x01 };
     58 
     59 private:
     60  void Clear() {
     61    mClipChainContentDescendants = nullptr;
     62    mClipChainContainingBlockDescendants = nullptr;
     63    mCurrentCombinedClipChain = nullptr;
     64    mCurrentCombinedClipChainIsValid = false;
     65    mClippedToDisplayPort = false;
     66  }
     67 
     68  void SetClipChainForContainingBlockDescendants(
     69      const DisplayItemClipChain* aClipChain) {
     70    mClipChainContainingBlockDescendants = aClipChain;
     71    InvalidateCurrentCombinedClipChain(aClipChain ? aClipChain->mASR : nullptr);
     72  }
     73 
     74  /**
     75   * Intersects the given clip rect (with optional aRadii) with the current
     76   * mClipContainingBlockDescendants and sets mClipContainingBlockDescendants to
     77   * the result, stored in aClipOnStack.
     78   */
     79  void ClipContainingBlockDescendants(nsDisplayListBuilder* aBuilder,
     80                                      const nsRect& aRect,
     81                                      const nsRectCornerRadii* aRadii,
     82                                      DisplayItemClipChain& aClipChainOnStack);
     83 
     84  void ClipToDisplayPort(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
     85                         DisplayItemClipChain& aClipChainOnStack);
     86 
     87  void ClipContentDescendants(nsDisplayListBuilder* aBuilder,
     88                              const nsRect& aRect,
     89                              const nsRectCornerRadii* aRadii,
     90                              DisplayItemClipChain& aClipChainOnStack);
     91  void ClipContentDescendants(nsDisplayListBuilder* aBuilder,
     92                              const nsRect& aRect, const nsRect& aRoundedRect,
     93                              const nsRectCornerRadii* aRadii,
     94                              DisplayItemClipChain& aClipChainOnStack);
     95 
     96  void InvalidateCurrentCombinedClipChain(
     97      const ActiveScrolledRoot* aInvalidateUpTo);
     98 
     99  /**
    100   * Clips containing-block descendants to the frame's content-box,
    101   * taking border-radius into account.
    102   * If aFlags contains ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT then
    103   * we assume display items will not draw outside the content rect, so
    104   * clipping is only required if there is a border-radius. This is an
    105   * optimization to reduce the amount of clipping required.
    106   */
    107  void ClipContainingBlockDescendantsToContentBox(
    108      nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
    109      DisplayItemClipChain& aClipChainOnStack, uint32_t aFlags);
    110 
    111  /**
    112   * All content descendants (i.e. following placeholder frames to their
    113   * out-of-flows if necessary) should be clipped by
    114   * mClipChainContentDescendants. Null if no clipping applies.
    115   */
    116  const DisplayItemClipChain* mClipChainContentDescendants;
    117  /**
    118   * All containing-block descendants (i.e. frame descendants), including
    119   * display items for the current frame, should be clipped by
    120   * mClipChainContainingBlockDescendants.
    121   * Null if no clipping applies.
    122   */
    123  const DisplayItemClipChain* mClipChainContainingBlockDescendants;
    124  /**
    125   * The intersection of mClipChainContentDescendants and
    126   * mClipChainContainingBlockDescendants.
    127   * Allocated in the nsDisplayListBuilder arena. Null if none has been
    128   * allocated or both mClipChainContentDescendants and
    129   * mClipChainContainingBlockDescendants are null.
    130   */
    131  const DisplayItemClipChain* mCurrentCombinedClipChain;
    132  bool mCurrentCombinedClipChainIsValid;
    133  /**
    134   * A flag that is used by sticky positioned items to know if the clip applied
    135   * to them is just the displayport clip or if there is additional clipping.
    136   */
    137  bool mClippedToDisplayPort;
    138 };
    139 
    140 /**
    141 * A class to automatically save and restore the current clip state. Also
    142 * offers methods for modifying the clip state. Only one modification is allowed
    143 * to be in scope at a time using one of these objects; multiple modifications
    144 * require nested objects. The interface is written this way to prevent
    145 * dangling pointers to DisplayItemClips.
    146 */
    147 class DisplayListClipState::AutoSaveRestore {
    148 public:
    149  explicit AutoSaveRestore(nsDisplayListBuilder* aBuilder);
    150  void Restore() {
    151    mState = mSavedState;
    152 #ifdef DEBUG
    153    mRestored = true;
    154 #endif
    155  }
    156  ~AutoSaveRestore() { Restore(); }
    157 
    158  void Clear() {
    159    NS_ASSERTION(!mRestored, "Already restored!");
    160    mState.Clear();
    161 #ifdef DEBUG
    162    mClipUsed = false;
    163 #endif
    164  }
    165 
    166  void SetClipChainForContainingBlockDescendants(
    167      const DisplayItemClipChain* aClipChain) {
    168    mState.SetClipChainForContainingBlockDescendants(aClipChain);
    169  }
    170 
    171  /**
    172   * Intersects the given clip rect (with optional aRadii) with the current
    173   * mClipContainingBlockDescendants and sets mClipContainingBlockDescendants to
    174   * the result, stored in aClipOnStack.
    175   */
    176  void ClipContainingBlockDescendants(
    177      const nsRect& aRect, const nsRectCornerRadii* aRadii = nullptr) {
    178    NS_ASSERTION(!mRestored, "Already restored!");
    179    NS_ASSERTION(!mClipUsed, "mClip already used");
    180 #ifdef DEBUG
    181    mClipUsed = true;
    182 #endif
    183    mState.ClipContainingBlockDescendants(mBuilder, aRect, aRadii, mClipChain);
    184  }
    185 
    186  void ClipToDisplayPort(const nsRect& aRect) {
    187    NS_ASSERTION(!mRestored, "Already restored!");
    188    NS_ASSERTION(!mClipUsed, "mClip already used");
    189 #ifdef DEBUG
    190    mClipUsed = true;
    191 #endif
    192    mState.ClipToDisplayPort(mBuilder, aRect, mClipChain);
    193  }
    194 
    195  void ClipContentDescendants(const nsRect& aRect,
    196                              const nsRectCornerRadii* aRadii = nullptr) {
    197    NS_ASSERTION(!mRestored, "Already restored!");
    198    NS_ASSERTION(!mClipUsed, "mClip already used");
    199 #ifdef DEBUG
    200    mClipUsed = true;
    201 #endif
    202    mState.ClipContentDescendants(mBuilder, aRect, aRadii, mClipChain);
    203  }
    204 
    205  void ClipContentDescendants(const nsRect& aRect, const nsRect& aRoundedRect,
    206                              const nsRectCornerRadii* aRadii = nullptr) {
    207    NS_ASSERTION(!mRestored, "Already restored!");
    208    NS_ASSERTION(!mClipUsed, "mClip already used");
    209 #ifdef DEBUG
    210    mClipUsed = true;
    211 #endif
    212    mState.ClipContentDescendants(mBuilder, aRect, aRoundedRect, aRadii,
    213                                  mClipChain);
    214  }
    215 
    216  /**
    217   * Clips containing-block descendants to the frame's content-box,
    218   * taking border-radius into account.
    219   * If aFlags contains ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT then
    220   * we assume display items will not draw outside the content rect, so
    221   * clipping is only required if there is a border-radius. This is an
    222   * optimization to reduce the amount of clipping required.
    223   */
    224  void ClipContainingBlockDescendantsToContentBox(
    225      nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, uint32_t aFlags = 0) {
    226    NS_ASSERTION(!mRestored, "Already restored!");
    227    NS_ASSERTION(!mClipUsed, "mClip already used");
    228 #ifdef DEBUG
    229    mClipUsed = true;
    230 #endif
    231    mState.ClipContainingBlockDescendantsToContentBox(aBuilder, aFrame,
    232                                                      mClipChain, aFlags);
    233  }
    234 
    235  void MaybeRemoveDisplayportClip() {
    236    if (!mState.mClipChainContainingBlockDescendants) return;
    237 
    238    // Only remove the displayport clip in the case where it's the first
    239    // element of the clip chain. This covers the vast majority of cases,
    240    // and handling displayport clips later in the clip chain would introduce
    241    // significant added complexity.
    242    if (mState.mClipChainContainingBlockDescendants->IsDisplayportClip()) {
    243      auto* displayportClipItem = mState.mClipChainContainingBlockDescendants;
    244      mState.mClipChainContainingBlockDescendants =
    245          mState.mClipChainContainingBlockDescendants->mParent;
    246      mState.InvalidateCurrentCombinedClipChain(displayportClipItem->mASR);
    247    }
    248  }
    249 
    250 protected:
    251  nsDisplayListBuilder* mBuilder;
    252  DisplayListClipState& mState;
    253  DisplayListClipState mSavedState;
    254  DisplayItemClipChain mClipChain;
    255 #ifdef DEBUG
    256  bool mClipUsed;
    257  bool mRestored;
    258 #endif
    259 };
    260 
    261 class DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox
    262    : public AutoSaveRestore {
    263 public:
    264  AutoClipContainingBlockDescendantsToContentBox(nsDisplayListBuilder* aBuilder,
    265                                                 nsIFrame* aFrame,
    266                                                 uint32_t aFlags = 0)
    267      : AutoSaveRestore(aBuilder) {
    268 #ifdef DEBUG
    269    mClipUsed = true;
    270 #endif
    271    mState.ClipContainingBlockDescendantsToContentBox(aBuilder, aFrame,
    272                                                      mClipChain, aFlags);
    273  }
    274 };
    275 
    276 /**
    277 * Do not use this outside of nsIFrame::BuildDisplayListForChild, use
    278 * multiple AutoSaveRestores instead. We provide this class just to ensure
    279 * BuildDisplayListForChild is as efficient as possible.
    280 */
    281 class DisplayListClipState::AutoClipMultiple : public AutoSaveRestore {
    282 public:
    283  explicit AutoClipMultiple(nsDisplayListBuilder* aBuilder)
    284      : AutoSaveRestore(aBuilder)
    285 #ifdef DEBUG
    286        ,
    287        mExtraClipUsed(false)
    288 #endif
    289  {
    290  }
    291 
    292  /**
    293   * Intersects the given clip rect (with optional aRadii) with the current
    294   * mClipContainingBlockDescendants and sets mClipContainingBlockDescendants to
    295   * the result, stored in aClipOnStack.
    296   */
    297  void ClipContainingBlockDescendantsExtra(const nsRect& aRect,
    298                                           const nsRectCornerRadii* aRadii) {
    299    NS_ASSERTION(!mRestored, "Already restored!");
    300    NS_ASSERTION(!mExtraClipUsed, "mExtraClip already used");
    301 #ifdef DEBUG
    302    mExtraClipUsed = true;
    303 #endif
    304    mState.ClipContainingBlockDescendants(mBuilder, aRect, aRadii,
    305                                          mExtraClipChain);
    306  }
    307 
    308 protected:
    309  DisplayItemClipChain mExtraClipChain;
    310 #ifdef DEBUG
    311  bool mExtraClipUsed;
    312 #endif
    313 };
    314 
    315 }  // namespace mozilla
    316 
    317 #endif /* DISPLAYLISTCLIPSTATE_H_ */