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
56namespace WebCore {
57
58RenderView::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
85RenderView::~RenderView()
86{
87}
88
89bool RenderView::hitTest(const HitTestRequest& request, HitTestResult& result)
90{
91    return hitTest(request, result.hitTestLocation(), result);
92}
93
94bool 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
113void RenderView::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit, LogicalExtentComputedValues& computedValues) const
114{
115    computedValues.m_extent = (!shouldUsePrintingLayout() && m_frameView) ? LayoutUnit(viewLogicalHeight()) : logicalHeight;
116}
117
118void RenderView::updateLogicalWidth()
119{
120    if (!shouldUsePrintingLayout() && m_frameView)
121        setLogicalWidth(viewLogicalWidth());
122}
123
124LayoutUnit 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
132bool RenderView::isChildAllowed(RenderObject* child, RenderStyle*) const
133{
134    return child->isBox();
135}
136
137void 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
151void RenderView::checkLayoutState(const LayoutState& state)
152{
153    ASSERT(layoutDeltaMatches(LayoutSize()));
154    ASSERT(!m_layoutStateDisableCount);
155    ASSERT(m_layoutState == &state);
156}
157#endif
158
159static 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
169void 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
181bool 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 compute the overrideLogicalHeights 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.
235void 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
263void 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                child->setChildNeedsLayout(true, MarkOnlyThis);
285        }
286    }
287
288    ASSERT(!m_layoutState);
289    if (!needsLayout())
290        return;
291
292    LayoutState state;
293    bool isSeamlessAncestorInFlowThread = initializeLayoutState(state);
294
295    m_pageLogicalHeightChanged = false;
296    m_layoutState = &state;
297
298    if (checkTwoPassLayoutForAutoHeightRegions())
299        layoutContentInAutoLogicalHeightRegions(state);
300    else
301        layoutContent(state);
302
303#ifndef NDEBUG
304    checkLayoutState(state);
305#endif
306    m_layoutState = 0;
307    setNeedsLayout(false);
308
309    if (isSeamlessAncestorInFlowThread)
310        flowThreadController()->setCurrentRenderFlowThread(0);
311}
312
313LayoutUnit RenderView::pageOrViewLogicalHeight() const
314{
315    if (document()->printing())
316        return pageLogicalHeight();
317
318    if (hasColumns() && !style()->hasInlineColumnAxis()) {
319        if (int pageLength = frameView()->pagination().pageLength)
320            return pageLength;
321    }
322
323    return viewLogicalHeight();
324}
325
326void RenderView::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const
327{
328    // If a container was specified, and was not 0 or the RenderView,
329    // then we should have found it by now.
330    ASSERT_ARG(repaintContainer, !repaintContainer || repaintContainer == this);
331    ASSERT_UNUSED(wasFixed, !wasFixed || *wasFixed == (mode & IsFixed));
332
333    if (!repaintContainer && mode & UseTransforms && shouldUseTransformFromContainer(0)) {
334        TransformationMatrix t;
335        getTransformFromContainer(0, LayoutSize(), t);
336        transformState.applyTransform(t);
337    }
338
339    if (mode & IsFixed && m_frameView)
340        transformState.move(m_frameView->scrollOffsetForFixedPosition());
341}
342
343const RenderObject* RenderView::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
344{
345    // If a container was specified, and was not 0 or the RenderView,
346    // then we should have found it by now.
347    ASSERT_ARG(ancestorToStopAt, !ancestorToStopAt || ancestorToStopAt == this);
348
349    LayoutSize scrollOffset;
350
351    if (m_frameView)
352        scrollOffset = m_frameView->scrollOffsetForFixedPosition();
353
354    if (!ancestorToStopAt && shouldUseTransformFromContainer(0)) {
355        TransformationMatrix t;
356        getTransformFromContainer(0, LayoutSize(), t);
357        geometryMap.pushView(this, scrollOffset, &t);
358    } else
359        geometryMap.pushView(this, scrollOffset);
360
361    return 0;
362}
363
364void RenderView::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const
365{
366    if (mode & IsFixed && m_frameView)
367        transformState.move(m_frameView->scrollOffsetForFixedPosition());
368
369    if (mode & UseTransforms && shouldUseTransformFromContainer(0)) {
370        TransformationMatrix t;
371        getTransformFromContainer(0, LayoutSize(), t);
372        transformState.applyTransform(t);
373    }
374}
375
376bool RenderView::requiresColumns(int desiredColumnCount) const
377{
378    if (m_frameView)
379        return m_frameView->pagination().mode != Pagination::Unpaginated;
380
381    return RenderBlock::requiresColumns(desiredColumnCount);
382}
383
384void RenderView::calcColumnWidth()
385{
386    int columnWidth = contentLogicalWidth();
387    if (m_frameView && style()->hasInlineColumnAxis()) {
388        if (int pageLength = m_frameView->pagination().pageLength)
389            columnWidth = pageLength;
390    }
391    setDesiredColumnCountAndWidth(1, columnWidth);
392}
393
394ColumnInfo::PaginationUnit RenderView::paginationUnit() const
395{
396    if (m_frameView)
397        return m_frameView->pagination().behavesLikeColumns ? ColumnInfo::Column : ColumnInfo::Page;
398
399    return ColumnInfo::Page;
400}
401
402void RenderView::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
403{
404    // If we ever require layout but receive a paint anyway, something has gone horribly wrong.
405    ASSERT(!needsLayout());
406    // RenderViews should never be called to paint with an offset not on device pixels.
407    ASSERT(LayoutPoint(IntPoint(paintOffset.x(), paintOffset.y())) == paintOffset);
408
409    // This avoids painting garbage between columns if there is a column gap.
410    if (m_frameView && m_frameView->pagination().mode != Pagination::Unpaginated)
411        paintInfo.context->fillRect(paintInfo.rect, m_frameView->baseBackgroundColor(), ColorSpaceDeviceRGB);
412
413    paintObject(paintInfo, paintOffset);
414}
415
416static inline bool isComposited(RenderObject* object)
417{
418    return object->hasLayer() && toRenderLayerModelObject(object)->layer()->isComposited();
419}
420
421static inline bool rendererObscuresBackground(RenderObject* rootObject)
422{
423    if (!rootObject)
424        return false;
425
426    RenderStyle* style = rootObject->style();
427    if (style->visibility() != VISIBLE
428        || style->opacity() != 1
429        || style->hasTransform())
430        return false;
431
432    if (isComposited(rootObject))
433        return false;
434
435    const RenderObject* rootRenderer = rootObject->rendererForRootBackground();
436    if (rootRenderer->style()->backgroundClip() == TextFillBox)
437        return false;
438
439    return true;
440}
441
442void RenderView::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint&)
443{
444    if (!paintInfo.shouldPaintWithinRoot(this))
445        return;
446
447    // Check to see if we are enclosed by a layer that requires complex painting rules.  If so, we cannot blit
448    // when scrolling, and we need to use slow repaints.  Examples of layers that require this are transparent layers,
449    // layers with reflections, or transformed layers.
450    // FIXME: This needs to be dynamic.  We should be able to go back to blitting if we ever stop being inside
451    // a transform, transparency layer, etc.
452    Element* elt;
453    for (elt = document()->ownerElement(); view() && elt && elt->renderer(); elt = elt->document()->ownerElement()) {
454        RenderLayer* layer = elt->renderer()->enclosingLayer();
455        if (layer->cannotBlitToWindow()) {
456            frameView()->setCannotBlitToWindow();
457            break;
458        }
459
460#if USE(ACCELERATED_COMPOSITING)
461        if (RenderLayer* compositingLayer = layer->enclosingCompositingLayerForRepaint()) {
462            if (!compositingLayer->backing()->paintsIntoWindow()) {
463                frameView()->setCannotBlitToWindow();
464                break;
465            }
466        }
467#endif
468    }
469
470    if (document()->ownerElement() || !view())
471        return;
472
473    if (paintInfo.skipRootBackground())
474        return;
475
476    bool rootFillsViewport = false;
477    bool rootObscuresBackground = false;
478    Node* documentElement = document()->documentElement();
479    if (RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0) {
480        // The document element's renderer is currently forced to be a block, but may not always be.
481        RenderBox* rootBox = rootRenderer->isBox() ? toRenderBox(rootRenderer) : 0;
482        rootFillsViewport = rootBox && !rootBox->x() && !rootBox->y() && rootBox->width() >= width() && rootBox->height() >= height();
483        rootObscuresBackground = rendererObscuresBackground(rootRenderer);
484    }
485
486    Page* page = document()->page();
487    float pageScaleFactor = page ? page->pageScaleFactor() : 1;
488
489    // If painting will entirely fill the view, no need to fill the background.
490    if (rootFillsViewport && rootObscuresBackground && pageScaleFactor >= 1)
491        return;
492
493    // This code typically only executes if the root element's visibility has been set to hidden,
494    // if there is a transform on the <html>, or if there is a page scale factor less than 1.
495    // Only fill with the base background color (typically white) if we're the root document,
496    // since iframes/frames with no background in the child document should show the parent's background.
497    if (frameView()->isTransparent()) // FIXME: This needs to be dynamic.  We should be able to go back to blitting if we ever stop being transparent.
498        frameView()->setCannotBlitToWindow(); // The parent must show behind the child.
499    else {
500        Color baseColor = frameView()->baseBackgroundColor();
501        if (baseColor.alpha()) {
502            CompositeOperator previousOperator = paintInfo.context->compositeOperation();
503            paintInfo.context->setCompositeOperation(CompositeCopy);
504            paintInfo.context->fillRect(paintInfo.rect, baseColor, style()->colorSpace());
505            paintInfo.context->setCompositeOperation(previousOperator);
506        } else
507            paintInfo.context->clearRect(paintInfo.rect);
508    }
509}
510
511bool RenderView::shouldRepaint(const LayoutRect& r) const
512{
513    if (printing() || r.width() == 0 || r.height() == 0)
514        return false;
515
516    if (!m_frameView)
517        return false;
518
519    if (m_frameView->repaintsDisabled())
520        return false;
521
522    return true;
523}
524
525void RenderView::repaintViewRectangle(const LayoutRect& ur, bool immediate) const
526{
527    if (!shouldRepaint(ur))
528        return;
529
530    // We always just invalidate the root view, since we could be an iframe that is clipped out
531    // or even invisible.
532    Element* elt = document()->ownerElement();
533    if (!elt)
534        m_frameView->repaintContentRectangle(pixelSnappedIntRect(ur), immediate);
535    else if (RenderBox* obj = elt->renderBox()) {
536        LayoutRect vr = viewRect();
537        LayoutRect r = intersection(ur, vr);
538
539        // Subtract out the contentsX and contentsY offsets to get our coords within the viewing
540        // rectangle.
541        r.moveBy(-vr.location());
542
543        // FIXME: Hardcoded offsets here are not good.
544        r.moveBy(obj->contentBoxRect().location());
545        obj->repaintRectangle(r, immediate);
546    }
547}
548
549void RenderView::repaintRectangleInViewAndCompositedLayers(const LayoutRect& ur, bool immediate)
550{
551    if (!shouldRepaint(ur))
552        return;
553
554    repaintViewRectangle(ur, immediate);
555
556#if USE(ACCELERATED_COMPOSITING)
557    if (compositor()->inCompositingMode()) {
558        IntRect repaintRect = pixelSnappedIntRect(ur);
559        compositor()->repaintCompositedLayers(&repaintRect);
560    }
561#endif
562}
563
564void RenderView::repaintViewAndCompositedLayers()
565{
566    repaint();
567
568#if USE(ACCELERATED_COMPOSITING)
569    if (compositor()->inCompositingMode())
570        compositor()->repaintCompositedLayers();
571#endif
572}
573
574void RenderView::computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect& rect, bool fixed) const
575{
576    // If a container was specified, and was not 0 or the RenderView,
577    // then we should have found it by now.
578    ASSERT_ARG(repaintContainer, !repaintContainer || repaintContainer == this);
579
580    if (printing())
581        return;
582
583    if (style()->isFlippedBlocksWritingMode()) {
584        // We have to flip by hand since the view's logical height has not been determined.  We
585        // can use the viewport width and height.
586        if (style()->isHorizontalWritingMode())
587            rect.setY(viewHeight() - rect.maxY());
588        else
589            rect.setX(viewWidth() - rect.maxX());
590    }
591
592    if (fixed && m_frameView)
593        rect.move(m_frameView->scrollOffsetForFixedPosition());
594
595    // Apply our transform if we have one (because of full page zooming).
596    if (!repaintContainer && layer() && layer()->transform())
597        rect = layer()->transform()->mapRect(rect);
598}
599
600void RenderView::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
601{
602    rects.append(pixelSnappedIntRect(accumulatedOffset, layer()->size()));
603}
604
605void RenderView::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
606{
607    if (wasFixed)
608        *wasFixed = false;
609    quads.append(FloatRect(FloatPoint(), layer()->size()));
610}
611
612static RenderObject* rendererAfterPosition(RenderObject* object, unsigned offset)
613{
614    if (!object)
615        return 0;
616
617    RenderObject* child = object->childAt(offset);
618    return child ? child : object->nextInPreOrderAfterChildren();
619}
620
621IntRect RenderView::selectionBounds(bool clipToVisibleContent) const
622{
623    typedef HashMap<RenderObject*, OwnPtr<RenderSelectionInfo> > SelectionMap;
624    SelectionMap selectedObjects;
625
626    RenderObject* os = m_selectionStart;
627    RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
628    while (os && os != stop) {
629        if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
630            // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
631            selectedObjects.set(os, adoptPtr(new RenderSelectionInfo(os, clipToVisibleContent)));
632            RenderBlock* cb = os->containingBlock();
633            while (cb && !cb->isRenderView()) {
634                OwnPtr<RenderSelectionInfo>& blockInfo = selectedObjects.add(cb, nullptr).iterator->value;
635                if (blockInfo)
636                    break;
637                blockInfo = adoptPtr(new RenderSelectionInfo(cb, clipToVisibleContent));
638                cb = cb->containingBlock();
639            }
640        }
641
642        os = os->nextInPreOrder();
643    }
644
645    // Now create a single bounding box rect that encloses the whole selection.
646    LayoutRect selRect;
647    SelectionMap::iterator end = selectedObjects.end();
648    for (SelectionMap::iterator i = selectedObjects.begin(); i != end; ++i) {
649        RenderSelectionInfo* info = i->value.get();
650        // RenderSelectionInfo::rect() is in the coordinates of the repaintContainer, so map to page coordinates.
651        LayoutRect currRect = info->rect();
652        if (RenderLayerModelObject* repaintContainer = info->repaintContainer()) {
653            FloatQuad absQuad = repaintContainer->localToAbsoluteQuad(FloatRect(currRect));
654            currRect = absQuad.enclosingBoundingBox();
655        }
656        selRect.unite(currRect);
657    }
658    return pixelSnappedIntRect(selRect);
659}
660
661void RenderView::repaintSelection() const
662{
663    HashSet<RenderBlock*> processedBlocks;
664
665    RenderObject* end = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
666    for (RenderObject* o = m_selectionStart; o && o != end; o = o->nextInPreOrder()) {
667        if (!o->canBeSelectionLeaf() && o != m_selectionStart && o != m_selectionEnd)
668            continue;
669        if (o->selectionState() == SelectionNone)
670            continue;
671
672        RenderSelectionInfo(o, true).repaint();
673
674        // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
675        for (RenderBlock* block = o->containingBlock(); block && !block->isRenderView(); block = block->containingBlock()) {
676            if (!processedBlocks.add(block).isNewEntry)
677                break;
678            RenderSelectionInfo(block, true).repaint();
679        }
680    }
681}
682
683#if USE(ACCELERATED_COMPOSITING)
684// Compositing layer dimensions take outline size into account, so we have to recompute layer
685// bounds when it changes.
686// FIXME: This is ugly; it would be nice to have a better way to do this.
687void RenderView::setMaximalOutlineSize(int o)
688{
689    if (o != m_maximalOutlineSize) {
690        m_maximalOutlineSize = o;
691
692        // maximalOutlineSize affects compositing layer dimensions.
693        compositor()->setCompositingLayersNeedRebuild();    // FIXME: this really just needs to be a geometry update.
694    }
695}
696#endif
697
698void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode)
699{
700    // Make sure both our start and end objects are defined.
701    // Check www.msnbc.com and try clicking around to find the case where this happened.
702    if ((start && !end) || (end && !start))
703        return;
704
705    bool caretChanged = m_selectionWasCaret != view()->frame()->selection()->isCaret();
706    m_selectionWasCaret = view()->frame()->selection()->isCaret();
707    // Just return if the selection hasn't changed.
708    if (m_selectionStart == start && m_selectionStartPos == startPos &&
709        m_selectionEnd == end && m_selectionEndPos == endPos && !caretChanged)
710        return;
711
712    if ((start && end) && (start->flowThreadContainingBlock() != end->flowThreadContainingBlock()))
713        return;
714
715    // Record the old selected objects.  These will be used later
716    // when we compare against the new selected objects.
717    int oldStartPos = m_selectionStartPos;
718    int oldEndPos = m_selectionEndPos;
719
720    // Objects each have a single selection rect to examine.
721    typedef HashMap<RenderObject*, OwnPtr<RenderSelectionInfo> > SelectedObjectMap;
722    SelectedObjectMap oldSelectedObjects;
723    SelectedObjectMap newSelectedObjects;
724
725    // Blocks contain selected objects and fill gaps between them, either on the left, right, or in between lines and blocks.
726    // In order to get the repaint rect right, we have to examine left, middle, and right rects individually, since otherwise
727    // the union of those rects might remain the same even when changes have occurred.
728    typedef HashMap<RenderBlock*, OwnPtr<RenderBlockSelectionInfo> > SelectedBlockMap;
729    SelectedBlockMap oldSelectedBlocks;
730    SelectedBlockMap newSelectedBlocks;
731
732    RenderObject* os = m_selectionStart;
733    RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
734    while (os && os != stop) {
735        if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
736            // Blocks are responsible for painting line gaps and margin gaps.  They must be examined as well.
737            oldSelectedObjects.set(os, adoptPtr(new RenderSelectionInfo(os, true)));
738            if (blockRepaintMode == RepaintNewXOROld) {
739                RenderBlock* cb = os->containingBlock();
740                while (cb && !cb->isRenderView()) {
741                    OwnPtr<RenderBlockSelectionInfo>& blockInfo = oldSelectedBlocks.add(cb, nullptr).iterator->value;
742                    if (blockInfo)
743                        break;
744                    blockInfo = adoptPtr(new RenderBlockSelectionInfo(cb));
745                    cb = cb->containingBlock();
746                }
747            }
748        }
749
750        os = os->nextInPreOrder();
751    }
752
753    // Now clear the selection.
754    SelectedObjectMap::iterator oldObjectsEnd = oldSelectedObjects.end();
755    for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i)
756        i->key->setSelectionStateIfNeeded(SelectionNone);
757
758    // set selection start and end
759    m_selectionStart = start;
760    m_selectionStartPos = startPos;
761    m_selectionEnd = end;
762    m_selectionEndPos = endPos;
763
764    // Update the selection status of all objects between m_selectionStart and m_selectionEnd
765    if (start && start == end)
766        start->setSelectionStateIfNeeded(SelectionBoth);
767    else {
768        if (start)
769            start->setSelectionStateIfNeeded(SelectionStart);
770        if (end)
771            end->setSelectionStateIfNeeded(SelectionEnd);
772    }
773
774    RenderObject* o = start;
775    stop = rendererAfterPosition(end, endPos);
776
777    while (o && o != stop) {
778        if (o != start && o != end && o->canBeSelectionLeaf())
779            o->setSelectionStateIfNeeded(SelectionInside);
780        o = o->nextInPreOrder();
781    }
782
783    if (blockRepaintMode != RepaintNothing)
784        layer()->clearBlockSelectionGapsBounds();
785
786    // Now that the selection state has been updated for the new objects, walk them again and
787    // put them in the new objects list.
788    o = start;
789    while (o && o != stop) {
790        if ((o->canBeSelectionLeaf() || o == start || o == end) && o->selectionState() != SelectionNone) {
791            newSelectedObjects.set(o, adoptPtr(new RenderSelectionInfo(o, true)));
792            RenderBlock* cb = o->containingBlock();
793            while (cb && !cb->isRenderView()) {
794                OwnPtr<RenderBlockSelectionInfo>& blockInfo = newSelectedBlocks.add(cb, nullptr).iterator->value;
795                if (blockInfo)
796                    break;
797                blockInfo = adoptPtr(new RenderBlockSelectionInfo(cb));
798                cb = cb->containingBlock();
799            }
800        }
801
802        o = o->nextInPreOrder();
803    }
804
805    if (!m_frameView || blockRepaintMode == RepaintNothing)
806        return;
807
808    m_frameView->beginDeferredRepaints();
809
810    // Have any of the old selected objects changed compared to the new selection?
811    for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i) {
812        RenderObject* obj = i->key;
813        RenderSelectionInfo* newInfo = newSelectedObjects.get(obj);
814        RenderSelectionInfo* oldInfo = i->value.get();
815        if (!newInfo || oldInfo->rect() != newInfo->rect() || oldInfo->state() != newInfo->state() ||
816            (m_selectionStart == obj && oldStartPos != m_selectionStartPos) ||
817            (m_selectionEnd == obj && oldEndPos != m_selectionEndPos)) {
818            oldInfo->repaint();
819            if (newInfo) {
820                newInfo->repaint();
821                newSelectedObjects.remove(obj);
822            }
823        }
824    }
825
826    // Any new objects that remain were not found in the old objects dict, and so they need to be updated.
827    SelectedObjectMap::iterator newObjectsEnd = newSelectedObjects.end();
828    for (SelectedObjectMap::iterator i = newSelectedObjects.begin(); i != newObjectsEnd; ++i)
829        i->value->repaint();
830
831    // Have any of the old blocks changed?
832    SelectedBlockMap::iterator oldBlocksEnd = oldSelectedBlocks.end();
833    for (SelectedBlockMap::iterator i = oldSelectedBlocks.begin(); i != oldBlocksEnd; ++i) {
834        RenderBlock* block = i->key;
835        RenderBlockSelectionInfo* newInfo = newSelectedBlocks.get(block);
836        RenderBlockSelectionInfo* oldInfo = i->value.get();
837        if (!newInfo || oldInfo->rects() != newInfo->rects() || oldInfo->state() != newInfo->state()) {
838            oldInfo->repaint();
839            if (newInfo) {
840                newInfo->repaint();
841                newSelectedBlocks.remove(block);
842            }
843        }
844    }
845
846    // Any new blocks that remain were not found in the old blocks dict, and so they need to be updated.
847    SelectedBlockMap::iterator newBlocksEnd = newSelectedBlocks.end();
848    for (SelectedBlockMap::iterator i = newSelectedBlocks.begin(); i != newBlocksEnd; ++i)
849        i->value->repaint();
850
851    m_frameView->endDeferredRepaints();
852}
853
854void RenderView::getSelection(RenderObject*& startRenderer, int& startOffset, RenderObject*& endRenderer, int& endOffset) const
855{
856    startRenderer = m_selectionStart;
857    startOffset = m_selectionStartPos;
858    endRenderer = m_selectionEnd;
859    endOffset = m_selectionEndPos;
860}
861
862void RenderView::clearSelection()
863{
864    layer()->repaintBlockSelectionGaps();
865    setSelection(0, -1, 0, -1, RepaintNewMinusOld);
866}
867
868void RenderView::selectionStartEnd(int& startPos, int& endPos) const
869{
870    startPos = m_selectionStartPos;
871    endPos = m_selectionEndPos;
872}
873
874bool RenderView::printing() const
875{
876    return document()->printing();
877}
878
879bool RenderView::shouldUsePrintingLayout() const
880{
881    if (!printing() || !m_frameView)
882        return false;
883    Frame* frame = m_frameView->frame();
884    return frame && frame->shouldUsePrintingLayout();
885}
886
887size_t RenderView::getRetainedWidgets(Vector<RenderWidget*>& renderWidgets)
888{
889    size_t size = m_widgets.size();
890
891    renderWidgets.reserveCapacity(size);
892
893    RenderWidgetSet::const_iterator end = m_widgets.end();
894    for (RenderWidgetSet::const_iterator it = m_widgets.begin(); it != end; ++it) {
895        renderWidgets.uncheckedAppend(*it);
896        (*it)->ref();
897    }
898
899    return size;
900}
901
902void RenderView::releaseWidgets(Vector<RenderWidget*>& renderWidgets)
903{
904    size_t size = renderWidgets.size();
905
906    for (size_t i = 0; i < size; ++i)
907        renderWidgets[i]->deref(renderArena());
908}
909
910void RenderView::updateWidgetPositions()
911{
912    // updateWidgetPosition() can possibly cause layout to be re-entered (via plug-ins running
913    // scripts in response to NPP_SetWindow, for example), so we need to keep the Widgets
914    // alive during enumeration.
915
916    Vector<RenderWidget*> renderWidgets;
917    size_t size = getRetainedWidgets(renderWidgets);
918
919    for (size_t i = 0; i < size; ++i)
920        renderWidgets[i]->updateWidgetPosition();
921
922    for (size_t i = 0; i < size; ++i)
923        renderWidgets[i]->widgetPositionsUpdated();
924
925    releaseWidgets(renderWidgets);
926}
927
928void RenderView::addWidget(RenderWidget* o)
929{
930    m_widgets.add(o);
931}
932
933void RenderView::removeWidget(RenderWidget* o)
934{
935    m_widgets.remove(o);
936}
937
938void RenderView::notifyWidgets(WidgetNotification notification)
939{
940    Vector<RenderWidget*> renderWidgets;
941    size_t size = getRetainedWidgets(renderWidgets);
942
943    for (size_t i = 0; i < size; ++i)
944        renderWidgets[i]->notifyWidget(notification);
945
946    releaseWidgets(renderWidgets);
947}
948
949LayoutRect RenderView::viewRect() const
950{
951    if (shouldUsePrintingLayout())
952        return LayoutRect(LayoutPoint(), size());
953    if (m_frameView)
954        return m_frameView->visibleContentRect();
955    return LayoutRect();
956}
957
958
959IntRect RenderView::unscaledDocumentRect() const
960{
961    LayoutRect overflowRect(layoutOverflowRect());
962    flipForWritingMode(overflowRect);
963    return pixelSnappedIntRect(overflowRect);
964}
965
966bool RenderView::rootBackgroundIsEntirelyFixed() const
967{
968    RenderObject* rootObject = document()->documentElement() ? document()->documentElement()->renderer() : 0;
969    if (!rootObject)
970        return false;
971
972    RenderObject* rootRenderer = rootObject->rendererForRootBackground();
973    return rootRenderer->hasEntirelyFixedBackground();
974}
975
976LayoutRect RenderView::backgroundRect(RenderBox* backgroundRenderer) const
977{
978    if (!hasColumns())
979        return unscaledDocumentRect();
980
981    ColumnInfo* columnInfo = this->columnInfo();
982    LayoutRect backgroundRect(0, 0, columnInfo->desiredColumnWidth(), columnInfo->columnHeight() * columnInfo->columnCount());
983    if (!isHorizontalWritingMode())
984        backgroundRect = backgroundRect.transposedRect();
985    backgroundRenderer->flipForWritingMode(backgroundRect);
986
987    return backgroundRect;
988}
989
990IntRect RenderView::documentRect() const
991{
992    FloatRect overflowRect(unscaledDocumentRect());
993    if (hasTransform())
994        overflowRect = layer()->currentTransform().mapRect(overflowRect);
995    return IntRect(overflowRect);
996}
997
998int RenderView::viewHeight() const
999{
1000    int height = 0;
1001    if (!shouldUsePrintingLayout() && m_frameView) {
1002        height = m_frameView->layoutHeight();
1003        height = m_frameView->useFixedLayout() ? ceilf(style()->effectiveZoom() * float(height)) : height;
1004    }
1005    return height;
1006}
1007
1008int RenderView::viewWidth() const
1009{
1010    int width = 0;
1011    if (!shouldUsePrintingLayout() && m_frameView) {
1012        width = m_frameView->layoutWidth();
1013        width = m_frameView->useFixedLayout() ? ceilf(style()->effectiveZoom() * float(width)) : width;
1014    }
1015    return width;
1016}
1017
1018int RenderView::viewLogicalHeight() const
1019{
1020    int height = style()->isHorizontalWritingMode() ? viewHeight() : viewWidth();
1021    return height;
1022}
1023
1024float RenderView::zoomFactor() const
1025{
1026    Frame* frame = m_frameView->frame();
1027    return frame ? frame->pageZoomFactor() : 1;
1028}
1029
1030void RenderView::pushLayoutState(RenderObject* root)
1031{
1032    ASSERT(m_layoutStateDisableCount == 0);
1033    ASSERT(m_layoutState == 0);
1034
1035    pushLayoutStateForCurrentFlowThread(root);
1036    m_layoutState = new (renderArena()) LayoutState(root);
1037}
1038
1039bool RenderView::shouldDisableLayoutStateForSubtree(RenderObject* renderer) const
1040{
1041    RenderObject* o = renderer;
1042    while (o) {
1043        if (o->hasColumns() || o->hasTransform() || o->hasReflection())
1044            return true;
1045        o = o->container();
1046    }
1047    return false;
1048}
1049
1050void RenderView::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
1051{
1052    if (result.innerNode())
1053        return;
1054
1055    Node* node = document()->documentElement();
1056    if (node) {
1057        result.setInnerNode(node);
1058        if (!result.innerNonSharedNode())
1059            result.setInnerNonSharedNode(node);
1060
1061        LayoutPoint adjustedPoint = point;
1062        offsetForContents(adjustedPoint);
1063
1064        result.setLocalPoint(adjustedPoint);
1065    }
1066}
1067
1068// FIXME: This function is obsolete and only used by embedded WebViews inside AppKit NSViews.
1069// Do not add callers of this function!
1070// The idea here is to take into account what object is moving the pagination point, and
1071// thus choose the best place to chop it.
1072void RenderView::setBestTruncatedAt(int y, RenderBoxModelObject* forRenderer, bool forcedBreak)
1073{
1074    // Nobody else can set a page break once we have a forced break.
1075    if (m_legacyPrinting.m_forcedPageBreak)
1076        return;
1077
1078    // Forced breaks always win over unforced breaks.
1079    if (forcedBreak) {
1080        m_legacyPrinting.m_forcedPageBreak = true;
1081        m_legacyPrinting.m_bestTruncatedAt = y;
1082        return;
1083    }
1084
1085    // Prefer the widest object that tries to move the pagination point
1086    IntRect boundingBox = forRenderer->borderBoundingBox();
1087    if (boundingBox.width() > m_legacyPrinting.m_truncatorWidth) {
1088        m_legacyPrinting.m_truncatorWidth = boundingBox.width();
1089        m_legacyPrinting.m_bestTruncatedAt = y;
1090    }
1091}
1092
1093#if USE(ACCELERATED_COMPOSITING)
1094bool RenderView::usesCompositing() const
1095{
1096    return m_compositor && m_compositor->inCompositingMode();
1097}
1098
1099RenderLayerCompositor* RenderView::compositor()
1100{
1101    if (!m_compositor)
1102        m_compositor = adoptPtr(new RenderLayerCompositor(this));
1103
1104    return m_compositor.get();
1105}
1106#endif
1107
1108void RenderView::setIsInWindow(bool isInWindow)
1109{
1110#if USE(ACCELERATED_COMPOSITING)
1111    if (m_compositor)
1112        m_compositor->setIsInWindow(isInWindow);
1113#endif
1114}
1115
1116#if ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS)
1117CustomFilterGlobalContext* RenderView::customFilterGlobalContext()
1118{
1119    if (!m_customFilterGlobalContext)
1120        m_customFilterGlobalContext = adoptPtr(new CustomFilterGlobalContext());
1121    return m_customFilterGlobalContext.get();
1122}
1123#endif
1124
1125void RenderView::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
1126{
1127    RenderBlock::styleDidChange(diff, oldStyle);
1128    if (hasRenderNamedFlowThreads())
1129        flowThreadController()->styleDidChange();
1130}
1131
1132bool RenderView::hasRenderNamedFlowThreads() const
1133{
1134    return m_flowThreadController && m_flowThreadController->hasRenderNamedFlowThreads();
1135}
1136
1137bool RenderView::checkTwoPassLayoutForAutoHeightRegions() const
1138{
1139    return hasRenderNamedFlowThreads() && m_flowThreadController->hasFlowThreadsWithAutoLogicalHeightRegions();
1140}
1141
1142FlowThreadController* RenderView::flowThreadController()
1143{
1144    if (!m_flowThreadController)
1145        m_flowThreadController = FlowThreadController::create(this);
1146
1147    return m_flowThreadController.get();
1148}
1149
1150void RenderView::pushLayoutStateForCurrentFlowThread(const RenderObject* object)
1151{
1152    if (!m_flowThreadController)
1153        return;
1154
1155    RenderFlowThread* currentFlowThread = m_flowThreadController->currentRenderFlowThread();
1156    if (!currentFlowThread)
1157        return;
1158
1159    currentFlowThread->pushFlowThreadLayoutState(object);
1160}
1161
1162void RenderView::popLayoutStateForCurrentFlowThread()
1163{
1164    if (!m_flowThreadController)
1165        return;
1166
1167    RenderFlowThread* currentFlowThread = m_flowThreadController->currentRenderFlowThread();
1168    if (!currentFlowThread)
1169        return;
1170
1171    currentFlowThread->popFlowThreadLayoutState();
1172}
1173
1174RenderBlock::IntervalArena* RenderView::intervalArena()
1175{
1176    if (!m_intervalArena)
1177        m_intervalArena = IntervalArena::create();
1178    return m_intervalArena.get();
1179}
1180
1181FragmentationDisabler::FragmentationDisabler(RenderObject* root)
1182{
1183    RenderView* renderView = root->view();
1184    ASSERT(renderView);
1185
1186    LayoutState* layoutState = renderView->layoutState();
1187
1188    m_root = root;
1189    m_fragmenting = layoutState && layoutState->isPaginated();
1190    m_flowThreadState = m_root->flowThreadState();
1191#ifndef NDEBUG
1192    m_layoutState = layoutState;
1193#endif
1194
1195    if (layoutState)
1196        layoutState->m_isPaginated = false;
1197
1198    if (m_flowThreadState != RenderObject::NotInsideFlowThread)
1199        m_root->setFlowThreadStateIncludingDescendants(RenderObject::NotInsideFlowThread);
1200}
1201
1202FragmentationDisabler::~FragmentationDisabler()
1203{
1204    RenderView* renderView = m_root->view();
1205    ASSERT(renderView);
1206
1207    LayoutState* layoutState = renderView->layoutState();
1208#ifndef NDEBUG
1209    ASSERT(m_layoutState == layoutState);
1210#endif
1211
1212    if (layoutState)
1213        layoutState->m_isPaginated = m_fragmenting;
1214
1215    if (m_flowThreadState != RenderObject::NotInsideFlowThread)
1216        m_root->setFlowThreadStateIncludingDescendants(m_flowThreadState);
1217}
1218
1219} // namespace WebCore
1220