Repository: typst/typst
File: crates/typst-layout/src/grid/rowspans.rs (Rust)

Code before:
                        .take_while(|row| row.y < header.end);

                    header_rows.map(|row| row.height).sum()
                } else {
                    // Without a header, start at the very top of the region.
                    Abs::zero()
                }
            };

            finished.push_frame(Point::new(dx, dy), frame);
        }

        Ok(())
    }

    /// Checks if a row contains the beginning of one or more rowspan cells.
    /// If so, adds them to the rowspans vector.
    pub fn check_for_rowspans(&mut self, disambiguator: usize, y: usize) {
        let offsets = points(self.rcols.iter().copied());
        for (x, dx) in (0..self.rcols.len()).zip(offsets) {
            let Some(cell) = self.grid.cell(x, y) else {
                continue;
            };
            let rowspan = self.grid.effective_rowspan_of_cell(cell);
            if rowspan > 1 {
                // Rowspan detected. We will lay it out later.
                self.rowspans.push(Rowspan {
                    x,
                    y,
                    disambiguator,
                    rowspan,
                    // The field below will be updated in
                    // 'check_for_unbreakable_rows'.
                    is_effectively_unbreakable: !cell.breakable,
                    dx,
                    // The four fields below will be updated in 'finish_region'.
                    dy: Abs::zero(),
                    first_region: usize::MAX,
                    region_full: Abs::zero(),
                    heights: vec![],
                    max_resolved_row: None,
                });
            }
        }
    }

    /// Checks if the upcoming rows will be grouped together under an
    /// unbreakable row group, and, if so, advances regions until there is
    /// enough space for them. This can be needed, for example, if there's an
    /// unbreakable rowspan crossing those rows.
    pub fn check_for_unbreakable_rows(

Review comment (suggestion):
I suspect this double reversal was indeed an oversight... The order of `self.rowspans` changes, but this doesn't seem to affect rowspan layout code as it doesn't consider that order (all information is contained in x, y, dx, which seems to be the same anyway), so that was a good catch.

Code after:
                        .rrows
                        .get(i)
                        .map(Vec::as_slice)
                        .or(current_rrows)
                        .unwrap_or(&[])
                        .iter()
                        .take_while(|row| row.y < header.end);

                    header_rows.map(|row| row.height).sum()
                } else {
                    // Without a header, start at the very top of the region.
                    Abs::zero()
                }
            };

            finished.push_frame(Point::new(dx, dy), frame);
        }

        Ok(())
    }

    /// Checks if a row contains the beginning of one or more rowspan cells.
    /// If so, adds them to the rowspans vector.
    pub fn check_for_rowspans(&mut self, disambiguator: usize, y: usize) {
        let offsets = points(self.rcols.iter().copied());
        for (x, dx) in (0..self.rcols.len()).zip(offsets) {
            let Some(cell) = self.grid.cell(x, y) else {
                continue;
            };
            let rowspan = self.grid.effective_rowspan_of_cell(cell);
            if rowspan > 1 {
                // Rowspan detected. We will lay it out later.
                self.rowspans.push(Rowspan {
                    x,
                    y,
                    disambiguator,
                    rowspan,
                    // The field below will be updated in
                    // 'check_for_unbreakable_rows'.
                    is_effectively_unbreakable: !cell.breakable,
                    dx,
                    // The four fields below will be updated in 'finish_region'.
                    dy: Abs::zero(),
                    first_region: usize::MAX,
                    region_full: Abs::zero(),
                    heights: vec![],
                    max_resolved_row: None,
                });
            }
        }
    }