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