1/* 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 3 * Copyright (C) 2006 Apple Computer, Inc. 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 22#ifndef RenderView_h 23#define RenderView_h 24 25#include "FrameView.h" 26#include "LayoutState.h" 27#include "PODFreeListArena.h" 28#include "RenderBlock.h" 29#include <wtf/OwnPtr.h> 30 31namespace WebCore { 32 33class FlowThreadController; 34class RenderQuote; 35class RenderWidget; 36 37#if USE(ACCELERATED_COMPOSITING) 38class RenderLayerCompositor; 39#endif 40 41#if ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) 42class CustomFilterGlobalContext; 43#endif 44 45class RenderView : public RenderBlock { 46public: 47 explicit RenderView(Document*); 48 virtual ~RenderView(); 49 50 bool hitTest(const HitTestRequest&, HitTestResult&); 51 bool hitTest(const HitTestRequest&, const HitTestLocation&, HitTestResult&); 52 53 virtual const char* renderName() const OVERRIDE { return "RenderView"; } 54 55 virtual bool isRenderView() const OVERRIDE { return true; } 56 57 virtual bool requiresLayer() const OVERRIDE { return true; } 58 59 virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE; 60 61 virtual void layout() OVERRIDE; 62 virtual void updateLogicalWidth() OVERRIDE; 63 virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const OVERRIDE; 64 65 virtual LayoutUnit availableLogicalHeight(AvailableLogicalHeightType) const OVERRIDE; 66 67 // The same as the FrameView's layoutHeight/layoutWidth but with null check guards. 68 int viewHeight() const; 69 int viewWidth() const; 70 int viewLogicalWidth() const { return style()->isHorizontalWritingMode() ? viewWidth() : viewHeight(); } 71 int viewLogicalHeight() const; 72 73 float zoomFactor() const; 74 75 FrameView* frameView() const { return m_frameView; } 76 77 virtual void computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect&, bool fixed = false) const OVERRIDE; 78 void repaintViewRectangle(const LayoutRect&, bool immediate = false) const; 79 // Repaint the view, and all composited layers that intersect the given absolute rectangle. 80 // FIXME: ideally we'd never have to do this, if all repaints are container-relative. 81 void repaintRectangleInViewAndCompositedLayers(const LayoutRect&, bool immediate = false); 82 void repaintViewAndCompositedLayers(); 83 84 virtual void paint(PaintInfo&, const LayoutPoint&); 85 virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&) OVERRIDE; 86 87 enum SelectionRepaintMode { RepaintNewXOROld, RepaintNewMinusOld, RepaintNothing }; 88 void setSelection(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode = RepaintNewXOROld); 89 void getSelection(RenderObject*& startRenderer, int& startOffset, RenderObject*& endRenderer, int& endOffset) const; 90 void clearSelection(); 91 RenderObject* selectionStart() const { return m_selectionStart; } 92 RenderObject* selectionEnd() const { return m_selectionEnd; } 93 IntRect selectionBounds(bool clipToVisibleContent = true) const; 94 void selectionStartEnd(int& startPos, int& endPos) const; 95 void repaintSelection() const; 96 97 bool printing() const; 98 99 virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const; 100 virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const; 101 102#if USE(ACCELERATED_COMPOSITING) 103 void setMaximalOutlineSize(int o); 104#else 105 void setMaximalOutlineSize(int o) { m_maximalOutlineSize = o; } 106#endif 107 int maximalOutlineSize() const { return m_maximalOutlineSize; } 108 109 virtual LayoutRect viewRect() const OVERRIDE; 110 111 void updateWidgetPositions(); 112 void addWidget(RenderWidget*); 113 void removeWidget(RenderWidget*); 114 115 void notifyWidgets(WidgetNotification); 116 117 // layoutDelta is used transiently during layout to store how far an object has moved from its 118 // last layout location, in order to repaint correctly. 119 // If we're doing a full repaint m_layoutState will be 0, but in that case layoutDelta doesn't matter. 120 LayoutSize layoutDelta() const 121 { 122 return m_layoutState ? m_layoutState->m_layoutDelta : LayoutSize(); 123 } 124 void addLayoutDelta(const LayoutSize& delta) 125 { 126 if (m_layoutState) { 127 m_layoutState->m_layoutDelta += delta; 128#if !ASSERT_DISABLED && ENABLE(SATURATED_LAYOUT_ARITHMETIC) 129 m_layoutState->m_layoutDeltaXSaturated |= m_layoutState->m_layoutDelta.width() == LayoutUnit::max() || m_layoutState->m_layoutDelta.width() == LayoutUnit::min(); 130 m_layoutState->m_layoutDeltaYSaturated |= m_layoutState->m_layoutDelta.height() == LayoutUnit::max() || m_layoutState->m_layoutDelta.height() == LayoutUnit::min(); 131#endif 132 } 133 } 134 135#if !ASSERT_DISABLED 136 bool layoutDeltaMatches(const LayoutSize& delta) 137 { 138 if (!m_layoutState) 139 return false; 140#if ENABLE(SATURATED_LAYOUT_ARITHMETIC) 141 return (delta.width() == m_layoutState->m_layoutDelta.width() || m_layoutState->m_layoutDeltaXSaturated) && (delta.height() == m_layoutState->m_layoutDelta.height() || m_layoutState->m_layoutDeltaYSaturated); 142#else 143 return delta == m_layoutState->m_layoutDelta; 144#endif 145 } 146#endif 147 148 bool doingFullRepaint() const { return m_frameView->needsFullRepaint(); } 149 150 // Subtree push/pop 151 void pushLayoutState(RenderObject*); 152 void popLayoutState(RenderObject*) { return popLayoutState(); } // Just doing this to keep popLayoutState() private and to make the subtree calls symmetrical. 153 154 bool shouldDisableLayoutStateForSubtree(RenderObject*) const; 155 156 // Returns true if layoutState should be used for its cached offset and clip. 157 bool layoutStateEnabled() const { return m_layoutStateDisableCount == 0 && m_layoutState; } 158 LayoutState* layoutState() const { return m_layoutState; } 159 160 virtual void updateHitTestResult(HitTestResult&, const LayoutPoint&); 161 162 LayoutUnit pageLogicalHeight() const { return m_pageLogicalHeight; } 163 void setPageLogicalHeight(LayoutUnit height) 164 { 165 if (m_pageLogicalHeight != height) { 166 m_pageLogicalHeight = height; 167 m_pageLogicalHeightChanged = true; 168 } 169 } 170 LayoutUnit pageOrViewLogicalHeight() const; 171 172 // FIXME: These functions are deprecated. No code should be added that uses these. 173 int bestTruncatedAt() const { return m_legacyPrinting.m_bestTruncatedAt; } 174 void setBestTruncatedAt(int y, RenderBoxModelObject* forRenderer, bool forcedBreak = false); 175 int truncatedAt() const { return m_legacyPrinting.m_truncatedAt; } 176 void setTruncatedAt(int y) 177 { 178 m_legacyPrinting.m_truncatedAt = y; 179 m_legacyPrinting.m_bestTruncatedAt = 0; 180 m_legacyPrinting.m_truncatorWidth = 0; 181 m_legacyPrinting.m_forcedPageBreak = false; 182 } 183 const IntRect& printRect() const { return m_legacyPrinting.m_printRect; } 184 void setPrintRect(const IntRect& r) { m_legacyPrinting.m_printRect = r; } 185 // End deprecated functions. 186 187 // Notification that this view moved into or out of a native window. 188 void setIsInWindow(bool); 189 190#if USE(ACCELERATED_COMPOSITING) 191 RenderLayerCompositor* compositor(); 192 bool usesCompositing() const; 193#endif 194 195#if ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) 196 CustomFilterGlobalContext* customFilterGlobalContext(); 197#endif 198 199 IntRect unscaledDocumentRect() const; 200 LayoutRect backgroundRect(RenderBox* backgroundRenderer) const; 201 202 IntRect documentRect() const; 203 204 // Renderer that paints the root background has background-images which all have background-attachment: fixed. 205 bool rootBackgroundIsEntirelyFixed() const; 206 207 bool hasRenderNamedFlowThreads() const; 208 bool checkTwoPassLayoutForAutoHeightRegions() const; 209 FlowThreadController* flowThreadController(); 210 211 void styleDidChange(StyleDifference, const RenderStyle* oldStyle); 212 213 IntervalArena* intervalArena(); 214 215 IntSize viewportSize() const { return document()->viewportSize(); } 216 217 void setRenderQuoteHead(RenderQuote* head) { m_renderQuoteHead = head; } 218 RenderQuote* renderQuoteHead() const { return m_renderQuoteHead; } 219 220 // FIXME: This is a work around because the current implementation of counters 221 // requires walking the entire tree repeatedly and most pages don't actually use either 222 // feature so we shouldn't take the performance hit when not needed. Long term we should 223 // rewrite the counter and quotes code. 224 void addRenderCounter() { m_renderCounterCount++; } 225 void removeRenderCounter() { ASSERT(m_renderCounterCount > 0); m_renderCounterCount--; } 226 bool hasRenderCounters() { return m_renderCounterCount; } 227 228 virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0) OVERRIDE; 229 230 IntRect pixelSnappedLayoutOverflowRect() const { return pixelSnappedIntRect(layoutOverflowRect()); } 231 232protected: 233 virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE; 234 virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE; 235 virtual void mapAbsoluteToLocalPoint(MapCoordinatesFlags, TransformState&) const; 236 virtual bool requiresColumns(int desiredColumnCount) const OVERRIDE; 237 238private: 239 bool initializeLayoutState(LayoutState&); 240 241 virtual void calcColumnWidth() OVERRIDE; 242 virtual ColumnInfo::PaginationUnit paginationUnit() const OVERRIDE; 243 244 bool shouldRepaint(const LayoutRect&) const; 245 246 // These functions may only be accessed by LayoutStateMaintainer. 247 bool pushLayoutState(RenderBox* renderer, const LayoutSize& offset, LayoutUnit pageHeight = 0, bool pageHeightChanged = false, ColumnInfo* colInfo = 0) 248 { 249 // We push LayoutState even if layoutState is disabled because it stores layoutDelta too. 250 if (!doingFullRepaint() || m_layoutState->isPaginated() || renderer->hasColumns() || renderer->flowThreadContainingBlock() 251 || m_layoutState->lineGrid() || (renderer->style()->lineGrid() != RenderStyle::initialLineGrid() && renderer->isBlockFlow()) 252#if ENABLE(CSS_SHAPES) 253 || (renderer->isRenderBlock() && toRenderBlock(renderer)->shapeInsideInfo()) 254 || (m_layoutState->shapeInsideInfo() && renderer->isRenderBlock() && !toRenderBlock(renderer)->allowsShapeInsideInfoSharing()) 255#endif 256 ) { 257 pushLayoutStateForCurrentFlowThread(renderer); 258 m_layoutState = new (renderArena()) LayoutState(m_layoutState, renderer, offset, pageHeight, pageHeightChanged, colInfo); 259 return true; 260 } 261 return false; 262 } 263 264 void popLayoutState() 265 { 266 LayoutState* state = m_layoutState; 267 m_layoutState = state->m_next; 268 state->destroy(renderArena()); 269 popLayoutStateForCurrentFlowThread(); 270 } 271 272 // Suspends the LayoutState optimization. Used under transforms that cannot be represented by 273 // LayoutState (common in SVG) and when manipulating the render tree during layout in ways 274 // that can trigger repaint of a non-child (e.g. when a list item moves its list marker around). 275 // Note that even when disabled, LayoutState is still used to store layoutDelta. 276 // These functions may only be accessed by LayoutStateMaintainer or LayoutStateDisabler. 277 void disableLayoutState() { m_layoutStateDisableCount++; } 278 void enableLayoutState() { ASSERT(m_layoutStateDisableCount > 0); m_layoutStateDisableCount--; } 279 280 void layoutContent(const LayoutState&); 281 void layoutContentInAutoLogicalHeightRegions(const LayoutState&); 282#ifndef NDEBUG 283 void checkLayoutState(const LayoutState&); 284#endif 285 286 size_t getRetainedWidgets(Vector<RenderWidget*>&); 287 void releaseWidgets(Vector<RenderWidget*>&); 288 289 void pushLayoutStateForCurrentFlowThread(const RenderObject*); 290 void popLayoutStateForCurrentFlowThread(); 291 292 friend class LayoutStateMaintainer; 293 friend class LayoutStateDisabler; 294 295protected: 296 FrameView* m_frameView; 297 298 RenderObject* m_selectionStart; 299 RenderObject* m_selectionEnd; 300 int m_selectionStartPos; 301 int m_selectionEndPos; 302 303 // FIXME: Only used by embedded WebViews inside AppKit NSViews. Find a way to remove. 304 struct LegacyPrinting { 305 LegacyPrinting() 306 : m_bestTruncatedAt(0) 307 , m_truncatedAt(0) 308 , m_truncatorWidth(0) 309 , m_forcedPageBreak(false) 310 { } 311 312 int m_bestTruncatedAt; 313 int m_truncatedAt; 314 int m_truncatorWidth; 315 IntRect m_printRect; 316 bool m_forcedPageBreak; 317 }; 318 LegacyPrinting m_legacyPrinting; 319 // End deprecated members. 320 321 int m_maximalOutlineSize; // Used to apply a fudge factor to dirty-rect checks on blocks/tables. 322 323 typedef HashSet<RenderWidget*> RenderWidgetSet; 324 RenderWidgetSet m_widgets; 325 326private: 327 bool shouldUsePrintingLayout() const; 328 329 LayoutUnit m_pageLogicalHeight; 330 bool m_pageLogicalHeightChanged; 331 LayoutState* m_layoutState; 332 unsigned m_layoutStateDisableCount; 333#if USE(ACCELERATED_COMPOSITING) 334 OwnPtr<RenderLayerCompositor> m_compositor; 335#endif 336#if ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) 337 OwnPtr<CustomFilterGlobalContext> m_customFilterGlobalContext; 338#endif 339 OwnPtr<FlowThreadController> m_flowThreadController; 340 RefPtr<IntervalArena> m_intervalArena; 341 342 RenderQuote* m_renderQuoteHead; 343 unsigned m_renderCounterCount; 344 345 bool m_selectionWasCaret; 346}; 347 348inline RenderView* toRenderView(RenderObject* object) 349{ 350 ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderView()); 351 return static_cast<RenderView*>(object); 352} 353 354inline const RenderView* toRenderView(const RenderObject* object) 355{ 356 ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderView()); 357 return static_cast<const RenderView*>(object); 358} 359 360// This will catch anyone doing an unnecessary cast. 361void toRenderView(const RenderView*); 362 363ALWAYS_INLINE RenderView* Document::renderView() const 364{ 365 return toRenderView(renderer()); 366} 367 368// Stack-based class to assist with LayoutState push/pop 369class LayoutStateMaintainer { 370 WTF_MAKE_NONCOPYABLE(LayoutStateMaintainer); 371public: 372 // ctor to push now 373 LayoutStateMaintainer(RenderView* view, RenderBox* root, LayoutSize offset, bool disableState = false, LayoutUnit pageHeight = 0, bool pageHeightChanged = false, ColumnInfo* colInfo = 0) 374 : m_view(view) 375 , m_disabled(disableState) 376 , m_didStart(false) 377 , m_didEnd(false) 378 , m_didCreateLayoutState(false) 379 { 380 push(root, offset, pageHeight, pageHeightChanged, colInfo); 381 } 382 383 // ctor to maybe push later 384 LayoutStateMaintainer(RenderView* view) 385 : m_view(view) 386 , m_disabled(false) 387 , m_didStart(false) 388 , m_didEnd(false) 389 , m_didCreateLayoutState(false) 390 { 391 } 392 393 ~LayoutStateMaintainer() 394 { 395 ASSERT(m_didStart == m_didEnd); // if this fires, it means that someone did a push(), but forgot to pop(). 396 } 397 398 void push(RenderBox* root, LayoutSize offset, LayoutUnit pageHeight = 0, bool pageHeightChanged = false, ColumnInfo* colInfo = 0) 399 { 400 ASSERT(!m_didStart); 401 // We push state even if disabled, because we still need to store layoutDelta 402 m_didCreateLayoutState = m_view->pushLayoutState(root, offset, pageHeight, pageHeightChanged, colInfo); 403 if (m_disabled && m_didCreateLayoutState) 404 m_view->disableLayoutState(); 405 m_didStart = true; 406 } 407 408 void pop() 409 { 410 if (m_didStart) { 411 ASSERT(!m_didEnd); 412 if (m_didCreateLayoutState) { 413 m_view->popLayoutState(); 414 if (m_disabled) 415 m_view->enableLayoutState(); 416 } 417 418 m_didEnd = true; 419 } 420 } 421 422 bool didPush() const { return m_didStart; } 423 424private: 425 RenderView* m_view; 426 bool m_disabled : 1; // true if the offset and clip part of layoutState is disabled 427 bool m_didStart : 1; // true if we did a push or disable 428 bool m_didEnd : 1; // true if we popped or re-enabled 429 bool m_didCreateLayoutState : 1; // true if we actually made a layout state. 430}; 431 432class LayoutStateDisabler { 433 WTF_MAKE_NONCOPYABLE(LayoutStateDisabler); 434public: 435 LayoutStateDisabler(RenderView* view) 436 : m_view(view) 437 { 438 if (m_view) 439 m_view->disableLayoutState(); 440 } 441 442 ~LayoutStateDisabler() 443 { 444 if (m_view) 445 m_view->enableLayoutState(); 446 } 447private: 448 RenderView* m_view; 449}; 450 451class FragmentationDisabler { 452 WTF_MAKE_NONCOPYABLE(FragmentationDisabler); 453public: 454 FragmentationDisabler(RenderObject* root); 455 ~FragmentationDisabler(); 456private: 457 RenderObject* m_root; 458 RenderObject::FlowThreadState m_flowThreadState; 459 bool m_fragmenting; 460#ifndef NDEBUG 461 LayoutState* m_layoutState; 462#endif 463}; 464 465} // namespace WebCore 466 467#endif // RenderView_h 468