use std::rc::Rc;
use crate::docx::NoteKind;
use crate::font::Face;
use crate::docx::VMerge;
use super::ids::{FloatId, FragmentId, ParaId, TableId, Unit};
#[derive(Clone, Debug)]
pub struct GlyphRun {
pub face: Rc<Face>,
pub size: f64,
pub baseline: f64,
pub x: f64,
pub glyphs: Box<[(u32, f64)]>,
pub chars: Box<[(char, f64, Option<Unit>)]>,
pub colour: Option<u32>,
pub para: Option<ParaId>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct ImageKey {
pub index: Option<usize>,
pub generation: u32,
}
#[derive(Clone, Debug)]
pub enum Item {
Glyphs(GlyphRun),
Rect {
rect: [f64; 4],
colour: u32,
},
Image {
rect: [f64; 4],
key: ImageKey,
},
Gridline {
line: [f64; 4],
},
}
impl Item {
pub fn top(&self) -> f64 {
match self {
Item::Glyphs(r) => r.baseline,
Item::Rect { rect, .. } | Item::Image { rect, .. } => rect[1],
Item::Gridline { line } => line[1],
}
}
}
#[derive(Debug)]
pub struct LineFragment {
pub items: Box<[Item]>,
pub pitch: f64,
pub baseline: f64,
pub atoms: Box<[(f64, f64, Unit, bool)]>,
}
#[derive(Clone, Debug)]
pub struct PlacedLine {
pub x: f64,
pub y: f64,
pub line: Rc<LineFragment>,
}
#[derive(Clone, Debug)]
pub struct ParaFragment {
pub para: ParaId,
pub lines: Box<[PlacedLine]>,
pub line_numbers: Box<[Box<[Item]>]>,
}
#[derive(Clone, Debug)]
pub struct CellFragment {
pub cell: usize,
pub content: Box<[Child]>,
pub place: CellPlace,
}
#[derive(Clone, Debug)]
pub struct CellPlace {
pub index: usize,
pub col: usize,
pub span: usize,
pub rect: [f64; 4],
pub clip: Option<f64>,
pub v_merge: VMerge,
pub hidden: Box<[(ParaId, Unit, Unit)]>,
pub closing: Option<(ParaId, [f64; 3])>,
}
impl CellPlace {
pub fn moved_down(&self, dy: f64) -> CellPlace {
let [x0, y0, x1, y1] = self.rect;
CellPlace {
rect: [x0, y0 + dy, x1, y1 + dy],
clip: self.clip.map(|c| c + dy),
closing: self.closing.map(|(p, [x, y, h])| (p, [x, y + dy, h])),
hidden: self.hidden.clone(),
..*self
}
}
}
#[derive(Clone, Debug)]
pub struct RowFragment {
pub row: usize,
pub rect: [f64; 4],
pub top: f64,
pub edges: Box<[(f64, usize)]>,
pub background: Box<[Item]>,
pub cells: Box<[CellFragment]>,
pub borders: Box<[Item]>,
pub repeat: bool,
}
#[derive(Clone, Debug)]
pub struct TableFragment {
pub table: TableId,
pub rows: Box<[RowFragment]>,
}
#[derive(Clone, Debug, PartialEq)]
pub enum BoxKind {
Body,
Column,
Notes,
Note {
kind: NoteKind,
id: i64,
},
Separator,
Float {
anchor: ParaId,
float: FloatId,
rect: [f64; 4],
},
Header {
story: String,
},
Footer {
story: String,
},
}
#[derive(Clone, Debug)]
pub enum Child {
Box(BoxFragment),
Para(ParaFragment),
Table(TableFragment),
Line {
para: Option<ParaId>,
placed: PlacedLine,
},
Items(Box<[Item]>),
Group {
offset: (f64, f64),
children: Rc<[Child]>,
},
}
#[derive(Clone, Debug)]
pub struct BoxFragment {
pub kind: BoxKind,
pub id: Option<FragmentId>,
pub offset: (f64, f64),
pub size: (f64, f64),
pub children: Box<[Child]>,
}
#[derive(Debug)]
pub struct PageFragment {
pub id: FragmentId,
pub w: f64,
pub h: f64,
pub body_area: Option<(f64, f64)>,
pub children: Box<[PageChild]>,
}
#[derive(Clone, Debug)]
pub enum PageChild {
Body(Rc<BoxFragment>),
Header(BoxFragment),
Footer(BoxFragment),
}
#[derive(Default)]
pub struct BoxBuilder {
children: Vec<Child>,
}
impl BoxBuilder {
pub fn new() -> BoxBuilder {
BoxBuilder::default()
}
pub fn push(&mut self, c: Child) {
self.children.push(c);
}
pub fn len(&self) -> usize {
self.children.len()
}
pub fn is_empty(&self) -> bool {
self.children.is_empty()
}
pub fn truncate(&mut self, len: usize) {
self.children.truncate(len);
}
pub fn finish(self, kind: BoxKind, offset: (f64, f64), size: (f64, f64)) -> BoxFragment {
BoxFragment { kind, id: None, offset, size, children: self.children.into_boxed_slice() }
}
}