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 "Document.h"
25 #include "Element.h"
26 #include "FloatQuad.h"
27 #include "Frame.h"
28 #include "FrameView.h"
29 #include "GraphicsContext.h"
30 #include "HTMLFrameOwnerElement.h"
31 #include "HitTestResult.h"
32 #include "RenderLayer.h"
33 #include "RenderSelectionInfo.h"
34 #include "RenderWidget.h"
35 #include "RenderWidgetProtector.h"
36 #include "TransformState.h"
37 
38 #if USE(ACCELERATED_COMPOSITING)
39 #include "RenderLayerCompositor.h"
40 #endif
41 
42 namespace WebCore {
43 
RenderView(Node * node,FrameView * view)44 RenderView::RenderView(Node* node, FrameView* view)
45     : RenderBlock(node)
46     , m_frameView(view)
47     , m_selectionStart(0)
48     , m_selectionEnd(0)
49     , m_selectionStartPos(-1)
50     , m_selectionEndPos(-1)
51     , m_maximalOutlineSize(0)
52     , m_pageLogicalHeight(0)
53     , m_pageLogicalHeightChanged(false)
54     , m_layoutState(0)
55     , m_layoutStateDisableCount(0)
56 {
57     // Clear our anonymous bit, set because RenderObject assumes
58     // any renderer with document as the node is anonymous.
59     setIsAnonymous(false);
60 
61     // init RenderObject attributes
62     setInline(false);
63 
64     m_minPreferredLogicalWidth = 0;
65     m_maxPreferredLogicalWidth = 0;
66 
67     setPreferredLogicalWidthsDirty(true, false);
68 
69     setPositioned(true); // to 0,0 :)
70 }
71 
~RenderView()72 RenderView::~RenderView()
73 {
74 }
75 
computeLogicalHeight()76 void RenderView::computeLogicalHeight()
77 {
78     if (!printing() && m_frameView)
79         setLogicalHeight(viewLogicalHeight());
80 }
81 
computeLogicalWidth()82 void RenderView::computeLogicalWidth()
83 {
84     if (!printing() && m_frameView)
85         setLogicalWidth(viewLogicalWidth());
86 }
87 
computePreferredLogicalWidths()88 void RenderView::computePreferredLogicalWidths()
89 {
90     ASSERT(preferredLogicalWidthsDirty());
91 
92     RenderBlock::computePreferredLogicalWidths();
93 
94     m_maxPreferredLogicalWidth = m_minPreferredLogicalWidth;
95 }
96 
isChildAllowed(RenderObject * child,RenderStyle *) const97 bool RenderView::isChildAllowed(RenderObject* child, RenderStyle*) const
98 {
99     return child->isBox();
100 }
101 
layout()102 void RenderView::layout()
103 {
104     if (!document()->paginated())
105         setPageLogicalHeight(0);
106 
107     if (printing())
108         m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = logicalWidth();
109 
110     // Use calcWidth/Height to get the new width/height, since this will take the full page zoom factor into account.
111     bool relayoutChildren = !printing() && (!m_frameView || width() != viewWidth() || height() != viewHeight());
112     if (relayoutChildren) {
113         setChildNeedsLayout(true, false);
114         for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
115             if (child->style()->logicalHeight().isPercent() || child->style()->logicalMinHeight().isPercent() || child->style()->logicalMaxHeight().isPercent())
116                 child->setChildNeedsLayout(true, false);
117         }
118     }
119 
120     ASSERT(!m_layoutState);
121     LayoutState state;
122     // FIXME: May be better to push a clip and avoid issuing offscreen repaints.
123     state.m_clipped = false;
124     state.m_pageLogicalHeight = m_pageLogicalHeight;
125     state.m_pageLogicalHeightChanged = m_pageLogicalHeightChanged;
126     m_pageLogicalHeightChanged = false;
127     m_layoutState = &state;
128 
129     if (needsLayout())
130         RenderBlock::layout();
131 
132     ASSERT(layoutDelta() == IntSize());
133     ASSERT(m_layoutStateDisableCount == 0);
134     ASSERT(m_layoutState == &state);
135     m_layoutState = 0;
136     setNeedsLayout(false);
137 }
138 
mapLocalToContainer(RenderBoxModelObject * repaintContainer,bool fixed,bool useTransforms,TransformState & transformState) const139 void RenderView::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState) const
140 {
141     // If a container was specified, and was not 0 or the RenderView,
142     // then we should have found it by now.
143     ASSERT_ARG(repaintContainer, !repaintContainer || repaintContainer == this);
144 
145     if (!repaintContainer && useTransforms && shouldUseTransformFromContainer(0)) {
146         TransformationMatrix t;
147         getTransformFromContainer(0, IntSize(), t);
148         transformState.applyTransform(t);
149     }
150 
151     if (fixed && m_frameView)
152         transformState.move(m_frameView->scrollOffsetForFixedPosition());
153 }
154 
mapAbsoluteToLocalPoint(bool fixed,bool useTransforms,TransformState & transformState) const155 void RenderView::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState& transformState) const
156 {
157     if (fixed && m_frameView)
158         transformState.move(-m_frameView->scrollOffsetForFixedPosition());
159 
160     if (useTransforms && shouldUseTransformFromContainer(0)) {
161         TransformationMatrix t;
162         getTransformFromContainer(0, IntSize(), t);
163         transformState.applyTransform(t);
164     }
165 }
166 
paint(PaintInfo & paintInfo,int tx,int ty)167 void RenderView::paint(PaintInfo& paintInfo, int tx, int ty)
168 {
169     // If we ever require layout but receive a paint anyway, something has gone horribly wrong.
170     ASSERT(!needsLayout());
171     paintObject(paintInfo, tx, ty);
172 }
173 
isComposited(RenderObject * object)174 static inline bool isComposited(RenderObject* object)
175 {
176     return object->hasLayer() && toRenderBoxModelObject(object)->layer()->isComposited();
177 }
178 
rendererObscuresBackground(RenderObject * object)179 static inline bool rendererObscuresBackground(RenderObject* object)
180 {
181     return object && object->style()->visibility() == VISIBLE
182         && object->style()->opacity() == 1
183         && !object->style()->hasTransform()
184         && !isComposited(object);
185 }
186 
paintBoxDecorations(PaintInfo & paintInfo,int,int)187 void RenderView::paintBoxDecorations(PaintInfo& paintInfo, int, int)
188 {
189     // Check to see if we are enclosed by a layer that requires complex painting rules.  If so, we cannot blit
190     // when scrolling, and we need to use slow repaints.  Examples of layers that require this are transparent layers,
191     // layers with reflections, or transformed layers.
192     // FIXME: This needs to be dynamic.  We should be able to go back to blitting if we ever stop being inside
193     // a transform, transparency layer, etc.
194     Element* elt;
195     for (elt = document()->ownerElement(); view() && elt && elt->renderer(); elt = elt->document()->ownerElement()) {
196         RenderLayer* layer = elt->renderer()->enclosingLayer();
197         if (layer->requiresSlowRepaints()) {
198             frameView()->setUseSlowRepaints();
199             break;
200         }
201 
202 #if USE(ACCELERATED_COMPOSITING)
203         if (RenderLayer* compositingLayer = layer->enclosingCompositingLayer()) {
204             if (!compositingLayer->backing()->paintingGoesToWindow()) {
205                 frameView()->setUseSlowRepaints();
206                 break;
207             }
208         }
209 #endif
210     }
211 
212     if (document()->ownerElement() || !view())
213         return;
214 
215     bool rootFillsViewport = false;
216     Node* documentElement = document()->documentElement();
217     if (RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0) {
218         // The document element's renderer is currently forced to be a block, but may not always be.
219         RenderBox* rootBox = rootRenderer->isBox() ? toRenderBox(rootRenderer) : 0;
220         rootFillsViewport = rootBox && !rootBox->x() && !rootBox->y() && rootBox->width() >= width() && rootBox->height() >= height();
221     }
222 
223     float pageScaleFactor = 1;
224     if (Frame* frame = m_frameView->frame())
225         pageScaleFactor = frame->pageScaleFactor();
226 
227     // If painting will entirely fill the view, no need to fill the background.
228     if (rootFillsViewport && rendererObscuresBackground(firstChild()) && pageScaleFactor >= 1)
229         return;
230 
231     // This code typically only executes if the root element's visibility has been set to hidden,
232     // if there is a transform on the <html>, or if there is a page scale factor less than 1.
233     // Only fill with the base background color (typically white) if we're the root document,
234     // since iframes/frames with no background in the child document should show the parent's background.
235     if (frameView()->isTransparent()) // FIXME: This needs to be dynamic.  We should be able to go back to blitting if we ever stop being transparent.
236         frameView()->setUseSlowRepaints(); // The parent must show behind the child.
237     else {
238         Color baseColor = frameView()->baseBackgroundColor();
239         if (baseColor.alpha() > 0) {
240             CompositeOperator previousOperator = paintInfo.context->compositeOperation();
241             paintInfo.context->setCompositeOperation(CompositeCopy);
242             paintInfo.context->fillRect(paintInfo.rect, baseColor, style()->colorSpace());
243             paintInfo.context->setCompositeOperation(previousOperator);
244         } else
245             paintInfo.context->clearRect(paintInfo.rect);
246     }
247 }
248 
shouldRepaint(const IntRect & r) const249 bool RenderView::shouldRepaint(const IntRect& r) const
250 {
251     if (printing() || r.width() == 0 || r.height() == 0)
252         return false;
253 
254     if (!m_frameView)
255         return false;
256 
257     return true;
258 }
259 
repaintViewRectangle(const IntRect & ur,bool immediate)260 void RenderView::repaintViewRectangle(const IntRect& ur, bool immediate)
261 {
262     if (!shouldRepaint(ur))
263         return;
264 
265     // We always just invalidate the root view, since we could be an iframe that is clipped out
266     // or even invisible.
267     Element* elt = document()->ownerElement();
268     if (!elt)
269         m_frameView->repaintContentRectangle(ur, immediate);
270     else if (RenderBox* obj = elt->renderBox()) {
271         IntRect vr = viewRect();
272         IntRect r = intersection(ur, vr);
273 
274         // Subtract out the contentsX and contentsY offsets to get our coords within the viewing
275         // rectangle.
276         r.move(-vr.x(), -vr.y());
277 
278         // FIXME: Hardcoded offsets here are not good.
279         r.move(obj->borderLeft() + obj->paddingLeft(),
280                obj->borderTop() + obj->paddingTop());
281         obj->repaintRectangle(r, immediate);
282     }
283 }
284 
repaintRectangleInViewAndCompositedLayers(const IntRect & ur,bool immediate)285 void RenderView::repaintRectangleInViewAndCompositedLayers(const IntRect& ur, bool immediate)
286 {
287     if (!shouldRepaint(ur))
288         return;
289 
290     repaintViewRectangle(ur, immediate);
291 
292 #if USE(ACCELERATED_COMPOSITING)
293     if (compositor()->inCompositingMode())
294         compositor()->repaintCompositedLayersAbsoluteRect(ur);
295 #endif
296 }
297 
computeRectForRepaint(RenderBoxModelObject * repaintContainer,IntRect & rect,bool fixed)298 void RenderView::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& rect, bool fixed)
299 {
300     // If a container was specified, and was not 0 or the RenderView,
301     // then we should have found it by now.
302     ASSERT_ARG(repaintContainer, !repaintContainer || repaintContainer == this);
303 
304     if (printing())
305         return;
306 
307     if (style()->isFlippedBlocksWritingMode()) {
308         // We have to flip by hand since the view's logical height has not been determined.  We
309         // can use the viewport width and height.
310         if (style()->isHorizontalWritingMode())
311             rect.setY(viewHeight() - rect.maxY());
312         else
313             rect.setX(viewWidth() - rect.maxX());
314     }
315 
316     if (fixed && m_frameView)
317         rect.move(m_frameView->scrollXForFixedPosition(), m_frameView->scrollYForFixedPosition());
318 
319     // Apply our transform if we have one (because of full page zooming).
320     if (!repaintContainer && m_layer && m_layer->transform())
321         rect = m_layer->transform()->mapRect(rect);
322 }
323 
absoluteRects(Vector<IntRect> & rects,int tx,int ty)324 void RenderView::absoluteRects(Vector<IntRect>& rects, int tx, int ty)
325 {
326     rects.append(IntRect(tx, ty, m_layer->width(), m_layer->height()));
327 }
328 
absoluteQuads(Vector<FloatQuad> & quads)329 void RenderView::absoluteQuads(Vector<FloatQuad>& quads)
330 {
331     quads.append(FloatRect(0, 0, m_layer->width(), m_layer->height()));
332 }
333 
rendererAfterPosition(RenderObject * object,unsigned offset)334 static RenderObject* rendererAfterPosition(RenderObject* object, unsigned offset)
335 {
336     if (!object)
337         return 0;
338 
339     RenderObject* child = object->childAt(offset);
340     return child ? child : object->nextInPreOrderAfterChildren();
341 }
342 
selectionBounds(bool clipToVisibleContent) const343 IntRect RenderView::selectionBounds(bool clipToVisibleContent) const
344 {
345     document()->updateStyleIfNeeded();
346 
347     typedef HashMap<RenderObject*, RenderSelectionInfo*> SelectionMap;
348     SelectionMap selectedObjects;
349 
350     RenderObject* os = m_selectionStart;
351     RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
352     while (os && os != stop) {
353         if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
354             // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
355             selectedObjects.set(os, new RenderSelectionInfo(os, clipToVisibleContent));
356             RenderBlock* cb = os->containingBlock();
357             while (cb && !cb->isRenderView()) {
358                 RenderSelectionInfo* blockInfo = selectedObjects.get(cb);
359                 if (blockInfo)
360                     break;
361                 selectedObjects.set(cb, new RenderSelectionInfo(cb, clipToVisibleContent));
362                 cb = cb->containingBlock();
363             }
364         }
365 
366         os = os->nextInPreOrder();
367     }
368 
369     // Now create a single bounding box rect that encloses the whole selection.
370     IntRect selRect;
371     SelectionMap::iterator end = selectedObjects.end();
372     for (SelectionMap::iterator i = selectedObjects.begin(); i != end; ++i) {
373         RenderSelectionInfo* info = i->second;
374         // RenderSelectionInfo::rect() is in the coordinates of the repaintContainer, so map to page coordinates.
375         IntRect currRect = info->rect();
376         if (RenderBoxModelObject* repaintContainer = info->repaintContainer()) {
377             FloatQuad absQuad = repaintContainer->localToAbsoluteQuad(FloatRect(currRect));
378             currRect = absQuad.enclosingBoundingBox();
379         }
380         selRect.unite(currRect);
381         delete info;
382     }
383     return selRect;
384 }
385 
386 #if USE(ACCELERATED_COMPOSITING)
387 // Compositing layer dimensions take outline size into account, so we have to recompute layer
388 // bounds when it changes.
389 // FIXME: This is ugly; it would be nice to have a better way to do this.
setMaximalOutlineSize(int o)390 void RenderView::setMaximalOutlineSize(int o)
391 {
392     if (o != m_maximalOutlineSize) {
393         m_maximalOutlineSize = o;
394 
395         // maximalOutlineSize affects compositing layer dimensions.
396         compositor()->setCompositingLayersNeedRebuild();    // FIXME: this really just needs to be a geometry update.
397     }
398 }
399 #endif
400 
setSelection(RenderObject * start,int startPos,RenderObject * end,int endPos,SelectionRepaintMode blockRepaintMode)401 void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode)
402 {
403     // Make sure both our start and end objects are defined.
404     // Check www.msnbc.com and try clicking around to find the case where this happened.
405     if ((start && !end) || (end && !start))
406         return;
407 
408     // Just return if the selection hasn't changed.
409     if (m_selectionStart == start && m_selectionStartPos == startPos &&
410         m_selectionEnd == end && m_selectionEndPos == endPos)
411         return;
412 
413     // Record the old selected objects.  These will be used later
414     // when we compare against the new selected objects.
415     int oldStartPos = m_selectionStartPos;
416     int oldEndPos = m_selectionEndPos;
417 
418     // Objects each have a single selection rect to examine.
419     typedef HashMap<RenderObject*, RenderSelectionInfo*> SelectedObjectMap;
420     SelectedObjectMap oldSelectedObjects;
421     SelectedObjectMap newSelectedObjects;
422 
423     // Blocks contain selected objects and fill gaps between them, either on the left, right, or in between lines and blocks.
424     // In order to get the repaint rect right, we have to examine left, middle, and right rects individually, since otherwise
425     // the union of those rects might remain the same even when changes have occurred.
426     typedef HashMap<RenderBlock*, RenderBlockSelectionInfo*> SelectedBlockMap;
427     SelectedBlockMap oldSelectedBlocks;
428     SelectedBlockMap newSelectedBlocks;
429 
430     RenderObject* os = m_selectionStart;
431     RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
432     while (os && os != stop) {
433         if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
434             // Blocks are responsible for painting line gaps and margin gaps.  They must be examined as well.
435             oldSelectedObjects.set(os, new RenderSelectionInfo(os, true));
436             if (blockRepaintMode == RepaintNewXOROld) {
437                 RenderBlock* cb = os->containingBlock();
438                 while (cb && !cb->isRenderView()) {
439                     RenderBlockSelectionInfo* blockInfo = oldSelectedBlocks.get(cb);
440                     if (blockInfo)
441                         break;
442                     oldSelectedBlocks.set(cb, new RenderBlockSelectionInfo(cb));
443                     cb = cb->containingBlock();
444                 }
445             }
446         }
447 
448         os = os->nextInPreOrder();
449     }
450 
451     // Now clear the selection.
452     SelectedObjectMap::iterator oldObjectsEnd = oldSelectedObjects.end();
453     for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i)
454         i->first->setSelectionState(SelectionNone);
455 
456     // set selection start and end
457     m_selectionStart = start;
458     m_selectionStartPos = startPos;
459     m_selectionEnd = end;
460     m_selectionEndPos = endPos;
461 
462     // Update the selection status of all objects between m_selectionStart and m_selectionEnd
463     if (start && start == end)
464         start->setSelectionState(SelectionBoth);
465     else {
466         if (start)
467             start->setSelectionState(SelectionStart);
468         if (end)
469             end->setSelectionState(SelectionEnd);
470     }
471 
472     RenderObject* o = start;
473     stop = rendererAfterPosition(end, endPos);
474 
475     while (o && o != stop) {
476         if (o != start && o != end && o->canBeSelectionLeaf())
477             o->setSelectionState(SelectionInside);
478         o = o->nextInPreOrder();
479     }
480 
481     m_layer->clearBlockSelectionGapsBounds();
482 
483     // Now that the selection state has been updated for the new objects, walk them again and
484     // put them in the new objects list.
485     o = start;
486     while (o && o != stop) {
487         if ((o->canBeSelectionLeaf() || o == start || o == end) && o->selectionState() != SelectionNone) {
488             newSelectedObjects.set(o, new RenderSelectionInfo(o, true));
489             RenderBlock* cb = o->containingBlock();
490             while (cb && !cb->isRenderView()) {
491                 RenderBlockSelectionInfo* blockInfo = newSelectedBlocks.get(cb);
492                 if (blockInfo)
493                     break;
494                 newSelectedBlocks.set(cb, new RenderBlockSelectionInfo(cb));
495                 cb = cb->containingBlock();
496             }
497         }
498 
499         o = o->nextInPreOrder();
500     }
501 
502     if (!m_frameView) {
503         // We built the maps, but we aren't going to use them.
504         // We need to delete the values, otherwise they'll all leak!
505         deleteAllValues(oldSelectedObjects);
506         deleteAllValues(newSelectedObjects);
507         deleteAllValues(oldSelectedBlocks);
508         deleteAllValues(newSelectedBlocks);
509         return;
510     }
511 
512     m_frameView->beginDeferredRepaints();
513 
514     // Have any of the old selected objects changed compared to the new selection?
515     for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i) {
516         RenderObject* obj = i->first;
517         RenderSelectionInfo* newInfo = newSelectedObjects.get(obj);
518         RenderSelectionInfo* oldInfo = i->second;
519         if (!newInfo || oldInfo->rect() != newInfo->rect() || oldInfo->state() != newInfo->state() ||
520             (m_selectionStart == obj && oldStartPos != m_selectionStartPos) ||
521             (m_selectionEnd == obj && oldEndPos != m_selectionEndPos)) {
522             oldInfo->repaint();
523             if (newInfo) {
524                 newInfo->repaint();
525                 newSelectedObjects.remove(obj);
526                 delete newInfo;
527             }
528         }
529         delete oldInfo;
530     }
531 
532     // Any new objects that remain were not found in the old objects dict, and so they need to be updated.
533     SelectedObjectMap::iterator newObjectsEnd = newSelectedObjects.end();
534     for (SelectedObjectMap::iterator i = newSelectedObjects.begin(); i != newObjectsEnd; ++i) {
535         RenderSelectionInfo* newInfo = i->second;
536         newInfo->repaint();
537         delete newInfo;
538     }
539 
540     // Have any of the old blocks changed?
541     SelectedBlockMap::iterator oldBlocksEnd = oldSelectedBlocks.end();
542     for (SelectedBlockMap::iterator i = oldSelectedBlocks.begin(); i != oldBlocksEnd; ++i) {
543         RenderBlock* block = i->first;
544         RenderBlockSelectionInfo* newInfo = newSelectedBlocks.get(block);
545         RenderBlockSelectionInfo* oldInfo = i->second;
546         if (!newInfo || oldInfo->rects() != newInfo->rects() || oldInfo->state() != newInfo->state()) {
547             oldInfo->repaint();
548             if (newInfo) {
549                 newInfo->repaint();
550                 newSelectedBlocks.remove(block);
551                 delete newInfo;
552             }
553         }
554         delete oldInfo;
555     }
556 
557     // Any new blocks that remain were not found in the old blocks dict, and so they need to be updated.
558     SelectedBlockMap::iterator newBlocksEnd = newSelectedBlocks.end();
559     for (SelectedBlockMap::iterator i = newSelectedBlocks.begin(); i != newBlocksEnd; ++i) {
560         RenderBlockSelectionInfo* newInfo = i->second;
561         newInfo->repaint();
562         delete newInfo;
563     }
564 
565     m_frameView->endDeferredRepaints();
566 }
567 
clearSelection()568 void RenderView::clearSelection()
569 {
570     m_layer->repaintBlockSelectionGaps();
571     setSelection(0, -1, 0, -1, RepaintNewMinusOld);
572 }
573 
selectionStartEnd(int & startPos,int & endPos) const574 void RenderView::selectionStartEnd(int& startPos, int& endPos) const
575 {
576     startPos = m_selectionStartPos;
577     endPos = m_selectionEndPos;
578 }
579 
printing() const580 bool RenderView::printing() const
581 {
582     return document()->printing();
583 }
584 
getRetainedWidgets(Vector<RenderWidget * > & renderWidgets)585 size_t RenderView::getRetainedWidgets(Vector<RenderWidget*>& renderWidgets)
586 {
587     size_t size = m_widgets.size();
588 
589     renderWidgets.reserveCapacity(size);
590 
591     RenderWidgetSet::const_iterator end = m_widgets.end();
592     for (RenderWidgetSet::const_iterator it = m_widgets.begin(); it != end; ++it) {
593         renderWidgets.uncheckedAppend(*it);
594         (*it)->ref();
595     }
596 
597     return size;
598 }
599 
releaseWidgets(Vector<RenderWidget * > & renderWidgets)600 void RenderView::releaseWidgets(Vector<RenderWidget*>& renderWidgets)
601 {
602     size_t size = renderWidgets.size();
603 
604     for (size_t i = 0; i < size; ++i)
605         renderWidgets[i]->deref(renderArena());
606 }
607 
updateWidgetPositions()608 void RenderView::updateWidgetPositions()
609 {
610     // updateWidgetPosition() can possibly cause layout to be re-entered (via plug-ins running
611     // scripts in response to NPP_SetWindow, for example), so we need to keep the Widgets
612     // alive during enumeration.
613 
614     Vector<RenderWidget*> renderWidgets;
615     size_t size = getRetainedWidgets(renderWidgets);
616 
617     for (size_t i = 0; i < size; ++i)
618         renderWidgets[i]->updateWidgetPosition();
619 
620     for (size_t i = 0; i < size; ++i)
621         renderWidgets[i]->widgetPositionsUpdated();
622 
623     releaseWidgets(renderWidgets);
624 }
625 
addWidget(RenderWidget * o)626 void RenderView::addWidget(RenderWidget* o)
627 {
628     m_widgets.add(o);
629 }
630 
removeWidget(RenderWidget * o)631 void RenderView::removeWidget(RenderWidget* o)
632 {
633     m_widgets.remove(o);
634 }
635 
notifyWidgets(WidgetNotification notification)636 void RenderView::notifyWidgets(WidgetNotification notification)
637 {
638     Vector<RenderWidget*> renderWidgets;
639     size_t size = getRetainedWidgets(renderWidgets);
640 
641     for (size_t i = 0; i < size; ++i)
642         renderWidgets[i]->notifyWidget(notification);
643 
644     releaseWidgets(renderWidgets);
645 }
646 
viewRect() const647 IntRect RenderView::viewRect() const
648 {
649     if (printing())
650         return IntRect(0, 0, width(), height());
651     if (m_frameView)
652         return m_frameView->visibleContentRect();
653     return IntRect();
654 }
655 
docTop() const656 int RenderView::docTop() const
657 {
658     IntRect overflowRect(0, minYLayoutOverflow(), 0, maxYLayoutOverflow() - minYLayoutOverflow());
659     flipForWritingMode(overflowRect);
660     if (hasTransform())
661         overflowRect = layer()->currentTransform().mapRect(overflowRect);
662     return overflowRect.y();
663 }
664 
docBottom() const665 int RenderView::docBottom() const
666 {
667     IntRect overflowRect(layoutOverflowRect());
668     flipForWritingMode(overflowRect);
669     if (hasTransform())
670         overflowRect = layer()->currentTransform().mapRect(overflowRect);
671     return overflowRect.maxY();
672 }
673 
docLeft() const674 int RenderView::docLeft() const
675 {
676     IntRect overflowRect(layoutOverflowRect());
677     flipForWritingMode(overflowRect);
678     if (hasTransform())
679         overflowRect = layer()->currentTransform().mapRect(overflowRect);
680     return overflowRect.x();
681 }
682 
docRight() const683 int RenderView::docRight() const
684 {
685     IntRect overflowRect(layoutOverflowRect());
686     flipForWritingMode(overflowRect);
687     if (hasTransform())
688         overflowRect = layer()->currentTransform().mapRect(overflowRect);
689     return overflowRect.maxX();
690 }
691 
viewHeight() const692 int RenderView::viewHeight() const
693 {
694     int height = 0;
695     if (!printing() && m_frameView) {
696         height = m_frameView->layoutHeight();
697         height = m_frameView->useFixedLayout() ? ceilf(style()->effectiveZoom() * float(height)) : height;
698     }
699     return height;
700 }
701 
viewWidth() const702 int RenderView::viewWidth() const
703 {
704     int width = 0;
705     if (!printing() && m_frameView) {
706         width = m_frameView->layoutWidth();
707         width = m_frameView->useFixedLayout() ? ceilf(style()->effectiveZoom() * float(width)) : width;
708     }
709     return width;
710 }
711 
zoomFactor() const712 float RenderView::zoomFactor() const
713 {
714     Frame* frame = m_frameView->frame();
715     return frame ? frame->pageZoomFactor() : 1;
716 }
717 
pushLayoutState(RenderObject * root)718 void RenderView::pushLayoutState(RenderObject* root)
719 {
720     ASSERT(m_layoutStateDisableCount == 0);
721     ASSERT(m_layoutState == 0);
722 
723     m_layoutState = new (renderArena()) LayoutState(root);
724 }
725 
shouldDisableLayoutStateForSubtree(RenderObject * renderer) const726 bool RenderView::shouldDisableLayoutStateForSubtree(RenderObject* renderer) const
727 {
728     RenderObject* o = renderer;
729     while (o) {
730         if (o->hasColumns() || o->hasTransform() || o->hasReflection())
731             return true;
732         o = o->container();
733     }
734     return false;
735 }
736 
updateHitTestResult(HitTestResult & result,const IntPoint & point)737 void RenderView::updateHitTestResult(HitTestResult& result, const IntPoint& point)
738 {
739     if (result.innerNode())
740         return;
741 
742     Node* node = document()->documentElement();
743     if (node) {
744         result.setInnerNode(node);
745         if (!result.innerNonSharedNode())
746             result.setInnerNonSharedNode(node);
747         result.setLocalPoint(point);
748     }
749 }
750 
751 // FIXME: This function is obsolete and only used by embedded WebViews inside AppKit NSViews.
752 // Do not add callers of this function!
753 // The idea here is to take into account what object is moving the pagination point, and
754 // thus choose the best place to chop it.
setBestTruncatedAt(int y,RenderBoxModelObject * forRenderer,bool forcedBreak)755 void RenderView::setBestTruncatedAt(int y, RenderBoxModelObject* forRenderer, bool forcedBreak)
756 {
757     // Nobody else can set a page break once we have a forced break.
758     if (m_legacyPrinting.m_forcedPageBreak)
759         return;
760 
761     // Forced breaks always win over unforced breaks.
762     if (forcedBreak) {
763         m_legacyPrinting.m_forcedPageBreak = true;
764         m_legacyPrinting.m_bestTruncatedAt = y;
765         return;
766     }
767 
768     // Prefer the widest object that tries to move the pagination point
769     IntRect boundingBox = forRenderer->borderBoundingBox();
770     if (boundingBox.width() > m_legacyPrinting.m_truncatorWidth) {
771         m_legacyPrinting.m_truncatorWidth = boundingBox.width();
772         m_legacyPrinting.m_bestTruncatedAt = y;
773     }
774 }
775 
776 #if USE(ACCELERATED_COMPOSITING)
usesCompositing() const777 bool RenderView::usesCompositing() const
778 {
779     return m_compositor && m_compositor->inCompositingMode();
780 }
781 
compositor()782 RenderLayerCompositor* RenderView::compositor()
783 {
784     if (!m_compositor)
785         m_compositor = adoptPtr(new RenderLayerCompositor(this));
786 
787     return m_compositor.get();
788 }
789 #endif
790 
didMoveOnscreen()791 void RenderView::didMoveOnscreen()
792 {
793 #if USE(ACCELERATED_COMPOSITING)
794     if (m_compositor)
795         m_compositor->didMoveOnscreen();
796 #endif
797 }
798 
willMoveOffscreen()799 void RenderView::willMoveOffscreen()
800 {
801 #if USE(ACCELERATED_COMPOSITING)
802     if (m_compositor)
803         m_compositor->willMoveOffscreen();
804 #endif
805 }
806 
807 } // namespace WebCore
808