1/*
2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
3 * (C) 2000 Antti Koivisto (koivisto@kde.org)
4 * (C) 2000 Dirk Mueller (mueller@kde.org)
5 * (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
6 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012 Apple Inc. All rights reserved.
7 * Copyright (C) 2009 Google Inc. All rights reserved.
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
18 *
19 * You should have received a copy of the GNU Library General Public License
20 * along with this library; see the file COPYING.LIB. If not, write to
21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23 *
24 */
25
26#pragma once
27
28#include "CachedImageClient.h"
29#include "Element.h"
30#include "FloatQuad.h"
31#include "Frame.h"
32#include "LayoutRect.h"
33#include "Page.h"
34#include "RenderObjectEnums.h"
35#include "RenderStyle.h"
36#include "ScrollAlignment.h"
37#include "StyleImage.h"
38#include "TextAffinity.h"
39#include <wtf/IsoMalloc.h>
40#include <wtf/WeakPtr.h>
41
42namespace WebCore {
43
44class AffineTransform;
45class CSSAnimationController;
46class Color;
47class Cursor;
48class Document;
49class DocumentTimeline;
50class HitTestLocation;
51class HitTestRequest;
52class HitTestResult;
53class InlineBox;
54class Path;
55class Position;
56class PseudoStyleRequest;
57class RenderBoxModelObject;
58class RenderInline;
59class RenderBlock;
60class RenderElement;
61class RenderFragmentedFlow;
62class RenderGeometryMap;
63class RenderLayer;
64class RenderLayerModelObject;
65class RenderFragmentContainer;
66class RenderTheme;
67class RenderTreeBuilder;
68class SelectionRangeData;
69class TransformState;
70class VisiblePosition;
71
72#if PLATFORM(IOS_FAMILY)
73class SelectionRect;
74#endif
75
76struct PaintInfo;
77
78#if PLATFORM(IOS_FAMILY)
79const int caretWidth = 2; // This value should be kept in sync with UIKit. See <rdar://problem/15580601>.
80#else
81const int caretWidth = 1;
82#endif
83
84enum class ShouldAllowCrossOriginScrolling { No, Yes };
85
86struct ScrollRectToVisibleOptions;
87
88// Base class for all rendering tree objects.
89class RenderObject : public CachedImageClient, public CanMakeWeakPtr<RenderObject> {
90 WTF_MAKE_ISO_ALLOCATED(RenderObject);
91 friend class RenderBlock;
92 friend class RenderBlockFlow;
93 friend class RenderElement;
94 friend class RenderLayer;
95public:
96 // Anonymous objects should pass the document as their node, and they will then automatically be
97 // marked as anonymous in the constructor.
98 explicit RenderObject(Node&);
99 virtual ~RenderObject();
100
101 RenderTheme& theme() const;
102
103 virtual const char* renderName() const = 0;
104
105 RenderElement* parent() const { return m_parent; }
106 bool isDescendantOf(const RenderObject*) const;
107
108 RenderObject* previousSibling() const { return m_previous; }
109 RenderObject* nextSibling() const { return m_next; }
110
111 // Use RenderElement versions instead.
112 virtual RenderObject* firstChildSlow() const { return nullptr; }
113 virtual RenderObject* lastChildSlow() const { return nullptr; }
114
115 RenderObject* nextInPreOrder() const;
116 RenderObject* nextInPreOrder(const RenderObject* stayWithin) const;
117 RenderObject* nextInPreOrderAfterChildren() const;
118 RenderObject* nextInPreOrderAfterChildren(const RenderObject* stayWithin) const;
119 RenderObject* previousInPreOrder() const;
120 RenderObject* previousInPreOrder(const RenderObject* stayWithin) const;
121 WEBCORE_EXPORT RenderObject* childAt(unsigned) const;
122
123 RenderObject* firstLeafChild() const;
124 RenderObject* lastLeafChild() const;
125
126#if ENABLE(TEXT_AUTOSIZING)
127 // Minimal distance between the block with fixed height and overflowing content and the text block to apply text autosizing.
128 // The greater this constant is the more potential places we have where autosizing is turned off.
129 // So it should be as low as possible. There are sites that break at 2.
130 static const int TextAutoSizingFixedHeightDepth = 3;
131
132 enum BlockContentHeightType {
133 FixedHeight,
134 FlexibleHeight,
135 OverflowHeight
136 };
137
138 typedef BlockContentHeightType (*HeightTypeTraverseNextInclusionFunction)(const RenderObject&);
139 RenderObject* traverseNext(const RenderObject* stayWithin, HeightTypeTraverseNextInclusionFunction, int& currentDepth, int& newFixedDepth) const;
140#endif
141
142 WEBCORE_EXPORT RenderLayer* enclosingLayer() const;
143
144 // Scrolling is a RenderBox concept, however some code just cares about recursively scrolling our enclosing ScrollableArea(s).
145 WEBCORE_EXPORT bool scrollRectToVisible(const LayoutRect& absoluteRect, bool insideFixed, const ScrollRectToVisibleOptions&);
146
147 // Convenience function for getting to the nearest enclosing box of a RenderObject.
148 WEBCORE_EXPORT RenderBox& enclosingBox() const;
149 RenderBoxModelObject& enclosingBoxModelObject() const;
150 const RenderBox* enclosingScrollableContainerForSnapping() const;
151
152 // Function to return our enclosing flow thread if we are contained inside one. This
153 // function follows the containing block chain.
154 RenderFragmentedFlow* enclosingFragmentedFlow() const
155 {
156 if (fragmentedFlowState() == NotInsideFragmentedFlow)
157 return nullptr;
158
159 return locateEnclosingFragmentedFlow();
160 }
161
162 WEBCORE_EXPORT bool useDarkAppearance() const;
163 OptionSet<StyleColor::Options> styleColorOptions() const;
164
165#ifndef NDEBUG
166 void setHasAXObject(bool flag) { m_hasAXObject = flag; }
167 bool hasAXObject() const { return m_hasAXObject; }
168
169 // Helper class forbidding calls to setNeedsLayout() during its lifetime.
170 class SetLayoutNeededForbiddenScope {
171 public:
172 explicit SetLayoutNeededForbiddenScope(RenderObject*, bool isForbidden = true);
173 ~SetLayoutNeededForbiddenScope();
174 private:
175 RenderObject* m_renderObject;
176 bool m_preexistingForbidden;
177 };
178#endif
179
180 // Obtains the nearest enclosing block (including this block) that contributes a first-line style to our inline
181 // children.
182 virtual RenderBlock* firstLineBlock() const;
183
184 // RenderObject tree manipulation
185 //////////////////////////////////////////
186 virtual bool canHaveChildren() const = 0;
187 virtual bool canHaveGeneratedChildren() const;
188 virtual bool createsAnonymousWrapper() const { return false; }
189 //////////////////////////////////////////
190
191#if ENABLE(TREE_DEBUGGING)
192 void showNodeTreeForThis() const;
193 void showRenderTreeForThis() const;
194 void showLineTreeForThis() const;
195
196 void outputRenderObject(WTF::TextStream&, bool mark, int depth) const;
197 void outputRenderSubTreeAndMark(WTF::TextStream&, const RenderObject* markedObject, int depth) const;
198 void outputRegionsInformation(WTF::TextStream&) const;
199#endif
200
201 bool isPseudoElement() const { return node() && node()->isPseudoElement(); }
202
203 bool isRenderElement() const { return !isText(); }
204 bool isRenderReplaced() const;
205 bool isBoxModelObject() const;
206 bool isRenderBlock() const;
207 bool isRenderBlockFlow() const;
208 bool isRenderInline() const;
209 bool isRenderLayerModelObject() const;
210
211 virtual bool isCounter() const { return false; }
212 virtual bool isQuote() const { return false; }
213
214 virtual bool isDetailsMarker() const { return false; }
215 virtual bool isEmbeddedObject() const { return false; }
216 bool isFieldset() const;
217 virtual bool isFileUploadControl() const { return false; }
218 virtual bool isFrame() const { return false; }
219 virtual bool isFrameSet() const { return false; }
220 virtual bool isImage() const { return false; }
221 virtual bool isInlineBlockOrInlineTable() const { return false; }
222 virtual bool isListBox() const { return false; }
223 virtual bool isListItem() const { return false; }
224 virtual bool isListMarker() const { return false; }
225 virtual bool isMedia() const { return false; }
226 virtual bool isMenuList() const { return false; }
227#if ENABLE(METER_ELEMENT)
228 virtual bool isMeter() const { return false; }
229#endif
230 virtual bool isSnapshottedPlugIn() const { return false; }
231 virtual bool isProgress() const { return false; }
232 virtual bool isRenderButton() const { return false; }
233 virtual bool isRenderIFrame() const { return false; }
234 virtual bool isRenderImage() const { return false; }
235 virtual bool isRenderFragmentContainer() const { return false; }
236 virtual bool isReplica() const { return false; }
237
238 virtual bool isRubyInline() const { return false; }
239 virtual bool isRubyBlock() const { return false; }
240 virtual bool isRubyBase() const { return false; }
241 virtual bool isRubyRun() const { return false; }
242 virtual bool isRubyText() const { return false; }
243
244 virtual bool isSlider() const { return false; }
245 virtual bool isSliderThumb() const { return false; }
246 virtual bool isTable() const { return false; }
247 virtual bool isTableCell() const { return false; }
248 virtual bool isRenderTableCol() const { return false; }
249 virtual bool isTableCaption() const { return false; }
250 virtual bool isTableRow() const { return false; }
251 virtual bool isTableSection() const { return false; }
252 virtual bool isTextControl() const { return false; }
253 virtual bool isTextArea() const { return false; }
254 virtual bool isTextField() const { return false; }
255 virtual bool isSearchField() const { return false; }
256 virtual bool isTextControlInnerBlock() const { return false; }
257 virtual bool isVideo() const { return false; }
258 virtual bool isWidget() const { return false; }
259 virtual bool isCanvas() const { return false; }
260#if ENABLE(ATTACHMENT_ELEMENT)
261 virtual bool isAttachment() const { return false; }
262#endif
263#if ENABLE(FULLSCREEN_API)
264 virtual bool isRenderFullScreen() const { return false; }
265 virtual bool isRenderFullScreenPlaceholder() const { return false; }
266#endif
267 virtual bool isRenderGrid() const { return false; }
268 bool isInFlowRenderFragmentedFlow() const { return isRenderFragmentedFlow() && !isOutOfFlowPositioned(); }
269 bool isOutOfFlowRenderFragmentedFlow() const { return isRenderFragmentedFlow() && isOutOfFlowPositioned(); }
270
271 virtual bool isMultiColumnBlockFlow() const { return false; }
272 virtual bool isRenderMultiColumnSet() const { return false; }
273 virtual bool isRenderMultiColumnFlow() const { return false; }
274 virtual bool isRenderMultiColumnSpannerPlaceholder() const { return false; }
275
276 virtual bool isRenderScrollbarPart() const { return false; }
277
278 bool isDocumentElementRenderer() const { return document().documentElement() == &m_node; }
279 bool isBody() const { return node() && node()->hasTagName(HTMLNames::bodyTag); }
280 bool isHR() const { return node() && node()->hasTagName(HTMLNames::hrTag); }
281 bool isLegend() const;
282
283 bool isHTMLMarquee() const;
284
285 bool isTablePart() const { return isTableCell() || isRenderTableCol() || isTableCaption() || isTableRow() || isTableSection(); }
286
287 inline bool isBeforeContent() const;
288 inline bool isAfterContent() const;
289 inline bool isBeforeOrAfterContent() const;
290 static inline bool isBeforeContent(const RenderObject* obj) { return obj && obj->isBeforeContent(); }
291 static inline bool isAfterContent(const RenderObject* obj) { return obj && obj->isAfterContent(); }
292 static inline bool isBeforeOrAfterContent(const RenderObject* obj) { return obj && obj->isBeforeOrAfterContent(); }
293
294 bool beingDestroyed() const { return m_bitfields.beingDestroyed(); }
295
296 bool everHadLayout() const { return m_bitfields.everHadLayout(); }
297
298 bool childrenInline() const { return m_bitfields.childrenInline(); }
299 void setChildrenInline(bool b) { m_bitfields.setChildrenInline(b); }
300
301 enum FragmentedFlowState {
302 NotInsideFragmentedFlow = 0,
303 InsideInFragmentedFlow = 1,
304 };
305
306 void setFragmentedFlowStateIncludingDescendants(FragmentedFlowState);
307
308 FragmentedFlowState fragmentedFlowState() const { return m_bitfields.fragmentedFlowState(); }
309 void setFragmentedFlowState(FragmentedFlowState state) { m_bitfields.setFragmentedFlowState(state); }
310
311#if ENABLE(MATHML)
312 virtual bool isRenderMathMLBlock() const { return false; }
313 virtual bool isRenderMathMLTable() const { return false; }
314 virtual bool isRenderMathMLOperator() const { return false; }
315 virtual bool isRenderMathMLRow() const { return false; }
316 virtual bool isRenderMathMLMath() const { return false; }
317 virtual bool isRenderMathMLMenclose() const { return false; }
318 virtual bool isRenderMathMLFenced() const { return false; }
319 virtual bool isRenderMathMLFencedOperator() const { return false; }
320 virtual bool isRenderMathMLFraction() const { return false; }
321 virtual bool isRenderMathMLPadded() const { return false; }
322 virtual bool isRenderMathMLRoot() const { return false; }
323 virtual bool isRenderMathMLSpace() const { return false; }
324 virtual bool isRenderMathMLSquareRoot() const { return false; }
325 virtual bool isRenderMathMLScripts() const { return false; }
326 virtual bool isRenderMathMLToken() const { return false; }
327 virtual bool isRenderMathMLUnderOver() const { return false; }
328#endif // ENABLE(MATHML)
329
330 // FIXME: Until all SVG renders can be subclasses of RenderSVGModelObject we have
331 // to add SVG renderer methods to RenderObject with an ASSERT_NOT_REACHED() default implementation.
332 virtual bool isRenderSVGModelObject() const { return false; }
333 virtual bool isRenderSVGBlock() const { return false; };
334 virtual bool isSVGRoot() const { return false; }
335 virtual bool isSVGContainer() const { return false; }
336 virtual bool isSVGTransformableContainer() const { return false; }
337 virtual bool isSVGViewportContainer() const { return false; }
338 virtual bool isSVGGradientStop() const { return false; }
339 virtual bool isSVGHiddenContainer() const { return false; }
340 virtual bool isSVGPath() const { return false; }
341 virtual bool isSVGShape() const { return false; }
342 virtual bool isSVGText() const { return false; }
343 virtual bool isSVGTextPath() const { return false; }
344 virtual bool isSVGTSpan() const { return false; }
345 virtual bool isSVGInline() const { return false; }
346 virtual bool isSVGInlineText() const { return false; }
347 virtual bool isSVGImage() const { return false; }
348 virtual bool isSVGForeignObject() const { return false; }
349 virtual bool isSVGResourceContainer() const { return false; }
350 virtual bool isSVGResourceFilter() const { return false; }
351 virtual bool isSVGResourceClipper() const { return false; }
352 virtual bool isSVGResourceFilterPrimitive() const { return false; }
353
354 // FIXME: Those belong into a SVG specific base-class for all renderers (see above)
355 // Unfortunately we don't have such a class yet, because it's not possible for all renderers
356 // to inherit from RenderSVGObject -> RenderObject (some need RenderBlock inheritance for instance)
357 virtual void setNeedsTransformUpdate() { }
358 virtual void setNeedsBoundariesUpdate();
359 virtual bool needsBoundariesUpdate() { return false; }
360
361 // Per SVG 1.1 objectBoundingBox ignores clipping, masking, filter effects, opacity and stroke-width.
362 // This is used for all computation of objectBoundingBox relative units and by SVGLocatable::getBBox().
363 // NOTE: Markers are not specifically ignored here by SVG 1.1 spec, but we ignore them
364 // since stroke-width is ignored (and marker size can depend on stroke-width).
365 // objectBoundingBox is returned local coordinates.
366 // The name objectBoundingBox is taken from the SVG 1.1 spec.
367 virtual FloatRect objectBoundingBox() const;
368 virtual FloatRect strokeBoundingBox() const;
369
370 // Returns the smallest rectangle enclosing all of the painted content
371 // respecting clipping, masking, filters, opacity, stroke-width and markers
372 virtual FloatRect repaintRectInLocalCoordinates() const;
373
374 // This only returns the transform="" value from the element
375 // most callsites want localToParentTransform() instead.
376 virtual AffineTransform localTransform() const;
377
378 // Returns the full transform mapping from local coordinates to local coords for the parent SVG renderer
379 // This includes any viewport transforms and x/y offsets as well as the transform="" value off the element.
380 virtual const AffineTransform& localToParentTransform() const;
381
382 // SVG uses FloatPoint precise hit testing, and passes the point in parent
383 // coordinates instead of in repaint container coordinates. Eventually the
384 // rest of the rendering tree will move to a similar model.
385 virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
386
387 bool hasAspectRatio() const { return isReplaced() && (isImage() || isVideo() || isCanvas()); }
388 bool isAnonymous() const { return m_bitfields.isAnonymous(); }
389 bool isAnonymousBlock() const
390 {
391 // This function is kept in sync with anonymous block creation conditions in
392 // RenderBlock::createAnonymousBlock(). This includes creating an anonymous
393 // RenderBlock having a DisplayType::Block or DisplayType::Box display. Other classes such as RenderTextFragment
394 // are not RenderBlocks and will return false. See https://bugs.webkit.org/show_bug.cgi?id=56709.
395 return isAnonymous() && (style().display() == DisplayType::Block || style().display() == DisplayType::Box) && style().styleType() == PseudoId::None && isRenderBlock() && !isListMarker() && !isRenderFragmentedFlow() && !isRenderMultiColumnSet() && !isRenderView()
396#if ENABLE(FULLSCREEN_API)
397 && !isRenderFullScreen()
398 && !isRenderFullScreenPlaceholder()
399#endif
400#if ENABLE(MATHML)
401 && !isRenderMathMLBlock()
402#endif
403 ;
404 }
405
406 bool isFloating() const { return m_bitfields.floating(); }
407
408 bool isPositioned() const { return m_bitfields.isPositioned(); }
409 bool isInFlowPositioned() const { return m_bitfields.isRelativelyPositioned() || m_bitfields.isStickilyPositioned(); }
410 bool isOutOfFlowPositioned() const { return m_bitfields.isOutOfFlowPositioned(); } // absolute or fixed positioning
411 bool isFixedPositioned() const { return isOutOfFlowPositioned() && style().position() == PositionType::Fixed; }
412 bool isAbsolutelyPositioned() const { return isOutOfFlowPositioned() && style().position() == PositionType::Absolute; }
413 bool isRelativelyPositioned() const { return m_bitfields.isRelativelyPositioned(); }
414 bool isStickilyPositioned() const { return m_bitfields.isStickilyPositioned(); }
415
416 bool isText() const { return !m_bitfields.isBox() && m_bitfields.isTextOrRenderView(); }
417 bool isLineBreak() const { return m_bitfields.isLineBreak(); }
418 bool isBR() const { return isLineBreak() && !isWBR(); }
419 bool isLineBreakOpportunity() const { return isLineBreak() && isWBR(); }
420 bool isTextOrLineBreak() const { return isText() || isLineBreak(); }
421 bool isBox() const { return m_bitfields.isBox(); }
422 bool isRenderView() const { return m_bitfields.isBox() && m_bitfields.isTextOrRenderView(); }
423 bool isInline() const { return m_bitfields.isInline(); } // inline object
424 bool isReplaced() const { return m_bitfields.isReplaced(); } // a "replaced" element (see CSS)
425 bool isHorizontalWritingMode() const { return m_bitfields.horizontalWritingMode(); }
426
427 bool isDragging() const { return m_bitfields.hasRareData() && rareData().isDragging(); }
428 bool hasReflection() const { return m_bitfields.hasRareData() && rareData().hasReflection(); }
429 bool isRenderFragmentedFlow() const { return m_bitfields.hasRareData() && rareData().isRenderFragmentedFlow(); }
430 bool hasOutlineAutoAncestor() const { return m_bitfields.hasRareData() && rareData().hasOutlineAutoAncestor(); }
431
432 bool isExcludedFromNormalLayout() const { return m_bitfields.isExcludedFromNormalLayout(); }
433 void setIsExcludedFromNormalLayout(bool excluded) { m_bitfields.setIsExcludedFromNormalLayout(excluded); }
434 bool isExcludedAndPlacedInBorder() const { return isExcludedFromNormalLayout() && isLegend(); }
435
436 bool hasLayer() const { return m_bitfields.hasLayer(); }
437
438 enum BoxDecorationState {
439 NoBoxDecorations,
440 HasBoxDecorationsAndBackgroundObscurationStatusInvalid,
441 HasBoxDecorationsAndBackgroundIsKnownToBeObscured,
442 HasBoxDecorationsAndBackgroundMayBeVisible,
443 };
444 bool hasVisibleBoxDecorations() const { return m_bitfields.boxDecorationState() != NoBoxDecorations; }
445 bool backgroundIsKnownToBeObscured(const LayoutPoint& paintOffset);
446
447 bool needsLayout() const
448 {
449 return m_bitfields.needsLayout() || m_bitfields.normalChildNeedsLayout() || m_bitfields.posChildNeedsLayout()
450 || m_bitfields.needsSimplifiedNormalFlowLayout() || m_bitfields.needsPositionedMovementLayout();
451 }
452
453 bool selfNeedsLayout() const { return m_bitfields.needsLayout(); }
454 bool needsPositionedMovementLayout() const { return m_bitfields.needsPositionedMovementLayout(); }
455 bool needsPositionedMovementLayoutOnly() const
456 {
457 return m_bitfields.needsPositionedMovementLayout() && !m_bitfields.needsLayout() && !m_bitfields.normalChildNeedsLayout()
458 && !m_bitfields.posChildNeedsLayout() && !m_bitfields.needsSimplifiedNormalFlowLayout();
459 }
460
461 bool posChildNeedsLayout() const { return m_bitfields.posChildNeedsLayout(); }
462 bool needsSimplifiedNormalFlowLayout() const { return m_bitfields.needsSimplifiedNormalFlowLayout(); }
463 bool needsSimplifiedNormalFlowLayoutOnly() const;
464 bool normalChildNeedsLayout() const { return m_bitfields.normalChildNeedsLayout(); }
465
466 bool preferredLogicalWidthsDirty() const { return m_bitfields.preferredLogicalWidthsDirty(); }
467
468 bool isSelectionBorder() const;
469
470 bool hasOverflowClip() const { return m_bitfields.hasOverflowClip(); }
471
472 bool hasTransformRelatedProperty() const { return m_bitfields.hasTransformRelatedProperty(); } // Transform, perspective or transform-style: preserve-3d.
473 bool hasTransform() const { return hasTransformRelatedProperty() && style().hasTransform(); }
474
475 inline bool preservesNewline() const;
476
477 virtual void updateDragState(bool dragOn);
478
479 RenderView& view() const { return *document().renderView(); };
480
481 // Returns true if this renderer is rooted.
482 bool isRooted() const;
483
484 Node* node() const { return isAnonymous() ? nullptr : &m_node; }
485 Node* nonPseudoNode() const { return isPseudoElement() ? nullptr : node(); }
486
487 // Returns the styled node that caused the generation of this renderer.
488 // This is the same as node() except for renderers of :before and :after
489 // pseudo elements for which their parent node is returned.
490 Node* generatingNode() const { return isPseudoElement() ? generatingPseudoHostElement() : node(); }
491
492 Document& document() const { return m_node.document(); }
493 Frame& frame() const;
494 Page& page() const;
495 Settings& settings() const { return page().settings(); }
496
497 // Returns the object containing this one. Can be different from parent for positioned elements.
498 // If repaintContainer and repaintContainerSkipped are not null, on return *repaintContainerSkipped
499 // is true if the renderer returned is an ancestor of repaintContainer.
500 RenderElement* container() const;
501 RenderElement* container(const RenderLayerModelObject* repaintContainer, bool& repaintContainerSkipped) const;
502
503 RenderBoxModelObject* offsetParent() const;
504
505 void markContainingBlocksForLayout(ScheduleRelayout = ScheduleRelayout::Yes, RenderElement* newRoot = nullptr);
506 void setNeedsLayout(MarkingBehavior = MarkContainingBlockChain);
507 void clearNeedsLayout();
508 void setPreferredLogicalWidthsDirty(bool, MarkingBehavior = MarkContainingBlockChain);
509 void invalidateContainerPreferredLogicalWidths();
510
511 void setNeedsLayoutAndPrefWidthsRecalc()
512 {
513 setNeedsLayout();
514 setPreferredLogicalWidthsDirty(true);
515 }
516
517 void setPositionState(PositionType position)
518 {
519 ASSERT((position != PositionType::Absolute && position != PositionType::Fixed) || isBox());
520 m_bitfields.setPositionedState(static_cast<int>(position));
521 }
522 void clearPositionedState() { m_bitfields.clearPositionedState(); }
523
524 void setFloating(bool b = true) { m_bitfields.setFloating(b); }
525 void setInline(bool b = true) { m_bitfields.setIsInline(b); }
526
527 void setHasVisibleBoxDecorations(bool = true);
528 void invalidateBackgroundObscurationStatus();
529 virtual bool computeBackgroundIsKnownToBeObscured(const LayoutPoint&) { return false; }
530
531 void setIsText() { ASSERT(!isBox()); m_bitfields.setIsTextOrRenderView(true); }
532 void setIsLineBreak() { m_bitfields.setIsLineBreak(true); }
533 void setIsBox() { m_bitfields.setIsBox(true); }
534 void setIsRenderView() { ASSERT(isBox()); m_bitfields.setIsTextOrRenderView(true); }
535 void setReplaced(bool b = true) { m_bitfields.setIsReplaced(b); }
536 void setHorizontalWritingMode(bool b = true) { m_bitfields.setHorizontalWritingMode(b); }
537 void setHasOverflowClip(bool b = true) { m_bitfields.setHasOverflowClip(b); }
538 void setHasLayer(bool b = true) { m_bitfields.setHasLayer(b); }
539 void setHasTransformRelatedProperty(bool b = true) { m_bitfields.setHasTransformRelatedProperty(b); }
540
541 void setIsDragging(bool);
542 void setHasReflection(bool = true);
543 void setIsRenderFragmentedFlow(bool = true);
544 void setHasOutlineAutoAncestor(bool = true);
545
546 // Hook so that RenderTextControl can return the line height of its inner renderer.
547 // For other renderers, the value is the same as lineHeight(false).
548 virtual int innerLineHeight() const;
549
550 // used for element state updates that cannot be fixed with a
551 // repaint and do not need a relayout
552 virtual void updateFromElement() { }
553
554 bool isComposited() const;
555
556 bool hitTest(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestFilter = HitTestAll);
557 virtual void updateHitTestResult(HitTestResult&, const LayoutPoint&);
558 virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
559
560 virtual Position positionForPoint(const LayoutPoint&);
561 virtual VisiblePosition positionForPoint(const LayoutPoint&, const RenderFragmentContainer*);
562 VisiblePosition createVisiblePosition(int offset, EAffinity) const;
563 VisiblePosition createVisiblePosition(const Position&) const;
564
565 // returns the containing block level element for this element.
566 WEBCORE_EXPORT RenderBlock* containingBlock() const;
567 RenderBlock* containingBlockForObjectInFlow() const;
568
569 // Convert the given local point to absolute coordinates. If MapCoordinatesFlags includes UseTransforms, take transforms into account.
570 WEBCORE_EXPORT FloatPoint localToAbsolute(const FloatPoint& localPoint = FloatPoint(), MapCoordinatesFlags = 0, bool* wasFixed = nullptr) const;
571 FloatPoint absoluteToLocal(const FloatPoint&, MapCoordinatesFlags = 0) const;
572
573 // Convert a local quad to absolute coordinates, taking transforms into account.
574 FloatQuad localToAbsoluteQuad(const FloatQuad& quad, MapCoordinatesFlags mode = UseTransforms, bool* wasFixed = nullptr) const
575 {
576 return localToContainerQuad(quad, nullptr, mode, wasFixed);
577 }
578 // Convert an absolute quad to local coordinates.
579 FloatQuad absoluteToLocalQuad(const FloatQuad&, MapCoordinatesFlags mode = UseTransforms) const;
580
581 // Convert a local quad into the coordinate system of container, taking transforms into account.
582 WEBCORE_EXPORT FloatQuad localToContainerQuad(const FloatQuad&, const RenderLayerModelObject* repaintContainer, MapCoordinatesFlags = UseTransforms, bool* wasFixed = nullptr) const;
583 WEBCORE_EXPORT FloatPoint localToContainerPoint(const FloatPoint&, const RenderLayerModelObject* repaintContainer, MapCoordinatesFlags = UseTransforms, bool* wasFixed = nullptr) const;
584
585 // Return the offset from the container() renderer (excluding transforms). In multi-column layout,
586 // different offsets apply at different points, so return the offset that applies to the given point.
587 virtual LayoutSize offsetFromContainer(RenderElement&, const LayoutPoint&, bool* offsetDependsOnPoint = nullptr) const;
588 // Return the offset from an object up the container() chain. Asserts that none of the intermediate objects have transforms.
589 LayoutSize offsetFromAncestorContainer(RenderElement&) const;
590
591#if PLATFORM(IOS_FAMILY)
592 virtual void collectSelectionRects(Vector<SelectionRect>&, unsigned startOffset = 0, unsigned endOffset = std::numeric_limits<unsigned>::max());
593 virtual void absoluteQuadsForSelection(Vector<FloatQuad>& quads) const { absoluteQuads(quads); }
594#endif
595
596 virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint&) const { }
597
598 // FIXME: useTransforms should go away eventually
599 WEBCORE_EXPORT IntRect absoluteBoundingBoxRect(bool useTransform = true, bool* wasFixed = nullptr) const;
600 IntRect absoluteBoundingBoxRectIgnoringTransforms() const { return absoluteBoundingBoxRect(false); }
601
602 // Build an array of quads in absolute coords for line boxes
603 virtual void absoluteQuads(Vector<FloatQuad>&, bool* /*wasFixed*/ = nullptr) const { }
604
605 virtual void absoluteFocusRingQuads(Vector<FloatQuad>&);
606
607 static FloatRect absoluteBoundingBoxRectForRange(const Range*);
608
609 // the rect that will be painted if this object is passed as the paintingRoot
610 WEBCORE_EXPORT LayoutRect paintingRootRect(LayoutRect& topLevelRect);
611
612 virtual LayoutUnit minPreferredLogicalWidth() const { return 0; }
613 virtual LayoutUnit maxPreferredLogicalWidth() const { return 0; }
614
615 const RenderStyle& style() const;
616 const RenderStyle& firstLineStyle() const;
617
618 // Anonymous blocks that are part of of a continuation chain will return their inline continuation's outline style instead.
619 // This is typically only relevant when repainting.
620 virtual const RenderStyle& outlineStyleForRepaint() const { return style(); }
621
622 virtual CursorDirective getCursor(const LayoutPoint&, Cursor&) const;
623
624 // Return the RenderLayerModelObject in the container chain which is responsible for painting this object, or nullptr
625 // if painting is root-relative. This is the container that should be passed to the 'forRepaint'
626 // methods.
627 RenderLayerModelObject* containerForRepaint() const;
628 // Actually do the repaint of rect r for this object which has been computed in the coordinate space
629 // of repaintContainer. If repaintContainer is nullptr, repaint via the view.
630 void repaintUsingContainer(const RenderLayerModelObject* repaintContainer, const LayoutRect&, bool shouldClipToLayer = true) const;
631
632 // Repaint the entire object. Called when, e.g., the color of a border changes, or when a border
633 // style changes.
634 void repaint() const;
635
636 // Repaint a specific subrectangle within a given object. The rect |r| is in the object's coordinate space.
637 WEBCORE_EXPORT void repaintRectangle(const LayoutRect&, bool shouldClipToLayer = true) const;
638
639 // Repaint a slow repaint object, which, at this time, means we are repainting an object with background-attachment:fixed.
640 void repaintSlowRepaintObject() const;
641
642 // Returns the rect that should be repainted whenever this object changes. The rect is in the view's
643 // coordinate space. This method deals with outlines and overflow.
644 LayoutRect absoluteClippedOverflowRect() const
645 {
646 return clippedOverflowRectForRepaint(nullptr);
647 }
648 WEBCORE_EXPORT IntRect pixelSnappedAbsoluteClippedOverflowRect() const;
649 virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const;
650 virtual LayoutRect rectWithOutlineForRepaint(const RenderLayerModelObject* repaintContainer, LayoutUnit outlineWidth) const;
651 virtual LayoutRect outlineBoundsForRepaint(const RenderLayerModelObject* /*repaintContainer*/, const RenderGeometryMap* = nullptr) const { return LayoutRect(); }
652
653 // Given a rect in the object's coordinate space, compute a rect suitable for repainting
654 // that rect in view coordinates.
655 LayoutRect computeAbsoluteRepaintRect(const LayoutRect& r) const
656 {
657 return computeRectForRepaint(r, nullptr);
658 }
659 // Given a rect in the object's coordinate space, compute a rect suitable for repainting
660 // that rect in the coordinate space of repaintContainer.
661 LayoutRect computeRectForRepaint(const LayoutRect&, const RenderLayerModelObject* repaintContainer) const;
662 FloatRect computeFloatRectForRepaint(const FloatRect&, const RenderLayerModelObject* repaintContainer) const;
663
664 // Given a rect in the object's coordinate space, compute the location in container space where this rect is visible,
665 // when clipping and scrolling as specified by the context. When using edge-inclusive intersection, return WTF::nullopt
666 // rather than an empty rect if the rect is completely clipped out in container space.
667 enum class VisibleRectContextOption {
668 UseEdgeInclusiveIntersection = 1 << 0,
669 ApplyCompositedClips = 1 << 1,
670 ApplyCompositedContainerScrolls = 1 << 2,
671 ApplyContainerClip = 1 << 3,
672 };
673 struct VisibleRectContext {
674 VisibleRectContext(bool hasPositionFixedDescendant = false, bool dirtyRectIsFlipped = false, OptionSet<VisibleRectContextOption> options = { })
675 : m_hasPositionFixedDescendant(hasPositionFixedDescendant)
676 , m_dirtyRectIsFlipped(dirtyRectIsFlipped)
677 , m_options(options)
678 {
679 }
680 bool m_hasPositionFixedDescendant;
681 bool m_dirtyRectIsFlipped;
682 OptionSet<VisibleRectContextOption> m_options;
683 };
684 virtual Optional<LayoutRect> computeVisibleRectInContainer(const LayoutRect&, const RenderLayerModelObject* repaintContainer, VisibleRectContext) const;
685 virtual Optional<FloatRect> computeFloatVisibleRectInContainer(const FloatRect&, const RenderLayerModelObject* repaintContainer, VisibleRectContext) const;
686
687 virtual unsigned int length() const { return 1; }
688
689 bool isFloatingOrOutOfFlowPositioned() const { return (isFloating() || isOutOfFlowPositioned()); }
690
691 enum SelectionState {
692 SelectionNone, // The object is not selected.
693 SelectionStart, // The object either contains the start of a selection run or is the start of a run
694 SelectionInside, // The object is fully encompassed by a selection run
695 SelectionEnd, // The object either contains the end of a selection run or is the end of a run
696 SelectionBoth // The object contains an entire run or is the sole selected object in that run
697 };
698
699 // The current selection state for an object. For blocks, the state refers to the state of the leaf
700 // descendants (as described above in the SelectionState enum declaration).
701 SelectionState selectionState() const { return m_bitfields.selectionState(); }
702 virtual void setSelectionState(SelectionState state) { m_bitfields.setSelectionState(state); }
703 inline void setSelectionStateIfNeeded(SelectionState);
704 bool canUpdateSelectionOnRootLineBoxes();
705
706 // A single rectangle that encompasses all of the selected objects within this object. Used to determine the tightest
707 // possible bounding box for the selection.
708 LayoutRect selectionRect(bool clipToVisibleContent = true) { return selectionRectForRepaint(nullptr, clipToVisibleContent); }
709 virtual LayoutRect selectionRectForRepaint(const RenderLayerModelObject* /*repaintContainer*/, bool /*clipToVisibleContent*/ = true) { return LayoutRect(); }
710
711 virtual bool canBeSelectionLeaf() const { return false; }
712
713 // Whether or not a given block needs to paint selection gaps.
714 virtual bool shouldPaintSelectionGaps() const { return false; }
715
716 /**
717 * Returns the local coordinates of the caret within this render object.
718 * @param caretOffset zero-based offset determining position within the render object.
719 * @param extraWidthToEndOfLine optional out arg to give extra width to end of line -
720 * useful for character range rect computations
721 */
722 virtual LayoutRect localCaretRect(InlineBox*, unsigned caretOffset, LayoutUnit* extraWidthToEndOfLine = nullptr);
723
724 // When performing a global document tear-down, or when going into the page cache, the renderer of the document is cleared.
725 bool renderTreeBeingDestroyed() const;
726
727 void destroy();
728
729 // Virtual function helpers for the deprecated Flexible Box Layout (display: -webkit-box).
730 virtual bool isDeprecatedFlexibleBox() const { return false; }
731
732 // Virtual function helper for the new FlexibleBox Layout (display: -webkit-flex).
733 virtual bool isFlexibleBox() const { return false; }
734
735 bool isFlexibleBoxIncludingDeprecated() const
736 {
737 return isFlexibleBox() || isDeprecatedFlexibleBox();
738 }
739
740 virtual bool isCombineText() const { return false; }
741
742 virtual int caretMinOffset() const;
743 virtual int caretMaxOffset() const;
744
745 virtual int previousOffset(int current) const;
746 virtual int previousOffsetForBackwardDeletion(int current) const;
747 virtual int nextOffset(int current) const;
748
749 void imageChanged(CachedImage*, const IntRect* = nullptr) override;
750 virtual void imageChanged(WrappedImagePtr, const IntRect* = nullptr) { }
751
752 CSSAnimationController& animation() const;
753 DocumentTimeline* documentTimeline() const;
754
755 // Map points and quads through elements, potentially via 3d transforms. You should never need to call these directly; use
756 // localToAbsolute/absoluteToLocal methods instead.
757 virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags, bool* wasFixed = nullptr) const;
758 virtual void mapAbsoluteToLocalPoint(MapCoordinatesFlags, TransformState&) const;
759
760 // Pushes state onto RenderGeometryMap about how to map coordinates from this renderer to its container, or ancestorToStopAt (whichever is encountered first).
761 // Returns the renderer which was mapped to (container or ancestorToStopAt).
762 virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const;
763
764 bool shouldUseTransformFromContainer(const RenderObject* container) const;
765 void getTransformFromContainer(const RenderObject* container, const LayoutSize& offsetInContainer, TransformationMatrix&) const;
766
767 virtual void addFocusRingRects(Vector<LayoutRect>&, const LayoutPoint& /* additionalOffset */, const RenderLayerModelObject* /* paintContainer */ = nullptr) { };
768
769 LayoutRect absoluteOutlineBounds() const
770 {
771 return outlineBoundsForRepaint(nullptr);
772 }
773
774 virtual void willBeRemovedFromTree();
775 void resetFragmentedFlowStateOnRemoval();
776 void initializeFragmentedFlowStateOnInsertion();
777 virtual void insertedIntoTree();
778
779protected:
780 //////////////////////////////////////////
781 // Helper functions. Dangerous to use!
782 void setPreviousSibling(RenderObject* previous) { m_previous = previous; }
783 void setNextSibling(RenderObject* next) { m_next = next; }
784 void setParent(RenderElement*);
785 //////////////////////////////////////////
786 void addPDFURLRect(PaintInfo&, const LayoutPoint&);
787 Node& nodeForNonAnonymous() const { ASSERT(!isAnonymous()); return m_node; }
788
789 void adjustRectForOutlineAndShadow(LayoutRect&) const;
790
791 virtual void willBeDestroyed();
792
793 void setNeedsPositionedMovementLayoutBit(bool b) { m_bitfields.setNeedsPositionedMovementLayout(b); }
794 void setNormalChildNeedsLayoutBit(bool b) { m_bitfields.setNormalChildNeedsLayout(b); }
795 void setPosChildNeedsLayoutBit(bool b) { m_bitfields.setPosChildNeedsLayout(b); }
796 void setNeedsSimplifiedNormalFlowLayoutBit(bool b) { m_bitfields.setNeedsSimplifiedNormalFlowLayout(b); }
797
798 virtual RenderFragmentedFlow* locateEnclosingFragmentedFlow() const;
799 static void calculateBorderStyleColor(const BorderStyle&, const BoxSide&, Color&);
800
801 static FragmentedFlowState computedFragmentedFlowState(const RenderObject&);
802
803 static bool shouldApplyCompositedContainerScrollsForRepaint();
804
805 static VisibleRectContext visibleRectContextForRepaint();
806
807private:
808#ifndef NDEBUG
809 bool isSetNeedsLayoutForbidden() const { return m_setNeedsLayoutForbidden; }
810 void setNeedsLayoutIsForbidden(bool flag) { m_setNeedsLayoutForbidden = flag; }
811#endif
812
813 void addAbsoluteRectForLayer(LayoutRect& result);
814 void setLayerNeedsFullRepaint();
815 void setLayerNeedsFullRepaintForPositionedMovementLayout();
816
817 Node* generatingPseudoHostElement() const;
818
819 void propagateRepaintToParentWithOutlineAutoIfNeeded(const RenderLayerModelObject& repaintContainer, const LayoutRect& repaintRect) const;
820
821 virtual bool isWBR() const { ASSERT_NOT_REACHED(); return false; }
822
823 void setEverHadLayout(bool b) { m_bitfields.setEverHadLayout(b); }
824
825 bool hasRareData() const { return m_bitfields.hasRareData(); }
826 void setHasRareData(bool b) { m_bitfields.setHasRareData(b); }
827
828#ifndef NDEBUG
829 void checkBlockPositionedObjectsNeedLayout();
830#endif
831
832 Node& m_node;
833
834 RenderElement* m_parent;
835 RenderObject* m_previous;
836 RenderObject* m_next;
837
838#ifndef NDEBUG
839 bool m_hasAXObject : 1;
840 bool m_setNeedsLayoutForbidden : 1;
841#endif
842
843#define ADD_BOOLEAN_BITFIELD(name, Name) \
844 private:\
845 unsigned m_##name : 1;\
846 public:\
847 bool name() const { return m_##name; }\
848 void set##Name(bool name) { m_##name = name; }\
849
850#define ADD_ENUM_BITFIELD(name, Name, Type, width) \
851 private:\
852 unsigned m_##name : width;\
853 public:\
854 Type name() const { return static_cast<Type>(m_##name); }\
855 void set##Name(Type name) { m_##name = static_cast<unsigned>(name); }\
856
857 class RenderObjectBitfields {
858 enum PositionedState {
859 IsStaticallyPositioned = 0,
860 IsRelativelyPositioned = 1,
861 IsOutOfFlowPositioned = 2,
862 IsStickilyPositioned = 3
863 };
864
865 public:
866 RenderObjectBitfields(const Node& node)
867 : m_hasRareData(false)
868 , m_beingDestroyed(false)
869 , m_needsLayout(false)
870 , m_needsPositionedMovementLayout(false)
871 , m_normalChildNeedsLayout(false)
872 , m_posChildNeedsLayout(false)
873 , m_needsSimplifiedNormalFlowLayout(false)
874 , m_preferredLogicalWidthsDirty(false)
875 , m_floating(false)
876 , m_isAnonymous(node.isDocumentNode())
877 , m_isTextOrRenderView(false)
878 , m_isBox(false)
879 , m_isInline(true)
880 , m_isReplaced(false)
881 , m_isLineBreak(false)
882 , m_horizontalWritingMode(true)
883 , m_hasLayer(false)
884 , m_hasOverflowClip(false)
885 , m_hasTransformRelatedProperty(false)
886 , m_everHadLayout(false)
887 , m_childrenInline(false)
888 , m_isExcludedFromNormalLayout(false)
889 , m_positionedState(IsStaticallyPositioned)
890 , m_selectionState(SelectionNone)
891 , m_fragmentedFlowState(NotInsideFragmentedFlow)
892 , m_boxDecorationState(NoBoxDecorations)
893 {
894 }
895
896 ADD_BOOLEAN_BITFIELD(hasRareData, HasRareData);
897
898 ADD_BOOLEAN_BITFIELD(beingDestroyed, BeingDestroyed);
899 ADD_BOOLEAN_BITFIELD(needsLayout, NeedsLayout);
900 ADD_BOOLEAN_BITFIELD(needsPositionedMovementLayout, NeedsPositionedMovementLayout);
901 ADD_BOOLEAN_BITFIELD(normalChildNeedsLayout, NormalChildNeedsLayout);
902 ADD_BOOLEAN_BITFIELD(posChildNeedsLayout, PosChildNeedsLayout);
903 ADD_BOOLEAN_BITFIELD(needsSimplifiedNormalFlowLayout, NeedsSimplifiedNormalFlowLayout);
904 ADD_BOOLEAN_BITFIELD(preferredLogicalWidthsDirty, PreferredLogicalWidthsDirty);
905 ADD_BOOLEAN_BITFIELD(floating, Floating);
906
907 ADD_BOOLEAN_BITFIELD(isAnonymous, IsAnonymous);
908 ADD_BOOLEAN_BITFIELD(isTextOrRenderView, IsTextOrRenderView);
909 ADD_BOOLEAN_BITFIELD(isBox, IsBox);
910 ADD_BOOLEAN_BITFIELD(isInline, IsInline);
911 ADD_BOOLEAN_BITFIELD(isReplaced, IsReplaced);
912 ADD_BOOLEAN_BITFIELD(isLineBreak, IsLineBreak);
913 ADD_BOOLEAN_BITFIELD(horizontalWritingMode, HorizontalWritingMode);
914
915 ADD_BOOLEAN_BITFIELD(hasLayer, HasLayer);
916 ADD_BOOLEAN_BITFIELD(hasOverflowClip, HasOverflowClip); // Set in the case of overflow:auto/scroll/hidden
917 ADD_BOOLEAN_BITFIELD(hasTransformRelatedProperty, HasTransformRelatedProperty);
918 ADD_BOOLEAN_BITFIELD(unused, Unused);
919
920 ADD_BOOLEAN_BITFIELD(everHadLayout, EverHadLayout);
921
922 // from RenderBlock
923 ADD_BOOLEAN_BITFIELD(childrenInline, ChildrenInline);
924
925 ADD_BOOLEAN_BITFIELD(isExcludedFromNormalLayout, IsExcludedFromNormalLayout);
926
927 private:
928 unsigned m_positionedState : 2; // PositionedState
929 unsigned m_selectionState : 3; // SelectionState
930 unsigned m_fragmentedFlowState : 2; // FragmentedFlowState
931 unsigned m_boxDecorationState : 2; // BoxDecorationState
932
933 public:
934 bool isOutOfFlowPositioned() const { return m_positionedState == IsOutOfFlowPositioned; }
935 bool isRelativelyPositioned() const { return m_positionedState == IsRelativelyPositioned; }
936 bool isStickilyPositioned() const { return m_positionedState == IsStickilyPositioned; }
937 bool isPositioned() const { return m_positionedState != IsStaticallyPositioned; }
938
939 void setPositionedState(int positionState)
940 {
941 // This mask maps PositionType::Fixed and PositionType::Absolute to IsOutOfFlowPositioned, saving one bit.
942 m_positionedState = static_cast<PositionedState>(positionState & 0x3);
943 }
944 void clearPositionedState() { m_positionedState = static_cast<unsigned>(PositionType::Static); }
945
946 ALWAYS_INLINE SelectionState selectionState() const { return static_cast<SelectionState>(m_selectionState); }
947 ALWAYS_INLINE void setSelectionState(SelectionState selectionState) { m_selectionState = selectionState; }
948
949 ALWAYS_INLINE FragmentedFlowState fragmentedFlowState() const { return static_cast<FragmentedFlowState>(m_fragmentedFlowState); }
950 ALWAYS_INLINE void setFragmentedFlowState(FragmentedFlowState fragmentedFlowState) { m_fragmentedFlowState = fragmentedFlowState; }
951
952 ALWAYS_INLINE BoxDecorationState boxDecorationState() const { return static_cast<BoxDecorationState>(m_boxDecorationState); }
953 ALWAYS_INLINE void setBoxDecorationState(BoxDecorationState boxDecorationState) { m_boxDecorationState = boxDecorationState; }
954 };
955
956 RenderObjectBitfields m_bitfields;
957
958 // FIXME: This should be RenderElementRareData.
959 class RenderObjectRareData {
960 WTF_MAKE_FAST_ALLOCATED;
961 public:
962 RenderObjectRareData()
963 : m_isDragging(false)
964 , m_hasReflection(false)
965 , m_isRenderFragmentedFlow(false)
966 , m_hasOutlineAutoAncestor(false)
967 {
968 }
969 ADD_BOOLEAN_BITFIELD(isDragging, IsDragging);
970 ADD_BOOLEAN_BITFIELD(hasReflection, HasReflection);
971 ADD_BOOLEAN_BITFIELD(isRenderFragmentedFlow, IsRenderFragmentedFlow);
972 ADD_BOOLEAN_BITFIELD(hasOutlineAutoAncestor, HasOutlineAutoAncestor);
973
974 // From RenderElement
975 std::unique_ptr<RenderStyle> cachedFirstLineStyle;
976 };
977
978 const RenderObject::RenderObjectRareData& rareData() const;
979 RenderObjectRareData& ensureRareData();
980 void removeRareData();
981
982 typedef HashMap<const RenderObject*, std::unique_ptr<RenderObjectRareData>> RareDataMap;
983
984 static RareDataMap& rareDataMap();
985
986#undef ADD_BOOLEAN_BITFIELD
987};
988
989inline Frame& RenderObject::frame() const
990{
991 return *document().frame();
992}
993
994inline Page& RenderObject::page() const
995{
996 // The render tree will always be torn down before Frame is disconnected from Page,
997 // so it's safe to assume Frame::page() is non-null as long as there are live RenderObjects.
998 ASSERT(frame().page());
999 return *frame().page();
1000}
1001
1002inline CSSAnimationController& RenderObject::animation() const
1003{
1004 return frame().animation();
1005}
1006
1007inline DocumentTimeline* RenderObject::documentTimeline() const
1008{
1009 return document().existingTimeline();
1010}
1011
1012inline bool RenderObject::renderTreeBeingDestroyed() const
1013{
1014 return document().renderTreeBeingDestroyed();
1015}
1016
1017inline bool RenderObject::isBeforeContent() const
1018{
1019 // Text nodes don't have their own styles, so ignore the style on a text node.
1020 if (isText())
1021 return false;
1022 if (style().styleType() != PseudoId::Before)
1023 return false;
1024 return true;
1025}
1026
1027inline bool RenderObject::isAfterContent() const
1028{
1029 // Text nodes don't have their own styles, so ignore the style on a text node.
1030 if (isText())
1031 return false;
1032 if (style().styleType() != PseudoId::After)
1033 return false;
1034 return true;
1035}
1036
1037inline bool RenderObject::isBeforeOrAfterContent() const
1038{
1039 return isBeforeContent() || isAfterContent();
1040}
1041
1042inline void RenderObject::setNeedsLayout(MarkingBehavior markParents)
1043{
1044 ASSERT(!isSetNeedsLayoutForbidden());
1045 if (m_bitfields.needsLayout())
1046 return;
1047 m_bitfields.setNeedsLayout(true);
1048 if (markParents == MarkContainingBlockChain)
1049 markContainingBlocksForLayout();
1050 if (hasLayer())
1051 setLayerNeedsFullRepaint();
1052}
1053
1054inline bool RenderObject::preservesNewline() const
1055{
1056 if (isSVGInlineText())
1057 return false;
1058
1059 return style().preserveNewline();
1060}
1061
1062inline void RenderObject::setSelectionStateIfNeeded(SelectionState state)
1063{
1064 if (selectionState() == state)
1065 return;
1066
1067 setSelectionState(state);
1068}
1069
1070inline void RenderObject::setHasVisibleBoxDecorations(bool b)
1071{
1072 if (!b) {
1073 m_bitfields.setBoxDecorationState(NoBoxDecorations);
1074 return;
1075 }
1076 if (hasVisibleBoxDecorations())
1077 return;
1078 m_bitfields.setBoxDecorationState(HasBoxDecorationsAndBackgroundObscurationStatusInvalid);
1079}
1080
1081inline void RenderObject::invalidateBackgroundObscurationStatus()
1082{
1083 if (!hasVisibleBoxDecorations())
1084 return;
1085 m_bitfields.setBoxDecorationState(HasBoxDecorationsAndBackgroundObscurationStatusInvalid);
1086}
1087
1088inline bool RenderObject::backgroundIsKnownToBeObscured(const LayoutPoint& paintOffset)
1089{
1090 if (m_bitfields.boxDecorationState() == HasBoxDecorationsAndBackgroundObscurationStatusInvalid) {
1091 BoxDecorationState boxDecorationState = computeBackgroundIsKnownToBeObscured(paintOffset) ? HasBoxDecorationsAndBackgroundIsKnownToBeObscured : HasBoxDecorationsAndBackgroundMayBeVisible;
1092 m_bitfields.setBoxDecorationState(boxDecorationState);
1093 }
1094 return m_bitfields.boxDecorationState() == HasBoxDecorationsAndBackgroundIsKnownToBeObscured;
1095}
1096
1097inline bool RenderObject::needsSimplifiedNormalFlowLayoutOnly() const
1098{
1099 return m_bitfields.needsSimplifiedNormalFlowLayout() && !m_bitfields.needsLayout() && !m_bitfields.normalChildNeedsLayout()
1100 && !m_bitfields.posChildNeedsLayout() && !m_bitfields.needsPositionedMovementLayout();
1101}
1102
1103#if ENABLE(TREE_DEBUGGING)
1104void printRenderTreeForLiveDocuments();
1105void printLayerTreeForLiveDocuments();
1106void printGraphicsLayerTreeForLiveDocuments();
1107#endif
1108
1109} // namespace WebCore
1110
1111#define SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(ToValueTypeName, predicate) \
1112SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ToValueTypeName) \
1113 static bool isType(const WebCore::RenderObject& renderer) { return renderer.predicate; } \
1114SPECIALIZE_TYPE_TRAITS_END()
1115
1116#if ENABLE(TREE_DEBUGGING)
1117// Outside the WebCore namespace for ease of invocation from the debugger.
1118void showNodeTree(const WebCore::RenderObject*);
1119void showLineTree(const WebCore::RenderObject*);
1120void showRenderTree(const WebCore::RenderObject*);
1121#endif
1122