Skip to main content

path_kit/
rrect.rs

1//! 圆角矩形,支持四角独立半径。
2//! Rounded rectangle with per-corner radii.
3
4use crate::bridge::ffi;
5use crate::rect::Rect;
6use crate::RectCorner;
7
8/// 圆角矩形,支持四角独立半径。
9/// Rounded rectangle with per-corner radii (each corner can have different x/y).
10pub struct RRect {
11    inner: ffi::RRect,
12}
13
14/// 单角椭圆半径 (x, y),与 `SkRRect` 每角 radii 一致。
15/// Per-corner elliptical radii (x, y), matching `SkRRect` corner radii.
16#[derive(Debug, Clone, Copy, PartialEq)]
17pub struct Radii {
18    /// 该角 x 方向半径 / X-axis corner radius
19    pub x: f32,
20    /// 该角 y 方向半径 / Y-axis corner radius
21    pub y: f32,
22}
23
24impl RRect {
25    /// 创建空圆角矩形。Creates an empty RRect.
26    pub fn new() -> Self {
27        let mut inner = ffi::RRect {
28            fRect: ffi::Rect {
29                fLeft: 0.0,
30                fTop: 0.0,
31                fRight: 0.0,
32                fBottom: 0.0,
33            },
34            fRadii: [ffi::Point { fX: 0.0, fY: 0.0 }; 4],
35            fType: ffi::RRectType::Empty,
36        };
37        ffi::rrect_new_empty(&mut inner);
38        Self { inner }
39    }
40
41    /// 从矩形创建(直角)。Creates RRect from rect (sharp corners).
42    pub fn from_rect(rect: &Rect) -> Self {
43        let mut rr = Self::new();
44        let r: ffi::Rect = (*rect).into();
45        ffi::rrect_set_rect_xy(&mut rr.inner, &r, 0.0, 0.0);
46        rr
47    }
48
49    /// 从椭圆边界创建。Creates oval (ellipse) bounded by rect.
50    pub fn from_oval(rect: &Rect) -> Self {
51        let mut rr = Self::new();
52        let r: ffi::Rect = (*rect).into();
53        ffi::rrect_set_oval(&mut rr.inner, &r);
54        rr
55    }
56
57    /// 从矩形与统一圆角创建。Creates rounded rect with uniform radii.
58    pub fn from_rect_xy(rect: &Rect, rx: f32, ry: f32) -> Self {
59        let mut rr = Self::new();
60        let r: ffi::Rect = (*rect).into();
61        ffi::rrect_set_rect_xy(&mut rr.inner, &r, rx, ry);
62        rr
63    }
64
65    /// 从矩形与四角半径创建。Creates RRect with per-corner radii.
66    ///
67    /// `radii` 顺序:UpperLeft, UpperRight, LowerRight, LowerLeft。
68    /// Radii order: UpperLeft, UpperRight, LowerRight, LowerLeft.
69    pub fn from_rect_radii(rect: &Rect, radii: &[Radii; 4]) -> Self {
70        let mut rr = Self::new();
71        let r: ffi::Rect = (*rect).into();
72        let pts: [ffi::Point; 4] = [
73            ffi::Point {
74                fX: radii[0].x,
75                fY: radii[0].y,
76            },
77            ffi::Point {
78                fX: radii[1].x,
79                fY: radii[1].y,
80            },
81            ffi::Point {
82                fX: radii[2].x,
83                fY: radii[2].y,
84            },
85            ffi::Point {
86                fX: radii[3].x,
87                fY: radii[3].y,
88            },
89        ];
90        ffi::rrect_set_rect_radii(&mut rr.inner, &r, &pts);
91        rr
92    }
93
94    /// 边界矩形。Returns the bounding rect.
95    pub fn rect(&self) -> Rect {
96        self.inner.fRect.into()
97    }
98
99    /// 宽度。Returns width.
100    pub fn width(&self) -> f32 {
101        self.inner.fRect.fRight - self.inner.fRect.fLeft
102    }
103
104    /// 高度。Returns height.
105    pub fn height(&self) -> f32 {
106        self.inner.fRect.fBottom - self.inner.fRect.fTop
107    }
108
109    /// 是否为空。Returns true if empty.
110    pub fn is_empty(&self) -> bool {
111        self.inner.fType == ffi::RRectType::Empty
112    }
113
114    /// 是否为普通矩形。Returns true if sharp corners (no rounding).
115    pub fn is_rect(&self) -> bool {
116        self.inner.fType == ffi::RRectType::Rect
117    }
118
119    /// 是否为椭圆。Returns true if oval.
120    pub fn is_oval(&self) -> bool {
121        self.inner.fType == ffi::RRectType::Oval
122    }
123
124    /// 是否所有角半径相同。Returns true if uniform radii (simple type).
125    pub fn is_simple(&self) -> bool {
126        self.inner.fType == ffi::RRectType::Simple
127    }
128
129    /// 获取某角半径。Returns radii for corner (UpperLeft, UpperRight, LowerRight, LowerLeft).
130    pub fn radii(&self, corner: RectCorner) -> Radii {
131        let idx = match corner {
132            RectCorner::UpperLeft => 0usize,
133            RectCorner::UpperRight => 1,
134            RectCorner::LowerRight => 2,
135            RectCorner::LowerLeft => 3,
136            _ => 0,
137        };
138        Radii {
139            x: self.inner.fRadii[idx].fX,
140            y: self.inner.fRadii[idx].fY,
141        }
142    }
143
144    /// 数据是否有效。Returns true if valid.
145    pub fn is_valid(&self) -> bool {
146        ffi::rrect_is_valid(&self.inner)
147    }
148
149    /// 从 cxx 桥接结构创建(仅 crate 内使用)。Internal use only.
150    pub(crate) fn from_ffi(inner: ffi::RRect) -> Self {
151        Self { inner }
152    }
153
154    /// 内部 FFI 副本(仅 crate 内使用)。Internal use only.
155    pub(crate) fn as_ffi(&self) -> ffi::RRect {
156        self.inner
157    }
158}
159
160impl Default for RRect {
161    fn default() -> Self {
162        Self::new()
163    }
164}
165
166impl Clone for RRect {
167    fn clone(&self) -> Self {
168        Self { inner: self.inner }
169    }
170}