1use crate::line::CTLine;
11use core_foundation::array::{CFArray, CFArrayRef};
12use core_foundation::base::{CFRange, CFTypeID, TCFType};
13use core_foundation::{declare_TCFType, impl_CFTypeDescription, impl_TCFType};
14use core_graphics::context::{CGContext, CGContextRef};
15use core_graphics::geometry::CGPoint;
16use core_graphics::path::{CGPath, SysCGPathRef};
17use foreign_types::{ForeignType, ForeignTypeRef};
18
19#[repr(C)]
20pub struct __CTFrame(core::ffi::c_void);
21
22pub type CTFrameRef = *const __CTFrame;
23
24declare_TCFType! {
25 CTFrame, CTFrameRef
26}
27impl_TCFType!(CTFrame, CTFrameRef, CTFrameGetTypeID);
28impl_CFTypeDescription!(CTFrame);
29
30impl CTFrame {
31 pub fn get_path(&self) -> CGPath {
33 unsafe { CGPath::from_ptr(CTFrameGetPath(self.as_concrete_TypeRef())).clone() }
34 }
35
36 pub fn get_lines(&self) -> Vec<CTLine> {
40 unsafe {
41 let array_ref = CTFrameGetLines(self.as_concrete_TypeRef());
42 let array: CFArray<CTLine> = CFArray::wrap_under_get_rule(array_ref);
43 array
44 .iter()
45 .map(|l| CTLine::wrap_under_get_rule(l.as_concrete_TypeRef()))
46 .collect()
47 }
48 }
49
50 pub fn get_line_origins(&self, range: impl Into<Option<CFRange>>) -> Vec<CGPoint> {
62 let range = range.into().unwrap_or_else(|| CFRange::init(0, 0));
63 let len = match range.length {
64 0 => unsafe {
66 let array_ref = CTFrameGetLines(self.as_concrete_TypeRef());
67 let array: CFArray<CTLine> = CFArray::wrap_under_get_rule(array_ref);
68 array.len() - range.location
69 },
70 n => n,
71 };
72 let len = len.max(0) as usize;
73 let mut out = vec![CGPoint::new(0., 0.); len];
74 unsafe {
75 CTFrameGetLineOrigins(self.as_concrete_TypeRef(), range, out.as_mut_ptr());
76 }
77 out
78 }
79
80 pub fn draw(&self, context: &CGContextRef) {
81 unsafe {
82 CTFrameDraw(self.as_concrete_TypeRef(), context.as_ptr());
83 }
84 }
85}
86
87#[cfg_attr(feature = "link", link(name = "CoreText", kind = "framework"))]
88extern "C" {
89 fn CTFrameGetTypeID() -> CFTypeID;
90 fn CTFrameGetLines(frame: CTFrameRef) -> CFArrayRef;
91 fn CTFrameDraw(frame: CTFrameRef, context: *mut <CGContext as ForeignType>::CType);
92 fn CTFrameGetLineOrigins(frame: CTFrameRef, range: CFRange, origins: *mut CGPoint);
93 fn CTFrameGetPath(frame: CTFrameRef) -> SysCGPathRef;
94}