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}