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;
19use std::os::raw::c_void;
20
21#[repr(C)]
22pub struct __CTLine(c_void);
23
24pub type CTLineRef = *const __CTLine;
25
26declare_TCFType! {
27    CTLine, CTLineRef
28}
29impl_TCFType!(CTLine, CTLineRef, CTLineGetTypeID);
30impl_CFTypeDescription!(CTLine);
31
32/// Metrics for a given line.
33pub struct TypographicBounds {
34    pub width: CGFloat,
35    pub ascent: CGFloat,
36    pub descent: CGFloat,
37    pub leading: CGFloat,
38}
39
40impl CTLine {
41    pub fn new_with_attributed_string(string: CFAttributedStringRef) -> Self {
42        unsafe {
43            let ptr = CTLineCreateWithAttributedString(string);
44            CTLine::wrap_under_create_rule(ptr)
45        }
46    }
47
48    pub fn glyph_runs(&self) -> CFArray<CTRun> {
49        unsafe { TCFType::wrap_under_get_rule(CTLineGetGlyphRuns(self.0)) }
50    }
51
52    pub fn get_string_range(&self) -> CFRange {
53        unsafe { CTLineGetStringRange(self.as_concrete_TypeRef()) }
54    }
55
56    pub fn draw(&self, context: &CGContext) {
57        unsafe { CTLineDraw(self.as_concrete_TypeRef(), context.as_ptr()) }
58    }
59
60    pub fn get_image_bounds(&self, context: &CGContext) -> CGRect {
61        unsafe { CTLineGetImageBounds(self.as_concrete_TypeRef(), context.as_ptr()) }
62    }
63
64    pub fn get_typographic_bounds(&self) -> TypographicBounds {
65        let mut ascent = 0.0;
66        let mut descent = 0.0;
67        let mut leading = 0.0;
68        unsafe {
69            let width = CTLineGetTypographicBounds(
70                self.as_concrete_TypeRef(),
71                &mut ascent,
72                &mut descent,
73                &mut leading,
74            );
75            TypographicBounds {
76                width,
77                ascent,
78                descent,
79                leading,
80            }
81        }
82    }
83
84    pub fn get_string_index_for_position(&self, position: CGPoint) -> CFIndex {
85        unsafe { CTLineGetStringIndexForPosition(self.as_concrete_TypeRef(), position) }
86    }
87
88    pub fn get_string_offset_for_string_index(&self, charIndex: CFIndex) -> CGFloat {
89        unsafe {
90            CTLineGetOffsetForStringIndex(self.as_concrete_TypeRef(), charIndex, std::ptr::null())
91        }
92    }
93}
94
95#[cfg_attr(feature = "link", link(name = "CoreText", kind = "framework"))]
96extern "C" {
97    fn CTLineGetTypeID() -> CFTypeID;
98    fn CTLineGetGlyphRuns(line: CTLineRef) -> CFArrayRef;
99    fn CTLineGetStringRange(line: CTLineRef) -> CFRange;
100
101    // Creating Lines
102    fn CTLineCreateWithAttributedString(string: CFAttributedStringRef) -> CTLineRef;
103
104    // Drawing the Line
105    fn CTLineDraw(line: CTLineRef, context: *const core_graphics::sys::CGContext);
106
107    // Measuring Lines
108    fn CTLineGetImageBounds(
109        line: CTLineRef,
110        context: *const core_graphics::sys::CGContext,
111    ) -> CGRect;
112    fn CTLineGetTypographicBounds(
113        line: CTLineRef,
114        ascent: *mut CGFloat,
115        descent: *mut CGFloat,
116        leading: *mut CGFloat,
117    ) -> CGFloat;
118
119    // Getting Line Positioning
120    fn CTLineGetStringIndexForPosition(line: CTLineRef, position: CGPoint) -> CFIndex;
121    fn CTLineGetOffsetForStringIndex(
122        line: CTLineRef,
123        charIndex: CFIndex,
124        secondaryOffset: *const CGFloat,
125    ) -> CGFloat;
126}