oxipdf-ir 0.1.0

Intermediate representation types for the oxipdf PDF engine
Documentation
//! Fragmentation / pagination style properties (§6.4).

/// Fragmentation-related style properties controlling page break behavior.
///
/// Default values follow standard typographic conventions:
/// - 2-line widow/orphan minimum
/// - No forced breaks
/// - Auto break-inside (the fragmenter may split the element)
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct FragmentationStyle {
    /// Break behavior before this node.
    pub break_before: BreakValue,
    /// Break behavior after this node.
    pub break_after: BreakValue,
    /// Whether the fragmenter may break inside this node.
    pub break_inside: BreakInside,
    /// Minimum number of lines at the end of a paragraph that must remain
    /// on the current page before a break (prevents orphans).
    pub orphans: u32,
    /// Minimum number of lines at the start of a paragraph that must appear
    /// on the new page after a break (prevents widows).
    pub widows: u32,
    /// Whether this element should be kept together with the next sibling
    /// on the same page (e.g., heading + first paragraph).
    pub keep_with_next: bool,
    /// How to render borders/padding when a container is split across pages (§6.4.1).
    pub box_decoration_break: BoxDecorationBreak,
    /// Academic figure float placement. Controls what happens when this node
    /// doesn't fit on the current page. Default is `Inline` (no deferral).
    pub float_placement: FloatPlacement,
    /// Maximum number of pages a `BestFit` float can be deferred from its
    /// reference point. When the deferral distance would exceed this limit,
    /// the float is forced onto the current page (no deferral).
    /// 0 means unlimited (default).
    pub max_float_deferral: u32,
}

impl Default for FragmentationStyle {
    fn default() -> Self {
        Self {
            break_before: BreakValue::Auto,
            break_after: BreakValue::Auto,
            break_inside: BreakInside::Auto,
            orphans: 2,
            widows: 2,
            keep_with_next: false,
            box_decoration_break: BoxDecorationBreak::Slice,
            float_placement: FloatPlacement::Inline,
            max_float_deferral: 0,
        }
    }
}

/// Break behavior before or after an element.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum BreakValue {
    /// Break is neither forced nor forbidden.
    #[default]
    Auto,
    /// Avoid a page break here if possible.
    Avoid,
    /// Always force a page break here.
    Always,
    /// Avoid a page break (synonym for `Avoid` in paged context).
    AvoidPage,
}

/// Whether the fragmenter may break inside an element.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum BreakInside {
    /// The fragmenter may split this element across pages.
    #[default]
    Auto,
    /// Avoid splitting this element across pages if possible.
    Avoid,
}

/// Academic figure float placement strategy.
///
/// Controls how the fragmenter handles a node that doesn't fit on the
/// current page. Unlike CSS `float` (which wraps inline content around
/// a box), this controls pagination-level placement — deferring figures
/// to the next page while letting body text fill the remaining space.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum FloatPlacement {
    /// Normal flow. The node stays wherever the continuous layout placed it.
    /// If it overflows the page, it is either clipped or causes an error
    /// (for atomic nodes).
    #[default]
    Inline,
    /// Best fit: if the node fits on the current page, place it normally.
    /// If it overflows, defer it to the top of the next page and let
    /// subsequent body text fill the remaining space on the current page.
    BestFit,
    /// Always place at the top of whichever page the node lands on.
    TopOfPage,
    /// Always defer to the top of the next page, regardless of fit.
    NextPage,
}

/// How borders and padding are rendered when a container is split across pages.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum BoxDecorationBreak {
    /// Borders/padding are "sliced" at the break point: open-bottom on the
    /// current page, open-top on the continuation page.
    #[default]
    Slice,
    /// Borders/padding are fully repeated (cloned) on each fragment.
    Clone,
}