File indexing completed on 2025-01-12 12:28:10
0001 /* 0002 * This file is part of the DOM implementation for KDE. 0003 * 0004 * Copyright (C) 1997 Martin Jones (mjones@kde.org) 0005 * (C) 1997 Torben Weis (weis@kde.org) 0006 * (C) 1998 Waldo Bastian (bastian@kde.org) 0007 * (C) 1999-2003 Lars Knoll (knoll@kde.org) 0008 * (C) 1999 Antti Koivisto (koivisto@kde.org) 0009 * (C) 2003 Apple Computer, Inc. 0010 * (C) 2009 Carlos Licea (carlos.licea@kdemail.net) 0011 * 0012 * This library is free software; you can redistribute it and/or 0013 * modify it under the terms of the GNU Library General Public 0014 * License as published by the Free Software Foundation; either 0015 * version 2 of the License, or (at your option) any later version. 0016 * 0017 * This library is distributed in the hope that it will be useful, 0018 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0019 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0020 * Library General Public License for more details. 0021 * 0022 * You should have received a copy of the GNU Library General Public License 0023 * along with this library; see the file COPYING.LIB. If not, write to 0024 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0025 * Boston, MA 02110-1301, USA. 0026 * 0027 */ 0028 #ifndef RENDER_TABLE_H 0029 #define RENDER_TABLE_H 0030 0031 #include <QColor> 0032 #include <QVector> 0033 0034 #include "rendering/render_box.h" 0035 #include "rendering/render_block.h" 0036 #include "rendering/render_style.h" 0037 0038 #include "misc/khtmllayout.h" 0039 0040 namespace khtml 0041 { 0042 0043 class RenderTable; 0044 class RenderTableSection; 0045 class RenderTableRow; 0046 class RenderTableCell; 0047 class RenderTableCol; 0048 class TableLayout; 0049 0050 class RenderTable : public RenderBlock 0051 { 0052 public: 0053 0054 RenderTable(DOM::NodeImpl *node); 0055 ~RenderTable(); 0056 0057 const char *renderName() const override 0058 { 0059 return "RenderTable"; 0060 } 0061 0062 void setStyle(RenderStyle *style) override; 0063 0064 bool isTable() const override 0065 { 0066 return true; 0067 } 0068 0069 int getColumnPos(int col) const 0070 { 0071 return columnPos[col]; 0072 } 0073 0074 int borderHSpacing() const 0075 { 0076 return hspacing; 0077 } 0078 int borderVSpacing() const 0079 { 0080 return vspacing; 0081 } 0082 0083 bool collapseBorders() const 0084 { 0085 return style()->borderCollapse(); 0086 } 0087 int borderLeft() const override; 0088 int borderRight() const override; 0089 int borderTop() const override; 0090 int borderBottom() const override; 0091 int paddingLeft() const override 0092 { 0093 return collapseBorders() ? 0 : RenderBlock::paddingLeft(); 0094 } 0095 int paddingRight() const override 0096 { 0097 return collapseBorders() ? 0 : RenderBlock::paddingRight(); 0098 } 0099 int paddingTop() const override 0100 { 0101 return collapseBorders() ? 0 : RenderBlock::paddingTop(); 0102 } 0103 int paddingBottom() const override 0104 { 0105 return collapseBorders() ? 0 : RenderBlock::paddingBottom(); 0106 } 0107 0108 const QColor &bgColor() const 0109 { 0110 return style()->backgroundColor(); 0111 } 0112 0113 uint cellPadding() const 0114 { 0115 return padding; 0116 } 0117 void setCellPadding(uint p) 0118 { 0119 padding = p; 0120 } 0121 0122 // overrides 0123 void addChild(RenderObject *child, RenderObject *beforeChild = nullptr) override; 0124 void paint(PaintInfo &, int tx, int ty) override; 0125 void paintBoxDecorations(PaintInfo &, int _tx, int _ty) override; 0126 void layout() override; 0127 void calcMinMaxWidth() override; 0128 void close() override; 0129 0130 short lineHeight(bool b) const override; 0131 short baselinePosition(bool b) const override; 0132 0133 virtual void setCellWidths(); 0134 0135 void calcWidth() override; 0136 0137 QList< QRectF > getClientRects() override; 0138 0139 virtual FindSelectionResult checkSelectionPoint(int _x, int _y, int _tx, int _ty, 0140 DOM::NodeImpl *&node, int &offset, 0141 SelPointState &); 0142 0143 #ifdef ENABLE_DUMP 0144 void dump(QTextStream &stream, const QString &ind) const override; 0145 #endif 0146 struct ColumnStruct { 0147 enum { 0148 WidthUndefined = 0xffff 0149 }; 0150 ColumnStruct() 0151 { 0152 span = 1; 0153 width = WidthUndefined; 0154 } 0155 ushort span; 0156 ushort width; // the calculated position of the column 0157 }; 0158 0159 QVector<int> columnPos; 0160 QVector<ColumnStruct> columns; 0161 0162 void splitColumn(int pos, int firstSpan); 0163 void appendColumn(int span); 0164 int numEffCols() const 0165 { 0166 return columns.size(); 0167 } 0168 int spanOfEffCol(int effCol) const 0169 { 0170 return columns[effCol].span; 0171 } 0172 int colToEffCol(int col) const 0173 { 0174 int c = 0; 0175 int i = 0; 0176 while (c < col && i < (int)columns.size()) { 0177 c += columns[i].span; 0178 i++; 0179 } 0180 return i; 0181 } 0182 int effColToCol(int effCol) const 0183 { 0184 int c = 0; 0185 for (int i = 0; i < effCol; i++) { 0186 c += columns[i].span; 0187 } 0188 return c; 0189 } 0190 0191 int bordersPaddingAndSpacing() const 0192 { 0193 return borderLeft() + borderRight() + 0194 (collapseBorders() ? 0 : (paddingLeft() + paddingRight() + (numEffCols() + 1) * borderHSpacing())); 0195 } 0196 0197 RenderTableCol *colElement(int col, bool *startEdge = nullptr, bool *endEdge = nullptr) const; 0198 0199 void setNeedSectionRecalc() 0200 { 0201 needSectionRecalc = true; 0202 } 0203 0204 RenderObject *removeChildNode(RenderObject *child) override; 0205 0206 RenderTableSection *sectionAbove(const RenderTableSection *, bool skipEmptySections = false); 0207 RenderTableSection *sectionBelow(const RenderTableSection *, bool skipEmptySections = false); 0208 0209 RenderTableCell *cellAbove(const RenderTableCell *cell); 0210 RenderTableCell *cellBelow(const RenderTableCell *cell); 0211 RenderTableCell *cellBefore(const RenderTableCell *cell); 0212 RenderTableCell *cellAfter(const RenderTableCell *cell); 0213 0214 CollapsedBorderValue *currentBorderStyle() 0215 { 0216 return m_currentBorder; 0217 } 0218 0219 RenderTableSection *firstBodySection() const 0220 { 0221 return firstBody; 0222 } 0223 RenderFlow *caption() const 0224 { 0225 return tCaption; 0226 } 0227 0228 protected: 0229 0230 void recalcSections(); 0231 0232 friend class AutoTableLayout; 0233 friend class FixedTableLayout; 0234 0235 RenderFlow *tCaption; 0236 RenderTableSection *head; 0237 RenderTableSection *foot; 0238 RenderTableSection *firstBody; 0239 0240 TableLayout *tableLayout; 0241 0242 CollapsedBorderValue *m_currentBorder; 0243 0244 bool has_col_elems : 1; 0245 uint needSectionRecalc : 1; 0246 uint padding : 22; 0247 0248 ushort hspacing; 0249 ushort vspacing; 0250 0251 friend class TableSectionIterator; 0252 }; 0253 0254 // ------------------------------------------------------------------------- 0255 0256 class RenderTableSection : public RenderBox 0257 { 0258 public: 0259 RenderTableSection(DOM::NodeImpl *node); 0260 ~RenderTableSection(); 0261 void detach() override; 0262 0263 void setStyle(RenderStyle *style) override; 0264 0265 const char *renderName() const override 0266 { 0267 return "RenderTableSection"; 0268 } 0269 0270 // overrides 0271 void addChild(RenderObject *child, RenderObject *beforeChild = nullptr) override; 0272 bool isTableSection() const override 0273 { 0274 return true; 0275 } 0276 0277 short lineHeight(bool) const override 0278 { 0279 return 0; 0280 } 0281 void position(InlineBox *, int, int, bool) override {} 0282 0283 virtual FindSelectionResult checkSelectionPoint(int _x, int _y, int _tx, int _ty, 0284 DOM::NodeImpl *&node, int &offset, 0285 SelPointState &); 0286 0287 #ifdef ENABLE_DUMP 0288 void dump(QTextStream &stream, const QString &ind) const override; 0289 #endif 0290 0291 void addCell(RenderTableCell *cell, RenderTableRow *row); 0292 0293 void setCellWidths(); 0294 void calcRowHeight(); 0295 int layoutRows(int height); 0296 0297 RenderTable *table() const 0298 { 0299 return static_cast<RenderTable *>(parent()); 0300 } 0301 0302 typedef QVector<RenderTableCell *> Row; 0303 struct RowStruct { 0304 Row *row; 0305 RenderTableRow *rowRenderer; 0306 int baseLine; 0307 Length height; 0308 bool needFlex; 0309 }; 0310 0311 RenderTableCell *&cellAt(int row, int col) 0312 { 0313 return (*(grid[row].row))[col]; 0314 } 0315 RenderTableCell *cellAt(int row, int col) const 0316 { 0317 return (*(grid[row].row))[col]; 0318 } 0319 0320 int lowestPosition(bool includeOverflowInterior, bool includeSelf) const override; 0321 int rightmostPosition(bool includeOverflowInterior, bool includeSelf) const override; 0322 int leftmostPosition(bool includeOverflowInterior, bool includeSelf) const override; 0323 int highestPosition(bool includeOverflowInterior, bool includeSelf) const override; 0324 0325 int borderLeft() const override 0326 { 0327 return table()->collapseBorders() ? 0 : RenderBox::borderLeft(); 0328 } 0329 int borderRight() const override 0330 { 0331 return table()->collapseBorders() ? 0 : RenderBox::borderRight(); 0332 } 0333 int borderTop() const override 0334 { 0335 return table()->collapseBorders() ? 0 : RenderBox::borderTop(); 0336 } 0337 int borderBottom() const override 0338 { 0339 return table()->collapseBorders() ? 0 : RenderBox::borderBottom(); 0340 } 0341 0342 void paint(PaintInfo &i, int tx, int ty) override; 0343 0344 int numRows() const 0345 { 0346 return grid.size(); 0347 } 0348 int getBaseline(int row) 0349 { 0350 return grid[row].baseLine; 0351 } 0352 0353 void setNeedCellRecalc() 0354 { 0355 needCellRecalc = true; 0356 table()->setNeedSectionRecalc(); 0357 } 0358 0359 RenderObject *removeChildNode(RenderObject *child) override; 0360 0361 bool canClear(RenderObject *child, PageBreakLevel level) override; 0362 void addSpaceAt(int pos, int dy); 0363 0364 bool nodeAtPoint(NodeInfo &info, int x, int y, int tx, int ty, HitTestAction action, bool inside) override; 0365 0366 // this gets a cell grid data structure. changing the number of 0367 // columns is done by the table 0368 QVector<RowStruct> grid; 0369 QVector<int> rowPos; 0370 0371 int numColumns() const; 0372 0373 //QMap< lastInsertedColumn, cell > 0374 QMap< int, RenderTableCell * > cellsWithColSpanZero; 0375 //QMap< nextRowToInsert, cell > 0376 QMap< int, RenderTableCell * > cellsWithRowSpanZero; 0377 0378 int cRow; 0379 int cCol; 0380 bool needCellRecalc; 0381 0382 void recalcCells(); 0383 protected: 0384 void ensureRows(int numRows); 0385 void clearGrid(); 0386 bool emptyRow(int rowNum); 0387 bool flexCellChildren(RenderObject *p) const; 0388 0389 friend class TableSectionIterator; 0390 }; 0391 0392 // ------------------------------------------------------------------------- 0393 0394 class RenderTableRow : public RenderBox 0395 { 0396 public: 0397 RenderTableRow(DOM::NodeImpl *node); 0398 0399 void detach() override; 0400 0401 void setStyle(RenderStyle *) override; 0402 const char *renderName() const override 0403 { 0404 return "RenderTableRow"; 0405 } 0406 bool isTableRow() const override 0407 { 0408 return true; 0409 } 0410 void addChild(RenderObject *child, RenderObject *beforeChild = nullptr) override; 0411 0412 short offsetWidth() const override; 0413 int offsetHeight() const override; 0414 int offsetLeft() const override; 0415 int offsetTop() const override; 0416 0417 short lineHeight(bool) const override 0418 { 0419 return 0; 0420 } 0421 void position(InlineBox *, int, int, bool) override {} 0422 0423 bool nodeAtPoint(NodeInfo &info, int x, int y, int tx, int ty, HitTestAction action, bool inside) override; 0424 0425 void layout() override; 0426 0427 RenderObject *removeChildNode(RenderObject *child) override; 0428 0429 // The only time rows get a layer is when they have transparency. 0430 bool requiresLayer() const override 0431 { 0432 return style()->opacity() < 1.0f; 0433 } 0434 void paint(PaintInfo &i, int tx, int ty) override; 0435 0436 void paintRow(PaintInfo &i, int tx, int ty, int w, int h); 0437 0438 RenderTable *table() const 0439 { 0440 return static_cast<RenderTable *>(parent()->parent()); 0441 } 0442 RenderTableSection *section() const 0443 { 0444 return static_cast<RenderTableSection *>(parent()); 0445 } 0446 }; 0447 0448 // ------------------------------------------------------------------------- 0449 0450 class RenderTableCell : public RenderBlock 0451 { 0452 public: 0453 RenderTableCell(DOM::NodeImpl *node); 0454 0455 void layout() override; 0456 void detach() override; 0457 0458 const char *renderName() const override 0459 { 0460 return "RenderTableCell"; 0461 } 0462 bool isTableCell() const override 0463 { 0464 return true; 0465 } 0466 0467 // ### FIX these two... 0468 long cellIndex() const 0469 { 0470 return 0; 0471 } 0472 void setCellIndex(long) { } 0473 0474 unsigned short colSpan() const 0475 { 0476 return cSpan; 0477 } 0478 void setColSpan(unsigned short c) 0479 { 0480 cSpan = c; 0481 } 0482 0483 unsigned short rowSpan() const 0484 { 0485 return rSpan; 0486 } 0487 void setRowSpan(unsigned short r) 0488 { 0489 rSpan = r; 0490 } 0491 0492 int col() const 0493 { 0494 return _col; 0495 } 0496 void setCol(int col) 0497 { 0498 _col = col; 0499 } 0500 int row() const 0501 { 0502 return _row; 0503 } 0504 void setRow(int r) 0505 { 0506 _row = r; 0507 } 0508 0509 Length styleOrColWidth(); 0510 0511 // overrides 0512 void calcMinMaxWidth() override; 0513 void calcWidth() override; 0514 void setWidth(int width) override; 0515 void setStyle(RenderStyle *style) override; 0516 bool requiresLayer() const override; 0517 0518 int borderLeft() const override; 0519 int borderRight() const override; 0520 int borderTop() const override; 0521 int borderBottom() const override; 0522 0523 CollapsedBorderValue collapsedLeftBorder(bool rtl) const; 0524 CollapsedBorderValue collapsedRightBorder(bool rtl) const; 0525 CollapsedBorderValue collapsedTopBorder() const; 0526 CollapsedBorderValue collapsedBottomBorder() const; 0527 void collectBorders(QList<CollapsedBorderValue> &borderStyles) override; 0528 0529 void updateFromElement() override; 0530 0531 void setCellTopExtra(int p) 0532 { 0533 _topExtra = p; 0534 } 0535 void setCellBottomExtra(int p) 0536 { 0537 _bottomExtra = p; 0538 } 0539 int cellTopExtra() const 0540 { 0541 return _topExtra; 0542 } 0543 int cellBottomExtra() const 0544 { 0545 return _bottomExtra; 0546 } 0547 0548 int pageTopAfter(int x) const override; 0549 0550 void paint(PaintInfo &i, int tx, int ty) override; 0551 0552 void paintCollapsedBorder(QPainter *p, int x, int y, int w, int h); 0553 void paintBackgroundsBehindCell(PaintInfo &i, int _tx, int _ty, RenderObject *backgroundObject); 0554 0555 void close() override; 0556 0557 // lie position to outside observers 0558 int yPos() const override 0559 { 0560 return m_y + _topExtra; 0561 } 0562 0563 void repaintRectangle(int x, int y, int w, int h, Priority p = NormalPriority, bool f = false) override; 0564 0565 short baselinePosition(bool = false) const override; 0566 0567 bool nodeAtPoint(NodeInfo &info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction, bool inside) override; 0568 0569 RenderTable *table() const 0570 { 0571 return static_cast<RenderTable *>(parent()->parent()->parent()); 0572 } 0573 RenderTableSection *section() const 0574 { 0575 return static_cast<RenderTableSection *>(parent()->parent()); 0576 } 0577 0578 #ifdef ENABLE_DUMP 0579 void dump(QTextStream &stream, const QString &ind) const override; 0580 #endif 0581 0582 bool widthChanged() 0583 { 0584 bool retval = m_widthChanged; 0585 m_widthChanged = false; 0586 return retval; 0587 } 0588 0589 int cellPercentageHeight() const 0590 { 0591 return m_percentageHeight; 0592 } 0593 void setCellPercentageHeight(int h) 0594 { 0595 m_percentageHeight = h; 0596 } 0597 bool hasFlexedAnonymous() const 0598 { 0599 return m_hasFlexedAnonymous; 0600 } 0601 void setHasFlexedAnonymous(bool b = true) 0602 { 0603 m_hasFlexedAnonymous = b; 0604 } 0605 0606 protected: 0607 void paintBoxDecorations(PaintInfo &p, int _tx, int _ty) override; 0608 int borderTopExtra() const override 0609 { 0610 return _topExtra; 0611 } 0612 int borderBottomExtra() const override 0613 { 0614 return _bottomExtra; 0615 } 0616 0617 int _row; 0618 int _col; 0619 ushort rSpan; 0620 ushort cSpan; 0621 int _topExtra; 0622 signed int _bottomExtra : 30; 0623 bool m_widthChanged : 1; 0624 bool m_hasFlexedAnonymous : 1; 0625 int m_percentageHeight; 0626 }; 0627 0628 // ------------------------------------------------------------------------- 0629 0630 class RenderTableCol : public RenderBox 0631 { 0632 public: 0633 RenderTableCol(DOM::NodeImpl *node); 0634 0635 const char *renderName() const override 0636 { 0637 return "RenderTableCol"; 0638 } 0639 0640 bool isTableCol() const override 0641 { 0642 return true; 0643 } 0644 0645 short lineHeight(bool) const override 0646 { 0647 return 0; 0648 } 0649 void position(InlineBox *, int, int, bool) override {} 0650 void layout() override {} 0651 bool requiresLayer() const override 0652 { 0653 return false; 0654 } 0655 0656 void updateFromElement() override; 0657 0658 #ifdef ENABLE_DUMP 0659 void dump(QTextStream &stream, const QString &ind) const override; 0660 #endif 0661 0662 int span() const 0663 { 0664 return m_span; 0665 } 0666 void setSpan(int s) 0667 { 0668 m_span = s; 0669 } 0670 0671 private: 0672 int m_span; 0673 }; 0674 0675 // ------------------------------------------------------------------------- 0676 0677 /** This class provides an iterator to iterate through the sections of a 0678 * render table in their visual order. 0679 * 0680 * In HTML, sections are specified in the order of THEAD, TFOOT, and TBODY. 0681 * Visually, TBODY sections appear between THEAD and TFOOT, which this iterator 0682 * takes into regard. 0683 * @author Leo Savernik 0684 * @internal 0685 */ 0686 class TableSectionIterator 0687 { 0688 public: 0689 0690 /** 0691 * Initializes a new iterator 0692 * @param table table whose sections to iterate 0693 * @param fromEnd @p true, begin with last section, @p false, begin with 0694 * first section. 0695 */ 0696 TableSectionIterator(RenderTable *table, bool fromEnd = false); 0697 0698 /** 0699 * Initializes a new iterator 0700 * @param start table section to start with. 0701 */ 0702 TableSectionIterator(RenderTableSection *start) : sec(start) {} 0703 0704 /** 0705 * Uninitialized iterator. 0706 */ 0707 TableSectionIterator() {} 0708 0709 /** Returns the current section, or @p 0 if the end has been reached. 0710 */ 0711 RenderTableSection *operator *() const 0712 { 0713 return sec; 0714 } 0715 0716 /** Moves to the next section in visual order. */ 0717 TableSectionIterator &operator ++(); 0718 0719 /** Moves to the previous section in visual order. */ 0720 TableSectionIterator &operator --(); 0721 0722 private: 0723 RenderTableSection *sec; 0724 }; 0725 0726 } 0727 #endif 0728