Skip to main content

gdk4/
cairo_interaction.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use cairo::{Context, Region};
4use gdk_pixbuf::Pixbuf;
5use glib::translate::*;
6
7use crate::{RGBA, Rectangle, Surface, ffi};
8
9// rustdoc-stripper-ignore-next
10/// Trait containing integration methods with [`cairo::Surface`].
11pub trait GdkCairoSurfaceExt {
12    /// Creates region that covers the area where the given
13    /// @surface is more than 50% opaque.
14    ///
15    /// This function takes into account device offsets that might be
16    /// set with cairo_surface_set_device_offset().
17    /// ## `surface`
18    /// a cairo surface
19    ///
20    /// # Returns
21    ///
22    /// A [`cairo::Region`][crate::cairo::Region]
23    #[doc(alias = "gdk_cairo_region_create_from_surface")]
24    fn create_region(&self) -> Region;
25}
26
27impl GdkCairoSurfaceExt for cairo::Surface {
28    fn create_region(&self) -> Region {
29        unsafe {
30            from_glib_full(ffi::gdk_cairo_region_create_from_surface(
31                self.to_glib_none().0,
32            ))
33        }
34    }
35}
36
37// rustdoc-stripper-ignore-next
38/// Trait containing integration methods with [`cairo::Context`].
39pub trait GdkCairoContextExt: sealed::Sealed {
40    // rustdoc-stripper-ignore-next
41    /// # Safety
42    ///
43    /// It's the responsibility of the caller to ensure that source
44    /// is a valid GL resource.
45    // rustdoc-stripper-ignore-next-stop
46    /// Draws GL content onto a cairo context.
47    ///
48    /// It takes a render buffer ID (@source_type == GL_RENDERBUFFER) or a texture
49    /// id (@source_type == GL_TEXTURE) and draws it onto @cr with an OVER operation,
50    /// respecting the current clip. The top left corner of the rectangle specified
51    /// by @x, @y, @width and @height will be drawn at the current (0,0) position of
52    /// the [`cairo::Context`][crate::cairo::Context].
53    ///
54    /// This will work for *all* [`cairo::Context`][crate::cairo::Context], as long as @surface is realized, but the
55    /// fallback implementation that reads back the pixels from the buffer may be
56    /// used in the general case. In the case of direct drawing to a surface with
57    /// no special effects applied to @cr it will however use a more efficient
58    /// approach.
59    ///
60    /// For GL_RENDERBUFFER the code will always fall back to software for buffers
61    /// with alpha components, so make sure you use GL_TEXTURE if using alpha.
62    ///
63    /// Calling this may change the current GL context.
64    ///
65    /// # Deprecated since 4.6
66    ///
67    /// The function is overly complex and produces broken output
68    ///   in various combinations of arguments. If you want to draw with GL textures
69    ///   in GTK, use [`GLTexture::new()`][crate::GLTexture::new()]; if you want to use that texture in
70    ///   Cairo, use [`TextureExtManual::download()`][crate::prelude::TextureExtManual::download()] to download the data into a Cairo
71    ///   image surface.
72    /// ## `cr`
73    /// a cairo context
74    /// ## `surface`
75    /// The surface we're rendering for (not necessarily into)
76    /// ## `source`
77    /// The GL ID of the source buffer
78    /// ## `source_type`
79    /// The type of the @source
80    /// ## `buffer_scale`
81    /// The scale-factor that the @source buffer is allocated for
82    /// ## `x`
83    /// The source x position in @source to start copying from in GL coordinates
84    /// ## `y`
85    /// The source y position in @source to start copying from in GL coordinates
86    /// ## `width`
87    /// The width of the region to draw
88    /// ## `height`
89    /// The height of the region to draw
90    #[doc(alias = "gdk_cairo_draw_from_gl")]
91    #[allow(clippy::too_many_arguments)]
92    unsafe fn draw_from_gl(
93        &self,
94        surface: &Surface,
95        source: i32,
96        source_type: i32,
97        buffer_scale: i32,
98        x: i32,
99        y: i32,
100        width: i32,
101        height: i32,
102    ) {
103        unsafe {
104            skip_assert_initialized!();
105            ffi::gdk_cairo_draw_from_gl(
106                self.to_raw(),
107                surface.to_glib_none().0,
108                source,
109                source_type,
110                buffer_scale,
111                x,
112                y,
113                width,
114                height,
115            );
116        }
117    }
118
119    /// Sets the specified [`RGBA`][crate::RGBA] as the source color of @cr.
120    /// ## `cr`
121    /// a cairo context
122    /// ## `rgba`
123    /// a [`RGBA`][crate::RGBA]
124    #[doc(alias = "gdk_cairo_set_source_rgba")]
125    #[doc(alias = "set_source_rgba")]
126    fn set_source_color(&self, rgba: &RGBA) {
127        unsafe {
128            ffi::gdk_cairo_set_source_rgba(self.to_raw(), rgba.to_glib_none().0);
129        }
130    }
131
132    /// Sets the given pixbuf as the source pattern for @cr.
133    ///
134    /// The pattern has an extend mode of `CAIRO_EXTEND_NONE` and is aligned
135    /// so that the origin of @pixbuf is @pixbuf_x, @pixbuf_y.
136    ///
137    /// # Deprecated since 4.20
138    ///
139    /// Use cairo_set_source_surface() and gdk_texture_download()
140    /// ## `cr`
141    /// a cairo context
142    /// ## `pixbuf`
143    /// a [`gdk_pixbuf::Pixbuf`][crate::gdk_pixbuf::Pixbuf]
144    /// ## `pixbuf_x`
145    /// X coordinate of location to place upper left corner of @pixbuf
146    /// ## `pixbuf_y`
147    /// Y coordinate of location to place upper left corner of @pixbuf
148    #[doc(alias = "gdk_cairo_set_source_pixbuf")]
149    fn set_source_pixbuf(&self, pixbuf: &Pixbuf, x: f64, y: f64) {
150        unsafe {
151            ffi::gdk_cairo_set_source_pixbuf(self.to_raw(), pixbuf.to_glib_none().0, x, y);
152        }
153    }
154
155    /// Adds the given rectangle to the current path of @cr.
156    /// ## `cr`
157    /// a cairo context
158    /// ## `rectangle`
159    /// a [`Rectangle`][crate::Rectangle]
160    #[doc(alias = "gdk_cairo_rectangle")]
161    fn add_rectangle(&self, rectangle: &Rectangle) {
162        unsafe {
163            ffi::gdk_cairo_rectangle(self.to_raw(), rectangle.to_glib_none().0);
164        }
165    }
166
167    /// Adds the given region to the current path of @cr.
168    /// ## `cr`
169    /// a cairo context
170    /// ## `region`
171    /// a [`cairo::Region`][crate::cairo::Region]
172    #[doc(alias = "gdk_cairo_region")]
173    fn add_region(&self, region: &Region) {
174        unsafe {
175            ffi::gdk_cairo_region(self.to_raw(), region.to_glib_none().0);
176        }
177    }
178}
179
180impl GdkCairoContextExt for Context {}
181
182mod sealed {
183    use cairo::{Context, ffi::cairo_t};
184
185    pub trait Sealed {
186        fn to_raw(&self) -> *mut cairo_t;
187    }
188
189    impl Sealed for Context {
190        fn to_raw(&self) -> *mut cairo_t {
191            self.to_raw_none()
192        }
193    }
194}