b29122779f57c2e38c8485825078b0d5da2d63e1
[WebKit-https.git] / Source / WebCore / rendering / RenderView.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
4  *
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.
9  *
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.
14  *
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.
19  */
20
21 #include "config.h"
22 #include "RenderView.h"
23
24 #include "ColumnInfo.h"
25 #include "Document.h"
26 #include "Element.h"
27 #include "FloatQuad.h"
28 #include "FlowThreadController.h"
29 #include "Frame.h"
30 #include "FrameSelection.h"
31 #include "FrameView.h"
32 #include "GraphicsContext.h"
33 #include "HTMLFrameOwnerElement.h"
34 #include "HTMLIFrameElement.h"
35 #include "HitTestResult.h"
36 #include "Page.h"
37 #include "RenderGeometryMap.h"
38 #include "RenderLayer.h"
39 #include "RenderLayerBacking.h"
40 #include "RenderNamedFlowThread.h"
41 #include "RenderSelectionInfo.h"
42 #include "RenderWidget.h"
43 #include "RenderWidgetProtector.h"
44 #include "StyleInheritedData.h"
45 #include "TransformState.h"
46 #include <wtf/StackStats.h>
47
48 #if USE(ACCELERATED_COMPOSITING)
49 #include "RenderLayerCompositor.h"
50 #endif
51
52 #if ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS)
53 #include "CustomFilterGlobalContext.h"
54 #endif
55
56 namespace WebCore {
57
58 RenderView::RenderView(Document* document)
59     : RenderBlock(document)
60     , m_frameView(document->view())
61     , m_selectionStart(0)
62     , m_selectionEnd(0)
63     , m_selectionStartPos(-1)
64     , m_selectionEndPos(-1)
65     , m_maximalOutlineSize(0)
66     , m_pageLogicalHeight(0)
67     , m_pageLogicalHeightChanged(false)
68     , m_layoutState(0)
69     , m_layoutStateDisableCount(0)
70     , m_renderQuoteHead(0)
71     , m_renderCounterCount(0)
72     , m_selectionWasCaret(false)
73 {
74     // init RenderObject attributes
75     setInline(false);
76     
77     m_minPreferredLogicalWidth = 0;
78     m_maxPreferredLogicalWidth = 0;
79
80     setPreferredLogicalWidthsDirty(true, MarkOnlyThis);
81     
82     setPositionState(AbsolutePosition); // to 0,0 :)
83 }
84
85 RenderView::~RenderView()
86 {
87 }
88
89 bool RenderView::hitTest(const HitTestRequest& request, HitTestResult& result)
90 {
91     return hitTest(request, result.hitTestLocation(), result);
92 }
93
94 bool RenderView::hitTest(const HitTestRequest& request, const HitTestLocation& location, HitTestResult& result)
95 {
96     if (layer()->hitTest(request, location, result))
97         return true;
98
99     // FIXME: Consider if this test should be done unconditionally.
100     if (request.allowsFrameScrollbars() && m_frameView) {
101         // ScrollView scrollbars are not the same as RenderLayer scrollbars tested by RenderLayer::hitTestOverflowControls,
102         // so we need to test ScrollView scrollbars separately here.
103         Scrollbar* frameScrollbar = m_frameView->scrollbarAtPoint(location.roundedPoint());
104         if (frameScrollbar) {
105             result.setScrollbar(frameScrollbar);
106             return true;
107         }
108     }
109
110     return false;
111 }
112
113 void RenderView::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit, LogicalExtentComputedValues& computedValues) const
114 {
115     computedValues.m_extent = (!shouldUsePrintingLayout() && m_frameView) ? LayoutUnit(viewLogicalHeight()) : logicalHeight;
116 }
117
118 void RenderView::updateLogicalWidth()
119 {
120     if (!shouldUsePrintingLayout() && m_frameView)
121         setLogicalWidth(viewLogicalWidth());
122 }
123
124 LayoutUnit RenderView::availableLogicalHeight(AvailableLogicalHeightType heightType) const
125 {
126     // If we have columns, then the available logical height is reduced to the column height.
127     if (hasColumns())
128         return columnInfo()->columnHeight();
129     return RenderBlock::availableLogicalHeight(heightType);
130 }
131
132 bool RenderView::isChildAllowed(RenderObject* child, RenderStyle*) const
133 {
134     return child->isBox();
135 }
136
137 void RenderView::layoutContent(const LayoutState& state)
138 {
139     UNUSED_PARAM(state);
140     ASSERT(needsLayout());
141
142     RenderBlock::layout();
143     if (hasRenderNamedFlowThreads())
144         flowThreadController()->layoutRenderNamedFlowThreads();
145 #ifndef NDEBUG
146     checkLayoutState(state);
147 #endif
148 }
149
150 #ifndef NDEBUG
151 void RenderView::checkLayoutState(const LayoutState& state)
152 {
153     ASSERT(layoutDeltaMatches(LayoutSize()));
154     ASSERT(!m_layoutStateDisableCount);
155     ASSERT(m_layoutState == &state);
156 }
157 #endif
158
159 static RenderBox* enclosingSeamlessRenderer(Document* doc)
160 {
161     if (!doc)
162         return 0;
163     Element* ownerElement = doc->seamlessParentIFrame();
164     if (!ownerElement)
165         return 0;
166     return ownerElement->renderBox();
167 }
168
169 void RenderView::addChild(RenderObject* newChild, RenderObject* beforeChild)
170 {
171     // Seamless iframes are considered part of an enclosing render flow thread from the parent document. This is necessary for them to look
172     // up regions in the parent document during layout.
173     if (newChild && !newChild->isRenderFlowThread()) {
174         RenderBox* seamlessBox = enclosingSeamlessRenderer(document());
175         if (seamlessBox && seamlessBox->flowThreadContainingBlock())
176             newChild->setFlowThreadState(seamlessBox->flowThreadState());
177     }
178     RenderBlock::addChild(newChild, beforeChild);
179 }
180
181 bool RenderView::initializeLayoutState(LayoutState& state)
182 {
183     bool isSeamlessAncestorInFlowThread = false;
184
185     // FIXME: May be better to push a clip and avoid issuing offscreen repaints.
186     state.m_clipped = false;
187     
188     // Check the writing mode of the seamless ancestor. It has to match our document's writing mode, or we won't inherit any
189     // pagination information.
190     RenderBox* seamlessAncestor = enclosingSeamlessRenderer(document());
191     LayoutState* seamlessLayoutState = seamlessAncestor ? seamlessAncestor->view()->layoutState() : 0;
192     bool shouldInheritPagination = seamlessLayoutState && !m_pageLogicalHeight && seamlessAncestor->style()->writingMode() == style()->writingMode();
193     
194     state.m_pageLogicalHeight = shouldInheritPagination ? seamlessLayoutState->m_pageLogicalHeight : m_pageLogicalHeight;
195     state.m_pageLogicalHeightChanged = shouldInheritPagination ? seamlessLayoutState->m_pageLogicalHeightChanged : m_pageLogicalHeightChanged;
196     state.m_isPaginated = state.m_pageLogicalHeight;
197     if (state.m_isPaginated && shouldInheritPagination) {
198         // Set up the correct pagination offset. We can use a negative offset in order to push the top of the RenderView into its correct place
199         // on a page. We can take the iframe's offset from the logical top of the first page and make the negative into the pagination offset within the child
200         // view.
201         bool isFlipped = seamlessAncestor->style()->isFlippedBlocksWritingMode();
202         LayoutSize layoutOffset = seamlessLayoutState->layoutOffset();
203         LayoutSize iFrameOffset(layoutOffset.width() + seamlessAncestor->x() + (!isFlipped ? seamlessAncestor->borderLeft() + seamlessAncestor->paddingLeft() :
204             seamlessAncestor->borderRight() + seamlessAncestor->paddingRight()),
205             layoutOffset.height() + seamlessAncestor->y() + (!isFlipped ? seamlessAncestor->borderTop() + seamlessAncestor->paddingTop() :
206             seamlessAncestor->borderBottom() + seamlessAncestor->paddingBottom()));
207         
208         LayoutSize offsetDelta = seamlessLayoutState->m_pageOffset - iFrameOffset;
209         state.m_pageOffset = offsetDelta;
210         
211         // Set the current render flow thread to point to our ancestor. This will allow the seamless document to locate the correct
212         // regions when doing a layout.
213         if (seamlessAncestor->flowThreadContainingBlock()) {
214             flowThreadController()->setCurrentRenderFlowThread(seamlessAncestor->view()->flowThreadController()->currentRenderFlowThread());
215             isSeamlessAncestorInFlowThread = true;
216         }
217     }
218
219     // FIXME: We need to make line grids and exclusions work with seamless iframes as well here. Basically all layout state information needs
220     // to propagate here and not just pagination information.
221     return isSeamlessAncestorInFlowThread;
222 }
223
224 // The algorithm below assumes this is a full layout. In case there are previously computed values for regions, supplemental steps are taken
225 // to ensure the results are the same as those obtained from a full layout (i.e. the auto-height regions from all the flows are marked as needing
226 // layout).
227 // 1. The flows are laid out from the outer flow to the inner flow. This successfully computes the outer non-auto-height regions size so the 
228 // inner flows have the necessary information to correctly fragment the content.
229 // 2. The flows are laid out from the inner flow to the outer flow. After an inner flow is laid out it goes into the constrained layout phase
230 // and marks the auto-height regions they need layout. This means the outer flows will relayout if they depend on regions with auto-height regions
231 // belonging to inner flows. This step will correctly set the computedAutoHeight for the auto-height regions. It's possible for non-auto-height
232 // regions to relayout if they depend on auto-height regions. This will invalidate the inner flow threads and mark them as needing layout.
233 // 3. The last step is to do one last layout if there are pathological dependencies between non-auto-height regions and auto-height regions
234 // as detected in the previous step.
235 void RenderView::layoutContentInAutoLogicalHeightRegions(const LayoutState& state)
236 {
237     // We need to invalidate all the flows with auto-height regions if one such flow needs layout.
238     // If none is found we do a layout a check back again afterwards.
239     if (!flowThreadController()->updateFlowThreadsNeedingLayout()) {
240         // Do a first layout of the content. In some cases more layouts are not needed (e.g. only flows with non-auto-height regions have changed).
241         layoutContent(state);
242
243         // If we find no named flow needing a two step layout after the first layout, exit early.
244         // Otherwise, initiate the two step layout algorithm and recompute all the flows.
245         if (!flowThreadController()->updateFlowThreadsNeedingTwoStepLayout())
246             return;
247     }
248
249     // Layout to recompute all the named flows with auto-height regions.
250     layoutContent(state);
251
252     // Propagate the computed auto-height values upwards.
253     // Non-auto-height regions may invalidate the flow thread because they depended on auto-height regions, but that's ok.
254     flowThreadController()->updateFlowThreadsIntoConstrainedPhase();
255
256     // Do one last layout that should update the auto-height regions found in the main flow
257     // and solve pathological dependencies between regions (e.g. a non-auto-height region depending
258     // on an auto-height one).
259     if (needsLayout())
260         layoutContent(state);
261 }
262
263 void RenderView::layout()
264 {
265     StackStats::LayoutCheckPoint layoutCheckPoint;
266     if (!document()->paginated())
267         setPageLogicalHeight(0);
268
269     if (shouldUsePrintingLayout())
270         m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = logicalWidth();
271
272     // Use calcWidth/Height to get the new width/height, since this will take the full page zoom factor into account.
273     bool relayoutChildren = !shouldUsePrintingLayout() && (!m_frameView || width() != viewWidth() || height() != viewHeight());
274     if (relayoutChildren) {
275         setChildNeedsLayout(true, MarkOnlyThis);
276         for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
277             if ((child->isBox() && (toRenderBox(child)->hasRelativeLogicalHeight() || toRenderBox(child)->hasViewportPercentageLogicalHeight()))
278                     || child->style()->logicalHeight().isPercent()
279                     || child->style()->logicalMinHeight().isPercent()
280                     || child->style()->logicalMaxHeight().isPercent()
281                     || child->style()->logicalHeight().isViewportPercentage()
282                     || child->style()->logicalMinHeight().isViewportPercentage()
283                     || child->style()->logicalMaxHeight().isViewportPercentage()
284 #if ENABLE(SVG)
285                     || child->isSVGRoot()
286 #endif
287                 )
288                 child->setChildNeedsLayout(true, MarkOnlyThis);
289         }
290     }
291
292     ASSERT(!m_layoutState);
293     if (!needsLayout())
294         return;
295
296     LayoutState state;
297     bool isSeamlessAncestorInFlowThread = initializeLayoutState(state);
298
299     m_pageLogicalHeightChanged = false;
300     m_layoutState = &state;
301
302     if (checkTwoPassLayoutForAutoHeightRegions())
303         layoutContentInAutoLogicalHeightRegions(state);
304     else
305         layoutContent(state);
306
307 #ifndef NDEBUG
308     checkLayoutState(state);
309 #endif
310     m_layoutState = 0;
311     setNeedsLayout(false);
312     
313     if (isSeamlessAncestorInFlowThread)
314         flowThreadController()->setCurrentRenderFlowThread(0);
315 }
316
317 LayoutUnit RenderView::pageOrViewLogicalHeight() const
318 {
319     if (document()->printing())
320         return pageLogicalHeight();
321     
322     if (hasColumns() && !style()->hasInlineColumnAxis()) {
323         if (int pageLength = frameView()->pagination().pageLength)
324             return pageLength;
325     }
326
327     return viewLogicalHeight();
328 }
329
330 void RenderView::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const
331 {
332     // If a container was specified, and was not 0 or the RenderView,
333     // then we should have found it by now.
334     ASSERT_ARG(repaintContainer, !repaintContainer || repaintContainer == this);
335     ASSERT_UNUSED(wasFixed, !wasFixed || *wasFixed == (mode & IsFixed));
336
337     if (!repaintContainer && mode & UseTransforms && shouldUseTransformFromContainer(0)) {
338         TransformationMatrix t;
339         getTransformFromContainer(0, LayoutSize(), t);
340         transformState.applyTransform(t);
341     }
342     
343     if (mode & IsFixed && m_frameView)
344         transformState.move(m_frameView->scrollOffsetForFixedPosition());
345 }
346
347 const RenderObject* RenderView::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
348 {
349     // If a container was specified, and was not 0 or the RenderView,
350     // then we should have found it by now.
351     ASSERT_ARG(ancestorToStopAt, !ancestorToStopAt || ancestorToStopAt == this);
352
353     LayoutSize scrollOffset;
354
355     if (m_frameView)
356         scrollOffset = m_frameView->scrollOffsetForFixedPosition();
357
358     if (!ancestorToStopAt && shouldUseTransformFromContainer(0)) {
359         TransformationMatrix t;
360         getTransformFromContainer(0, LayoutSize(), t);
361         geometryMap.pushView(this, scrollOffset, &t);
362     } else
363         geometryMap.pushView(this, scrollOffset);
364
365     return 0;
366 }
367
368 void RenderView::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const
369 {
370     if (mode & IsFixed && m_frameView)
371         transformState.move(m_frameView->scrollOffsetForFixedPosition());
372
373     if (mode & UseTransforms && shouldUseTransformFromContainer(0)) {
374         TransformationMatrix t;
375         getTransformFromContainer(0, LayoutSize(), t);
376         transformState.applyTransform(t);
377     }
378 }
379
380 bool RenderView::requiresColumns(int desiredColumnCount) const
381 {
382     if (m_frameView)
383         return m_frameView->pagination().mode != Pagination::Unpaginated;
384
385     return RenderBlock::requiresColumns(desiredColumnCount);
386 }
387
388 void RenderView::calcColumnWidth()
389 {
390     int columnWidth = contentLogicalWidth();
391     if (m_frameView && style()->hasInlineColumnAxis()) {
392         if (int pageLength = m_frameView->pagination().pageLength)
393             columnWidth = pageLength;
394     }
395     setDesiredColumnCountAndWidth(1, columnWidth);
396 }
397
398 ColumnInfo::PaginationUnit RenderView::paginationUnit() const
399 {
400     if (m_frameView)
401         return m_frameView->pagination().behavesLikeColumns ? ColumnInfo::Column : ColumnInfo::Page;
402
403     return ColumnInfo::Page;
404 }
405
406 void RenderView::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
407 {
408     // If we ever require layout but receive a paint anyway, something has gone horribly wrong.
409     ASSERT(!needsLayout());
410     // RenderViews should never be called to paint with an offset not on device pixels.
411     ASSERT(LayoutPoint(IntPoint(paintOffset.x(), paintOffset.y())) == paintOffset);
412
413     // This avoids painting garbage between columns if there is a column gap.
414     if (m_frameView && m_frameView->pagination().mode != Pagination::Unpaginated && paintInfo.shouldPaintWithinRoot(this))
415         paintInfo.context->fillRect(paintInfo.rect, m_frameView->baseBackgroundColor(), ColorSpaceDeviceRGB);
416
417     paintObject(paintInfo, paintOffset);
418 }
419
420 static inline bool isComposited(RenderObject* object)
421 {
422     return object->hasLayer() && toRenderLayerModelObject(object)->layer()->isComposited();
423 }
424
425 static inline bool rendererObscuresBackground(RenderObject* rootObject)
426 {
427     if (!rootObject)
428         return false;
429     
430     RenderStyle* style = rootObject->style();
431     if (style->visibility() != VISIBLE
432         || style->opacity() != 1
433         || style->hasTransform())
434         return false;
435     
436     if (isComposited(rootObject))
437         return false;
438
439     const RenderObject* rootRenderer = rootObject->rendererForRootBackground();
440     if (rootRenderer->style()->backgroundClip() == TextFillBox)
441         return false;
442
443     return true;
444 }
445
446 void RenderView::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint&)
447 {
448     if (!paintInfo.shouldPaintWithinRoot(this))
449         return;
450
451     // Check to see if we are enclosed by a layer that requires complex painting rules.  If so, we cannot blit
452     // when scrolling, and we need to use slow repaints.  Examples of layers that require this are transparent layers,
453     // layers with reflections, or transformed layers.
454     // FIXME: This needs to be dynamic.  We should be able to go back to blitting if we ever stop being inside
455     // a transform, transparency layer, etc.
456     Element* elt;
457     for (elt = document()->ownerElement(); view() && elt && elt->renderer(); elt = elt->document()->ownerElement()) {
458         RenderLayer* layer = elt->renderer()->enclosingLayer();
459         if (layer->cannotBlitToWindow()) {
460             frameView()->setCannotBlitToWindow();
461             break;
462         }
463
464 #if USE(ACCELERATED_COMPOSITING)
465         if (RenderLayer* compositingLayer = layer->enclosingCompositingLayerForRepaint()) {
466             if (!compositingLayer->backing()->paintsIntoWindow()) {
467                 frameView()->setCannotBlitToWindow();
468                 break;
469             }
470         }
471 #endif
472     }
473
474     if (document()->ownerElement() || !view())
475         return;
476
477     if (paintInfo.skipRootBackground())
478         return;
479
480     bool rootFillsViewport = false;
481     bool rootObscuresBackground = false;
482     Node* documentElement = document()->documentElement();
483     if (RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0) {
484         // The document element's renderer is currently forced to be a block, but may not always be.
485         RenderBox* rootBox = rootRenderer->isBox() ? toRenderBox(rootRenderer) : 0;
486         rootFillsViewport = rootBox && !rootBox->x() && !rootBox->y() && rootBox->width() >= width() && rootBox->height() >= height();
487         rootObscuresBackground = rendererObscuresBackground(rootRenderer);
488     }
489     
490     Page* page = document()->page();
491     float pageScaleFactor = page ? page->pageScaleFactor() : 1;
492
493     // If painting will entirely fill the view, no need to fill the background.
494     if (rootFillsViewport && rootObscuresBackground && pageScaleFactor >= 1)
495         return;
496
497     // This code typically only executes if the root element's visibility has been set to hidden,
498     // if there is a transform on the <html>, or if there is a page scale factor less than 1.
499     // Only fill with the base background color (typically white) if we're the root document, 
500     // since iframes/frames with no background in the child document should show the parent's background.
501     if (frameView()->isTransparent()) // FIXME: This needs to be dynamic.  We should be able to go back to blitting if we ever stop being transparent.
502         frameView()->setCannotBlitToWindow(); // The parent must show behind the child.
503     else {
504         Color baseColor = frameView()->baseBackgroundColor();
505         if (baseColor.alpha()) {
506             CompositeOperator previousOperator = paintInfo.context->compositeOperation();
507             paintInfo.context->setCompositeOperation(CompositeCopy);
508             paintInfo.context->fillRect(paintInfo.rect, baseColor, style()->colorSpace());
509             paintInfo.context->setCompositeOperation(previousOperator);
510         } else
511             paintInfo.context->clearRect(paintInfo.rect);
512     }
513 }
514
515 bool RenderView::shouldRepaint(const LayoutRect& r) const
516 {
517     if (printing() || r.width() == 0 || r.height() == 0)
518         return false;
519
520     if (!m_frameView)
521         return false;
522
523     if (m_frameView->repaintsDisabled())
524         return false;
525
526     return true;
527 }
528
529 void RenderView::repaintRootContents()
530 {
531 #if USE(ACCELERATED_COMPOSITING)
532     if (layer()->isComposited()) {
533         layer()->setBackingNeedsRepaint();
534         return;
535     }
536 #endif
537     repaint();
538 }
539
540 void RenderView::repaintViewRectangle(const LayoutRect& ur, bool immediate) const
541 {
542     if (!shouldRepaint(ur))
543         return;
544
545     // We always just invalidate the root view, since we could be an iframe that is clipped out
546     // or even invisible.
547     Element* elt = document()->ownerElement();
548     if (!elt)
549         m_frameView->repaintContentRectangle(pixelSnappedIntRect(ur), immediate);
550     else if (RenderBox* obj = elt->renderBox()) {
551         LayoutRect vr = viewRect();
552         LayoutRect r = intersection(ur, vr);
553         
554         // Subtract out the contentsX and contentsY offsets to get our coords within the viewing
555         // rectangle.
556         r.moveBy(-vr.location());
557
558         // FIXME: Hardcoded offsets here are not good.
559         r.moveBy(obj->contentBoxRect().location());
560         obj->repaintRectangle(r, immediate);
561     }
562 }
563
564 void RenderView::repaintRectangleInViewAndCompositedLayers(const LayoutRect& ur, bool immediate)
565 {
566     if (!shouldRepaint(ur))
567         return;
568
569     repaintViewRectangle(ur, immediate);
570     
571 #if USE(ACCELERATED_COMPOSITING)
572     if (compositor()->inCompositingMode()) {
573         IntRect repaintRect = pixelSnappedIntRect(ur);
574         compositor()->repaintCompositedLayers(&repaintRect);
575     }
576 #endif
577 }
578
579 void RenderView::repaintViewAndCompositedLayers()
580 {
581     repaintRootContents();
582 #if USE(ACCELERATED_COMPOSITING)
583     if (compositor()->inCompositingMode())
584         compositor()->repaintCompositedLayers();
585 #endif
586 }
587
588 LayoutRect RenderView::visualOverflowRect() const
589 {
590     if (m_frameView->paintsEntireContents())
591         return layoutOverflowRect();
592
593     return RenderBlock::visualOverflowRect();
594 }
595
596 void RenderView::computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect& rect, bool fixed) const
597 {
598     // If a container was specified, and was not 0 or the RenderView,
599     // then we should have found it by now.
600     ASSERT_ARG(repaintContainer, !repaintContainer || repaintContainer == this);
601
602     if (printing())
603         return;
604
605     if (style()->isFlippedBlocksWritingMode()) {
606         // We have to flip by hand since the view's logical height has not been determined.  We
607         // can use the viewport width and height.
608         if (style()->isHorizontalWritingMode())
609             rect.setY(viewHeight() - rect.maxY());
610         else
611             rect.setX(viewWidth() - rect.maxX());
612     }
613
614     if (fixed && m_frameView)
615         rect.move(m_frameView->scrollOffsetForFixedPosition());
616         
617     // Apply our transform if we have one (because of full page zooming).
618     if (!repaintContainer && layer() && layer()->transform())
619         rect = layer()->transform()->mapRect(rect);
620 }
621
622 void RenderView::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
623 {
624     rects.append(pixelSnappedIntRect(accumulatedOffset, layer()->size()));
625 }
626
627 void RenderView::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
628 {
629     if (wasFixed)
630         *wasFixed = false;
631     quads.append(FloatRect(FloatPoint(), layer()->size()));
632 }
633
634 static RenderObject* rendererAfterPosition(RenderObject* object, unsigned offset)
635 {
636     if (!object)
637         return 0;
638
639     RenderObject* child = object->childAt(offset);
640     return child ? child : object->nextInPreOrderAfterChildren();
641 }
642
643 IntRect RenderView::selectionBounds(bool clipToVisibleContent) const
644 {
645     document()->updateStyleIfNeeded();
646
647     typedef HashMap<RenderObject*, OwnPtr<RenderSelectionInfo> > SelectionMap;
648     SelectionMap selectedObjects;
649
650     RenderObject* os = m_selectionStart;
651     RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
652     while (os && os != stop) {
653         if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
654             // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
655             selectedObjects.set(os, adoptPtr(new RenderSelectionInfo(os, clipToVisibleContent)));
656             RenderBlock* cb = os->containingBlock();
657             while (cb && !cb->isRenderView()) {
658                 OwnPtr<RenderSelectionInfo>& blockInfo = selectedObjects.add(cb, nullptr).iterator->value;
659                 if (blockInfo)
660                     break;
661                 blockInfo = adoptPtr(new RenderSelectionInfo(cb, clipToVisibleContent));
662                 cb = cb->containingBlock();
663             }
664         }
665
666         os = os->nextInPreOrder();
667     }
668
669     // Now create a single bounding box rect that encloses the whole selection.
670     LayoutRect selRect;
671     SelectionMap::iterator end = selectedObjects.end();
672     for (SelectionMap::iterator i = selectedObjects.begin(); i != end; ++i) {
673         RenderSelectionInfo* info = i->value.get();
674         // RenderSelectionInfo::rect() is in the coordinates of the repaintContainer, so map to page coordinates.
675         LayoutRect currRect = info->rect();
676         if (RenderLayerModelObject* repaintContainer = info->repaintContainer()) {
677             FloatQuad absQuad = repaintContainer->localToAbsoluteQuad(FloatRect(currRect));
678             currRect = absQuad.enclosingBoundingBox(); 
679         }
680         selRect.unite(currRect);
681     }
682     return pixelSnappedIntRect(selRect);
683 }
684
685 void RenderView::repaintSelection() const
686 {
687     document()->updateStyleIfNeeded();
688
689     HashSet<RenderBlock*> processedBlocks;
690
691     RenderObject* end = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
692     for (RenderObject* o = m_selectionStart; o && o != end; o = o->nextInPreOrder()) {
693         if (!o->canBeSelectionLeaf() && o != m_selectionStart && o != m_selectionEnd)
694             continue;
695         if (o->selectionState() == SelectionNone)
696             continue;
697
698         RenderSelectionInfo(o, true).repaint();
699
700         // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
701         for (RenderBlock* block = o->containingBlock(); block && !block->isRenderView(); block = block->containingBlock()) {
702             if (!processedBlocks.add(block).isNewEntry)
703                 break;
704             RenderSelectionInfo(block, true).repaint();
705         }
706     }
707 }
708
709 #if USE(ACCELERATED_COMPOSITING)
710 // Compositing layer dimensions take outline size into account, so we have to recompute layer
711 // bounds when it changes.
712 // FIXME: This is ugly; it would be nice to have a better way to do this.
713 void RenderView::setMaximalOutlineSize(int o)
714 {
715     if (o != m_maximalOutlineSize) {
716         m_maximalOutlineSize = o;
717
718         // maximalOutlineSize affects compositing layer dimensions.
719         compositor()->setCompositingLayersNeedRebuild();    // FIXME: this really just needs to be a geometry update.
720     }
721 }
722 #endif
723
724 void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode)
725 {
726     // Make sure both our start and end objects are defined.
727     // Check www.msnbc.com and try clicking around to find the case where this happened.
728     if ((start && !end) || (end && !start))
729         return;
730
731     bool caretChanged = m_selectionWasCaret != view()->frame()->selection()->isCaret();
732     m_selectionWasCaret = view()->frame()->selection()->isCaret();
733     // Just return if the selection hasn't changed.
734     if (m_selectionStart == start && m_selectionStartPos == startPos &&
735         m_selectionEnd == end && m_selectionEndPos == endPos && !caretChanged)
736         return;
737
738     if ((start && end) && (start->flowThreadContainingBlock() != end->flowThreadContainingBlock()))
739         return;
740
741     // Record the old selected objects.  These will be used later
742     // when we compare against the new selected objects.
743     int oldStartPos = m_selectionStartPos;
744     int oldEndPos = m_selectionEndPos;
745
746     // Objects each have a single selection rect to examine.
747     typedef HashMap<RenderObject*, OwnPtr<RenderSelectionInfo> > SelectedObjectMap;
748     SelectedObjectMap oldSelectedObjects;
749     SelectedObjectMap newSelectedObjects;
750
751     // Blocks contain selected objects and fill gaps between them, either on the left, right, or in between lines and blocks.
752     // In order to get the repaint rect right, we have to examine left, middle, and right rects individually, since otherwise
753     // the union of those rects might remain the same even when changes have occurred.
754     typedef HashMap<RenderBlock*, OwnPtr<RenderBlockSelectionInfo> > SelectedBlockMap;
755     SelectedBlockMap oldSelectedBlocks;
756     SelectedBlockMap newSelectedBlocks;
757
758     RenderObject* os = m_selectionStart;
759     RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
760     while (os && os != stop) {
761         if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
762             // Blocks are responsible for painting line gaps and margin gaps.  They must be examined as well.
763             oldSelectedObjects.set(os, adoptPtr(new RenderSelectionInfo(os, true)));
764             if (blockRepaintMode == RepaintNewXOROld) {
765                 RenderBlock* cb = os->containingBlock();
766                 while (cb && !cb->isRenderView()) {
767                     OwnPtr<RenderBlockSelectionInfo>& blockInfo = oldSelectedBlocks.add(cb, nullptr).iterator->value;
768                     if (blockInfo)
769                         break;
770                     blockInfo = adoptPtr(new RenderBlockSelectionInfo(cb));
771                     cb = cb->containingBlock();
772                 }
773             }
774         }
775
776         os = os->nextInPreOrder();
777     }
778
779     // Now clear the selection.
780     SelectedObjectMap::iterator oldObjectsEnd = oldSelectedObjects.end();
781     for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i)
782         i->key->setSelectionStateIfNeeded(SelectionNone);
783
784     // set selection start and end
785     m_selectionStart = start;
786     m_selectionStartPos = startPos;
787     m_selectionEnd = end;
788     m_selectionEndPos = endPos;
789
790     // Update the selection status of all objects between m_selectionStart and m_selectionEnd
791     if (start && start == end)
792         start->setSelectionStateIfNeeded(SelectionBoth);
793     else {
794         if (start)
795             start->setSelectionStateIfNeeded(SelectionStart);
796         if (end)
797             end->setSelectionStateIfNeeded(SelectionEnd);
798     }
799
800     RenderObject* o = start;
801     stop = rendererAfterPosition(end, endPos);
802
803     while (o && o != stop) {
804         if (o != start && o != end && o->canBeSelectionLeaf())
805             o->setSelectionStateIfNeeded(SelectionInside);
806         o = o->nextInPreOrder();
807     }
808
809     if (blockRepaintMode != RepaintNothing)
810         layer()->clearBlockSelectionGapsBounds();
811
812     // Now that the selection state has been updated for the new objects, walk them again and
813     // put them in the new objects list.
814     o = start;
815     while (o && o != stop) {
816         if ((o->canBeSelectionLeaf() || o == start || o == end) && o->selectionState() != SelectionNone) {
817             newSelectedObjects.set(o, adoptPtr(new RenderSelectionInfo(o, true)));
818             RenderBlock* cb = o->containingBlock();
819             while (cb && !cb->isRenderView()) {
820                 OwnPtr<RenderBlockSelectionInfo>& blockInfo = newSelectedBlocks.add(cb, nullptr).iterator->value;
821                 if (blockInfo)
822                     break;
823                 blockInfo = adoptPtr(new RenderBlockSelectionInfo(cb));
824                 cb = cb->containingBlock();
825             }
826         }
827
828         o = o->nextInPreOrder();
829     }
830
831     if (!m_frameView || blockRepaintMode == RepaintNothing)
832         return;
833
834     m_frameView->beginDeferredRepaints();
835
836     // Have any of the old selected objects changed compared to the new selection?
837     for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i) {
838         RenderObject* obj = i->key;
839         RenderSelectionInfo* newInfo = newSelectedObjects.get(obj);
840         RenderSelectionInfo* oldInfo = i->value.get();
841         if (!newInfo || oldInfo->rect() != newInfo->rect() || oldInfo->state() != newInfo->state() ||
842             (m_selectionStart == obj && oldStartPos != m_selectionStartPos) ||
843             (m_selectionEnd == obj && oldEndPos != m_selectionEndPos)) {
844             oldInfo->repaint();
845             if (newInfo) {
846                 newInfo->repaint();
847                 newSelectedObjects.remove(obj);
848             }
849         }
850     }
851
852     // Any new objects that remain were not found in the old objects dict, and so they need to be updated.
853     SelectedObjectMap::iterator newObjectsEnd = newSelectedObjects.end();
854     for (SelectedObjectMap::iterator i = newSelectedObjects.begin(); i != newObjectsEnd; ++i)
855         i->value->repaint();
856
857     // Have any of the old blocks changed?
858     SelectedBlockMap::iterator oldBlocksEnd = oldSelectedBlocks.end();
859     for (SelectedBlockMap::iterator i = oldSelectedBlocks.begin(); i != oldBlocksEnd; ++i) {
860         RenderBlock* block = i->key;
861         RenderBlockSelectionInfo* newInfo = newSelectedBlocks.get(block);
862         RenderBlockSelectionInfo* oldInfo = i->value.get();
863         if (!newInfo || oldInfo->rects() != newInfo->rects() || oldInfo->state() != newInfo->state()) {
864             oldInfo->repaint();
865             if (newInfo) {
866                 newInfo->repaint();
867                 newSelectedBlocks.remove(block);
868             }
869         }
870     }
871
872     // Any new blocks that remain were not found in the old blocks dict, and so they need to be updated.
873     SelectedBlockMap::iterator newBlocksEnd = newSelectedBlocks.end();
874     for (SelectedBlockMap::iterator i = newSelectedBlocks.begin(); i != newBlocksEnd; ++i)
875         i->value->repaint();
876
877     m_frameView->endDeferredRepaints();
878 }
879
880 void RenderView::getSelection(RenderObject*& startRenderer, int& startOffset, RenderObject*& endRenderer, int& endOffset) const
881 {
882     startRenderer = m_selectionStart;
883     startOffset = m_selectionStartPos;
884     endRenderer = m_selectionEnd;
885     endOffset = m_selectionEndPos;
886 }
887
888 void RenderView::clearSelection()
889 {
890     layer()->repaintBlockSelectionGaps();
891     setSelection(0, -1, 0, -1, RepaintNewMinusOld);
892 }
893
894 void RenderView::selectionStartEnd(int& startPos, int& endPos) const
895 {
896     startPos = m_selectionStartPos;
897     endPos = m_selectionEndPos;
898 }
899
900 bool RenderView::printing() const
901 {
902     return document()->printing();
903 }
904
905 bool RenderView::shouldUsePrintingLayout() const
906 {
907     if (!printing() || !m_frameView)
908         return false;
909     Frame* frame = m_frameView->frame();
910     return frame && frame->shouldUsePrintingLayout();
911 }
912
913 size_t RenderView::getRetainedWidgets(Vector<RenderWidget*>& renderWidgets)
914 {
915     size_t size = m_widgets.size();
916
917     renderWidgets.reserveCapacity(size);
918
919     RenderWidgetSet::const_iterator end = m_widgets.end();
920     for (RenderWidgetSet::const_iterator it = m_widgets.begin(); it != end; ++it) {
921         renderWidgets.uncheckedAppend(*it);
922         (*it)->ref();
923     }
924     
925     return size;
926 }
927
928 void RenderView::releaseWidgets(Vector<RenderWidget*>& renderWidgets)
929 {
930     size_t size = renderWidgets.size();
931
932     for (size_t i = 0; i < size; ++i)
933         renderWidgets[i]->deref(renderArena());
934 }
935
936 void RenderView::updateWidgetPositions()
937 {
938     // updateWidgetPosition() can possibly cause layout to be re-entered (via plug-ins running
939     // scripts in response to NPP_SetWindow, for example), so we need to keep the Widgets
940     // alive during enumeration.    
941
942     Vector<RenderWidget*> renderWidgets;
943     size_t size = getRetainedWidgets(renderWidgets);
944     
945     for (size_t i = 0; i < size; ++i)
946         renderWidgets[i]->updateWidgetPosition();
947
948     for (size_t i = 0; i < size; ++i)
949         renderWidgets[i]->widgetPositionsUpdated();
950
951     releaseWidgets(renderWidgets);
952 }
953
954 void RenderView::addWidget(RenderWidget* o)
955 {
956     m_widgets.add(o);
957 }
958
959 void RenderView::removeWidget(RenderWidget* o)
960 {
961     m_widgets.remove(o);
962 }
963
964 void RenderView::notifyWidgets(WidgetNotification notification)
965 {
966     Vector<RenderWidget*> renderWidgets;
967     size_t size = getRetainedWidgets(renderWidgets);
968
969     for (size_t i = 0; i < size; ++i)
970         renderWidgets[i]->notifyWidget(notification);
971
972     releaseWidgets(renderWidgets);
973 }
974
975 LayoutRect RenderView::viewRect() const
976 {
977     if (shouldUsePrintingLayout())
978         return LayoutRect(LayoutPoint(), size());
979     if (m_frameView)
980         return m_frameView->visibleContentRect();
981     return LayoutRect();
982 }
983
984
985 IntRect RenderView::unscaledDocumentRect() const
986 {
987     LayoutRect overflowRect(layoutOverflowRect());
988     flipForWritingMode(overflowRect);
989     return pixelSnappedIntRect(overflowRect);
990 }
991
992 bool RenderView::rootBackgroundIsEntirelyFixed() const
993 {
994     RenderObject* rootObject = document()->documentElement() ? document()->documentElement()->renderer() : 0;
995     if (!rootObject)
996         return false;
997
998     RenderObject* rootRenderer = rootObject->rendererForRootBackground();
999     return rootRenderer->hasEntirelyFixedBackground();
1000 }
1001
1002 LayoutRect RenderView::backgroundRect(RenderBox* backgroundRenderer) const
1003 {
1004     if (!hasColumns())
1005         return unscaledDocumentRect();
1006
1007     ColumnInfo* columnInfo = this->columnInfo();
1008     LayoutRect backgroundRect(0, 0, columnInfo->desiredColumnWidth(), columnInfo->columnHeight() * columnInfo->columnCount());
1009     if (!isHorizontalWritingMode())
1010         backgroundRect = backgroundRect.transposedRect();
1011     backgroundRenderer->flipForWritingMode(backgroundRect);
1012
1013     return backgroundRect;
1014 }
1015
1016 IntRect RenderView::documentRect() const
1017 {
1018     FloatRect overflowRect(unscaledDocumentRect());
1019     if (hasTransform())
1020         overflowRect = layer()->currentTransform().mapRect(overflowRect);
1021     return IntRect(overflowRect);
1022 }
1023
1024 int RenderView::viewHeight() const
1025 {
1026     int height = 0;
1027     if (!shouldUsePrintingLayout() && m_frameView) {
1028         height = m_frameView->layoutHeight();
1029         height = m_frameView->useFixedLayout() ? ceilf(style()->effectiveZoom() * float(height)) : height;
1030     }
1031     return height;
1032 }
1033
1034 int RenderView::viewWidth() const
1035 {
1036     int width = 0;
1037     if (!shouldUsePrintingLayout() && m_frameView) {
1038         width = m_frameView->layoutWidth();
1039         width = m_frameView->useFixedLayout() ? ceilf(style()->effectiveZoom() * float(width)) : width;
1040     }
1041     return width;
1042 }
1043
1044 int RenderView::viewLogicalHeight() const
1045 {
1046     int height = style()->isHorizontalWritingMode() ? viewHeight() : viewWidth();
1047     return height;
1048 }
1049
1050 float RenderView::zoomFactor() const
1051 {
1052     Frame* frame = m_frameView->frame();
1053     return frame ? frame->pageZoomFactor() : 1;
1054 }
1055
1056 void RenderView::pushLayoutState(RenderObject* root)
1057 {
1058     ASSERT(m_layoutStateDisableCount == 0);
1059     ASSERT(m_layoutState == 0);
1060
1061     pushLayoutStateForCurrentFlowThread(root);
1062     m_layoutState = new (renderArena()) LayoutState(root);
1063 }
1064
1065 bool RenderView::shouldDisableLayoutStateForSubtree(RenderObject* renderer) const
1066 {
1067     RenderObject* o = renderer;
1068     while (o) {
1069         if (o->hasColumns() || o->hasTransform() || o->hasReflection())
1070             return true;
1071         o = o->container();
1072     }
1073     return false;
1074 }
1075
1076 void RenderView::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
1077 {
1078     if (result.innerNode())
1079         return;
1080
1081     Node* node = document()->documentElement();
1082     if (node) {
1083         result.setInnerNode(node);
1084         if (!result.innerNonSharedNode())
1085             result.setInnerNonSharedNode(node);
1086
1087         LayoutPoint adjustedPoint = point;
1088         offsetForContents(adjustedPoint);
1089
1090         result.setLocalPoint(adjustedPoint);
1091     }
1092 }
1093
1094 // FIXME: This function is obsolete and only used by embedded WebViews inside AppKit NSViews.
1095 // Do not add callers of this function!
1096 // The idea here is to take into account what object is moving the pagination point, and
1097 // thus choose the best place to chop it.
1098 void RenderView::setBestTruncatedAt(int y, RenderBoxModelObject* forRenderer, bool forcedBreak)
1099 {
1100     // Nobody else can set a page break once we have a forced break.
1101     if (m_legacyPrinting.m_forcedPageBreak)
1102         return;
1103
1104     // Forced breaks always win over unforced breaks.
1105     if (forcedBreak) {
1106         m_legacyPrinting.m_forcedPageBreak = true;
1107         m_legacyPrinting.m_bestTruncatedAt = y;
1108         return;
1109     }
1110
1111     // Prefer the widest object that tries to move the pagination point
1112     IntRect boundingBox = forRenderer->borderBoundingBox();
1113     if (boundingBox.width() > m_legacyPrinting.m_truncatorWidth) {
1114         m_legacyPrinting.m_truncatorWidth = boundingBox.width();
1115         m_legacyPrinting.m_bestTruncatedAt = y;
1116     }
1117 }
1118
1119 #if USE(ACCELERATED_COMPOSITING)
1120 bool RenderView::usesCompositing() const
1121 {
1122     return m_compositor && m_compositor->inCompositingMode();
1123 }
1124
1125 RenderLayerCompositor* RenderView::compositor()
1126 {
1127     if (!m_compositor)
1128         m_compositor = adoptPtr(new RenderLayerCompositor(this));
1129
1130     return m_compositor.get();
1131 }
1132 #endif
1133
1134 void RenderView::setIsInWindow(bool isInWindow)
1135 {
1136 #if USE(ACCELERATED_COMPOSITING)
1137     if (m_compositor)
1138         m_compositor->setIsInWindow(isInWindow);
1139 #endif
1140 }
1141
1142 #if ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS)
1143 CustomFilterGlobalContext* RenderView::customFilterGlobalContext()
1144 {
1145     if (!m_customFilterGlobalContext)
1146         m_customFilterGlobalContext = adoptPtr(new CustomFilterGlobalContext());
1147     return m_customFilterGlobalContext.get();
1148 }
1149 #endif
1150
1151 void RenderView::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
1152 {
1153     RenderBlock::styleDidChange(diff, oldStyle);
1154     if (hasRenderNamedFlowThreads())
1155         flowThreadController()->styleDidChange();
1156 }
1157
1158 bool RenderView::hasRenderNamedFlowThreads() const
1159 {
1160     return m_flowThreadController && m_flowThreadController->hasRenderNamedFlowThreads();
1161 }
1162
1163 bool RenderView::checkTwoPassLayoutForAutoHeightRegions() const
1164 {
1165     return hasRenderNamedFlowThreads() && m_flowThreadController->hasFlowThreadsWithAutoLogicalHeightRegions();
1166 }
1167
1168 FlowThreadController* RenderView::flowThreadController()
1169 {
1170     if (!m_flowThreadController)
1171         m_flowThreadController = FlowThreadController::create(this);
1172
1173     return m_flowThreadController.get();
1174 }
1175
1176 void RenderView::pushLayoutStateForCurrentFlowThread(const RenderObject* object)
1177 {
1178     if (!m_flowThreadController)
1179         return;
1180
1181     RenderFlowThread* currentFlowThread = m_flowThreadController->currentRenderFlowThread();
1182     if (!currentFlowThread)
1183         return;
1184
1185     currentFlowThread->pushFlowThreadLayoutState(object);
1186 }
1187
1188 void RenderView::popLayoutStateForCurrentFlowThread()
1189 {
1190     if (!m_flowThreadController)
1191         return;
1192
1193     RenderFlowThread* currentFlowThread = m_flowThreadController->currentRenderFlowThread();
1194     if (!currentFlowThread)
1195         return;
1196
1197     currentFlowThread->popFlowThreadLayoutState();
1198 }
1199
1200 RenderBlock::IntervalArena* RenderView::intervalArena()
1201 {
1202     if (!m_intervalArena)
1203         m_intervalArena = IntervalArena::create();
1204     return m_intervalArena.get();
1205 }
1206
1207 FragmentationDisabler::FragmentationDisabler(RenderObject* root)
1208 {
1209     RenderView* renderView = root->view();
1210     ASSERT(renderView);
1211
1212     LayoutState* layoutState = renderView->layoutState();
1213
1214     m_root = root;
1215     m_fragmenting = layoutState && layoutState->isPaginated();
1216     m_flowThreadState = m_root->flowThreadState();
1217 #ifndef NDEBUG
1218     m_layoutState = layoutState;
1219 #endif
1220
1221     if (layoutState)
1222         layoutState->m_isPaginated = false;
1223         
1224     if (m_flowThreadState != RenderObject::NotInsideFlowThread)
1225         m_root->setFlowThreadStateIncludingDescendants(RenderObject::NotInsideFlowThread);
1226 }
1227
1228 FragmentationDisabler::~FragmentationDisabler()
1229 {
1230     RenderView* renderView = m_root->view();
1231     ASSERT(renderView);
1232
1233     LayoutState* layoutState = renderView->layoutState();
1234 #ifndef NDEBUG
1235     ASSERT(m_layoutState == layoutState);
1236 #endif
1237
1238     if (layoutState)
1239         layoutState->m_isPaginated = m_fragmenting;
1240         
1241     if (m_flowThreadState != RenderObject::NotInsideFlowThread)
1242         m_root->setFlowThreadStateIncludingDescendants(m_flowThreadState);
1243 }
1244
1245 } // namespace WebCore