use crate::args::{FlipType, LayoutType, OddEven};
pub fn generate_booklet_imposition(n: u32, layout: LayoutType) -> Vec<u32> {
if n == 0 {
return Vec::new();
}
let pages_per_physical_sheet: u32 = match layout {
LayoutType::TwoUp => 4,
LayoutType::FourUp => 8,
};
let total_pages = n.div_ceil(pages_per_physical_sheet) * pages_per_physical_sheet;
let mut imposition_list: Vec<u32> = Vec::new();
let num_physical_sheets = total_pages / pages_per_physical_sheet;
for k in 0..num_physical_sheets {
match layout {
LayoutType::FourUp => {
let side_a_pages = [
total_pages - (4 * k), 1 + (4 * k), total_pages - (4 * k + 2), 3 + (4 * k), ];
imposition_list.extend_from_slice(&side_a_pages);
let side_b_pages = [
2 + (4 * k), total_pages - (4 * k + 1), 4 + (4 * k), total_pages - (4 * k + 3), ];
imposition_list.extend_from_slice(&side_b_pages);
}
LayoutType::TwoUp => {
let side_a_pages = [
total_pages - (2 * k), 1 + (2 * k), ];
imposition_list.extend_from_slice(&side_a_pages);
let side_b_pages = [
2 + (2 * k), total_pages - (2 * k + 1), ];
imposition_list.extend_from_slice(&side_b_pages);
}
}
}
let final_imposition_list: Vec<u32> = imposition_list
.into_iter()
.map(|p| if p > n { 0 } else { p })
.collect();
final_imposition_list
}
pub fn generate_double_sided_order(
total_pages: u32,
flip_type: FlipType,
odd_even: OddEven,
) -> Vec<u32> {
let should_reverse = match (flip_type, odd_even) {
(FlipType::RR, OddEven::Odd) => true,
(FlipType::RR, OddEven::Even) => true,
(FlipType::NN, OddEven::Odd) => false,
(FlipType::NN, OddEven::Even) => false,
(FlipType::RN, OddEven::Odd) => true,
(FlipType::RN, OddEven::Even) => false,
(FlipType::NR, OddEven::Odd) => false,
(FlipType::NR, OddEven::Even) => true,
};
let mut pages = match odd_even {
OddEven::Odd => {
(1..=total_pages).step_by(2).collect::<Vec<u32>>()
}
OddEven::Even => {
let mut even_pages: Vec<u32> = (2..=total_pages).step_by(2).collect();
if total_pages % 2 == 1 {
even_pages.push(0);
}
even_pages
}
};
if should_reverse {
pages.reverse();
}
pages
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_eight_up_n_0_pages() {
assert_eq!(generate_booklet_imposition(0, LayoutType::FourUp), vec![]);
}
#[test]
fn test_eight_up_n_16_pages() {
let expected = vec![
16, 1, 14, 3, 2, 15, 4, 13, 12, 5, 10, 7, 6, 11, 8, 9, ];
assert_eq!(
generate_booklet_imposition(16, LayoutType::FourUp),
expected
);
}
#[test]
fn test_eight_up_n_1_page() {
let expected = vec![0, 1, 0, 0, 0, 0, 0, 0];
assert_eq!(generate_booklet_imposition(1, LayoutType::FourUp), expected);
}
#[test]
fn test_eight_up_n_8_pages() {
let expected = vec![8, 1, 6, 3, 2, 7, 4, 5];
assert_eq!(generate_booklet_imposition(8, LayoutType::FourUp), expected);
}
#[test]
fn test_eight_up_n_5_pages() {
let expected = vec![0, 1, 0, 3, 2, 0, 4, 5];
assert_eq!(generate_booklet_imposition(5, LayoutType::FourUp), expected);
}
#[test]
fn test_four_up_n_0_pages() {
assert_eq!(generate_booklet_imposition(0, LayoutType::TwoUp), vec![]);
}
#[test]
fn test_four_up_n_4_pages() {
let expected = vec![4, 1, 2, 3];
assert_eq!(generate_booklet_imposition(4, LayoutType::TwoUp), expected);
}
#[test]
fn test_four_up_n_8_pages() {
let expected = vec![8, 1, 2, 7, 6, 3, 4, 5];
assert_eq!(generate_booklet_imposition(8, LayoutType::TwoUp), expected);
}
#[test]
fn test_four_up_n_1_page() {
let expected = vec![0, 1, 0, 0];
assert_eq!(generate_booklet_imposition(1, LayoutType::TwoUp), expected);
}
#[test]
fn test_four_up_n_6_pages() {
let expected = vec![
0, 1, 2, 0, 6, 3, 4, 5,
];
assert_eq!(generate_booklet_imposition(6, LayoutType::TwoUp), expected);
}
#[test]
fn test_double_sided_zero_pages() {
let result = generate_double_sided_order(0, FlipType::RR, OddEven::Odd);
assert_eq!(result, vec![]);
}
#[test]
fn test_double_sided_single_page() {
let result = generate_double_sided_order(1, FlipType::RR, OddEven::Odd);
assert_eq!(result, vec![1]);
let result = generate_double_sided_order(1, FlipType::RR, OddEven::Even);
assert_eq!(result, vec![0]);
}
}