File indexing completed on 2024-04-28 15:24:09

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