1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use babl::ObjectType;
use glib::translate::*;

use crate::{BlitFlags, Node, Rectangle};

impl Node {
    /// Render a rectangular region from a node.
    /// ## `scale`
    /// the scale to render at 1.0 is default, other values changes the
    /// width/height of the sampled region.
    /// ## `roi`
    /// the rectangle to render from the node, the coordinate system used is
    /// coordinates after scale has been applied.
    /// ## `format`
    /// the `BablFormat` desired.
    /// ## `destination_buf`
    /// a memory buffer large enough to contain the data, can be
    /// left as NULL when forcing a rendering of a region.
    /// ## `rowstride`
    /// rowstride in bytes, or GEGL_AUTO_ROWSTRIDE to compute the
    /// rowstride based on the width and bytes per pixel for the specified format.
    /// ## `flags`
    /// an or'ed combination of GEGL_BLIT_DEFAULT, GEGL_BLIT_CACHE and
    /// GEGL_BLIT_DIRTY. if cache is enabled, a cache will be set up for subsequent
    /// requests of image data from this node. By passing in GEGL_BLIT_DIRTY the
    /// function will return with the latest rendered results in the cache without
    /// regard to wheter the regions has been rendered or not.
    #[doc(alias = "gegl_node_blit")]
    pub fn blit(
        &self,
        scale: f64,
        roi: &Rectangle,
        format: &babl::Format,
        destination_buf: Option<&mut [u8]>,
        rowstride: i32,
        flags: BlitFlags,
    ) {
        if destination_buf.is_some() {
            assert!(
                (format.bytes_per_pixel() * roi.width() * roi.height()) as usize
                    <= destination_buf.as_ref().unwrap().len()
            );
        }
        unsafe {
            ffi::gegl_node_blit(
                self.to_glib_none().0,
                scale,
                roi.to_glib_none().0,
                format.inner(),
                destination_buf
                    .map(|buf| buf.as_ptr() as *mut std::ffi::c_void)
                    .unwrap_or_else(std::ptr::null_mut),
                rowstride,
                flags.bits(),
            )
        }
    }

    /// Creates a new processing node that performs the specified operation with
    /// a NULL terminated list of key/value pairs for initial parameter values
    /// configuring the operation. Usually the first pair should be "operation"
    /// and the type of operation to be associated. If no operation is provided
    /// the node doesn't have an initial operation and can be used to construct
    /// a subgraph with special middle-man routing nodes created with
    /// `gegl_node_get_output_proxy` and `gegl_node_get_input_proxy`.
    /// ## `first_property_name`
    /// the first property name
    ///
    /// # Returns
    ///
    /// A newly created [`Node`][crate::Node]. The node will be destroyed by the parent.
    /// Calling g_object_unref on a node will cause the node to be dropped by the
    /// parent. (You may also add additional references using
    /// g_object_ref/g_object_unref, but in general relying on the parents reference
    /// counting is easiest.)
    #[doc(alias = "gegl_node_new_child")]
    #[must_use]
    pub fn new_child(
        &self,
        operation: Option<&str>,
        props: &[(&str, glib::Value)],
    ) -> Option<Node> {
        operation
            .and_then(|operation| self.create_child(operation))
            .or_else(|| self.add_child(&Node::new()))
            .map(|node| {
                for prop in props {
                    node.set_property(prop.0, &prop.1)
                }

                node
            })
    }

    /// Synthetic sugar for linking a chain of nodes with "input"->"output". The
    /// list is NULL terminated.
    /// ## `first_sink`
    /// the first consumer of data.
    #[doc(alias = "gegl_node_link_many")]
    pub fn link_many(&self, dests: &[&Self]) {
        let mut source = self;

        for dest in dests {
            source.link(&dest);
            source = dest;
        }
    }

    /// Returns the position and dimensions of a rectangle spanning the area
    /// defined by a node.
    #[doc(alias = "get_bounding_box")]
    pub fn bounding_box(&self) -> Rectangle {
        unsafe {
            Rectangle {
                inner: ffi::gegl_node_get_bounding_box(self.to_glib_none().0),
            }
        }
    }
}