only match consecutive conflicting headers

This commit is contained in:
PgBiel 2025-04-07 21:19:28 -03:00
parent 8e50df544d
commit 05d4af43b6
2 changed files with 46 additions and 27 deletions

View File

@ -219,21 +219,47 @@ impl<'a> GridLayouter<'a> {
if first_header.unwrap().range().contains(&y) {
consecutive_header_count += 1;
if self.upcoming_headers.get(consecutive_header_count).is_none_or(
|h| {
h.unwrap().start > first_header.unwrap().end
|| h.unwrap().level <= first_header.unwrap().level
},
) {
// Next row either isn't a header. or is in a
// conflicting one, which is the sign that we need to go.
// TODO: surely there is a better way to do this
match self.upcoming_headers.get(consecutive_header_count) {
// No more headers, so place the latest headers.
None => {
self.place_new_headers(
first_header,
consecutive_header_count,
None,
engine,
)?;
consecutive_header_count = 0;
}
// Next header is not consecutive, so place the latest headers.
Some(next_header)
if next_header.unwrap().start > first_header.unwrap().end =>
{
self.place_new_headers(
consecutive_header_count,
None,
engine,
)?;
consecutive_header_count = 0;
}
// Next header is consecutive and conflicts with one or
// more of the latest consecutive headers, so we must
// place them before proceeding.
Some(next_header)
if next_header.unwrap().level
<= first_header.unwrap().level =>
{
self.place_new_headers(
consecutive_header_count,
Some(next_header),
engine,
)?;
consecutive_header_count = 0;
}
// Next header is a non-conflicting consecutive header.
// Keep collecting more headers.
_ => {}
}
y = first_header.unwrap().end;
// Skip header rows during normal layout.
continue;

View File

@ -24,28 +24,21 @@ pub enum HeadersToLayout<'a> {
impl<'a> GridLayouter<'a> {
pub fn place_new_headers(
&mut self,
first_header: &Repeatable<Header>,
consecutive_header_count: usize,
conflicting_header: Option<&Repeatable<Header>>,
engine: &mut Engine,
) -> SourceResult<()> {
// Next row either isn't a header. or is in a
// conflicting one, which is the sign that we need to go.
let (consecutive_headers, new_upcoming_headers) =
self.upcoming_headers.split_at(consecutive_header_count);
self.upcoming_headers = new_upcoming_headers;
let (non_conflicting_headers, conflicting_headers) = match self
.upcoming_headers
.get(consecutive_header_count)
.map(Repeatable::unwrap)
{
Some(next_header) if next_header.level <= first_header.unwrap().level => {
let (non_conflicting_headers, conflicting_headers) = match conflicting_header {
Some(conflicting_header) => {
// All immediately conflicting headers will
// be placed as normal rows.
consecutive_headers.split_at(
consecutive_headers
.partition_point(|h| next_header.level > h.unwrap().level),
)
consecutive_headers.split_at(consecutive_headers.partition_point(|h| {
conflicting_header.unwrap().level > h.unwrap().level
}))
}
_ => (consecutive_headers, Default::default()),
};