File indexing completed on 2025-01-12 12:27:55
0001 /* 0002 * This file is part of the render object implementation for KHTML. 0003 * 0004 * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org) 0005 * (C) 1999-2003 Antti Koivisto (koivisto@kde.org) 0006 * (C) 2002-2003 Dirk Mueller (mueller@kde.org) 0007 * (C) 2003 Apple Computer, Inc. 0008 * 0009 * This library is free software; you can redistribute it and/or 0010 * modify it under the terms of the GNU Library General Public 0011 * License as published by the Free Software Foundation; either 0012 * version 2 of the License, or (at your option) any later version. 0013 * 0014 * This library is distributed in the hope that it will be useful, 0015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0017 * Library General Public License for more details. 0018 * 0019 * You should have received a copy of the GNU Library General Public License 0020 * along with this library; see the file COPYING.LIB. If not, write to 0021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0022 * Boston, MA 02110-1301, USA. 0023 * 0024 */ 0025 0026 #ifndef RENDER_BLOCK_H 0027 #define RENDER_BLOCK_H 0028 0029 #include <QList> 0030 0031 #include "render_flow.h" 0032 0033 namespace DOM 0034 { 0035 class Position; 0036 } 0037 0038 namespace khtml 0039 { 0040 0041 class RenderBlock : public RenderFlow 0042 { 0043 public: 0044 RenderBlock(DOM::NodeImpl *node); 0045 virtual ~RenderBlock(); 0046 0047 const char *renderName() const override; 0048 0049 bool isRenderBlock() const override 0050 { 0051 return true; 0052 } 0053 bool isBlockFlow() const override 0054 { 0055 return (!isInline() || isReplaced()) && !isTable(); 0056 } 0057 bool isInlineFlow() const override 0058 { 0059 return isInline() && !isReplaced(); 0060 } 0061 bool isInlineBlockOrInlineTable() const override 0062 { 0063 return isInline() && isReplaced(); 0064 } 0065 0066 bool childrenInline() const override 0067 { 0068 return m_childrenInline; 0069 } 0070 virtual void setChildrenInline(bool b) 0071 { 0072 m_childrenInline = b; 0073 } 0074 short baselinePosition(bool firstLine) const override; 0075 0076 int getBaselineOfLastLineBox() const; 0077 void makeChildrenNonInline(RenderObject *insertionPoint = nullptr); 0078 0079 void makePageBreakAvoidBlocks(); 0080 0081 // The height (and width) of a block when you include overflow spillage out of the bottom 0082 // of the block (e.g., a <div style="height:25px"> that has a 100px tall image inside 0083 // it would have an overflow height of borderTop() + paddingTop() + 100px. 0084 int overflowHeight() const override 0085 { 0086 return m_overflowHeight; 0087 } 0088 int overflowWidth() const override 0089 { 0090 return m_overflowWidth; 0091 } 0092 int overflowLeft() const override 0093 { 0094 return m_overflowLeft; 0095 } 0096 int overflowTop() const override 0097 { 0098 return m_overflowTop; 0099 } 0100 virtual void setOverflowHeight(int h) 0101 { 0102 m_overflowHeight = h; 0103 } 0104 virtual void setOverflowWidth(int w) 0105 { 0106 m_overflowWidth = w; 0107 } 0108 virtual void setOverflowLeft(int l) 0109 { 0110 m_overflowLeft = l; 0111 } 0112 virtual void setOverflowTop(int t) 0113 { 0114 m_overflowTop = t; 0115 } 0116 0117 bool isSelfCollapsingBlock() const override; 0118 bool isTopMarginQuirk() const override 0119 { 0120 return m_topMarginQuirk; 0121 } 0122 bool isBottomMarginQuirk() const override 0123 { 0124 return m_bottomMarginQuirk; 0125 } 0126 0127 short maxTopMargin(bool positive) const override 0128 { 0129 if (positive) { 0130 return m_maxTopPosMargin; 0131 } else { 0132 return m_maxTopNegMargin; 0133 } 0134 } 0135 short maxBottomMargin(bool positive) const override 0136 { 0137 if (positive) { 0138 return m_maxBottomPosMargin; 0139 } else { 0140 return m_maxBottomNegMargin; 0141 } 0142 } 0143 0144 void initMaxMarginValues() 0145 { 0146 if (m_marginTop >= 0) { 0147 m_maxTopPosMargin = m_marginTop; 0148 } else { 0149 m_maxTopNegMargin = -m_marginTop; 0150 } 0151 if (m_marginBottom >= 0) { 0152 m_maxBottomPosMargin = m_marginBottom; 0153 } else { 0154 m_maxBottomNegMargin = -m_marginBottom; 0155 } 0156 } 0157 0158 void addChildToFlow(RenderObject *newChild, RenderObject *beforeChild) override; 0159 void removeChild(RenderObject *oldChild) override; 0160 0161 void setStyle(RenderStyle *_style) override; 0162 void attach() override; 0163 void updateFirstLetter(); 0164 0165 void layout() override; 0166 void layoutBlock(bool relayoutChildren); 0167 void layoutBlockChildren(bool relayoutChildren); 0168 void layoutInlineChildren(bool relayoutChildren, int breakBeforeLine = 0); 0169 0170 void layoutPositionedObjects(bool relayoutChildren); 0171 void insertPositionedObject(RenderObject *o); 0172 void removePositionedObject(RenderObject *o); 0173 0174 QRegion visibleFloatingRegion(int x, int y) const; 0175 // Called to lay out the legend for a fieldset. 0176 virtual RenderObject *layoutLegend(bool /*relayoutChildren*/) 0177 { 0178 return nullptr; 0179 } 0180 0181 // the implementation of the following functions is in bidi.cpp 0182 void bidiReorderLine(const BidiIterator &start, const BidiIterator &end, BidiState &bidi); 0183 void fitBelowFloats(int widthToFit, int &availableWidth); 0184 BidiIterator findNextLineBreak(BidiIterator &start, BidiState &info); 0185 RootInlineBox *constructLine(const BidiIterator &start, const BidiIterator &end); 0186 InlineFlowBox *createLineBoxes(RenderObject *obj); 0187 bool inlineChildNeedsLineBox(RenderObject *obj); 0188 void computeHorizontalPositionsForLine(InlineFlowBox *lineBox, BidiState &bidi); 0189 void computeVerticalPositionsForLine(RootInlineBox *lineBox); 0190 bool clearLineOfPageBreaks(InlineFlowBox *lineBox); 0191 void checkLinesForOverflow(); 0192 void deleteEllipsisLineBoxes(); 0193 void checkLinesForTextOverflow(); 0194 RootInlineBox *determineStartPosition(bool fullLayout, BidiIterator &start, BidiState &bidi); 0195 RootInlineBox *determineEndPosition(RootInlineBox *startLine, BidiIterator &cleanLineStart, BidiStatus &cleanLineBidiStatus, BidiContext *cleanLineBidiContext, int &yPos); 0196 bool matchedEndLine(const BidiIterator &start, const BidiStatus &status, BidiContext *context, 0197 const BidiIterator &endLineStart, const BidiStatus &endLineStatus, BidiContext *endLineContext, 0198 RootInlineBox *&endLine, int &endYPos); 0199 // end bidi.cpp functions 0200 0201 void paint(PaintInfo &i, int tx, int ty) override; 0202 void paintObject(PaintInfo &i, int tx, int ty, bool paintOutline = true); 0203 void paintFloats(PaintInfo &i, int _tx, int _ty, bool paintSelection = false); 0204 0205 void insertFloatingObject(RenderObject *o); 0206 void removeFloatingObject(RenderObject *o); 0207 0208 // called from lineWidth, to position the floats added in the last line. 0209 void positionNewFloats(); 0210 void clearFloats(); 0211 int getClearDelta(RenderObject *child, int yPos); 0212 void markAllDescendantsWithFloatsForLayout(RenderObject *floatToRemove = nullptr) override; 0213 0214 // FIXME: containsFloats() should not return true if the floating objects list 0215 // is empty. However, layoutInlineChildren() relies on the current behavior. 0216 // http://bugzilla.opendarwin.org/show_bug.cgi?id=7395#c3 0217 bool hasFloats() const override 0218 { 0219 return m_floatingObjects != nullptr; 0220 } 0221 bool containsFloat(RenderObject *o) const override; 0222 0223 bool hasOverhangingFloats() const override 0224 { 0225 return floatBottom() > m_height; 0226 } 0227 void addOverHangingFloats(RenderBlock *block, int xoffset, int yoffset, bool child); 0228 0229 int nearestFloatBottom(int height) const; 0230 int floatBottom() const; 0231 inline int leftBottom(); 0232 inline int rightBottom(); 0233 0234 virtual unsigned short lineWidth(int y, bool *canClearLine = nullptr) const; 0235 int lowestPosition(bool includeOverflowInterior = true, bool includeSelf = true) const override; 0236 int rightmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const override; 0237 int leftmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const override; 0238 int highestPosition(bool includeOverflowInterior, bool includeSelf) const override; 0239 int lowestAbsolutePosition() const; 0240 int leftmostAbsolutePosition() const; 0241 int rightmostAbsolutePosition() const; 0242 int highestAbsolutePosition() const; 0243 0244 int rightOffset() const; 0245 int rightRelOffset(int y, int fixedOffset, bool applyTextIndent = true, int *heightRemaining = nullptr, bool *canClearLine = nullptr) const; 0246 int rightOffset(int y, bool *canClearLine = nullptr) const 0247 { 0248 return rightRelOffset(y, rightOffset(), true, nullptr, canClearLine); 0249 } 0250 0251 int leftOffset() const; 0252 int leftRelOffset(int y, int fixedOffset, bool applyTextIndent = true, int *heightRemaining = nullptr, bool *canClearLine = nullptr) const; 0253 int leftOffset(int y, bool *canClearLine = nullptr) const 0254 { 0255 return leftRelOffset(y, leftOffset(), true, nullptr, canClearLine); 0256 } 0257 0258 bool nodeAtPoint(NodeInfo &info, int x, int y, int _tx, int _ty, HitTestAction hitTestAction = HitTestAll, bool inside = false) override; 0259 0260 bool isPointInScrollbar(int x, int y, int tx, int ty); 0261 0262 RenderPosition positionForCoordinates(int x, int y) override; 0263 0264 void calcMinMaxWidth() override; 0265 void calcInlineMinMaxWidth(); 0266 void calcBlockMinMaxWidth(); 0267 0268 void close() override; 0269 0270 int getBaselineOfFirstLineBox() override; 0271 0272 RootInlineBox *firstRootBox() const 0273 { 0274 return static_cast<RootInlineBox *>(m_firstLineBox); 0275 } 0276 RootInlineBox *lastRootBox() const 0277 { 0278 return static_cast<RootInlineBox *>(m_lastLineBox); 0279 } 0280 0281 InlineFlowBox *getFirstLineBox() override; 0282 0283 bool inRootBlockContext() const; 0284 void deleteLineBoxTree(); 0285 0286 #ifdef ENABLE_DUMP 0287 void printTree(int indent = 0) const override; 0288 void dump(QTextStream &stream, const QString &ind) const override; 0289 #endif 0290 0291 protected: 0292 void newLine(); 0293 0294 private: 0295 RenderPosition positionForBox(InlineBox *box, bool start = true) const; 0296 RenderPosition positionForRenderer(RenderObject *renderer, bool start = true) const; 0297 0298 protected: 0299 struct FloatingObject { 0300 enum Type { 0301 FloatLeft, 0302 FloatRight 0303 }; 0304 0305 FloatingObject(Type _type) 0306 { 0307 node = nullptr; 0308 startY = 0; 0309 endY = 0; 0310 type = _type; 0311 left = 0; 0312 width = 0; 0313 noPaint = false; 0314 crossedLayer = false; 0315 0316 } 0317 RenderObject *node; 0318 int startY; 0319 int endY; 0320 short left; 0321 short width; 0322 KDE_BF_ENUM(Type) type : 1; // left or right aligned 0323 bool noPaint : 1; 0324 bool crossedLayer : 1; // lock noPaint flag 0325 }; 0326 0327 // The following helper functions and structs are used by layoutBlockChildren. 0328 class CompactInfo 0329 { 0330 // A compact child that needs to be collapsed into the margin of the following block. 0331 RenderObject *m_compact; 0332 0333 // The block with the open margin that the compact child is going to place itself within. 0334 RenderObject *m_block; 0335 bool m_treatAsBlock : 1; 0336 0337 public: 0338 RenderObject *compact() const 0339 { 0340 return m_compact; 0341 } 0342 RenderObject *block() const 0343 { 0344 return m_block; 0345 } 0346 void setTreatAsBlock(bool b) 0347 { 0348 m_treatAsBlock = b; 0349 } 0350 bool treatAsBlock() const 0351 { 0352 return m_treatAsBlock; 0353 } 0354 bool matches(RenderObject *child) const 0355 { 0356 return m_compact && m_block == child; 0357 } 0358 0359 void clear() 0360 { 0361 set(nullptr, nullptr); 0362 } 0363 void set(RenderObject *c, RenderObject *b) 0364 { 0365 m_compact = c; 0366 m_block = b; 0367 } 0368 0369 CompactInfo() 0370 { 0371 clear(); 0372 } 0373 }; 0374 0375 class MarginInfo 0376 { 0377 // Collapsing flags for whether we can collapse our margins with our children's margins. 0378 bool m_canCollapseWithChildren : 1; 0379 bool m_canCollapseTopWithChildren : 1; 0380 bool m_canCollapseBottomWithChildren : 1; 0381 0382 // Whether or not we are a quirky container, i.e., do we collapse away top and bottom 0383 // margins in our container. Table cells and the body are the common examples. We 0384 // also have a custom style property for Safari RSS to deal with TypePad blog articles. 0385 bool m_quirkContainer : 1; 0386 0387 // This flag tracks whether we are still looking at child margins that can all collapse together at the beginning of a block. 0388 // They may or may not collapse with the top margin of the block (|m_canCollapseTopWithChildren| tells us that), but they will 0389 // always be collapsing with one another. This variable can remain set to true through multiple iterations 0390 // as long as we keep encountering self-collapsing blocks. 0391 bool m_atTopOfBlock : 1; 0392 0393 // This flag is set when we know we're examining bottom margins and we know we're at the bottom of the block. 0394 bool m_atBottomOfBlock : 1; 0395 0396 // If our last normal flow child was a self-collapsing block that cleared a float, 0397 // we track it in this variable. 0398 bool m_selfCollapsingBlockClearedFloat : 1; 0399 0400 // These variables are used to detect quirky margins that we need to collapse away (in table cells 0401 // and in the body element). 0402 bool m_topQuirk : 1; 0403 bool m_bottomQuirk : 1; 0404 bool m_determinedTopQuirk : 1; 0405 0406 // These flags track the previous maximal positive and negative margins. 0407 int m_posMargin; 0408 int m_negMargin; 0409 0410 public: 0411 MarginInfo(RenderBlock *b, int top, int bottom); 0412 0413 void setAtTopOfBlock(bool b) 0414 { 0415 m_atTopOfBlock = b; 0416 } 0417 void setAtBottomOfBlock(bool b) 0418 { 0419 m_atBottomOfBlock = b; 0420 } 0421 void clearMargin() 0422 { 0423 m_posMargin = m_negMargin = 0; 0424 } 0425 void setSelfCollapsingBlockClearedFloat(bool b) 0426 { 0427 m_selfCollapsingBlockClearedFloat = b; 0428 } 0429 void setTopQuirk(bool b) 0430 { 0431 m_topQuirk = b; 0432 } 0433 void setBottomQuirk(bool b) 0434 { 0435 m_bottomQuirk = b; 0436 } 0437 void setDeterminedTopQuirk(bool b) 0438 { 0439 m_determinedTopQuirk = b; 0440 } 0441 void setPosMargin(int p) 0442 { 0443 m_posMargin = p; 0444 } 0445 void setNegMargin(int n) 0446 { 0447 m_negMargin = n; 0448 } 0449 void setPosMarginIfLarger(int p) 0450 { 0451 if (p > m_posMargin) { 0452 m_posMargin = p; 0453 } 0454 } 0455 void setNegMarginIfLarger(int n) 0456 { 0457 if (n > m_negMargin) { 0458 m_negMargin = n; 0459 } 0460 } 0461 0462 void setMargin(int p, int n) 0463 { 0464 m_posMargin = p; 0465 m_negMargin = n; 0466 } 0467 0468 bool atTopOfBlock() const 0469 { 0470 return m_atTopOfBlock; 0471 } 0472 bool canCollapseWithTop() const 0473 { 0474 return m_atTopOfBlock && m_canCollapseTopWithChildren; 0475 } 0476 bool canCollapseWithBottom() const 0477 { 0478 return m_atBottomOfBlock && m_canCollapseBottomWithChildren; 0479 } 0480 bool canCollapseTopWithChildren() const 0481 { 0482 return m_canCollapseTopWithChildren; 0483 } 0484 bool canCollapseBottomWithChildren() const 0485 { 0486 return m_canCollapseBottomWithChildren; 0487 } 0488 bool selfCollapsingBlockClearedFloat() const 0489 { 0490 return m_selfCollapsingBlockClearedFloat; 0491 } 0492 bool quirkContainer() const 0493 { 0494 return m_quirkContainer; 0495 } 0496 bool determinedTopQuirk() const 0497 { 0498 return m_determinedTopQuirk; 0499 } 0500 bool topQuirk() const 0501 { 0502 return m_topQuirk; 0503 } 0504 bool bottomQuirk() const 0505 { 0506 return m_bottomQuirk; 0507 } 0508 int posMargin() const 0509 { 0510 return m_posMargin; 0511 } 0512 int negMargin() const 0513 { 0514 return m_negMargin; 0515 } 0516 int margin() const 0517 { 0518 return m_posMargin - m_negMargin; 0519 } 0520 }; 0521 0522 class PageBreakInfo 0523 { 0524 int m_pageBottom; // Next calculated page-break 0525 bool m_forcePageBreak : 1; // Must break before next block 0526 // ### to do better "page-break-after/before: avoid" this struct 0527 // should keep a pagebreakAvoid block and gather children in it 0528 public: 0529 PageBreakInfo(int pageBottom) : m_pageBottom(pageBottom), m_forcePageBreak(false) {} 0530 bool forcePageBreak() 0531 { 0532 return m_forcePageBreak; 0533 } 0534 void setForcePageBreak(bool b) 0535 { 0536 m_forcePageBreak = b; 0537 } 0538 int pageBottom() 0539 { 0540 return m_pageBottom; 0541 } 0542 void setPageBottom(int bottom) 0543 { 0544 m_pageBottom = bottom; 0545 } 0546 }; 0547 0548 bool canClear(RenderObject *child, PageBreakLevel level) override; 0549 void clearPageBreak(RenderObject *child, int pageBottom); 0550 0551 void adjustPositionedBlock(RenderObject *child, const MarginInfo &marginInfo); 0552 void adjustFloatingBlock(const MarginInfo &marginInfo); 0553 RenderObject *handleSpecialChild(RenderObject *child, const MarginInfo &marginInfo, CompactInfo &compactInfo, bool &handled); 0554 RenderObject *handleFloatingChild(RenderObject *child, const MarginInfo &marginInfo, bool &handled); 0555 RenderObject *handlePositionedChild(RenderObject *child, const MarginInfo &marginInfo, bool &handled); 0556 RenderObject *handleCompactChild(RenderObject *child, CompactInfo &compactInfo, const MarginInfo &marginInfo, bool &handled); 0557 RenderObject *handleRunInChild(RenderObject *child, bool &handled); 0558 int collapseMargins(RenderObject *child, MarginInfo &marginInfo, int yPos); 0559 int clearFloatsIfNeeded(RenderObject *child, MarginInfo &marginInfo, int oldTopPosMargin, int oldTopNegMargin, int yPos); 0560 void adjustSizeForCompactIfNeeded(RenderObject *child, CompactInfo &compactInfo); 0561 void insertCompactIfNeeded(RenderObject *child, CompactInfo &compactInfo); 0562 int estimateVerticalPosition(RenderObject *child, const MarginInfo &info); 0563 void determineHorizontalPosition(RenderObject *child); 0564 void handleBottomOfBlock(int top, int bottom, MarginInfo &marginInfo); 0565 void setCollapsedBottomMargin(const MarginInfo &marginInfo); 0566 void clearChildOfPageBreaks(RenderObject *child, PageBreakInfo &pageBreakInfo, MarginInfo &marginInfo); 0567 // End helper functions and structs used by layoutBlockChildren. 0568 0569 protected: 0570 // How much content overflows out of our block vertically or horizontally (all we support 0571 // for now is spillage out of the bottom and the right, which are the common cases). 0572 int m_overflowHeight; 0573 int m_overflowWidth; 0574 0575 // Left and top overflow. 0576 int m_overflowTop; 0577 int m_overflowLeft; 0578 0579 QList<FloatingObject *> *m_floatingObjects; 0580 QList<RenderObject *> *m_positionedObjects; 0581 0582 private: 0583 bool m_childrenInline : 1; 0584 bool m_firstLine : 1; // used in inline layouting 0585 KDE_BF_ENUM(EClear) m_clearStatus : 2; // used during layuting of paragraphs 0586 bool m_avoidPageBreak : 1; // anonymous avoid page-break block 0587 bool m_topMarginQuirk : 1; 0588 bool m_bottomMarginQuirk : 1; 0589 0590 short m_maxTopPosMargin; 0591 short m_maxTopNegMargin; 0592 short m_maxBottomPosMargin; 0593 short m_maxBottomNegMargin; 0594 0595 }; 0596 0597 } // namespace 0598 0599 #endif // RENDER_BLOCK_H 0600