layout/base/DisplayItemClip.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 DISPLAYITEMCLIP_H_
     7 #define DISPLAYITEMCLIP_H_
     9 #include "nsRect.h"
    10 #include "nsTArray.h"
    11 #include "nsStyleConsts.h"
    13 class gfxContext;
    14 class nsDisplayItem;
    15 class nsPresContext;
    16 class nsRegion;
    18 namespace mozilla {
    20 /**
    21  * An DisplayItemClip represents the intersection of an optional rectangle
    22  * with a list of rounded rectangles (which is often empty), all in appunits.
    23  * It can represent everything CSS clipping can do to an element (except for
    24  * SVG clip-path), including no clipping at all.
    25  */
    26 class DisplayItemClip {
    27 public:
    28   struct RoundedRect {
    29     nsRect mRect;
    30     // Indices into mRadii are the NS_CORNER_* constants in nsStyleConsts.h
    31     nscoord mRadii[8];
    33     RoundedRect operator+(const nsPoint& aOffset) const {
    34       RoundedRect r = *this;
    35       r.mRect += aOffset;
    36       return r;
    37     }
    38     bool operator==(const RoundedRect& aOther) const {
    39       if (!mRect.IsEqualInterior(aOther.mRect)) {
    40         return false;
    41       }
    43       NS_FOR_CSS_HALF_CORNERS(corner) {
    44         if (mRadii[corner] != aOther.mRadii[corner]) {
    45           return false;
    46         }
    47       }
    48       return true;
    49     }
    50     bool operator!=(const RoundedRect& aOther) const {
    51       return !(*this == aOther);
    52     }
    53   };
    55   // Constructs a DisplayItemClip that does no clipping at all.
    56   DisplayItemClip() : mHaveClipRect(false) {}
    58   void SetTo(const nsRect& aRect);
    59   void SetTo(const nsRect& aRect, const nscoord* aRadii);
    60   void IntersectWith(const DisplayItemClip& aOther);
    62   // Apply this |DisplayItemClip| to the given gfxContext.  Any saving of state
    63   // or clearing of other clips must be done by the caller.
    64   // See aBegin/aEnd note on ApplyRoundedRectsTo.
    65   void ApplyTo(gfxContext* aContext, nsPresContext* aPresContext,
    66                uint32_t aBegin = 0, uint32_t aEnd = UINT32_MAX);
    68   void ApplyRectTo(gfxContext* aContext, int32_t A2D) const;
    69   // Applies the rounded rects in this Clip to aContext
    70   // Will only apply rounded rects from aBegin (inclusive) to aEnd
    71   // (exclusive) or the number of rounded rects, whichever is smaller.
    72   void ApplyRoundedRectsTo(gfxContext* aContext, int32_t A2DPRInt32,
    73                            uint32_t aBegin, uint32_t aEnd) const;
    75   // Draw (fill) the rounded rects in this clip to aContext
    76   void DrawRoundedRectsTo(gfxContext* aContext, int32_t A2D,
    77                           uint32_t aBegin, uint32_t aEnd) const;
    78   // 'Draw' (create as a path, does not stroke or fill) aRoundRect to aContext
    79   void AddRoundedRectPathTo(gfxContext* aContext, int32_t A2D,
    80                             const RoundedRect &aRoundRect) const;
    82   // Returns true if the intersection of aRect and this clip region is
    83   // non-empty. This is precise for DisplayItemClips with at most one
    84   // rounded rectangle. When multiple rounded rectangles are present, we just
    85   // check that the rectangle intersects all of them (but possibly in different
    86   // places). So it may return true when the correct answer is false.
    87   bool MayIntersect(const nsRect& aRect) const;
    88   // Return a rectangle contained in the intersection of aRect with this
    89   // clip region. Tries to return the largest possible rectangle, but may
    90   // not succeed.
    91   nsRect ApproximateIntersectInward(const nsRect& aRect) const;
    93   /*
    94    * Computes a region which contains the clipped area of this DisplayItemClip,
    95    * or if aOldClip is non-null, the union of the clipped area of this
    96    * DisplayItemClip with the clipped area of aOldClip translated by aShift.
    97    * The result is stored in aCombined. If the result would be infinite
    98    * (because one or both of the clips does no clipping), returns false.
    99    */
   100   bool ComputeRegionInClips(DisplayItemClip* aOldClip,
   101                             const nsPoint& aShift,
   102                             nsRegion* aCombined) const;
   104   // Returns false if aRect is definitely not clipped by a rounded corner in
   105   // this clip. Returns true if aRect is clipped by a rounded corner in this
   106   // clip or it can not be quickly determined that it is not clipped by a
   107   // rounded corner in this clip.
   108   bool IsRectClippedByRoundedCorner(const nsRect& aRect) const;
   110   // Returns false if aRect is definitely not clipped by anything in this clip.
   111   // Fast but not necessarily accurate.
   112   bool IsRectAffectedByClip(const nsRect& aRect) const;
   114   // Intersection of all rects in this clip ignoring any rounded corners.
   115   nsRect NonRoundedIntersection() const;
   117   // Intersect the given rects with all rects in this clip, ignoring any
   118   // rounded corners.
   119   nsRect ApplyNonRoundedIntersection(const nsRect& aRect) const;
   121   // Gets rid of any rounded corners in this clip.
   122   void RemoveRoundedCorners();
   124   // Adds the difference between Intersect(*this + aPoint, aBounds) and
   125   // Intersect(aOther, aOtherBounds) to aDifference (or a bounding-box thereof).
   126   void AddOffsetAndComputeDifference(const nsPoint& aPoint, const nsRect& aBounds,
   127                                      const DisplayItemClip& aOther, const nsRect& aOtherBounds,
   128                                      nsRegion* aDifference);
   130   bool operator==(const DisplayItemClip& aOther) const {
   131     return mHaveClipRect == aOther.mHaveClipRect &&
   132            (!mHaveClipRect || mClipRect.IsEqualInterior(aOther.mClipRect)) &&
   133            mRoundedClipRects == aOther.mRoundedClipRects;
   134   }
   135   bool operator!=(const DisplayItemClip& aOther) const {
   136     return !(*this == aOther);
   137   }
   139   bool HasClip() const { return mHaveClipRect; }
   140   const nsRect& GetClipRect() const
   141   {
   142     NS_ASSERTION(HasClip(), "No clip rect!");
   143     return mClipRect;
   144   }
   146   void MoveBy(nsPoint aPoint);
   148 #ifdef MOZ_DUMP_PAINTING
   149   nsCString ToString() const;
   150 #endif
   152   /**
   153    * Find the largest N such that the first N rounded rects in 'this' are
   154    * equal to the first N rounded rects in aOther, and N <= aMax.
   155    */
   156   uint32_t GetCommonRoundedRectCount(const DisplayItemClip& aOther,
   157                                      uint32_t aMax) const;
   158   uint32_t GetRoundedRectCount() const { return mRoundedClipRects.Length(); }
   159   void AppendRoundedRects(nsTArray<RoundedRect>* aArray, uint32_t aCount) const;
   161   static const DisplayItemClip& NoClip();
   163   static void Shutdown();
   165 private:
   166   nsRect mClipRect;
   167   nsTArray<RoundedRect> mRoundedClipRects;
   168   // If mHaveClipRect is false then this object represents no clipping at all
   169   // and mRoundedClipRects must be empty.
   170   bool mHaveClipRect;
   171 };
   173 }
   175 #endif /* DISPLAYITEMCLIP_H_ */

mercurial