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 "HitTestResult.h"
31 #include "RenderLayer.h"
32 #include "RenderSelectionInfo.h"
33 #include "RenderWidget.h"
34 #include "TransformState.h"
35
36 #if USE(ACCELERATED_COMPOSITING)
37 #include "RenderLayerCompositor.h"
38 #endif
39
40 #ifdef ANDROID_LAYOUT
41 #include "Settings.h"
42 #endif
43
44 namespace WebCore {
45
RenderView(Node * node,FrameView * view)46 RenderView::RenderView(Node* node, FrameView* view)
47 : RenderBlock(node)
48 , m_frameView(view)
49 , m_selectionStart(0)
50 , m_selectionEnd(0)
51 , m_selectionStartPos(-1)
52 , m_selectionEndPos(-1)
53 , m_printImages(true)
54 , m_maximalOutlineSize(0)
55 , m_layoutState(0)
56 , m_layoutStateDisableCount(0)
57 {
58 // Clear our anonymous bit, set because RenderObject assumes
59 // any renderer with document as the node is anonymous.
60 setIsAnonymous(false);
61
62 // init RenderObject attributes
63 setInline(false);
64
65 m_minPrefWidth = 0;
66 m_maxPrefWidth = 0;
67
68 setPrefWidthsDirty(true, false);
69
70 setPositioned(true); // to 0,0 :)
71
72 // Create a new root layer for our layer hierarchy.
73 m_layer = new (node->document()->renderArena()) RenderLayer(this);
74 setHasLayer(true);
75 }
76
~RenderView()77 RenderView::~RenderView()
78 {
79 }
80
calcHeight()81 void RenderView::calcHeight()
82 {
83 if (!printing() && m_frameView)
84 setHeight(viewHeight());
85 }
86
calcWidth()87 void RenderView::calcWidth()
88 {
89 if (!printing() && m_frameView)
90 setWidth(viewWidth());
91 #ifdef ANDROID_LAYOUT
92 const Settings * settings = document()->settings();
93 ASSERT(settings);
94 if (settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen)
95 m_visibleWidth = m_frameView->screenWidth();
96 if (settings->useWideViewport() && settings->viewportWidth() == -1 && width() < minPrefWidth())
97 setWidth(m_minPrefWidth);
98 #endif
99 m_marginLeft = 0;
100 m_marginRight = 0;
101 }
102
calcPrefWidths()103 void RenderView::calcPrefWidths()
104 {
105 ASSERT(prefWidthsDirty());
106
107 RenderBlock::calcPrefWidths();
108
109 m_maxPrefWidth = m_minPrefWidth;
110 }
111
layout()112 void RenderView::layout()
113 {
114 if (printing())
115 m_minPrefWidth = m_maxPrefWidth = width();
116
117 // Use calcWidth/Height to get the new width/height, since this will take the full page zoom factor into account.
118 bool relayoutChildren = !printing() && (!m_frameView || width() != viewWidth() || height() != viewHeight());
119 if (relayoutChildren) {
120 setChildNeedsLayout(true, false);
121 for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
122 if (child->style()->height().isPercent() || child->style()->minHeight().isPercent() || child->style()->maxHeight().isPercent())
123 child->setChildNeedsLayout(true, false);
124 }
125 }
126
127 ASSERT(!m_layoutState);
128 LayoutState state;
129 // FIXME: May be better to push a clip and avoid issuing offscreen repaints.
130 state.m_clipped = false;
131 m_layoutState = &state;
132
133 if (needsLayout())
134 RenderBlock::layout();
135
136 // Reset overflowWidth and overflowHeight, since they act as a lower bound for docWidth() and docHeight().
137 setOverflowWidth(width());
138 setOverflowHeight(height());
139
140 setOverflowWidth(docWidth());
141 setOverflowHeight(docHeight());
142
143 ASSERT(layoutDelta() == IntSize());
144 ASSERT(m_layoutStateDisableCount == 0);
145 ASSERT(m_layoutState == &state);
146 m_layoutState = 0;
147 setNeedsLayout(false);
148 }
149
mapLocalToContainer(RenderBoxModelObject * repaintContainer,bool fixed,bool,TransformState & transformState) const150 void RenderView::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool /*useTransforms*/, TransformState& transformState) const
151 {
152 // If a container was specified, and was not 0 or the RenderView,
153 // then we should have found it by now.
154 ASSERT_UNUSED(repaintContainer, !repaintContainer || repaintContainer == this);
155
156 if (fixed && m_frameView)
157 transformState.move(m_frameView->scrollOffset());
158 }
159
mapAbsoluteToLocalPoint(bool fixed,bool,TransformState & transformState) const160 void RenderView::mapAbsoluteToLocalPoint(bool fixed, bool /*useTransforms*/, TransformState& transformState) const
161 {
162 if (fixed && m_frameView)
163 transformState.move(-m_frameView->scrollOffset());
164 }
165
paint(PaintInfo & paintInfo,int tx,int ty)166 void RenderView::paint(PaintInfo& paintInfo, int tx, int ty)
167 {
168 // If we ever require layout but receive a paint anyway, something has gone horribly wrong.
169 ASSERT(!needsLayout());
170
171 // Cache the print rect because the dirty rect could get changed during painting.
172 if (printing())
173 setPrintRect(paintInfo.rect);
174 else
175 setPrintRect(IntRect());
176 paintObject(paintInfo, tx, ty);
177 }
178
rendererObscuresBackground(RenderObject * object)179 static inline bool rendererObscuresBackground(RenderObject* object)
180 {
181 return object && object->style()->visibility() == VISIBLE && object->style()->opacity() == 1 && !object->style()->hasTransform();
182 }
183
paintBoxDecorations(PaintInfo & paintInfo,int,int)184 void RenderView::paintBoxDecorations(PaintInfo& paintInfo, int, int)
185 {
186 // Check to see if we are enclosed by a layer that requires complex painting rules. If so, we cannot blit
187 // when scrolling, and we need to use slow repaints. Examples of layers that require this are transparent layers,
188 // layers with reflections, or transformed layers.
189 // FIXME: This needs to be dynamic. We should be able to go back to blitting if we ever stop being inside
190 // a transform, transparency layer, etc.
191 Element* elt;
192 for (elt = document()->ownerElement(); view() && elt && elt->renderer(); elt = elt->document()->ownerElement()) {
193 RenderLayer* layer = elt->renderer()->enclosingLayer();
194 if (layer->requiresSlowRepaints()) {
195 frameView()->setUseSlowRepaints();
196 break;
197 }
198 }
199
200 // If painting will entirely fill the view, no need to fill the background.
201 if (elt || rendererObscuresBackground(firstChild()) || !view())
202 return;
203
204 // This code typically only executes if the root element's visibility has been set to hidden,
205 // or there is a transform on the <html>.
206 // Only fill with the base background color (typically white) if we're the root document,
207 // since iframes/frames with no background in the child document should show the parent's background.
208 if (view()->isTransparent()) // FIXME: This needs to be dynamic. We should be able to go back to blitting if we ever stop being transparent.
209 frameView()->setUseSlowRepaints(); // The parent must show behind the child.
210 else {
211 Color baseColor = frameView()->baseBackgroundColor();
212 if (baseColor.alpha() > 0) {
213 paintInfo.context->save();
214 paintInfo.context->setCompositeOperation(CompositeCopy);
215 paintInfo.context->fillRect(paintInfo.rect, baseColor);
216 paintInfo.context->restore();
217 } else
218 paintInfo.context->clearRect(paintInfo.rect);
219 }
220 }
221
shouldRepaint(const IntRect & r) const222 bool RenderView::shouldRepaint(const IntRect& r) const
223 {
224 if (printing() || r.width() == 0 || r.height() == 0)
225 return false;
226
227 if (!m_frameView)
228 return false;
229
230 return true;
231 }
232
repaintViewRectangle(const IntRect & ur,bool immediate)233 void RenderView::repaintViewRectangle(const IntRect& ur, bool immediate)
234 {
235 if (!shouldRepaint(ur))
236 return;
237
238 // We always just invalidate the root view, since we could be an iframe that is clipped out
239 // or even invisible.
240 Element* elt = document()->ownerElement();
241 if (!elt)
242 m_frameView->repaintContentRectangle(ur, immediate);
243 else if (RenderBox* obj = elt->renderBox()) {
244 IntRect vr = viewRect();
245 IntRect r = intersection(ur, vr);
246
247 // Subtract out the contentsX and contentsY offsets to get our coords within the viewing
248 // rectangle.
249 r.move(-vr.x(), -vr.y());
250
251 // FIXME: Hardcoded offsets here are not good.
252 r.move(obj->borderLeft() + obj->paddingLeft(),
253 obj->borderTop() + obj->paddingTop());
254 obj->repaintRectangle(r, immediate);
255 }
256 }
257
repaintRectangleInViewAndCompositedLayers(const IntRect & ur,bool immediate)258 void RenderView::repaintRectangleInViewAndCompositedLayers(const IntRect& ur, bool immediate)
259 {
260 if (!shouldRepaint(ur))
261 return;
262
263 repaintViewRectangle(ur, immediate);
264
265 #if USE(ACCELERATED_COMPOSITING)
266 // If we're a frame, repaintViewRectangle will have repainted via a RenderObject in the
267 // parent document.
268 if (document()->ownerElement())
269 return;
270
271 if (compositor()->inCompositingMode())
272 compositor()->repaintCompositedLayersAbsoluteRect(ur);
273 #endif
274 }
275
computeRectForRepaint(RenderBoxModelObject * repaintContainer,IntRect & rect,bool fixed)276 void RenderView::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& rect, bool fixed)
277 {
278 // If a container was specified, and was not 0 or the RenderView,
279 // then we should have found it by now.
280 ASSERT_UNUSED(repaintContainer, !repaintContainer || repaintContainer == this);
281
282 if (printing())
283 return;
284
285 if (fixed && m_frameView)
286 rect.move(m_frameView->scrollX(), m_frameView->scrollY());
287
288 // Apply our transform if we have one (because of full page zooming).
289 if (m_layer && m_layer->transform())
290 rect = m_layer->transform()->mapRect(rect);
291 }
292
absoluteRects(Vector<IntRect> & rects,int tx,int ty)293 void RenderView::absoluteRects(Vector<IntRect>& rects, int tx, int ty)
294 {
295 rects.append(IntRect(tx, ty, m_layer->width(), m_layer->height()));
296 }
297
absoluteQuads(Vector<FloatQuad> & quads)298 void RenderView::absoluteQuads(Vector<FloatQuad>& quads)
299 {
300 quads.append(FloatRect(0, 0, m_layer->width(), m_layer->height()));
301 }
302
rendererAfterPosition(RenderObject * object,unsigned offset)303 static RenderObject* rendererAfterPosition(RenderObject* object, unsigned offset)
304 {
305 if (!object)
306 return 0;
307
308 RenderObject* child = object->childAt(offset);
309 return child ? child : object->nextInPreOrderAfterChildren();
310 }
311
selectionBounds(bool clipToVisibleContent) const312 IntRect RenderView::selectionBounds(bool clipToVisibleContent) const
313 {
314 document()->updateStyleIfNeeded();
315
316 typedef HashMap<RenderObject*, RenderSelectionInfo*> SelectionMap;
317 SelectionMap selectedObjects;
318
319 RenderObject* os = m_selectionStart;
320 RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
321 while (os && os != stop) {
322 if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
323 // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
324 selectedObjects.set(os, new RenderSelectionInfo(os, clipToVisibleContent));
325 RenderBlock* cb = os->containingBlock();
326 while (cb && !cb->isRenderView()) {
327 RenderSelectionInfo* blockInfo = selectedObjects.get(cb);
328 if (blockInfo)
329 break;
330 selectedObjects.set(cb, new RenderSelectionInfo(cb, clipToVisibleContent));
331 cb = cb->containingBlock();
332 }
333 }
334
335 os = os->nextInPreOrder();
336 }
337
338 // Now create a single bounding box rect that encloses the whole selection.
339 IntRect selRect;
340 SelectionMap::iterator end = selectedObjects.end();
341 for (SelectionMap::iterator i = selectedObjects.begin(); i != end; ++i) {
342 RenderSelectionInfo* info = i->second;
343 selRect.unite(info->rect());
344 delete info;
345 }
346 return selRect;
347 }
348
349 #if USE(ACCELERATED_COMPOSITING)
350 // Compositing layer dimensions take outline size into account, so we have to recompute layer
351 // bounds when it changes.
352 // FIXME: This is ugly; it would be nice to have a better way to do this.
setMaximalOutlineSize(int o)353 void RenderView::setMaximalOutlineSize(int o)
354 {
355 if (o != m_maximalOutlineSize) {
356 m_maximalOutlineSize = o;
357
358 // maximalOutlineSize affects compositing layer dimensions.
359 compositor()->setCompositingLayersNeedRebuild(); // FIXME: this really just needs to be a geometry update.
360 }
361 }
362 #endif
363
setSelection(RenderObject * start,int startPos,RenderObject * end,int endPos,SelectionRepaintMode blockRepaintMode)364 void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode)
365 {
366 // Make sure both our start and end objects are defined.
367 // Check www.msnbc.com and try clicking around to find the case where this happened.
368 if ((start && !end) || (end && !start))
369 return;
370
371 // Just return if the selection hasn't changed.
372 if (m_selectionStart == start && m_selectionStartPos == startPos &&
373 m_selectionEnd == end && m_selectionEndPos == endPos)
374 return;
375
376 // Record the old selected objects. These will be used later
377 // when we compare against the new selected objects.
378 int oldStartPos = m_selectionStartPos;
379 int oldEndPos = m_selectionEndPos;
380
381 // Objects each have a single selection rect to examine.
382 typedef HashMap<RenderObject*, RenderSelectionInfo*> SelectedObjectMap;
383 SelectedObjectMap oldSelectedObjects;
384 SelectedObjectMap newSelectedObjects;
385
386 // Blocks contain selected objects and fill gaps between them, either on the left, right, or in between lines and blocks.
387 // In order to get the repaint rect right, we have to examine left, middle, and right rects individually, since otherwise
388 // the union of those rects might remain the same even when changes have occurred.
389 typedef HashMap<RenderBlock*, RenderBlockSelectionInfo*> SelectedBlockMap;
390 SelectedBlockMap oldSelectedBlocks;
391 SelectedBlockMap newSelectedBlocks;
392
393 RenderObject* os = m_selectionStart;
394 RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
395 while (os && os != stop) {
396 if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
397 // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
398 oldSelectedObjects.set(os, new RenderSelectionInfo(os, true));
399 RenderBlock* cb = os->containingBlock();
400 while (cb && !cb->isRenderView()) {
401 RenderBlockSelectionInfo* blockInfo = oldSelectedBlocks.get(cb);
402 if (blockInfo)
403 break;
404 oldSelectedBlocks.set(cb, new RenderBlockSelectionInfo(cb));
405 cb = cb->containingBlock();
406 }
407 }
408
409 os = os->nextInPreOrder();
410 }
411
412 // Now clear the selection.
413 SelectedObjectMap::iterator oldObjectsEnd = oldSelectedObjects.end();
414 for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i)
415 i->first->setSelectionState(SelectionNone);
416
417 // set selection start and end
418 m_selectionStart = start;
419 m_selectionStartPos = startPos;
420 m_selectionEnd = end;
421 m_selectionEndPos = endPos;
422
423 // Update the selection status of all objects between m_selectionStart and m_selectionEnd
424 if (start && start == end)
425 start->setSelectionState(SelectionBoth);
426 else {
427 if (start)
428 start->setSelectionState(SelectionStart);
429 if (end)
430 end->setSelectionState(SelectionEnd);
431 }
432
433 RenderObject* o = start;
434 stop = rendererAfterPosition(end, endPos);
435
436 while (o && o != stop) {
437 if (o != start && o != end && o->canBeSelectionLeaf())
438 o->setSelectionState(SelectionInside);
439 o = o->nextInPreOrder();
440 }
441
442 m_cachedSelectionBounds = IntRect();
443
444 // Now that the selection state has been updated for the new objects, walk them again and
445 // put them in the new objects list.
446 o = start;
447 while (o && o != stop) {
448 if ((o->canBeSelectionLeaf() || o == start || o == end) && o->selectionState() != SelectionNone) {
449 newSelectedObjects.set(o, new RenderSelectionInfo(o, true));
450 RenderBlock* cb = o->containingBlock();
451 while (cb && !cb->isRenderView()) {
452 RenderBlockSelectionInfo* blockInfo = newSelectedBlocks.get(cb);
453 if (blockInfo)
454 break;
455 blockInfo = new RenderBlockSelectionInfo(cb);
456 newSelectedBlocks.set(cb, blockInfo);
457 m_cachedSelectionBounds.unite(blockInfo->rects());
458 cb = cb->containingBlock();
459 }
460 }
461
462 o = o->nextInPreOrder();
463 }
464
465 if (!m_frameView) {
466 // We built the maps, but we aren't going to use them.
467 // We need to delete the values, otherwise they'll all leak!
468 deleteAllValues(oldSelectedObjects);
469 deleteAllValues(newSelectedObjects);
470 deleteAllValues(oldSelectedBlocks);
471 deleteAllValues(newSelectedBlocks);
472 return;
473 }
474
475 // Have any of the old selected objects changed compared to the new selection?
476 for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i) {
477 RenderObject* obj = i->first;
478 RenderSelectionInfo* newInfo = newSelectedObjects.get(obj);
479 RenderSelectionInfo* oldInfo = i->second;
480 if (!newInfo || oldInfo->rect() != newInfo->rect() || oldInfo->state() != newInfo->state() ||
481 (m_selectionStart == obj && oldStartPos != m_selectionStartPos) ||
482 (m_selectionEnd == obj && oldEndPos != m_selectionEndPos)) {
483 oldInfo->repaint();
484 if (newInfo) {
485 newInfo->repaint();
486 newSelectedObjects.remove(obj);
487 delete newInfo;
488 }
489 }
490 delete oldInfo;
491 }
492
493 // Any new objects that remain were not found in the old objects dict, and so they need to be updated.
494 SelectedObjectMap::iterator newObjectsEnd = newSelectedObjects.end();
495 for (SelectedObjectMap::iterator i = newSelectedObjects.begin(); i != newObjectsEnd; ++i) {
496 RenderSelectionInfo* newInfo = i->second;
497 newInfo->repaint();
498 delete newInfo;
499 }
500
501 // Have any of the old blocks changed?
502 SelectedBlockMap::iterator oldBlocksEnd = oldSelectedBlocks.end();
503 for (SelectedBlockMap::iterator i = oldSelectedBlocks.begin(); i != oldBlocksEnd; ++i) {
504 RenderBlock* block = i->first;
505 RenderBlockSelectionInfo* newInfo = newSelectedBlocks.get(block);
506 RenderBlockSelectionInfo* oldInfo = i->second;
507 if (!newInfo || oldInfo->rects() != newInfo->rects() || oldInfo->state() != newInfo->state()) {
508 if (blockRepaintMode == RepaintNewXOROld)
509 oldInfo->repaint();
510 if (newInfo) {
511 newInfo->repaint();
512 newSelectedBlocks.remove(block);
513 delete newInfo;
514 }
515 }
516 delete oldInfo;
517 }
518
519 // Any new blocks that remain were not found in the old blocks dict, and so they need to be updated.
520 SelectedBlockMap::iterator newBlocksEnd = newSelectedBlocks.end();
521 for (SelectedBlockMap::iterator i = newSelectedBlocks.begin(); i != newBlocksEnd; ++i) {
522 RenderBlockSelectionInfo* newInfo = i->second;
523 newInfo->repaint();
524 delete newInfo;
525 }
526 }
527
clearSelection()528 void RenderView::clearSelection()
529 {
530 repaintViewRectangle(m_cachedSelectionBounds);
531 setSelection(0, -1, 0, -1, RepaintNewMinusOld);
532 }
533
selectionStartEnd(int & startPos,int & endPos) const534 void RenderView::selectionStartEnd(int& startPos, int& endPos) const
535 {
536 startPos = m_selectionStartPos;
537 endPos = m_selectionEndPos;
538 }
539
printing() const540 bool RenderView::printing() const
541 {
542 return document()->printing();
543 }
544
updateWidgetPositions()545 void RenderView::updateWidgetPositions()
546 {
547 RenderWidgetSet::iterator end = m_widgets.end();
548 for (RenderWidgetSet::iterator it = m_widgets.begin(); it != end; ++it)
549 (*it)->updateWidgetPosition();
550 }
551
addWidget(RenderWidget * o)552 void RenderView::addWidget(RenderWidget* o)
553 {
554 m_widgets.add(o);
555 }
556
removeWidget(RenderWidget * o)557 void RenderView::removeWidget(RenderWidget* o)
558 {
559 m_widgets.remove(o);
560 }
561
viewRect() const562 IntRect RenderView::viewRect() const
563 {
564 if (printing())
565 return IntRect(0, 0, width(), height());
566 if (m_frameView)
567 return m_frameView->visibleContentRect();
568 return IntRect();
569 }
570
docHeight() const571 int RenderView::docHeight() const
572 {
573 int h = lowestPosition();
574
575 // FIXME: This doesn't do any margin collapsing.
576 // Instead of this dh computation we should keep the result
577 // when we call RenderBlock::layout.
578 int dh = 0;
579 for (RenderBox* c = firstChildBox(); c; c = c->nextSiblingBox())
580 dh += c->height() + c->marginTop() + c->marginBottom();
581
582 if (dh > h)
583 h = dh;
584
585 return h;
586 }
587
docWidth() const588 int RenderView::docWidth() const
589 {
590 int w = rightmostPosition();
591
592 for (RenderBox* c = firstChildBox(); c; c = c->nextSiblingBox()) {
593 int dw = c->width() + c->marginLeft() + c->marginRight();
594 if (dw > w)
595 w = dw;
596 }
597
598 return w;
599 }
600
viewHeight() const601 int RenderView::viewHeight() const
602 {
603 int height = 0;
604 if (!printing() && m_frameView) {
605 height = m_frameView->layoutHeight();
606 height = m_frameView->useFixedLayout() ? ceilf(style()->effectiveZoom() * float(height)) : height;
607 }
608 return height;
609 }
610
viewWidth() const611 int RenderView::viewWidth() const
612 {
613 int width = 0;
614 if (!printing() && m_frameView) {
615 width = m_frameView->layoutWidth();
616 width = m_frameView->useFixedLayout() ? ceilf(style()->effectiveZoom() * float(width)) : width;
617 }
618 return width;
619 }
620
zoomFactor() const621 float RenderView::zoomFactor() const
622 {
623 if (m_frameView->frame() && m_frameView->frame()->shouldApplyPageZoom())
624 return m_frameView->frame()->zoomFactor();
625
626 return 1.0f;
627 }
628
629 // The idea here is to take into account what object is moving the pagination point, and
630 // thus choose the best place to chop it.
setBestTruncatedAt(int y,RenderBoxModelObject * forRenderer,bool forcedBreak)631 void RenderView::setBestTruncatedAt(int y, RenderBoxModelObject* forRenderer, bool forcedBreak)
632 {
633 // Nobody else can set a page break once we have a forced break.
634 if (m_forcedPageBreak)
635 return;
636
637 // Forced breaks always win over unforced breaks.
638 if (forcedBreak) {
639 m_forcedPageBreak = true;
640 m_bestTruncatedAt = y;
641 return;
642 }
643
644 // Prefer the widest object that tries to move the pagination point
645 IntRect boundingBox = forRenderer->borderBoundingBox();
646 if (boundingBox.width() > m_truncatorWidth) {
647 m_truncatorWidth = boundingBox.width();
648 m_bestTruncatedAt = y;
649 }
650 }
651
pushLayoutState(RenderObject * root)652 void RenderView::pushLayoutState(RenderObject* root)
653 {
654 ASSERT(!doingFullRepaint());
655 ASSERT(m_layoutStateDisableCount == 0);
656 ASSERT(m_layoutState == 0);
657
658 m_layoutState = new (renderArena()) LayoutState(root);
659 }
660
updateHitTestResult(HitTestResult & result,const IntPoint & point)661 void RenderView::updateHitTestResult(HitTestResult& result, const IntPoint& point)
662 {
663 if (result.innerNode())
664 return;
665
666 Node* node = document()->documentElement();
667 if (node) {
668 result.setInnerNode(node);
669 if (!result.innerNonSharedNode())
670 result.setInnerNonSharedNode(node);
671 result.setLocalPoint(point);
672 }
673 }
674
675 #if USE(ACCELERATED_COMPOSITING)
usesCompositing() const676 bool RenderView::usesCompositing() const
677 {
678 return m_compositor && m_compositor->inCompositingMode();
679 }
680
compositor()681 RenderLayerCompositor* RenderView::compositor()
682 {
683 if (!m_compositor)
684 m_compositor.set(new RenderLayerCompositor(this));
685
686 return m_compositor.get();
687 }
688 #endif
689
didMoveOnscreen()690 void RenderView::didMoveOnscreen()
691 {
692 #if USE(ACCELERATED_COMPOSITING)
693 if (m_compositor)
694 m_compositor->didMoveOnscreen();
695 #endif
696 }
697
willMoveOffscreen()698 void RenderView::willMoveOffscreen()
699 {
700 #if USE(ACCELERATED_COMPOSITING)
701 if (m_compositor)
702 m_compositor->willMoveOffscreen();
703 #endif
704 }
705
706 } // namespace WebCore
707