easyofd_core/text/
ct_cg_transform.rs1#[allow(non_camel_case_types)]
9#[derive(Debug, Clone)]
10pub struct CT_CGTransform {
11 pub code_position: Option<u32>,
13 pub code_count: Option<u32>,
15 pub glyph_count: Option<u32>,
17 pub glyphs: Vec<u32>,
19}
20
21impl CT_CGTransform {
22 #[must_use]
24 pub fn new() -> Self {
25 Self {
26 code_position: None,
27 code_count: None,
28 glyph_count: None,
29 glyphs: Vec::new(),
30 }
31 }
32
33 #[must_use]
35 pub fn code_position(mut self, pos: u32) -> Self {
36 self.code_position = Some(pos);
37 self
38 }
39
40 #[must_use]
42 pub fn code_count(mut self, count: u32) -> Self {
43 self.code_count = Some(count);
44 self
45 }
46
47 #[must_use]
49 pub fn glyph_count(mut self, count: u32) -> Self {
50 self.glyph_count = Some(count);
51 self
52 }
53
54 #[must_use]
56 pub fn glyphs(mut self, glyphs: Vec<u32>) -> Self {
57 self.glyphs = glyphs;
58 self
59 }
60
61 pub fn add_glyph(&mut self, glyph: u32) {
63 self.glyphs.push(glyph);
64 }
65
66 #[must_use]
68 pub fn get_code_position(&self) -> Option<u32> {
69 self.code_position
70 }
71
72 #[must_use]
74 pub fn get_code_count(&self) -> Option<u32> {
75 self.code_count
76 }
77
78 #[must_use]
80 pub fn get_glyph_count(&self) -> Option<u32> {
81 self.glyph_count
82 }
83
84 #[must_use]
86 pub fn get_glyphs(&self) -> &[u32] {
87 &self.glyphs
88 }
89
90 #[must_use]
92 pub fn to_xml_string(&self) -> String {
93 use std::fmt::Write;
94 let mut xml = String::from("<ofd:CGTransform");
95 if let Some(cp) = self.code_position {
96 write!(xml, " CodePosition=\"{cp}\"").expect("写入内存缓冲区不会失败");
97 }
98 if let Some(cc) = self.code_count {
99 write!(xml, " CodeCount=\"{cc}\"").expect("写入内存缓冲区不会失败");
100 }
101 if let Some(gc) = self.glyph_count {
102 write!(xml, " GlyphCount=\"{gc}\"").expect("写入内存缓冲区不会失败");
103 }
104 if !self.glyphs.is_empty() {
105 xml.push_str(" Glyphs=\"");
106 for (i, g) in self.glyphs.iter().enumerate() {
107 if i > 0 {
108 xml.push(' ');
109 }
110 write!(xml, "{g}").expect("写入内存缓冲区不会失败");
111 }
112 xml.push('"');
113 }
114 xml.push_str(" />");
115 xml
116 }
117}
118
119impl Default for CT_CGTransform {
120 fn default() -> Self {
121 Self::new()
122 }
123}
124
125#[cfg(test)]
126mod tests {
127 use super::*;
128
129 #[test]
130 fn test_ct_cg_transform_new() {
131 let t = CT_CGTransform::new();
132 assert!(t.code_position.is_none());
133 assert!(t.code_count.is_none());
134 assert!(t.glyph_count.is_none());
135 assert!(t.glyphs.is_empty());
136 }
137
138 #[test]
139 fn test_ct_cg_transform_builder() {
140 let t = CT_CGTransform::new()
141 .code_position(0)
142 .code_count(2)
143 .glyph_count(2)
144 .glyphs(vec![100, 200]);
145 assert_eq!(t.get_code_position(), Some(0));
146 assert_eq!(t.get_code_count(), Some(2));
147 assert_eq!(t.get_glyph_count(), Some(2));
148 assert_eq!(t.get_glyphs(), &[100, 200]);
149 }
150
151 #[test]
152 fn test_ct_cg_transform_add_glyph() {
153 let mut t = CT_CGTransform::new();
154 t.add_glyph(50);
155 t.add_glyph(60);
156 t.add_glyph(70);
157 assert_eq!(t.get_glyphs().len(), 3);
158 }
159
160 #[test]
161 fn test_ct_cg_transform_to_xml_minimal() {
162 let t = CT_CGTransform::new();
163 let xml = t.to_xml_string();
164 assert!(xml.contains("<ofd:CGTransform"));
165 assert!(xml.ends_with(" />"));
166 }
167
168 #[test]
169 fn test_ct_cg_transform_to_xml_full() {
170 let t = CT_CGTransform::new()
171 .code_position(3)
172 .code_count(1)
173 .glyph_count(2)
174 .glyphs(vec![101, 202]);
175 let xml = t.to_xml_string();
176 assert!(xml.contains("CodePosition=\"3\""));
177 assert!(xml.contains("CodeCount=\"1\""));
178 assert!(xml.contains("GlyphCount=\"2\""));
179 assert!(xml.contains("Glyphs=\"101 202\""));
180 }
181
182 #[test]
183 fn test_ct_cg_transform_clone_debug() {
184 let t = CT_CGTransform::new().code_position(1);
185 let t2 = t.clone();
186 assert_eq!(t2.get_code_position(), Some(1));
187 assert!(format!("{t:?}").contains("CT_CGTransform"));
188 }
189}