1/* 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 4 * Copyright (C) 2003, 2006, 2007, 2009, 2013 Apple Inc. All rights reserved. 5 * Copyright (C) 2010, 2012 Google Inc. All rights reserved. 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Library General Public 9 * License as published by the Free Software Foundation; either 10 * version 2 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Library General Public License for more details. 16 * 17 * You should have received a copy of the GNU Library General Public License 18 * along with this library; see the file COPYING.LIB. If not, write to 19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 * Boston, MA 02110-1301, USA. 21 */ 22 23#ifndef RenderElement_h 24#define RenderElement_h 25 26#include "AnimationController.h" 27#include "RenderObject.h" 28 29namespace WebCore { 30 31class ControlStates; 32 33class RenderElement : public RenderObject { 34public: 35 virtual ~RenderElement(); 36 37 static RenderPtr<RenderElement> createFor(Element&, PassRef<RenderStyle>); 38 39 bool hasInitializedStyle() const { return m_hasInitializedStyle; } 40 41 RenderStyle& style() const { return const_cast<RenderStyle&>(m_style.get()); } 42 RenderStyle& firstLineStyle() const; 43 44 void initializeStyle(); 45 46 void setStyle(PassRef<RenderStyle>); 47 // Called to update a style that is allowed to trigger animations. 48 void setAnimatableStyle(PassRef<RenderStyle>); 49 50 // This is null for anonymous renderers. 51 Element* element() const { return toElement(RenderObject::node()); } 52 Element* nonPseudoElement() const { return toElement(RenderObject::nonPseudoNode()); } 53 Element* generatingElement() const; 54 55 RenderObject* firstChild() const { return m_firstChild; } 56 RenderObject* lastChild() const { return m_lastChild; } 57 58 // FIXME: Make these standalone and move to relevant files. 59 bool isRenderLayerModelObject() const; 60 bool isBoxModelObject() const; 61 bool isRenderBlock() const; 62 bool isRenderBlockFlow() const; 63 bool isRenderReplaced() const; 64 bool isRenderInline() const; 65 bool isRenderNamedFlowFragmentContainer() const; 66 67 virtual bool isChildAllowed(const RenderObject&, const RenderStyle&) const { return true; } 68 virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0); 69 virtual void addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild = 0) { return addChild(newChild, beforeChild); } 70 virtual RenderObject* removeChild(RenderObject&); 71 72 // The following functions are used when the render tree hierarchy changes to make sure layers get 73 // properly added and removed. Since containership can be implemented by any subclass, and since a hierarchy 74 // can contain a mixture of boxes and other object types, these functions need to be in the base class. 75 void addLayers(RenderLayer* parentLayer); 76 void removeLayers(RenderLayer* parentLayer); 77 void moveLayers(RenderLayer* oldParent, RenderLayer* newParent); 78 RenderLayer* findNextLayer(RenderLayer* parentLayer, RenderObject* startPoint, bool checkParent = true); 79 80 enum NotifyChildrenType { NotifyChildren, DontNotifyChildren }; 81 void insertChildInternal(RenderObject*, RenderObject* beforeChild, NotifyChildrenType); 82 RenderObject* removeChildInternal(RenderObject&, NotifyChildrenType); 83 84 virtual RenderElement* hoverAncestor() const; 85 86 virtual void dirtyLinesFromChangedChild(RenderObject*) { } 87 88 bool ancestorLineBoxDirty() const { return m_ancestorLineBoxDirty; } 89 void setAncestorLineBoxDirty(bool f = true); 90 91 void setChildNeedsLayout(MarkingBehavior = MarkContainingBlockChain); 92 void clearChildNeedsLayout(); 93 void setNeedsPositionedMovementLayout(const RenderStyle* oldStyle); 94 void setNeedsSimplifiedNormalFlowLayout(); 95 96 virtual void paint(PaintInfo&, const LayoutPoint&) = 0; 97 98 // Recursive function that computes the size and position of this object and all its descendants. 99 virtual void layout(); 100 101 /* This function performs a layout only if one is needed. */ 102 void layoutIfNeeded() { if (needsLayout()) layout(); } 103 104 // Return the renderer whose background style is used to paint the root background. Should only be called on the renderer for which isRoot() is true. 105 RenderElement& rendererForRootBackground(); 106 107 // Used only by Element::pseudoStyleCacheIsInvalid to get a first line style based off of a 108 // given new style, without accessing the cache. 109 PassRefPtr<RenderStyle> uncachedFirstLineStyle(RenderStyle*) const; 110 111 // Updates only the local style ptr of the object. Does not update the state of the object, 112 // and so only should be called when the style is known not to have changed (or from setStyle). 113 void setStyleInternal(PassRef<RenderStyle> style) { m_style = WTF::move(style); } 114 115 // Repaint only if our old bounds and new bounds are different. The caller may pass in newBounds and newOutlineBox if they are known. 116 bool repaintAfterLayoutIfNeeded(const RenderLayerModelObject* repaintContainer, const LayoutRect& oldBounds, const LayoutRect& oldOutlineBox, const LayoutRect* newBoundsPtr = nullptr, const LayoutRect* newOutlineBoxPtr = nullptr); 117 118 bool borderImageIsLoadedAndCanBeRendered() const; 119 120 // Returns true if this renderer requires a new stacking context. 121 bool createsGroup() const { return isTransparent() || hasMask() || hasFilter() || hasBlendMode(); } 122 123 bool isTransparent() const { return style().opacity() < 1.0f; } 124 float opacity() const { return style().opacity(); } 125 126 bool visibleToHitTesting() const { return style().visibility() == VISIBLE && style().pointerEvents() != PE_NONE; } 127 128 bool hasBackground() const { return style().hasBackground(); } 129 bool hasMask() const { return style().hasMask(); } 130 bool hasClip() const { return isOutOfFlowPositioned() && style().hasClip(); } 131 bool hasClipOrOverflowClip() const { return hasClip() || hasOverflowClip(); } 132 bool hasClipPath() const { return style().clipPath(); } 133 bool hasHiddenBackface() const { return style().backfaceVisibility() == BackfaceVisibilityHidden; } 134 135#if ENABLE(CSS_FILTERS) 136 bool hasFilter() const { return style().hasFilter(); } 137#else 138 bool hasFilter() const { return false; } 139#endif 140 141#if ENABLE(CSS_COMPOSITING) 142 bool hasBlendMode() const { return style().hasBlendMode(); } 143#else 144 bool hasBlendMode() const { return false; } 145#endif 146 147#if ENABLE(CSS_SHAPES) 148 bool hasShapeOutside() const { return style().shapeOutside(); } 149#else 150 bool hasShapeOutside() const { return false; } 151#endif 152 153 bool repaintForPausedImageAnimationsIfNeeded(const IntRect& visibleRect); 154 bool hasPausedImageAnimations() const { return m_hasPausedImageAnimations; } 155 void setHasPausedImageAnimations(bool b) { m_hasPausedImageAnimations = b; } 156 157 RenderNamedFlowThread* renderNamedFlowThreadWrapper(); 158 159 void setRenderBoxNeedsLazyRepaint(bool b) { m_renderBoxNeedsLazyRepaint = b; } 160 bool renderBoxNeedsLazyRepaint() const { return m_renderBoxNeedsLazyRepaint; } 161 162protected: 163 enum BaseTypeFlags { 164 RenderLayerModelObjectFlag = 1 << 0, 165 RenderBoxModelObjectFlag = 1 << 1, 166 RenderInlineFlag = 1 << 2, 167 RenderReplacedFlag = 1 << 3, 168 RenderBlockFlag = 1 << 4, 169 RenderBlockFlowFlag = 1 << 5, 170 }; 171 172 RenderElement(Element&, PassRef<RenderStyle>, unsigned baseTypeFlags); 173 RenderElement(Document&, PassRef<RenderStyle>, unsigned baseTypeFlags); 174 175 bool layerCreationAllowedForSubtree() const; 176 177 enum StylePropagationType { PropagateToAllChildren, PropagateToBlockChildrenOnly }; 178 void propagateStyleToAnonymousChildren(StylePropagationType); 179 180 LayoutUnit valueForLength(const Length&, LayoutUnit maximumValue) const; 181 LayoutUnit minimumValueForLength(const Length&, LayoutUnit maximumValue, bool roundPercentages = false) const; 182 183 void setFirstChild(RenderObject* child) { m_firstChild = child; } 184 void setLastChild(RenderObject* child) { m_lastChild = child; } 185 void destroyLeftoverChildren(); 186 187 virtual void styleWillChange(StyleDifference, const RenderStyle& newStyle); 188 virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); 189 190 virtual void insertedIntoTree() override; 191 virtual void willBeRemovedFromTree() override; 192 virtual void willBeDestroyed() override; 193 194 void setRenderInlineAlwaysCreatesLineBoxes(bool b) { m_renderInlineAlwaysCreatesLineBoxes = b; } 195 bool renderInlineAlwaysCreatesLineBoxes() const { return m_renderInlineAlwaysCreatesLineBoxes; } 196 197 static bool hasControlStatesForRenderer(const RenderObject*); 198 static ControlStates* controlStatesForRenderer(const RenderObject*); 199 static void removeControlStatesForRenderer(const RenderObject*); 200 static void addControlStatesForRenderer(const RenderObject*, ControlStates*); 201 202private: 203 RenderElement(ContainerNode&, PassRef<RenderStyle>, unsigned baseTypeFlags); 204 void node() const = delete; 205 void nonPseudoNode() const = delete; 206 void generatingNode() const = delete; 207 void isText() const = delete; 208 void isRenderElement() const = delete; 209 210 virtual RenderObject* firstChildSlow() const override final { return firstChild(); } 211 virtual RenderObject* lastChildSlow() const override final { return lastChild(); } 212 213 bool shouldRepaintForStyleDifference(StyleDifference) const; 214 bool hasImmediateNonWhitespaceTextChildOrBorderOrOutline() const; 215 216 void updateFillImages(const FillLayer*, const FillLayer*); 217 void updateImage(StyleImage*, StyleImage*); 218#if ENABLE(CSS_SHAPES) 219 void updateShapeImage(const ShapeValue*, const ShapeValue*); 220#endif 221 222 StyleDifference adjustStyleDifference(StyleDifference, unsigned contextSensitiveProperties) const; 223 RenderStyle* cachedFirstLineStyle() const; 224 225 virtual void newImageAnimationFrameAvailable(CachedImage&) final override; 226 227 unsigned m_baseTypeFlags : 6; 228 bool m_ancestorLineBoxDirty : 1; 229 bool m_hasInitializedStyle : 1; 230 231 bool m_renderInlineAlwaysCreatesLineBoxes : 1; 232 bool m_renderBoxNeedsLazyRepaint : 1; 233 bool m_hasPausedImageAnimations : 1; 234 235 RenderObject* m_firstChild; 236 RenderObject* m_lastChild; 237 238 Ref<RenderStyle> m_style; 239 240 // FIXME: Get rid of this hack. 241 // Store state between styleWillChange and styleDidChange 242 static bool s_affectsParentBlock; 243 static bool s_noLongerAffectsParentBlock; 244}; 245 246RENDER_OBJECT_TYPE_CASTS(RenderElement, isRenderElement()) 247 248inline void RenderElement::setAnimatableStyle(PassRef<RenderStyle> style) 249{ 250 setStyle(animation().updateAnimations(*this, WTF::move(style))); 251} 252 253inline RenderStyle& RenderElement::firstLineStyle() const 254{ 255 return document().styleSheetCollection().usesFirstLineRules() ? *cachedFirstLineStyle() : style(); 256} 257 258inline void RenderElement::setAncestorLineBoxDirty(bool f) 259{ 260 m_ancestorLineBoxDirty = f; 261 if (m_ancestorLineBoxDirty) 262 setNeedsLayout(); 263} 264 265inline void RenderElement::setChildNeedsLayout(MarkingBehavior markParents) 266{ 267 ASSERT(!isSetNeedsLayoutForbidden()); 268 if (normalChildNeedsLayout()) 269 return; 270 setNormalChildNeedsLayoutBit(true); 271 if (markParents == MarkContainingBlockChain) 272 markContainingBlocksForLayout(); 273} 274 275inline LayoutUnit RenderElement::valueForLength(const Length& length, LayoutUnit maximumValue) const 276{ 277 return WebCore::valueForLength(length, maximumValue); 278} 279 280inline LayoutUnit RenderElement::minimumValueForLength(const Length& length, LayoutUnit maximumValue, bool roundPercentages) const 281{ 282 return WebCore::minimumValueForLength(length, maximumValue, roundPercentages); 283} 284 285inline bool RenderElement::isRenderLayerModelObject() const 286{ 287 return m_baseTypeFlags & RenderLayerModelObjectFlag; 288} 289 290inline bool RenderElement::isBoxModelObject() const 291{ 292 return m_baseTypeFlags & RenderBoxModelObjectFlag; 293} 294 295inline bool RenderElement::isRenderBlock() const 296{ 297 return m_baseTypeFlags & RenderBlockFlag; 298} 299 300inline bool RenderElement::isRenderBlockFlow() const 301{ 302 return m_baseTypeFlags & RenderBlockFlowFlag; 303} 304 305inline bool RenderElement::isRenderReplaced() const 306{ 307 return m_baseTypeFlags & RenderReplacedFlag; 308} 309 310inline bool RenderElement::isRenderInline() const 311{ 312 return m_baseTypeFlags & RenderInlineFlag; 313} 314 315inline Element* RenderElement::generatingElement() const 316{ 317 if (parent() && isRenderNamedFlowFragment()) 318 return parent()->generatingElement(); 319 return toElement(RenderObject::generatingNode()); 320} 321 322inline bool RenderObject::isRenderLayerModelObject() const 323{ 324 return isRenderElement() && toRenderElement(this)->isRenderLayerModelObject(); 325} 326 327inline bool RenderObject::isBoxModelObject() const 328{ 329 return isRenderElement() && toRenderElement(this)->isBoxModelObject(); 330} 331 332inline bool RenderObject::isRenderBlock() const 333{ 334 return isRenderElement() && toRenderElement(this)->isRenderBlock(); 335} 336 337inline bool RenderObject::isRenderBlockFlow() const 338{ 339 return isRenderElement() && toRenderElement(this)->isRenderBlockFlow(); 340} 341 342inline bool RenderObject::isRenderReplaced() const 343{ 344 return isRenderElement() && toRenderElement(this)->isRenderReplaced(); 345} 346 347inline bool RenderObject::isRenderInline() const 348{ 349 return isRenderElement() && toRenderElement(this)->isRenderInline(); 350} 351 352inline RenderStyle& RenderObject::style() const 353{ 354 if (isText()) 355 return m_parent->style(); 356 return toRenderElement(this)->style(); 357} 358 359inline RenderStyle& RenderObject::firstLineStyle() const 360{ 361 if (isText()) 362 return m_parent->firstLineStyle(); 363 return toRenderElement(this)->firstLineStyle(); 364} 365 366inline RenderElement* ContainerNode::renderer() const 367{ 368 return toRenderElement(Node::renderer()); 369} 370 371inline int adjustForAbsoluteZoom(int value, const RenderElement& renderer) 372{ 373 return adjustForAbsoluteZoom(value, renderer.style()); 374} 375 376#if ENABLE(SUBPIXEL_LAYOUT) 377inline LayoutUnit adjustLayoutUnitForAbsoluteZoom(LayoutUnit value, const RenderElement& renderer) 378{ 379 return adjustLayoutUnitForAbsoluteZoom(value, renderer.style()); 380} 381#endif 382 383} // namespace WebCore 384 385#endif // RenderElement_h 386