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