2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2006 Apple Computer, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
25 #include "core/frame/FrameView.h"
26 #include "core/rendering/LayoutState.h"
27 #include "core/rendering/RenderBlockFlow.h"
28 #include "platform/PODFreeListArena.h"
29 #include "platform/scroll/ScrollableArea.h"
30 #include "wtf/OwnPtr.h"
34 class FlowThreadController;
35 class RenderLayerCompositor;
38 struct OutlineRectInfo {
39 LayoutRect oldOutlineRect;
40 LayoutRect newOutlineRect;
42 typedef HashMap<RenderObject*, OwnPtr<OutlineRectInfo> > OutlineRects;
44 // The root of the render tree, corresponding to the CSS initial containing block.
45 // It's dimensions match that of the logical viewport (which may be different from
46 // the visible viewport in fixed-layout mode), and it is always at position (0,0)
47 // relative to the document (and so isn't necessarily in view).
48 class RenderView FINAL : public RenderBlockFlow {
50 explicit RenderView(Document*);
51 virtual ~RenderView();
53 bool hitTest(const HitTestRequest&, HitTestResult&);
54 bool hitTest(const HitTestRequest&, const HitTestLocation&, HitTestResult&);
56 virtual const char* renderName() const OVERRIDE { return "RenderView"; }
58 virtual bool isRenderView() const OVERRIDE { return true; }
60 virtual LayerType layerTypeRequired() const OVERRIDE { return NormalLayer; }
62 virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
64 virtual void layout() OVERRIDE;
65 virtual void updateLogicalWidth() OVERRIDE;
66 virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const OVERRIDE;
68 virtual LayoutUnit availableLogicalHeight(AvailableLogicalHeightType) const OVERRIDE;
70 // The same as the FrameView's layoutHeight/layoutWidth but with null check guards.
71 int viewHeight(IncludeScrollbarsInRect = ExcludeScrollbars) const;
72 int viewWidth(IncludeScrollbarsInRect = ExcludeScrollbars) const;
73 int viewLogicalWidth() const
75 return style()->isHorizontalWritingMode() ? viewWidth(ExcludeScrollbars) : viewHeight(ExcludeScrollbars);
77 int viewLogicalHeight() const;
79 float zoomFactor() const;
81 FrameView* frameView() const { return m_frameView; }
83 virtual void computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect&, bool fixed = false) const OVERRIDE;
84 void repaintViewRectangle(const LayoutRect&) const;
86 void repaintViewAndCompositedLayers();
88 virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
89 virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&) OVERRIDE;
91 enum SelectionRepaintMode { RepaintNewXOROld, RepaintNewMinusOld, RepaintNothing };
92 void setSelection(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode = RepaintNewXOROld);
93 void getSelection(RenderObject*& startRenderer, int& startOffset, RenderObject*& endRenderer, int& endOffset) const;
94 void clearSelection();
95 RenderObject* selectionStart() const { return m_selectionStart; }
96 RenderObject* selectionEnd() const { return m_selectionEnd; }
97 IntRect selectionBounds(bool clipToVisibleContent = true) const;
98 void selectionStartEnd(int& startPos, int& endPos) const;
99 void repaintSelection() const;
101 virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const OVERRIDE;
102 virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const OVERRIDE;
104 virtual LayoutRect viewRect() const OVERRIDE;
106 // layoutDelta is used transiently during layout to store how far an object has moved from its
107 // last layout location, in order to repaint correctly.
108 // If we're doing a full repaint m_layoutState will be 0, but in that case layoutDelta doesn't matter.
109 LayoutSize layoutDelta() const
111 ASSERT(!RuntimeEnabledFeatures::repaintAfterLayoutEnabled());
112 return m_layoutState ? m_layoutState->layoutDelta() : LayoutSize();
114 void addLayoutDelta(const LayoutSize& delta)
116 ASSERT(!RuntimeEnabledFeatures::repaintAfterLayoutEnabled());
118 m_layoutState->addLayoutDelta(delta);
122 bool layoutDeltaMatches(const LayoutSize& delta)
124 ASSERT(!RuntimeEnabledFeatures::repaintAfterLayoutEnabled());
127 return (delta.width() == m_layoutState->layoutDelta().width() || m_layoutState->layoutDeltaXSaturated()) && (delta.height() == m_layoutState->layoutDelta().height() || m_layoutState->layoutDeltaYSaturated());
131 bool doingFullRepaint() const { return m_frameView->needsFullRepaint(); }
134 void pushLayoutState(RenderObject&);
136 void popLayoutState()
138 LayoutState* state = m_layoutState;
139 m_layoutState = state->next();
141 popLayoutStateForCurrentFlowThread();
144 bool shouldDisableLayoutStateForSubtree(RenderObject&) const;
146 // Returns true if layoutState should be used for its cached offset and clip.
147 bool layoutStateEnabled() const { return m_layoutStateDisableCount == 0 && m_layoutState; }
148 LayoutState* layoutState() const { return m_layoutState; }
150 virtual void updateHitTestResult(HitTestResult&, const LayoutPoint&) OVERRIDE;
152 LayoutUnit pageLogicalHeight() const { return m_pageLogicalHeight; }
153 void setPageLogicalHeight(LayoutUnit height)
155 if (m_pageLogicalHeight != height) {
156 m_pageLogicalHeight = height;
157 m_pageLogicalHeightChanged = true;
160 bool pageLogicalHeightChanged() const { return m_pageLogicalHeightChanged; }
162 // Notification that this view moved into or out of a native window.
163 void setIsInWindow(bool);
165 RenderLayerCompositor* compositor();
166 bool usesCompositing() const;
168 IntRect unscaledDocumentRect() const;
169 LayoutRect backgroundRect(RenderBox* backgroundRenderer) const;
171 IntRect documentRect() const;
173 // Renderer that paints the root background has background-images which all have background-attachment: fixed.
174 bool rootBackgroundIsEntirelyFixed() const;
176 FlowThreadController* flowThreadController();
178 IntervalArena* intervalArena();
180 void setRenderQuoteHead(RenderQuote* head) { m_renderQuoteHead = head; }
181 RenderQuote* renderQuoteHead() const { return m_renderQuoteHead; }
183 // FIXME: This is a work around because the current implementation of counters
184 // requires walking the entire tree repeatedly and most pages don't actually use either
185 // feature so we shouldn't take the performance hit when not needed. Long term we should
186 // rewrite the counter and quotes code.
187 void addRenderCounter() { m_renderCounterCount++; }
188 void removeRenderCounter() { ASSERT(m_renderCounterCount > 0); m_renderCounterCount--; }
189 bool hasRenderCounters() { return m_renderCounterCount; }
191 virtual bool backgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) const OVERRIDE;
193 double layoutViewportWidth() const;
194 double layoutViewportHeight() const;
196 // Suspends the LayoutState optimization. Used under transforms that cannot be represented by
197 // LayoutState (common in SVG) and when manipulating the render tree during layout in ways
198 // that can trigger repaint of a non-child (e.g. when a list item moves its list marker around).
199 // Note that even when disabled, LayoutState is still used to store layoutDelta.
200 // These functions may only be accessed by LayoutStateMaintainer or LayoutStateDisabler.
201 void disableLayoutState() { m_layoutStateDisableCount++; }
202 void enableLayoutState() { ASSERT(m_layoutStateDisableCount > 0); m_layoutStateDisableCount--; }
204 OutlineRects& outlineRects() { return m_outlineRects; }
207 virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE;
208 virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE;
209 virtual void mapAbsoluteToLocalPoint(MapCoordinatesFlags, TransformState&) const OVERRIDE;
210 virtual void computeSelfHitTestRects(Vector<LayoutRect>&, const LayoutPoint& layerOffset) const OVERRIDE;
212 bool shouldRepaint(const LayoutRect&) const;
214 bool rootFillsViewportBackground(RenderBox* rootBox) const;
216 // These functions may only be accessed by LayoutStateMaintainer.
217 bool pushLayoutState(RenderBox& renderer, const LayoutSize& offset, LayoutUnit pageHeight = 0, bool pageHeightChanged = false, ColumnInfo* colInfo = 0)
219 // We push LayoutState even if layoutState is disabled because it stores layoutDelta too.
220 if (!doingFullRepaint() || m_layoutState->isPaginated() || renderer.hasColumns() || renderer.flowThreadContainingBlock()
222 pushLayoutStateForCurrentFlowThread(renderer);
223 m_layoutState = new LayoutState(m_layoutState, renderer, offset, pageHeight, pageHeightChanged, colInfo);
229 void layoutContent();
231 void checkLayoutState();
234 void positionDialog(RenderBox*);
235 void positionDialogs();
237 void pushLayoutStateForCurrentFlowThread(const RenderObject&);
238 void popLayoutStateForCurrentFlowThread();
240 friend class LayoutStateMaintainer;
241 friend class LayoutStateDisabler;
242 friend class RootLayoutStateScope;
244 bool shouldUsePrintingLayout() const;
246 FrameView* m_frameView;
248 RenderObject* m_selectionStart;
249 RenderObject* m_selectionEnd;
251 int m_selectionStartPos;
252 int m_selectionEndPos;
254 LayoutUnit m_pageLogicalHeight;
255 bool m_pageLogicalHeightChanged;
256 LayoutState* m_layoutState;
257 unsigned m_layoutStateDisableCount;
258 OwnPtr<RenderLayerCompositor> m_compositor;
259 OwnPtr<FlowThreadController> m_flowThreadController;
260 RefPtr<IntervalArena> m_intervalArena;
262 RenderQuote* m_renderQuoteHead;
263 unsigned m_renderCounterCount;
265 OutlineRects m_outlineRects;
268 DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderView, isRenderView());
270 class RootLayoutStateScope {
272 explicit RootLayoutStateScope(RenderView& view)
274 , m_rootLayoutState(view.pageLogicalHeight(), view.pageLogicalHeightChanged())
276 ASSERT(!m_view.m_layoutState);
277 m_view.m_layoutState = &m_rootLayoutState;
280 ~RootLayoutStateScope()
282 ASSERT(m_view.m_layoutState == &m_rootLayoutState);
283 m_view.m_layoutState = 0;
287 LayoutState m_rootLayoutState;
290 // Stack-based class to assist with LayoutState push/pop
291 class LayoutStateMaintainer {
292 WTF_MAKE_NONCOPYABLE(LayoutStateMaintainer);
295 explicit LayoutStateMaintainer(RenderBox& root, const LayoutSize& offset, LayoutUnit pageHeight = 0, bool pageHeightChanged = false, ColumnInfo* colInfo = 0)
296 : m_view(*root.view())
297 , m_disabled(root.shouldDisableLayoutState())
300 , m_didCreateLayoutState(false)
302 push(root, offset, pageHeight, pageHeightChanged, colInfo);
305 // ctor to maybe push later
306 explicit LayoutStateMaintainer(RenderBox& root)
307 : m_view(*root.view())
311 , m_didCreateLayoutState(false)
315 ~LayoutStateMaintainer()
319 ASSERT(m_didStart == m_didEnd); // if this fires, it means that someone did a push(), but forgot to pop().
322 void push(RenderBox& root, const LayoutSize& offset, LayoutUnit pageHeight = 0, bool pageHeightChanged = false, ColumnInfo* colInfo = 0)
325 // We push state even if disabled, because we still need to store layoutDelta
326 m_didCreateLayoutState = m_view.pushLayoutState(root, offset, pageHeight, pageHeightChanged, colInfo);
327 if (m_disabled && m_didCreateLayoutState)
328 m_view.disableLayoutState();
332 bool didPush() const { return m_didStart; }
337 ASSERT(m_didStart && !m_didEnd);
338 if (m_didCreateLayoutState) {
339 m_view.popLayoutState();
341 m_view.enableLayoutState();
348 bool m_disabled : 1; // true if the offset and clip part of layoutState is disabled
349 bool m_didStart : 1; // true if we did a push or disable
350 bool m_didEnd : 1; // true if we popped or re-enabled
351 bool m_didCreateLayoutState : 1; // true if we actually made a layout state.
354 class LayoutStateDisabler {
355 WTF_MAKE_NONCOPYABLE(LayoutStateDisabler);
357 LayoutStateDisabler(const RenderBox& root)
358 : m_view(*root.view())
360 m_view.disableLayoutState();
363 ~LayoutStateDisabler()
365 m_view.enableLayoutState();
371 } // namespace WebCore
373 #endif // RenderView_h