1 /* 2 * This file is part of the html renderer for KDE. 3 * 4 * Copyright (C) 2000-2003 Lars Knoll (knoll@kde.org) 5 * (C) 2000 Antti Koivisto (koivisto@kde.org) 6 * (C) 2000-2003 Dirk Mueller (mueller@kde.org) 7 * (C) 2002-2003 Apple Computer, Inc. 8 * (C) 2004 Allan Sandfeld Jensen 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Library General Public 12 * License as published by the Free Software Foundation; either 13 * version 2 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Library General Public License for more details. 19 * 20 * You should have received a copy of the GNU Library General Public License 21 * along with this library; see the file COPYING.LIB. If not, write to 22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 23 * Boston, MA 02110-1301, USA. 24 * 25 */ 26 #ifndef render_object_h 27 #define render_object_h 28 29 #include <QColor> 30 #include <QRect> 31 #include <assert.h> 32 #include <QList> 33 34 #include <QDebug> 35 36 #include "xml/dom_docimpl.h" 37 #include "misc/khtmllayout.h" 38 #include "misc/loader_client.h" 39 #include "misc/helper.h" 40 #include "rendering/render_style.h" 41 #include "rendering/render_position.h" 42 #include <QTextStream> 43 44 // svg 45 #include "FloatRect.h" 46 #include "AffineTransform.h" 47 48 using WebCore::FloatRect; 49 using WebCore::AffineTransform; 50 51 class QPainter; 52 class QTextStream; 53 template<class Key, class T> class QCache; 54 55 #ifndef NDEBUG 56 #define KHTMLAssert( x ) if( !(x) ) { \ 57 const RenderObject *o = this; while( o->parent() ) o = o->parent(); \ 58 o->printTree(); \ 59 qDebug(" this object = %p", (void*) this); \ 60 assert( x ); \ 61 } 62 #else 63 #define KHTMLAssert( x ) 64 #endif 65 66 /* 67 * The painting of a layer occurs in three distinct phases. Each phase involves 68 * a recursive descent into the layer's render objects. The first phase is the background phase. 69 * The backgrounds and borders of all blocks are painted. Inlines are not painted at all. 70 * Floats must paint above block backgrounds but entirely below inline content that can overlap them. 71 * In the foreground phase, all inlines are fully painted. Inline replaced elements will get all 72 * three phases invoked on them during this phase. 73 */ 74 75 typedef enum { 76 PaintActionElementBackground = 0, 77 PaintActionChildBackground, 78 PaintActionChildBackgrounds, 79 PaintActionFloat, 80 PaintActionForeground, 81 PaintActionOutline, 82 PaintActionSelection, 83 PaintActionCollapsedTableBorders 84 } PaintAction; 85 86 typedef enum { 87 HitTestAll = 0, 88 HitTestSelfOnly = 1, 89 HitTestChildrenOnly = 2 90 } HitTestAction; 91 92 typedef enum { 93 PageBreakNormal = 0, // all rules apply 94 PageBreakHarder = 1, // page-break-inside: avoid is ignored 95 PageBreakForced = 2 // page-break-after/before: avoid, orphans and widows ignored 96 } PageBreakLevel; 97 98 typedef enum { 99 LowPriority = 0, 100 NormalPriority = 1, 101 HighPriority = 2, 102 RealtimePriority = 3 103 } Priority; 104 105 inline PageBreakLevel operator| (PageBreakLevel a, PageBreakLevel b) 106 { 107 if (a == PageBreakForced || b == PageBreakForced) { 108 return PageBreakForced; 109 } 110 if (a == PageBreakHarder || b == PageBreakHarder) { 111 return PageBreakHarder; 112 } 113 return PageBreakNormal; 114 } 115 116 namespace DOM 117 { 118 class HTMLAreaElementImpl; 119 class NodeImpl; 120 class DocumentImpl; 121 class ElementImpl; 122 class EventImpl; 123 class Selection; 124 } 125 126 namespace khtml 127 { 128 class RenderFlow; 129 class RenderStyle; 130 class CachedObject; 131 class RenderObject; 132 class RenderCanvas; 133 class RenderText; 134 class RenderFrameSet; 135 class RenderArena; 136 class RenderLayer; 137 class RenderBlock; 138 class InlineBox; 139 class InlineFlowBox; 140 class CounterNode; 141 class RenderPosition; 142 143 /** 144 * Base Class for all rendering tree objects. 145 */ 146 class RenderObject : public CachedObjectClient 147 { 148 RenderObject(const RenderObject &); 149 RenderObject &operator=(const RenderObject &); 150 public: 151 KHTML_EXPORT static void cleanup(); 152 153 RenderObject(DOM::NodeImpl *node); 154 virtual ~RenderObject(); 155 parent()156 RenderObject *parent() const 157 { 158 return m_parent; 159 } 160 previousSibling()161 RenderObject *previousSibling() const 162 { 163 return m_previous; 164 } nextSibling()165 RenderObject *nextSibling() const 166 { 167 return m_next; 168 } 169 firstChild()170 virtual RenderObject *firstChild() const 171 { 172 return nullptr; 173 } lastChild()174 virtual RenderObject *lastChild() const 175 { 176 return nullptr; 177 } 178 179 RenderObject *nextRenderer() const; 180 RenderObject *previousRenderer() const; 181 182 RenderObject *nextEditable() const; 183 RenderObject *previousEditable() const; 184 185 RenderObject *firstLeafChild() const; 186 RenderObject *lastLeafChild() const; 187 childAllowed()188 virtual bool childAllowed() const 189 { 190 return false; 191 } borderTopExtra()192 virtual int borderTopExtra() const 193 { 194 return 0; 195 } borderBottomExtra()196 virtual int borderBottomExtra() const 197 { 198 return 0; 199 } 200 layer()201 virtual RenderLayer *layer() const 202 { 203 return nullptr; 204 } 205 RenderLayer *enclosingLayer() const; 206 RenderLayer *enclosingStackingContext() const; 207 void addLayers(RenderLayer *parentLayer, RenderObject *newObject); 208 void removeLayers(RenderLayer *parentLayer); 209 void moveLayers(RenderLayer *oldParent, RenderLayer *newParent); 210 RenderLayer *findNextLayer(RenderLayer *parentLayer, RenderObject *startPoint, 211 bool checkParent = true); positionChildLayers()212 virtual void positionChildLayers() { } requiresLayer()213 virtual bool requiresLayer() const 214 { 215 return isRoot()/* ### */ || isPositioned() || isRelPositioned() || hasOverflowClip() || style()->opacity() < 1.0f; 216 } 217 overflowClipRect(int,int)218 virtual QRect overflowClipRect(int /*tx*/, int /*ty*/) 219 { 220 return QRect(0, 0, 0, 0); 221 } clipRect(int,int)222 virtual QRect clipRect(int /*tx*/, int /*ty*/) 223 { 224 return QRect(0, 0, 0, 0); 225 } hasClip()226 bool hasClip() const 227 { 228 return isPositioned() && style()->hasClip(); 229 } hasOverflowClip()230 bool hasOverflowClip() const 231 { 232 return m_hasOverflowClip; 233 } 234 scrollsOverflow()235 bool scrollsOverflow() const 236 { 237 return scrollsOverflowX() || scrollsOverflowY(); 238 } scrollsOverflowX()239 bool scrollsOverflowX() const 240 { 241 return hasOverflowClip() && (style()->overflowX() == OSCROLL || style()->overflowX() == OAUTO); 242 } scrollsOverflowY()243 bool scrollsOverflowY() const 244 { 245 return hasOverflowClip() && (style()->overflowY() == OSCROLL || style()->overflowY() == OAUTO); 246 } 247 getBaselineOfFirstLineBox()248 virtual int getBaselineOfFirstLineBox() 249 { 250 return -1; // Tables and blocks implement this. 251 } getFirstLineBox()252 virtual InlineFlowBox *getFirstLineBox() 253 { 254 return nullptr; // Tables and blocks implement this. 255 } 256 257 // Whether or not a positioned element requires normal flow x/y to be computed 258 // to determine its position. hasStaticX()259 bool hasStaticX() const 260 { 261 return style()->left().isAuto() && style()->right().isAuto(); 262 } hasStaticY()263 bool hasStaticY() const 264 { 265 return style()->top().isAuto() && style()->bottom().isAuto(); 266 } isPosWithStaticDim()267 bool isPosWithStaticDim() const 268 { 269 return isPositioned() && (hasStaticX() || hasStaticY()); 270 } 271 272 // Linear tree traversal 273 RenderObject *objectBelow() const; 274 RenderObject *objectAbove() const; 275 276 // Returns if an object has counter-increment or counter-reset 277 bool hasCounter(const DOMString &counter) const; 278 // Calculates the value of the counter 279 CounterNode *getCounter(const DOMString &counter, bool view = false, bool counters = false); 280 // Detaches all counterNodes 281 void detachCounters(); 282 283 protected: 284 // Helper functions for counter-cache 285 void insertCounter(const DOMString &counter, CounterNode *value); 286 CounterNode *lookupCounter(const DOMString &counter) const; 287 288 public: 289 ////////////////////////////////////////// 290 // RenderObject tree manipulation 291 virtual void addChild(RenderObject *newChild, RenderObject *beforeChild = nullptr); 292 virtual void removeChild(RenderObject *oldChild); 293 294 // raw tree manipulation 295 virtual RenderObject *removeChildNode(RenderObject *child); 296 virtual void appendChildNode(RenderObject *child); 297 virtual void insertChildNode(RenderObject *child, RenderObject *before); 298 ////////////////////////////////////////// 299 300 ////////////////////////////////////////// 301 // Helper functions. Dangerous to use! setPreviousSibling(RenderObject * previous)302 void setPreviousSibling(RenderObject *previous) 303 { 304 m_previous = previous; 305 } setNextSibling(RenderObject * next)306 void setNextSibling(RenderObject *next) 307 { 308 m_next = next; 309 } setParent(RenderObject * parent)310 void setParent(RenderObject *parent) 311 { 312 m_parent = parent; 313 } 314 ////////////////////////////////////////// 315 316 public: renderName()317 virtual const char *renderName() const 318 { 319 return "RenderObject"; 320 } 321 #ifdef ENABLE_DUMP 322 QString information() const; 323 virtual void printTree(int indent = 0) const; 324 virtual void dump(QTextStream &stream, const QString &ind = QString()) const; 325 void printLineBoxTree() const; 326 #endif 327 328 static RenderObject *createObject(DOM::NodeImpl *node, RenderStyle *style); 329 330 // Overloaded new operator. Derived classes must override operator new 331 // in order to allocate out of the RenderArena. 332 void *operator new(size_t sz, RenderArena *renderArena) throw(); 333 334 // Overridden to prevent the normal delete from being called. 335 void operator delete(void *ptr, size_t sz); 336 337 private: 338 // The normal operator new is disallowed on all render objects. 339 void *operator new(size_t sz); 340 341 public: 342 RenderArena *renderArena() const; continuation()343 virtual RenderFlow *continuation() const 344 { 345 return nullptr; 346 } isInlineContinuation()347 virtual bool isInlineContinuation() const 348 { 349 return false; 350 } 351 isRoot()352 bool isRoot() const 353 { 354 return m_isRoot && !m_isAnonymous; 355 } setIsRoot(bool b)356 void setIsRoot(bool b) 357 { 358 m_isRoot = b; 359 } 360 bool isHR() const; 361 // some helper functions... isRenderBlock()362 virtual bool isRenderBlock() const 363 { 364 return false; 365 } isRenderInline()366 virtual bool isRenderInline() const 367 { 368 return false; 369 } isInlineFlow()370 virtual bool isInlineFlow() const 371 { 372 return false; 373 } isBlockFlow()374 virtual bool isBlockFlow() const 375 { 376 return false; 377 } isInlineBlockOrInlineTable()378 virtual bool isInlineBlockOrInlineTable() const 379 { 380 return false; 381 } childrenInline()382 virtual bool childrenInline() const 383 { 384 return false; 385 } isBox()386 virtual bool isBox() const 387 { 388 return false; 389 } isRenderReplaced()390 virtual bool isRenderReplaced() const 391 { 392 return false; 393 } 394 isGlyph()395 virtual bool isGlyph() const 396 { 397 return false; 398 } isCounter()399 virtual bool isCounter() const 400 { 401 return false; 402 } isQuote()403 virtual bool isQuote() const 404 { 405 return false; 406 } isListItem()407 virtual bool isListItem() const 408 { 409 return false; 410 } isListMarker()411 virtual bool isListMarker() const 412 { 413 return false; 414 } isCanvas()415 virtual bool isCanvas() const 416 { 417 return false; 418 } isBR()419 virtual bool isBR() const 420 { 421 return false; 422 } isTableCell()423 virtual bool isTableCell() const 424 { 425 return false; 426 } isTableRow()427 virtual bool isTableRow() const 428 { 429 return false; 430 } isTableSection()431 virtual bool isTableSection() const 432 { 433 return false; 434 } isTableCol()435 virtual bool isTableCol() const 436 { 437 return false; 438 } isTable()439 virtual bool isTable() const 440 { 441 return false; 442 } isWidget()443 virtual bool isWidget() const 444 { 445 return false; 446 } isBody()447 virtual bool isBody() const 448 { 449 return false; 450 } isFormElement()451 virtual bool isFormElement() const 452 { 453 return false; 454 } isFrameSet()455 virtual bool isFrameSet() const 456 { 457 return false; 458 } isApplet()459 virtual bool isApplet() const 460 { 461 return false; 462 } isMedia()463 virtual bool isMedia() const 464 { 465 return false; 466 } 467 468 virtual bool isEditable() const; 469 470 // svg isSVGRoot()471 virtual bool isSVGRoot() const 472 { 473 return false; 474 } isRenderPath()475 virtual bool isRenderPath() const 476 { 477 return false; 478 } isSVGContainer()479 virtual bool isSVGContainer() const 480 { 481 return false; 482 } isSVGText()483 virtual bool isSVGText() const 484 { 485 return false; 486 } isSVGHiddenContainer()487 virtual bool isSVGHiddenContainer() const 488 { 489 return false; 490 } 491 492 virtual FloatRect relativeBBox(bool includeStroke = false) const; 493 494 virtual AffineTransform localTransform() const; 495 virtual AffineTransform absoluteTransform() const; 496 // end svg 497 498 bool isHTMLMarquee() const; 499 bool isWordBreak() const; 500 isAnonymous()501 bool isAnonymous() const 502 { 503 return m_isAnonymous; 504 } setIsAnonymous(bool b)505 void setIsAnonymous(bool b) 506 { 507 m_isAnonymous = b; 508 } isAnonymousBlock()509 bool isAnonymousBlock() const 510 { 511 return isAnonymous() && style()->display() == BLOCK && node()->isDocumentNode(); 512 } isPseudoAnonymous()513 bool isPseudoAnonymous() const 514 { 515 return isAnonymous() && !node()->isDocumentNode(); 516 } 517 isFloating()518 bool isFloating() const 519 { 520 return m_floating; 521 } isPositioned()522 bool isPositioned() const 523 { 524 return m_positioned; 525 } isRelPositioned()526 bool isRelPositioned() const 527 { 528 return m_relPositioned; 529 } isText()530 bool isText() const 531 { 532 return m_isText; 533 } isInline()534 bool isInline() const 535 { 536 return m_inline; 537 } isCompact()538 bool isCompact() const 539 { 540 return style()->display() == COMPACT; // compact 541 } isRunIn()542 bool isRunIn() const 543 { 544 return style()->display() == RUN_IN; // run-in object 545 } 546 bool mouseInside() const; 547 bool isDragging() const; isReplaced()548 bool isReplaced() const 549 { 550 return m_replaced; 551 } isReplacedBlock()552 bool isReplacedBlock() const 553 { 554 return isInline() && isReplaced() && isRenderBlock(); 555 } shouldPaintBackgroundOrBorder()556 bool shouldPaintBackgroundOrBorder() const 557 { 558 return m_paintBackground; 559 } needsLayout()560 bool needsLayout() const 561 { 562 return m_needsLayout || m_normalChildNeedsLayout || m_posChildNeedsLayout; 563 } markedForRepaint()564 bool markedForRepaint() const 565 { 566 return m_markedForRepaint; 567 } setMarkedForRepaint(bool m)568 void setMarkedForRepaint(bool m) 569 { 570 m_markedForRepaint = m; 571 } selfNeedsLayout()572 bool selfNeedsLayout() const 573 { 574 return m_needsLayout; 575 } posChildNeedsLayout()576 bool posChildNeedsLayout() const 577 { 578 return m_posChildNeedsLayout; 579 } normalChildNeedsLayout()580 bool normalChildNeedsLayout() const 581 { 582 return m_normalChildNeedsLayout; 583 } minMaxKnown()584 bool minMaxKnown() const 585 { 586 return m_minMaxKnown; 587 } hasFirstLine()588 bool hasFirstLine() const 589 { 590 return m_hasFirstLine; 591 } isSelectionBorder()592 bool isSelectionBorder() const 593 { 594 return m_isSelectionBorder; 595 } recalcMinMax()596 bool recalcMinMax() const 597 { 598 return m_recalcMinMax; 599 } 600 601 RenderCanvas *canvas() const; 602 // don't even think about making this method virtual! 603 DOM::DocumentImpl *document() const; element()604 DOM::NodeImpl *element() const 605 { 606 return isAnonymous() ? nullptr : m_node; 607 } node()608 DOM::NodeImpl *node() const 609 { 610 return m_node; 611 } 612 handleEvent(const DOM::EventImpl &)613 virtual bool handleEvent(const DOM::EventImpl &) 614 { 615 return false; 616 } 617 618 /** 619 * returns the object containing this one. can be different from parent for 620 * positioned elements 621 */ 622 RenderObject *container() const; 623 624 void markContainingBlocksForLayout(); 625 void dirtyFormattingContext(bool checkContainer); 626 void repaintDuringLayout(); 627 void setNeedsLayout(bool b, bool markParents = true); 628 void setChildNeedsLayout(bool b, bool markParents = true); 629 void setMinMaxKnown(bool b = true) 630 { 631 m_minMaxKnown = b; 632 if (!b) { 633 RenderObject *o = this; 634 while (o) { // ### && !o->m_recalcMinMax ) { 635 o->m_recalcMinMax = true; 636 o = o->m_parent; 637 } 638 } 639 } setNeedsLayoutAndMinMaxRecalc()640 void setNeedsLayoutAndMinMaxRecalc() 641 { 642 setMinMaxKnown(false); 643 setNeedsLayout(true); 644 } 645 void setPositioned(bool b = true) 646 { 647 m_positioned = b; 648 } 649 void setRelPositioned(bool b = true) 650 { 651 m_relPositioned = b; 652 } 653 void setFloating(bool b = true) 654 { 655 m_floating = b; 656 } 657 void setInline(bool b = true) 658 { 659 m_inline = b; 660 } 661 void setMouseInside(bool b = true) 662 { 663 m_mouseInside = b; 664 } 665 void setShouldPaintBackgroundOrBorder(bool b = true) 666 { 667 m_paintBackground = b; 668 } setRenderText()669 void setRenderText() 670 { 671 m_isText = true; 672 } 673 void setReplaced(bool b = true) 674 { 675 m_replaced = b; 676 } 677 void setHasOverflowClip(bool b = true) 678 { 679 m_hasOverflowClip = b; 680 } 681 void setIsSelectionBorder(bool b = true) 682 { 683 m_isSelectionBorder = b; 684 } 685 686 void scheduleRelayout(RenderObject *clippedObj = nullptr); 687 688 void updateBackgroundImages(RenderStyle *oldStyle); 689 690 virtual InlineBox *createInlineBox(bool makePlaceHolderBox, bool isRootLineBox); removeInlineBox(InlineBox *)691 virtual void removeInlineBox(InlineBox * /*box*/) {} 692 693 virtual InlineBox *inlineBox(long offset = 0); 694 virtual short lineHeight(bool firstLine) const; 695 virtual short verticalPositionHint(bool firstLine) const; 696 virtual short baselinePosition(bool firstLine) const; 697 short getVerticalPosition(bool firstLine, RenderObject *ref = nullptr) const; 698 699 /* 700 * Print the object and its children, clipped by (x|y|w|h). 701 * (tx|ty) is the calculated position of the parent 702 */ 703 struct PaintInfo { PaintInfoPaintInfo704 PaintInfo(QPainter *_p, const QRect &_r, PaintAction _phase) 705 : p(_p), r(_r), phase(_phase), outlineObjects(nullptr) {} ~PaintInfoPaintInfo706 ~PaintInfo() 707 { 708 delete outlineObjects; 709 } 710 QPainter *p; 711 QRect r; 712 PaintAction phase; 713 QList<RenderFlow *> *outlineObjects; // used to list which outlines should be painted by a block with inline children 714 }; 715 virtual void paint(PaintInfo &i, int tx, int ty); 716 717 void calcBorderRadii(QPoint &topLeftRadii, QPoint &topRightRadii, QPoint &bottomLeftRadii, QPoint &bottomRightRadii, int w, int h) const; 718 719 void drawBorderArc(QPainter *p, int x, int y, float horThickness, float vertThickness, 720 const QPoint &radius, int angleStart, int angleSpan, const QBrush &brush, 721 const QColor &textColor, EBorderStyle style, qreal *dashOffset = nullptr) const; 722 723 void paintBorder(QPainter *p, int _tx, int _ty, int w, int h, const RenderStyle *style, bool begin = true, bool end = true); 724 void paintOutline(QPainter *p, int _tx, int _ty, int w, int h, const RenderStyle *style); 725 paintBoxDecorations(PaintInfo &,int,int)726 virtual void paintBoxDecorations(PaintInfo &, int /*_tx*/, int /*_ty*/) {} 727 paintBackgroundExtended(QPainter *,const QColor &,const BackgroundLayer *,QRect,int,int,int,int,int,int,int,int,int,int,int,int)728 virtual void paintBackgroundExtended(QPainter * /*p*/, const QColor & /*c*/, const BackgroundLayer * /*bgLayer*/, 729 QRect /*clipr*/, int /*_tx*/, int /*_ty*/, 730 int /*w*/, int /*height*/, int /*bleft*/, int /*bright*/, int /*pleft*/, int /*pright*/, 731 int /*btop*/, int /*bbottom*/, int /*ptop*/, int /*pbottom*/) {} 732 733 /* 734 * This function calculates the minimum & maximum width that the object 735 * can be set to. 736 * 737 * when the Element calls setMinMaxKnown(true), calcMinMaxWidth() will 738 * be no longer called. 739 * 740 * when a element has a fixed size, m_minWidth and m_maxWidth should be 741 * set to the same value. This has the special meaning that m_width, 742 * contains the actual value. 743 * 744 * assumes calcMinMaxWidth has already been called for all children. 745 */ calcMinMaxWidth()746 virtual void calcMinMaxWidth() { } 747 748 /* 749 * Does the min max width recalculations after changes. 750 */ 751 void recalcMinMaxWidths(); 752 753 /* 754 * Calculates the actual width of the object (only for non inline 755 * objects) 756 */ calcWidth()757 virtual void calcWidth() {} 758 759 /* 760 * Calculates the actual width of the object (only for non inline 761 * objects) 762 */ calcHeight()763 virtual void calcHeight() {} 764 765 /* 766 * This function should cause the Element to calculate its 767 * width and height and the layout of its content 768 * 769 * when the Element calls setNeedsLayout(false), layout() is no 770 * longer called during relayouts, as long as there is no 771 * style sheet change. When that occurs, m_needsLayout will be 772 * set to true and the Element receives layout() calls 773 * again. 774 */ 775 virtual void layout() = 0; 776 777 /* This function performs a layout only if one is needed. */ layoutIfNeeded()778 void layoutIfNeeded() 779 { 780 if (needsLayout()) { 781 layout(); 782 } 783 } 784 785 // used for element state updates that can not be fixed with a 786 // repaint and do not need a relayout updateFromElement()787 virtual void updateFromElement() {} 788 789 // Called immediately after render-object is inserted attach()790 virtual void attach() 791 { 792 m_attached = true; 793 } attached()794 bool attached() 795 { 796 return m_attached; 797 } 798 // The corresponding closing element has been parsed. ### remove me close()799 virtual void close() { } 800 availableHeight()801 virtual int availableHeight() const 802 { 803 return 0; 804 } 805 806 // Whether or not the element shrinks to its max width (rather than filling the width 807 // of a containing block). HTML4 buttons, legends, and floating/compact elements do this. 808 bool sizesToMaxWidth() const; 809 810 /* 811 * NeesPageClear indicates the object crossed a page-break but could not break itself and now 812 * needs to be moved clear by its parent. 813 */ 814 void setNeedsPageClear(bool b = true) 815 { 816 m_needsPageClear = b; 817 } needsPageClear()818 virtual bool needsPageClear() const 819 { 820 return m_needsPageClear; 821 } 822 823 /* 824 * ContainsPageBreak indicates the object contains a clean page-break. 825 * ### should be removed and replaced with (crossesPageBreak && !needsPageClear) 826 */ 827 void setContainsPageBreak(bool b = true) 828 { 829 m_containsPageBreak = b; 830 } containsPageBreak()831 virtual bool containsPageBreak() const 832 { 833 return m_containsPageBreak; 834 } 835 pageTopAfter(int y)836 virtual int pageTopAfter(int y) const 837 { 838 if (parent()) { 839 return parent()->pageTopAfter(y); 840 } else { 841 return 0; 842 } 843 } 844 crossesPageBreak(int top,int bottom)845 virtual int crossesPageBreak(int top, int bottom) const 846 { 847 if (parent()) { 848 return parent()->crossesPageBreak(top, bottom); 849 } else { 850 return 0; 851 } 852 } 853 854 // Checks if a page-break before child is possible at the given page-break level 855 // false means the child should attempt the break self. canClear(RenderObject *,PageBreakLevel level)856 virtual bool canClear(RenderObject * /*child*/, PageBreakLevel level) 857 { 858 if (parent()) { 859 return parent()->canClear(this, level); 860 } else { 861 return false; 862 } 863 } 864 865 void setAfterPageBreak(bool b = true) 866 { 867 m_afterPageBreak = b; 868 } 869 void setBeforePageBreak(bool b = true) 870 { 871 m_beforePageBreak = b; 872 } afterPageBreak()873 virtual bool afterPageBreak() const 874 { 875 return m_afterPageBreak; 876 } beforePageBreak()877 virtual bool beforePageBreak() const 878 { 879 return m_beforePageBreak; 880 } 881 882 // does a query on the rendertree and finds the innernode 883 // and overURL for the given position 884 // if readonly == false, it will recalc hover styles accordingly 885 class NodeInfo 886 { 887 friend class RenderImage; 888 friend class RenderFlow; 889 friend class RenderInline; 890 friend class RenderText; 891 friend class RenderWidget; 892 friend class RenderObject; 893 friend class RenderFrameSet; 894 friend class RenderLayer; 895 friend class DOM::HTMLAreaElementImpl; 896 public: NodeInfo(bool readonly,bool active)897 NodeInfo(bool readonly, bool active) 898 : m_innerNode(nullptr), m_innerNonSharedNode(nullptr), m_innerURLElement(nullptr), m_readonly(readonly), m_active(active) 899 { } 900 innerNode()901 DOM::NodeImpl *innerNode() const 902 { 903 return m_innerNode; 904 } innerNonSharedNode()905 DOM::NodeImpl *innerNonSharedNode() const 906 { 907 return m_innerNonSharedNode; 908 } URLElement()909 DOM::NodeImpl *URLElement() const 910 { 911 return m_innerURLElement; 912 } readonly()913 bool readonly() const 914 { 915 return m_readonly; 916 } active()917 bool active() const 918 { 919 return m_active; 920 } 921 922 private: setInnerNode(DOM::NodeImpl * n)923 void setInnerNode(DOM::NodeImpl *n) 924 { 925 m_innerNode = n; 926 } setInnerNonSharedNode(DOM::NodeImpl * n)927 void setInnerNonSharedNode(DOM::NodeImpl *n) 928 { 929 m_innerNonSharedNode = n; 930 } setURLElement(DOM::NodeImpl * n)931 void setURLElement(DOM::NodeImpl *n) 932 { 933 m_innerURLElement = n; 934 } 935 936 DOM::NodeImpl *m_innerNode; 937 DOM::NodeImpl *m_innerNonSharedNode; 938 DOM::NodeImpl *m_innerURLElement; 939 bool m_readonly; 940 bool m_active; 941 }; 942 943 /** contains stateful information for a checkSelectionPoint call 944 */ 945 struct SelPointState { 946 /** last node that was before the current position */ 947 DOM::NodeImpl *m_lastNode; 948 /** offset of last node */ 949 long m_lastOffset; 950 /** true when the last node had the result SelectionAfterInLine */ 951 bool m_afterInLine; 952 SelPointStateSelPointState953 SelPointState() : m_lastNode(nullptr), m_lastOffset(0), m_afterInLine(false) 954 {} 955 }; 956 957 #if 0 958 virtual FindSelectionResult checkSelectionPoint(int _x, int _y, int _tx, int _ty, 959 DOM::NodeImpl *&, int &offset, 960 SelPointState &); 961 #endif 962 virtual bool nodeAtPoint(NodeInfo &info, int x, int y, int tx, int ty, HitTestAction, bool inside = false); 963 void setInnerNode(NodeInfo &info); 964 965 // Position/Selection stuff 966 virtual RenderPosition positionForCoordinates(int x, int y); 967 968 // set the style of the object. 969 virtual void setStyle(RenderStyle *style); 970 971 // returns the containing block level element for this element. 972 RenderBlock *containingBlock() const; 973 974 // return just the width of the containing block 975 virtual short containingBlockWidth(RenderObject *providedCB = nullptr) const; 976 // return just the height of the containing block 977 virtual int containingBlockHeight(RenderObject *providedCB = nullptr) const; 978 979 // size of the content area (box size minus padding/border) contentWidth()980 virtual short contentWidth() const 981 { 982 return 0; 983 } contentHeight()984 virtual int contentHeight() const 985 { 986 return 0; 987 } 988 989 // intrinsic extend of replaced elements. undefined otherwise intrinsicWidth()990 virtual short intrinsicWidth() const 991 { 992 return 0; 993 } intrinsicHeight()994 virtual int intrinsicHeight() const 995 { 996 return 0; 997 } 998 999 // relative to parent node setPos(int,int)1000 virtual void setPos(int /*xPos*/, int /*yPos*/) { } setWidth(int)1001 virtual void setWidth(int /*width*/) { } setHeight(int)1002 virtual void setHeight(int /*height*/) { } 1003 xPos()1004 virtual int xPos() const 1005 { 1006 return 0; 1007 } yPos()1008 virtual int yPos() const 1009 { 1010 return 0; 1011 } 1012 1013 /** the position of the object from where it begins drawing, including 1014 * its negative overflow 1015 */ effectiveXPos()1016 int effectiveXPos() const 1017 { 1018 return xPos() + (hasOverflowClip() ? 0 : overflowLeft()); 1019 } 1020 1021 /** the position of the object from where it begins drawing, including 1022 * its negative overflow 1023 */ effectiveYPos()1024 int effectiveYPos() const 1025 { 1026 return yPos() + (hasOverflowClip() ? -borderTopExtra() : qMin(overflowTop(), -borderTopExtra())); 1027 } 1028 1029 /** Leftmost coordinate of this inline element relative to containing 1030 * block. Always zero for non-inline elements. 1031 */ inlineXPos()1032 virtual int inlineXPos() const 1033 { 1034 return 0; 1035 } 1036 /** Topmost coordinate of this inline element relative to containing 1037 * block. Always zero for non-inline elements. 1038 */ inlineYPos()1039 virtual int inlineYPos() const 1040 { 1041 return 0; 1042 } 1043 1044 // calculate client position of box 1045 virtual bool absolutePosition(int &/*xPos*/, int &/*yPos*/, bool fixed = false) const; 1046 1047 // width and height are without margins but include paddings and borders width()1048 virtual short width() const 1049 { 1050 return 0; 1051 } height()1052 virtual int height() const 1053 { 1054 return 0; 1055 } 1056 1057 // The height of a block when you include overflow spillage out of 1058 // the bottom of the block (e.g., a <div style="height:25px"> that 1059 // has a 100px tall image inside it would have an overflow height 1060 // of borderTop() + paddingTop() + 100px. overflowHeight()1061 virtual int overflowHeight() const 1062 { 1063 return height(); 1064 } overflowWidth()1065 virtual int overflowWidth() const 1066 { 1067 return width(); 1068 } 1069 // how much goes over the left hand side (0 or a negative number) overflowTop()1070 virtual int overflowTop() const 1071 { 1072 return 0; 1073 } overflowLeft()1074 virtual int overflowLeft() const 1075 { 1076 return 0; 1077 } 1078 1079 /** 1080 * Returns the height that is effectively considered when contemplating the 1081 * object as a whole -- usually the overflow height, or the height if clipped. 1082 */ effectiveHeight()1083 int effectiveHeight() const 1084 { 1085 return hasOverflowClip() ? height() + borderTopExtra() + borderBottomExtra() : 1086 qMax(overflowHeight() - overflowTop(), height() + borderTopExtra() + borderBottomExtra()); 1087 } 1088 /** 1089 * Returns the width that is effectively considered when contemplating the 1090 * object as a whole -- usually the overflow width, or the width if clipped. 1091 */ effectiveWidth()1092 int effectiveWidth() const 1093 { 1094 return hasOverflowClip() ? width() : overflowWidth() - overflowLeft(); 1095 } 1096 1097 QRectF clientRectToViewport(const QRectF &rect); 1098 virtual QList< QRectF > getClientRects(); 1099 1100 // IE extensions, heavily used in ECMA offsetWidth()1101 virtual short offsetWidth() const 1102 { 1103 return width(); 1104 } offsetHeight()1105 virtual int offsetHeight() const 1106 { 1107 return height() + borderTopExtra() + borderBottomExtra(); 1108 } 1109 virtual int offsetLeft() const; 1110 virtual int offsetTop() const; 1111 virtual RenderObject *offsetParent() const; 1112 int clientLeft() const; 1113 int clientTop() const; 1114 short clientWidth() const; 1115 int clientHeight() const; 1116 virtual short scrollWidth() const; 1117 virtual int scrollHeight() const; 1118 isSelfCollapsingBlock()1119 virtual bool isSelfCollapsingBlock() const 1120 { 1121 return false; 1122 } collapsedMarginTop()1123 short collapsedMarginTop() const 1124 { 1125 return maxTopMargin(true) - maxTopMargin(false); 1126 } collapsedMarginBottom()1127 short collapsedMarginBottom() const 1128 { 1129 return maxBottomMargin(true) - maxBottomMargin(false); 1130 } 1131 isTopMarginQuirk()1132 virtual bool isTopMarginQuirk() const 1133 { 1134 return false; 1135 } isBottomMarginQuirk()1136 virtual bool isBottomMarginQuirk() const 1137 { 1138 return false; 1139 } maxTopMargin(bool positive)1140 virtual short maxTopMargin(bool positive) const 1141 { 1142 return positive ? qMax(int(marginTop()), 0) : - qMin(int(marginTop()), 0); 1143 } maxBottomMargin(bool positive)1144 virtual short maxBottomMargin(bool positive) const 1145 { 1146 return positive ? qMax(int(marginBottom()), 0) : - qMin(int(marginBottom()), 0); 1147 } 1148 marginTop()1149 virtual short marginTop() const 1150 { 1151 return 0; 1152 } marginBottom()1153 virtual short marginBottom() const 1154 { 1155 return 0; 1156 } marginLeft()1157 virtual short marginLeft() const 1158 { 1159 return 0; 1160 } marginRight()1161 virtual short marginRight() const 1162 { 1163 return 0; 1164 } 1165 1166 virtual int paddingTop() const; 1167 virtual int paddingBottom() const; 1168 virtual int paddingLeft() const; 1169 virtual int paddingRight() const; 1170 borderTop()1171 virtual int borderTop() const 1172 { 1173 return style()->borderTopWidth(); 1174 } borderBottom()1175 virtual int borderBottom() const 1176 { 1177 return style()->borderBottomWidth(); 1178 } borderLeft()1179 virtual int borderLeft() const 1180 { 1181 return style()->borderLeftWidth(); 1182 } borderRight()1183 virtual int borderRight() const 1184 { 1185 return style()->borderRightWidth(); 1186 } 1187 minWidth()1188 virtual short minWidth() const 1189 { 1190 return 0; 1191 } maxWidth()1192 virtual int maxWidth() const 1193 { 1194 return 0; 1195 } 1196 style()1197 RenderStyle *style() const 1198 { 1199 return m_style; 1200 } style(bool firstLine)1201 RenderStyle *style(bool firstLine) const 1202 { 1203 RenderStyle *s = m_style; 1204 if (firstLine && hasFirstLine()) { 1205 RenderStyle *pseudoStyle = style()->getPseudoStyle(RenderStyle::FIRST_LINE); 1206 if (pseudoStyle) { 1207 s = pseudoStyle; 1208 } 1209 } 1210 return s; 1211 } 1212 1213 void getTextDecorationColors(int decorations, QColor &underline, QColor &overline, 1214 QColor &linethrough, bool quirksMode = false); 1215 1216 enum BorderSide { 1217 BSTop, BSBottom, BSLeft, BSRight 1218 }; 1219 void drawBorder(QPainter *p, int x1, int y1, int x2, int y2, BorderSide s, 1220 QColor c, const QColor &textcolor, EBorderStyle style, 1221 int adjbw1, int adjbw2, bool invalidisInvert = false, qreal *dashOffset = nullptr); 1222 1223 // Used by collapsed border tables. 1224 virtual void collectBorders(QList<CollapsedBorderValue> &borderStyles); 1225 1226 // force a complete repaint 1227 virtual void repaint(Priority p = NormalPriority) 1228 { 1229 if (m_parent) { 1230 m_parent->repaint(p); 1231 } 1232 } 1233 virtual void repaintRectangle(int x, int y, int w, int h, Priority p = NormalPriority, bool f = false); 1234 length()1235 virtual unsigned int length() const 1236 { 1237 return 1; 1238 } 1239 isHidden()1240 virtual bool isHidden() const 1241 { 1242 return isFloating() || isPositioned(); 1243 } 1244 1245 // Special objects are objects that are neither really inline nor blocklevel isFloatingOrPositioned()1246 bool isFloatingOrPositioned() const 1247 { 1248 return (isFloating() || isPositioned()); 1249 } hasOverhangingFloats()1250 virtual bool hasOverhangingFloats() const 1251 { 1252 return false; 1253 } hasFloats()1254 virtual bool hasFloats() const 1255 { 1256 return false; 1257 } containsFloat(RenderObject *)1258 virtual bool containsFloat(RenderObject * /*o*/) const 1259 { 1260 return false; 1261 } 1262 virtual void markAllDescendantsWithFloatsForLayout(RenderObject * /*floatToRemove*/ = nullptr) {} 1263 1264 bool flowAroundFloats() const; 1265 bool usesLineWidth() const; 1266 1267 // positioning of inline children (bidi) position(InlineBox *,int,int,bool)1268 virtual void position(InlineBox *, int, int, bool) {} 1269 // virtual void position(int, int, int, int, int, bool, bool, int) {} 1270 1271 // Applied as a "slop" to dirty rect checks during the outline painting phase's dirty-rect checks. 1272 int maximalOutlineSize(PaintAction p) const; 1273 1274 enum SelectionState { 1275 SelectionNone, 1276 SelectionStart, 1277 SelectionInside, 1278 SelectionEnd, 1279 SelectionBoth 1280 }; 1281 selectionState()1282 virtual SelectionState selectionState() const 1283 { 1284 return SelectionNone; 1285 } setSelectionState(SelectionState)1286 virtual void setSelectionState(SelectionState) {} 1287 bool shouldSelect() const; 1288 virtual bool isPointInsideSelection(int x, int y, const DOM::Selection &) const; 1289 1290 DOM::NodeImpl *draggableNode(bool dhtmlOK, bool uaOK, bool &dhtmlWillDrag) const; 1291 1292 /** 1293 * Flags which influence the appearance and position 1294 * @param CFOverride input overrides existing character, caret should be 1295 * cover the whole character 1296 * @param CFOutside coordinates are to be interpreted outside of the 1297 * render object 1298 * @param CFOutsideEnd coordinates are to be interpreted at the outside 1299 * end of the render object (only valid if CFOutside is also set) 1300 */ 1301 enum CaretFlags { CFOverride = 0x01, CFOutside = 0x02, CFOutsideEnd = 0x04 }; 1302 1303 /** 1304 * Returns the content coordinates of the caret within this render object. 1305 * @param offset zero-based offset determining position within the render object. 1306 * @param flags combination of enum CaretFlags 1307 * @param _x returns the left coordinate 1308 * @param _y returns the top coordinate 1309 * @param width returns the caret's width 1310 * @param height returns the caret's height 1311 */ 1312 virtual void caretPos(int offset, int flags, int &_x, int &_y, int &width, int &height) const; 1313 1314 // returns the lowest position of the lowest object in that particular object. 1315 // This 'height' is relative to the topleft of the margin box of the object. 1316 // Implemented in RenderFlow. 1317 virtual int lowestPosition(bool /*includeOverflowInterior*/ = true, bool /*includeSelf*/ = true) const 1318 { 1319 return 0; 1320 } 1321 virtual int rightmostPosition(bool /*includeOverflowInterior*/ = true, bool /*includeSelf*/ = true) const 1322 { 1323 return 0; 1324 } 1325 virtual int leftmostPosition(bool /*includeOverflowInterior*/ = true, bool /*includeSelf*/ = true) const 1326 { 1327 return 0; 1328 } 1329 virtual int highestPosition(bool /*includeOverflowInterior*/ = true, bool /*includeSelf*/ = true) const 1330 { 1331 return 0; 1332 } 1333 1334 // recursively invalidate current layout 1335 // unused: void invalidateLayout(); 1336 calcVerticalMargins()1337 virtual void calcVerticalMargins() {} 1338 void removeFromObjectLists(); 1339 void setInPosObjectList(bool b = true) 1340 { 1341 m_inPosObjectList = b; 1342 } inPosObjectList()1343 bool inPosObjectList() const 1344 { 1345 return m_inPosObjectList; 1346 } 1347 1348 virtual void deleteInlineBoxes(RenderArena *arena = nullptr) 1349 { 1350 (void)arena; 1351 } 1352 virtual void dirtyInlineBoxes(bool /*fullLayout*/, bool /*isRootLineBox*/ = false) {} dirtyLinesFromChangedChild(RenderObject *)1353 virtual void dirtyLinesFromChangedChild(RenderObject *) {} 1354 virtual void detach(); 1355 documentBeingDestroyed()1356 bool documentBeingDestroyed() const 1357 { 1358 return !document()->renderer(); 1359 } 1360 setDoNotDelete(bool b)1361 void setDoNotDelete(bool b) 1362 { 1363 m_doNotDelete = b; 1364 } doNotDelete()1365 bool doNotDelete() const 1366 { 1367 return m_doNotDelete; 1368 } 1369 font(bool firstLine)1370 const QFont &font(bool firstLine) const 1371 { 1372 return style(firstLine)->font(); 1373 } 1374 fontMetrics(bool firstLine)1375 const QFontMetrics &fontMetrics(bool firstLine) const 1376 { 1377 return style(firstLine)->fontMetrics(); 1378 } 1379 1380 /** returns the lowest possible value the caret offset may have to 1381 * still point to a valid position. 1382 * 1383 * Returns 0 by default. 1384 */ 1385 virtual long caretMinOffset() const; 1386 /** returns the highest possible value the caret offset may have to 1387 * still point to a valid position. 1388 * 1389 * Returns 0 by default, as generic elements are considered to have no 1390 * width. 1391 */ 1392 virtual long caretMaxOffset() const; 1393 virtual unsigned long caretMaxRenderedOffset() const; 1394 1395 void updatePixmap(const QRect &, CachedImage *) override; 1396 1397 QRegion visibleFlowRegion(int x, int y) const; 1398 removeSuperfluousAnonymousBlockChild(RenderObject *)1399 virtual void removeSuperfluousAnonymousBlockChild(RenderObject *) {} 1400 1401 // Unregisters from parent but does not destroy 1402 void remove(); 1403 protected: 1404 virtual void selectionStartEnd(int &spos, int &epos); 1405 1406 virtual QRect viewRect() const; setDetached()1407 void setDetached() 1408 { 1409 m_attached = false; 1410 } 1411 void invalidateVerticalPosition(); 1412 bool attemptDirectLayerTranslation(); 1413 void updateWidgetMasks(); 1414 1415 void arenaDelete(RenderArena *arena); 1416 1417 private: 1418 RenderStyle *m_style; 1419 DOM::NodeImpl *m_node; 1420 RenderObject *m_parent; 1421 RenderObject *m_previous; 1422 RenderObject *m_next; 1423 1424 short m_verticalPosition; 1425 1426 bool m_needsLayout : 1; 1427 bool m_normalChildNeedsLayout : 1; 1428 bool m_markedForRepaint : 1; 1429 bool m_posChildNeedsLayout : 1; 1430 1431 bool m_minMaxKnown : 1; 1432 bool m_floating : 1; 1433 1434 bool m_positioned : 1; 1435 bool m_relPositioned : 1; 1436 bool m_paintBackground : 1; // if the box has something to paint in the 1437 // background painting phase (background, border, etc) 1438 1439 bool m_isAnonymous : 1; 1440 bool m_recalcMinMax : 1; 1441 bool m_isText : 1; 1442 bool m_inline : 1; 1443 bool m_attached : 1; 1444 1445 bool m_replaced : 1; 1446 bool m_mouseInside : 1; 1447 bool m_hasFirstLine : 1; 1448 bool m_isSelectionBorder : 1; 1449 1450 bool m_isRoot : 1; 1451 1452 bool m_beforePageBreak : 1; 1453 bool m_afterPageBreak : 1; 1454 1455 bool m_needsPageClear : 1; 1456 bool m_containsPageBreak : 1; 1457 1458 bool m_hasOverflowClip : 1; 1459 bool m_inPosObjectList : 1; 1460 1461 bool m_doNotDelete : 1; // This object should not be auto-deleted 1462 1463 // ### we have 16 + 26 bits. 1464 1465 static QCache<quint64, QPixmap> *s_dashedLineCache; 1466 1467 void arenaDelete(RenderArena *arena, void *objectBase); 1468 1469 friend class RenderLayer; 1470 friend class RenderListItem; 1471 friend class RenderContainer; 1472 friend class RenderCanvas; 1473 }; 1474 1475 enum VerticalPositionHint { 1476 PositionTop = -0x4000, 1477 PositionBottom = 0x4000, 1478 PositionUndefined = 0x3fff 1479 }; 1480 1481 } //namespace 1482 #endif 1483