File indexing completed on 2025-04-27 10:07:36
0001 /* 0002 * This file is part of the html renderer for KDE. 0003 * 0004 * Copyright (C) 2000-2003 Lars Knoll (knoll@kde.org) 0005 * (C) 2000 Antti Koivisto (koivisto@kde.org) 0006 * (C) 2000-2003 Dirk Mueller (mueller@kde.org) 0007 * (C) 2002-2003 Apple Computer, Inc. 0008 * (C) 2004 Allan Sandfeld Jensen 0009 * 0010 * This library is free software; you can redistribute it and/or 0011 * modify it under the terms of the GNU Library General Public 0012 * License as published by the Free Software Foundation; either 0013 * version 2 of the License, or (at your option) any later version. 0014 * 0015 * This library is distributed in the hope that it will be useful, 0016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0018 * Library General Public License for more details. 0019 * 0020 * You should have received a copy of the GNU Library General Public License 0021 * along with this library; see the file COPYING.LIB. If not, write to 0022 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0023 * Boston, MA 02110-1301, USA. 0024 * 0025 */ 0026 #ifndef render_object_h 0027 #define render_object_h 0028 0029 #include <QColor> 0030 #include <QRect> 0031 #include <assert.h> 0032 #include <QList> 0033 0034 #include <QDebug> 0035 0036 #include "xml/dom_docimpl.h" 0037 #include "misc/khtmllayout.h" 0038 #include "misc/loader_client.h" 0039 #include "misc/helper.h" 0040 #include "rendering/render_style.h" 0041 #include "rendering/render_position.h" 0042 #include <QTextStream> 0043 0044 // svg 0045 #include "FloatRect.h" 0046 #include "AffineTransform.h" 0047 0048 using WebCore::FloatRect; 0049 using WebCore::AffineTransform; 0050 0051 class QPainter; 0052 class QTextStream; 0053 template<class Key, class T> class QCache; 0054 0055 #ifndef NDEBUG 0056 #define KHTMLAssert( x ) if( !(x) ) { \ 0057 const RenderObject *o = this; while( o->parent() ) o = o->parent(); \ 0058 o->printTree(); \ 0059 qDebug(" this object = %p", (void*) this); \ 0060 assert( x ); \ 0061 } 0062 #else 0063 #define KHTMLAssert( x ) 0064 #endif 0065 0066 /* 0067 * The painting of a layer occurs in three distinct phases. Each phase involves 0068 * a recursive descent into the layer's render objects. The first phase is the background phase. 0069 * The backgrounds and borders of all blocks are painted. Inlines are not painted at all. 0070 * Floats must paint above block backgrounds but entirely below inline content that can overlap them. 0071 * In the foreground phase, all inlines are fully painted. Inline replaced elements will get all 0072 * three phases invoked on them during this phase. 0073 */ 0074 0075 typedef enum { 0076 PaintActionElementBackground = 0, 0077 PaintActionChildBackground, 0078 PaintActionChildBackgrounds, 0079 PaintActionFloat, 0080 PaintActionForeground, 0081 PaintActionOutline, 0082 PaintActionSelection, 0083 PaintActionCollapsedTableBorders 0084 } PaintAction; 0085 0086 typedef enum { 0087 HitTestAll = 0, 0088 HitTestSelfOnly = 1, 0089 HitTestChildrenOnly = 2 0090 } HitTestAction; 0091 0092 typedef enum { 0093 PageBreakNormal = 0, // all rules apply 0094 PageBreakHarder = 1, // page-break-inside: avoid is ignored 0095 PageBreakForced = 2 // page-break-after/before: avoid, orphans and widows ignored 0096 } PageBreakLevel; 0097 0098 typedef enum { 0099 LowPriority = 0, 0100 NormalPriority = 1, 0101 HighPriority = 2, 0102 RealtimePriority = 3 0103 } Priority; 0104 0105 inline PageBreakLevel operator| (PageBreakLevel a, PageBreakLevel b) 0106 { 0107 if (a == PageBreakForced || b == PageBreakForced) { 0108 return PageBreakForced; 0109 } 0110 if (a == PageBreakHarder || b == PageBreakHarder) { 0111 return PageBreakHarder; 0112 } 0113 return PageBreakNormal; 0114 } 0115 0116 namespace DOM 0117 { 0118 class HTMLAreaElementImpl; 0119 class NodeImpl; 0120 class DocumentImpl; 0121 class ElementImpl; 0122 class EventImpl; 0123 class Selection; 0124 } 0125 0126 namespace khtml 0127 { 0128 class RenderFlow; 0129 class RenderStyle; 0130 class CachedObject; 0131 class RenderObject; 0132 class RenderCanvas; 0133 class RenderText; 0134 class RenderFrameSet; 0135 class RenderArena; 0136 class RenderLayer; 0137 class RenderBlock; 0138 class InlineBox; 0139 class InlineFlowBox; 0140 class CounterNode; 0141 class RenderPosition; 0142 0143 /** 0144 * Base Class for all rendering tree objects. 0145 */ 0146 class RenderObject : public CachedObjectClient 0147 { 0148 RenderObject(const RenderObject &); 0149 RenderObject &operator=(const RenderObject &); 0150 public: 0151 KHTML_EXPORT static void cleanup(); 0152 0153 RenderObject(DOM::NodeImpl *node); 0154 virtual ~RenderObject(); 0155 0156 RenderObject *parent() const 0157 { 0158 return m_parent; 0159 } 0160 0161 RenderObject *previousSibling() const 0162 { 0163 return m_previous; 0164 } 0165 RenderObject *nextSibling() const 0166 { 0167 return m_next; 0168 } 0169 0170 virtual RenderObject *firstChild() const 0171 { 0172 return nullptr; 0173 } 0174 virtual RenderObject *lastChild() const 0175 { 0176 return nullptr; 0177 } 0178 0179 RenderObject *nextRenderer() const; 0180 RenderObject *previousRenderer() const; 0181 0182 RenderObject *nextEditable() const; 0183 RenderObject *previousEditable() const; 0184 0185 RenderObject *firstLeafChild() const; 0186 RenderObject *lastLeafChild() const; 0187 0188 virtual bool childAllowed() const 0189 { 0190 return false; 0191 } 0192 virtual int borderTopExtra() const 0193 { 0194 return 0; 0195 } 0196 virtual int borderBottomExtra() const 0197 { 0198 return 0; 0199 } 0200 0201 virtual RenderLayer *layer() const 0202 { 0203 return nullptr; 0204 } 0205 RenderLayer *enclosingLayer() const; 0206 RenderLayer *enclosingStackingContext() const; 0207 void addLayers(RenderLayer *parentLayer, RenderObject *newObject); 0208 void removeLayers(RenderLayer *parentLayer); 0209 void moveLayers(RenderLayer *oldParent, RenderLayer *newParent); 0210 RenderLayer *findNextLayer(RenderLayer *parentLayer, RenderObject *startPoint, 0211 bool checkParent = true); 0212 virtual void positionChildLayers() { } 0213 virtual bool requiresLayer() const 0214 { 0215 return isRoot()/* ### */ || isPositioned() || isRelPositioned() || hasOverflowClip() || style()->opacity() < 1.0f; 0216 } 0217 0218 virtual QRect overflowClipRect(int /*tx*/, int /*ty*/) 0219 { 0220 return QRect(0, 0, 0, 0); 0221 } 0222 virtual QRect clipRect(int /*tx*/, int /*ty*/) 0223 { 0224 return QRect(0, 0, 0, 0); 0225 } 0226 bool hasClip() const 0227 { 0228 return isPositioned() && style()->hasClip(); 0229 } 0230 bool hasOverflowClip() const 0231 { 0232 return m_hasOverflowClip; 0233 } 0234 0235 bool scrollsOverflow() const 0236 { 0237 return scrollsOverflowX() || scrollsOverflowY(); 0238 } 0239 bool scrollsOverflowX() const 0240 { 0241 return hasOverflowClip() && (style()->overflowX() == OSCROLL || style()->overflowX() == OAUTO); 0242 } 0243 bool scrollsOverflowY() const 0244 { 0245 return hasOverflowClip() && (style()->overflowY() == OSCROLL || style()->overflowY() == OAUTO); 0246 } 0247 0248 virtual int getBaselineOfFirstLineBox() 0249 { 0250 return -1; // Tables and blocks implement this. 0251 } 0252 virtual InlineFlowBox *getFirstLineBox() 0253 { 0254 return nullptr; // Tables and blocks implement this. 0255 } 0256 0257 // Whether or not a positioned element requires normal flow x/y to be computed 0258 // to determine its position. 0259 bool hasStaticX() const 0260 { 0261 return style()->left().isAuto() && style()->right().isAuto(); 0262 } 0263 bool hasStaticY() const 0264 { 0265 return style()->top().isAuto() && style()->bottom().isAuto(); 0266 } 0267 bool isPosWithStaticDim() const 0268 { 0269 return isPositioned() && (hasStaticX() || hasStaticY()); 0270 } 0271 0272 // Linear tree traversal 0273 RenderObject *objectBelow() const; 0274 RenderObject *objectAbove() const; 0275 0276 // Returns if an object has counter-increment or counter-reset 0277 bool hasCounter(const DOMString &counter) const; 0278 // Calculates the value of the counter 0279 CounterNode *getCounter(const DOMString &counter, bool view = false, bool counters = false); 0280 // Detaches all counterNodes 0281 void detachCounters(); 0282 0283 protected: 0284 // Helper functions for counter-cache 0285 void insertCounter(const DOMString &counter, CounterNode *value); 0286 CounterNode *lookupCounter(const DOMString &counter) const; 0287 0288 public: 0289 ////////////////////////////////////////// 0290 // RenderObject tree manipulation 0291 virtual void addChild(RenderObject *newChild, RenderObject *beforeChild = nullptr); 0292 virtual void removeChild(RenderObject *oldChild); 0293 0294 // raw tree manipulation 0295 virtual RenderObject *removeChildNode(RenderObject *child); 0296 virtual void appendChildNode(RenderObject *child); 0297 virtual void insertChildNode(RenderObject *child, RenderObject *before); 0298 ////////////////////////////////////////// 0299 0300 ////////////////////////////////////////// 0301 // Helper functions. Dangerous to use! 0302 void setPreviousSibling(RenderObject *previous) 0303 { 0304 m_previous = previous; 0305 } 0306 void setNextSibling(RenderObject *next) 0307 { 0308 m_next = next; 0309 } 0310 void setParent(RenderObject *parent) 0311 { 0312 m_parent = parent; 0313 } 0314 ////////////////////////////////////////// 0315 0316 public: 0317 virtual const char *renderName() const 0318 { 0319 return "RenderObject"; 0320 } 0321 #ifdef ENABLE_DUMP 0322 QString information() const; 0323 virtual void printTree(int indent = 0) const; 0324 virtual void dump(QTextStream &stream, const QString &ind = QString()) const; 0325 void printLineBoxTree() const; 0326 #endif 0327 0328 static RenderObject *createObject(DOM::NodeImpl *node, RenderStyle *style); 0329 0330 // Overloaded new operator. Derived classes must override operator new 0331 // in order to allocate out of the RenderArena. 0332 void *operator new(size_t sz, RenderArena *renderArena) throw(); 0333 0334 // Overridden to prevent the normal delete from being called. 0335 void operator delete(void *ptr, size_t sz); 0336 0337 private: 0338 // The normal operator new is disallowed on all render objects. 0339 void *operator new(size_t sz); 0340 0341 public: 0342 RenderArena *renderArena() const; 0343 virtual RenderFlow *continuation() const 0344 { 0345 return nullptr; 0346 } 0347 virtual bool isInlineContinuation() const 0348 { 0349 return false; 0350 } 0351 0352 bool isRoot() const 0353 { 0354 return m_isRoot && !m_isAnonymous; 0355 } 0356 void setIsRoot(bool b) 0357 { 0358 m_isRoot = b; 0359 } 0360 bool isHR() const; 0361 // some helper functions... 0362 virtual bool isRenderBlock() const 0363 { 0364 return false; 0365 } 0366 virtual bool isRenderInline() const 0367 { 0368 return false; 0369 } 0370 virtual bool isInlineFlow() const 0371 { 0372 return false; 0373 } 0374 virtual bool isBlockFlow() const 0375 { 0376 return false; 0377 } 0378 virtual bool isInlineBlockOrInlineTable() const 0379 { 0380 return false; 0381 } 0382 virtual bool childrenInline() const 0383 { 0384 return false; 0385 } 0386 virtual bool isBox() const 0387 { 0388 return false; 0389 } 0390 virtual bool isRenderReplaced() const 0391 { 0392 return false; 0393 } 0394 0395 virtual bool isGlyph() const 0396 { 0397 return false; 0398 } 0399 virtual bool isCounter() const 0400 { 0401 return false; 0402 } 0403 virtual bool isQuote() const 0404 { 0405 return false; 0406 } 0407 virtual bool isListItem() const 0408 { 0409 return false; 0410 } 0411 virtual bool isListMarker() const 0412 { 0413 return false; 0414 } 0415 virtual bool isCanvas() const 0416 { 0417 return false; 0418 } 0419 virtual bool isBR() const 0420 { 0421 return false; 0422 } 0423 virtual bool isTableCell() const 0424 { 0425 return false; 0426 } 0427 virtual bool isTableRow() const 0428 { 0429 return false; 0430 } 0431 virtual bool isTableSection() const 0432 { 0433 return false; 0434 } 0435 virtual bool isTableCol() const 0436 { 0437 return false; 0438 } 0439 virtual bool isTable() const 0440 { 0441 return false; 0442 } 0443 virtual bool isWidget() const 0444 { 0445 return false; 0446 } 0447 virtual bool isBody() const 0448 { 0449 return false; 0450 } 0451 virtual bool isFormElement() const 0452 { 0453 return false; 0454 } 0455 virtual bool isFrameSet() const 0456 { 0457 return false; 0458 } 0459 virtual bool isApplet() const 0460 { 0461 return false; 0462 } 0463 virtual bool isMedia() const 0464 { 0465 return false; 0466 } 0467 0468 virtual bool isEditable() const; 0469 0470 // svg 0471 virtual bool isSVGRoot() const 0472 { 0473 return false; 0474 } 0475 virtual bool isRenderPath() const 0476 { 0477 return false; 0478 } 0479 virtual bool isSVGContainer() const 0480 { 0481 return false; 0482 } 0483 virtual bool isSVGText() const 0484 { 0485 return false; 0486 } 0487 virtual bool isSVGHiddenContainer() const 0488 { 0489 return false; 0490 } 0491 0492 virtual FloatRect relativeBBox(bool includeStroke = false) const; 0493 0494 virtual AffineTransform localTransform() const; 0495 virtual AffineTransform absoluteTransform() const; 0496 // end svg 0497 0498 bool isHTMLMarquee() const; 0499 bool isWordBreak() const; 0500 0501 bool isAnonymous() const 0502 { 0503 return m_isAnonymous; 0504 } 0505 void setIsAnonymous(bool b) 0506 { 0507 m_isAnonymous = b; 0508 } 0509 bool isAnonymousBlock() const 0510 { 0511 return isAnonymous() && style()->display() == BLOCK && node()->isDocumentNode(); 0512 } 0513 bool isPseudoAnonymous() const 0514 { 0515 return isAnonymous() && !node()->isDocumentNode(); 0516 } 0517 0518 bool isFloating() const 0519 { 0520 return m_floating; 0521 } 0522 bool isPositioned() const 0523 { 0524 return m_positioned; 0525 } 0526 bool isRelPositioned() const 0527 { 0528 return m_relPositioned; 0529 } 0530 bool isText() const 0531 { 0532 return m_isText; 0533 } 0534 bool isInline() const 0535 { 0536 return m_inline; 0537 } 0538 bool isCompact() const 0539 { 0540 return style()->display() == COMPACT; // compact 0541 } 0542 bool isRunIn() const 0543 { 0544 return style()->display() == RUN_IN; // run-in object 0545 } 0546 bool mouseInside() const; 0547 bool isDragging() const; 0548 bool isReplaced() const 0549 { 0550 return m_replaced; 0551 } 0552 bool isReplacedBlock() const 0553 { 0554 return isInline() && isReplaced() && isRenderBlock(); 0555 } 0556 bool shouldPaintBackgroundOrBorder() const 0557 { 0558 return m_paintBackground; 0559 } 0560 bool needsLayout() const 0561 { 0562 return m_needsLayout || m_normalChildNeedsLayout || m_posChildNeedsLayout; 0563 } 0564 bool markedForRepaint() const 0565 { 0566 return m_markedForRepaint; 0567 } 0568 void setMarkedForRepaint(bool m) 0569 { 0570 m_markedForRepaint = m; 0571 } 0572 bool selfNeedsLayout() const 0573 { 0574 return m_needsLayout; 0575 } 0576 bool posChildNeedsLayout() const 0577 { 0578 return m_posChildNeedsLayout; 0579 } 0580 bool normalChildNeedsLayout() const 0581 { 0582 return m_normalChildNeedsLayout; 0583 } 0584 bool minMaxKnown() const 0585 { 0586 return m_minMaxKnown; 0587 } 0588 bool hasFirstLine() const 0589 { 0590 return m_hasFirstLine; 0591 } 0592 bool isSelectionBorder() const 0593 { 0594 return m_isSelectionBorder; 0595 } 0596 bool recalcMinMax() const 0597 { 0598 return m_recalcMinMax; 0599 } 0600 0601 RenderCanvas *canvas() const; 0602 // don't even think about making this method virtual! 0603 DOM::DocumentImpl *document() const; 0604 DOM::NodeImpl *element() const 0605 { 0606 return isAnonymous() ? nullptr : m_node; 0607 } 0608 DOM::NodeImpl *node() const 0609 { 0610 return m_node; 0611 } 0612 0613 virtual bool handleEvent(const DOM::EventImpl &) 0614 { 0615 return false; 0616 } 0617 0618 /** 0619 * returns the object containing this one. can be different from parent for 0620 * positioned elements 0621 */ 0622 RenderObject *container() const; 0623 0624 void markContainingBlocksForLayout(); 0625 void dirtyFormattingContext(bool checkContainer); 0626 void repaintDuringLayout(); 0627 void setNeedsLayout(bool b, bool markParents = true); 0628 void setChildNeedsLayout(bool b, bool markParents = true); 0629 void setMinMaxKnown(bool b = true) 0630 { 0631 m_minMaxKnown = b; 0632 if (!b) { 0633 RenderObject *o = this; 0634 while (o) { // ### && !o->m_recalcMinMax ) { 0635 o->m_recalcMinMax = true; 0636 o = o->m_parent; 0637 } 0638 } 0639 } 0640 void setNeedsLayoutAndMinMaxRecalc() 0641 { 0642 setMinMaxKnown(false); 0643 setNeedsLayout(true); 0644 } 0645 void setPositioned(bool b = true) 0646 { 0647 m_positioned = b; 0648 } 0649 void setRelPositioned(bool b = true) 0650 { 0651 m_relPositioned = b; 0652 } 0653 void setFloating(bool b = true) 0654 { 0655 m_floating = b; 0656 } 0657 void setInline(bool b = true) 0658 { 0659 m_inline = b; 0660 } 0661 void setMouseInside(bool b = true) 0662 { 0663 m_mouseInside = b; 0664 } 0665 void setShouldPaintBackgroundOrBorder(bool b = true) 0666 { 0667 m_paintBackground = b; 0668 } 0669 void setRenderText() 0670 { 0671 m_isText = true; 0672 } 0673 void setReplaced(bool b = true) 0674 { 0675 m_replaced = b; 0676 } 0677 void setHasOverflowClip(bool b = true) 0678 { 0679 m_hasOverflowClip = b; 0680 } 0681 void setIsSelectionBorder(bool b = true) 0682 { 0683 m_isSelectionBorder = b; 0684 } 0685 0686 void scheduleRelayout(RenderObject *clippedObj = nullptr); 0687 0688 void updateBackgroundImages(RenderStyle *oldStyle); 0689 0690 virtual InlineBox *createInlineBox(bool makePlaceHolderBox, bool isRootLineBox); 0691 virtual void removeInlineBox(InlineBox * /*box*/) {} 0692 0693 virtual InlineBox *inlineBox(long offset = 0); 0694 virtual short lineHeight(bool firstLine) const; 0695 virtual short verticalPositionHint(bool firstLine) const; 0696 virtual short baselinePosition(bool firstLine) const; 0697 short getVerticalPosition(bool firstLine, RenderObject *ref = nullptr) const; 0698 0699 /* 0700 * Print the object and its children, clipped by (x|y|w|h). 0701 * (tx|ty) is the calculated position of the parent 0702 */ 0703 struct PaintInfo { 0704 PaintInfo(QPainter *_p, const QRect &_r, PaintAction _phase) 0705 : p(_p), r(_r), phase(_phase), outlineObjects(nullptr) {} 0706 ~PaintInfo() 0707 { 0708 delete outlineObjects; 0709 } 0710 QPainter *p; 0711 QRect r; 0712 PaintAction phase; 0713 QList<RenderFlow *> *outlineObjects; // used to list which outlines should be painted by a block with inline children 0714 }; 0715 virtual void paint(PaintInfo &i, int tx, int ty); 0716 0717 void calcBorderRadii(QPoint &topLeftRadii, QPoint &topRightRadii, QPoint &bottomLeftRadii, QPoint &bottomRightRadii, int w, int h) const; 0718 0719 void drawBorderArc(QPainter *p, int x, int y, float horThickness, float vertThickness, 0720 const QPoint &radius, int angleStart, int angleSpan, const QBrush &brush, 0721 const QColor &textColor, EBorderStyle style, qreal *dashOffset = nullptr) const; 0722 0723 void paintBorder(QPainter *p, int _tx, int _ty, int w, int h, const RenderStyle *style, bool begin = true, bool end = true); 0724 void paintOutline(QPainter *p, int _tx, int _ty, int w, int h, const RenderStyle *style); 0725 0726 virtual void paintBoxDecorations(PaintInfo &, int /*_tx*/, int /*_ty*/) {} 0727 0728 virtual void paintBackgroundExtended(QPainter * /*p*/, const QColor & /*c*/, const BackgroundLayer * /*bgLayer*/, 0729 QRect /*clipr*/, int /*_tx*/, int /*_ty*/, 0730 int /*w*/, int /*height*/, int /*bleft*/, int /*bright*/, int /*pleft*/, int /*pright*/, 0731 int /*btop*/, int /*bbottom*/, int /*ptop*/, int /*pbottom*/) {} 0732 0733 /* 0734 * This function calculates the minimum & maximum width that the object 0735 * can be set to. 0736 * 0737 * when the Element calls setMinMaxKnown(true), calcMinMaxWidth() will 0738 * be no longer called. 0739 * 0740 * when a element has a fixed size, m_minWidth and m_maxWidth should be 0741 * set to the same value. This has the special meaning that m_width, 0742 * contains the actual value. 0743 * 0744 * assumes calcMinMaxWidth has already been called for all children. 0745 */ 0746 virtual void calcMinMaxWidth() { } 0747 0748 /* 0749 * Does the min max width recalculations after changes. 0750 */ 0751 void recalcMinMaxWidths(); 0752 0753 /* 0754 * Calculates the actual width of the object (only for non inline 0755 * objects) 0756 */ 0757 virtual void calcWidth() {} 0758 0759 /* 0760 * Calculates the actual width of the object (only for non inline 0761 * objects) 0762 */ 0763 virtual void calcHeight() {} 0764 0765 /* 0766 * This function should cause the Element to calculate its 0767 * width and height and the layout of its content 0768 * 0769 * when the Element calls setNeedsLayout(false), layout() is no 0770 * longer called during relayouts, as long as there is no 0771 * style sheet change. When that occurs, m_needsLayout will be 0772 * set to true and the Element receives layout() calls 0773 * again. 0774 */ 0775 virtual void layout() = 0; 0776 0777 /* This function performs a layout only if one is needed. */ 0778 void layoutIfNeeded() 0779 { 0780 if (needsLayout()) { 0781 layout(); 0782 } 0783 } 0784 0785 // used for element state updates that can not be fixed with a 0786 // repaint and do not need a relayout 0787 virtual void updateFromElement() {} 0788 0789 // Called immediately after render-object is inserted 0790 virtual void attach() 0791 { 0792 m_attached = true; 0793 } 0794 bool attached() 0795 { 0796 return m_attached; 0797 } 0798 // The corresponding closing element has been parsed. ### remove me 0799 virtual void close() { } 0800 0801 virtual int availableHeight() const 0802 { 0803 return 0; 0804 } 0805 0806 // Whether or not the element shrinks to its max width (rather than filling the width 0807 // of a containing block). HTML4 buttons, legends, and floating/compact elements do this. 0808 bool sizesToMaxWidth() const; 0809 0810 /* 0811 * NeesPageClear indicates the object crossed a page-break but could not break itself and now 0812 * needs to be moved clear by its parent. 0813 */ 0814 void setNeedsPageClear(bool b = true) 0815 { 0816 m_needsPageClear = b; 0817 } 0818 virtual bool needsPageClear() const 0819 { 0820 return m_needsPageClear; 0821 } 0822 0823 /* 0824 * ContainsPageBreak indicates the object contains a clean page-break. 0825 * ### should be removed and replaced with (crossesPageBreak && !needsPageClear) 0826 */ 0827 void setContainsPageBreak(bool b = true) 0828 { 0829 m_containsPageBreak = b; 0830 } 0831 virtual bool containsPageBreak() const 0832 { 0833 return m_containsPageBreak; 0834 } 0835 0836 virtual int pageTopAfter(int y) const 0837 { 0838 if (parent()) { 0839 return parent()->pageTopAfter(y); 0840 } else { 0841 return 0; 0842 } 0843 } 0844 0845 virtual int crossesPageBreak(int top, int bottom) const 0846 { 0847 if (parent()) { 0848 return parent()->crossesPageBreak(top, bottom); 0849 } else { 0850 return 0; 0851 } 0852 } 0853 0854 // Checks if a page-break before child is possible at the given page-break level 0855 // false means the child should attempt the break self. 0856 virtual bool canClear(RenderObject * /*child*/, PageBreakLevel level) 0857 { 0858 if (parent()) { 0859 return parent()->canClear(this, level); 0860 } else { 0861 return false; 0862 } 0863 } 0864 0865 void setAfterPageBreak(bool b = true) 0866 { 0867 m_afterPageBreak = b; 0868 } 0869 void setBeforePageBreak(bool b = true) 0870 { 0871 m_beforePageBreak = b; 0872 } 0873 virtual bool afterPageBreak() const 0874 { 0875 return m_afterPageBreak; 0876 } 0877 virtual bool beforePageBreak() const 0878 { 0879 return m_beforePageBreak; 0880 } 0881 0882 // does a query on the rendertree and finds the innernode 0883 // and overURL for the given position 0884 // if readonly == false, it will recalc hover styles accordingly 0885 class NodeInfo 0886 { 0887 friend class RenderImage; 0888 friend class RenderFlow; 0889 friend class RenderInline; 0890 friend class RenderText; 0891 friend class RenderWidget; 0892 friend class RenderObject; 0893 friend class RenderFrameSet; 0894 friend class RenderLayer; 0895 friend class DOM::HTMLAreaElementImpl; 0896 public: 0897 NodeInfo(bool readonly, bool active) 0898 : m_innerNode(nullptr), m_innerNonSharedNode(nullptr), m_innerURLElement(nullptr), m_readonly(readonly), m_active(active) 0899 { } 0900 0901 DOM::NodeImpl *innerNode() const 0902 { 0903 return m_innerNode; 0904 } 0905 DOM::NodeImpl *innerNonSharedNode() const 0906 { 0907 return m_innerNonSharedNode; 0908 } 0909 DOM::NodeImpl *URLElement() const 0910 { 0911 return m_innerURLElement; 0912 } 0913 bool readonly() const 0914 { 0915 return m_readonly; 0916 } 0917 bool active() const 0918 { 0919 return m_active; 0920 } 0921 0922 private: 0923 void setInnerNode(DOM::NodeImpl *n) 0924 { 0925 m_innerNode = n; 0926 } 0927 void setInnerNonSharedNode(DOM::NodeImpl *n) 0928 { 0929 m_innerNonSharedNode = n; 0930 } 0931 void setURLElement(DOM::NodeImpl *n) 0932 { 0933 m_innerURLElement = n; 0934 } 0935 0936 DOM::NodeImpl *m_innerNode; 0937 DOM::NodeImpl *m_innerNonSharedNode; 0938 DOM::NodeImpl *m_innerURLElement; 0939 bool m_readonly; 0940 bool m_active; 0941 }; 0942 0943 /** contains stateful information for a checkSelectionPoint call 0944 */ 0945 struct SelPointState { 0946 /** last node that was before the current position */ 0947 DOM::NodeImpl *m_lastNode; 0948 /** offset of last node */ 0949 long m_lastOffset; 0950 /** true when the last node had the result SelectionAfterInLine */ 0951 bool m_afterInLine; 0952 0953 SelPointState() : m_lastNode(nullptr), m_lastOffset(0), m_afterInLine(false) 0954 {} 0955 }; 0956 0957 #if 0 0958 virtual FindSelectionResult checkSelectionPoint(int _x, int _y, int _tx, int _ty, 0959 DOM::NodeImpl *&, int &offset, 0960 SelPointState &); 0961 #endif 0962 virtual bool nodeAtPoint(NodeInfo &info, int x, int y, int tx, int ty, HitTestAction, bool inside = false); 0963 void setInnerNode(NodeInfo &info); 0964 0965 // Position/Selection stuff 0966 virtual RenderPosition positionForCoordinates(int x, int y); 0967 0968 // set the style of the object. 0969 virtual void setStyle(RenderStyle *style); 0970 0971 // returns the containing block level element for this element. 0972 RenderBlock *containingBlock() const; 0973 0974 // return just the width of the containing block 0975 virtual short containingBlockWidth(RenderObject *providedCB = nullptr) const; 0976 // return just the height of the containing block 0977 virtual int containingBlockHeight(RenderObject *providedCB = nullptr) const; 0978 0979 // size of the content area (box size minus padding/border) 0980 virtual short contentWidth() const 0981 { 0982 return 0; 0983 } 0984 virtual int contentHeight() const 0985 { 0986 return 0; 0987 } 0988 0989 // intrinsic extend of replaced elements. undefined otherwise 0990 virtual short intrinsicWidth() const 0991 { 0992 return 0; 0993 } 0994 virtual int intrinsicHeight() const 0995 { 0996 return 0; 0997 } 0998 0999 // relative to parent node 1000 virtual void setPos(int /*xPos*/, int /*yPos*/) { } 1001 virtual void setWidth(int /*width*/) { } 1002 virtual void setHeight(int /*height*/) { } 1003 1004 virtual int xPos() const 1005 { 1006 return 0; 1007 } 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 */ 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 */ 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 */ 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 */ 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 1048 virtual short width() const 1049 { 1050 return 0; 1051 } 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. 1061 virtual int overflowHeight() const 1062 { 1063 return height(); 1064 } 1065 virtual int overflowWidth() const 1066 { 1067 return width(); 1068 } 1069 // how much goes over the left hand side (0 or a negative number) 1070 virtual int overflowTop() const 1071 { 1072 return 0; 1073 } 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 */ 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 */ 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 1101 virtual short offsetWidth() const 1102 { 1103 return width(); 1104 } 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 1119 virtual bool isSelfCollapsingBlock() const 1120 { 1121 return false; 1122 } 1123 short collapsedMarginTop() const 1124 { 1125 return maxTopMargin(true) - maxTopMargin(false); 1126 } 1127 short collapsedMarginBottom() const 1128 { 1129 return maxBottomMargin(true) - maxBottomMargin(false); 1130 } 1131 1132 virtual bool isTopMarginQuirk() const 1133 { 1134 return false; 1135 } 1136 virtual bool isBottomMarginQuirk() const 1137 { 1138 return false; 1139 } 1140 virtual short maxTopMargin(bool positive) const 1141 { 1142 return positive ? qMax(int(marginTop()), 0) : - qMin(int(marginTop()), 0); 1143 } 1144 virtual short maxBottomMargin(bool positive) const 1145 { 1146 return positive ? qMax(int(marginBottom()), 0) : - qMin(int(marginBottom()), 0); 1147 } 1148 1149 virtual short marginTop() const 1150 { 1151 return 0; 1152 } 1153 virtual short marginBottom() const 1154 { 1155 return 0; 1156 } 1157 virtual short marginLeft() const 1158 { 1159 return 0; 1160 } 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 1171 virtual int borderTop() const 1172 { 1173 return style()->borderTopWidth(); 1174 } 1175 virtual int borderBottom() const 1176 { 1177 return style()->borderBottomWidth(); 1178 } 1179 virtual int borderLeft() const 1180 { 1181 return style()->borderLeftWidth(); 1182 } 1183 virtual int borderRight() const 1184 { 1185 return style()->borderRightWidth(); 1186 } 1187 1188 virtual short minWidth() const 1189 { 1190 return 0; 1191 } 1192 virtual int maxWidth() const 1193 { 1194 return 0; 1195 } 1196 1197 RenderStyle *style() const 1198 { 1199 return m_style; 1200 } 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 1235 virtual unsigned int length() const 1236 { 1237 return 1; 1238 } 1239 1240 virtual bool isHidden() const 1241 { 1242 return isFloating() || isPositioned(); 1243 } 1244 1245 // Special objects are objects that are neither really inline nor blocklevel 1246 bool isFloatingOrPositioned() const 1247 { 1248 return (isFloating() || isPositioned()); 1249 } 1250 virtual bool hasOverhangingFloats() const 1251 { 1252 return false; 1253 } 1254 virtual bool hasFloats() const 1255 { 1256 return false; 1257 } 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) 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 1282 virtual SelectionState selectionState() const 1283 { 1284 return SelectionNone; 1285 } 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 1337 virtual void calcVerticalMargins() {} 1338 void removeFromObjectLists(); 1339 void setInPosObjectList(bool b = true) 1340 { 1341 m_inPosObjectList = b; 1342 } 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) {} 1353 virtual void dirtyLinesFromChangedChild(RenderObject *) {} 1354 virtual void detach(); 1355 1356 bool documentBeingDestroyed() const 1357 { 1358 return !document()->renderer(); 1359 } 1360 1361 void setDoNotDelete(bool b) 1362 { 1363 m_doNotDelete = b; 1364 } 1365 bool doNotDelete() const 1366 { 1367 return m_doNotDelete; 1368 } 1369 1370 const QFont &font(bool firstLine) const 1371 { 1372 return style(firstLine)->font(); 1373 } 1374 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 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; 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