Skip to main content

easyofd_reader/keyword/
keyword_position.rs

1//! 关键字位置。
2//!
3//! 对应 Java: org.ofdrw.reader.keyword.KeywordPosition
4
5use easyofd_core::ST_Box;
6
7/// 关键字位置,描述关键字在 OFD 文档中的定位信息。
8///
9/// 对应 Java: `org.ofdrw.reader.keyword.KeywordPosition`
10#[derive(Debug, Clone)]
11pub struct KeywordPosition {
12    /// 关键字所在页码(从 1 开始)。
13    pub page: usize,
14    /// 关键字在页面中的矩形区域(毫米)。
15    pub rect: ST_Box,
16    /// 所属关键字文本。
17    pub keyword: Option<String>,
18}
19
20impl KeywordPosition {
21    /// 创建新的关键字位置。
22    #[must_use]
23    pub fn new(page: usize, rect: ST_Box) -> Self {
24        Self {
25            page,
26            rect,
27            keyword: None,
28        }
29    }
30
31    /// 设置所属关键字。
32    #[must_use]
33    pub fn with_keyword(mut self, keyword: impl Into<String>) -> Self {
34        self.keyword = Some(keyword.into());
35        self
36    }
37
38    /// 获取矩形区域左上角 X 坐标。
39    #[must_use]
40    pub fn x(&self) -> f64 {
41        self.rect.top_left_x
42    }
43
44    /// 获取矩形区域左上角 Y 坐标。
45    #[must_use]
46    pub fn y(&self) -> f64 {
47        self.rect.top_left_y
48    }
49
50    /// 获取矩形区域宽度。
51    #[must_use]
52    pub fn width(&self) -> f64 {
53        self.rect.width
54    }
55
56    /// 获取矩形区域高度。
57    #[must_use]
58    pub fn height(&self) -> f64 {
59        self.rect.height
60    }
61}
62
63impl std::fmt::Display for KeywordPosition {
64    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65        write!(
66            f,
67            "KeywordPosition{{page={}, rect=({}, {}, {}, {}), keyword={}}}",
68            self.page,
69            self.rect.top_left_x,
70            self.rect.top_left_y,
71            self.rect.width,
72            self.rect.height,
73            self.keyword.as_deref().unwrap_or("")
74        )
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use super::*;
81
82    #[test]
83    fn test_keyword_position_new() {
84        let rect = ST_Box::new(10.0, 20.0, 50.0, 12.0);
85        let pos = KeywordPosition::new(1, rect);
86        assert_eq!(pos.page, 1);
87        assert!((pos.x() - 10.0).abs() < f64::EPSILON);
88        assert!((pos.y() - 20.0).abs() < f64::EPSILON);
89        assert!((pos.width() - 50.0).abs() < f64::EPSILON);
90        assert!((pos.height() - 12.0).abs() < f64::EPSILON);
91        assert!(pos.keyword.is_none());
92    }
93
94    #[test]
95    fn test_keyword_position_with_keyword() {
96        let rect = ST_Box::new(0.0, 0.0, 100.0, 20.0);
97        let pos = KeywordPosition::new(3, rect).with_keyword("OFD");
98        assert_eq!(pos.keyword.as_deref(), Some("OFD"));
99    }
100
101    #[test]
102    fn test_keyword_position_display() {
103        let rect = ST_Box::new(10.0, 20.0, 50.0, 12.0);
104        let pos = KeywordPosition::new(1, rect).with_keyword("test");
105        let s = format!("{pos}");
106        assert!(s.contains("page=1"));
107        assert!(s.contains("test"));
108    }
109}