core_text/
line.rs

1// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution.
3//
4// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7// option. This file may not be copied, modified, or distributed
8// except according to those terms.
9
10use crate::run::CTRun;
11use core_foundation::array::{CFArray, CFArrayRef};
12use core_foundation::attributed_string::CFAttributedStringRef;
13use core_foundation::base::{CFIndex, CFRange, CFTypeID, TCFType};
14use core_foundation::{declare_TCFType, impl_CFTypeDescription, impl_TCFType};
15use core_graphics::base::CGFloat;
16use core_graphics::context::CGContext;
17use core_graphics::geometry::{CGPoint, CGRect};
18use foreign_types::ForeignType;
19
20#[repr(C)]
21pub struct __CTLine(core::ffi::c_void);
22
23pub type CTLineRef = *const __CTLine;
24
25declare_TCFType! {
26    CTLine, CTLineRef
27}
28impl_TCFType!(CTLine, CTLineRef, CTLineGetTypeID);
29impl_CFTypeDescription!(CTLine);
30
31/// Metrics for a given line.
32pub struct TypographicBounds {
33    pub width: CGFloat,
34    pub ascent: CGFloat,
35    pub descent: CGFloat,
36    pub leading: CGFloat,
37}
38
39impl CTLine {
40    pub fn new_with_attributed_string(string: CFAttributedStringRef) -> Self {
41        unsafe {
42            let ptr = CTLineCreateWithAttributedString(string);
43            CTLine::wrap_under_create_rule(ptr)
44        }
45    }
46
47    pub fn glyph_runs(&self) -> CFArray<CTRun> {
48        unsafe { TCFType::wrap_under_get_rule(CTLineGetGlyphRuns(self.0)) }
49    }
50
51    pub fn get_string_range(&self) -> CFRange {
52        unsafe { CTLineGetStringRange(self.as_concrete_TypeRef()) }
53    }
54
55    pub fn draw(&self, context: &CGContext) {
56        unsafe { CTLineDraw(self.as_concrete_TypeRef(), context.as_ptr()) }
57    }
58
59    pub fn get_image_bounds(&self, context: &CGContext) -> CGRect {
60        unsafe { CTLineGetImageBounds(self.as_concrete_TypeRef(), context.as_ptr()) }
61    }
62
63    pub fn get_typographic_bounds(&self) -> TypographicBounds {
64        let mut ascent = 0.0;
65        let mut descent = 0.0;
66        let mut leading = 0.0;
67        unsafe {
68            let width = CTLineGetTypographicBounds(
69                self.as_concrete_TypeRef(),
70                &mut ascent,
71                &mut descent,
72                &mut leading,
73            );
74            TypographicBounds {
75                width,
76                ascent,
77                descent,
78                leading,
79            }
80        }
81    }
82
83    pub fn get_string_index_for_position(&self, position: CGPoint) -> CFIndex {
84        unsafe { CTLineGetStringIndexForPosition(self.as_concrete_TypeRef(), position) }
85    }
86
87    pub fn get_string_offset_for_string_index(&self, charIndex: CFIndex) -> CGFloat {
88        unsafe {
89            CTLineGetOffsetForStringIndex(self.as_concrete_TypeRef(), charIndex, std::ptr::null())
90        }
91    }
92}
93
94#[cfg_attr(feature = "link", link(name = "CoreText", kind = "framework"))]
95extern "C" {
96    fn CTLineGetTypeID() -> CFTypeID;
97    fn CTLineGetGlyphRuns(line: CTLineRef) -> CFArrayRef;
98    fn CTLineGetStringRange(line: CTLineRef) -> CFRange;
99
100    // Creating Lines
101    fn CTLineCreateWithAttributedString(string: CFAttributedStringRef) -> CTLineRef;
102
103    // Drawing the Line
104    fn CTLineDraw(line: CTLineRef, context: *const core_graphics::sys::CGContext);
105
106    // Measuring Lines
107    fn CTLineGetImageBounds(
108        line: CTLineRef,
109        context: *const core_graphics::sys::CGContext,
110    ) -> CGRect;
111    fn CTLineGetTypographicBounds(
112        line: CTLineRef,
113        ascent: *mut CGFloat,
114        descent: *mut CGFloat,
115        leading: *mut CGFloat,
116    ) -> CGFloat;
117
118    // Getting Line Positioning
119    fn CTLineGetStringIndexForPosition(line: CTLineRef, position: CGPoint) -> CFIndex;
120    fn CTLineGetOffsetForStringIndex(
121        line: CTLineRef,
122        charIndex: CFIndex,
123        secondaryOffset: *const CGFloat,
124    ) -> CGFloat;
125}