Skip to main content

pango/
glyph_item_iter.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{marker::PhantomData, mem};
4
5use glib::{GStr, GString, prelude::*, translate::*};
6
7use crate::{GlyphItem, ffi};
8
9/// offset` to get to the text of @glyph_item.
10/// The @start_index and @end_index values can directly index into @text. The
11/// @start_glyph, @end_glyph, @start_char, and @end_char values however are
12/// zero-based for the @glyph_item.  For each cluster, the item pointed at by
13/// the start variables is included in the cluster while the one pointed at by
14/// end variables is not.
15///
16/// None of the members of a [`GlyphItemIter`][crate::GlyphItemIter] should be modified manually.
17#[derive(Clone, Debug)]
18pub struct GlyphItemIter<'item> {
19    inner: ffi::PangoGlyphItemIter,
20    text: GString,
21    item: PhantomData<&'item GlyphItem>,
22}
23
24impl StaticType for GlyphItemIter<'_> {
25    #[inline]
26    fn static_type() -> glib::Type {
27        unsafe { from_glib(ffi::pango_glyph_item_iter_get_type()) }
28    }
29}
30
31impl<'item> GlyphItemIter<'item> {
32    #[doc(alias = "pango_glyph_item_iter_init_start")]
33    pub fn new_start(glyph_item: &'item GlyphItem, text: &str) -> Result<Self, glib::BoolError> {
34        unsafe {
35            let mut iter = mem::MaybeUninit::zeroed();
36            let text = GString::from(text);
37            let res: bool = from_glib(ffi::pango_glyph_item_iter_init_start(
38                iter.as_mut_ptr(),
39                mut_override(glyph_item.to_glib_none().0),
40                text.as_ptr(),
41            ));
42
43            if res {
44                Ok(Self {
45                    inner: iter.assume_init(),
46                    text,
47                    item: PhantomData,
48                })
49            } else {
50                Err(glib::bool_error!("Failed to create glyph item iter"))
51            }
52        }
53    }
54
55    #[doc(alias = "pango_glyph_item_iter_init_end")]
56    pub fn new_end(glyph_item: &'item GlyphItem, text: &str) -> Result<Self, glib::BoolError> {
57        unsafe {
58            let mut iter = mem::MaybeUninit::zeroed();
59            let text = GString::from(text);
60            let res: bool = from_glib(ffi::pango_glyph_item_iter_init_end(
61                iter.as_mut_ptr(),
62                mut_override(glyph_item.to_glib_none().0),
63                text.as_ptr(),
64            ));
65
66            if res {
67                Ok(Self {
68                    inner: iter.assume_init(),
69                    text,
70                    item: PhantomData,
71                })
72            } else {
73                Err(glib::bool_error!("Failed to create glyph item iter"))
74            }
75        }
76    }
77
78    #[doc(alias = "pango_glyph_item_iter_next_cluster")]
79    pub fn next_cluster(&mut self) -> bool {
80        unsafe {
81            from_glib(ffi::pango_glyph_item_iter_next_cluster(
82                self.to_glib_none_mut().0,
83            ))
84        }
85    }
86
87    #[doc(alias = "pango_glyph_item_iter_prev_cluster")]
88    pub fn prev_cluster(&mut self) -> bool {
89        unsafe {
90            from_glib(ffi::pango_glyph_item_iter_prev_cluster(
91                self.to_glib_none_mut().0,
92            ))
93        }
94    }
95
96    #[inline]
97    pub fn glyph_item(&self) -> &'item GlyphItem {
98        unsafe { &*(&self.inner.glyph_item as *const _ as *const GlyphItem) }
99    }
100    #[inline]
101    pub fn text(&self) -> &GStr {
102        self.text.as_gstr()
103    }
104    #[inline]
105    pub fn start_glyph(&self) -> i32 {
106        self.inner.start_glyph
107    }
108    #[inline]
109    pub fn start_index(&self) -> i32 {
110        self.inner.start_index
111    }
112    #[inline]
113    pub fn start_char(&self) -> i32 {
114        self.inner.start_char
115    }
116    #[inline]
117    pub fn end_glyph(&self) -> i32 {
118        self.inner.end_glyph
119    }
120    #[inline]
121    pub fn end_index(&self) -> i32 {
122        self.inner.end_index
123    }
124    #[inline]
125    pub fn end_char(&self) -> i32 {
126        self.inner.end_char
127    }
128}
129
130impl<'item> IntoIterator for GlyphItemIter<'item> {
131    type Item = (i32, i32, i32, i32, i32, i32);
132    type IntoIter = GlyphItemIntoIter<'item>;
133    #[inline]
134    fn into_iter(self) -> Self::IntoIter {
135        GlyphItemIntoIter(Some(self))
136    }
137}
138
139#[derive(Clone, Debug)]
140#[repr(transparent)]
141pub struct GlyphItemIntoIter<'item>(Option<GlyphItemIter<'item>>);
142
143impl Iterator for GlyphItemIntoIter<'_> {
144    type Item = (i32, i32, i32, i32, i32, i32);
145    fn next(&mut self) -> Option<Self::Item> {
146        if let Some(iter) = &mut self.0 {
147            let values = (
148                iter.start_glyph(),
149                iter.start_index(),
150                iter.start_char(),
151                iter.end_glyph(),
152                iter.end_index(),
153                iter.end_char(),
154            );
155            if !iter.next_cluster() {
156                self.0 = None;
157            }
158            Some(values)
159        } else {
160            None
161        }
162    }
163}
164
165impl std::iter::FusedIterator for GlyphItemIntoIter<'_> {}
166
167#[doc(hidden)]
168impl<'a, 'item> ToGlibPtr<'a, *const ffi::PangoGlyphItemIter> for GlyphItemIter<'item>
169where
170    'item: 'a,
171{
172    type Storage = PhantomData<&'a Self>;
173    #[inline]
174    fn to_glib_none(&'a self) -> Stash<'a, *const ffi::PangoGlyphItemIter, Self> {
175        Stash(&self.inner, PhantomData)
176    }
177}
178
179#[doc(hidden)]
180impl<'a, 'item> ToGlibPtrMut<'a, *mut ffi::PangoGlyphItemIter> for GlyphItemIter<'item>
181where
182    'item: 'a,
183{
184    type Storage = PhantomData<&'a mut Self>;
185    #[inline]
186    fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut ffi::PangoGlyphItemIter, Self> {
187        StashMut(&mut self.inner, PhantomData)
188    }
189}