layout/base/DisplayListClipState.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 20; 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/. */
     6 #ifndef DISPLAYLISTCLIPSTATE_H_
     7 #define DISPLAYLISTCLIPSTATE_H_
     9 #include "DisplayItemClip.h"
    11 #include "mozilla/DebugOnly.h"
    13 class nsIFrame;
    14 class nsDisplayListBuilder;
    16 namespace mozilla {
    18 /**
    19  * All clip coordinates are in appunits relative to the reference frame
    20  * for the display item we're building.
    21  */
    22 class DisplayListClipState {
    23 public:
    24   DisplayListClipState()
    25     : mClipContentDescendants(nullptr)
    26     , mClipContainingBlockDescendants(nullptr)
    27     , mCurrentCombinedClip(nullptr)
    28   {}
    30   /**
    31    * Returns intersection of mClipContainingBlockDescendants and
    32    * mClipContentDescendants, allocated on aBuilder's arena.
    33    */
    34   const DisplayItemClip* GetCurrentCombinedClip(nsDisplayListBuilder* aBuilder);
    36   const DisplayItemClip* GetClipForContainingBlockDescendants() const
    37   {
    38     return mClipContainingBlockDescendants;
    39   }
    40   const DisplayItemClip* GetClipForContentDescendants() const
    41   {
    42     return mClipContentDescendants;
    43   }
    45   class AutoSaveRestore;
    46   friend class AutoSaveRestore;
    48   class AutoClipContainingBlockDescendantsToContentBox;
    49   friend class AutoClipContainingBlockDescendantsToContentBox;
    51   class AutoClipMultiple;
    52   friend class AutoClipMultiple;
    54   enum {
    55     ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT = 0x01
    56   };
    58 private:
    59   void SetClipForContainingBlockDescendants(const DisplayItemClip* aClip)
    60   {
    61     mClipContainingBlockDescendants = aClip;
    62     mCurrentCombinedClip = nullptr;
    63   }
    65   void Clear()
    66   {
    67     mClipContentDescendants = nullptr;
    68     mClipContainingBlockDescendants = nullptr;
    69     mCurrentCombinedClip = nullptr;
    70   }
    72   /**
    73    * Intersects the given clip rect (with optional aRadii) with the current
    74    * mClipContainingBlockDescendants and sets mClipContainingBlockDescendants to
    75    * the result, stored in aClipOnStack.
    76    */
    77   void ClipContainingBlockDescendants(const nsRect& aRect,
    78                                       const nscoord* aRadii,
    79                                       DisplayItemClip& aClipOnStack);
    81   void ClipContentDescendants(const nsRect& aRect,
    82                               const nscoord* aRadii,
    83                               DisplayItemClip& aClipOnStack);
    85   /**
    86    * Clips containing-block descendants to the frame's content-box,
    87    * taking border-radius into account.
    88    * If aFlags contains ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT then
    89    * we assume display items will not draw outside the content rect, so
    90    * clipping is only required if there is a border-radius. This is an
    91    * optimization to reduce the amount of clipping required.
    92    */
    93   void ClipContainingBlockDescendantsToContentBox(nsDisplayListBuilder* aBuilder,
    94                                                   nsIFrame* aFrame,
    95                                                   DisplayItemClip& aClipOnStack,
    96                                                   uint32_t aFlags);
    98   /**
    99    * All content descendants (i.e. following placeholder frames to their
   100    * out-of-flows if necessary) should be clipped by mClipContentDescendants.
   101    * Null if no clipping applies.
   102    */
   103   const DisplayItemClip* mClipContentDescendants;
   104   /**
   105    * All containing-block descendants (i.e. frame descendants), including
   106    * display items for the current frame, should be clipped by
   107    * mClipContainingBlockDescendants.
   108    * Null if no clipping applies.
   109    */
   110   const DisplayItemClip* mClipContainingBlockDescendants;
   111   /**
   112    * The intersection of mClipContentDescendants and
   113    * mClipContainingBlockDescendants.
   114    * Allocated in the nsDisplayListBuilder arena. Null if none has been
   115    * allocated or both mClipContentDescendants and mClipContainingBlockDescendants
   116    * are null.
   117    */
   118   const DisplayItemClip* mCurrentCombinedClip;
   119 };
   121 /**
   122  * A class to automatically save and restore the current clip state. Also
   123  * offers methods for modifying the clip state. Only one modification is allowed
   124  * to be in scope at a time using one of these objects; multiple modifications
   125  * require nested objects. The interface is written this way to prevent
   126  * dangling pointers to DisplayItemClips.
   127  */
   128 class DisplayListClipState::AutoSaveRestore {
   129 public:
   130   AutoSaveRestore(nsDisplayListBuilder* aBuilder);
   131   void Restore()
   132   {
   133     mState = mSavedState;
   134     mRestored = true;
   135   }
   136   ~AutoSaveRestore()
   137   {
   138     mState = mSavedState;
   139   }
   141   void Clear()
   142   {
   143     NS_ASSERTION(!mRestored, "Already restored!");
   144     mState.Clear();
   145     mClipUsed = false;
   146   }
   148   /**
   149    * Intersects the given clip rect (with optional aRadii) with the current
   150    * mClipContainingBlockDescendants and sets mClipContainingBlockDescendants to
   151    * the result, stored in aClipOnStack.
   152    */
   153   void ClipContainingBlockDescendants(const nsRect& aRect,
   154                                       const nscoord* aRadii = nullptr)
   155   {
   156     NS_ASSERTION(!mRestored, "Already restored!");
   157     NS_ASSERTION(!mClipUsed, "mClip already used");
   158     mClipUsed = true;
   159     mState.ClipContainingBlockDescendants(aRect, aRadii, mClip);
   160   }
   162   void ClipContentDescendants(const nsRect& aRect,
   163                               const nscoord* aRadii = nullptr)
   164   {
   165     NS_ASSERTION(!mRestored, "Already restored!");
   166     NS_ASSERTION(!mClipUsed, "mClip already used");
   167     mClipUsed = true;
   168     mState.ClipContentDescendants(aRect, aRadii, mClip);
   169   }
   171   /**
   172    * Clips containing-block descendants to the frame's content-box,
   173    * taking border-radius into account.
   174    * If aFlags contains ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT then
   175    * we assume display items will not draw outside the content rect, so
   176    * clipping is only required if there is a border-radius. This is an
   177    * optimization to reduce the amount of clipping required.
   178    */
   179   void ClipContainingBlockDescendantsToContentBox(nsDisplayListBuilder* aBuilder,
   180                                                   nsIFrame* aFrame,
   181                                                   uint32_t aFlags = 0)
   182   {
   183     NS_ASSERTION(!mRestored, "Already restored!");
   184     NS_ASSERTION(!mClipUsed, "mClip already used");
   185     mClipUsed = true;
   186     mState.ClipContainingBlockDescendantsToContentBox(aBuilder, aFrame, mClip, aFlags);
   187   }
   189 protected:
   190   DisplayListClipState& mState;
   191   DisplayListClipState mSavedState;
   192   DisplayItemClip mClip;
   193   DebugOnly<bool> mClipUsed;
   194   DebugOnly<bool> mRestored;
   195 };
   197 class DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox : public AutoSaveRestore {
   198 public:
   199   AutoClipContainingBlockDescendantsToContentBox(nsDisplayListBuilder* aBuilder,
   200                                                  nsIFrame* aFrame,
   201                                                  uint32_t aFlags = 0)
   202     : AutoSaveRestore(aBuilder)
   203   {
   204     mClipUsed = true;
   205     mState.ClipContainingBlockDescendantsToContentBox(aBuilder, aFrame, mClip, aFlags);
   206   }
   207 };
   209 /**
   210  * Do not use this outside of nsFrame::BuildDisplayListForChild, use
   211  * multiple AutoSaveRestores instead. We provide this class just to ensure
   212  * BuildDisplayListForChild is as efficient as possible.
   213  */
   214 class DisplayListClipState::AutoClipMultiple : public AutoSaveRestore {
   215 public:
   216   AutoClipMultiple(nsDisplayListBuilder* aBuilder)
   217     : AutoSaveRestore(aBuilder)
   218     , mExtraClipUsed(false)
   219   {}
   221   /**
   222    * *aClip must survive longer than this object. Be careful!!!
   223    */
   224   void SetClipForContainingBlockDescendants(const DisplayItemClip* aClip)
   225   {
   226     mState.SetClipForContainingBlockDescendants(aClip);
   227   }
   229   /**
   230    * Intersects the given clip rect (with optional aRadii) with the current
   231    * mClipContainingBlockDescendants and sets mClipContainingBlockDescendants to
   232    * the result, stored in aClipOnStack.
   233    */
   234   void ClipContainingBlockDescendantsExtra(const nsRect& aRect,
   235                                            const nscoord* aRadii)
   236   {
   237     NS_ASSERTION(!mRestored, "Already restored!");
   238     NS_ASSERTION(!mExtraClipUsed, "mExtraClip already used");
   239     mExtraClipUsed = true;
   240     mState.ClipContainingBlockDescendants(aRect, aRadii, mExtraClip);
   241   }
   243 protected:
   244   DisplayItemClip mExtraClip;
   245   DebugOnly<bool> mExtraClipUsed;
   246 };
   248 }
   250 #endif /* DISPLAYLISTCLIPSTATE_H_ */

mercurial