add font stretch (#813)

Co-authored-by: 张德新 <zhangdexin@sinosoft.com.cn>
main
shenhunluo 2025-05-02 20:32:58 +08:00 committed by GitHub
parent d95137cb9f
commit 50e6eddb08
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 86 additions and 0 deletions

View File

@ -94,6 +94,7 @@ mod shading;
mod shape; mod shape;
mod spec_vanish; mod spec_vanish;
mod start; mod start;
mod stretch;
mod strike; mod strike;
mod structured_data_tag; mod structured_data_tag;
mod structured_data_tag_property; mod structured_data_tag_property;
@ -232,6 +233,7 @@ pub use shading::*;
pub use shape::*; pub use shape::*;
pub use spec_vanish::*; pub use spec_vanish::*;
pub use start::*; pub use start::*;
pub use stretch::*;
pub use strike::*; pub use strike::*;
pub use structured_data_tag::*; pub use structured_data_tag::*;
pub use structured_data_tag_property::*; pub use structured_data_tag_property::*;

View File

@ -263,6 +263,11 @@ impl Run {
self self
} }
pub fn stretch(mut self, v: i32) -> Run {
self.run_property = self.run_property.stretch(v);
self
}
pub fn color(mut self, color: impl Into<String>) -> Run { pub fn color(mut self, color: impl Into<String>) -> Run {
self.run_property = self.run_property.color(color); self.run_property = self.run_property.color(color);
self self

View File

@ -40,6 +40,8 @@ pub struct RunProperty {
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub character_spacing: Option<CharacterSpacing>, pub character_spacing: Option<CharacterSpacing>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub stretch: Option<Stretch>,
#[serde(skip_serializing_if = "Option::is_none")]
pub fonts: Option<RunFonts>, pub fonts: Option<RunFonts>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub text_border: Option<TextBorder>, pub text_border: Option<TextBorder>,
@ -169,6 +171,11 @@ impl RunProperty {
self self
} }
pub fn stretch(mut self, v: i32) -> RunProperty {
self.stretch = Some(Stretch::new(v));
self
}
pub fn text_border(mut self, b: TextBorder) -> Self { pub fn text_border(mut self, b: TextBorder) -> Self {
self.text_border = Some(b); self.text_border = Some(b);
self self
@ -222,6 +229,7 @@ impl BuildXML for RunProperty {
.add_optional_child(&self.del)? .add_optional_child(&self.del)?
.add_optional_child(&self.vert_align)? .add_optional_child(&self.vert_align)?
.add_optional_child(&self.character_spacing)? .add_optional_child(&self.character_spacing)?
.add_optional_child(&self.stretch)?
.add_optional_child(&self.style)? .add_optional_child(&self.style)?
.add_optional_child(&self.positional_tab)? .add_optional_child(&self.positional_tab)?
.add_optional_child(&self.shading)? .add_optional_child(&self.shading)?
@ -318,6 +326,16 @@ mod tests {
); );
} }
#[test]
fn test_stretch() {
let c = RunProperty::new().stretch(80);
let b = c.build();
assert_eq!(
str::from_utf8(&b).unwrap(),
r#"<w:rPr><w:w w:val="80" /></w:rPr>"#
);
}
#[test] #[test]
fn test_ptab() { fn test_ptab() {
let c = RunProperty::new().ptab(PositionalTab::new( let c = RunProperty::new().ptab(PositionalTab::new(

View File

@ -0,0 +1,55 @@
use crate::documents::BuildXML;
use crate::xml_builder::*;
use std::io::Write;
use serde::*;
#[derive(Debug, Clone, Deserialize, PartialEq)]
pub struct Stretch {
value: i32,
}
impl Stretch {
pub fn new(s: i32) -> Stretch {
Self { value: s }
}
}
impl BuildXML for Stretch {
fn build_to<W: Write>(
&self,
stream: xml::writer::EventWriter<W>,
) -> xml::writer::Result<xml::writer::EventWriter<W>> {
XMLBuilder::from(stream).w(self.value)?.into_inner()
}
}
impl Serialize for Stretch {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_i32(self.value)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(test)]
use pretty_assertions::assert_eq;
use std::str;
#[test]
fn test_stretch() {
let b = Stretch::new(200).build();
assert_eq!(str::from_utf8(&b).unwrap(), r#"<w:w w:val="200" />"#);
}
#[test]
fn test_stretch_json() {
let s = Stretch { value: 100 };
assert_eq!(serde_json::to_string(&s).unwrap(), r#"100"#);
}
}

View File

@ -278,6 +278,12 @@ impl<W: Write> XMLBuilder<W> {
.close() .close()
} }
// i.e. <w:w ... >
pub(crate) fn w(self, s: i32) -> Result<Self> {
self.write(XmlEvent::start_element("w:w").attr("w:val", &format!("{}", s)))?
.close()
}
// i.e. <w:spacing ... > // i.e. <w:spacing ... >
pub(crate) fn line_spacing( pub(crate) fn line_spacing(
self, self,