pixman-0.2.1/.cargo_vcs_info.json0000644000000001440000000000100123270ustar { "git": { "sha1": "92f4f9c716d031d9c9c015ebe5fba49a771c5252" }, "path_in_vcs": "pixman" }pixman-0.2.1/Cargo.lock0000644000000257220000000000100103130ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "adler" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "bit_field" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bytemuck" version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" [[package]] name = "byteorder" version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "color_quant" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "crc32fast" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-deque" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" dependencies = [ "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" version = "0.9.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", "memoffset", "scopeguard", ] [[package]] name = "crossbeam-utils" version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if", ] [[package]] name = "crunchy" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "drm-fourcc" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0aafbcdb8afc29c1a7ee5fbe53b5d62f4565b35a042a662ca9fecd0b54dae6f4" [[package]] name = "either" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "exr" version = "1.71.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "832a761f35ab3e6664babfbdc6cef35a4860e816ec3916dcfd0882954e98a8a8" dependencies = [ "bit_field", "flume", "half", "lebe", "miniz_oxide", "rayon-core", "smallvec", "zune-inflate", ] [[package]] name = "fdeflate" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10" dependencies = [ "simd-adler32", ] [[package]] name = "flate2" version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" dependencies = [ "crc32fast", "miniz_oxide", ] [[package]] name = "flume" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" dependencies = [ "spin", ] [[package]] name = "gif" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045" dependencies = [ "color_quant", "weezl", ] [[package]] name = "half" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0" dependencies = [ "crunchy", ] [[package]] name = "image" version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711" dependencies = [ "bytemuck", "byteorder", "color_quant", "exr", "gif", "jpeg-decoder", "num-rational", "num-traits", "png", "qoi", "tiff", ] [[package]] name = "jpeg-decoder" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e" dependencies = [ "rayon", ] [[package]] name = "lebe" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "lock_api" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" dependencies = [ "autocfg", "scopeguard", ] [[package]] name = "memoffset" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ "autocfg", ] [[package]] name = "miniz_oxide" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ "adler", "simd-adler32", ] [[package]] name = "num-integer" version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ "autocfg", "num-traits", ] [[package]] name = "num-rational" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" dependencies = [ "autocfg", "num-integer", "num-traits", ] [[package]] name = "num-traits" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", ] [[package]] name = "paste" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "pixman" version = "0.2.1" dependencies = [ "drm-fourcc", "image", "paste", "pixman-sys", "thiserror", ] [[package]] name = "pixman-sys" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1a0483e89e81d7915defe83c51f23f6800594d64f6f4a21253ce87fd8444ada" [[package]] name = "png" version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" dependencies = [ "bitflags", "crc32fast", "fdeflate", "flate2", "miniz_oxide", ] [[package]] name = "proc-macro2" version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] [[package]] name = "qoi" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" dependencies = [ "bytemuck", ] [[package]] name = "quote" version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] [[package]] name = "rayon" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" dependencies = [ "either", "rayon-core", ] [[package]] name = "rayon-core" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" dependencies = [ "crossbeam-deque", "crossbeam-utils", ] [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "simd-adler32" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] name = "smallvec" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" dependencies = [ "lock_api", ] [[package]] name = "syn" version = "2.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "thiserror" version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "tiff" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d172b0f4d3fba17ba89811858b9d3d97f928aece846475bbda076ca46736211" dependencies = [ "flate2", "jpeg-decoder", "weezl", ] [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "weezl" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" [[package]] name = "zune-inflate" version = "0.2.54" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" dependencies = [ "simd-adler32", ] pixman-0.2.1/Cargo.toml0000644000000040150000000000100103260ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.65.0" name = "pixman" version = "0.2.1" authors = ["Christian Meissl "] build = false autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "Pixman is a low-level software library for pixel manipulation, providing features such as image compositing and trapezoid rasterization." documentation = "https://docs.rs/pixman/" readme = "README.md" keywords = [ "pixman", "2d", ] categories = [ "rendering", "api-bindings", ] license = "MIT" repository = "https://github.com/cmeissl/pixman-rs" [package.metadata.docs.rs] features = ["drm-fourcc"] rustdoc-args = [ "--cfg", "docsrs", ] [lib] name = "pixman" path = "src/lib.rs" [[example]] name = "alpha" path = "examples/alpha.rs" [[example]] name = "checkerboard" path = "examples/checkerboard.rs" [[example]] name = "clip" path = "examples/clip.rs" [[example]] name = "conical" path = "examples/conical.rs" [[example]] name = "fill" path = "examples/fill.rs" [[example]] name = "gradient" path = "examples/gradient.rs" [[example]] name = "solid_fill" path = "examples/solid_fill.rs" [[example]] name = "trap" path = "examples/trap.rs" [[example]] name = "tri" path = "examples/tri.rs" [dependencies.drm-fourcc] version = "2.2.0" optional = true [dependencies.paste] version = "1.0.14" [dependencies.pixman-sys] version = "0.1.0" [dependencies.thiserror] version = "1.0.50" [dev-dependencies.image] version = "0.24.7" [features] default = [] drm-fourcc = ["dep:drm-fourcc"] sync = [] pixman-0.2.1/Cargo.toml.orig000064400000000000000000000015311046102023000140070ustar 00000000000000[package] authors = ["Christian Meissl "] categories = ["rendering", "api-bindings"] description = "Pixman is a low-level software library for pixel manipulation, providing features such as image compositing and trapezoid rasterization." documentation = "https://docs.rs/pixman/" edition = "2021" keywords = ["pixman", "2d"] license = "MIT" name = "pixman" repository = "https://github.com/cmeissl/pixman-rs" rust-version = "1.65.0" version = "0.2.1" readme = "../README.md" [package.metadata.docs.rs] features = ["drm-fourcc"] rustdoc-args = ["--cfg", "docsrs"] [dependencies] drm-fourcc = {version = "2.2.0", optional = true} paste = "1.0.14" pixman-sys = {version = "0.1.0", path = "../pixman-sys"} thiserror = "1.0.50" [dev-dependencies] image = "0.24.7" [features] default = [] drm-fourcc = ["dep:drm-fourcc"] sync = [] pixman-0.2.1/README.md000064400000000000000000000013251046102023000124000ustar 00000000000000# Pixman-rs This project contains rust bindings for [`pixman`](https://www.pixman.org/). From the official pixman docs: > Pixman is a low-level software library for pixel manipulation, providing features such as image compositing and trapezoid rasterization. > Important users of pixman are the cairo graphics library and the X server. > > Pixman is implemented as a library in the C programming language. It runs on many platforms, including Linux, BSD Derivatives, MacOS X, and Windows. > > Pixman is free and open source software. It is available to be redistributed and/or modified under the terms of the MIT license. ## Currently unsupported features - Indexed image - Glyph cache - Separable convolution filterpixman-0.2.1/examples/alpha.rs000064400000000000000000000052371046102023000144000ustar 00000000000000use pixman::{ Fixed, FormatCode, GradientStop, Image, LinearGradient, Operation, Point, Repeat, Transform, }; const WIDTH: usize = 400; const HEIGHT: usize = 200; pub fn main() { let stops = [ GradientStop::new(0, [0x0000, 0x0000, 0x0000, 0x0000]), GradientStop::new(1, [0xffff, 0x0000, 0x1111, 0xffff]), ]; let p1 = Point::from((0f64, 0f64)); let p2 = Point::from((WIDTH as f64, 0f64)); let transform = Transform::new([ [Fixed::ONE, Fixed::ZERO, Fixed::ZERO], [Fixed::ZERO, Fixed::ONE, Fixed::ZERO], [Fixed::ZERO, Fixed::ZERO, Fixed::ONE], ]); let mut alpha = [0x4f00004fu32; WIDTH * HEIGHT]; /* pale blue */ let mut alpha_img = Image::from_slice_mut( FormatCode::A8R8G8B8, WIDTH, HEIGHT, &mut alpha, WIDTH * 4, false, ) .unwrap(); let mut dest = [0xffffff00u32; WIDTH * HEIGHT]; /* yellow */ let mut dest_img = Image::from_slice_mut( FormatCode::A8R8G8B8, WIDTH, HEIGHT, &mut dest, WIDTH * 4, false, ) .unwrap(); let mut src = [0xffff0000; WIDTH * HEIGHT]; let src_img = Image::from_slice_mut( FormatCode::A8R8G8B8, WIDTH, HEIGHT, &mut src, WIDTH * 4, false, ) .unwrap(); let mut grad_img = LinearGradient::new(p1, p2, &stops).unwrap(); grad_img.set_transform(transform).unwrap(); grad_img.set_repeat(Repeat::Pad); alpha_img.composite( Operation::Over, &grad_img, None, (0, 0), (0, 0), (0, 0), ((10 * WIDTH) as u16, HEIGHT as u16), ); let src_img = src_img.set_alpha_map(&alpha_img, 10, 10); dest_img.composite( Operation::Over, &src_img, None, (0, 0), (0, 0), (0, 0), ((10 * WIDTH) as u16, HEIGHT as u16), ); let mut out_img = Image::new( FormatCode::A8B8G8R8, dest_img.width(), dest_img.height(), false, ) .unwrap(); out_img.composite( Operation::Src, &dest_img, None, (0, 0), (0, 0), (0, 0), (dest_img.width() as u16, dest_img.height() as u16), ); let image_buffer = image::ImageBuffer::, _>::from_raw( out_img.width() as u32, out_img.height() as u32, unsafe { std::slice::from_raw_parts( out_img.data() as *const u8, out_img.stride() * out_img.height(), ) }, ) .unwrap(); image_buffer .save_with_format("out.png", image::ImageFormat::Png) .unwrap(); } pixman-0.2.1/examples/checkerboard.rs000064400000000000000000000051611046102023000157230ustar 00000000000000use pixman::{Color, Filter, FormatCode, Image, Operation, Repeat, Solid}; const WIDTH: usize = 400; const HEIGHT: usize = 400; const TILE_SIZE: usize = 25; pub fn main() { let mut checkerboard = Image::new(FormatCode::A8R8G8B8, WIDTH, HEIGHT, false).unwrap(); let mut destination = Image::new(FormatCode::A8R8G8B8, WIDTH, HEIGHT, false).unwrap(); // let transform = Transform::new([ // [-1.96830, -1.82250, 512.12250], // [0.00000, -7.29000, 1458.00000], // [0.00000, -0.00911, 0.59231], // ]); for i in 0..(HEIGHT / TILE_SIZE) { for j in 0..(WIDTH / TILE_SIZE) { let u = (j + 1) as f64 / (WIDTH / TILE_SIZE) as f64; let v = (i + 1) as f64 / (HEIGHT / TILE_SIZE) as f64; let black = Color::new(0, 0, 0, 0xffff); let white = Color::new( (v * 0xffff as f64) as u16, (u * 0xffff as f64) as u16, ((1.0 - u) * 0xffff as f64) as u16, 0xffff, ); let c = if (j & 1) != (i & 1) { black } else { white }; let fill = Solid::new(c).unwrap(); checkerboard.composite( Operation::Src, &fill, None, (0, 0), (0, 0), ((j * TILE_SIZE) as i16, (i * TILE_SIZE) as i16), (TILE_SIZE as u16, TILE_SIZE as u16), ); } } // NOTE: The transform from the original demo completely breaks the image // checkerboard.set_transform(transform).unwrap(); checkerboard.set_filter(Filter::Best, &[]).unwrap(); checkerboard.set_repeat(Repeat::None); destination.composite( Operation::Src, &checkerboard, None, (0, 0), (0, 0), (0, 0), (WIDTH as u16, HEIGHT as u16), ); let mut out_img = Image::new( FormatCode::A8B8G8R8, destination.width(), destination.height(), false, ) .unwrap(); out_img.composite( Operation::Src, &destination, None, (0, 0), (0, 0), (0, 0), (destination.width() as u16, destination.height() as u16), ); let image_buffer = image::ImageBuffer::, _>::from_raw( out_img.width() as u32, out_img.height() as u32, unsafe { std::slice::from_raw_parts( out_img.data() as *const u8, out_img.stride() * out_img.height(), ) }, ) .unwrap(); image_buffer .save_with_format("out.png", image::ImageFormat::Png) .unwrap(); } pixman-0.2.1/examples/clip.rs000064400000000000000000000050371046102023000142400ustar 00000000000000use pixman::{ Fixed, FormatCode, GradientStop, Image, Operation, Point, RadialGradient, Region32, Repeat, Transform, }; const WIDTH: usize = 200; const HEIGHT: usize = 200; pub fn main() { let stops = [ GradientStop::new(0, [0xffff, 0x0000, 0x0000, 0xffff]), GradientStop::new(1, [0xffff, 0xffff, 0x0000, 0xffff]), ]; let trans = Transform::new([[1.3, 0.0, -0.5], [0.0, 1.0, -0.5], [0.0, 0.0, 1.0]]); let c_inner = Point::from((100.0, 100.0)); let c_outer = Point::from((100.0, 100.0)); let r_inner = Fixed::from(0); let r_outer = Fixed::from(100.0); let mut src = [0xff0000ffu32; WIDTH * HEIGHT]; let mut src_img = Image::from_slice_mut( FormatCode::A8R8G8B8, WIDTH, HEIGHT, &mut src, WIDTH * 4, false, ) .unwrap(); let gradient_img = RadialGradient::new(c_inner, c_outer, r_inner, r_outer, &stops).unwrap(); src_img.composite( Operation::Over, &gradient_img, None, (0, 0), (0, 0), (0, 0), (WIDTH as u16, HEIGHT as u16), ); let clip_region = Region32::init_rect(50, 0, 100, 200); src_img.set_clip_region32(Some(&clip_region)).unwrap(); src_img.set_source_clipping(true); src_img.set_has_client_clip(true); src_img.set_transform(trans).unwrap(); src_img.set_repeat(Repeat::Normal); let mut dst = [0xffff0000u32; WIDTH * HEIGHT]; let mut dst_img = Image::from_slice_mut( FormatCode::A8R8G8B8, WIDTH, HEIGHT, &mut dst, WIDTH * 4, false, ) .unwrap(); dst_img.composite( Operation::Over, &src_img, None, (0, 0), (0, 0), (0, 0), (WIDTH as u16, HEIGHT as u16), ); let mut out_img = Image::new( FormatCode::A8B8G8R8, dst_img.width(), dst_img.height(), false, ) .unwrap(); out_img.composite( Operation::Src, &dst_img, None, (0, 0), (0, 0), (0, 0), (dst_img.width() as u16, dst_img.height() as u16), ); let image_buffer = image::ImageBuffer::, _>::from_raw( out_img.width() as u32, out_img.height() as u32, unsafe { std::slice::from_raw_parts( out_img.data() as *const u8, out_img.stride() * out_img.height(), ) }, ) .unwrap(); image_buffer .save_with_format("out.png", image::ImageFormat::Png) .unwrap(); } pixman-0.2.1/examples/conical.rs000064400000000000000000000064011046102023000147150ustar 00000000000000use pixman::{ ConicalGradient, FormatCode, GradientStop, Image, Operation, Repeat, Solid, Transform, }; const SIZE: usize = 128; const GRADIENTS_PER_ROW: usize = 7; const NUM_ROWS: usize = (NUM_GRADIENTS + GRADIENTS_PER_ROW - 1) / GRADIENTS_PER_ROW; const WIDTH: usize = SIZE * GRADIENTS_PER_ROW; const HEIGHT: usize = SIZE * NUM_ROWS; const NUM_GRADIENTS: usize = 35; pub fn main() { let mut dest_img = Image::new(FormatCode::A8R8G8B8, WIDTH, HEIGHT, false).unwrap(); draw_checkerboard(&mut dest_img, 25, 0xffaaaaaa, 0xff888888); let transform = Transform::identity() .translate(0.5, 0.5, true) .unwrap() .scale(SIZE as f32, SIZE as f32, true) .unwrap() .translate(0.5, 0.5, true) .unwrap(); for i in 0..NUM_GRADIENTS { let column = i % GRADIENTS_PER_ROW; let row = i / GRADIENTS_PER_ROW; let mut src_img = create_conical(i); src_img.set_repeat(Repeat::Normal); src_img.set_transform(transform).unwrap(); dest_img.composite32( Operation::Over, &src_img, None, (0, 0), (0, 0), ((column * SIZE) as i32, (row * SIZE) as i32), (SIZE as i32, SIZE as i32), ); } let mut out_img = Image::new( FormatCode::A8B8G8R8, dest_img.width(), dest_img.height(), false, ) .unwrap(); out_img.composite( Operation::Src, &dest_img, None, (0, 0), (0, 0), (0, 0), (dest_img.width() as u16, dest_img.height() as u16), ); let image_buffer = image::ImageBuffer::, _>::from_raw( out_img.width() as u32, out_img.height() as u32, unsafe { std::slice::from_raw_parts( out_img.data() as *const u8, out_img.stride() * out_img.height(), ) }, ) .unwrap(); image_buffer .save_with_format("out.png", image::ImageFormat::Png) .unwrap(); } fn create_conical(index: usize) -> ConicalGradient<'static> { let angle = (0.5 / NUM_GRADIENTS as f64 + index as f64 / NUM_GRADIENTS as f64) * 720.0 - 180.0; ConicalGradient::new( (0.0, 0.0), angle, &[ GradientStop::new(0.25, [1.0, 0.0, 0.0, 0.7]), GradientStop::new(0.5, [1.0, 1.0, 0.0, 0.7]), GradientStop::new(0.75, [0.0, 1.0, 0.0, 0.7]), GradientStop::new(1.0, [0.0, 0.0, 1.0, 0.7]), ], ) .unwrap() } fn draw_checkerboard(image: &mut Image<'_, '_>, check_size: usize, color1: u32, color2: u32) { let c1 = Solid::new(color1).unwrap(); let c2 = Solid::new(color2).unwrap(); let n_checks_x = (image.width() + check_size - 1) / check_size; let n_checks_y = (image.height() + check_size - 1) / check_size; for j in 0..n_checks_y { for i in 0..n_checks_x { let src = if ((i ^ j) & 1) == 1 { &c1 } else { &c2 }; image.composite32( Operation::Src, src, None, (0, 0), (0, 0), ((i * check_size) as i32, (j * check_size) as i32), (check_size as i32, check_size as i32), ); } } } pixman-0.2.1/examples/fill.rs000064400000000000000000000013111046102023000142260ustar 00000000000000use pixman::FormatCode; const WIDTH: usize = 200; const HEIGHT: usize = 200; pub fn main() { let mut bits = [0u32; WIDTH * HEIGHT]; pixman::fill( &mut bits, WIDTH as u32, FormatCode::bpp(FormatCode::A8R8G8B8), 0, 0, WIDTH as u32, HEIGHT as u32, 0xff000000, // ABGR ) .unwrap(); let bits = unsafe { std::slice::from_raw_parts_mut(&mut bits as *mut _ as *mut _, bits.len() * 4) }; let image_buffer = image::ImageBuffer::, _>::from_raw(WIDTH as u32, HEIGHT as u32, bits) .unwrap(); image_buffer .save_with_format("out.png", image::ImageFormat::Png) .unwrap(); } pixman-0.2.1/examples/gradient.rs000064400000000000000000000036701046102023000151070ustar 00000000000000use pixman::{ Fixed, FormatCode, GradientStop, Image, LinearGradient, Operation, Point, Repeat, Transform, }; const WIDTH: usize = 400; const HEIGHT: usize = 200; pub fn main() { let stops = [ GradientStop::new(0, [0x0000, 0x0000, 0xffff, 0xffff]), GradientStop::new(1, [0xffff, 0x1111, 0x1111, 0xffff]), ]; let p1 = Point::from((50f64, 0f64)); let p2 = Point::from((200f64, 0f64)); let transform = Transform::new([ [Fixed::ONE, Fixed::ZERO, Fixed::ZERO], [Fixed::ZERO, Fixed::ONE, Fixed::ZERO], [Fixed::ZERO, Fixed::ZERO, Fixed::ONE], ]); let mut dest = [0xff00ff00u32; WIDTH * HEIGHT]; let mut dest_img = Image::from_slice_mut( FormatCode::A8R8G8B8, WIDTH, HEIGHT, &mut dest, WIDTH * 4, false, ) .unwrap(); let mut src_img = LinearGradient::new(p1, p2, &stops).unwrap(); src_img.set_transform(transform).unwrap(); src_img.set_repeat(Repeat::None); dest_img.composite( Operation::Over, &src_img, None, (0, 0), (0, 0), (0, 0), ((10 * WIDTH) as u16, HEIGHT as u16), ); let mut out_img = Image::new( FormatCode::A8B8G8R8, dest_img.width(), dest_img.height(), false, ) .unwrap(); out_img.composite( Operation::Src, &dest_img, None, (0, 0), (0, 0), (0, 0), (dest_img.width() as u16, dest_img.height() as u16), ); let image_buffer = image::ImageBuffer::, _>::from_raw( out_img.width() as u32, out_img.height() as u32, unsafe { std::slice::from_raw_parts( out_img.data() as *const u8, out_img.stride() * out_img.height(), ) }, ) .unwrap(); image_buffer .save_with_format("out.png", image::ImageFormat::Png) .unwrap(); } pixman-0.2.1/examples/solid_fill.rs000064400000000000000000000021611046102023000154240ustar 00000000000000use pixman::{FormatCode, Image, Operation, Repeat, Solid}; pub fn main() { let mut dst = Image::new(FormatCode::A8R8G8B8, 800, 600, true).unwrap(); let mut solid = Solid::new([0xffff, 0xffff, 0xffff, 0xffff]).unwrap(); solid.set_repeat(Repeat::Normal); dst.composite( Operation::Over, &solid, None, (0, 0), (0, 0), (50, 0), (50, 50), ); let mut out_img = Image::new(FormatCode::A8B8G8R8, dst.width(), dst.height(), false).unwrap(); out_img.composite( Operation::Src, &dst, None, (0, 0), (0, 0), (0, 0), (dst.width() as u16, dst.height() as u16), ); let image_buffer = image::ImageBuffer::, _>::from_raw( out_img.width() as u32, out_img.height() as u32, unsafe { std::slice::from_raw_parts( out_img.data() as *const u8, out_img.stride() * out_img.height(), ) }, ) .unwrap(); image_buffer .save_with_format("out.png", image::ImageFormat::Png) .unwrap(); } pixman-0.2.1/examples/trap.rs000064400000000000000000000040621046102023000142540ustar 00000000000000use pixman::{Color, Fixed, FormatCode, Image, Operation, Solid, Span, Trap}; const WIDTH: usize = 200; const HEIGHT: usize = 200; pub fn main() { let white = Color::from([0x0000, 0xffff, 0x0000, 0xffff]); let mut mbits = [0u32; WIDTH * HEIGHT]; let mut bits = [0xffu8; WIDTH * HEIGHT * 4]; let bits = unsafe { std::slice::from_raw_parts_mut(&mut bits as *mut u8 as *mut u32, bits.len() / 4) }; let trap = Trap::new( Span::new( Fixed::from_int(50) + Fixed::from_raw(0x8000), Fixed::from_int(150) + Fixed::from_raw(0x8000), 30, ), Span::new( Fixed::from_int(50) + Fixed::from_raw(0x8000), Fixed::from_int(150) + Fixed::from_raw(0x8000), 150, ), ); let mut mask_img = Image::from_slice_mut(FormatCode::A8, WIDTH, HEIGHT, &mut mbits, WIDTH, false).unwrap(); let src_img = Solid::new(white).unwrap(); let mut dest_img = Image::from_slice_mut(FormatCode::A8R8G8B8, WIDTH, HEIGHT, bits, WIDTH * 4, false).unwrap(); mask_img.add_traps((0, 0), &[trap]); dest_img.composite( Operation::Over, &src_img, Some(&mask_img), (0, 0), (0, 0), (0, 0), (WIDTH as u16, HEIGHT as u16), ); let mut out_img = Image::new( FormatCode::A8B8G8R8, dest_img.width(), dest_img.height(), false, ) .unwrap(); out_img.composite( Operation::Src, &dest_img, None, (0, 0), (0, 0), (0, 0), (dest_img.width() as u16, dest_img.height() as u16), ); let image_buffer = image::ImageBuffer::, _>::from_raw( out_img.width() as u32, out_img.height() as u32, unsafe { std::slice::from_raw_parts( out_img.data() as *const u8, out_img.stride() * out_img.height(), ) }, ) .unwrap(); image_buffer .save_with_format("out.png", image::ImageFormat::Png) .unwrap(); } pixman-0.2.1/examples/tri.rs000064400000000000000000000034431046102023000141060ustar 00000000000000use pixman::{Color, FormatCode, Image, Operation, Solid, Triangle}; const WIDTH: usize = 200; const HEIGHT: usize = 200; pub fn main() { let tris = [ Triangle::from([(100, 100), (10, 50), (110, 10)]), Triangle::from([(100, 100), (150, 10), (200, 50)]), Triangle::from([(100, 100), (10, 170), (90, 175)]), Triangle::from([(100, 100), (170, 150), (120, 190)]), ]; let color = Color::new(0x4444, 0x4444, 0xffff, 0xffff); let mut bits = [0u32; WIDTH * HEIGHT]; for (i, item) in bits.iter_mut().enumerate().take(WIDTH * HEIGHT) { *item = ((i / HEIGHT) as u32) * 0x01010000; } let src_img = Solid::new(color).unwrap(); let mut dest_img = Image::from_slice_mut( FormatCode::A8R8G8B8, WIDTH, HEIGHT, &mut bits, WIDTH * 4, false, ) .unwrap(); dest_img.composite_triangles( Operation::AtopReverse, &src_img, FormatCode::A8, (200, 200), (-5, 5), &tris, ); let mut out_img = Image::new( FormatCode::A8B8G8R8, dest_img.width(), dest_img.height(), false, ) .unwrap(); out_img.composite( Operation::Src, &dest_img, None, (0, 0), (0, 0), (0, 0), (dest_img.width() as u16, dest_img.height() as u16), ); let image_buffer = image::ImageBuffer::, _>::from_raw( out_img.width() as u32, out_img.height() as u32, unsafe { std::slice::from_raw_parts( out_img.data() as *const u8, out_img.stride() * out_img.height(), ) }, ) .unwrap(); image_buffer .save_with_format("out.png", image::ImageFormat::Png) .unwrap(); } pixman-0.2.1/src/color.rs000064400000000000000000000062261046102023000134010ustar 00000000000000use pixman_sys as ffi; /// Rgba color in the range of [`u16::MIN`] to [`u16::MAX`] #[derive(Debug, Clone, Copy)] #[repr(transparent)] pub struct Color(ffi::pixman_color_t); impl Color { /// Create a [`Color`] from the provided components /// /// Note: Color component range of [`u16::MIN`] to [`u16::MAX`] #[inline] pub fn new(r: u16, g: u16, b: u16, a: u16) -> Self { Self(ffi::pixman_color_t { red: r, green: g, blue: b, alpha: a, }) } /// Create a [`Color`] from the provided components /// /// Note: Color component range of `0f32` to `1f32` #[inline] pub fn from_f32(r: f32, g: f32, b: f32, a: f32) -> Self { Self::from_f64(r as f64, g as f64, b as f64, a as f64) } /// Create a [`Color`] from the provided components /// /// Note: Color component range of `0f64` to `1f64` #[inline] pub fn from_f64(r: f64, g: f64, b: f64, a: f64) -> Self { Self(ffi::pixman_color_t { red: double_to_color(r), green: double_to_color(g), blue: double_to_color(b), alpha: double_to_color(a), }) } /// Create a [`Color`] from the provided color value #[inline] pub fn from_u32(color8: u32) -> Self { let alpha = (color8 & 0xff000000) >> 24; let red = (color8 & 0x00ff0000) >> 16; let green = (color8 & 0x0000ff00) >> 8; let blue = color8 & 0x000000ff; let alpha = alpha | alpha << 8; let red = red | red << 8; let green = green | green << 8; let blue = blue | blue << 8; Self::new(red as u16, green as u16, blue as u16, alpha as u16) } /// Get the red color component #[inline] pub fn r(&self) -> u16 { self.0.red } /// Get the green color component #[inline] pub fn g(&self) -> u16 { self.0.green } /// Get the blue color component #[inline] pub fn b(&self) -> u16 { self.0.blue } /// Get the alpha color component #[inline] pub fn a(&self) -> u16 { self.0.alpha } #[inline] pub(crate) fn as_ptr(&self) -> *const ffi::pixman_color_t { &self.0 as *const _ } } impl From for Color { #[inline] fn from(value: ffi::pixman_color_t) -> Self { Self(value) } } impl From for ffi::pixman_color_t { #[inline] fn from(value: Color) -> Self { value.0 } } impl From<[u16; 4]> for Color { #[inline] fn from(value: [u16; 4]) -> Self { Self::new(value[0], value[1], value[2], value[3]) } } impl From<[f32; 4]> for Color { #[inline] fn from(value: [f32; 4]) -> Self { Self::from_f32(value[0], value[1], value[2], value[3]) } } impl From<[f64; 4]> for Color { #[inline] fn from(value: [f64; 4]) -> Self { Self::from_f64(value[0], value[1], value[2], value[3]) } } impl From for Color { #[inline] fn from(value: u32) -> Self { Self::from_u32(value) } } #[inline] fn double_to_color(x: f64) -> u16 { (((x * 65536.0) as u32) - (((x * 65536.0) as u32) >> 16)) as u16 } pixman-0.2.1/src/dither.rs000064400000000000000000000034731046102023000135430ustar 00000000000000use pixman_sys as ffi; use thiserror::Error; /// Defiens the possible dither operations #[derive(Debug, Clone, Copy)] pub enum Dither { /// No dithering None, /// Fast dithering Fast, /// Good dithering Good, /// Best dithering Best, /// Ordered bayer 8 dithering OrderedBayer8, /// Ordered blue noise 64 OrderedBlueNoise64, } /// The dither operation is unknown #[derive(Debug, Error)] #[error("Unknown dither {0}")] pub struct UnknownDither(ffi::pixman_dither_t); impl TryFrom for Dither { type Error = UnknownDither; fn try_from(value: ffi::pixman_dither_t) -> Result { let repeat = match value { ffi::pixman_dither_t_PIXMAN_DITHER_NONE => Dither::None, ffi::pixman_dither_t_PIXMAN_DITHER_FAST => Dither::Fast, ffi::pixman_dither_t_PIXMAN_DITHER_GOOD => Dither::Good, ffi::pixman_dither_t_PIXMAN_DITHER_BEST => Dither::Best, ffi::pixman_dither_t_PIXMAN_DITHER_ORDERED_BAYER_8 => Dither::OrderedBayer8, ffi::pixman_dither_t_PIXMAN_DITHER_ORDERED_BLUE_NOISE_64 => Dither::OrderedBlueNoise64, _ => return Err(UnknownDither(value)), }; Ok(repeat) } } impl From for ffi::pixman_dither_t { fn from(value: Dither) -> Self { match value { Dither::None => ffi::pixman_dither_t_PIXMAN_DITHER_NONE, Dither::Fast => ffi::pixman_dither_t_PIXMAN_DITHER_FAST, Dither::Good => ffi::pixman_dither_t_PIXMAN_DITHER_GOOD, Dither::Best => ffi::pixman_dither_t_PIXMAN_DITHER_BEST, Dither::OrderedBayer8 => ffi::pixman_dither_t_PIXMAN_DITHER_ORDERED_BAYER_8, Dither::OrderedBlueNoise64 => ffi::pixman_dither_t_PIXMAN_DITHER_ORDERED_BLUE_NOISE_64, } } } pixman-0.2.1/src/edge.rs000064400000000000000000000040351046102023000131630ustar 00000000000000use std::{mem::MaybeUninit, os::raw::c_int}; use crate::{ffi, Fixed, Line}; /// Defines a single edge #[derive(Debug, Clone, Copy)] #[repr(transparent)] pub struct Edge(ffi::pixman_edge_t); impl Edge { /// Create a edge from the provided values pub fn new( bpp: i32, y_start: impl Into, x_top: impl Into, y_top: impl Into, x_bot: impl Into, y_bot: impl Into, ) -> Self { let mut edge = MaybeUninit::uninit(); unsafe { ffi::pixman_edge_init( edge.as_mut_ptr(), bpp, y_start.into().into_raw(), x_top.into().into_raw(), y_top.into().into_raw(), x_bot.into().into_raw(), y_bot.into().into_raw(), ); } Self(unsafe { edge.assume_init() }) } /// Initialize one edge structure given a line, starting y value /// and a pixel offset for the line pub fn from_line( bpp: isize, y: impl Into, line: impl Into, x_off: i32, y_off: i32, ) -> Self { let mut edge = MaybeUninit::uninit(); unsafe { ffi::pixman_line_fixed_edge_init( edge.as_mut_ptr(), bpp as c_int, y.into().into_raw(), line.into().as_ptr(), x_off, y_off, ) } Self(unsafe { edge.assume_init() }) } /// Step an edge by any amount (including negative values) pub fn step(&mut self, n: i32) { unsafe { ffi::pixman_edge_step(&mut self.0, n); } } #[inline] pub(crate) fn as_ptr(&self) -> *const ffi::pixman_edge_t { &self.0 } } impl From for Edge { #[inline] fn from(value: ffi::pixman_edge_t) -> Self { Self(value) } } impl From for ffi::pixman_edge_t { #[inline] fn from(value: Edge) -> Self { value.0 } } pixman-0.2.1/src/filter.rs000064400000000000000000000041371046102023000135470ustar 00000000000000use pixman_sys as ffi; use thiserror::Error; /// Defines the possible filter operations #[derive(Debug, Clone, Copy)] pub enum Filter { /// Fast filtering Fast, /// Good filtering Good, /// Best filtering Best, /// Nearest-neighbor filtering Nearest, /// Bilinear filtering Bilinear, /// Custom convolution kernel Convolution, /// Custom separable convolution kernel SeparableConvolution, } /// The filter operation is unknown #[derive(Debug, Error)] #[error("Unknown filter {0}")] pub struct UnknownFilter(ffi::pixman_dither_t); impl TryFrom for Filter { type Error = UnknownFilter; fn try_from(value: ffi::pixman_dither_t) -> Result { let repeat = match value { ffi::pixman_filter_t_PIXMAN_FILTER_FAST => Filter::Fast, ffi::pixman_filter_t_PIXMAN_FILTER_GOOD => Filter::Good, ffi::pixman_filter_t_PIXMAN_FILTER_BEST => Filter::Best, ffi::pixman_filter_t_PIXMAN_FILTER_NEAREST => Filter::Nearest, ffi::pixman_filter_t_PIXMAN_FILTER_BILINEAR => Filter::Bilinear, ffi::pixman_filter_t_PIXMAN_FILTER_CONVOLUTION => Filter::Convolution, ffi::pixman_filter_t_PIXMAN_FILTER_SEPARABLE_CONVOLUTION => { Filter::SeparableConvolution } _ => return Err(UnknownFilter(value)), }; Ok(repeat) } } impl From for ffi::pixman_dither_t { fn from(value: Filter) -> Self { match value { Filter::Fast => ffi::pixman_filter_t_PIXMAN_FILTER_FAST, Filter::Good => ffi::pixman_filter_t_PIXMAN_FILTER_GOOD, Filter::Best => ffi::pixman_filter_t_PIXMAN_FILTER_BEST, Filter::Nearest => ffi::pixman_filter_t_PIXMAN_FILTER_NEAREST, Filter::Bilinear => ffi::pixman_filter_t_PIXMAN_FILTER_BILINEAR, Filter::Convolution => ffi::pixman_filter_t_PIXMAN_FILTER_CONVOLUTION, Filter::SeparableConvolution => { ffi::pixman_filter_t_PIXMAN_FILTER_SEPARABLE_CONVOLUTION } } } } pixman-0.2.1/src/fixed.rs000064400000000000000000000027751046102023000133670ustar 00000000000000use pixman_sys as ffi; /// Fixed-point value #[derive(Debug, Clone, Copy)] #[repr(transparent)] pub struct Fixed(ffi::pixman_fixed_t); impl Fixed { /// One pub const ONE: Fixed = Fixed::from_int(1); /// Zero pub const ZERO: Fixed = Fixed::from_raw(0); /// Initialize this fixed-point from a raw value #[inline] pub const fn from_raw(value: ffi::pixman_fixed_t) -> Self { Self(value) } /// Initialize this fixed-point from an integer #[inline] pub const fn from_int(value: i32) -> Self { Self(((value as u32) << 16) as ffi::pixman_fixed_t) } /// Initialize this fixed-point from an `f64` #[inline] pub fn from_double(value: f64) -> Self { Self((value * 65536.0) as ffi::pixman_fixed_t) } /// Get the int value of this fixed point #[inline] pub const fn to_int(self) -> i32 { self.0 >> 16 } /// Access the raw fixed-point value #[inline] pub fn into_raw(self) -> ffi::pixman_fixed_t { self.0 } } impl std::ops::Add for Fixed { type Output = Fixed; fn add(self, rhs: Self) -> Self::Output { Self(self.0 + rhs.0) } } impl From for Fixed { #[inline] fn from(value: i32) -> Self { Self::from_int(value) } } impl From for Fixed { #[inline] fn from(value: f32) -> Self { Self::from_double(value as f64) } } impl From for Fixed { #[inline] fn from(value: f64) -> Self { Self::from_double(value) } } pixman-0.2.1/src/format.rs000064400000000000000000000361111046102023000135470ustar 00000000000000use pixman_sys as ffi; #[cfg(feature = "drm-fourcc")] use thiserror::Error; /// Possible format codes #[derive(Debug, Clone, Copy)] pub enum FormatCode { /// 128bpp RgbaFloat RgbaFloat, /// 96bpp RgbFloat RgbFloat, /// 32bpp A8R8G8B8 A8R8G8B8, /// 32bpp X8R8G8B8 X8R8G8B8, /// 32bpp A8B8G8R8 A8B8G8R8, /// 32bpp X8B8G8R8 X8B8G8R8, /// 32bpp B8G8R8A8 B8G8R8A8, /// 32bpp B8G8R8X8 B8G8R8X8, /// 32bpp R8G8B8A8 R8G8B8A8, /// 32bpp R8G8B8X8 R8G8B8X8, /// 32bpp X14R6G6B6 X14R6G6B6, /// 32bpp X2R10G10B10 X2R10G10B10, /// 32bpp A2R10G10B10 A2R10G10B10, /// 32bpp X2B10G10R10 X2B10G10R10, /// 32bpp A2B10G10R10 A2B10G10R10, /// sRGB A8R8G8B8sRGB A8R8G8B8sRGB, /// 24bpp R8G8B8 R8G8B8, /// 24bpp B8G8R8 B8G8R8, /// 16bpp R5G6B5 R5G6B5, /// 16bpp B5G6R5 B5G6R5, /// 16bpp A1R5G5B5 A1R5G5B5, /// 16bpp X1R5G5B5 X1R5G5B5, /// 16bpp A1B5G5R5 A1B5G5R5, /// 16bpp X1B5G5R5 X1B5G5R5, /// 16bpp A4R4G4B4 A4R4G4B4, /// 16bpp X4R4G4B4 X4R4G4B4, /// 16bpp A4B4G4R4 A4B4G4R4, /// 16bpp X4B4G4R4 X4B4G4R4, /// 8bpp A8 A8, /// 8bpp R3G3B2 R3G3B2, /// 8bpp B2G3R3 B2G3R3, /// 8bpp A2R2G2B2 A2R2G2B2, /// 8bpp A2B2G2R2 A2B2G2R2, /// 8bpp C8 C8, /// 8bpp G8 G8, /// 8bpp X4A4 X4A4, /// 8bpp X4C4 X4C4, /// 8bpp X4G4 X4G4, /// 4bpp A4 A4, /// 4bpp R1G2B1 R1G2B1, /// 4bpp B1G2R1 B1G2R1, /// 4bpp A1R1G1B1 A1R1G1B1, /// 4bpp A1B1G1R1 A1B1G1R1, /// 4bpp C4 C4, /// 4bpp G4 G4, /// 1bpp A1 A1, /// 1bpp G1 G1, /// YUV YUY2 YUY2, /// YUV YV12 YV12, } impl FormatCode { /// Get the bpp for the specified format pub fn bpp(code: Self) -> u32 { let val = Into::::into(code); let ofs = 24; let num = 8; ((val >> (ofs)) & ((1 << (num)) - 1)) << ((val >> 22) & 3) } } impl From for FormatCode { fn from(value: ffi::pixman_format_code_t) -> Self { match value { ffi::pixman_format_code_t_PIXMAN_rgba_float => FormatCode::RgbaFloat, ffi::pixman_format_code_t_PIXMAN_rgb_float => FormatCode::RgbFloat, ffi::pixman_format_code_t_PIXMAN_a8r8g8b8 => FormatCode::A8R8G8B8, ffi::pixman_format_code_t_PIXMAN_x8r8g8b8 => FormatCode::X8R8G8B8, ffi::pixman_format_code_t_PIXMAN_a8b8g8r8 => FormatCode::A8B8G8R8, ffi::pixman_format_code_t_PIXMAN_x8b8g8r8 => FormatCode::X8B8G8R8, ffi::pixman_format_code_t_PIXMAN_b8g8r8a8 => FormatCode::B8G8R8A8, ffi::pixman_format_code_t_PIXMAN_b8g8r8x8 => FormatCode::B8G8R8X8, ffi::pixman_format_code_t_PIXMAN_r8g8b8a8 => FormatCode::R8G8B8A8, ffi::pixman_format_code_t_PIXMAN_r8g8b8x8 => FormatCode::R8G8B8X8, ffi::pixman_format_code_t_PIXMAN_x14r6g6b6 => FormatCode::X14R6G6B6, ffi::pixman_format_code_t_PIXMAN_x2r10g10b10 => FormatCode::X2R10G10B10, ffi::pixman_format_code_t_PIXMAN_a2r10g10b10 => FormatCode::A2R10G10B10, ffi::pixman_format_code_t_PIXMAN_x2b10g10r10 => FormatCode::X2B10G10R10, ffi::pixman_format_code_t_PIXMAN_a2b10g10r10 => FormatCode::A2B10G10R10, ffi::pixman_format_code_t_PIXMAN_a8r8g8b8_sRGB => FormatCode::A8R8G8B8sRGB, ffi::pixman_format_code_t_PIXMAN_r8g8b8 => FormatCode::R8G8B8, ffi::pixman_format_code_t_PIXMAN_b8g8r8 => FormatCode::B8G8R8, ffi::pixman_format_code_t_PIXMAN_r5g6b5 => FormatCode::R5G6B5, ffi::pixman_format_code_t_PIXMAN_b5g6r5 => FormatCode::B5G6R5, ffi::pixman_format_code_t_PIXMAN_a1r5g5b5 => FormatCode::A1R5G5B5, ffi::pixman_format_code_t_PIXMAN_x1r5g5b5 => FormatCode::X1R5G5B5, ffi::pixman_format_code_t_PIXMAN_a1b5g5r5 => FormatCode::A1B5G5R5, ffi::pixman_format_code_t_PIXMAN_x1b5g5r5 => FormatCode::X1B5G5R5, ffi::pixman_format_code_t_PIXMAN_a4r4g4b4 => FormatCode::A4R4G4B4, ffi::pixman_format_code_t_PIXMAN_x4r4g4b4 => FormatCode::X4R4G4B4, ffi::pixman_format_code_t_PIXMAN_a4b4g4r4 => FormatCode::A4B4G4R4, ffi::pixman_format_code_t_PIXMAN_x4b4g4r4 => FormatCode::X4B4G4R4, ffi::pixman_format_code_t_PIXMAN_a8 => FormatCode::A8, ffi::pixman_format_code_t_PIXMAN_r3g3b2 => FormatCode::R3G3B2, ffi::pixman_format_code_t_PIXMAN_b2g3r3 => FormatCode::B2G3R3, ffi::pixman_format_code_t_PIXMAN_a2r2g2b2 => FormatCode::A2R2G2B2, ffi::pixman_format_code_t_PIXMAN_a2b2g2r2 => FormatCode::A2B2G2R2, ffi::pixman_format_code_t_PIXMAN_c8 => FormatCode::C8, ffi::pixman_format_code_t_PIXMAN_g8 => FormatCode::G8, ffi::pixman_format_code_t_PIXMAN_x4a4 => FormatCode::X4A4, // NOTE: These format codes are identical to c8 and g8, respectively // ffi::pixman_format_code_t_PIXMAN_x4c4 => FormatCode::X4C4, // ffi::pixman_format_code_t_PIXMAN_x4g4 => FormatCode::X4G4, ffi::pixman_format_code_t_PIXMAN_a4 => FormatCode::A4, ffi::pixman_format_code_t_PIXMAN_r1g2b1 => FormatCode::R1G2B1, ffi::pixman_format_code_t_PIXMAN_b1g2r1 => FormatCode::B1G2R1, ffi::pixman_format_code_t_PIXMAN_a1r1g1b1 => FormatCode::A1R1G1B1, ffi::pixman_format_code_t_PIXMAN_a1b1g1r1 => FormatCode::A1B1G1R1, ffi::pixman_format_code_t_PIXMAN_c4 => FormatCode::C4, ffi::pixman_format_code_t_PIXMAN_g4 => FormatCode::G4, ffi::pixman_format_code_t_PIXMAN_a1 => FormatCode::A1, ffi::pixman_format_code_t_PIXMAN_g1 => FormatCode::G1, ffi::pixman_format_code_t_PIXMAN_yuy2 => FormatCode::YUY2, ffi::pixman_format_code_t_PIXMAN_yv12 => FormatCode::YV12, _ => unreachable!(), } } } impl From for ffi::pixman_format_code_t { fn from(value: FormatCode) -> Self { match value { FormatCode::RgbaFloat => ffi::pixman_format_code_t_PIXMAN_rgba_float, FormatCode::RgbFloat => ffi::pixman_format_code_t_PIXMAN_rgb_float, FormatCode::A8R8G8B8 => ffi::pixman_format_code_t_PIXMAN_a8r8g8b8, FormatCode::X8R8G8B8 => ffi::pixman_format_code_t_PIXMAN_x8r8g8b8, FormatCode::A8B8G8R8 => ffi::pixman_format_code_t_PIXMAN_a8b8g8r8, FormatCode::X8B8G8R8 => ffi::pixman_format_code_t_PIXMAN_x8b8g8r8, FormatCode::B8G8R8A8 => ffi::pixman_format_code_t_PIXMAN_b8g8r8a8, FormatCode::B8G8R8X8 => ffi::pixman_format_code_t_PIXMAN_b8g8r8x8, FormatCode::R8G8B8A8 => ffi::pixman_format_code_t_PIXMAN_r8g8b8a8, FormatCode::R8G8B8X8 => ffi::pixman_format_code_t_PIXMAN_r8g8b8x8, FormatCode::X14R6G6B6 => ffi::pixman_format_code_t_PIXMAN_x14r6g6b6, FormatCode::X2R10G10B10 => ffi::pixman_format_code_t_PIXMAN_x2r10g10b10, FormatCode::A2R10G10B10 => ffi::pixman_format_code_t_PIXMAN_a2r10g10b10, FormatCode::X2B10G10R10 => ffi::pixman_format_code_t_PIXMAN_x2b10g10r10, FormatCode::A2B10G10R10 => ffi::pixman_format_code_t_PIXMAN_a2b10g10r10, FormatCode::A8R8G8B8sRGB => ffi::pixman_format_code_t_PIXMAN_a8r8g8b8_sRGB, FormatCode::R8G8B8 => ffi::pixman_format_code_t_PIXMAN_r8g8b8, FormatCode::B8G8R8 => ffi::pixman_format_code_t_PIXMAN_b8g8r8, FormatCode::R5G6B5 => ffi::pixman_format_code_t_PIXMAN_r5g6b5, FormatCode::B5G6R5 => ffi::pixman_format_code_t_PIXMAN_b5g6r5, FormatCode::A1R5G5B5 => ffi::pixman_format_code_t_PIXMAN_a1r5g5b5, FormatCode::X1R5G5B5 => ffi::pixman_format_code_t_PIXMAN_x1r5g5b5, FormatCode::A1B5G5R5 => ffi::pixman_format_code_t_PIXMAN_a1b5g5r5, FormatCode::X1B5G5R5 => ffi::pixman_format_code_t_PIXMAN_x1b5g5r5, FormatCode::A4R4G4B4 => ffi::pixman_format_code_t_PIXMAN_a4r4g4b4, FormatCode::X4R4G4B4 => ffi::pixman_format_code_t_PIXMAN_x4r4g4b4, FormatCode::A4B4G4R4 => ffi::pixman_format_code_t_PIXMAN_a4b4g4r4, FormatCode::X4B4G4R4 => ffi::pixman_format_code_t_PIXMAN_x4b4g4r4, FormatCode::A8 => ffi::pixman_format_code_t_PIXMAN_a8, FormatCode::R3G3B2 => ffi::pixman_format_code_t_PIXMAN_r3g3b2, FormatCode::B2G3R3 => ffi::pixman_format_code_t_PIXMAN_b2g3r3, FormatCode::A2R2G2B2 => ffi::pixman_format_code_t_PIXMAN_a2r2g2b2, FormatCode::A2B2G2R2 => ffi::pixman_format_code_t_PIXMAN_a2b2g2r2, FormatCode::C8 => ffi::pixman_format_code_t_PIXMAN_c8, FormatCode::G8 => ffi::pixman_format_code_t_PIXMAN_g8, FormatCode::X4A4 => ffi::pixman_format_code_t_PIXMAN_x4a4, FormatCode::X4C4 => ffi::pixman_format_code_t_PIXMAN_x4c4, FormatCode::X4G4 => ffi::pixman_format_code_t_PIXMAN_x4g4, FormatCode::A4 => ffi::pixman_format_code_t_PIXMAN_a4, FormatCode::R1G2B1 => ffi::pixman_format_code_t_PIXMAN_r1g2b1, FormatCode::B1G2R1 => ffi::pixman_format_code_t_PIXMAN_b1g2r1, FormatCode::A1R1G1B1 => ffi::pixman_format_code_t_PIXMAN_a1r1g1b1, FormatCode::A1B1G1R1 => ffi::pixman_format_code_t_PIXMAN_a1b1g1r1, FormatCode::C4 => ffi::pixman_format_code_t_PIXMAN_c4, FormatCode::G4 => ffi::pixman_format_code_t_PIXMAN_g4, FormatCode::A1 => ffi::pixman_format_code_t_PIXMAN_a1, FormatCode::G1 => ffi::pixman_format_code_t_PIXMAN_g1, FormatCode::YUY2 => ffi::pixman_format_code_t_PIXMAN_yuy2, FormatCode::YV12 => ffi::pixman_format_code_t_PIXMAN_yv12, } } } /// The provided drm-fourcc has no matching format code #[cfg(feature = "drm-fourcc")] #[derive(Debug, Error)] #[error("Unsupported drm fourcc {0}")] pub struct UnsupportedDrmFourcc(drm_fourcc::DrmFourcc); #[cfg(feature = "drm-fourcc")] impl TryFrom for FormatCode { type Error = UnsupportedDrmFourcc; fn try_from(value: drm_fourcc::DrmFourcc) -> Result { use drm_fourcc::DrmFourcc; let format = match value { #[cfg(target_endian = "little")] DrmFourcc::Rgb565 => FormatCode::R5G6B5, #[cfg(target_endian = "little")] DrmFourcc::Xrgb8888 => FormatCode::X8R8G8B8, #[cfg(target_endian = "big")] DrmFourcc::Xrgb8888 => FormatCode::B8G8R8X8, #[cfg(target_endian = "little")] DrmFourcc::Argb8888 => FormatCode::A8R8G8B8, #[cfg(target_endian = "big")] DrmFourcc::Argb8888 => FormatCode::B8G8R8A8, #[cfg(target_endian = "little")] DrmFourcc::Xbgr8888 => FormatCode::X8B8G8R8, #[cfg(target_endian = "big")] DrmFourcc::Xbgr8888 => FormatCode::R8G8B8X8, #[cfg(target_endian = "little")] DrmFourcc::Abgr8888 => FormatCode::A8B8G8R8, #[cfg(target_endian = "big")] DrmFourcc::Abgr8888 => FormatCode::R8G8B8A8, #[cfg(target_endian = "little")] DrmFourcc::Rgbx8888 => FormatCode::R8G8B8X8, #[cfg(target_endian = "big")] DrmFourcc::Rgbx8888 => FormatCode::X8B8G8R8, #[cfg(target_endian = "little")] DrmFourcc::Rgba8888 => FormatCode::R8G8B8A8, #[cfg(target_endian = "big")] DrmFourcc::Rgba8888 => FormatCode::A8B8G8R8, #[cfg(target_endian = "little")] DrmFourcc::Bgrx8888 => FormatCode::B8G8R8X8, #[cfg(target_endian = "big")] DrmFourcc::Bgrx8888 => FormatCode::X8R8G8B8, #[cfg(target_endian = "little")] DrmFourcc::Bgra8888 => FormatCode::B8G8R8A8, #[cfg(target_endian = "big")] DrmFourcc::Bgra8888 => FormatCode::A8R8G8B8, #[cfg(target_endian = "little")] DrmFourcc::Xrgb2101010 => FormatCode::X2R10G10B10, #[cfg(target_endian = "little")] DrmFourcc::Argb2101010 => FormatCode::A2R10G10B10, #[cfg(target_endian = "little")] DrmFourcc::Xbgr2101010 => FormatCode::X2B10G10R10, #[cfg(target_endian = "little")] DrmFourcc::Abgr2101010 => FormatCode::A2B10G10R10, other => return Err(UnsupportedDrmFourcc(other)), }; Ok(format) } } /// The provided format code has no matching drm-fourcc #[cfg(feature = "drm-fourcc")] #[derive(Debug, Error)] #[error("Unsupported format code {0:?}")] pub struct UnsupportedFormatCode(FormatCode); #[cfg(feature = "drm-fourcc")] impl TryFrom for drm_fourcc::DrmFourcc { type Error = UnsupportedFormatCode; fn try_from(value: FormatCode) -> Result { use drm_fourcc::DrmFourcc; let format = match value { #[cfg(target_endian = "little")] FormatCode::R5G6B5 => DrmFourcc::Rgb565, #[cfg(target_endian = "little")] FormatCode::X8R8G8B8 => DrmFourcc::Xrgb8888, #[cfg(target_endian = "big")] FormatCode::B8G8R8X8 => DrmFourcc::Xrgb8888, #[cfg(target_endian = "little")] FormatCode::A8R8G8B8 => DrmFourcc::Argb8888, #[cfg(target_endian = "big")] FormatCode::B8G8R8A8 => DrmFourcc::Argb8888, #[cfg(target_endian = "little")] FormatCode::X8B8G8R8 => DrmFourcc::Xbgr8888, #[cfg(target_endian = "big")] FormatCode::R8G8B8X8 => DrmFourcc::Xbgr8888, #[cfg(target_endian = "little")] FormatCode::A8B8G8R8 => DrmFourcc::Abgr8888, #[cfg(target_endian = "big")] FormatCode::R8G8B8A8 => DrmFourcc::Abgr8888, #[cfg(target_endian = "little")] FormatCode::R8G8B8X8 => DrmFourcc::Rgbx8888, #[cfg(target_endian = "big")] FormatCode::X8B8G8R8 => DrmFourcc::Rgbx8888, #[cfg(target_endian = "little")] FormatCode::R8G8B8A8 => DrmFourcc::Rgba8888, #[cfg(target_endian = "big")] FormatCode::A8B8G8R8 => DrmFourcc::Rgba8888, #[cfg(target_endian = "little")] FormatCode::B8G8R8X8 => DrmFourcc::Bgrx8888, #[cfg(target_endian = "big")] FormatCode::X8R8G8B8 => DrmFourcc::Bgrx8888, #[cfg(target_endian = "little")] FormatCode::B8G8R8A8 => DrmFourcc::Bgra8888, #[cfg(target_endian = "big")] FormatCode::A8R8G8B8 => DrmFourcc::Bgra8888, #[cfg(target_endian = "little")] FormatCode::X2R10G10B10 => DrmFourcc::Xrgb2101010, #[cfg(target_endian = "little")] FormatCode::A2R10G10B10 => DrmFourcc::Argb2101010, #[cfg(target_endian = "little")] FormatCode::X2B10G10R10 => DrmFourcc::Xbgr2101010, #[cfg(target_endian = "little")] FormatCode::A2B10G10R10 => DrmFourcc::Abgr2101010, other => return Err(UnsupportedFormatCode(other)), }; Ok(format) } } pixman-0.2.1/src/gradient_stop.rs000064400000000000000000000017701046102023000151240ustar 00000000000000use pixman_sys as ffi; use crate::{Color, Fixed}; /// Gradient-stop #[derive(Debug, Clone, Copy)] #[repr(transparent)] pub struct GradientStop(ffi::pixman_gradient_stop_t); impl GradientStop { /// Initialize the gradient stop from the provided valued #[inline] pub fn new(x: impl Into, color: impl Into) -> Self { Self(ffi::pixman_gradient_stop { x: x.into().into_raw(), color: color.into().into(), }) } /// Access the stop x value #[inline] pub fn x(&self) -> Fixed { Fixed::from_raw(self.0.x) } /// Access the stop color #[inline] pub fn color(&self) -> Color { Color::from(self.0.color) } } impl From for GradientStop { #[inline] fn from(value: ffi::pixman_gradient_stop_t) -> Self { Self(value) } } impl From for ffi::pixman_gradient_stop_t { #[inline] fn from(value: GradientStop) -> Self { value.0 } } pixman-0.2.1/src/image/bits.rs000064400000000000000000000334771046102023000143160ustar 00000000000000use std::{ffi::c_int, marker::PhantomData, mem::MaybeUninit}; use crate::{ ffi, Box32, Color, CreateFailed, Edge, Fixed, FormatCode, ImageRef, Operation, OperationFailed, Rectangle16, Region16, Trap, Trapezoid, Triangle, }; /// Image holding some pixel data #[derive(Debug)] pub struct Image<'bits, 'alpha> { image: ImageRef, _bits: PhantomData<&'bits ()>, _alpha: PhantomData<&'alpha ()>, } // SAFETY: A reference to the image is only created by `set_alpha_map`. // Which returns a type with a lifetime bound, so `&mut self` methods cannot // be called while this additional reference is in use. // // Thus the only mutability allowed is reference counting, which is made // thread-safe with the `REF_COUNT_LOCK` mutex, used when calling // `pixman_image_unref`, or `pixman_image_set_alpha_map`. #[cfg(feature = "sync")] unsafe impl Send for Image<'_, '_> {} #[cfg(feature = "sync")] unsafe impl Sync for Image<'_, '_> {} impl std::ops::Deref for Image<'_, '_> { type Target = ImageRef; fn deref(&self) -> &Self::Target { &self.image } } impl std::ops::DerefMut for Image<'_, '_> { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.image } } impl Image<'static, 'static> { /// Create a new image with the specified format and size pub fn new( format: FormatCode, width: usize, height: usize, clear: bool, ) -> Result { let ptr = if clear { unsafe { ffi::pixman_image_create_bits( format.into(), width as c_int, height as c_int, std::ptr::null_mut(), 0, ) } } else { unsafe { ffi::pixman_image_create_bits_no_clear( format.into(), width as c_int, height as c_int, std::ptr::null_mut(), 0, ) } }; if ptr.is_null() { Err(CreateFailed) } else { Ok(unsafe { Self::from_ptr(ptr) }) } } } impl<'bits> Image<'bits, 'static> { /// Create an image from some pre-allocated pixel data pub fn from_slice_mut( format: FormatCode, width: usize, height: usize, bits: &'bits mut [u32], rowstride_bytes: usize, clear: bool, ) -> Result { unsafe { Self::from_raw_mut( format, width, height, bits.as_mut_ptr(), rowstride_bytes, clear, ) } } /// Create an image from some pre-allocated pixel data pointer /// /// # Safety /// /// The caller is responsible to make sure the pointer stays /// valid for the lifetime of the created image. pub unsafe fn from_raw_mut( format: FormatCode, width: usize, height: usize, bits: *mut u32, rowstride_bytes: usize, clear: bool, ) -> Result { let ptr = if clear { unsafe { ffi::pixman_image_create_bits( format.into(), width as c_int, height as c_int, bits, rowstride_bytes as c_int, ) } } else { unsafe { ffi::pixman_image_create_bits_no_clear( format.into(), width as c_int, height as c_int, bits, rowstride_bytes as c_int, ) } }; if ptr.is_null() { Err(CreateFailed) } else { Ok(unsafe { Self::from_ptr(ptr) }) } } } impl<'bits, 'a> Image<'bits, 'a> { /// Set an alpha map that will be used when this image is /// used as a src in a blit operation pub fn set_alpha_map<'alpha: 'a>( self, alpha_map: &'alpha Image<'_, 'static>, x: i16, y: i16, ) -> Image<'bits, 'alpha> { #[cfg(feature = "sync")] let _lock = crate::REF_COUNT_LOCK.lock().unwrap(); unsafe { ffi::pixman_image_set_alpha_map(self.as_ptr(), alpha_map.as_ptr(), x, y); } Image { image: self.image, _bits: self._bits, _alpha: PhantomData, } } /// Clear a previously set alpha map pub fn clear_alpha_map(self) -> Image<'bits, 'static> { #[cfg(feature = "sync")] let _lock = crate::REF_COUNT_LOCK.lock().unwrap(); unsafe { ffi::pixman_image_set_alpha_map(self.as_ptr(), std::ptr::null_mut(), 0, 0); } Image { image: self.image, _bits: self._bits, _alpha: PhantomData, } } } impl Image<'_, '_> { /// Get the width of the image pub fn width(&self) -> usize { unsafe { ffi::pixman_image_get_width(self.as_ptr()) as usize } } /// Get the height of the image pub fn height(&self) -> usize { unsafe { ffi::pixman_image_get_height(self.as_ptr()) as usize } } /// Get the stride of the image pub fn stride(&self) -> usize { unsafe { ffi::pixman_image_get_stride(self.as_ptr()) as usize } } /// Get the depth of the image pub fn depth(&self) -> usize { unsafe { ffi::pixman_image_get_depth(self.as_ptr()) as usize } } /// Get the format of the image pub fn format(&self) -> FormatCode { let format = unsafe { ffi::pixman_image_get_format(self.as_ptr()) }; FormatCode::from(format) } /// Access the underlying pixel data /// /// # Safety /// /// The pointer is valid for the lifetime of the image pub unsafe fn data(&self) -> *mut u32 { unsafe { ffi::pixman_image_get_data(self.as_ptr()) } } /// Fill this image with the specified boxes and color pub fn fill_boxes( &mut self, op: Operation, color: impl Into, boxes: &[Box32], ) -> Result<(), OperationFailed> { let color = color.into(); let res = unsafe { ffi::pixman_image_fill_boxes( op.into(), self.as_ptr(), color.as_ptr(), boxes.len() as c_int, boxes.as_ptr(), ) }; if res == 1 { Ok(()) } else { Err(OperationFailed) } } /// Fill this image with the specified rectangles and color pub fn fill_rectangles( &mut self, op: Operation, color: impl Into, rects: &[Rectangle16], ) -> Result<(), OperationFailed> { let color = color.into(); let res = unsafe { ffi::pixman_image_fill_rectangles( op.into(), self.as_ptr(), color.as_ptr(), rects.len() as c_int, rects.as_ptr(), ) }; if res == 1 { Ok(()) } else { Err(OperationFailed) } } /// Composite the specified src image into this image #[allow(clippy::too_many_arguments)] pub fn composite( &mut self, operation: Operation, src: &ImageRef, mask: Option<&ImageRef>, src_loc: (i16, i16), mask_loc: (i16, i16), dest_loc: (i16, i16), size: (u16, u16), ) { let mask_ptr = if let Some(mask) = mask { mask.as_ptr() } else { std::ptr::null_mut() }; unsafe { ffi::pixman_image_composite( operation.into(), src.as_ptr(), mask_ptr, self.as_ptr(), src_loc.0, src_loc.1, mask_loc.0, mask_loc.1, dest_loc.0, dest_loc.1, size.0, size.1, ) } } /// Composite the specified src image into this image #[allow(clippy::too_many_arguments)] pub fn composite32( &mut self, operation: Operation, src: &ImageRef, mask: Option<&ImageRef>, src_loc: (i32, i32), mask_loc: (i32, i32), dest_loc: (i32, i32), size: (i32, i32), ) { let mask_ptr = if let Some(mask) = mask { mask.as_ptr() } else { std::ptr::null_mut() }; unsafe { ffi::pixman_image_composite32( operation.into(), src.as_ptr(), mask_ptr, self.as_ptr(), src_loc.0, src_loc.1, mask_loc.0, mask_loc.1, dest_loc.0, dest_loc.1, size.0, size.1, ) } } /// Composite the specified triangles into this image pub fn composite_triangles( &mut self, operation: Operation, src: &ImageRef, mask_format: FormatCode, src_loc: (i32, i32), dest_loc: (i32, i32), tris: &[Triangle], ) { unsafe { ffi::pixman_composite_triangles( operation.into(), src.as_ptr(), self.as_ptr(), mask_format.into(), src_loc.0, src_loc.1, dest_loc.0, dest_loc.1, tris.len() as i32, tris.as_ptr() as *const ffi::pixman_triangle_t, ); } } /// Composite the specified trapezoids into this image pub fn composite_trapezoids( &mut self, operation: Operation, src: &ImageRef, mask_format: FormatCode, src_loc: (i32, i32), dest_loc: (i32, i32), traps: &[Trapezoid], ) { unsafe { ffi::pixman_composite_trapezoids( operation.into(), src.as_ptr(), self.as_ptr(), mask_format.into(), src_loc.0, src_loc.1, dest_loc.0, dest_loc.1, traps.len() as i32, traps.as_ptr() as *const ffi::pixman_trapezoid_t, ); } } /// Add the specified traps to this image pub fn add_traps(&mut self, offset: (i16, i16), traps: &[Trap]) { unsafe { ffi::pixman_add_traps( self.as_ptr(), offset.0, offset.1, traps.len() as i32, traps.as_ptr() as *const ffi::pixman_trap_t, ); } } /// Add the specified trapezoids to this image pub fn add_trapezoids(&mut self, offset: (i16, i32), traps: &[Trapezoid]) { unsafe { ffi::pixman_add_trapezoids( self.as_ptr(), offset.0, offset.1, traps.len() as i32, traps.as_ptr() as *const _, ); } } /// Add the specified triangles to this image pub fn add_triangles(&mut self, offset: (i32, i32), tris: &[Triangle]) { unsafe { ffi::pixman_add_triangles( self.as_ptr(), offset.0, offset.1, tris.len() as i32, tris.as_ptr() as *const _, ); } } /// Compute the composite region for the specified src pub fn compute_composite_region( &self, src: &ImageRef, mask: Option<&ImageRef>, src_loc: (i16, i16), mask_loc: (i16, i16), dest_loc: (i16, i16), size: (u16, u16), ) -> Option { let mask_ptr = if let Some(mask) = mask { mask.as_ptr() } else { std::ptr::null_mut() }; let mut region = MaybeUninit::uninit(); let res = unsafe { ffi::pixman_compute_composite_region( region.as_mut_ptr(), src.as_ptr(), mask_ptr, self.as_ptr(), src_loc.0, src_loc.1, mask_loc.0, mask_loc.1, dest_loc.0, dest_loc.1, size.0, size.1, ) }; if res == 1 { Some(Region16::from(unsafe { region.assume_init() })) } else { None } } /// Rasterize the specified edges pub fn rasterize_edges(&mut self, l: Edge, r: Edge, t: impl Into, b: impl Into) { unsafe { ffi::pixman_rasterize_edges( self.as_ptr(), l.as_ptr() as *mut _, r.as_ptr() as *mut _, t.into().into_raw(), b.into().into_raw(), ) } } /// Rasterize the specified trapezoids pub fn rasterize_trapezoid(&mut self, trap: Trapezoid, offset: (i32, i32)) { unsafe { ffi::pixman_rasterize_trapezoid(self.as_ptr(), trap.as_ptr(), offset.0, offset.1) } } } impl Image<'_, '_> { /// Initialize the image from a raw pointer /// /// # Safety /// /// The pointer is expected to be valid and have a ref-count of at least one. /// Ownership of the pointer is transferred and unref will be called on drop. /// /// Any other references to the `pixman_image_t` must not be mutated while this /// `Image` exists, including changes to the reference count. pub unsafe fn from_ptr(ptr: *mut ffi::pixman_image_t) -> Self { Self { image: unsafe { ImageRef::from_ptr(ptr) }, _bits: PhantomData, _alpha: PhantomData, } } } pixman-0.2.1/src/image/conical_gradient.rs000064400000000000000000000016231046102023000166260ustar 00000000000000use std::ffi::c_int; use crate::{ffi, image_type, CreateFailed, Fixed, GradientStop, Point}; image_type! { /// Conical gradient image #[derive(Debug)] ConicalGradient } impl ConicalGradient<'static> { /// Create a new conical gradient image usable as the src in blit operations pub fn new( center: impl Into, angle: impl Into, stops: &[GradientStop], ) -> Result { let center = center.into(); let angle = angle.into(); let ptr = unsafe { ffi::pixman_image_create_conical_gradient( center.as_ptr(), angle.into_raw(), stops.as_ptr() as *const _, stops.len() as c_int, ) }; if ptr.is_null() { Err(CreateFailed) } else { Ok(unsafe { Self::from_ptr(ptr) }) } } } pixman-0.2.1/src/image/linear_gradient.rs000064400000000000000000000015671046102023000164770ustar 00000000000000use std::ffi::c_int; use crate::{ffi, image_type, CreateFailed, GradientStop, Point}; image_type! { /// Linear gradient image #[derive(Debug)] LinearGradient } impl LinearGradient<'static> { /// Create a new linear gradient image usable as the src in blit operations pub fn new( p1: impl Into, p2: impl Into, stops: &[GradientStop], ) -> Result { let p1: Point = p1.into(); let p2: Point = p2.into(); let ptr = unsafe { ffi::pixman_image_create_linear_gradient( p1.as_ptr(), p2.as_ptr(), stops.as_ptr() as *const _, stops.len() as c_int, ) }; if ptr.is_null() { Err(CreateFailed) } else { Ok(unsafe { Self::from_ptr(ptr) }) } } } pixman-0.2.1/src/image/mod.rs000064400000000000000000000201421046102023000141150ustar 00000000000000use std::os::raw::c_int; use pixman_sys as ffi; use thiserror::Error; use crate::{ repeat::Repeat, Dither, Filter, Fixed, OperationFailed, Region16, Region32, Transform, }; mod bits; mod conical_gradient; mod linear_gradient; mod radial_gradient; mod solid; pub use bits::*; pub use conical_gradient::ConicalGradient; pub use linear_gradient::LinearGradient; pub use radial_gradient::RadialGradient; pub use solid::Solid; /// Resource creation failed #[derive(Debug, Error)] #[error("Resource creation failed")] pub struct CreateFailed; /// A reference to a raw image #[derive(Debug)] pub struct ImageRef(*mut ffi::pixman_image_t); // SAFETY: See `Image`. #[cfg(feature = "sync")] unsafe impl Send for ImageRef {} #[cfg(feature = "sync")] unsafe impl Sync for ImageRef {} impl ImageRef { /// Set the repeat operation for this image pub fn set_repeat(&mut self, repeat: Repeat) { unsafe { ffi::pixman_image_set_repeat(self.0, repeat.into()); } } /// Apply the specified transform during sampling from this image pub fn set_transform( &mut self, transform: impl Into, ) -> Result<(), OperationFailed> { let transform = transform.into(); let res = unsafe { ffi::pixman_image_set_transform(self.0, transform.as_ptr()) }; if res == 1 { Ok(()) } else { Err(OperationFailed) } } /// Clear a previously applied transform pub fn clear_transform(&mut self) -> Result<(), OperationFailed> { let res = unsafe { ffi::pixman_image_set_transform(self.0, std::ptr::null()) }; if res == 1 { Ok(()) } else { Err(OperationFailed) } } /// Apply a clip region used during composition pub fn set_clip_region(&mut self, region: Option<&Region16>) -> Result<(), OperationFailed> { let region = if let Some(region) = region { region.as_ptr() } else { std::ptr::null() }; let res = unsafe { ffi::pixman_image_set_clip_region(self.0, region) }; if res == 1 { Ok(()) } else { Err(OperationFailed) } } /// Apply a clip region used during composition pub fn set_clip_region32(&mut self, region: Option<&Region32>) -> Result<(), OperationFailed> { let region = if let Some(region) = region { region.as_ptr() } else { std::ptr::null() }; let res = unsafe { ffi::pixman_image_set_clip_region32(self.0, region) }; if res == 1 { Ok(()) } else { Err(OperationFailed) } } /// Set the dither operation used during composition pub fn set_dither(&mut self, dither: Dither) { unsafe { ffi::pixman_image_set_dither(self.0, dither.into()); } } /// Set the dither offset pub fn set_dither_offset(&mut self, offset_x: c_int, offset_y: c_int) { unsafe { ffi::pixman_image_set_dither_offset(self.0, offset_x, offset_y) } } /// Set the filter operation used during composition pub fn set_filter( &mut self, filter: Filter, filter_params: &[Fixed], ) -> Result<(), OperationFailed> { let res = unsafe { ffi::pixman_image_set_filter( self.0, filter.into(), filter_params.as_ptr() as *const _, filter_params.len() as i32, ) }; if res == 1 { Ok(()) } else { Err(OperationFailed) } } /// Set whether the source clip was set by a client pub fn set_has_client_clip(&mut self, client_clip: bool) { let client_clip = if client_clip { 1 } else { 0 }; unsafe { ffi::pixman_image_set_has_client_clip(self.0, client_clip); } } // TODO: pixman_image_set_indexed //pub fn set_indexed(&mut self) /// Set whether the clip applies when the image is used as a source pub fn set_source_clipping(&mut self, source_clipping: bool) { let source_clipping = if source_clipping { 1 } else { 0 }; unsafe { ffi::pixman_image_set_source_clipping(self.0, source_clipping); } } /// Whether the image has component alpha or unified alpha pub fn component_alpha(&self) -> bool { unsafe { ffi::pixman_image_get_component_alpha(self.0) == 1 } } /// Set whether the image has component alpha or unified alpha pub fn set_component_alpha(&mut self, component_alpha: bool) { let component_alpha = if component_alpha { 1 } else { 0 }; unsafe { ffi::pixman_image_set_component_alpha(self.0, component_alpha) } } } impl ImageRef { /// Create a reference to a raw image /// /// # Safety /// /// The pointer is expected to be valid and have a ref-count of at least one. /// Ownership of the pointer is transferred and unref will be called on drop. pub unsafe fn from_ptr(ptr: *mut ffi::pixman_image_t) -> Self { assert!(!ptr.is_null()); ImageRef(ptr) } /// Access the raw image pointer pub fn as_ptr(&self) -> *mut ffi::pixman_image_t { self.0 } } impl Drop for ImageRef { fn drop(&mut self) { #[cfg(feature = "sync")] let _lock = crate::REF_COUNT_LOCK.lock().unwrap(); unsafe { ffi::pixman_image_unref(self.0); } } } macro_rules! image_type { ($(#[$attr:meta])* $name:ident) => { $(#[$attr])* pub struct $name<'alpha> { image: $crate::ImageRef, _phantom: std::marker::PhantomData<&'alpha ()>, } impl<'a> $name<'a> { /// Set an alpha map that will be used when this image is /// used as a src in a blit operation pub fn set_alpha_map<'alpha: 'a>( self, alpha_map: &'alpha crate::Image<'_, 'static>, x: i16, y: i16, ) -> $name<'alpha> { #[cfg(feature = "sync")] let _lock = $crate::REF_COUNT_LOCK.lock().unwrap(); unsafe { $crate::ffi::pixman_image_set_alpha_map( self.as_ptr(), alpha_map.as_ptr(), x, y, ); } $name { image: self.image, _phantom: std::marker::PhantomData, } } /// Clear a previously set alpha map pub fn clear_alpha_map(self) -> $name<'static> { #[cfg(feature = "sync")] let _lock = $crate::REF_COUNT_LOCK.lock().unwrap(); unsafe { $crate::ffi::pixman_image_set_alpha_map( self.as_ptr(), std::ptr::null_mut(), 0, 0, ); } $name { image: self.image, _phantom: std::marker::PhantomData, } } } impl<'alpha> $name<'alpha> { /// Initialize the image from a raw pointer /// /// # Safety /// /// The pointer is expected to be valid and have a ref-count of at least one. /// Ownership of the pointer is transferred and unref will be called on drop. pub unsafe fn from_ptr(ptr: *mut ffi::pixman_image_t) -> Self { Self { image: $crate::ImageRef::from_ptr(ptr), _phantom: std::marker::PhantomData, } } } impl<'alpha> std::ops::Deref for $name<'alpha> { type Target = $crate::ImageRef; fn deref(&self) -> &Self::Target { &self.image } } impl<'alpha> std::ops::DerefMut for $name<'alpha> { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.image } } }; } pub(crate) use image_type; pixman-0.2.1/src/image/radial_gradient.rs000064400000000000000000000022121046102023000164450ustar 00000000000000use std::ffi::c_int; use crate::{ffi, image_type, CreateFailed, Fixed, GradientStop, Point}; image_type! { /// Radial gradient image #[derive(Debug)] RadialGradient } impl RadialGradient<'static> { /// Create a new radial gradient image usable as the src in blit operations pub fn new( inner: impl Into, outer: impl Into, inner_radius: impl Into, outer_radius: impl Into, stops: &[GradientStop], ) -> Result { let inner = inner.into(); let outer = outer.into(); let inner_radius = inner_radius.into(); let other_radius = outer_radius.into(); let ptr = unsafe { ffi::pixman_image_create_radial_gradient( inner.as_ptr(), outer.as_ptr(), inner_radius.into_raw(), other_radius.into_raw(), stops.as_ptr() as *const _, stops.len() as c_int, ) }; if ptr.is_null() { Err(CreateFailed) } else { Ok(unsafe { Self::from_ptr(ptr) }) } } } pixman-0.2.1/src/image/solid.rs000064400000000000000000000010501046102023000144450ustar 00000000000000use crate::{ffi, image_type, Color, CreateFailed}; image_type! { /// Solid color image #[derive(Debug)] Solid } impl Solid<'static> { /// Create a new solid color image usable as the src in blit operations pub fn new(color: impl Into) -> Result { let color = color.into(); let ptr = unsafe { ffi::pixman_image_create_solid_fill(color.as_ptr()) }; if ptr.is_null() { Err(CreateFailed) } else { Ok(unsafe { Self::from_ptr(ptr) }) } } } pixman-0.2.1/src/lib.rs000064400000000000000000000111561046102023000130270ustar 00000000000000#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![warn(missing_docs, missing_debug_implementations)] //! # From the official [pixman docs](https://www.pixman.org/): //! //! > Pixman is a low-level software library for pixel manipulation, providing features such as image compositing and trapezoid rasterization. //! > Important users of pixman are the cairo graphics library and the X server. //! > //! > Pixman is implemented as a library in the C programming language. It runs on many platforms, including Linux, BSD Derivatives, MacOS X, and Windows. //! > //! > Pixman is free and open source software. It is available to be redistributed and/or modified under the terms of the MIT license. use std::os::raw::c_int; pub use pixman_sys as ffi; /// 16bit Box pub type Box16 = ffi::pixman_box16_t; /// 32bit Box pub type Box32 = ffi::pixman_box32_t; /// 16bit Rectangle pub type Rectangle16 = ffi::pixman_rectangle16_t; /// 32bit Rectangle pub type Rectangle32 = ffi::pixman_rectangle32_t; mod color; mod dither; mod edge; mod filter; mod fixed; mod format; mod gradient_stop; mod image; mod line; mod operation; mod point; mod region; mod repeat; mod span; mod transform; mod trap; mod trapezoid; mod triangle; mod vector; pub use color::*; pub use dither::*; pub use edge::*; pub use filter::*; pub use fixed::*; pub use format::*; pub use gradient_stop::*; pub use image::*; pub use line::*; pub use operation::*; pub use point::*; pub use region::*; pub use repeat::*; pub use span::*; pub use transform::*; pub use trap::*; pub use trapezoid::*; pub use triangle::*; pub use vector::*; /// The requested operation failed #[derive(Debug, thiserror::Error)] #[error("The requested operation failed")] pub struct OperationFailed; #[cfg(feature = "sync")] static REF_COUNT_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(()); /// Blit the src into the dst with the specified values #[allow(clippy::too_many_arguments)] pub fn blit( src_bits: &[u32], dst_bits: &mut [u32], src_stride: isize, dst_stride: isize, src_bpp: isize, dst_bpp: isize, src_x: isize, src_y: isize, dest_x: isize, dest_y: isize, width: isize, height: isize, ) -> Result<(), OperationFailed> { let res = unsafe { ffi::pixman_blt( src_bits.as_ptr() as *mut _, dst_bits.as_mut_ptr(), src_stride as c_int, dst_stride as c_int, src_bpp as c_int, dst_bpp as c_int, src_x as c_int, src_y as c_int, dest_x as c_int, dest_y as c_int, width as c_int, height as c_int, ) }; if res == 1 { Ok(()) } else { Err(OperationFailed) } } /// Fill the provided bits with the provided values #[allow(clippy::too_many_arguments)] pub fn fill( bits: &mut [u32], stride: u32, bpp: u32, x: u32, y: u32, width: u32, height: u32, filler: u32, ) -> Result<(), OperationFailed> { let res = unsafe { ffi::pixman_fill( bits.as_mut_ptr(), stride as c_int, bpp as c_int, x as c_int, y as c_int, width as c_int, height as c_int, filler, ) }; if res == 1 { Ok(()) } else { Err(OperationFailed) } } // TODO: pixman_filter_create_separable_convolution // TODO: pixman_format_supported_destination // TODO: pixman_format_supported_source // TODO: pixman_glyph_cache_create // TODO: pixman_glyph_cache_destroy // TODO: pixman_glyph_cache_freeze // TODO: pixman_glyph_cache_insert // TODO: pixman_glyph_cache_lookup // TODO: pixman_glyph_cache_remove // TODO: pixman_glyph_cache_thaw // TODO: pixman_glyph_get_extents // TODO: pixman_glyph_get_mask_format /// Compute the smallest value greater than or equal to y which is on a /// grid row. pub fn sample_ceil_y(y: impl Into, bpp: i32) -> Fixed { Fixed::from_raw(unsafe { ffi::pixman_sample_ceil_y(y.into().into_raw(), bpp) }) } /// Compute the largest value strictly less than y which is on a /// grid row. pub fn sample_floor_y(y: impl Into, bpp: i32) -> Fixed { Fixed::from_raw(unsafe { ffi::pixman_sample_floor_y(y.into().into_raw(), bpp) }) } #[cfg(all(test, feature = "sync"))] mod test { use super::*; fn is_send_and_sync() {} #[test] fn test_send_sync() { is_send_and_sync::>(); is_send_and_sync::(); is_send_and_sync::(); is_send_and_sync::(); is_send_and_sync::(); is_send_and_sync::(); } } pixman-0.2.1/src/line.rs000064400000000000000000000022021046102023000132000ustar 00000000000000use crate::{ffi, Point}; /// Single line #[derive(Debug, Clone, Copy)] #[repr(transparent)] pub struct Line(ffi::pixman_line_fixed_t); impl Line { /// Initialize a line from two points #[inline] pub fn new(p1: impl Into, p2: impl Into) -> Self { Self(ffi::pixman_line_fixed_t { p1: p1.into().into(), p2: p2.into().into(), }) } /// Access the first point #[inline] pub fn p1(&self) -> Point { Point::from(self.0.p1) } /// Access the second point #[inline] pub fn p2(&self) -> Point { Point::from(self.0.p2) } #[inline] pub(crate) fn as_ptr(&self) -> *const ffi::pixman_line_fixed_t { &self.0 } } impl From for Line { #[inline] fn from(value: ffi::pixman_line_fixed_t) -> Self { Self(value) } } impl From for ffi::pixman_line_fixed_t { #[inline] fn from(value: Line) -> Self { value.0 } } impl + Copy> From<[P; 2]> for Line { #[inline] fn from(value: [P; 2]) -> Self { Self::new(value[0], value[1]) } } pixman-0.2.1/src/operation.rs000064400000000000000000000250451046102023000142630ustar 00000000000000use pixman_sys as ffi; use thiserror::Error; /// Defines the possible operations for composition #[derive(Debug, Clone, Copy)] pub enum Operation { /// Clear Clear, /// Src Src, /// Dst Dst, /// Over Over, /// Over-reverse OverReverse, /// In In, /// In-reverse InReverse, /// Out Out, /// Out-reverse OutReverse, /// A-top Atop, /// A-top-reverse AtopReverse, /// Xor Xor, /// Add Add, /// Saturate Saturate, /// Disjoint-clear DisjointClear, /// Disjoint-src DisjointSrc, /// Disjoint-dst DisjointDst, /// Disjoint-over DisjointOver, /// Disjoint-over-reverse DisjointOverReverse, /// Disjoint-in DisjointIn, /// Disjoint-in-reverse DisjointInReverse, /// Disjoint-out DisjointOut, /// Disjoint-out-reverse DisjointOutReverse, /// Disjoint-a-top DisjointAtop, /// Disjoint-a-top-reverse DisjointAtopReverse, /// Disjoint-xor DisjointXor, /// Conjoint-clear ConjointClear, /// Conjoint-src ConjointSrc, /// Conjoint-dst ConjointDst, /// Conjoint-over ConjointOver, /// Conjoint-over-reverse ConjointOverReverse, /// Conjoint-in ConjointIn, /// Conjoint-in-reverse ConjointInReverse, /// Conjoint-out ConjointOut, /// Conjoint-out-reverse ConjointOutReverse, /// Conjoint-a-top ConjointAtop, /// Conjoint-a-top-reverse ConjointAtopReverse, /// Conjoint-xor ConjointXor, /// Multiply Multiply, /// Screen Screen, /// Overlay Overlay, /// Darken Darken, /// Lighten Lighten, /// Color dodge ColorDodge, /// Color burn ColorBurn, /// Hard-light HardLight, /// Soft-light SoftLight, /// Difference Difference, /// Exclustion Exclustion, /// Hls hue HslHue, /// Hls saturation HslSaturation, /// Hls color HslColor, /// Hls luminosity HslLuminosity, } /// The operation is unknown #[derive(Debug, Error)] #[error("Unknown operation {0}")] pub struct UnknownOperation(ffi::pixman_op_t); impl TryFrom for Operation { type Error = UnknownOperation; fn try_from(value: ffi::pixman_op_t) -> Result { let format = match value { ffi::pixman_op_t_PIXMAN_OP_CLEAR => Operation::Clear, ffi::pixman_op_t_PIXMAN_OP_SRC => Operation::Src, ffi::pixman_op_t_PIXMAN_OP_DST => Operation::Dst, ffi::pixman_op_t_PIXMAN_OP_OVER => Operation::Over, ffi::pixman_op_t_PIXMAN_OP_OVER_REVERSE => Operation::OverReverse, ffi::pixman_op_t_PIXMAN_OP_IN => Operation::In, ffi::pixman_op_t_PIXMAN_OP_IN_REVERSE => Operation::InReverse, ffi::pixman_op_t_PIXMAN_OP_OUT => Operation::Out, ffi::pixman_op_t_PIXMAN_OP_OUT_REVERSE => Operation::OutReverse, ffi::pixman_op_t_PIXMAN_OP_ATOP => Operation::Atop, ffi::pixman_op_t_PIXMAN_OP_ATOP_REVERSE => Operation::AtopReverse, ffi::pixman_op_t_PIXMAN_OP_XOR => Operation::Xor, ffi::pixman_op_t_PIXMAN_OP_ADD => Operation::Add, ffi::pixman_op_t_PIXMAN_OP_SATURATE => Operation::Saturate, ffi::pixman_op_t_PIXMAN_OP_DISJOINT_CLEAR => Operation::DisjointClear, ffi::pixman_op_t_PIXMAN_OP_DISJOINT_SRC => Operation::DisjointSrc, ffi::pixman_op_t_PIXMAN_OP_DISJOINT_DST => Operation::DisjointDst, ffi::pixman_op_t_PIXMAN_OP_DISJOINT_OVER => Operation::DisjointOver, ffi::pixman_op_t_PIXMAN_OP_DISJOINT_OVER_REVERSE => Operation::DisjointOverReverse, ffi::pixman_op_t_PIXMAN_OP_DISJOINT_IN => Operation::DisjointIn, ffi::pixman_op_t_PIXMAN_OP_DISJOINT_IN_REVERSE => Operation::DisjointInReverse, ffi::pixman_op_t_PIXMAN_OP_DISJOINT_OUT => Operation::DisjointOut, ffi::pixman_op_t_PIXMAN_OP_DISJOINT_OUT_REVERSE => Operation::DisjointOutReverse, ffi::pixman_op_t_PIXMAN_OP_DISJOINT_ATOP => Operation::DisjointAtop, ffi::pixman_op_t_PIXMAN_OP_DISJOINT_ATOP_REVERSE => Operation::DisjointAtopReverse, ffi::pixman_op_t_PIXMAN_OP_DISJOINT_XOR => Operation::DisjointXor, ffi::pixman_op_t_PIXMAN_OP_CONJOINT_CLEAR => Operation::ConjointClear, ffi::pixman_op_t_PIXMAN_OP_CONJOINT_SRC => Operation::ConjointSrc, ffi::pixman_op_t_PIXMAN_OP_CONJOINT_DST => Operation::ConjointDst, ffi::pixman_op_t_PIXMAN_OP_CONJOINT_OVER => Operation::ConjointOver, ffi::pixman_op_t_PIXMAN_OP_CONJOINT_OVER_REVERSE => Operation::ConjointOverReverse, ffi::pixman_op_t_PIXMAN_OP_CONJOINT_IN => Operation::ConjointIn, ffi::pixman_op_t_PIXMAN_OP_CONJOINT_IN_REVERSE => Operation::ConjointInReverse, ffi::pixman_op_t_PIXMAN_OP_CONJOINT_OUT => Operation::ConjointOut, ffi::pixman_op_t_PIXMAN_OP_CONJOINT_OUT_REVERSE => Operation::ConjointOutReverse, ffi::pixman_op_t_PIXMAN_OP_CONJOINT_ATOP => Operation::ConjointAtop, ffi::pixman_op_t_PIXMAN_OP_CONJOINT_ATOP_REVERSE => Operation::ConjointAtopReverse, ffi::pixman_op_t_PIXMAN_OP_CONJOINT_XOR => Operation::ConjointXor, ffi::pixman_op_t_PIXMAN_OP_MULTIPLY => Operation::Multiply, ffi::pixman_op_t_PIXMAN_OP_SCREEN => Operation::Screen, ffi::pixman_op_t_PIXMAN_OP_OVERLAY => Operation::Overlay, ffi::pixman_op_t_PIXMAN_OP_DARKEN => Operation::Darken, ffi::pixman_op_t_PIXMAN_OP_LIGHTEN => Operation::Lighten, ffi::pixman_op_t_PIXMAN_OP_COLOR_DODGE => Operation::ColorDodge, ffi::pixman_op_t_PIXMAN_OP_COLOR_BURN => Operation::ColorBurn, ffi::pixman_op_t_PIXMAN_OP_HARD_LIGHT => Operation::HardLight, ffi::pixman_op_t_PIXMAN_OP_SOFT_LIGHT => Operation::SoftLight, ffi::pixman_op_t_PIXMAN_OP_DIFFERENCE => Operation::Difference, ffi::pixman_op_t_PIXMAN_OP_EXCLUSION => Operation::Exclustion, ffi::pixman_op_t_PIXMAN_OP_HSL_HUE => Operation::HslHue, ffi::pixman_op_t_PIXMAN_OP_HSL_SATURATION => Operation::HslSaturation, ffi::pixman_op_t_PIXMAN_OP_HSL_COLOR => Operation::HslColor, ffi::pixman_op_t_PIXMAN_OP_HSL_LUMINOSITY => Operation::HslLuminosity, _ => return Err(UnknownOperation(value)), }; Ok(format) } } impl From for ffi::pixman_op_t { fn from(value: Operation) -> Self { match value { Operation::Clear => ffi::pixman_op_t_PIXMAN_OP_CLEAR, Operation::Src => ffi::pixman_op_t_PIXMAN_OP_SRC, Operation::Dst => ffi::pixman_op_t_PIXMAN_OP_DST, Operation::Over => ffi::pixman_op_t_PIXMAN_OP_OVER, Operation::OverReverse => ffi::pixman_op_t_PIXMAN_OP_OVER_REVERSE, Operation::In => ffi::pixman_op_t_PIXMAN_OP_IN, Operation::InReverse => ffi::pixman_op_t_PIXMAN_OP_IN_REVERSE, Operation::Out => ffi::pixman_op_t_PIXMAN_OP_OUT, Operation::OutReverse => ffi::pixman_op_t_PIXMAN_OP_OUT_REVERSE, Operation::Atop => ffi::pixman_op_t_PIXMAN_OP_ATOP, Operation::AtopReverse => ffi::pixman_op_t_PIXMAN_OP_ATOP_REVERSE, Operation::Xor => ffi::pixman_op_t_PIXMAN_OP_XOR, Operation::Add => ffi::pixman_op_t_PIXMAN_OP_ADD, Operation::Saturate => ffi::pixman_op_t_PIXMAN_OP_SATURATE, Operation::DisjointClear => ffi::pixman_op_t_PIXMAN_OP_DISJOINT_CLEAR, Operation::DisjointSrc => ffi::pixman_op_t_PIXMAN_OP_DISJOINT_SRC, Operation::DisjointDst => ffi::pixman_op_t_PIXMAN_OP_DISJOINT_DST, Operation::DisjointOver => ffi::pixman_op_t_PIXMAN_OP_DISJOINT_OVER, Operation::DisjointOverReverse => ffi::pixman_op_t_PIXMAN_OP_DISJOINT_OVER_REVERSE, Operation::DisjointIn => ffi::pixman_op_t_PIXMAN_OP_DISJOINT_IN, Operation::DisjointInReverse => ffi::pixman_op_t_PIXMAN_OP_DISJOINT_IN_REVERSE, Operation::DisjointOut => ffi::pixman_op_t_PIXMAN_OP_DISJOINT_OUT, Operation::DisjointOutReverse => ffi::pixman_op_t_PIXMAN_OP_DISJOINT_OUT_REVERSE, Operation::DisjointAtop => ffi::pixman_op_t_PIXMAN_OP_DISJOINT_ATOP, Operation::DisjointAtopReverse => ffi::pixman_op_t_PIXMAN_OP_DISJOINT_ATOP_REVERSE, Operation::DisjointXor => ffi::pixman_op_t_PIXMAN_OP_DISJOINT_XOR, Operation::ConjointClear => ffi::pixman_op_t_PIXMAN_OP_CONJOINT_CLEAR, Operation::ConjointSrc => ffi::pixman_op_t_PIXMAN_OP_CONJOINT_SRC, Operation::ConjointDst => ffi::pixman_op_t_PIXMAN_OP_CONJOINT_DST, Operation::ConjointOver => ffi::pixman_op_t_PIXMAN_OP_CONJOINT_OVER, Operation::ConjointOverReverse => ffi::pixman_op_t_PIXMAN_OP_CONJOINT_OVER_REVERSE, Operation::ConjointIn => ffi::pixman_op_t_PIXMAN_OP_CONJOINT_IN, Operation::ConjointInReverse => ffi::pixman_op_t_PIXMAN_OP_CONJOINT_IN_REVERSE, Operation::ConjointOut => ffi::pixman_op_t_PIXMAN_OP_CONJOINT_OUT, Operation::ConjointOutReverse => ffi::pixman_op_t_PIXMAN_OP_CONJOINT_OUT_REVERSE, Operation::ConjointAtop => ffi::pixman_op_t_PIXMAN_OP_CONJOINT_ATOP, Operation::ConjointAtopReverse => ffi::pixman_op_t_PIXMAN_OP_CONJOINT_ATOP_REVERSE, Operation::ConjointXor => ffi::pixman_op_t_PIXMAN_OP_CONJOINT_XOR, Operation::Multiply => ffi::pixman_op_t_PIXMAN_OP_MULTIPLY, Operation::Screen => ffi::pixman_op_t_PIXMAN_OP_SCREEN, Operation::Overlay => ffi::pixman_op_t_PIXMAN_OP_OVERLAY, Operation::Darken => ffi::pixman_op_t_PIXMAN_OP_DARKEN, Operation::Lighten => ffi::pixman_op_t_PIXMAN_OP_LIGHTEN, Operation::ColorDodge => ffi::pixman_op_t_PIXMAN_OP_COLOR_DODGE, Operation::ColorBurn => ffi::pixman_op_t_PIXMAN_OP_COLOR_BURN, Operation::HardLight => ffi::pixman_op_t_PIXMAN_OP_HARD_LIGHT, Operation::SoftLight => ffi::pixman_op_t_PIXMAN_OP_SOFT_LIGHT, Operation::Difference => ffi::pixman_op_t_PIXMAN_OP_DIFFERENCE, Operation::Exclustion => ffi::pixman_op_t_PIXMAN_OP_EXCLUSION, Operation::HslHue => ffi::pixman_op_t_PIXMAN_OP_HSL_HUE, Operation::HslSaturation => ffi::pixman_op_t_PIXMAN_OP_HSL_SATURATION, Operation::HslColor => ffi::pixman_op_t_PIXMAN_OP_HSL_COLOR, Operation::HslLuminosity => ffi::pixman_op_t_PIXMAN_OP_HSL_LUMINOSITY, } } } pixman-0.2.1/src/point.rs000064400000000000000000000023211046102023000134040ustar 00000000000000use pixman_sys as ffi; use crate::fixed::Fixed; /// A single point #[derive(Debug, Clone, Copy)] #[repr(transparent)] pub struct Point(ffi::pixman_point_fixed_t); impl Point { /// Initialize the point from x and y values #[inline] pub fn new(x: impl Into, y: impl Into) -> Self { Self(ffi::pixman_point_fixed { x: x.into().into_raw(), y: y.into().into_raw(), }) } /// Access the x value #[inline] pub fn x(&self) -> Fixed { Fixed::from_raw(self.0.x) } /// Access the y value #[inline] pub fn y(&self) -> Fixed { Fixed::from_raw(self.0.y) } #[inline] pub(crate) fn as_ptr(&self) -> *const ffi::pixman_point_fixed_t { &self.0 as *const ffi::pixman_point_fixed_t } } impl From for Point { #[inline] fn from(value: ffi::pixman_point_fixed_t) -> Self { Self(value) } } impl From for ffi::pixman_point_fixed_t { #[inline] fn from(value: Point) -> Self { value.0 } } impl From<(X, Y)> for Point where X: Into, Y: Into, { fn from((x, y): (X, Y)) -> Self { Self::new(x, y) } } pixman-0.2.1/src/region.rs000064400000000000000000000251051046102023000135430ustar 00000000000000use paste::paste; use crate::{Box16, Box32}; /// Describes overlap of a region with a rectangle #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum Overlap { /// No intersection Out, /// Region contains a rectangle In, /// Partial intersection Part, } macro_rules! impl_region { ($(#[$attr:meta])* $name:ident, ffi => $ffi:path, impl => $impl:ident, box_t => $box_t:path, loc_t => $loc_t:path, size_t => $size_t:path$(,)?) => { $(#[$attr])* pub struct $name($ffi); impl $name { /// Initialize a region from the provided values pub fn init_rect(x: $loc_t, y: $loc_t, width: $size_t, height: $size_t) -> Self { let mut region = std::mem::MaybeUninit::uninit(); unsafe { paste! { $crate::ffi::[<$impl _init_rect>]( region.as_mut_ptr(), x as std::ffi::c_int, y as std::ffi::c_int, width as std::ffi::c_uint, height as std::ffi::c_uint, ); } } Self(unsafe { region.assume_init() }) } /// Initialize the region from the provided boxes pub fn init_rects(boxes: &[$box_t]) -> Self { let mut region = std::mem::MaybeUninit::uninit(); unsafe { paste! { $crate::ffi::[<$impl _init_rects>]( region.as_mut_ptr(), boxes.as_ptr(), boxes.len() as i32, ); } } Self(unsafe { region.assume_init() }) } /// Initialize the region from the provided extents pub fn init_with_extents(extents: &[$box_t]) -> Self { let mut region = std::mem::MaybeUninit::uninit(); unsafe { paste! { $crate::ffi::[<$impl _init_with_extents>]( region.as_mut_ptr(), extents.as_ptr(), ) } } Self(unsafe { region.assume_init() }) } /// Intersect the region with another region pub fn intersect(&self, other: &$name) -> Self { let mut region = $name::default(); unsafe { paste!($crate::ffi::[<$impl _intersect>](&mut region.0, &self.0, &other.0)); } region } /// Intersect the region with a rect pub fn intersect_rect(&self, x: $loc_t, y: $loc_t, width: $size_t, height: $size_t) -> Self { let mut dest = $name::default(); unsafe { paste! { $crate::ffi::[<$impl _intersect_rect>]( &mut dest.0, &self.0, x as std::ffi::c_int, y as std::ffi::c_int, width as std::ffi::c_uint, height as std::ffi::c_uint, ); } } dest } /// Take a region and a box and return a region that is everything /// in the box but not in the region. The careful reader will note /// that this is the same as subtracting the region from the box... pub fn inverse(&self, bbox: $box_t) -> Self { let mut region = $name::default(); unsafe { paste!($crate::ffi::[<$impl _inverse>](&mut region.0, &self.0, &bbox)); } region } /// Return the number of rects in this region pub fn n_rects(&self) -> usize { unsafe { paste!($crate::ffi::[<$impl _n_rects>](&self.0) as usize) } } /// Whether this region is empty pub fn is_non_empty(&self) -> bool { unsafe { paste!($crate::ffi::[<$impl _not_empty>](&self.0) == 1) } } /// Returns the rectangles in this region pub fn rectangles(&self) -> &[$box_t] { let mut n_rects = 0; let rectangles = unsafe { let rects = paste!($crate::ffi::[<$impl _rectangles>](&self.0, &mut n_rects)); std::slice::from_raw_parts(rects, n_rects as usize) }; rectangles } /// Reset this region to the provided box pub fn reset(&mut self, box_: $box_t) { unsafe { paste!($crate::ffi::[<$impl _reset>](&mut self.0, &box_)); } } /// Run a selfcheck on the region pub fn selfcheck(&mut self) -> bool { unsafe { paste!($crate::ffi::[<$impl _selfcheck>](&mut self.0) == 1) } } /// Subtract reg_s from reg_m and leave the result in reg_d. /// S stands for subtrahend, M for minuend and D for difference. pub fn subtract(&self, other: &$name) -> Self { let mut region = $name::default(); unsafe { paste!($crate::ffi::[<$impl _subtract>](&mut region.0, &self.0, &other.0)); } region } /// Translate this region by the specified amount pub fn translate(&mut self, x: $loc_t, y: $loc_t) { unsafe { paste! { $crate::ffi::[<$impl _translate>]( &mut self.0, x as std::ffi::c_int, y as std::ffi::c_int,) } }; } /// Create the union between this region and another region pub fn union(&self, other: &$name) -> Self { let mut region = $name::default(); unsafe { paste!($crate::ffi::[<$impl _union>](&mut region.0, &self.0, &other.0)); } region } /// Create the union between this region and the provided rect pub fn union_rect(&self, x: $loc_t, y: $loc_t, width: $size_t, height: $size_t) -> Self { let mut region = $name::default(); unsafe { paste! { $crate::ffi::[<$impl _union_rect>]( &mut region.0, &self.0, x as std::ffi::c_int, y as std::ffi::c_int, width as std::ffi::c_uint, height as std::ffi::c_uint, ); } } region } /// Clear this region pub fn clear(&mut self) { unsafe { paste!($crate::ffi::[<$impl _clear>](&mut self.0)); } } /// Whether this region contains the provided point pub fn contains_point(&self, x: $loc_t, y: $loc_t) -> Option<$box_t> { let mut r#box = std::mem::MaybeUninit::uninit(); let contains_point = unsafe { paste! { $crate::ffi::[<$impl _contains_point>]( &self.0, x as std::ffi::c_int, y as std::ffi::c_int, r#box.as_mut_ptr(), ) == 1 } }; if contains_point { Some(unsafe { r#box.assume_init() }) } else { None } } /// Whether this region contains the provided rectangle pub fn contains_rectangle(&self, rect: $box_t) -> Overlap { let overlap = unsafe { paste!($crate::ffi::[<$impl _contains_rectangle>](&self.0, &rect)) }; match overlap { $crate::ffi::pixman_region_overlap_t_PIXMAN_REGION_OUT => Overlap::Out, $crate::ffi::pixman_region_overlap_t_PIXMAN_REGION_IN => Overlap::In, $crate::ffi::pixman_region_overlap_t_PIXMAN_REGION_PART => Overlap::Part, _ => unreachable!(), } } #[inline] pub(crate) fn as_ptr(&self) -> *const $ffi { &self.0 } } impl Default for $name { #[inline] fn default() -> Self { let mut region = std::mem::MaybeUninit::uninit(); unsafe { paste!($crate::ffi::[<$impl _init>](region.as_mut_ptr())); } Self(unsafe { region.assume_init() }) } } impl From<$ffi> for $name { #[inline] fn from(value: $ffi) -> Self { Self(value) } } impl From<$name> for $ffi { #[inline] fn from(value: $name) -> Self { value.0 } } impl Clone for $name { #[inline] fn clone(&self) -> Self { let mut region = $name::default(); unsafe { paste!($crate::ffi::[<$impl _copy>](&mut region.0, &self.0)); } region } } impl PartialEq for $name { #[inline] fn eq(&self, other: &Self) -> bool { unsafe { paste!($crate::ffi::[<$impl _equal>](&self.0, &other.0) == 1) } } } impl Eq for $name {} impl Drop for $name { fn drop(&mut self) { unsafe { paste!($crate::ffi::[<$impl _fini>](&mut self.0)); } } } }; } impl_region! { /// 16bit region #[derive(Debug)] Region16, ffi => crate::ffi::pixman_region16_t, impl => pixman_region, box_t => Box16, loc_t => i16, size_t => u16, } impl_region! { /// 32bit region #[derive(Debug)] Region32, ffi => crate::ffi::pixman_region32_t, impl => pixman_region32, box_t => Box32, loc_t => i32, size_t => u32, } pixman-0.2.1/src/repeat.rs000064400000000000000000000025431046102023000135410ustar 00000000000000use pixman_sys as ffi; use thiserror::Error; /// Defines the possible repeat operations #[derive(Debug, Clone, Copy)] pub enum Repeat { /// No repeat None, /// Normal repeat Normal, /// Pad repeat Pad, /// Reflect repeat Reflect, } /// The repeat operations is unknown #[derive(Debug, Error)] #[error("Unknown repeat {0}")] pub struct UnknownRepeat(ffi::pixman_repeat_t); impl TryFrom for Repeat { type Error = UnknownRepeat; fn try_from(value: ffi::pixman_repeat_t) -> Result { let repeat = match value { ffi::pixman_repeat_t_PIXMAN_REPEAT_NONE => Repeat::None, ffi::pixman_repeat_t_PIXMAN_REPEAT_NORMAL => Repeat::Normal, ffi::pixman_repeat_t_PIXMAN_REPEAT_PAD => Repeat::Pad, ffi::pixman_repeat_t_PIXMAN_REPEAT_REFLECT => Repeat::Reflect, _ => return Err(UnknownRepeat(value)), }; Ok(repeat) } } impl From for ffi::pixman_repeat_t { fn from(value: Repeat) -> Self { match value { Repeat::None => ffi::pixman_repeat_t_PIXMAN_REPEAT_NONE, Repeat::Normal => ffi::pixman_repeat_t_PIXMAN_REPEAT_NORMAL, Repeat::Pad => ffi::pixman_repeat_t_PIXMAN_REPEAT_PAD, Repeat::Reflect => ffi::pixman_repeat_t_PIXMAN_REPEAT_REFLECT, } } } pixman-0.2.1/src/span.rs000064400000000000000000000023631046102023000132220ustar 00000000000000use crate::{ffi, Fixed}; /// A single span #[derive(Debug, Clone, Copy)] #[repr(transparent)] pub struct Span(ffi::pixman_span_fix_t); impl Span { /// Initialize the span with from the provided components #[inline] pub fn new(l: impl Into, r: impl Into, y: impl Into) -> Self { Self(ffi::pixman_span_fix_t { l: l.into().into_raw(), r: r.into().into_raw(), y: y.into().into_raw(), }) } /// Get the l component of this span #[inline] pub fn l(&self) -> Fixed { Fixed::from(self.0.l) } /// Get the r component of this span #[inline] pub fn r(&self) -> Fixed { Fixed::from(self.0.r) } /// Get the y component of this span #[inline] pub fn y(&self) -> Fixed { Fixed::from(self.0.y) } } impl + Copy> From<[T; 3]> for Span { #[inline] fn from(value: [T; 3]) -> Self { Self::new(value[0], value[1], value[2]) } } impl From for Span { #[inline] fn from(value: ffi::pixman_span_fix_t) -> Self { Self(value) } } impl From for ffi::pixman_span_fix_t { #[inline] fn from(value: Span) -> Self { value.0 } } pixman-0.2.1/src/transform.rs000064400000000000000000000321221046102023000142700ustar 00000000000000use std::mem::MaybeUninit; use paste::paste; use thiserror::Error; use crate::{ffi, FVector, Fixed, Vector}; macro_rules! impl_transform { ($(#[$attr:meta])* $name:ident, ffi => $ffi:path, impl => $impl:ident, vector_t => $vector_t:path$(,)?) => { $(#[$attr])* pub struct $name($ffi); impl $name { /// Transform the provided bounds pub fn transform_bounds(&self, mut b: $crate::Box16) -> Option<$crate::Box16> { let res = unsafe { paste!($crate::ffi::[<$impl _bounds>](self.as_ptr(), &mut b)) }; if res == 1 { Some(b) } else { None } } /// Initialize an identity transform #[inline] pub fn identity() -> Self { let mut transform = MaybeUninit::uninit(); unsafe { paste!($crate::ffi::[<$impl _init_identity>](transform.as_mut_ptr())); } Self(unsafe { transform.assume_init() }) } /// Invert this transform pub fn invert(&self) -> Option { let mut transform = MaybeUninit::uninit(); let res = unsafe { paste!($crate::ffi::[<$impl _invert>](transform.as_mut_ptr(), self.as_ptr())) }; if res == 1 { Some(Self(unsafe { transform.assume_init() })) } else { None } } /// Multiply this transform with the provided transform pub fn multiply(&self, other: &$name) -> Self { let mut transform = MaybeUninit::uninit(); unsafe { paste!($crate::ffi::[<$impl _multiply>](transform.as_mut_ptr(), self.as_ptr(), other.as_ptr())); }; Self(unsafe { transform.assume_init() }) } /// Transform the given point pub fn transform_point(&self, mut vector: $vector_t) -> Option<$vector_t> { let res = unsafe { paste!($crate::ffi::[<$impl _point>](self.as_ptr(), vector.as_mut_ptr())) }; if res == 1 { Some(vector) } else { None } } /// Transform the given point pub fn transform_point_3d(&self, mut vector: $vector_t) -> $vector_t { unsafe { paste!($crate::ffi::[<$impl _point_3d>](self.as_ptr(), vector.as_mut_ptr())) }; vector } #[inline] pub(crate) fn as_ptr(&self) -> *const $ffi { &self.0 as *const $ffi } #[inline] pub(crate) fn as_mut_ptr(&mut self) -> *mut $ffi { &mut self.0 as *mut $ffi } } impl From<$ffi> for $name { #[inline] fn from(value: $ffi) -> Self { Self(value) } } impl From<$name> for $ffi { #[inline] fn from(value: $name) -> Self { value.0 } } }; } impl_transform! { /// Fixed-point transform #[derive(Debug, Clone, Copy)] #[repr(transparent)] Transform, ffi => crate::ffi::pixman_transform_t, impl => pixman_transform, vector_t => Vector, } impl_transform! { /// Floating-point transform #[derive(Debug, Clone, Copy)] #[repr(transparent)] FTransform, ffi => crate::ffi::pixman_f_transform_t, impl => pixman_f_transform, vector_t => FVector, } impl Transform { /// Initialize a transform from the provided matrix #[inline] pub fn new + Copy>(matrix: [[T; 3]; 3]) -> Self { let matrix = [ [ matrix[0][0].into().into_raw(), matrix[0][1].into().into_raw(), matrix[0][2].into().into_raw(), ], [ matrix[1][0].into().into_raw(), matrix[1][1].into().into_raw(), matrix[1][2].into().into_raw(), ], [ matrix[2][0].into().into_raw(), matrix[2][1].into().into_raw(), matrix[2][2].into().into_raw(), ], ]; Self(ffi::pixman_transform { matrix }) } /// Initialize a transform from a rotation #[inline] pub fn from_rotation(cos: impl Into, sin: impl Into) -> Self { let mut transform = MaybeUninit::uninit(); unsafe { ffi::pixman_transform_init_rotate( transform.as_mut_ptr(), cos.into().into_raw(), sin.into().into_raw(), ); } Self(unsafe { transform.assume_init() }) } /// Initialize a transform from a scale #[inline] pub fn from_scale(sx: impl Into, sy: impl Into) -> Self { let mut transform = MaybeUninit::uninit(); unsafe { ffi::pixman_transform_init_scale( transform.as_mut_ptr(), sx.into().into_raw(), sy.into().into_raw(), ); } Self(unsafe { transform.assume_init() }) } /// Initialize a transform from a translation #[inline] pub fn from_translation(tx: impl Into, ty: impl Into) -> Self { let mut transform = MaybeUninit::uninit(); unsafe { ffi::pixman_transform_init_translate( transform.as_mut_ptr(), tx.into().into_raw(), ty.into().into_raw(), ); } Self(unsafe { transform.assume_init() }) } /// Whether this transform represents an identity transform pub fn is_identity(&self) -> bool { unsafe { ffi::pixman_transform_is_identity(self.as_ptr()) == 1 } } /// TODO: Docs pub fn is_int_translate(&self) -> bool { unsafe { ffi::pixman_transform_is_int_translate(self.as_ptr()) == 1 } } /// Whether this transform represents an inverse transform pub fn is_inverse(&self, other: &Transform) -> bool { unsafe { ffi::pixman_transform_is_inverse(self.as_ptr(), other.as_ptr()) == 1 } } /// Whether this transform contains a scale transform pub fn is_scale(&self) -> bool { unsafe { ffi::pixman_transform_is_scale(self.as_ptr()) == 1 } } /// Add a rotation to this transform pub fn rotate( mut self, c: impl Into, s: impl Into, reverse: bool, ) -> Option { let c = c.into().into_raw(); let s = s.into().into_raw(); let res = if reverse { unsafe { ffi::pixman_transform_rotate(std::ptr::null_mut(), self.as_mut_ptr(), c, s) } } else { unsafe { ffi::pixman_transform_rotate(self.as_mut_ptr(), std::ptr::null_mut(), c, s) } }; if res == 1 { Some(self) } else { None } } /// Add a scale to this transform pub fn scale( mut self, sx: impl Into, sy: impl Into, reverse: bool, ) -> Option { let sx = sx.into().into_raw(); let sy = sy.into().into_raw(); let res = if reverse { unsafe { ffi::pixman_transform_scale(std::ptr::null_mut(), self.as_mut_ptr(), sx, sy) } } else { unsafe { ffi::pixman_transform_scale(self.as_mut_ptr(), std::ptr::null_mut(), sx, sy) } }; if res == 1 { Some(self) } else { None } } /// Add a translation to this transform pub fn translate( mut self, tx: impl Into, ty: impl Into, reverse: bool, ) -> Option { let tx = tx.into().into_raw(); let ty = ty.into().into_raw(); let res = if reverse { unsafe { ffi::pixman_transform_translate(std::ptr::null_mut(), self.as_mut_ptr(), tx, ty) } } else { unsafe { ffi::pixman_transform_translate(self.as_mut_ptr(), std::ptr::null_mut(), tx, ty) } }; if res == 1 { Some(self) } else { None } } /// Access the current transform matrix #[inline] pub fn matrix(&self) -> [[Fixed; 3]; 3] { [ [ Fixed::from_raw(self.0.matrix[0][0]), Fixed::from_raw(self.0.matrix[0][1]), Fixed::from_raw(self.0.matrix[0][2]), ], [ Fixed::from_raw(self.0.matrix[1][0]), Fixed::from_raw(self.0.matrix[1][1]), Fixed::from_raw(self.0.matrix[1][2]), ], [ Fixed::from_raw(self.0.matrix[2][0]), Fixed::from_raw(self.0.matrix[2][1]), Fixed::from_raw(self.0.matrix[2][2]), ], ] } } impl + Copy> From<[[T; 3]; 3]> for Transform { #[inline] fn from(value: [[T; 3]; 3]) -> Self { Transform::new(value) } } /// Failed to init Transform from FTransform #[derive(Debug, Error)] #[error("Failed to init Transform from FTransform")] pub struct TransformConvertError; impl TryFrom for Transform { type Error = TransformConvertError; fn try_from(value: FTransform) -> Result { let mut transform = MaybeUninit::uninit(); let res = unsafe { ffi::pixman_transform_from_pixman_f_transform(transform.as_mut_ptr(), value.as_ptr()) }; if res != 1 { Err(TransformConvertError) } else { Ok(Self(unsafe { transform.assume_init() })) } } } impl FTransform { /// Initialize a transform from the provided matrix #[inline] pub fn new(m: [[f64; 3]; 3]) -> Self { let m = [ [m[0][0], m[0][1], m[0][2]], [m[1][0], m[1][1], m[1][2]], [m[2][0], m[2][1], m[2][2]], ]; Self(ffi::pixman_f_transform_t { m }) } /// Initialize a transform from a rotation #[inline] pub fn from_rotation(cos: f64, sin: f64) -> Self { let mut transform = MaybeUninit::uninit(); unsafe { ffi::pixman_f_transform_init_rotate(transform.as_mut_ptr(), cos, sin); } Self(unsafe { transform.assume_init() }) } /// Initialize a transform from a scale #[inline] pub fn from_scale(sx: f64, sy: f64) -> Self { let mut transform = MaybeUninit::uninit(); unsafe { ffi::pixman_f_transform_init_scale(transform.as_mut_ptr(), sx, sy); } Self(unsafe { transform.assume_init() }) } /// Initialize a transform from a translation #[inline] pub fn from_translation(tx: f64, ty: f64) -> Self { let mut transform = MaybeUninit::uninit(); unsafe { ffi::pixman_f_transform_init_translate(transform.as_mut_ptr(), tx, ty); } Self(unsafe { transform.assume_init() }) } /// Add a rotation to this transform pub fn rotate(mut self, c: f64, s: f64, reverse: bool) -> Option { let res = if reverse { unsafe { ffi::pixman_f_transform_rotate(std::ptr::null_mut(), self.as_mut_ptr(), c, s) } } else { unsafe { ffi::pixman_f_transform_rotate(self.as_mut_ptr(), std::ptr::null_mut(), c, s) } }; if res == 1 { Some(self) } else { None } } /// Add a scale to this transform pub fn scale(mut self, sx: f64, sy: f64, reverse: bool) -> Option { let res = if reverse { unsafe { ffi::pixman_f_transform_scale(std::ptr::null_mut(), self.as_mut_ptr(), sx, sy) } } else { unsafe { ffi::pixman_f_transform_scale(self.as_mut_ptr(), std::ptr::null_mut(), sx, sy) } }; if res == 1 { Some(self) } else { None } } /// Add a translation to this transform pub fn translate(mut self, tx: f64, ty: f64, reverse: bool) -> Option { let res = if reverse { unsafe { ffi::pixman_f_transform_translate(std::ptr::null_mut(), self.as_mut_ptr(), tx, ty) } } else { unsafe { ffi::pixman_f_transform_translate(self.as_mut_ptr(), std::ptr::null_mut(), tx, ty) } }; if res == 1 { Some(self) } else { None } } /// Access the current transform matrix #[inline] pub fn matrix(&self) -> [[f64; 3]; 3] { self.0.m } } impl From<[[f64; 3]; 3]> for FTransform { #[inline] fn from(value: [[f64; 3]; 3]) -> Self { FTransform::new(value) } } impl From for FTransform { fn from(value: Transform) -> Self { let mut transform = MaybeUninit::uninit(); unsafe { ffi::pixman_f_transform_from_pixman_transform(transform.as_mut_ptr(), value.as_ptr()); } Self(unsafe { transform.assume_init() }) } } pixman-0.2.1/src/trap.rs000064400000000000000000000016111046102023000132220ustar 00000000000000use crate::{ffi, Span}; /// A single trap #[derive(Debug, Clone, Copy)] #[repr(transparent)] pub struct Trap(ffi::pixman_trap_t); impl Trap { /// Initialize the trap from the provided values #[inline] pub fn new(top: impl Into, bot: impl Into) -> Self { Self(ffi::pixman_trap_t { top: top.into().into(), bot: bot.into().into(), }) } /// Access the top value of this trap #[inline] pub fn top(&self) -> Span { Span::from(self.0.top) } /// Access the bot value of this trap #[inline] pub fn bot(&self) -> Span { Span::from(self.0.bot) } } impl From for Trap { #[inline] fn from(value: ffi::pixman_trap_t) -> Self { Self(value) } } impl From for ffi::pixman_trap_t { #[inline] fn from(value: Trap) -> Self { value.0 } } pixman-0.2.1/src/trapezoid.rs000064400000000000000000000030251046102023000142560ustar 00000000000000use crate::{ffi, Fixed, Line}; /// A trapezoid #[derive(Debug, Clone, Copy)] #[repr(transparent)] pub struct Trapezoid(ffi::pixman_trapezoid_t); impl Trapezoid { /// Initialize a trapezoid from the provided values #[inline] pub fn new( top: impl Into, bottom: impl Into, left: impl Into, right: impl Into, ) -> Self { Self(ffi::pixman_trapezoid_t { top: top.into().into_raw(), bottom: bottom.into().into_raw(), left: left.into().into(), right: right.into().into(), }) } /// Access the top component of the trapezoid #[inline] pub fn top(&self) -> Fixed { Fixed::from(self.0.top) } /// Access the bottom component of the trapezoid #[inline] pub fn bottom(&self) -> Fixed { Fixed::from(self.0.bottom) } /// Access the left component of the trapezoid #[inline] pub fn left(&self) -> Line { Line::from(self.0.left) } /// Access the right component of the trapezoid #[inline] pub fn right(&self) -> Line { Line::from(self.0.right) } #[inline] pub(crate) fn as_ptr(&self) -> *const ffi::pixman_trapezoid_t { &self.0 } } impl From for Trapezoid { #[inline] fn from(value: ffi::pixman_trapezoid_t) -> Self { Self(value) } } impl From for ffi::pixman_trapezoid_t { #[inline] fn from(value: Trapezoid) -> Self { value.0 } } pixman-0.2.1/src/triangle.rs000064400000000000000000000023741046102023000140700ustar 00000000000000use crate::{ffi, Point}; /// A triangle #[derive(Debug, Clone, Copy)] #[repr(transparent)] pub struct Triangle(ffi::pixman_triangle_t); impl Triangle { /// Initialize the triangle from the provided values pub fn new(p1: impl Into, p2: impl Into, p3: impl Into) -> Self { Self(ffi::pixman_triangle_t { p1: p1.into().into(), p2: p2.into().into(), p3: p3.into().into(), }) } /// Access the first point of this triangle #[inline] pub fn p1(&self) -> Point { self.0.p1.into() } /// Access the second point of this triangle #[inline] pub fn p2(&self) -> Point { self.0.p2.into() } /// Access the third point of this triangle #[inline] pub fn p3(&self) -> Point { self.0.p3.into() } } impl + Copy> From<[P; 3]> for Triangle { #[inline] fn from(value: [P; 3]) -> Self { Self::new(value[0], value[1], value[2]) } } impl From for Triangle { #[inline] fn from(value: ffi::pixman_triangle_t) -> Self { Self(value) } } impl From for ffi::pixman_triangle_t { #[inline] fn from(value: Triangle) -> Self { value.0 } } pixman-0.2.1/src/vector.rs000064400000000000000000000050561046102023000135650ustar 00000000000000use crate::{ffi, Fixed}; /// A single vector #[derive(Debug, Clone, Copy)] #[repr(transparent)] pub struct Vector(ffi::pixman_vector_t); impl Vector { /// Initialize a vector from the provided values #[inline] pub fn new + Copy>(vector: [T; 3]) -> Self { Self(ffi::pixman_vector { vector: [ vector[0].into().into_raw(), vector[1].into().into_raw(), vector[2].into().into_raw(), ], }) } /// Access the x component of this vector pub fn x(&self) -> Fixed { Fixed::from_raw(self.0.vector[0]) } /// Access the y component of this vector pub fn y(&self) -> Fixed { Fixed::from_raw(self.0.vector[1]) } /// Access the z component of this vector pub fn z(&self) -> Fixed { Fixed::from_raw(self.0.vector[2]) } #[inline] pub(crate) fn as_mut_ptr(&mut self) -> *mut ffi::pixman_vector_t { &mut self.0 as *mut ffi::pixman_vector_t } } impl + Copy> From<[T; 3]> for Vector { #[inline] fn from(value: [T; 3]) -> Self { Self::new(value) } } impl From for Vector { #[inline] fn from(value: ffi::pixman_vector_t) -> Self { Self(value) } } impl From for ffi::pixman_vector_t { #[inline] fn from(value: Vector) -> Self { value.0 } } /// Floating-point vector #[derive(Debug, Clone, Copy)] #[repr(transparent)] pub struct FVector(ffi::pixman_f_vector_t); impl FVector { /// Initialize the vector from the specified values #[inline] pub fn new(v: [f64; 3]) -> Self { Self(ffi::pixman_f_vector_t { v: [v[0], v[1], v[2]], }) } /// Access the x component of this vector pub fn x(&self) -> f64 { self.0.v[0] } /// Access the y component of this vector pub fn y(&self) -> f64 { self.0.v[1] } /// Access the z component of this vector pub fn z(&self) -> f64 { self.0.v[2] } #[inline] pub(crate) fn as_mut_ptr(&mut self) -> *mut ffi::pixman_f_vector_t { &mut self.0 as *mut ffi::pixman_f_vector_t } } impl From<[f64; 3]> for FVector { #[inline] fn from(value: [f64; 3]) -> Self { Self::new(value) } } impl From for FVector { #[inline] fn from(value: ffi::pixman_f_vector_t) -> Self { Self(value) } } impl From for ffi::pixman_f_vector_t { #[inline] fn from(value: FVector) -> Self { value.0 } }