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