use crate::{CjkFontOrdering, Error, Matrix, Point, SimpleFontEncoding, WriteMode};
#[derive(Clone, Debug, PartialEq)]
pub enum PdfColor {
Gray(f32),
Rgb([f32; 3]),
Cmyk([f32; 4]),
}
impl PdfColor {
pub fn gray(gray: f32) -> Self {
Self::Gray(gray)
}
pub fn rgb(red: f32, green: f32, blue: f32) -> Self {
Self::Rgb([red, green, blue])
}
pub fn cmyk(cyan: f32, magenta: f32, yellow: f32, key: f32) -> Self {
Self::Cmyk([cyan, magenta, yellow, key])
}
pub(crate) fn components(&self) -> &[f32] {
match self {
Self::Gray(components) => std::slice::from_ref(components),
Self::Rgb(components) => components,
Self::Cmyk(components) => components,
}
}
pub(crate) fn validate(&self) -> Result<(), Error> {
if self
.components()
.iter()
.all(|component| component.is_finite() && (0.0..=1.0).contains(component))
{
return Ok(());
}
Err(Error::InvalidArgument(
"color components must be finite values in the 0..=1 range".to_owned(),
))
}
}
impl From<[f32; 1]> for PdfColor {
fn from(value: [f32; 1]) -> Self {
Self::Gray(value[0])
}
}
impl From<[f32; 3]> for PdfColor {
fn from(value: [f32; 3]) -> Self {
Self::Rgb(value)
}
}
impl From<[f32; 4]> for PdfColor {
fn from(value: [f32; 4]) -> Self {
Self::Cmyk(value)
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct FinishOptions {
pub color: Option<PdfColor>,
pub fill: Option<PdfColor>,
pub width: f32,
pub line_cap: Option<i32>,
pub line_join: Option<i32>,
pub miter_limit: Option<f32>,
pub dashes: Option<String>,
pub even_odd: bool,
pub close_path: bool,
pub morph: Option<(Point, Matrix)>,
pub stroke_opacity: Option<f32>,
pub fill_opacity: Option<f32>,
pub oc: Option<i32>,
}
impl Default for FinishOptions {
fn default() -> Self {
Self {
color: Some(PdfColor::Rgb([0.0, 0.0, 0.0])),
fill: None,
width: 1.0,
line_cap: None,
line_join: None,
miter_limit: None,
dashes: None,
even_odd: false,
close_path: true,
morph: None,
stroke_opacity: None,
fill_opacity: None,
oc: None,
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct TextOptions<'a> {
pub fontsize: f32,
pub lineheight: f32,
pub fontname: String,
pub fontfile: Option<&'a [u8]>,
pub color: Option<PdfColor>,
pub fill: Option<PdfColor>,
pub render_mode: i32,
pub border_width: f32,
pub miter_limit: Option<f32>,
pub rotate: i32,
pub simple: bool,
pub encoding: SimpleFontEncoding,
pub ordering: Option<CjkFontOrdering>,
pub wmode: WriteMode,
pub serif: bool,
pub stroke_opacity: Option<f32>,
pub fill_opacity: Option<f32>,
pub oc: Option<i32>,
}
impl Default for TextOptions<'_> {
fn default() -> Self {
Self {
fontsize: 11.0,
lineheight: 1.2,
fontname: "helv".to_owned(),
fontfile: None,
color: None,
fill: None,
render_mode: 0,
border_width: 0.05,
miter_limit: Some(1.0),
rotate: 0,
simple: true,
encoding: SimpleFontEncoding::Latin,
ordering: None,
wmode: WriteMode::Horizontal,
serif: false,
stroke_opacity: None,
fill_opacity: None,
oc: None,
}
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum TextAlign {
#[default]
Left,
Center,
Right,
Justify,
}
#[derive(Clone, Debug, PartialEq)]
pub struct TextboxOptions<'a> {
pub fontsize: f32,
pub lineheight: f32,
pub fontname: String,
pub fontfile: Option<&'a [u8]>,
pub color: Option<PdfColor>,
pub fill: Option<PdfColor>,
pub render_mode: i32,
pub border_width: f32,
pub miter_limit: Option<f32>,
pub rotate: i32,
pub simple: bool,
pub encoding: SimpleFontEncoding,
pub ordering: Option<CjkFontOrdering>,
pub wmode: WriteMode,
pub serif: bool,
pub stroke_opacity: Option<f32>,
pub fill_opacity: Option<f32>,
pub oc: Option<i32>,
pub align: TextAlign,
}
impl Default for TextboxOptions<'_> {
fn default() -> Self {
Self {
fontsize: 11.0,
lineheight: 1.2,
fontname: "helv".to_owned(),
fontfile: None,
color: None,
fill: None,
render_mode: 0,
border_width: 0.05,
miter_limit: Some(1.0),
rotate: 0,
simple: true,
encoding: SimpleFontEncoding::Latin,
ordering: None,
wmode: WriteMode::Horizontal,
serif: false,
stroke_opacity: None,
fill_opacity: None,
oc: None,
align: TextAlign::Left,
}
}
}
impl<'a> From<TextOptions<'a>> for TextboxOptions<'a> {
fn from(value: TextOptions<'a>) -> Self {
Self {
fontsize: value.fontsize,
lineheight: value.lineheight,
fontname: value.fontname,
fontfile: value.fontfile,
color: value.color,
fill: value.fill,
render_mode: value.render_mode,
border_width: value.border_width,
miter_limit: value.miter_limit,
rotate: value.rotate,
simple: value.simple,
encoding: value.encoding,
ordering: value.ordering,
wmode: value.wmode,
serif: value.serif,
stroke_opacity: value.stroke_opacity,
fill_opacity: value.fill_opacity,
oc: value.oc,
align: TextAlign::Left,
}
}
}