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, GlyphString, Item};
10
11/// Reorder items from logical order to visual order.
12///
13/// The visual order is determined from the associated directional
14/// levels of the items. The original list is unmodified.
15///
16/// (Please open a bug if you use this function.
17///  It is not a particularly convenient interface, and the code
18///  is duplicated elsewhere in Pango for that reason.)
19/// ## `items`
20/// a `GList` of [`Item`][crate::Item]
21///   in logical order.
22///
23/// # Returns
24///
25/// a `GList`
26///   of [`Item`][crate::Item] structures in visual order.
27#[doc(alias = "pango_reorder_items")]
28pub fn reorder_items(logical_items: &glib::List<Item>) -> glib::List<Item> {
29    unsafe {
30        FromGlibPtrContainer::from_glib_full(ffi::pango_reorder_items(
31            logical_items.as_ptr() as *mut _
32        ))
33    }
34}
35
36/// Convert the characters in @text into glyphs.
37///
38/// Given a segment of text and the corresponding [`Analysis`][crate::Analysis] structure
39/// returned from [`itemize()`][crate::itemize()], convert the characters into glyphs.
40/// You may also pass in only a substring of the item from [`itemize()`][crate::itemize()].
41///
42/// This is similar to [`shape()`][crate::shape()], except it also can optionally take
43/// the full paragraph text as input, which will then be used to perform
44/// certain cross-item shaping interactions. If you have access to the broader
45/// text of which @item_text is part of, provide the broader text as
46/// @paragraph_text. If @paragraph_text is [`None`], item text is used instead.
47///
48/// Some aspects of hyphen insertion and text transformation (in particular,
49/// capitalization) require log attrs, and thus can only be handled by
50/// `shape_item()`.
51///
52/// Note that the extra attributes in the @analyis that is returned from
53/// [`itemize()`][crate::itemize()] have indices that are relative to the entire paragraph,
54/// so you do not pass the full paragraph text as @paragraph_text, you need
55/// to subtract the item offset from their indices before calling
56/// [`shape_full()`][crate::shape_full()].
57/// ## `item_text`
58/// valid UTF-8 text to shape.
59/// ## `item_length`
60/// the length (in bytes) of @item_text. -1 means nul-terminated text.
61/// ## `paragraph_text`
62/// text of the paragraph (see details).
63/// ## `paragraph_length`
64/// the length (in bytes) of @paragraph_text. -1 means nul-terminated text.
65/// ## `analysis`
66/// [`Analysis`][crate::Analysis] structure from [`itemize()`][crate::itemize()].
67/// ## `glyphs`
68/// glyph string in which to store results.
69#[doc(alias = "pango_shape_full")]
70pub fn shape_full(
71    item_text: &str,
72    paragraph_text: Option<&str>,
73    analysis: &Analysis,
74    glyphs: &mut GlyphString,
75) {
76    let item_length = item_text.len() as i32;
77    let paragraph_length = paragraph_text.map(|t| t.len() as i32).unwrap_or_default();
78    let paragraph_ptr = paragraph_text.map_or(ptr::null(), |t| t.as_ptr() as *const c_char);
79    unsafe {
80        // The function does not take null-terminated strings when a length is provided.
81        // It also requires item_text to point to a subsequence of paragraph_text.
82        // Using to_glib_none() on &str will copy the string and cause problems.
83        ffi::pango_shape_full(
84            item_text.as_ptr() as *const c_char,
85            item_length,
86            paragraph_ptr,
87            paragraph_length,
88            analysis.to_glib_none().0,
89            glyphs.to_glib_none_mut().0,
90        );
91    }
92}
93
94/// Convert the characters in @text into glyphs.
95///
96/// Given a segment of text and the corresponding [`Analysis`][crate::Analysis] structure
97/// returned from [`itemize()`][crate::itemize()], convert the characters into glyphs.
98/// You may also pass in only a substring of the item from [`itemize()`][crate::itemize()].
99///
100/// This is similar to [`shape_full()`][crate::shape_full()], except it also takes flags
101/// that can influence the shaping process.
102///
103/// Some aspects of hyphen insertion and text transformation (in particular,
104/// capitalization) require log attrs, and thus can only be handled by
105/// `shape_item()`.
106///
107/// Note that the extra attributes in the @analyis that is returned from
108/// [`itemize()`][crate::itemize()] have indices that are relative to the entire paragraph,
109/// so you do not pass the full paragraph text as @paragraph_text, you need
110/// to subtract the item offset from their indices before calling
111/// [`shape_with_flags()`][crate::shape_with_flags()].
112/// ## `item_text`
113/// valid UTF-8 text to shape
114/// ## `item_length`
115/// the length (in bytes) of @item_text.
116///     -1 means nul-terminated text.
117/// ## `paragraph_text`
118/// text of the paragraph (see details).
119/// ## `paragraph_length`
120/// the length (in bytes) of @paragraph_text.
121///     -1 means nul-terminated text.
122/// ## `analysis`
123/// [`Analysis`][crate::Analysis] structure from [`itemize()`][crate::itemize()]
124/// ## `glyphs`
125/// glyph string in which to store results
126/// ## `flags`
127/// flags influencing the shaping process
128#[cfg(feature = "v1_44")]
129#[cfg_attr(docsrs, doc(cfg(feature = "v1_44")))]
130#[doc(alias = "pango_shape_with_flags")]
131pub fn shape_with_flags(
132    item_text: &str,
133    paragraph_text: Option<&str>,
134    analysis: &Analysis,
135    glyphs: &mut GlyphString,
136    flags: ShapeFlags,
137) {
138    let item_length = item_text.len() as i32;
139    let paragraph_length = paragraph_text.map(|t| t.len() as i32).unwrap_or_default();
140    let paragraph_ptr = paragraph_text.map_or(ptr::null(), |t| t.as_ptr() as *const c_char);
141    unsafe {
142        // See: shape_full
143        ffi::pango_shape_with_flags(
144            item_text.as_ptr() as *const c_char,
145            item_length,
146            paragraph_ptr,
147            paragraph_length,
148            analysis.to_glib_none().0,
149            glyphs.to_glib_none_mut().0,
150            flags.into_glib(),
151        );
152    }
153}
154
155/// Converts extents from Pango units to device units.
156///
157/// The conversion is done by dividing by the `PANGO_SCALE` factor and
158/// performing rounding.
159///
160/// The @inclusive rectangle is converted by flooring the x/y coordinates
161/// and extending width/height, such that the final rectangle completely
162/// includes the original rectangle.
163///
164/// The @nearest rectangle is converted by rounding the coordinates
165/// of the rectangle to the nearest device unit (pixel).
166///
167/// The rule to which argument to use is: if you want the resulting device-space
168/// rectangle to completely contain the original rectangle, pass it in as
169/// @inclusive. If you want two touching-but-not-overlapping rectangles stay
170/// touching-but-not-overlapping after rounding to device units, pass them in
171/// as @nearest.
172/// ## `inclusive`
173/// rectangle to round to pixels inclusively
174/// ## `nearest`
175/// rectangle to round to nearest pixels
176#[doc(alias = "pango_extents_to_pixels")]
177pub fn extents_to_pixels(
178    mut inclusive: Option<&mut crate::Rectangle>,
179    mut nearest: Option<&mut crate::Rectangle>,
180) {
181    unsafe {
182        ffi::pango_extents_to_pixels(inclusive.to_glib_none_mut().0, nearest.to_glib_none_mut().0);
183    }
184}