1/*
2 * Copyright (C) 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 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
27#ifndef RenderNamedFlowThread_h
28#define RenderNamedFlowThread_h
29
30#include "RenderFlowThread.h"
31#include "SelectionSubtreeRoot.h"
32#include "Timer.h"
33#include <wtf/HashCountedSet.h>
34#include <wtf/ListHashSet.h>
35#include <wtf/text/AtomicString.h>
36
37namespace WebCore {
38
39class Node;
40class RenderNamedFlowThread;
41class WebKitNamedFlow;
42
43typedef ListHashSet<RenderNamedFlowThread*> RenderNamedFlowThreadList;
44typedef HashCountedSet<RenderNamedFlowThread*> RenderNamedFlowThreadCountedSet;
45typedef ListHashSet<Element*> NamedFlowContentElements;
46
47class RenderNamedFlowThread final : public RenderFlowThread, public SelectionSubtreeRoot {
48public:
49    RenderNamedFlowThread(Document&, PassRef<RenderStyle>, PassRef<WebKitNamedFlow>);
50    virtual ~RenderNamedFlowThread();
51
52    const AtomicString& flowThreadName() const;
53
54    const RenderRegionList& invalidRenderRegionList() const { return m_invalidRegionList; }
55
56    RenderElement* nextRendererForElement(Element&) const;
57
58    void addFlowChild(RenderElement&);
59    void removeFlowChild(RenderElement&);
60    bool hasChildren() const { return !m_flowThreadChildList.isEmpty(); }
61#ifndef NDEBUG
62    bool hasChild(RenderElement& child) const { return m_flowThreadChildList.contains(&child); }
63#endif
64
65    void pushDependencies(RenderNamedFlowThreadList&);
66
67    virtual void addRegionToThread(RenderRegion*) override;
68    virtual void removeRegionFromThread(RenderRegion*) override;
69
70    virtual void regionChangedWritingMode(RenderRegion*) override;
71
72    LayoutRect decorationsClipRectForBoxInNamedFlowFragment(const RenderBox&, RenderNamedFlowFragment&) const;
73
74    RenderNamedFlowFragment* fragmentFromAbsolutePointAndBox(const IntPoint&, const RenderBox& flowedBox);
75
76    void registerNamedFlowContentElement(Element&);
77    void unregisterNamedFlowContentElement(Element&);
78    const NamedFlowContentElements& contentElements() const { return m_contentElements; }
79    bool hasContentElement(Element&) const;
80
81    bool isMarkedForDestruction() const;
82    void getRanges(Vector<RefPtr<Range>>&, const RenderNamedFlowFragment*) const;
83
84    virtual void applyBreakAfterContent(LayoutUnit) override final;
85
86    virtual bool collectsGraphicsLayersUnderRegions() const override;
87
88    // Check if the content is flown into at least a region with region styling rules.
89    bool hasRegionsWithStyling() const { return m_hasRegionsWithStyling; }
90    void checkRegionsWithStyling();
91
92    void clearRenderObjectCustomStyle(const RenderObject*);
93
94    virtual void removeFlowChildInfo(RenderObject*) override final;
95
96    LayoutUnit flowContentBottom() const { return m_flowContentBottom; }
97    void dispatchNamedFlowEvents();
98
99    void setDispatchRegionOversetChangeEvent(bool value) { m_dispatchRegionOversetChangeEvent = value; }
100
101    virtual bool absoluteQuadsForBox(Vector<FloatQuad>&, bool*, const RenderBox*, float, float) const override;
102
103protected:
104    void setMarkForDestruction();
105    void resetMarkForDestruction();
106
107private:
108    virtual const char* renderName() const override;
109    virtual bool isRenderNamedFlowThread() const override { return true; }
110    virtual bool isChildAllowed(const RenderObject&, const RenderStyle&) const override;
111    virtual void computeOverflow(LayoutUnit, bool = false) override;
112    virtual void layout() override final;
113
114    void dispatchRegionOversetChangeEventIfNeeded();
115
116    bool dependsOn(RenderNamedFlowThread* otherRenderFlowThread) const;
117    void addDependencyOnFlowThread(RenderNamedFlowThread*);
118    void removeDependencyOnFlowThread(RenderNamedFlowThread*);
119
120    void addFragmentToNamedFlowThread(RenderNamedFlowFragment*);
121
122    void checkInvalidRegions();
123
124    bool canBeDestroyed() const { return m_invalidRegionList.isEmpty() && m_regionList.isEmpty() && m_contentElements.isEmpty(); }
125    void regionOversetChangeEventTimerFired(Timer<RenderNamedFlowThread>&);
126    void clearContentElements();
127    void updateWritingMode();
128
129    WebKitNamedFlow& namedFlow() { return m_namedFlow.get(); }
130    const WebKitNamedFlow& namedFlow() const { return m_namedFlow.get(); }
131
132    // Observer flow threads have invalid regions that depend on the state of this thread
133    // to re-validate their regions. Keeping a set of observer threads make it easy
134    // to notify them when a region was removed from this flow.
135    RenderNamedFlowThreadCountedSet m_observerThreadsSet;
136
137    // Some threads need to have a complete layout before we layout this flow.
138    // That's because they contain a RenderRegion that should display this thread. The set makes it
139    // easy to sort the order of threads layout.
140    RenderNamedFlowThreadCountedSet m_layoutBeforeThreadsSet;
141
142    // Holds the sorted children of a named flow. This is the only way we can get the ordering right.
143    ListHashSet<RenderElement*> m_flowThreadChildList;
144
145    NamedFlowContentElements m_contentElements;
146
147    RenderRegionList m_invalidRegionList;
148
149    bool m_hasRegionsWithStyling : 1;
150    bool m_dispatchRegionOversetChangeEvent : 1;
151
152    // The DOM Object that represents a named flow.
153    Ref<WebKitNamedFlow> m_namedFlow;
154
155    Timer<RenderNamedFlowThread> m_regionOversetChangeEventTimer;
156
157    LayoutUnit m_flowContentBottom;
158};
159
160RENDER_OBJECT_TYPE_CASTS(RenderNamedFlowThread, isRenderNamedFlowThread())
161
162} // namespace WebCore
163
164#endif // RenderNamedFlowThread_h
165