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::{ffi, Rectangle, Surface, RGBA};
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        skip_assert_initialized!();
104        ffi::gdk_cairo_draw_from_gl(
105            self.to_raw(),
106            surface.to_glib_none().0,
107            source,
108            source_type,
109            buffer_scale,
110            x,
111            y,
112            width,
113            height,
114        );
115    }
116
117    /// Sets the specified [`RGBA`][crate::RGBA] as the source color of @cr.
118    /// ## `cr`
119    /// a cairo context
120    /// ## `rgba`
121    /// a [`RGBA`][crate::RGBA]
122    #[doc(alias = "gdk_cairo_set_source_rgba")]
123    #[doc(alias = "set_source_rgba")]
124    fn set_source_color(&self, rgba: &RGBA) {
125        unsafe {
126            ffi::gdk_cairo_set_source_rgba(self.to_raw(), rgba.to_glib_none().0);
127        }
128    }
129
130    /// Sets the given pixbuf as the source pattern for @cr.
131    ///
132    /// The pattern has an extend mode of `CAIRO_EXTEND_NONE` and is aligned
133    /// so that the origin of @pixbuf is @pixbuf_x, @pixbuf_y.
134    ///
135    /// # Deprecated since 4.20
136    ///
137    /// Use cairo_set_source_surface() and gdk_texture_download()
138    /// ## `cr`
139    /// a cairo context
140    /// ## `pixbuf`
141    /// a [`gdk_pixbuf::Pixbuf`][crate::gdk_pixbuf::Pixbuf]
142    /// ## `pixbuf_x`
143    /// X coordinate of location to place upper left corner of @pixbuf
144    /// ## `pixbuf_y`
145    /// Y coordinate of location to place upper left corner of @pixbuf
146    #[doc(alias = "gdk_cairo_set_source_pixbuf")]
147    fn set_source_pixbuf(&self, pixbuf: &Pixbuf, x: f64, y: f64) {
148        unsafe {
149            ffi::gdk_cairo_set_source_pixbuf(self.to_raw(), pixbuf.to_glib_none().0, x, y);
150        }
151    }
152
153    /// Adds the given rectangle to the current path of @cr.
154    /// ## `cr`
155    /// a cairo context
156    /// ## `rectangle`
157    /// a [`Rectangle`][crate::Rectangle]
158    #[doc(alias = "gdk_cairo_rectangle")]
159    fn add_rectangle(&self, rectangle: &Rectangle) {
160        unsafe {
161            ffi::gdk_cairo_rectangle(self.to_raw(), rectangle.to_glib_none().0);
162        }
163    }
164
165    /// Adds the given region to the current path of @cr.
166    /// ## `cr`
167    /// a cairo context
168    /// ## `region`
169    /// a [`cairo::Region`][crate::cairo::Region]
170    #[doc(alias = "gdk_cairo_region")]
171    fn add_region(&self, region: &Region) {
172        unsafe {
173            ffi::gdk_cairo_region(self.to_raw(), region.to_glib_none().0);
174        }
175    }
176}
177
178impl GdkCairoContextExt for Context {}
179
180mod sealed {
181    use cairo::{ffi::cairo_t, Context};
182
183    pub trait Sealed {
184        fn to_raw(&self) -> *mut cairo_t;
185    }
186
187    impl Sealed for Context {
188        fn to_raw(&self) -> *mut cairo_t {
189            self.to_raw_none()
190        }
191    }
192}