Bug 1409114 Comment 8 Edit History

Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.

I had a bit of a read of the code surrounding this, since it was interesting and I really don't know it well enough.

The frame tree structure for a table looks like this:

```
Table
  RowGroup1
    Row1
      Cell1
      Cell2
    Row2
      Cell3
  RowGroup2
    Row3
      Cell4
  ColGroupList<
  ColGroup1
    Column1
    Column2
  ColGroup2
    Column3
  >
```

Tracing through the display list building code for this gives us this iteration order:

```
Table BuildDisplayList/DisplayGenericTablePart

  For-each ColGroup, call BuildDisplayList/DisplayGenericTablePart
    Build a vector of Column indices in the ColGroup
      For-each RowGroup in the table, call PaintRowGroupBackgroundByColIdx with the Column indices
        For-each Row in the RowGroup
          For-each Cell in the Row
            Add col-group background for the cell if cell is in one of the columns

      For-each Column, call BuildDisplayList/DisplayGenericTablePart
        For-each RowGroup in the table, call PaintRowGroupBackgroundByColIdx with the the current Column index
          For-each Row in the RowGroup
            For-each Cell in the Row
              Add column background for the cell if cell is in the current columns

  For-each RowGroup (principal child list) BuildDisplayList/DisplayGenericTablePart
    Call PaintRowGroupBackground
      For-each Row, call PaintRowBackground
        For-each Cell in the Row
          Add the row-group background for the cell
		
    For-each Row in the group call BuildDisplayList/DisplayGenericTablePart (uses DisplayRows, maybe using a cursor to optimise iteration)
      Call PaintRowBackground
        For-each Cell in the Row
          Add the row background for the cell

      For-each Cell in the Row, call BuildDisplayList/DisplayGenericTablePart
        Add display items for cell, and recurse into descendants.
```

(Which is the same as bz said at [1], just worded slightly differently)


I think we could solve all of this by doing a single iteration of the table (just descending through principal children lists), collecting the different types of items separately, and then collating them in the right order at the end.

We can create a temporary nsDisplayListSet to collect all the 'normal' items (items for the cells themselves, and their descendants), and pass this through BuildDisplayList. We can then also create 4 (col-group, col, row-group, row) extra nsDisplayLists (stored centrally somewhere, similar to nsDisplayListBuilder::GetCurrentTableItem), and each cell can also add background items to those lists.

Once we've finished building all the items for the table, we can sort the special lists so that they have the same order as the current iterations, and append all their items to the BorderBackground() list of the outer nsDisplayListSet. Then we append all the items/lists from the temp nsDisplayListSet to the outer, guaranteeing that these items end up after all table-specific backgrounds.

For sorting the special lists, both row-group and row backgrounds should already be in the right order. Column backgrounds need to be sorted by column, but we can look this up easily using nsTableCellFrame::GetColIndex (or cache it when we stored the item to avoid another dereference). 

The col-group lists needs to be sorted by col-group, which we don't have an easy way to do (afaict). I believe col-groups are relatively rare, so we can probably not worry about this too much. Maybe build a hashmap of column index -> col-group index?

Doing that would give us a single pass over all the cells, and should make things significantly faster, especially when retaining isn't effective.



[1] https://bugzilla.mozilla.org/show_bug.cgi?id=1409047#c9
I had a bit of a read of the code surrounding this, since it was interesting and I really don't know it well enough.

The frame tree structure for a table looks like this:

```
Table
  RowGroup1
    Row1
      Cell1
      Cell2
    Row2
      Cell3
  RowGroup2
    Row3
      Cell4
  ColGroupList<
  ColGroup1
    Column1
    Column2
  ColGroup2
    Column3
  >
```

Tracing through the display list building code for this gives us this iteration order:

```
Table BuildDisplayList/DisplayGenericTablePart

  For-each ColGroup, call BuildDisplayList/DisplayGenericTablePart
    Build a vector of Column indices in the ColGroup
    For-each RowGroup in the table, call PaintRowGroupBackgroundByColIdx with the Column indices
      For-each Row in the RowGroup
        For-each Cell in the Row
          Add col-group background for the cell if cell is in one of the columns

    For-each Column, call BuildDisplayList/DisplayGenericTablePart
      For-each RowGroup in the table, call PaintRowGroupBackgroundByColIdx with the the current Column index
        For-each Row in the RowGroup
          For-each Cell in the Row
            Add column background for the cell if cell is in the current columns

  For-each RowGroup (principal child list) BuildDisplayList/DisplayGenericTablePart
    Call PaintRowGroupBackground
      For-each Row, call PaintRowBackground
        For-each Cell in the Row
          Add the row-group background for the cell
		
    For-each Row in the group call BuildDisplayList/DisplayGenericTablePart (uses DisplayRows, maybe using a cursor to optimise iteration)
      Call PaintRowBackground
        For-each Cell in the Row
          Add the row background for the cell

      For-each Cell in the Row, call BuildDisplayList/DisplayGenericTablePart
        Add display items for cell, and recurse into descendants.
```

(Which is the same as bz said at [1], just worded slightly differently)


I think we could solve all of this by doing a single iteration of the table (just descending through principal children lists), collecting the different types of items separately, and then collating them in the right order at the end.

We can create a temporary nsDisplayListSet to collect all the 'normal' items (items for the cells themselves, and their descendants), and pass this through BuildDisplayList. We can then also create 4 (col-group, col, row-group, row) extra nsDisplayLists (stored centrally somewhere, similar to nsDisplayListBuilder::GetCurrentTableItem), and each cell can also add background items to those lists.

Once we've finished building all the items for the table, we can sort the special lists so that they have the same order as the current iterations, and append all their items to the BorderBackground() list of the outer nsDisplayListSet. Then we append all the items/lists from the temp nsDisplayListSet to the outer, guaranteeing that these items end up after all table-specific backgrounds.

For sorting the special lists, both row-group and row backgrounds should already be in the right order. Column backgrounds need to be sorted by column, but we can look this up easily using nsTableCellFrame::GetColIndex (or cache it when we stored the item to avoid another dereference). 

The col-group lists needs to be sorted by col-group, which we don't have an easy way to do (afaict). I believe col-groups are relatively rare, so we can probably not worry about this too much. Maybe build a hashmap of column index -> col-group index?

Doing that would give us a single pass over all the cells, and should make things significantly faster, especially when retaining isn't effective.



[1] https://bugzilla.mozilla.org/show_bug.cgi?id=1409047#c9
I had a bit of a read of the code surrounding this, since it was interesting and I really don't know it well enough.

The frame tree structure for a table looks like this:

```
Table
  RowGroup1
    Row1
      Cell1
      Cell2
    Row2
      Cell3
  RowGroup2
    Row3
      Cell4
  ColGroupList<
  ColGroup1
    Column1
    Column2
  ColGroup2
    Column3
  >
```

Tracing through the display list building code for this gives us this iteration order:

```
Table BuildDisplayList/DisplayGenericTablePart

  Table box shadow outer

  Table background

  Table box shadow inner

  Table outline

  For-each ColGroup, call BuildDisplayList/DisplayGenericTablePart
    ColGroup box shadow outer, inner and outline.

    Build a vector of Column indices in the ColGroup
    For-each RowGroup in the table, call PaintRowGroupBackgroundByColIdx with the Column indices
      For-each Row in the RowGroup
        For-each Cell in the Row
          Add col-group background for the cell if cell is in one of the columns

    For-each Column, call BuildDisplayList/DisplayGenericTablePart
      Column box shadow outer, inner and outline.

      For-each RowGroup in the table, call PaintRowGroupBackgroundByColIdx with the the current Column index
        For-each Row in the RowGroup
          For-each Cell in the Row
            Add column background for the cell if cell is in the current columns

      Column border.
    ColGroup border.

  For-each RowGroup (principal child list) BuildDisplayList/DisplayGenericTablePart
    RowGroup box shadow outer, inner and outline.

    Call PaintRowGroupBackground
      For-each Row, call PaintRowBackground
        For-each Cell in the Row
          Add the row-group background for the cell
		
    For-each Row in the group call BuildDisplayList/DisplayGenericTablePart (uses DisplayRows, maybe using a cursor to optimise iteration)
      Row box shadow outer, inner and outline.

      Call PaintRowBackground
        For-each Cell in the Row
          Add the row background for the cell

      For-each Cell in the Row, call BuildDisplayList/DisplayGenericTablePart
        Add display items for cell, and recurse into descendants.

      Row border.

    RowGroup border.
  Table border.
```

(Which is the same as bz said at [1], just worded slightly differently)


I think we could solve all of this by doing a single iteration of the table (just descending through principal children lists), collecting the different types of items separately, and then collating them in the right order at the end.

We can create a temporary nsDisplayListSet to collect all the 'normal' items (items for the cells themselves, and their descendants), and pass this through BuildDisplayList. We can then also create 4 (col-group, col, row-group, row) extra nsDisplayLists (stored centrally somewhere, similar to nsDisplayListBuilder::GetCurrentTableItem), and each cell can also add background items to those lists.

Once we've finished building all the items for the table, we can sort the special lists so that they have the same order as the current iterations, and append all their items to the BorderBackground() list of the outer nsDisplayListSet. Then we append all the items/lists from the temp nsDisplayListSet to the outer, guaranteeing that these items end up after all table-specific backgrounds.

For sorting the special lists, both row-group and row backgrounds should already be in the right order. Column backgrounds need to be sorted by column, but we can look this up easily using nsTableCellFrame::GetColIndex (or cache it when we stored the item to avoid another dereference). 

The col-group lists needs to be sorted by col-group, which we don't have an easy way to do (afaict). I believe col-groups are relatively rare, so we can probably not worry about this too much. Maybe build a hashmap of column index -> col-group index?

Doing that would give us a single pass over all the cells, and should make things significantly faster, especially when retaining isn't effective.



[1] https://bugzilla.mozilla.org/show_bug.cgi?id=1409047#c9
I had a bit of a read of the code surrounding this, since it was interesting and I really don't know it well enough.

The frame tree structure for a table looks like this:

```
Table
  RowGroup1
    Row1
      Cell1
      Cell2
    Row2
      Cell3
  RowGroup2
    Row3
      Cell4
  ColGroupList<
  ColGroup1
    Column1
    Column2
  ColGroup2
    Column3
  >
```

Tracing through the display list building code for this gives us this iteration order:

```
Table BuildDisplayList/DisplayGenericTablePart

  Table box shadow outer

  Table background

  Table box shadow inner

  Table outline

  For-each ColGroup, call BuildDisplayList/DisplayGenericTablePart
    ColGroup box shadow outer

    Build a vector of Column indices in the ColGroup
    For-each RowGroup in the table, call PaintRowGroupBackgroundByColIdx with the Column indices
      For-each Row in the RowGroup
        For-each Cell in the Row
          Add col-group background for the cell if cell is in one of the columns

    For-each Column, call BuildDisplayList/DisplayGenericTablePart
      Column box shadow outer.

      For-each RowGroup in the table, call PaintRowGroupBackgroundByColIdx with the the current Column index
        For-each Row in the RowGroup
          For-each Cell in the Row
            Add column background for the cell if cell is in the current columns

      Column box shadow inner and outline.
    ColGroup box shadow inner and outline.

  For-each RowGroup (principal child list) BuildDisplayList/DisplayGenericTablePart
    RowGroup box shadow outer.

    Call PaintRowGroupBackground
      For-each Row, call PaintRowBackground
        For-each Cell in the Row
          Add the row-group background for the cell
		
    For-each Row in the group call BuildDisplayList/DisplayGenericTablePart (uses DisplayRows, maybe using a cursor to optimise iteration)
      Row box shadow outer.

      Call PaintRowBackground
        For-each Cell in the Row
          Add the row background for the cell

      For-each Cell in the Row, call BuildDisplayList/DisplayGenericTablePart
        Add display items for cell (border, background, shadows, outline etc), and recurse into descendants.

      Row box shadow inner and outline.

    RowGroup box shadow inner and outline.
  Table border, or border-collapse borders for the whole table.
```

(Which is the same as bz said at [1], just worded slightly differently)


I think we could solve all of this by doing a single iteration of the table (just descending through principal children lists), collecting the different types of items separately, and then collating them in the right order at the end.

We can create a temporary nsDisplayListSet to collect all the 'normal' items (items for the cells themselves, and their descendants), and pass this through BuildDisplayList. We can then also create 4 (col-group, col, row-group, row) extra nsDisplayLists (stored centrally somewhere, similar to nsDisplayListBuilder::GetCurrentTableItem), and each cell can also add background items to those lists.

Once we've finished building all the items for the table, we can sort the special lists so that they have the same order as the current iterations, and append all their items to the BorderBackground() list of the outer nsDisplayListSet. Then we append all the items/lists from the temp nsDisplayListSet to the outer, guaranteeing that these items end up after all table-specific backgrounds.

For sorting the special lists, both row-group and row backgrounds should already be in the right order. Column backgrounds need to be sorted by column, but we can look this up easily using nsTableCellFrame::GetColIndex (or cache it when we stored the item to avoid another dereference). 

The col-group lists needs to be sorted by col-group, which we don't have an easy way to do (afaict). I believe col-groups are relatively rare, so we can probably not worry about this too much. Maybe build a hashmap of column index -> col-group index?

Doing that would give us a single pass over all the cells, and should make things significantly faster, especially when retaining isn't effective.



[1] https://bugzilla.mozilla.org/show_bug.cgi?id=1409047#c9
I had a bit of a read of the code surrounding this, since it was interesting and I really don't know it well enough.

The frame tree structure for a table looks like this:

```
Table
  RowGroup1
    Row1
      Cell1
      Cell2
    Row2
      Cell3
  RowGroup2
    Row3
      Cell4
  ColGroupList<
  ColGroup1
    Column1
    Column2
  ColGroup2
    Column3
  >
```

Tracing through the display list building code for this gives us this iteration order:

```
Table BuildDisplayList/DisplayGenericTablePart

  Table box shadow outer

  Table background

  Table box shadow inner

  Table outline

  For-each ColGroup, call BuildDisplayList/DisplayGenericTablePart
    ColGroup box shadow outer

    Build a vector of Column indices in the ColGroup
    For-each RowGroup in the table, call PaintRowGroupBackgroundByColIdx with the Column indices
      For-each Row in the RowGroup
        For-each Cell in the Row
          Add col-group background for the cell if cell is in one of the columns

    For-each Column, call BuildDisplayList/DisplayGenericTablePart
      Column box shadow outer.

      For-each RowGroup in the table, call PaintRowGroupBackgroundByColIdx with the the current Column index
        For-each Row in the RowGroup
          For-each Cell in the Row
            Add column background for the cell if cell is in the current columns

      Column box shadow inner and outline.
    ColGroup box shadow inner and outline.

  For-each RowGroup (principal child list) BuildDisplayList/DisplayGenericTablePart
    RowGroup box shadow outer.

    Call PaintRowGroupBackground
      For-each Row, call PaintRowBackground
        For-each Cell in the Row
          Add the row-group background for the cell

    RowGroup box shadow inner and outline.
		
    For-each Row in the group call BuildDisplayList/DisplayGenericTablePart (uses DisplayRows, maybe using a cursor to optimise iteration)
      Row box shadow outer.

      Call PaintRowBackground
        For-each Cell in the Row
          Add the row background for the cell

      Row box shadow inner and outline.

      For-each Cell in the Row, call BuildDisplayList/DisplayGenericTablePart
        Add display items for cell (border, background, shadows, outline etc), and recurse into descendants.
    
  Table border, or border-collapse borders for the whole table.
```

(Which is the same as bz said at [1], just worded slightly differently)


I think we could solve all of this by doing a single iteration of the table (just descending through principal children lists), collecting the different types of items separately, and then collating them in the right order at the end.

We can create a temporary nsDisplayListSet to collect all the 'normal' items (items for the cells themselves, and their descendants), and pass this through BuildDisplayList. We can then also create 4 (col-group, col, row-group, row) extra nsDisplayLists (stored centrally somewhere, similar to nsDisplayListBuilder::GetCurrentTableItem), and each cell can also add background items to those lists.

Once we've finished building all the items for the table, we can sort the special lists so that they have the same order as the current iterations, and append all their items to the BorderBackground() list of the outer nsDisplayListSet. Then we append all the items/lists from the temp nsDisplayListSet to the outer, guaranteeing that these items end up after all table-specific backgrounds.

For sorting the special lists, both row-group and row backgrounds should already be in the right order. Column backgrounds need to be sorted by column, but we can look this up easily using nsTableCellFrame::GetColIndex (or cache it when we stored the item to avoid another dereference). 

The col-group lists needs to be sorted by col-group, which we don't have an easy way to do (afaict). I believe col-groups are relatively rare, so we can probably not worry about this too much. Maybe build a hashmap of column index -> col-group index?

Doing that would give us a single pass over all the cells, and should make things significantly faster, especially when retaining isn't effective.



[1] https://bugzilla.mozilla.org/show_bug.cgi?id=1409047#c9

Back to Bug 1409114 Comment 8