Home | History | Annotate | Download | only in rendering
      1 /*
      2  * Copyright (C) 2003, 2009, 2012 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #ifndef ClipRect_h
     27 #define ClipRect_h
     28 
     29 #include "platform/geometry/LayoutRect.h"
     30 
     31 #include "wtf/Vector.h"
     32 
     33 #ifndef NDEBUG
     34 #include "core/rendering/RenderBox.h" // For OverlayScrollbarSizeRelevancy.
     35 #endif
     36 
     37 namespace WebCore {
     38 
     39 class RenderLayer;
     40 class HitTestLocation;
     41 
     42 class ClipRect {
     43 public:
     44     ClipRect()
     45         : m_hasRadius(false)
     46     { }
     47 
     48     ClipRect(const LayoutRect& rect)
     49         : m_rect(rect)
     50         , m_hasRadius(false)
     51     { }
     52 
     53     const LayoutRect& rect() const { return m_rect; }
     54     void setRect(const LayoutRect& rect) { m_rect = rect; }
     55 
     56     bool hasRadius() const { return m_hasRadius; }
     57     void setHasRadius(bool hasRadius) { m_hasRadius = hasRadius; }
     58 
     59     bool operator==(const ClipRect& other) const { return rect() == other.rect() && hasRadius() == other.hasRadius(); }
     60     bool operator!=(const ClipRect& other) const { return rect() != other.rect() || hasRadius() != other.hasRadius(); }
     61     bool operator!=(const LayoutRect& otherRect) const { return rect() != otherRect; }
     62 
     63     void intersect(const LayoutRect& other) { m_rect.intersect(other); }
     64     void intersect(const ClipRect& other)
     65     {
     66         m_rect.intersect(other.rect());
     67         if (other.hasRadius())
     68             m_hasRadius = true;
     69     }
     70     void move(LayoutUnit x, LayoutUnit y) { m_rect.move(x, y); }
     71     void move(const LayoutSize& size) { m_rect.move(size); }
     72     void moveBy(const LayoutPoint& point) { m_rect.moveBy(point); }
     73 
     74     bool isEmpty() const { return m_rect.isEmpty(); }
     75     bool intersects(const LayoutRect& rect) const { return m_rect.intersects(rect); }
     76     bool intersects(const HitTestLocation&) const;
     77 
     78 private:
     79     LayoutRect m_rect;
     80     bool m_hasRadius;
     81 };
     82 
     83 inline ClipRect intersection(const ClipRect& a, const ClipRect& b)
     84 {
     85     ClipRect c = a;
     86     c.intersect(b);
     87     return c;
     88 }
     89 
     90 class ClipRects {
     91     WTF_MAKE_FAST_ALLOCATED;
     92 public:
     93     static PassRefPtr<ClipRects> create()
     94     {
     95         return adoptRef(new ClipRects);
     96     }
     97 
     98     static PassRefPtr<ClipRects> create(const ClipRects& other)
     99     {
    100         return adoptRef(new ClipRects(other));
    101     }
    102 
    103     ClipRects()
    104         : m_refCnt(1)
    105         , m_fixed(0)
    106     {
    107     }
    108 
    109     void reset(const LayoutRect& r)
    110     {
    111         m_overflowClipRect = r;
    112         m_fixedClipRect = r;
    113         m_posClipRect = r;
    114         m_fixed = 0;
    115     }
    116 
    117     const ClipRect& overflowClipRect() const { return m_overflowClipRect; }
    118     void setOverflowClipRect(const ClipRect& r) { m_overflowClipRect = r; }
    119 
    120     const ClipRect& fixedClipRect() const { return m_fixedClipRect; }
    121     void setFixedClipRect(const ClipRect&r) { m_fixedClipRect = r; }
    122 
    123     const ClipRect& posClipRect() const { return m_posClipRect; }
    124     void setPosClipRect(const ClipRect& r) { m_posClipRect = r; }
    125 
    126     bool fixed() const { return static_cast<bool>(m_fixed); }
    127     void setFixed(bool fixed) { m_fixed = fixed ? 1 : 0; }
    128 
    129     void ref() { m_refCnt++; }
    130     void deref()
    131     {
    132         if (!--m_refCnt)
    133             delete this;
    134     }
    135 
    136     bool operator==(const ClipRects& other) const
    137     {
    138         return m_overflowClipRect == other.overflowClipRect()
    139             && m_fixedClipRect == other.fixedClipRect()
    140             && m_posClipRect == other.posClipRect()
    141             && fixed() == other.fixed();
    142     }
    143 
    144     ClipRects& operator=(const ClipRects& other)
    145     {
    146         m_overflowClipRect = other.overflowClipRect();
    147         m_fixedClipRect = other.fixedClipRect();
    148         m_posClipRect = other.posClipRect();
    149         m_fixed = other.fixed();
    150         return *this;
    151     }
    152 
    153 private:
    154     ClipRects(const LayoutRect& r)
    155         : m_overflowClipRect(r)
    156         , m_fixedClipRect(r)
    157         , m_posClipRect(r)
    158         , m_refCnt(1)
    159         , m_fixed(0)
    160     {
    161     }
    162 
    163     ClipRects(const ClipRects& other)
    164         : m_overflowClipRect(other.overflowClipRect())
    165         , m_fixedClipRect(other.fixedClipRect())
    166         , m_posClipRect(other.posClipRect())
    167         , m_refCnt(1)
    168         , m_fixed(other.fixed())
    169     {
    170     }
    171 
    172     ClipRect m_overflowClipRect;
    173     ClipRect m_fixedClipRect;
    174     ClipRect m_posClipRect;
    175     unsigned m_refCnt : 31;
    176     unsigned m_fixed : 1;
    177 };
    178 
    179 enum ClipRectsType {
    180     PaintingClipRects, // Relative to painting ancestor. Used for painting.
    181     RootRelativeClipRects, // Relative to the ancestor treated as the root (e.g. transformed layer). Used for hit testing.
    182     CompositingClipRects, // Relative to the compositing ancestor. Used for updating graphics layer geometry.
    183     AbsoluteClipRects, // Relative to the RenderView's layer. Used for compositing overlap testing.
    184     NumCachedClipRectsTypes,
    185     AllClipRectTypes,
    186     TemporaryClipRects
    187 };
    188 
    189 enum ShouldRespectOverflowClip {
    190     IgnoreOverflowClip,
    191     RespectOverflowClip
    192 };
    193 
    194 struct ClipRectsCache {
    195     WTF_MAKE_FAST_ALLOCATED;
    196 public:
    197     ClipRectsCache()
    198     {
    199         for (int i = 0; i < NumCachedClipRectsTypes; ++i) {
    200             m_clipRectsRoot[i] = 0;
    201 #ifndef NDEBUG
    202             m_scrollbarRelevancy[i] = IgnoreOverlayScrollbarSize;
    203 #endif
    204         }
    205     }
    206 
    207     PassRefPtr<ClipRects> getClipRects(ClipRectsType clipRectsType, ShouldRespectOverflowClip respectOverflow) { return m_clipRects[getIndex(clipRectsType, respectOverflow)]; }
    208     void setClipRects(ClipRectsType clipRectsType, ShouldRespectOverflowClip respectOverflow, PassRefPtr<ClipRects> clipRects, const RenderLayer* root)
    209     {
    210         m_clipRects[getIndex(clipRectsType, respectOverflow)] = clipRects;
    211         m_clipRectsRoot[clipRectsType] = root;
    212     }
    213 
    214     const RenderLayer* clipRectsRoot(ClipRectsType clipRectsType) const { return m_clipRectsRoot[clipRectsType]; }
    215 
    216 #ifndef NDEBUG
    217     OverlayScrollbarSizeRelevancy m_scrollbarRelevancy[NumCachedClipRectsTypes];
    218 #endif
    219 
    220 private:
    221     int getIndex(ClipRectsType clipRectsType, ShouldRespectOverflowClip respectOverflow)
    222     {
    223         int index = static_cast<int>(clipRectsType);
    224         if (respectOverflow == RespectOverflowClip)
    225             index += static_cast<int>(NumCachedClipRectsTypes);
    226         return index;
    227     }
    228 
    229     const RenderLayer* m_clipRectsRoot[NumCachedClipRectsTypes];
    230     RefPtr<ClipRects> m_clipRects[NumCachedClipRectsTypes * 2];
    231 };
    232 
    233 struct LayerFragment {
    234 public:
    235     LayerFragment()
    236         : shouldPaintContent(false)
    237     { }
    238 
    239     void setRects(const LayoutRect& bounds, const ClipRect& background, const ClipRect& foreground, const ClipRect& outline)
    240     {
    241         layerBounds = bounds;
    242         backgroundRect = background;
    243         foregroundRect = foreground;
    244         outlineRect = outline;
    245     }
    246 
    247     void moveBy(const LayoutPoint& offset)
    248     {
    249         layerBounds.moveBy(offset);
    250         backgroundRect.moveBy(offset);
    251         foregroundRect.moveBy(offset);
    252         outlineRect.moveBy(offset);
    253         paginationClip.moveBy(offset);
    254     }
    255 
    256     void intersect(const LayoutRect& rect)
    257     {
    258         backgroundRect.intersect(rect);
    259         foregroundRect.intersect(rect);
    260         outlineRect.intersect(rect);
    261     }
    262 
    263     bool shouldPaintContent;
    264     LayoutRect layerBounds;
    265     ClipRect backgroundRect;
    266     ClipRect foregroundRect;
    267     ClipRect outlineRect;
    268 
    269     // Unique to paginated fragments. The physical translation to apply to shift the layer when painting/hit-testing.
    270     LayoutPoint paginationOffset;
    271 
    272     // Also unique to paginated fragments. An additional clip that applies to the layer. It is in layer-local
    273     // (physical) coordinates.
    274     LayoutRect paginationClip;
    275 };
    276 
    277 typedef Vector<LayerFragment, 1> LayerFragments;
    278 
    279 } // namespace WebCore
    280 
    281 #endif // ClipRect_h
    282