use chart::ChartSpace;
use drawing::{Color, Fill, Line, ShapeProperties, TextAnchor, TextBody};
pub const EMU_PER_INCH: i64 = 914_400;
pub const DEFAULT_SLIDE_WIDTH_EMU: i64 = 12_192_000;
pub const DEFAULT_SLIDE_HEIGHT_EMU: i64 = 6_858_000;
pub const DEFAULT_NOTES_WIDTH_EMU: i64 = 6_858_000;
pub const DEFAULT_NOTES_HEIGHT_EMU: i64 = 9_144_000;
#[derive(Debug, Clone, PartialEq)]
pub struct Presentation {
pub slides: Vec<Slide>,
pub slide_width_emu: i64,
pub slide_height_emu: i64,
pub theme: Option<Theme>,
pub properties: DocumentProperties,
pub table_styles: Vec<SlideTableStyle>,
pub embedded_fonts: Vec<EmbeddedFont>,
}
impl Presentation {
pub fn new() -> Self {
Self {
slides: Vec::new(),
slide_width_emu: DEFAULT_SLIDE_WIDTH_EMU,
slide_height_emu: DEFAULT_SLIDE_HEIGHT_EMU,
theme: None,
properties: DocumentProperties::new(),
table_styles: Vec::new(),
embedded_fonts: Vec::new(),
}
}
pub fn with_slide(mut self, slide: Slide) -> Self {
self.slides.push(slide);
self
}
pub fn add_slide(&mut self) -> &mut Slide {
self.slides.push(Slide::new());
self.slides.last_mut().expect("a slide was just pushed")
}
pub fn with_slide_size(mut self, width_emu: i64, height_emu: i64) -> Self {
self.slide_width_emu = width_emu;
self.slide_height_emu = height_emu;
self
}
pub fn with_theme(mut self, theme: Theme) -> Self {
self.theme = Some(theme);
self
}
pub fn with_properties(mut self, properties: DocumentProperties) -> Self {
self.properties = properties;
self
}
pub fn with_table_style(mut self, table_style: SlideTableStyle) -> Self {
self.table_styles.push(table_style);
self
}
pub fn with_embedded_font(mut self, font: EmbeddedFont) -> Self {
self.embedded_fonts.push(font);
self
}
}
impl Default for Presentation {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Slide {
pub shapes: Vec<Shape>,
pub notes: Option<TextBody>,
pub comments: Vec<SlideComment>,
pub background: Option<Fill>,
pub hidden: bool,
pub name: Option<String>,
pub hide_master_graphics: bool,
}
impl Slide {
pub fn new() -> Self {
Self::default()
}
pub fn with_shape(mut self, shape: Shape) -> Self {
self.shapes.push(shape);
self
}
pub fn add_shape(&mut self, shape: Shape) -> &mut Shape {
self.shapes.push(shape);
self.shapes.last_mut().expect("a shape was just pushed")
}
pub fn with_hidden(mut self, hidden: bool) -> Self {
self.hidden = hidden;
self
}
pub fn with_name(mut self, name: impl Into<String>) -> Self {
self.name = Some(name.into());
self
}
pub fn with_notes(mut self, notes: TextBody) -> Self {
self.notes = Some(notes);
self
}
pub fn with_comment(mut self, comment: SlideComment) -> Self {
self.comments.push(comment);
self
}
pub fn with_background(mut self, background: Fill) -> Self {
self.background = Some(background);
self
}
pub fn with_hide_master_graphics(mut self, hide: bool) -> Self {
self.hide_master_graphics = hide;
self
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Shape {
AutoShape(AutoShape),
Picture(Picture),
Chart(Box<SlideChart>),
Group(ShapeGroup),
Connector(Connector),
Table(SlideTable),
Media(SlideMedia),
}
#[derive(Debug, Clone, PartialEq)]
pub struct AutoShape {
pub id: u32,
pub name: String,
pub properties: ShapeProperties,
pub text_body: Option<TextBody>,
pub placeholder: Option<Placeholder>,
pub is_text_box: bool,
pub hyperlink: Option<SlideHyperlinkTarget>,
}
impl AutoShape {
pub fn new(id: u32, name: impl Into<String>) -> Self {
Self {
id,
name: name.into(),
properties: ShapeProperties::new(),
text_body: None,
placeholder: None,
is_text_box: false,
hyperlink: None,
}
}
pub fn with_properties(mut self, properties: ShapeProperties) -> Self {
self.properties = properties;
self
}
pub fn with_text_body(mut self, text_body: TextBody) -> Self {
self.text_body = Some(text_body);
self
}
pub fn with_placeholder(mut self, placeholder: Placeholder) -> Self {
self.placeholder = Some(placeholder);
self
}
pub fn with_text_box(mut self, is_text_box: bool) -> Self {
self.is_text_box = is_text_box;
self
}
pub fn with_hyperlink(mut self, url: impl Into<String>) -> Self {
self.hyperlink = Some(SlideHyperlinkTarget::External(url.into()));
self
}
pub fn with_hyperlink_target(mut self, target: SlideHyperlinkTarget) -> Self {
self.hyperlink = Some(target);
self
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SlideHyperlinkTarget {
External(String),
Slide(usize),
NextSlide,
PreviousSlide,
FirstSlide,
LastSlide,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Placeholder {
pub kind: PlaceholderKind,
pub index: Option<u32>,
}
impl Placeholder {
pub fn new(kind: PlaceholderKind) -> Self {
Self { kind, index: None }
}
pub fn with_index(mut self, index: u32) -> Self {
self.index = Some(index);
self
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PlaceholderKind {
Title,
Body,
CenterTitle,
SubTitle,
DateTime,
SlideNumber,
Footer,
Header,
Object,
SlideImage,
Other(String),
}
impl PlaceholderKind {
pub(crate) fn xml_token(&self) -> &str {
match self {
PlaceholderKind::Title => "title",
PlaceholderKind::Body => "body",
PlaceholderKind::CenterTitle => "ctrTitle",
PlaceholderKind::SubTitle => "subTitle",
PlaceholderKind::DateTime => "dt",
PlaceholderKind::SlideNumber => "sldNum",
PlaceholderKind::Footer => "ftr",
PlaceholderKind::Header => "hdr",
PlaceholderKind::Object => "obj",
PlaceholderKind::SlideImage => "sldImg",
PlaceholderKind::Other(token) => token,
}
}
pub(crate) fn from_xml_token(token: &str) -> Self {
match token {
"title" => PlaceholderKind::Title,
"body" => PlaceholderKind::Body,
"ctrTitle" => PlaceholderKind::CenterTitle,
"subTitle" => PlaceholderKind::SubTitle,
"dt" => PlaceholderKind::DateTime,
"sldNum" => PlaceholderKind::SlideNumber,
"ftr" => PlaceholderKind::Footer,
"hdr" => PlaceholderKind::Header,
"obj" => PlaceholderKind::Object,
"sldImg" => PlaceholderKind::SlideImage,
other => PlaceholderKind::Other(other.to_string()),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Picture {
pub id: u32,
pub name: String,
pub data: Vec<u8>,
pub format: PictureFormat,
pub offset_emu: (i64, i64),
pub extent_emu: (i64, i64),
pub description: String,
pub shape_properties: Option<ShapeProperties>,
pub external_link: Option<String>,
}
impl Picture {
pub fn new(
id: u32,
name: impl Into<String>,
data: impl Into<Vec<u8>>,
format: PictureFormat,
width_emu: i64,
height_emu: i64,
) -> Self {
Self {
id,
name: name.into(),
data: data.into(),
format,
offset_emu: (0, 0),
extent_emu: (width_emu, height_emu),
description: String::new(),
shape_properties: None,
external_link: None,
}
}
pub fn with_offset(mut self, x_emu: i64, y_emu: i64) -> Self {
self.offset_emu = (x_emu, y_emu);
self
}
pub fn with_description(mut self, description: impl Into<String>) -> Self {
self.description = description.into();
self
}
pub fn with_shape_properties(mut self, shape_properties: ShapeProperties) -> Self {
self.shape_properties = Some(shape_properties);
self
}
pub fn with_external_link(mut self, url: impl Into<String>) -> Self {
self.external_link = Some(url.into());
self
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PictureFormat {
Png,
Jpeg,
Gif,
Bmp,
}
impl PictureFormat {
pub(crate) fn extension(&self) -> &'static str {
match self {
PictureFormat::Png => "png",
PictureFormat::Jpeg => "jpeg",
PictureFormat::Gif => "gif",
PictureFormat::Bmp => "bmp",
}
}
pub(crate) fn content_type(&self) -> &'static str {
match self {
PictureFormat::Png => "image/png",
PictureFormat::Jpeg => "image/jpeg",
PictureFormat::Gif => "image/gif",
PictureFormat::Bmp => "image/bmp",
}
}
pub(crate) fn from_extension(part_name: &str) -> Option<Self> {
let extension = part_name.rsplit('.').next()?.to_ascii_lowercase();
match extension.as_str() {
"png" => Some(PictureFormat::Png),
"jpeg" | "jpg" => Some(PictureFormat::Jpeg),
"gif" => Some(PictureFormat::Gif),
"bmp" => Some(PictureFormat::Bmp),
_ => None,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct SlideMedia {
pub id: u32,
pub name: String,
pub data: Vec<u8>,
pub format: MediaFormat,
pub offset_emu: (i64, i64),
pub extent_emu: (i64, i64),
pub poster_image: Option<(Vec<u8>, PictureFormat)>,
}
impl SlideMedia {
pub fn new(
id: u32,
name: impl Into<String>,
data: impl Into<Vec<u8>>,
format: MediaFormat,
width_emu: i64,
height_emu: i64,
) -> Self {
Self {
id,
name: name.into(),
data: data.into(),
format,
offset_emu: (0, 0),
extent_emu: (width_emu, height_emu),
poster_image: None,
}
}
pub fn with_offset(mut self, x_emu: i64, y_emu: i64) -> Self {
self.offset_emu = (x_emu, y_emu);
self
}
pub fn with_poster_image(mut self, data: impl Into<Vec<u8>>, format: PictureFormat) -> Self {
self.poster_image = Some((data.into(), format));
self
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MediaFormat {
Mp4,
Wmv,
Avi,
Mp3,
Wav,
}
impl MediaFormat {
pub(crate) fn is_video(&self) -> bool {
matches!(self, MediaFormat::Mp4 | MediaFormat::Wmv | MediaFormat::Avi)
}
pub(crate) fn extension(&self) -> &'static str {
match self {
MediaFormat::Mp4 => "mp4",
MediaFormat::Wmv => "wmv",
MediaFormat::Avi => "avi",
MediaFormat::Mp3 => "mp3",
MediaFormat::Wav => "wav",
}
}
pub(crate) fn content_type(&self) -> &'static str {
match self {
MediaFormat::Mp4 => "video/mp4",
MediaFormat::Wmv => "video/x-ms-wmv",
MediaFormat::Avi => "video/avi",
MediaFormat::Mp3 => "audio/mpeg",
MediaFormat::Wav => "audio/wav",
}
}
pub(crate) fn from_extension(part_name: &str) -> Option<Self> {
let extension = part_name.rsplit('.').next()?.to_ascii_lowercase();
match extension.as_str() {
"mp4" => Some(MediaFormat::Mp4),
"wmv" => Some(MediaFormat::Wmv),
"avi" => Some(MediaFormat::Avi),
"mp3" => Some(MediaFormat::Mp3),
"wav" => Some(MediaFormat::Wav),
_ => None,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct SlideChart {
pub id: u32,
pub name: String,
pub chart_space: ChartSpace,
pub offset_emu: (i64, i64),
pub extent_emu: (i64, i64),
}
impl SlideChart {
pub fn new(
id: u32,
name: impl Into<String>,
chart_space: ChartSpace,
width_emu: i64,
height_emu: i64,
) -> Self {
Self {
id,
name: name.into(),
chart_space,
offset_emu: (0, 0),
extent_emu: (width_emu, height_emu),
}
}
pub fn with_offset(mut self, x_emu: i64, y_emu: i64) -> Self {
self.offset_emu = (x_emu, y_emu);
self
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct ShapeGroup {
pub id: u32,
pub name: String,
pub offset_emu: (i64, i64),
pub extent_emu: (i64, i64),
pub child_offset_emu: (i64, i64),
pub child_extent_emu: (i64, i64),
pub rotation_60000ths: i32,
pub flip_horizontal: bool,
pub flip_vertical: bool,
pub shapes: Vec<Shape>,
}
impl ShapeGroup {
pub fn new(id: u32, name: impl Into<String>) -> Self {
Self {
id,
name: name.into(),
offset_emu: (0, 0),
extent_emu: (0, 0),
child_offset_emu: (0, 0),
child_extent_emu: (0, 0),
rotation_60000ths: 0,
flip_horizontal: false,
flip_vertical: false,
shapes: Vec::new(),
}
}
pub fn with_transform(
mut self,
offset_emu: (i64, i64),
extent_emu: (i64, i64),
child_offset_emu: (i64, i64),
child_extent_emu: (i64, i64),
) -> Self {
self.offset_emu = offset_emu;
self.extent_emu = extent_emu;
self.child_offset_emu = child_offset_emu;
self.child_extent_emu = child_extent_emu;
self
}
pub fn with_rotation_degrees(mut self, degrees: f64) -> Self {
self.rotation_60000ths = (degrees * 60_000.0).round() as i32;
self
}
pub fn with_flip_horizontal(mut self, flip: bool) -> Self {
self.flip_horizontal = flip;
self
}
pub fn with_flip_vertical(mut self, flip: bool) -> Self {
self.flip_vertical = flip;
self
}
pub fn with_shape(mut self, shape: Shape) -> Self {
self.shapes.push(shape);
self
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Connector {
pub id: u32,
pub name: String,
pub properties: ShapeProperties,
pub start_connection: Option<ShapeConnection>,
pub end_connection: Option<ShapeConnection>,
}
impl Connector {
pub fn new(id: u32, name: impl Into<String>) -> Self {
Self {
id,
name: name.into(),
properties: ShapeProperties::new(),
start_connection: None,
end_connection: None,
}
}
pub fn with_properties(mut self, properties: ShapeProperties) -> Self {
self.properties = properties;
self
}
pub fn with_start_connection(mut self, shape_id: u32, index: u32) -> Self {
self.start_connection = Some(ShapeConnection { shape_id, index });
self
}
pub fn with_end_connection(mut self, shape_id: u32, index: u32) -> Self {
self.end_connection = Some(ShapeConnection { shape_id, index });
self
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ShapeConnection {
pub shape_id: u32,
pub index: u32,
}
#[derive(Debug, Clone, PartialEq)]
pub struct SlideTable {
pub id: u32,
pub name: String,
pub offset_emu: (i64, i64),
pub extent_emu: (i64, i64),
pub column_widths_emu: Vec<i64>,
pub rows: Vec<TableRow>,
pub style_id: Option<String>,
pub style_first_row: bool,
pub style_first_column: bool,
pub style_last_row: bool,
pub style_last_column: bool,
pub style_band_rows: bool,
pub style_band_columns: bool,
}
impl SlideTable {
pub fn new(id: u32, name: impl Into<String>, width_emu: i64, height_emu: i64) -> Self {
Self {
id,
name: name.into(),
offset_emu: (0, 0),
extent_emu: (width_emu, height_emu),
column_widths_emu: Vec::new(),
rows: Vec::new(),
style_id: None,
style_first_row: false,
style_first_column: false,
style_last_row: false,
style_last_column: false,
style_band_rows: false,
style_band_columns: false,
}
}
pub fn with_offset(mut self, x_emu: i64, y_emu: i64) -> Self {
self.offset_emu = (x_emu, y_emu);
self
}
pub fn with_style_id(mut self, style_id: impl Into<String>) -> Self {
self.style_id = Some(style_id.into());
self
}
pub fn with_column_widths(mut self, column_widths_emu: impl Into<Vec<i64>>) -> Self {
self.column_widths_emu = column_widths_emu.into();
self
}
pub fn with_row(mut self, row: TableRow) -> Self {
self.rows.push(row);
self
}
pub fn with_style_first_row(mut self, apply: bool) -> Self {
self.style_first_row = apply;
self
}
pub fn with_style_first_column(mut self, apply: bool) -> Self {
self.style_first_column = apply;
self
}
pub fn with_style_last_row(mut self, apply: bool) -> Self {
self.style_last_row = apply;
self
}
pub fn with_style_last_column(mut self, apply: bool) -> Self {
self.style_last_column = apply;
self
}
pub fn with_style_band_rows(mut self, apply: bool) -> Self {
self.style_band_rows = apply;
self
}
pub fn with_style_band_columns(mut self, apply: bool) -> Self {
self.style_band_columns = apply;
self
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct TableRow {
pub height_emu: i64,
pub cells: Vec<TableCell>,
}
impl TableRow {
pub fn new(height_emu: i64) -> Self {
Self {
height_emu,
cells: Vec::new(),
}
}
pub fn with_cell(mut self, cell: TableCell) -> Self {
self.cells.push(cell);
self
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct TableCell {
pub text_body: Option<TextBody>,
pub horizontal_span: Option<u32>,
pub vertical_span: Option<u32>,
pub horizontal_merge: bool,
pub vertical_merge: bool,
pub properties: Option<TableCellProperties>,
}
impl TableCell {
pub fn new() -> Self {
Self::default()
}
pub fn with_text_body(mut self, text_body: TextBody) -> Self {
self.text_body = Some(text_body);
self
}
pub fn with_properties(mut self, properties: TableCellProperties) -> Self {
self.properties = Some(properties);
self
}
pub fn with_horizontal_span(mut self, span: u32) -> Self {
self.horizontal_span = Some(span);
self
}
pub fn with_vertical_span(mut self, span: u32) -> Self {
self.vertical_span = Some(span);
self
}
pub fn horizontally_merged() -> Self {
Self {
horizontal_merge: true,
..Self::default()
}
}
pub fn vertically_merged() -> Self {
Self {
vertical_merge: true,
..Self::default()
}
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct TableCellProperties {
pub margin_left_emu: Option<i64>,
pub margin_top_emu: Option<i64>,
pub margin_right_emu: Option<i64>,
pub margin_bottom_emu: Option<i64>,
pub anchor: Option<TextAnchor>,
pub border_left: Option<Line>,
pub border_right: Option<Line>,
pub border_top: Option<Line>,
pub border_bottom: Option<Line>,
pub fill: Option<Fill>,
}
impl TableCellProperties {
pub fn new() -> Self {
Self::default()
}
pub fn with_margins_emu(mut self, left: i64, top: i64, right: i64, bottom: i64) -> Self {
self.margin_left_emu = Some(left);
self.margin_top_emu = Some(top);
self.margin_right_emu = Some(right);
self.margin_bottom_emu = Some(bottom);
self
}
pub fn with_anchor(mut self, anchor: TextAnchor) -> Self {
self.anchor = Some(anchor);
self
}
pub fn with_border_left(mut self, border: Line) -> Self {
self.border_left = Some(border);
self
}
pub fn with_border_right(mut self, border: Line) -> Self {
self.border_right = Some(border);
self
}
pub fn with_border_top(mut self, border: Line) -> Self {
self.border_top = Some(border);
self
}
pub fn with_border_bottom(mut self, border: Line) -> Self {
self.border_bottom = Some(border);
self
}
pub fn with_fill(mut self, fill: Fill) -> Self {
self.fill = Some(fill);
self
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct SlideComment {
pub author: String,
pub initials: String,
pub date: String,
pub position_emu: (i64, i64),
pub text: String,
}
impl SlideComment {
pub fn new(
author: impl Into<String>,
initials: impl Into<String>,
date: impl Into<String>,
text: impl Into<String>,
) -> Self {
Self {
author: author.into(),
initials: initials.into(),
date: date.into(),
position_emu: (0, 0),
text: text.into(),
}
}
pub fn with_position(mut self, x_emu: i64, y_emu: i64) -> Self {
self.position_emu = (x_emu, y_emu);
self
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Theme {
pub name: String,
pub colors: ColorScheme,
pub fonts: FontScheme,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ColorScheme {
pub dark1: String,
pub light1: String,
pub dark2: String,
pub light2: String,
pub accent1: String,
pub accent2: String,
pub accent3: String,
pub accent4: String,
pub accent5: String,
pub accent6: String,
pub hyperlink: String,
pub followed_hyperlink: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FontScheme {
pub major_latin: String,
pub minor_latin: String,
}
impl Theme {
pub fn office_default() -> Self {
Self {
name: "Office".to_string(),
colors: ColorScheme::office_default(),
fonts: FontScheme::office_default(),
}
}
}
impl ColorScheme {
pub fn office_default() -> Self {
Self {
dark1: "000000".to_string(),
light1: "FFFFFF".to_string(),
dark2: "44546A".to_string(),
light2: "E7E6E6".to_string(),
accent1: "4472C4".to_string(),
accent2: "ED7D31".to_string(),
accent3: "A5A5A5".to_string(),
accent4: "FFC000".to_string(),
accent5: "5B9BD5".to_string(),
accent6: "70AD47".to_string(),
hyperlink: "0563C1".to_string(),
followed_hyperlink: "954F72".to_string(),
}
}
}
impl FontScheme {
pub fn office_default() -> Self {
Self {
major_latin: "Calibri Light".to_string(),
minor_latin: "Calibri".to_string(),
}
}
}
#[derive(Debug, Default, Clone, PartialEq)]
pub struct DocumentProperties {
pub title: Option<String>,
pub author: Option<String>,
pub subject: Option<String>,
pub keywords: Option<String>,
pub company: Option<String>,
pub manager: Option<String>,
pub hyperlink_base: Option<String>,
pub custom_properties: Vec<(String, CustomPropertyValue)>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum CustomPropertyValue {
Text(String),
Bool(bool),
Int(i32),
Number(f64),
}
impl DocumentProperties {
pub fn new() -> Self {
Self::default()
}
pub fn with_title(mut self, title: impl Into<String>) -> Self {
self.title = Some(title.into());
self
}
pub fn with_author(mut self, author: impl Into<String>) -> Self {
self.author = Some(author.into());
self
}
pub fn with_subject(mut self, subject: impl Into<String>) -> Self {
self.subject = Some(subject.into());
self
}
pub fn with_keywords(mut self, keywords: impl Into<String>) -> Self {
self.keywords = Some(keywords.into());
self
}
pub fn with_company(mut self, company: impl Into<String>) -> Self {
self.company = Some(company.into());
self
}
pub fn with_manager(mut self, manager: impl Into<String>) -> Self {
self.manager = Some(manager.into());
self
}
pub fn with_hyperlink_base(mut self, hyperlink_base: impl Into<String>) -> Self {
self.hyperlink_base = Some(hyperlink_base.into());
self
}
pub fn with_custom_property(
mut self,
name: impl Into<String>,
value: CustomPropertyValue,
) -> Self {
self.custom_properties.push((name.into(), value));
self
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct SlideTableStyle {
pub id: String,
pub name: String,
pub whole_table: Option<TableStylePart>,
pub band1_horizontal: Option<TableStylePart>,
pub band2_horizontal: Option<TableStylePart>,
pub band1_vertical: Option<TableStylePart>,
pub band2_vertical: Option<TableStylePart>,
pub first_row: Option<TableStylePart>,
pub last_row: Option<TableStylePart>,
pub first_column: Option<TableStylePart>,
pub last_column: Option<TableStylePart>,
}
impl SlideTableStyle {
pub fn new(id: impl Into<String>, name: impl Into<String>) -> Self {
Self {
id: id.into(),
name: name.into(),
..Default::default()
}
}
pub fn with_whole_table(mut self, part: TableStylePart) -> Self {
self.whole_table = Some(part);
self
}
pub fn with_band1_horizontal(mut self, part: TableStylePart) -> Self {
self.band1_horizontal = Some(part);
self
}
pub fn with_band2_horizontal(mut self, part: TableStylePart) -> Self {
self.band2_horizontal = Some(part);
self
}
pub fn with_band1_vertical(mut self, part: TableStylePart) -> Self {
self.band1_vertical = Some(part);
self
}
pub fn with_band2_vertical(mut self, part: TableStylePart) -> Self {
self.band2_vertical = Some(part);
self
}
pub fn with_first_row(mut self, part: TableStylePart) -> Self {
self.first_row = Some(part);
self
}
pub fn with_last_row(mut self, part: TableStylePart) -> Self {
self.last_row = Some(part);
self
}
pub fn with_first_column(mut self, part: TableStylePart) -> Self {
self.first_column = Some(part);
self
}
pub fn with_last_column(mut self, part: TableStylePart) -> Self {
self.last_column = Some(part);
self
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct TableStylePart {
pub fill: Option<Fill>,
pub bold: bool,
pub italic: bool,
pub text_color: Option<Color>,
}
impl TableStylePart {
pub fn new() -> Self {
Self::default()
}
pub fn with_fill(mut self, fill: Fill) -> Self {
self.fill = Some(fill);
self
}
pub fn with_bold(mut self, bold: bool) -> Self {
self.bold = bold;
self
}
pub fn with_italic(mut self, italic: bool) -> Self {
self.italic = italic;
self
}
pub fn with_text_color(mut self, color: Color) -> Self {
self.text_color = Some(color);
self
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct EmbeddedFont {
pub typeface: String,
pub regular: Option<Vec<u8>>,
pub bold: Option<Vec<u8>>,
pub italic: Option<Vec<u8>>,
pub bold_italic: Option<Vec<u8>>,
}
impl EmbeddedFont {
pub fn new(typeface: impl Into<String>) -> Self {
Self {
typeface: typeface.into(),
..Default::default()
}
}
pub fn with_regular(mut self, data: impl Into<Vec<u8>>) -> Self {
self.regular = Some(data.into());
self
}
pub fn with_bold(mut self, data: impl Into<Vec<u8>>) -> Self {
self.bold = Some(data.into());
self
}
pub fn with_italic(mut self, data: impl Into<Vec<u8>>) -> Self {
self.italic = Some(data.into());
self
}
pub fn with_bold_italic(mut self, data: impl Into<Vec<u8>>) -> Self {
self.bold_italic = Some(data.into());
self
}
}