appcore_filemaker/
source_text.rs1use serde::{Deserialize, Serialize};
12
13use crate::{
14 Alignment, ErrorCode, FileMakerError, Length, Result, TextIr, TextOverflow, Unit, WritingMode,
15};
16
17#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
19#[serde(default, deny_unknown_fields)]
20pub struct TextSourceOptions {
21 pub overflow: TextOverflow,
23 pub max_lines: Option<usize>,
25 pub min_font_size: Option<Length>,
27 pub line_height: u32,
29 pub writing_mode: WritingMode,
31 pub align_x: Alignment,
33 pub padding_inline: Length,
35 pub padding: crate::TextBlockPadding,
37}
38
39impl Default for TextSourceOptions {
40 fn default() -> Self {
41 Self {
42 overflow: TextOverflow::Wrap,
43 max_lines: None,
44 min_font_size: Some(Length::Absolute(Unit::from_raw(6_000_000))),
45 line_height: 1_200_000,
46 writing_mode: WritingMode::Horizontal,
47 align_x: Alignment::Start,
48 padding_inline: Length::Absolute(Unit::ZERO),
49 padding: crate::TextBlockPadding::default(),
50 }
51 }
52}
53
54pub(crate) fn validate_text_options(options: &TextSourceOptions) -> Result<()> {
55 let minimum = options
56 .min_font_size
57 .map(|value| value.resolve(Unit::ZERO, Unit::ZERO))
58 .transpose()?
59 .flatten();
60 let invalid_padding = match options.padding_inline {
61 Length::Absolute(value) => value < Unit::ZERO,
62 Length::Logical(value) => value < 0,
63 Length::Percent(value) => !(0..500_000).contains(&value),
64 Length::Auto => true,
65 };
66 let block_padding = [
67 options.padding.top,
68 options.padding.right,
69 options.padding.bottom,
70 options.padding.left,
71 ];
72 let invalid_block_padding = block_padding.iter().any(|value| match value {
73 Length::Absolute(unit) => *unit < Unit::ZERO,
74 Length::Logical(units) => *units < 0,
75 Length::Percent(units) => !(0..500_000).contains(units),
76 Length::Auto => true,
77 });
78 if options.max_lines == Some(0)
79 || !(500_000..=4_000_000).contains(&options.line_height)
80 || minimum.is_some_and(|value| value <= Unit::ZERO)
81 || options
82 .min_font_size
83 .is_some_and(|value| !matches!(value, Length::Absolute(_)))
84 || invalid_padding
85 || invalid_block_padding
86 {
87 return Err(FileMakerError::new(
88 ErrorCode::SchemaField,
89 "text options contain an invalid line, font, or inline-padding constraint",
90 ));
91 }
92 Ok(())
93}
94
95pub(crate) fn convert_text_options(options: TextSourceOptions) -> TextIr {
96 TextIr {
97 overflow: options.overflow,
98 max_lines: options.max_lines,
99 min_font_size: options.min_font_size,
100 line_height: options.line_height,
101 writing_mode: options.writing_mode,
102 align_x: options.align_x,
103 padding_inline: options.padding_inline,
104 padding: options.padding,
105 }
106}