pango/
functions.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::translate::*;
4use std::{ffi::c_char, ptr};
5
6pub use crate::auto::functions::*;
7#[cfg(feature = "v1_44")]
8use crate::ShapeFlags;
9use crate::{ffi, Analysis, AttrIterator, AttrList, Context, Direction, GlyphString, Item};
10
11#[doc(alias = "pango_reorder_items")]
12pub fn reorder_items(logical_items: &glib::List<Item>) -> glib::List<Item> {
13    unsafe {
14        FromGlibPtrContainer::from_glib_full(ffi::pango_reorder_items(
15            logical_items.as_ptr() as *mut _
16        ))
17    }
18}
19
20#[doc(alias = "pango_shape_full")]
21pub fn shape_full(
22    item_text: &str,
23    paragraph_text: Option<&str>,
24    analysis: &Analysis,
25    glyphs: &mut GlyphString,
26) {
27    let item_length = item_text.len() as i32;
28    let paragraph_length = paragraph_text.map(|t| t.len() as i32).unwrap_or_default();
29    let paragraph_ptr = paragraph_text.map_or(ptr::null(), |t| t.as_ptr() as *const c_char);
30    unsafe {
31        // The function does not take null-terminated strings when a length is provided.
32        // It also requires item_text to point to a subsequence of paragraph_text.
33        // Using to_glib_none() on &str will copy the string and cause problems.
34        ffi::pango_shape_full(
35            item_text.as_ptr() as *const c_char,
36            item_length,
37            paragraph_ptr,
38            paragraph_length,
39            analysis.to_glib_none().0,
40            glyphs.to_glib_none_mut().0,
41        );
42    }
43}
44
45#[doc(alias = "pango_shape")]
46pub fn shape(item_text: &str, analysis: &Analysis, glyphs: &mut GlyphString) {
47    let item_length = item_text.len() as i32;
48    unsafe {
49        // The function does not take null-terminated strings when a length is provided.
50        // Using to_glib_none() on &str will copy the string unnecessarily.
51        ffi::pango_shape(
52            item_text.as_ptr() as *const c_char,
53            item_length,
54            analysis.to_glib_none().0,
55            glyphs.to_glib_none_mut().0,
56        );
57    }
58}
59
60#[cfg(feature = "v1_44")]
61#[cfg_attr(docsrs, doc(cfg(feature = "v1_44")))]
62#[doc(alias = "pango_shape_with_flags")]
63pub fn shape_with_flags(
64    item_text: &str,
65    paragraph_text: Option<&str>,
66    analysis: &Analysis,
67    glyphs: &mut GlyphString,
68    flags: ShapeFlags,
69) {
70    let item_length = item_text.len() as i32;
71    let paragraph_length = paragraph_text.map(|t| t.len() as i32).unwrap_or_default();
72    let paragraph_ptr = paragraph_text.map_or(ptr::null(), |t| t.as_ptr() as *const c_char);
73    unsafe {
74        // See: shape_full
75        ffi::pango_shape_with_flags(
76            item_text.as_ptr() as *const c_char,
77            item_length,
78            paragraph_ptr,
79            paragraph_length,
80            analysis.to_glib_none().0,
81            glyphs.to_glib_none_mut().0,
82            flags.into_glib(),
83        );
84    }
85}
86
87#[doc(alias = "pango_extents_to_pixels")]
88pub fn extents_to_pixels(
89    mut inclusive: Option<&mut crate::Rectangle>,
90    mut nearest: Option<&mut crate::Rectangle>,
91) {
92    unsafe {
93        ffi::pango_extents_to_pixels(inclusive.to_glib_none_mut().0, nearest.to_glib_none_mut().0);
94    }
95}
96
97#[doc(alias = "pango_itemize")]
98pub fn itemize(
99    context: &Context,
100    text: &str,
101    start_index: i32,
102    length: i32,
103    attrs: &AttrList,
104    cached_iter: Option<&AttrIterator>,
105) -> Vec<Item> {
106    let total_length = text.len() as i32;
107    assert!(
108        start_index >= 0 && start_index < total_length,
109        "start_index is out of range"
110    );
111    assert!(
112        length >= 0 && start_index.checked_add(length).unwrap() <= total_length,
113        "start_index + length is out of range"
114    );
115    unsafe {
116        FromGlibPtrContainer::from_glib_full(ffi::pango_itemize(
117            context.to_glib_none().0,
118            text.to_glib_none().0,
119            start_index,
120            length,
121            attrs.to_glib_none().0,
122            mut_override(cached_iter.to_glib_none().0),
123        ))
124    }
125}
126
127#[doc(alias = "pango_itemize_with_base_dir")]
128pub fn itemize_with_base_dir(
129    context: &Context,
130    base_dir: Direction,
131    text: &str,
132    start_index: i32,
133    length: i32,
134    attrs: &AttrList,
135    cached_iter: Option<&AttrIterator>,
136) -> Vec<Item> {
137    let total_length = text.len() as i32;
138    assert!(
139        start_index >= 0 && start_index < total_length,
140        "start_index is out of range"
141    );
142    assert!(
143        length >= 0 && start_index.checked_add(length).unwrap() <= total_length,
144        "start_index + length is out of range"
145    );
146    unsafe {
147        FromGlibPtrContainer::from_glib_full(ffi::pango_itemize_with_base_dir(
148            context.to_glib_none().0,
149            base_dir.into_glib(),
150            text.to_glib_none().0,
151            start_index,
152            length,
153            attrs.to_glib_none().0,
154            mut_override(cached_iter.to_glib_none().0),
155        ))
156    }
157}