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