31f95508dcdbb5a426d8fe1c3c958beb15d21a1f
[WebKit-https.git] / Source / WebCore / rendering / LayerOverlapMap.cpp
1 /*
2  * Copyright (C) 2019 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "LayerOverlapMap.h"
28 #include <wtf/text/TextStream.h>
29
30 namespace WebCore {
31
32 struct RectList {
33     Vector<LayoutRect> rects;
34     LayoutRect boundingRect;
35     
36     void append(const LayoutRect& rect)
37     {
38         rects.append(rect);
39         boundingRect.unite(rect);
40     }
41
42     void append(const RectList& rectList)
43     {
44         rects.appendVector(rectList.rects);
45         boundingRect.unite(rectList.boundingRect);
46     }
47     
48     bool intersects(const LayoutRect& rect) const
49     {
50         if (!rects.size() || !rect.intersects(boundingRect))
51             return false;
52
53         for (const auto& currentRect : rects) {
54             if (currentRect.intersects(rect))
55                 return true;
56         }
57         return false;
58     }
59 };
60
61 class OverlapMapContainer {
62 public:
63     void add(const LayoutRect& bounds)
64     {
65         m_rectList.append(bounds);
66     }
67
68     bool overlapsLayers(const LayoutRect& bounds) const
69     {
70         return m_rectList.intersects(bounds);
71     }
72
73     void unite(const OverlapMapContainer& otherContainer)
74     {
75         m_rectList.append(otherContainer.m_rectList);
76     }
77     
78     const RectList& rectList() const { return m_rectList; }
79
80 private:
81     RectList m_rectList;
82 };
83
84 LayerOverlapMap::LayerOverlapMap()
85     : m_geometryMap(UseTransforms)
86 {
87     // Begin assuming the root layer will be composited so that there is
88     // something on the stack. The root layer should also never get an
89     // popCompositingContainer call.
90     pushCompositingContainer();
91 }
92
93 LayerOverlapMap::~LayerOverlapMap() = default;
94
95 void LayerOverlapMap::add(const LayoutRect& bounds)
96 {
97     // Layers do not contribute to overlap immediately--instead, they will
98     // contribute to overlap as soon as their composited ancestor has been
99     // recursively processed and popped off the stack.
100     ASSERT(m_overlapStack.size() >= 2);
101     m_overlapStack[m_overlapStack.size() - 2]->add(bounds);
102     m_isEmpty = false;
103 }
104
105 bool LayerOverlapMap::overlapsLayers(const LayoutRect& bounds) const
106 {
107     return m_overlapStack.last()->overlapsLayers(bounds);
108 }
109
110 void LayerOverlapMap::pushCompositingContainer()
111 {
112     m_overlapStack.append(std::make_unique<OverlapMapContainer>());
113 }
114
115 void LayerOverlapMap::popCompositingContainer()
116 {
117     m_overlapStack[m_overlapStack.size() - 2]->unite(*m_overlapStack.last());
118     m_overlapStack.removeLast();
119 }
120
121 static TextStream& operator<<(TextStream& ts, const RectList& rectList)
122 {
123     ts << "bounds " << rectList.boundingRect << " (" << rectList.rects << " rects)";
124     return ts;
125 }
126
127 static TextStream& operator<<(TextStream& ts, const OverlapMapContainer& container)
128 {
129     ts << container.rectList();
130     return ts;
131 }
132
133 TextStream& operator<<(TextStream& ts, const LayerOverlapMap& overlapMap)
134 {
135     TextStream multilineStream;
136
137     TextStream::GroupScope scope(ts);
138     multilineStream << indent << "LayerOverlapMap\n";
139
140     for (auto& container : overlapMap.overlapStack())
141         multilineStream << "  " << *container << "\n";
142
143     ts << multilineStream.release();
144     return ts;
145 }
146
147 } // namespace WebCore