« Return to Thread: Patch for when rowspan or colspan equals 0

Re: Patch for when rowspan or colspan equals 0

by Bugzilla from carlos_licea@hotmail.com :: Rate this Message:

Reply to Author | View in Thread

Some parts of this message have been removed. Learn more about Nabble's security policy.
Hi list,
I had forgotten to submit this patch.
Now i believe it should be safe enough to commit.
Also I'm tired of this code, so I'll stop my work for now and start implementing the DOM Level 3 XPath specification.
Carlos



[tables.diff]

Index: html/html_tableimpl.cpp
===================================================================
--- html/html_tableimpl.cpp (revisión: 954616)
+++ html/html_tableimpl.cpp (copia de trabajo)
@@ -210,7 +210,7 @@
     lastSection = section;
     if ( index < 0 ) //append/last mode
         return 0;
-    
+
     long rows   = section->numRows();
     if ( index >= rows ) {
         section =  0;
@@ -428,7 +428,7 @@
 
     return cellChanged;
 }
-
+
 void HTMLTableElementImpl::parseAttribute(AttributeImpl *attr)
 {
     // ### to CSS!!
@@ -910,14 +910,14 @@
         // limit this to something not causing an overflow with short int
         if(rSpan < 0 || rSpan > 1024) rSpan = 1;
         if (renderer())
-            renderer()->updateFromElement();                    
+            renderer()->updateFromElement();
         break;
     case ATTR_COLSPAN:
         cSpan = attr->val() ? attr->val()->toInt() : 1;
         // limit this to something not causing an overflow with short int
         if(cSpan < 0 || cSpan > 1024) cSpan = 1;
         if (renderer())
-            renderer()->updateFromElement();        
+            renderer()->updateFromElement();
         break;
     case ATTR_NOWRAP:
         if (attr->val() != 0)
Index: rendering/render_table.cpp
===================================================================
--- rendering/render_table.cpp (revisión: 954616)
+++ rendering/render_table.cpp (copia de trabajo)
@@ -9,6 +9,7 @@
  *           (C) 2003 Apple Computer, Inc.
  *           (C) 2005 Allan Sandfeld Jensen (kde@...)
  *           (C) 2008 Germain Garand (germain@...)
+ *           (C) 2009 Carlos Licea (carlos.licea@...
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -182,7 +183,7 @@
                     head = static_cast<RenderTableSection *>(child);
                 } else {
                     resetSectionPointerIfNotBefore(firstBody, beforeChild);
-                    if (!firstBody)
+                    if (!firstBody)
                         firstBody = static_cast<RenderTableSection*>(child);
                 }
             }
@@ -761,10 +762,10 @@
                 maxCols = sectionCols;
         }
     }
-    
+
     columns.resize(maxCols);
     columnPos.resize(maxCols+1);
-    
+
     needSectionRecalc = false;
     setNeedsLayout(true);
 }
@@ -1028,6 +1029,7 @@
 
 RenderTableSection::RenderTableSection(DOM::NodeImpl* node)
     : RenderBox(node)
+    , containsSpansZero(false)
 {
     // init RenderObject attributes
     setInline(false);   // our object is not Inline
@@ -1156,7 +1158,7 @@
     // <TR><TD colspan="2">5
     // </TABLE>
  while ( cCol < nCols && cellAt( cRow, cCol ) )
-    cCol++;
+    ++cCol;
 
 //       qDebug("adding cell at %d/%d span=(%d/%d)",  cRow, cCol, rSpan, cSpan );
 
@@ -1190,44 +1192,158 @@
  }
     }
 
+    //What:Postion the cell
+    //How: we take care of special case when colspan or rowspan equals 0
+    //after that position the cell, that is just to tell where is it and tell
+    //other cells where they can't be located (marking the cells as -1)
+    //later taking the span into account (and in other function) the cell is
+    //then painted (that's why we need to set the colspan and rowspan properly
+    //when any of them is cero
+
     // make sure we have enough rows
-    ensureRows( cRow + rSpan );
+    ensureRows( cRow + (rSpan? rSpan : 1 ) );
 
     grid[cRow].rowRenderer = row;
 
     int col = cCol;
     // tell the cell where it is
     RenderTableCell *set = cell;
+    kDebug()<<"row"<<cRow<<"col"<<cCol;
+//     kDebug()<<"cSpan"<<cSpan<<"rSpan"<<rSpan;
+
+    //check wether we are in a column or in a row with span = 0
+    QList< int > columnsToAvoid;
+    if( containsSpansZero ) {
+        //Update any column which its last span update was in a previous column
+        int lowestCol = cellsWithColSpanZero.lowerBound( 0 ).key();
+        if( lowestCol < cCol ) {
+            //add the columns for this cell
+            if ( cCol >= nCols ) {
+                table()->appendColumn( cSpan );
+                nCols = columns.size();
+            }
+            //check and update all the cells that are updated to a previous column
+            while( lowestCol < nCols ) {
+                while( RenderTableCell* cell = cellsWithColSpanZero.take( lowestCol ) ) {
+                    const int cellRow = cell->row();
+                    const int cellRowSpan = cell->rowSpan();
+                    int finalSpan = cell->colSpan();
+                    for( int i = lowestCol; i < nCols; ++i ) {
+                        if( !cellAt( cellRow, i ) ) {
+                            cellAt( cellRow, i ) = (RenderTableCell *)-1;
+                        }
+                        ++finalSpan;
+                    }
+                    cell->setColSpan( finalSpan );
+                    cellsWithColSpanZero.insertMulti( nCols, cell );
+                }
+                lowestCol = cellsWithColSpanZero.lowerBound( 0 ).key();
+            }
+        }
+        if( cellsWithRowSpanZero.contains( cRow ) ) {
+            //No need to check if we have enough columns, we already found the first cell
+            //when rowspan="0", and as such, we've already inserted it
+            while( RenderTableCell* cell = cellsWithRowSpanZero.take( cRow ) ) {
+                const int cellCol = cell->col();
+                const int finalCol = cellCol + cell->colSpan() - 1;
+                RenderTableCell* set = cell;
+                for( int i = cellCol; i <= finalCol; ++i ) {
+                    if( !cellAt( cRow, i ) ) {
+                        cellAt( cRow, i ) = set;
+                    }
+                    set = (RenderTableCell *)-1;
+                    columnsToAvoid << i;
+                }
+                cell->setRowSpan( cell->rowSpan() + 1 );
+                //mark it to be inserted in next row
+                cellsWithRowSpanZero.insertMulti( cRow + 1, cell );
+            }
+        }
+    }
+
+    //Save the column if the its span is 0
+    if( !cSpan ) {
+        //Check if we only span in the current colgroup
+        if( RenderTableCol* colgroup = table()->colElement( cCol ) ) {
+            //Calculate the correct span and then handle the cell normally
+
+            int firstColumnOfColgroup = cCol;
+            while( --firstColumnOfColgroup >= 0 && colgroup == table()->colElement(firstColumnOfColgroup) ) ;
+            ++firstColumnOfColgroup;
+
+            int alreadyUsedSpan = 0;
+            RenderTableCell* colgroupCell = cellAt( cRow, firstColumnOfColgroup + alreadyUsedSpan );
+            while( firstColumnOfColgroup + alreadyUsedSpan < cCol ) {
+                alreadyUsedSpan += colgroupCell->colSpan();
+                colgroupCell = cellAt( cRow, firstColumnOfColgroup + alreadyUsedSpan );
+            }
+
+            const int finalSpan = colgroup->span() - alreadyUsedSpan;
+            cell->setColSpan( finalSpan );
+            
+            //We know exactly the cSpan so we can handle the cell as a normal cell
+            //unless, of course, the rowspan is also 0
+            cSpan = finalSpan;
+        }
+        //or if we span in the whole table and mark it as inserted till
+        //this column and updated whenever another column is inserted
+        else {
+            //We define the proper span and let the other code handle it
+            const int finalSpan = nCols - cCol;
+            cSpan = finalSpan;
+
+            cell->setColSpan( finalSpan );
+
+            cellsWithColSpanZero.insertMulti( cCol + finalSpan - 1, cell );
+            containsSpansZero = true;
+        }
+    }
+
+    if( !rSpan ) {
+        //For now we span 1
+        rSpan = 1;
+        cell->setRowSpan( 1 );
+
+        //mark it to be inserted in next row
+        cellsWithRowSpanZero.insertMulti( cRow + 1, cell );
+        containsSpansZero = true;
+    }
+
     while ( cSpan ) {
- int currentSpan;
- if ( cCol >= nCols ) {
-    table()->appendColumn( cSpan );
-    currentSpan = cSpan;
- } else {
-    if ( cSpan < columns[cCol].span )
- table()->splitColumn( cCol, cSpan );
-    currentSpan = columns[cCol].span;
- }
- int r = 0;
- while ( r < rSpan ) {
-    if ( !cellAt( cRow + r, cCol ) ) {
-// qDebug("    adding cell at %d, %d",  cRow + r, cCol );
- cellAt( cRow + r, cCol ) = set;
-    }
-    r++;
- }
- cCol++;
- cSpan -= currentSpan;
- set = (RenderTableCell *)-1;
+        int currentSpan;
+        if ( cCol >= nCols ) {
+            table()->appendColumn( cSpan );
+            currentSpan = cSpan;
+        } else {
+            if ( cSpan < columns[cCol].span ) {
+                table()->splitColumn( cCol, cSpan );
+            }
+            currentSpan = columns[cCol].span;
+        }
+
+        while( columnsToAvoid.contains(cCol) )
+            ++cCol;
+
+        int r = 0;
+        while ( r < rSpan ) {
+            if ( !cellAt( cRow + r, cCol ) ) {
+    qDebug("    adding cell at %d, %d",  cRow + r, cCol );
+                cellAt( cRow + r, cCol ) = set;
+            }
+            ++r;
+        }
+        ++cCol;
+        cSpan -= currentSpan;
+        set = (RenderTableCell *)-1;
     }
+
+
     if ( cell ) {
- cell->setRow( cRow );
- cell->setCol( table()->effColToCol( col ) );
+        cell->setRow( cRow );
+        cell->setCol( table()->effColToCol( col ) );
     }
 }
 
-
-
 void RenderTableSection::setCellWidths()
 {
 #ifdef DEBUG_LAYOUT
@@ -1781,7 +1897,7 @@
  if ( !cell || cell == (RenderTableCell *)-1 || nextrow && (*nextrow)[c] == cell )
     continue;
                 RenderObject* rowr = cell->parent();
-                int rtx = tx+rowr->xPos();
+                int rtx = tx+rowr->xPos();
                 int rty = ty+rowr->yPos();
 #ifdef TABLE_PRINT
  kDebug( 6040 ) << "painting cell " << r << "/" << c;
@@ -1826,23 +1942,25 @@
 int RenderTableSection::numColumns() const
 {
     int result = 0;
-    
+
     for (int r = 0; r < numRows(); ++r) {
         for (int c = result; c < table()->numEffCols(); ++c) {
             if (cellAt(r, c))
                 result = c;
         }
     }
-    
+
     return result + 1;
 }
-
+
 void RenderTableSection::recalcCells()
 {
     cCol = 0;
     cRow = -1;
     clearGrid();
     grid.resize( 0 );
+    cellsWithColSpanZero.clear();
+    cellsWithRowSpanZero.clear();
 
     for (RenderObject *row = firstChild(); row; row = row->nextSibling()) {
         if (row->isTableRow())  {
@@ -1854,6 +1972,7 @@
             for (RenderObject *cell = row->firstChild(); cell; cell = cell->nextSibling())
                 if (cell->isTableCell())
                     addCell( static_cast<RenderTableCell *>(cell), static_cast<RenderTableRow *>(row) );
+
  }
     }
     needCellRecalc = false;
@@ -2563,7 +2682,7 @@
     RenderTableCol* colElt = table()->colElement(col() + (rtl ? colSpan() - 1 : 0), &startColEdge, &endColEdge);
     if (colElt && (!rtl ? startColEdge : endColEdge)) {
         result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderLeft(), BCOL));
-        if (!result.exists())
+        if (!result.exists())
             return result;
         if (colElt->parent()->isTableCol() && (!rtl ? !colElt->previousSibling() : !colElt->nextSibling())) {
             result = compareBorders(result, CollapsedBorderValue(&colElt->parent()->style()->borderLeft(), BCOLGROUP));
Index: rendering/render_table.h
===================================================================
--- rendering/render_table.h (revisión: 954616)
+++ rendering/render_table.h (copia de trabajo)
@@ -273,6 +273,12 @@
 
     int numColumns() const;
 
+    //QMap< nextColumnToInsert, cell >
+    QMap< int, RenderTableCell* > cellsWithColSpanZero;
+    //QMap< nextRowToInsert, cell >
+    QMap< int, RenderTableCell* > cellsWithRowSpanZero;
+    bool containsSpansZero;
+
     signed short cRow;
     ushort cCol;
     bool needCellRecalc;

 « Return to Thread: Patch for when rowspan or colspan equals 0