1 /* 2 * Copyright (C) 2000 Lars Knoll (knoll (at) kde.org) 3 * (C) 2000 Antti Koivisto (koivisto (at) kde.org) 4 * (C) 2000 Dirk Mueller (mueller (at) kde.org) 5 * (C) 2004 Allan Sandfeld Jensen (kde (at) carewolf.com) 6 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 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 #ifndef RenderObject_h 27 #define RenderObject_h 28 29 #include "AffineTransform.h" 30 #include "CachedResourceClient.h" 31 #include "Document.h" 32 #include "Element.h" 33 #include "FloatQuad.h" 34 #include "RenderObjectChildList.h" 35 #include "RenderStyle.h" 36 #include "TextAffinity.h" 37 #include "TransformationMatrix.h" 38 #include <wtf/UnusedParam.h> 39 40 namespace WebCore { 41 42 class AnimationController; 43 class HitTestResult; 44 class InlineBox; 45 class InlineFlowBox; 46 class OverlapTestRequestClient; 47 class Position; 48 class RenderBoxModelObject; 49 class RenderInline; 50 class RenderBlock; 51 class RenderFlow; 52 class RenderLayer; 53 class RenderTheme; 54 class TransformState; 55 class VisiblePosition; 56 #if ENABLE(SVG) 57 class SVGRenderBase; 58 #endif 59 60 /* 61 * The painting of a layer occurs in three distinct phases. Each phase involves 62 * a recursive descent into the layer's render objects. The first phase is the background phase. 63 * The backgrounds and borders of all blocks are painted. Inlines are not painted at all. 64 * Floats must paint above block backgrounds but entirely below inline content that can overlap them. 65 * In the foreground phase, all inlines are fully painted. Inline replaced elements will get all 66 * three phases invoked on them during this phase. 67 */ 68 69 enum PaintPhase { 70 PaintPhaseBlockBackground, 71 PaintPhaseChildBlockBackground, 72 PaintPhaseChildBlockBackgrounds, 73 PaintPhaseFloat, 74 PaintPhaseForeground, 75 PaintPhaseOutline, 76 PaintPhaseChildOutlines, 77 PaintPhaseSelfOutline, 78 PaintPhaseSelection, 79 PaintPhaseCollapsedTableBorders, 80 PaintPhaseTextClip, 81 PaintPhaseMask 82 }; 83 84 enum PaintBehaviorFlags { 85 PaintBehaviorNormal = 0, 86 PaintBehaviorSelectionOnly = 1 << 0, 87 PaintBehaviorForceBlackText = 1 << 1, 88 PaintBehaviorFlattenCompositingLayers = 1 << 2 89 }; 90 typedef unsigned PaintBehavior; 91 92 enum HitTestFilter { 93 HitTestAll, 94 HitTestSelf, 95 HitTestDescendants 96 }; 97 98 enum HitTestAction { 99 HitTestBlockBackground, 100 HitTestChildBlockBackground, 101 HitTestChildBlockBackgrounds, 102 HitTestFloat, 103 HitTestForeground 104 }; 105 106 // Sides used when drawing borders and outlines. This is in RenderObject rather than RenderBoxModelObject since outlines can 107 // be drawn by SVG around bounding boxes. 108 enum BoxSide { 109 BSTop, 110 BSBottom, 111 BSLeft, 112 BSRight 113 }; 114 115 const int caretWidth = 1; 116 117 #if ENABLE(DASHBOARD_SUPPORT) 118 struct DashboardRegionValue { 119 bool operator==(const DashboardRegionValue& o) const 120 { 121 return type == o.type && bounds == o.bounds && clip == o.clip && label == o.label; 122 } 123 bool operator!=(const DashboardRegionValue& o) const 124 { 125 return !(*this == o); 126 } 127 128 String label; 129 IntRect bounds; 130 IntRect clip; 131 int type; 132 }; 133 #endif 134 135 // Base class for all rendering tree objects. 136 class RenderObject : public CachedResourceClient { 137 friend class RenderBlock; 138 friend class RenderBox; 139 friend class RenderLayer; 140 friend class RenderObjectChildList; 141 friend class RenderSVGContainer; 142 public: 143 // Anonymous objects should pass the document as their node, and they will then automatically be 144 // marked as anonymous in the constructor. 145 RenderObject(Node*); 146 virtual ~RenderObject(); 147 148 RenderTheme* theme() const; 149 150 virtual const char* renderName() const = 0; 151 152 RenderObject* parent() const { return m_parent; } 153 bool isDescendantOf(const RenderObject*) const; 154 155 RenderObject* previousSibling() const { return m_previous; } 156 RenderObject* nextSibling() const { return m_next; } 157 158 RenderObject* firstChild() const 159 { 160 if (const RenderObjectChildList* children = virtualChildren()) 161 return children->firstChild(); 162 return 0; 163 } 164 RenderObject* lastChild() const 165 { 166 if (const RenderObjectChildList* children = virtualChildren()) 167 return children->lastChild(); 168 return 0; 169 } 170 virtual RenderObjectChildList* virtualChildren() { return 0; } 171 virtual const RenderObjectChildList* virtualChildren() const { return 0; } 172 173 RenderObject* nextInPreOrder() const; 174 RenderObject* nextInPreOrder(RenderObject* stayWithin) const; 175 RenderObject* nextInPreOrderAfterChildren() const; 176 RenderObject* nextInPreOrderAfterChildren(RenderObject* stayWithin) const; 177 RenderObject* previousInPreOrder() const; 178 RenderObject* childAt(unsigned) const; 179 180 RenderObject* firstLeafChild() const; 181 RenderObject* lastLeafChild() const; 182 183 // The following six functions are used when the render tree hierarchy changes to make sure layers get 184 // properly added and removed. Since containership can be implemented by any subclass, and since a hierarchy 185 // can contain a mixture of boxes and other object types, these functions need to be in the base class. 186 RenderLayer* enclosingLayer() const; 187 RenderLayer* enclosingSelfPaintingLayer() const; 188 void addLayers(RenderLayer* parentLayer, RenderObject* newObject); 189 void removeLayers(RenderLayer* parentLayer); 190 void moveLayers(RenderLayer* oldParent, RenderLayer* newParent); 191 RenderLayer* findNextLayer(RenderLayer* parentLayer, RenderObject* startPoint, bool checkParent = true); 192 193 // Convenience function for getting to the nearest enclosing box of a RenderObject. 194 RenderBox* enclosingBox() const; 195 RenderBoxModelObject* enclosingBoxModelObject() const; 196 197 virtual bool isEmpty() const { return firstChild() == 0; } 198 199 #ifndef NDEBUG 200 void setHasAXObject(bool flag) { m_hasAXObject = flag; } 201 bool hasAXObject() const { return m_hasAXObject; } 202 bool isSetNeedsLayoutForbidden() const { return m_setNeedsLayoutForbidden; } 203 void setNeedsLayoutIsForbidden(bool flag) { m_setNeedsLayoutForbidden = flag; } 204 #endif 205 206 // Obtains the nearest enclosing block (including this block) that contributes a first-line style to our inline 207 // children. 208 virtual RenderBlock* firstLineBlock() const; 209 210 // Called when an object that was floating or positioned becomes a normal flow object 211 // again. We have to make sure the render tree updates as needed to accommodate the new 212 // normal flow object. 213 void handleDynamicFloatPositionChange(); 214 215 // RenderObject tree manipulation 216 ////////////////////////////////////////// 217 virtual bool canHaveChildren() const { return virtualChildren(); } 218 virtual bool isChildAllowed(RenderObject*, RenderStyle*) const { return true; } 219 virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0); 220 virtual void addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild = 0) { return addChild(newChild, beforeChild); } 221 virtual void removeChild(RenderObject*); 222 virtual bool createsAnonymousWrapper() const { return false; } 223 ////////////////////////////////////////// 224 225 protected: 226 ////////////////////////////////////////// 227 // Helper functions. Dangerous to use! 228 void setPreviousSibling(RenderObject* previous) { m_previous = previous; } 229 void setNextSibling(RenderObject* next) { m_next = next; } 230 void setParent(RenderObject* parent) { m_parent = parent; } 231 ////////////////////////////////////////// 232 private: 233 void addAbsoluteRectForLayer(IntRect& result); 234 void setLayerNeedsFullRepaint(); 235 236 public: 237 #ifndef NDEBUG 238 void showTreeForThis() const; 239 240 void showRenderObject() const; 241 // We don't make printedCharacters an optional parameter so that 242 // showRenderObject can be called from gdb easily. 243 void showRenderObject(int printedCharacters) const; 244 void showRenderTreeAndMark(const RenderObject* markedObject1 = 0, const char* markedLabel1 = 0, const RenderObject* markedObject2 = 0, const char* markedLabel2 = 0, int depth = 0) const; 245 #endif 246 247 static RenderObject* createObject(Node*, RenderStyle*); 248 249 // Overloaded new operator. Derived classes must override operator new 250 // in order to allocate out of the RenderArena. 251 void* operator new(size_t, RenderArena*) throw(); 252 253 // Overridden to prevent the normal delete from being called. 254 void operator delete(void*, size_t); 255 256 private: 257 // The normal operator new is disallowed on all render objects. 258 void* operator new(size_t) throw(); 259 260 public: 261 RenderArena* renderArena() const { return document()->renderArena(); } 262 263 virtual bool isApplet() const { return false; } 264 virtual bool isBR() const { return false; } 265 virtual bool isBlockFlow() const { return false; } 266 virtual bool isBoxModelObject() const { return false; } 267 virtual bool isCounter() const { return false; } 268 virtual bool isEmbeddedObject() const { return false; } 269 virtual bool isFieldset() const { return false; } 270 virtual bool isFileUploadControl() const { return false; } 271 virtual bool isFrame() const { return false; } 272 virtual bool isFrameSet() const { return false; } 273 virtual bool isImage() const { return false; } 274 virtual bool isInlineBlockOrInlineTable() const { return false; } 275 virtual bool isListBox() const { return false; } 276 virtual bool isListItem() const { return false; } 277 virtual bool isListMarker() const { return false; } 278 virtual bool isMedia() const { return false; } 279 virtual bool isMenuList() const { return false; } 280 virtual bool isRenderBlock() const { return false; } 281 virtual bool isRenderButton() const { return false; } 282 virtual bool isRenderImage() const { return false; } 283 virtual bool isRenderInline() const { return false; } 284 virtual bool isRenderPart() const { return false; } 285 virtual bool isRenderView() const { return false; } 286 virtual bool isReplica() const { return false; } 287 #if ENABLE(RUBY) 288 virtual bool isRuby() const { return false; } 289 virtual bool isRubyBase() const { return false; } 290 virtual bool isRubyRun() const { return false; } 291 virtual bool isRubyText() const { return false; } 292 #endif 293 virtual bool isSlider() const { return false; } 294 virtual bool isTable() const { return false; } 295 virtual bool isTableCell() const { return false; } 296 virtual bool isTableCol() const { return false; } 297 virtual bool isTableRow() const { return false; } 298 virtual bool isTableSection() const { return false; } 299 virtual bool isTextControl() const { return false; } 300 virtual bool isTextArea() const { return false; } 301 virtual bool isTextField() const { return false; } 302 virtual bool isVideo() const { return false; } 303 virtual bool isWidget() const { return false; } 304 virtual bool isCanvas() const { return false; } 305 306 bool isRoot() const { return document()->documentElement() == m_node; } 307 bool isBody() const; 308 bool isHR() const; 309 310 bool isHTMLMarquee() const; 311 312 inline bool isAfterContent() const; 313 static inline bool isAfterContent(const RenderObject* obj) { return obj && obj->isAfterContent(); } 314 315 bool childrenInline() const { return m_childrenInline; } 316 void setChildrenInline(bool b = true) { m_childrenInline = b; } 317 bool hasColumns() const { return m_hasColumns; } 318 void setHasColumns(bool b = true) { m_hasColumns = b; } 319 bool cellWidthChanged() const { return m_cellWidthChanged; } 320 void setCellWidthChanged(bool b = true) { m_cellWidthChanged = b; } 321 322 #if ENABLE(MATHML) 323 virtual bool isRenderMathMLBlock() const { return false; } 324 #endif // ENABLE(MATHML) 325 326 #if ENABLE(SVG) 327 // FIXME: Until all SVG renders can be subclasses of RenderSVGModelObject we have 328 // to add SVG renderer methods to RenderObject with an ASSERT_NOT_REACHED() default implementation. 329 virtual bool isSVGRoot() const { return false; } 330 virtual bool isSVGContainer() const { return false; } 331 virtual bool isSVGHiddenContainer() const { return false; } 332 virtual bool isRenderPath() const { return false; } 333 virtual bool isSVGText() const { return false; } 334 virtual bool isSVGImage() const { return false; } 335 virtual bool isSVGForeignObject() const { return false; } 336 337 virtual const SVGRenderBase* toSVGRenderBase() const; 338 339 // Per SVG 1.1 objectBoundingBox ignores clipping, masking, filter effects, opacity and stroke-width. 340 // This is used for all computation of objectBoundingBox relative units and by SVGLocateable::getBBox(). 341 // NOTE: Markers are not specifically ignored here by SVG 1.1 spec, but we ignore them 342 // since stroke-width is ignored (and marker size can depend on stroke-width). 343 // objectBoundingBox is returned local coordinates. 344 // The name objectBoundingBox is taken from the SVG 1.1 spec. 345 virtual FloatRect objectBoundingBox() const; 346 347 // Returns the smallest rectangle enclosing all of the painted content 348 // respecting clipping, masking, filters, opacity, stroke-width and markers 349 virtual FloatRect repaintRectInLocalCoordinates() const; 350 351 // FIXME: This accessor is deprecated and mostly around for SVGRenderTreeAsText. 352 // This only returns the transform="" value from the element 353 // most callsites want localToParentTransform() instead. 354 virtual AffineTransform localTransform() const; 355 356 // Returns the full transform mapping from local coordinates to local coords for the parent SVG renderer 357 // This includes any viewport transforms and x/y offsets as well as the transform="" value off the element. 358 virtual const AffineTransform& localToParentTransform() const; 359 360 // SVG uses FloatPoint precise hit testing, and passes the point in parent 361 // coordinates instead of in repaint container coordinates. Eventually the 362 // rest of the rendering tree will move to a similar model. 363 virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction); 364 #endif 365 366 bool isAnonymous() const { return m_isAnonymous; } 367 void setIsAnonymous(bool b) { m_isAnonymous = b; } 368 bool isAnonymousBlock() const 369 { 370 return m_isAnonymous && style()->display() == BLOCK && style()->styleType() == NOPSEUDO && !isListMarker(); 371 } 372 bool isInlineContinuation() const { return (node() ? node()->renderer() != this : false) && isRenderInline(); } 373 bool isFloating() const { return m_floating; } 374 bool isPositioned() const { return m_positioned; } // absolute or fixed positioning 375 bool isRelPositioned() const { return m_relPositioned; } // relative positioning 376 bool isText() const { return m_isText; } 377 bool isBox() const { return m_isBox; } 378 bool isInline() const { return m_inline; } // inline object 379 bool isRunIn() const { return style()->display() == RUN_IN; } // run-in object 380 bool isDragging() const { return m_isDragging; } 381 bool isReplaced() const { return m_replaced; } // a "replaced" element (see CSS) 382 383 bool hasLayer() const { return m_hasLayer; } 384 385 bool hasBoxDecorations() const { return m_paintBackground; } 386 bool mustRepaintBackgroundOrBorder() const; 387 388 bool needsLayout() const { return m_needsLayout || m_normalChildNeedsLayout || m_posChildNeedsLayout || m_needsPositionedMovementLayout; } 389 bool selfNeedsLayout() const { return m_needsLayout; } 390 bool needsPositionedMovementLayout() const { return m_needsPositionedMovementLayout; } 391 bool needsPositionedMovementLayoutOnly() const { return m_needsPositionedMovementLayout && !m_needsLayout && !m_normalChildNeedsLayout && !m_posChildNeedsLayout; } 392 bool posChildNeedsLayout() const { return m_posChildNeedsLayout; } 393 bool normalChildNeedsLayout() const { return m_normalChildNeedsLayout; } 394 395 bool prefWidthsDirty() const { return m_prefWidthsDirty; } 396 397 bool isSelectionBorder() const; 398 399 bool hasClip() const { return isPositioned() && style()->hasClip(); } 400 bool hasOverflowClip() const { return m_hasOverflowClip; } 401 402 bool hasTransform() const { return m_hasTransform; } 403 bool hasMask() const { return style() && style()->hasMask(); } 404 405 void drawLineForBoxSide(GraphicsContext*, int x1, int y1, int x2, int y2, BoxSide, 406 Color, const Color& textcolor, EBorderStyle, int adjbw1, int adjbw2); 407 void drawArcForBoxSide(GraphicsContext*, int x, int y, float thickness, IntSize radius, int angleStart, 408 int angleSpan, BoxSide, Color, const Color& textcolor, EBorderStyle, bool firstCorner); 409 410 public: 411 // The pseudo element style can be cached or uncached. Use the cached method if the pseudo element doesn't respect 412 // any pseudo classes (and therefore has no concept of changing state). 413 RenderStyle* getCachedPseudoStyle(PseudoId, RenderStyle* parentStyle = 0) const; 414 PassRefPtr<RenderStyle> getUncachedPseudoStyle(PseudoId, RenderStyle* parentStyle = 0, RenderStyle* ownStyle = 0) const; 415 416 virtual void updateDragState(bool dragOn); 417 418 RenderView* view() const; 419 420 // Returns true if this renderer is rooted, and optionally returns the hosting view (the root of the hierarchy). 421 bool isRooted(RenderView** = 0); 422 423 Node* node() const { return m_isAnonymous ? 0 : m_node; } 424 Document* document() const { return m_node->document(); } 425 void setNode(Node* node) { m_node = node; } 426 427 bool hasOutlineAnnotation() const; 428 bool hasOutline() const { return style()->hasOutline() || hasOutlineAnnotation(); } 429 430 // Returns the object containing this one. Can be different from parent for positioned elements. 431 // If repaintContainer and repaintContainerSkipped are not null, on return *repaintContainerSkipped 432 // is true if the renderer returned is an ancestor of repaintContainer. 433 RenderObject* container(RenderBoxModelObject* repaintContainer = 0, bool* repaintContainerSkipped = 0) const; 434 435 virtual RenderObject* hoverAncestor() const { return parent(); } 436 437 // IE Extension that can be called on any RenderObject. See the implementation for the details. 438 RenderBoxModelObject* offsetParent() const; 439 440 void markContainingBlocksForLayout(bool scheduleRelayout = true, RenderObject* newRoot = 0); 441 void setNeedsLayout(bool b, bool markParents = true); 442 void setChildNeedsLayout(bool b, bool markParents = true); 443 void setNeedsPositionedMovementLayout(); 444 void setPrefWidthsDirty(bool, bool markParents = true); 445 void invalidateContainerPrefWidths(); 446 447 void setNeedsLayoutAndPrefWidthsRecalc() 448 { 449 setNeedsLayout(true); 450 setPrefWidthsDirty(true); 451 } 452 453 void setPositioned(bool b = true) { m_positioned = b; } 454 void setRelPositioned(bool b = true) { m_relPositioned = b; } 455 void setFloating(bool b = true) { m_floating = b; } 456 void setInline(bool b = true) { m_inline = b; } 457 void setHasBoxDecorations(bool b = true) { m_paintBackground = b; } 458 void setIsText() { m_isText = true; } 459 void setIsBox() { m_isBox = true; } 460 void setReplaced(bool b = true) { m_replaced = b; } 461 void setHasOverflowClip(bool b = true) { m_hasOverflowClip = b; } 462 void setHasLayer(bool b = true) { m_hasLayer = b; } 463 void setHasTransform(bool b = true) { m_hasTransform = b; } 464 void setHasReflection(bool b = true) { m_hasReflection = b; } 465 466 void scheduleRelayout(); 467 468 void updateFillImages(const FillLayer*, const FillLayer*); 469 void updateImage(StyleImage*, StyleImage*); 470 471 // for discussion of lineHeight see CSS2 spec 472 virtual int lineHeight(bool firstLine, bool isRootLineBox = false) const; 473 // for the vertical-align property of inline elements 474 // the offset of baseline from the top of the object. 475 virtual int baselinePosition(bool firstLine, bool isRootLineBox = false) const; 476 477 typedef HashMap<OverlapTestRequestClient*, IntRect> OverlapTestRequestMap; 478 479 /* 480 * Paint the object and its children, clipped by (x|y|w|h). 481 * (tx|ty) is the calculated position of the parent 482 */ 483 struct PaintInfo { 484 PaintInfo(GraphicsContext* newContext, const IntRect& newRect, PaintPhase newPhase, bool newForceBlackText, 485 RenderObject* newPaintingRoot, ListHashSet<RenderInline*>* newOutlineObjects, 486 OverlapTestRequestMap* overlapTestRequests = 0) 487 : context(newContext) 488 , rect(newRect) 489 , phase(newPhase) 490 , forceBlackText(newForceBlackText) 491 , paintingRoot(newPaintingRoot) 492 , outlineObjects(newOutlineObjects) 493 , overlapTestRequests(overlapTestRequests) 494 { 495 } 496 497 GraphicsContext* context; 498 IntRect rect; 499 PaintPhase phase; 500 bool forceBlackText; 501 RenderObject* paintingRoot; // used to draw just one element and its visual kids 502 ListHashSet<RenderInline*>* outlineObjects; // used to list outlines that should be painted by a block with inline children 503 OverlapTestRequestMap* overlapTestRequests; 504 }; 505 506 virtual void paint(PaintInfo&, int tx, int ty); 507 508 // Recursive function that computes the size and position of this object and all its descendants. 509 virtual void layout(); 510 511 /* This function performs a layout only if one is needed. */ 512 void layoutIfNeeded() { if (needsLayout()) layout(); } 513 514 // Called when a positioned object moves but doesn't necessarily change size. A simplified layout is attempted 515 // that just updates the object's position. If the size does change, the object remains dirty. 516 virtual void tryLayoutDoingPositionedMovementOnly() { } 517 518 // used for element state updates that cannot be fixed with a 519 // repaint and do not need a relayout 520 virtual void updateFromElement() { } 521 522 #if ENABLE(DASHBOARD_SUPPORT) 523 virtual void addDashboardRegions(Vector<DashboardRegionValue>&); 524 void collectDashboardRegions(Vector<DashboardRegionValue>&); 525 #endif 526 527 bool hitTest(const HitTestRequest&, HitTestResult&, const IntPoint&, int tx, int ty, HitTestFilter = HitTestAll); 528 virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction); 529 virtual void updateHitTestResult(HitTestResult&, const IntPoint&); 530 531 VisiblePosition positionForCoordinates(int x, int y); 532 virtual VisiblePosition positionForPoint(const IntPoint&); 533 VisiblePosition createVisiblePosition(int offset, EAffinity); 534 VisiblePosition createVisiblePosition(const Position&); 535 536 virtual void dirtyLinesFromChangedChild(RenderObject*); 537 538 // Called to update a style that is allowed to trigger animations. 539 // FIXME: Right now this will typically be called only when updating happens from the DOM on explicit elements. 540 // We don't yet handle generated content animation such as first-letter or before/after (we'll worry about this later). 541 void setAnimatableStyle(PassRefPtr<RenderStyle>); 542 543 // Set the style of the object and update the state of the object accordingly. 544 virtual void setStyle(PassRefPtr<RenderStyle>); 545 546 // Updates only the local style ptr of the object. Does not update the state of the object, 547 // and so only should be called when the style is known not to have changed (or from setStyle). 548 void setStyleInternal(PassRefPtr<RenderStyle>); 549 550 // returns the containing block level element for this element. 551 RenderBlock* containingBlock() const; 552 553 // Convert the given local point to absolute coordinates 554 // FIXME: Temporary. If useTransforms is true, take transforms into account. Eventually localToAbsolute() will always be transform-aware. 555 FloatPoint localToAbsolute(FloatPoint localPoint = FloatPoint(), bool fixed = false, bool useTransforms = false) const; 556 FloatPoint absoluteToLocal(FloatPoint, bool fixed = false, bool useTransforms = false) const; 557 558 // Convert a local quad to absolute coordinates, taking transforms into account. 559 FloatQuad localToAbsoluteQuad(const FloatQuad& quad, bool fixed = false) const 560 { 561 return localToContainerQuad(quad, 0, fixed); 562 } 563 // Convert a local quad into the coordinate system of container, taking transforms into account. 564 FloatQuad localToContainerQuad(const FloatQuad&, RenderBoxModelObject* repaintContainer, bool fixed = false) const; 565 566 // Return the offset from the container() renderer (excluding transforms) 567 virtual IntSize offsetFromContainer(RenderObject*) const; 568 // Return the offset from an object up the container() chain. Asserts that none of the intermediate objects have transforms. 569 IntSize offsetFromAncestorContainer(RenderObject*) const; 570 571 virtual void absoluteRects(Vector<IntRect>&, int, int) { } 572 // FIXME: useTransforms should go away eventually 573 IntRect absoluteBoundingBoxRect(bool useTransforms = false); 574 575 // Build an array of quads in absolute coords for line boxes 576 virtual void absoluteQuads(Vector<FloatQuad>&) { } 577 578 void absoluteFocusRingQuads(Vector<FloatQuad>&); 579 580 // the rect that will be painted if this object is passed as the paintingRoot 581 IntRect paintingRootRect(IntRect& topLevelRect); 582 583 virtual int minPrefWidth() const { return 0; } 584 virtual int maxPrefWidth() const { return 0; } 585 586 RenderStyle* style() const { return m_style.get(); } 587 RenderStyle* firstLineStyle() const { return document()->usesFirstLineRules() ? firstLineStyleSlowCase() : style(); } 588 RenderStyle* style(bool firstLine) const { return firstLine ? firstLineStyle() : style(); } 589 590 // Used only by Element::pseudoStyleCacheIsInvalid to get a first line style based off of a 591 // given new style, without accessing the cache. 592 PassRefPtr<RenderStyle> uncachedFirstLineStyle(RenderStyle*) const; 593 594 // Anonymous blocks that are part of of a continuation chain will return their inline continuation's outline style instead. 595 // This is typically only relevant when repainting. 596 virtual RenderStyle* outlineStyleForRepaint() const { return style(); } 597 598 void getTextDecorationColors(int decorations, Color& underline, Color& overline, 599 Color& linethrough, bool quirksMode = false); 600 601 // Return the RenderBox in the container chain which is responsible for painting this object, or 0 602 // if painting is root-relative. This is the container that should be passed to the 'forRepaint' 603 // methods. 604 RenderBoxModelObject* containerForRepaint() const; 605 // Actually do the repaint of rect r for this object which has been computed in the coordinate space 606 // of repaintContainer. If repaintContainer is 0, repaint via the view. 607 void repaintUsingContainer(RenderBoxModelObject* repaintContainer, const IntRect& r, bool immediate = false); 608 609 // Repaint the entire object. Called when, e.g., the color of a border changes, or when a border 610 // style changes. 611 void repaint(bool immediate = false); 612 613 // Repaint a specific subrectangle within a given object. The rect |r| is in the object's coordinate space. 614 void repaintRectangle(const IntRect&, bool immediate = false); 615 616 // Repaint only if our old bounds and new bounds are different. 617 bool repaintAfterLayoutIfNeeded(RenderBoxModelObject* repaintContainer, const IntRect& oldBounds, const IntRect& oldOutlineBox); 618 619 // Repaint only if the object moved. 620 virtual void repaintDuringLayoutIfMoved(const IntRect& rect); 621 622 // Called to repaint a block's floats. 623 virtual void repaintOverhangingFloats(bool paintAllDescendants = false); 624 625 bool checkForRepaintDuringLayout() const; 626 627 // Returns the rect that should be repainted whenever this object changes. The rect is in the view's 628 // coordinate space. This method deals with outlines and overflow. 629 IntRect absoluteClippedOverflowRect() 630 { 631 return clippedOverflowRectForRepaint(0); 632 } 633 virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer); 634 virtual IntRect rectWithOutlineForRepaint(RenderBoxModelObject* repaintContainer, int outlineWidth); 635 636 // Given a rect in the object's coordinate space, compute a rect suitable for repainting 637 // that rect in view coordinates. 638 void computeAbsoluteRepaintRect(IntRect& r, bool fixed = false) 639 { 640 return computeRectForRepaint(0, r, fixed); 641 } 642 // Given a rect in the object's coordinate space, compute a rect suitable for repainting 643 // that rect in the coordinate space of repaintContainer. 644 virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false); 645 646 virtual unsigned int length() const { return 1; } 647 648 bool isFloatingOrPositioned() const { return (isFloating() || isPositioned()); } 649 650 bool isTransparent() const { return style()->opacity() < 1.0f; } 651 float opacity() const { return style()->opacity(); } 652 653 bool hasReflection() const { return m_hasReflection; } 654 655 // Applied as a "slop" to dirty rect checks during the outline painting phase's dirty-rect checks. 656 int maximalOutlineSize(PaintPhase) const; 657 658 void setHasMarkupTruncation(bool b = true) { m_hasMarkupTruncation = b; } 659 bool hasMarkupTruncation() const { return m_hasMarkupTruncation; } 660 661 enum SelectionState { 662 SelectionNone, // The object is not selected. 663 SelectionStart, // The object either contains the start of a selection run or is the start of a run 664 SelectionInside, // The object is fully encompassed by a selection run 665 SelectionEnd, // The object either contains the end of a selection run or is the end of a run 666 SelectionBoth // The object contains an entire run or is the sole selected object in that run 667 }; 668 669 // The current selection state for an object. For blocks, the state refers to the state of the leaf 670 // descendants (as described above in the SelectionState enum declaration). 671 SelectionState selectionState() const { return static_cast<SelectionState>(m_selectionState);; } 672 673 // Sets the selection state for an object. 674 virtual void setSelectionState(SelectionState state) { m_selectionState = state; } 675 676 // A single rectangle that encompasses all of the selected objects within this object. Used to determine the tightest 677 // possible bounding box for the selection. 678 IntRect selectionRect(bool clipToVisibleContent = true) { return selectionRectForRepaint(0, clipToVisibleContent); } 679 virtual IntRect selectionRectForRepaint(RenderBoxModelObject* /*repaintContainer*/, bool /*clipToVisibleContent*/ = true) { return IntRect(); } 680 681 // Whether or not an object can be part of the leaf elements of the selection. 682 virtual bool canBeSelectionLeaf() const { return false; } 683 684 // Whether or not a block has selected children. 685 bool hasSelectedChildren() const { return m_selectionState != SelectionNone; } 686 687 // Obtains the selection colors that should be used when painting a selection. 688 Color selectionBackgroundColor() const; 689 Color selectionForegroundColor() const; 690 691 // Whether or not a given block needs to paint selection gaps. 692 virtual bool shouldPaintSelectionGaps() const { return false; } 693 694 #if ENABLE(DRAG_SUPPORT) 695 Node* draggableNode(bool dhtmlOK, bool uaOK, int x, int y, bool& dhtmlWillDrag) const; 696 #endif 697 698 /** 699 * Returns the local coordinates of the caret within this render object. 700 * @param caretOffset zero-based offset determining position within the render object. 701 * @param extraWidthToEndOfLine optional out arg to give extra width to end of line - 702 * useful for character range rect computations 703 */ 704 virtual IntRect localCaretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0); 705 706 virtual void calcVerticalMargins() { } 707 bool isTopMarginQuirk() const { return m_topMarginQuirk; } 708 bool isBottomMarginQuirk() const { return m_bottomMarginQuirk; } 709 void setTopMarginQuirk(bool b = true) { m_topMarginQuirk = b; } 710 void setBottomMarginQuirk(bool b = true) { m_bottomMarginQuirk = b; } 711 712 // When performing a global document tear-down, the renderer of the document is cleared. We use this 713 // as a hook to detect the case of document destruction and don't waste time doing unnecessary work. 714 bool documentBeingDestroyed() const; 715 716 virtual void destroy(); 717 718 // Virtual function helpers for CSS3 Flexible Box Layout 719 virtual bool isFlexibleBox() const { return false; } 720 virtual bool isFlexingChildren() const { return false; } 721 virtual bool isStretchingChildren() const { return false; } 722 723 virtual int caretMinOffset() const; 724 virtual int caretMaxOffset() const; 725 virtual unsigned caretMaxRenderedOffset() const; 726 727 virtual int previousOffset(int current) const; 728 virtual int previousOffsetForBackwardDeletion(int current) const; 729 virtual int nextOffset(int current) const; 730 731 virtual void imageChanged(CachedImage*, const IntRect* = 0); 732 virtual void imageChanged(WrappedImagePtr, const IntRect* = 0) { } 733 virtual bool willRenderImage(CachedImage*); 734 735 void selectionStartEnd(int& spos, int& epos) const; 736 737 RenderObject* paintingRootForChildren(PaintInfo& paintInfo) const 738 { 739 // if we're the painting root, kids draw normally, and see root of 0 740 return (!paintInfo.paintingRoot || paintInfo.paintingRoot == this) ? 0 : paintInfo.paintingRoot; 741 } 742 743 bool shouldPaintWithinRoot(PaintInfo& paintInfo) const 744 { 745 return !paintInfo.paintingRoot || paintInfo.paintingRoot == this; 746 } 747 748 bool hasOverrideSize() const { return m_hasOverrideSize; } 749 void setHasOverrideSize(bool b) { m_hasOverrideSize = b; } 750 751 void remove() { if (parent()) parent()->removeChild(this); } 752 753 AnimationController* animation() const; 754 755 bool visibleToHitTesting() const { return style()->visibility() == VISIBLE && style()->pointerEvents() != PE_NONE; } 756 757 // Map points and quads through elements, potentially via 3d transforms. You should never need to call these directly; use 758 // localToAbsolute/absoluteToLocal methods instead. 759 virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&) const; 760 virtual void mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState&) const; 761 762 bool shouldUseTransformFromContainer(const RenderObject* container) const; 763 void getTransformFromContainer(const RenderObject* container, const IntSize& offsetInContainer, TransformationMatrix&) const; 764 765 virtual void addFocusRingRects(Vector<IntRect>&, int /*tx*/, int /*ty*/) { }; 766 767 IntRect absoluteOutlineBounds() const 768 { 769 return outlineBoundsForRepaint(0); 770 } 771 772 protected: 773 // Overrides should call the superclass at the end 774 virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle); 775 // Overrides should call the superclass at the start 776 virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); 777 778 void paintOutline(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*); 779 void addPDFURLRect(GraphicsContext*, const IntRect&); 780 781 virtual IntRect viewRect() const; 782 783 void adjustRectForOutlineAndShadow(IntRect&) const; 784 785 void arenaDelete(RenderArena*, void* objectBase); 786 787 virtual IntRect outlineBoundsForRepaint(RenderBoxModelObject* /*repaintContainer*/) const { return IntRect(); } 788 789 class LayoutRepainter { 790 public: 791 LayoutRepainter(RenderObject& object, bool checkForRepaint, const IntRect* oldBounds = 0) 792 : m_object(object) 793 , m_repaintContainer(0) 794 , m_checkForRepaint(checkForRepaint) 795 { 796 if (m_checkForRepaint) { 797 m_repaintContainer = m_object.containerForRepaint(); 798 m_oldBounds = oldBounds ? *oldBounds : m_object.clippedOverflowRectForRepaint(m_repaintContainer); 799 m_oldOutlineBox = m_object.outlineBoundsForRepaint(m_repaintContainer); 800 } 801 } 802 803 // Return true if it repainted. 804 bool repaintAfterLayout() 805 { 806 return m_checkForRepaint ? m_object.repaintAfterLayoutIfNeeded(m_repaintContainer, m_oldBounds, m_oldOutlineBox) : false; 807 } 808 809 bool checkForRepaint() const { return m_checkForRepaint; } 810 811 private: 812 RenderObject& m_object; 813 RenderBoxModelObject* m_repaintContainer; 814 IntRect m_oldBounds; 815 IntRect m_oldOutlineBox; 816 bool m_checkForRepaint; 817 }; 818 819 private: 820 RenderStyle* firstLineStyleSlowCase() const; 821 StyleDifference adjustStyleDifference(StyleDifference, unsigned contextSensitiveProperties) const; 822 823 RefPtr<RenderStyle> m_style; 824 825 Node* m_node; 826 827 RenderObject* m_parent; 828 RenderObject* m_previous; 829 RenderObject* m_next; 830 831 #ifndef NDEBUG 832 bool m_hasAXObject; 833 bool m_setNeedsLayoutForbidden : 1; 834 #endif 835 836 // 32 bits have been used here. THERE ARE NO FREE BITS AVAILABLE. 837 bool m_needsLayout : 1; 838 bool m_needsPositionedMovementLayout :1; 839 bool m_normalChildNeedsLayout : 1; 840 bool m_posChildNeedsLayout : 1; 841 bool m_prefWidthsDirty : 1; 842 bool m_floating : 1; 843 844 bool m_positioned : 1; 845 bool m_relPositioned : 1; 846 bool m_paintBackground : 1; // if the box has something to paint in the 847 // background painting phase (background, border, etc) 848 849 bool m_isAnonymous : 1; 850 bool m_isText : 1; 851 bool m_isBox : 1; 852 bool m_inline : 1; 853 bool m_replaced : 1; 854 bool m_isDragging : 1; 855 856 bool m_hasLayer : 1; 857 bool m_hasOverflowClip : 1; 858 bool m_hasTransform : 1; 859 bool m_hasReflection : 1; 860 861 bool m_hasOverrideSize : 1; 862 863 public: 864 bool m_hasCounterNodeMap : 1; 865 bool m_everHadLayout : 1; 866 867 private: 868 // These bitfields are moved here from subclasses to pack them together 869 // from RenderBlock 870 bool m_childrenInline : 1; 871 bool m_topMarginQuirk : 1; 872 bool m_bottomMarginQuirk : 1; 873 bool m_hasMarkupTruncation : 1; 874 unsigned m_selectionState : 3; // SelectionState 875 bool m_hasColumns : 1; 876 877 // from RenderTableCell 878 bool m_cellWidthChanged : 1; 879 880 private: 881 // Store state between styleWillChange and styleDidChange 882 static bool s_affectsParentBlock; 883 }; 884 885 inline bool RenderObject::documentBeingDestroyed() const 886 { 887 return !document()->renderer(); 888 } 889 890 inline bool RenderObject::isAfterContent() const 891 { 892 if (style()->styleType() != AFTER) 893 return false; 894 // Text nodes don't have their own styles, so ignore the style on a text node. 895 if (isText() && !isBR()) 896 return false; 897 return true; 898 } 899 900 inline void RenderObject::setNeedsLayout(bool b, bool markParents) 901 { 902 bool alreadyNeededLayout = m_needsLayout; 903 m_needsLayout = b; 904 if (b) { 905 ASSERT(!isSetNeedsLayoutForbidden()); 906 if (!alreadyNeededLayout) { 907 if (markParents) 908 markContainingBlocksForLayout(); 909 if (hasLayer()) 910 setLayerNeedsFullRepaint(); 911 } 912 } else { 913 m_everHadLayout = true; 914 m_posChildNeedsLayout = false; 915 m_normalChildNeedsLayout = false; 916 m_needsPositionedMovementLayout = false; 917 } 918 } 919 920 inline void RenderObject::setChildNeedsLayout(bool b, bool markParents) 921 { 922 bool alreadyNeededLayout = m_normalChildNeedsLayout; 923 m_normalChildNeedsLayout = b; 924 if (b) { 925 ASSERT(!isSetNeedsLayoutForbidden()); 926 if (!alreadyNeededLayout && markParents) 927 markContainingBlocksForLayout(); 928 } else { 929 m_posChildNeedsLayout = false; 930 m_normalChildNeedsLayout = false; 931 m_needsPositionedMovementLayout = false; 932 } 933 } 934 935 inline void RenderObject::setNeedsPositionedMovementLayout() 936 { 937 bool alreadyNeededLayout = needsLayout(); 938 m_needsPositionedMovementLayout = true; 939 if (!alreadyNeededLayout) { 940 markContainingBlocksForLayout(); 941 if (hasLayer()) 942 setLayerNeedsFullRepaint(); 943 } 944 } 945 946 inline bool objectIsRelayoutBoundary(const RenderObject *obj) 947 { 948 // FIXME: In future it may be possible to broaden this condition in order to improve performance. 949 // Table cells are excluded because even when their CSS height is fixed, their height() 950 // may depend on their contents. 951 return obj->isTextControl() 952 || (obj->hasOverflowClip() && !obj->style()->width().isIntrinsicOrAuto() && !obj->style()->height().isIntrinsicOrAuto() && !obj->style()->height().isPercent() && !obj->isTableCell()) 953 #if ENABLE(SVG) 954 || obj->isSVGRoot() 955 #endif 956 ; 957 } 958 959 inline void RenderObject::markContainingBlocksForLayout(bool scheduleRelayout, RenderObject* newRoot) 960 { 961 ASSERT(!scheduleRelayout || !newRoot); 962 963 RenderObject* o = container(); 964 RenderObject* last = this; 965 966 while (o) { 967 // Don't mark the outermost object of an unrooted subtree. That object will be 968 // marked when the subtree is added to the document. 969 RenderObject* container = o->container(); 970 if (!container && !o->isRenderView()) 971 return; 972 if (!last->isText() && (last->style()->position() == FixedPosition || last->style()->position() == AbsolutePosition)) { 973 if ((last->style()->top().isAuto() && last->style()->bottom().isAuto()) || last->style()->top().isStatic()) { 974 RenderObject* parent = last->parent(); 975 if (!parent->normalChildNeedsLayout()) { 976 parent->setChildNeedsLayout(true, false); 977 if (parent != newRoot) 978 parent->markContainingBlocksForLayout(scheduleRelayout, newRoot); 979 } 980 } 981 if (o->m_posChildNeedsLayout) 982 return; 983 o->m_posChildNeedsLayout = true; 984 ASSERT(!o->isSetNeedsLayoutForbidden()); 985 } else { 986 if (o->m_normalChildNeedsLayout) 987 return; 988 o->m_normalChildNeedsLayout = true; 989 ASSERT(!o->isSetNeedsLayoutForbidden()); 990 } 991 992 if (o == newRoot) 993 return; 994 995 last = o; 996 if (scheduleRelayout && objectIsRelayoutBoundary(last)) 997 break; 998 o = container; 999 } 1000 1001 if (scheduleRelayout) 1002 last->scheduleRelayout(); 1003 } 1004 1005 inline void makeMatrixRenderable(TransformationMatrix& matrix, bool has3DRendering) 1006 { 1007 #if !ENABLE(3D_RENDERING) 1008 UNUSED_PARAM(has3DRendering); 1009 matrix.makeAffine(); 1010 #else 1011 if (!has3DRendering) 1012 matrix.makeAffine(); 1013 #endif 1014 } 1015 1016 inline int adjustForAbsoluteZoom(int value, RenderObject* renderer) 1017 { 1018 float zoomFactor = renderer->style()->effectiveZoom(); 1019 if (zoomFactor == 1) 1020 return value; 1021 // Needed because computeLengthInt truncates (rather than rounds) when scaling up. 1022 if (zoomFactor > 1) 1023 value++; 1024 return static_cast<int>(value / zoomFactor); 1025 } 1026 1027 inline void adjustIntRectForAbsoluteZoom(IntRect& rect, RenderObject* renderer) 1028 { 1029 rect.setX(adjustForAbsoluteZoom(rect.x(), renderer)); 1030 rect.setY(adjustForAbsoluteZoom(rect.y(), renderer)); 1031 rect.setWidth(adjustForAbsoluteZoom(rect.width(), renderer)); 1032 rect.setHeight(adjustForAbsoluteZoom(rect.height(), renderer)); 1033 } 1034 1035 inline FloatPoint adjustFloatPointForAbsoluteZoom(const FloatPoint& point, RenderObject* renderer) 1036 { 1037 // The result here is in floats, so we don't need the truncation hack from the integer version above. 1038 float zoomFactor = renderer->style()->effectiveZoom(); 1039 if (zoomFactor == 1) 1040 return point; 1041 return FloatPoint(point.x() / zoomFactor, point.y() / zoomFactor); 1042 } 1043 1044 inline void adjustFloatQuadForAbsoluteZoom(FloatQuad& quad, RenderObject* renderer) 1045 { 1046 quad.setP1(adjustFloatPointForAbsoluteZoom(quad.p1(), renderer)); 1047 quad.setP2(adjustFloatPointForAbsoluteZoom(quad.p2(), renderer)); 1048 quad.setP3(adjustFloatPointForAbsoluteZoom(quad.p3(), renderer)); 1049 quad.setP4(adjustFloatPointForAbsoluteZoom(quad.p4(), renderer)); 1050 } 1051 1052 } // namespace WebCore 1053 1054 #ifndef NDEBUG 1055 // Outside the WebCore namespace for ease of invocation from gdb. 1056 void showTree(const WebCore::RenderObject*); 1057 void showRenderTree(const WebCore::RenderObject* object1); 1058 // We don't make object2 an optional parameter so that showRenderTree 1059 // can be called from gdb easily. 1060 void showRenderTree(const WebCore::RenderObject* object1, const WebCore::RenderObject* object2); 1061 #endif 1062 1063 #endif // RenderObject_h 1064