use super::super::draw_command::{DrawCommand, LayoutedPage};
use super::super::fragment::Fragment;
use super::super::page::PageConfig;
use super::super::paragraph::{layout_paragraph, ParagraphStyle};
use super::{FOOTNOTE_SEPARATOR_GAP, FOOTNOTE_SEPARATOR_LINE_WIDTH, FOOTNOTE_SEPARATOR_RATIO};
use crate::render::dimension::Pt;
fn split_at_breaks(fragments: &[Fragment], is_break: fn(&Fragment) -> bool) -> Vec<&[Fragment]> {
let has_break = fragments.iter().any(is_break);
if !has_break {
return vec![fragments];
}
let mut chunks = Vec::new();
let mut start = 0;
for (i, frag) in fragments.iter().enumerate() {
if is_break(frag) {
chunks.push(&fragments[start..i]);
start = i + 1;
}
}
chunks.push(&fragments[start..]);
chunks
}
pub(super) fn split_at_column_breaks(fragments: &[Fragment]) -> Vec<&[Fragment]> {
split_at_breaks(fragments, |f| matches!(f, Fragment::ColumnBreak))
}
pub(super) fn split_at_page_breaks(fragments: &[Fragment]) -> Vec<&[Fragment]> {
split_at_breaks(fragments, Fragment::is_page_break)
}
pub(super) fn render_page_footnotes(
page: &mut LayoutedPage,
config: &PageConfig,
footnotes: &[(&[Fragment], &ParagraphStyle)],
default_line_height: Pt,
measure_text: super::super::paragraph::MeasureTextFn<'_>,
separator_indent: Pt,
) {
let content_width = config.content_width();
let constraints = super::super::BoxConstraints::tight_width(content_width, Pt::INFINITY);
let page_bottom = config.page_size.height - config.margins.bottom;
let mut footnote_layouts = Vec::new();
let mut total_height = FOOTNOTE_SEPARATOR_GAP; for (frags, style) in footnotes {
let para = layout_paragraph(
frags,
&constraints,
style,
default_line_height,
measure_text,
);
total_height += para.size.height;
footnote_layouts.push(para);
}
let footnote_top = page_bottom - total_height;
let sep_x = config.margins.left + separator_indent;
let sep_width = content_width * FOOTNOTE_SEPARATOR_RATIO;
page.commands.push(DrawCommand::Line {
line: crate::render::geometry::PtLineSegment::new(
crate::render::geometry::PtOffset::new(sep_x, footnote_top),
crate::render::geometry::PtOffset::new(sep_x + sep_width, footnote_top),
),
color: crate::render::resolve::color::RgbColor::BLACK,
width: FOOTNOTE_SEPARATOR_LINE_WIDTH,
});
let mut cursor_y = footnote_top + FOOTNOTE_SEPARATOR_GAP;
for para in footnote_layouts {
for mut cmd in para.commands {
cmd.shift_y(cursor_y);
cmd.shift_x(config.margins.left);
page.commands.push(cmd);
}
cursor_y += para.size.height;
}
}
pub(super) fn table_x_offset(
alignment: Option<crate::model::Alignment>,
indent: Pt,
table_width: Pt,
content_width: Pt,
margin_left: Pt,
) -> Pt {
use crate::model::Alignment;
match alignment {
Some(Alignment::Center) => margin_left + (content_width - table_width) * 0.5,
Some(Alignment::End) => margin_left + content_width - table_width,
_ => margin_left + indent,
}
}