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