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    /// The main way to not draw GL content in GTK.
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    /// ## `cr`
135    /// a cairo context
136    /// ## `pixbuf`
137    /// a [`gdk_pixbuf::Pixbuf`][crate::gdk_pixbuf::Pixbuf]
138    /// ## `pixbuf_x`
139    /// X coordinate of location to place upper left corner of @pixbuf
140    /// ## `pixbuf_y`
141    /// Y coordinate of location to place upper left corner of @pixbuf
142    #[doc(alias = "gdk_cairo_set_source_pixbuf")]
143    fn set_source_pixbuf(&self, pixbuf: &Pixbuf, x: f64, y: f64) {
144        unsafe {
145            ffi::gdk_cairo_set_source_pixbuf(self.to_raw(), pixbuf.to_glib_none().0, x, y);
146        }
147    }
148
149    /// Adds the given rectangle to the current path of @cr.
150    /// ## `cr`
151    /// a cairo context
152    /// ## `rectangle`
153    /// a [`Rectangle`][crate::Rectangle]
154    #[doc(alias = "gdk_cairo_rectangle")]
155    fn add_rectangle(&self, rectangle: &Rectangle) {
156        unsafe {
157            ffi::gdk_cairo_rectangle(self.to_raw(), rectangle.to_glib_none().0);
158        }
159    }
160
161    /// Adds the given region to the current path of @cr.
162    /// ## `cr`
163    /// a cairo context
164    /// ## `region`
165    /// a [`cairo::Region`][crate::cairo::Region]
166    #[doc(alias = "gdk_cairo_region")]
167    fn add_region(&self, region: &Region) {
168        unsafe {
169            ffi::gdk_cairo_region(self.to_raw(), region.to_glib_none().0);
170        }
171    }
172}
173
174impl GdkCairoContextExt for Context {}
175
176mod sealed {
177    use cairo::{ffi::cairo_t, Context};
178
179    pub trait Sealed {
180        fn to_raw(&self) -> *mut cairo_t;
181    }
182
183    impl Sealed for Context {
184        fn to_raw(&self) -> *mut cairo_t {
185            self.to_raw_none()
186        }
187    }
188}