1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// Take a look at the license at the top of the repository in the LICENSE file.

use glib::translate::*;

#[cfg(feature = "v1_44")]
use crate::ShapeFlags;
use crate::{Analysis, GlyphString, Item};

/// Reorder items from logical order to visual order.
///
/// The visual order is determined from the associated directional
/// levels of the items. The original list is unmodified.
///
/// (Please open a bug if you use this function.
///  It is not a particularly convenient interface, and the code
///  is duplicated elsewhere in Pango for that reason.)
/// ## `items`
/// a `GList` of [`Item`][crate::Item]
///   in logical order.
///
/// # Returns
///
/// a `GList`
///   of [`Item`][crate::Item] structures in visual order.
#[doc(alias = "pango_reorder_items")]
pub fn reorder_items(logical_items: &glib::List<Item>) -> glib::List<Item> {
    unsafe {
        FromGlibPtrContainer::from_glib_full(ffi::pango_reorder_items(
            logical_items.as_ptr() as *mut _
        ))
    }
}

/// Convert the characters in @text into glyphs.
///
/// Given a segment of text and the corresponding [`Analysis`][crate::Analysis] structure
/// returned from [`itemize()`][crate::itemize()], convert the characters into glyphs.
/// You may also pass in only a substring of the item from [`itemize()`][crate::itemize()].
///
/// This is similar to [`shape()`][crate::shape()], except it also can optionally take
/// the full paragraph text as input, which will then be used to perform
/// certain cross-item shaping interactions. If you have access to the broader
/// text of which @item_text is part of, provide the broader text as
/// @paragraph_text. If @paragraph_text is [`None`], item text is used instead.
///
/// Some aspects of hyphen insertion and text transformation (in particular,
/// capitalization) require log attrs, and thus can only be handled by
/// `shape_item()`.
///
/// Note that the extra attributes in the @analyis that is returned from
/// [`itemize()`][crate::itemize()] have indices that are relative to the entire paragraph,
/// so you do not pass the full paragraph text as @paragraph_text, you need
/// to subtract the item offset from their indices before calling
/// [`shape_full()`][crate::shape_full()].
/// ## `item_text`
/// valid UTF-8 text to shape.
/// ## `item_length`
/// the length (in bytes) of @item_text. -1 means nul-terminated text.
/// ## `paragraph_text`
/// text of the paragraph (see details).
/// ## `paragraph_length`
/// the length (in bytes) of @paragraph_text. -1 means nul-terminated text.
/// ## `analysis`
/// [`Analysis`][crate::Analysis] structure from [`itemize()`][crate::itemize()].
/// ## `glyphs`
/// glyph string in which to store results.
#[doc(alias = "pango_shape_full")]
pub fn shape_full(
    item_text: &str,
    paragraph_text: Option<&str>,
    analysis: &Analysis,
    glyphs: &mut GlyphString,
) {
    let paragraph_length = match paragraph_text {
        Some(s) => s.len(),
        None => 0,
    } as i32;
    let paragraph_text = paragraph_text.to_glib_none();
    let item_length = item_text.len() as i32;
    unsafe {
        ffi::pango_shape_full(
            item_text.to_glib_none().0,
            item_length,
            paragraph_text.0,
            paragraph_length,
            analysis.to_glib_none().0,
            glyphs.to_glib_none_mut().0,
        );
    }
}

/// Convert the characters in @text into glyphs.
///
/// Given a segment of text and the corresponding [`Analysis`][crate::Analysis] structure
/// returned from [`itemize()`][crate::itemize()], convert the characters into glyphs.
/// You may also pass in only a substring of the item from [`itemize()`][crate::itemize()].
///
/// This is similar to [`shape_full()`][crate::shape_full()], except it also takes flags
/// that can influence the shaping process.
///
/// Some aspects of hyphen insertion and text transformation (in particular,
/// capitalization) require log attrs, and thus can only be handled by
/// `shape_item()`.
///
/// Note that the extra attributes in the @analyis that is returned from
/// [`itemize()`][crate::itemize()] have indices that are relative to the entire paragraph,
/// so you do not pass the full paragraph text as @paragraph_text, you need
/// to subtract the item offset from their indices before calling
/// [`shape_with_flags()`][crate::shape_with_flags()].
/// ## `item_text`
/// valid UTF-8 text to shape
/// ## `item_length`
/// the length (in bytes) of @item_text.
///     -1 means nul-terminated text.
/// ## `paragraph_text`
/// text of the paragraph (see details).
/// ## `paragraph_length`
/// the length (in bytes) of @paragraph_text.
///     -1 means nul-terminated text.
/// ## `analysis`
/// [`Analysis`][crate::Analysis] structure from [`itemize()`][crate::itemize()]
/// ## `glyphs`
/// glyph string in which to store results
/// ## `flags`
/// flags influencing the shaping process
#[cfg(feature = "v1_44")]
#[cfg_attr(docsrs, doc(cfg(feature = "v1_44")))]
#[doc(alias = "pango_shape_with_flags")]
pub fn shape_with_flags(
    item_text: &str,
    paragraph_text: Option<&str>,
    analysis: &Analysis,
    glyphs: &mut GlyphString,
    flags: ShapeFlags,
) {
    let item_length = item_text.len() as i32;
    let paragraph_length = paragraph_text.map(|t| t.len() as i32).unwrap_or_default();
    unsafe {
        ffi::pango_shape_with_flags(
            item_text.to_glib_none().0,
            item_length,
            paragraph_text.to_glib_none().0,
            paragraph_length,
            analysis.to_glib_none().0,
            glyphs.to_glib_none_mut().0,
            flags.into_glib(),
        );
    }
}

/// Converts extents from Pango units to device units.
///
/// The conversion is done by dividing by the `PANGO_SCALE` factor and
/// performing rounding.
///
/// The @inclusive rectangle is converted by flooring the x/y coordinates
/// and extending width/height, such that the final rectangle completely
/// includes the original rectangle.
///
/// The @nearest rectangle is converted by rounding the coordinates
/// of the rectangle to the nearest device unit (pixel).
///
/// The rule to which argument to use is: if you want the resulting device-space
/// rectangle to completely contain the original rectangle, pass it in as
/// @inclusive. If you want two touching-but-not-overlapping rectangles stay
/// touching-but-not-overlapping after rounding to device units, pass them in
/// as @nearest.
/// ## `inclusive`
/// rectangle to round to pixels inclusively
/// ## `nearest`
/// rectangle to round to nearest pixels
#[doc(alias = "pango_extents_to_pixels")]
pub fn extents_to_pixels(
    mut inclusive: Option<&mut crate::Rectangle>,
    mut nearest: Option<&mut crate::Rectangle>,
) {
    unsafe {
        ffi::pango_extents_to_pixels(inclusive.to_glib_none_mut().0, nearest.to_glib_none_mut().0);
    }
}