From c69c14e5bea1c9c34d81d3ab1eeeb8e97a15b03d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?joseLu=C3=ADs?= Date: Sun, 27 Jun 2021 13:12:26 +0200 Subject: [PATCH] [rust] keep on solving multiple architecture bugs #1339 - fix notcurses_debug test on s390x & ppc64le. - fix NcChannels parameters for NcPlane methods gradient & gradient_sized. - fix ncplane_gradient & ncplane_gradient_sized on i686 & arm7hl by reimplementing them as a thin wrapper. - fix ncdirect_hline_interp & ncdirect_vline_interp on i686 & arm7hl by reimplementing them as a thin wrapper. - fix some docs & do some minimal refactoring. --- rust/src/bindings.rs | 6 +- rust/src/direct/methods.rs | 5 +- rust/src/direct/reimplemented.rs | 58 +++++++++++++++- rust/src/notcurses/test/reimplemented.rs | 5 ++ rust/src/plane/methods.rs | 43 +++++------- rust/src/plane/reimplemented.rs | 85 ++++++++++++++++++++---- 6 files changed, 155 insertions(+), 47 deletions(-) diff --git a/rust/src/bindings.rs b/rust/src/bindings.rs index 03acf404b..dffa4793e 100644 --- a/rust/src/bindings.rs +++ b/rust/src/bindings.rs @@ -155,6 +155,8 @@ pub use ffi::{ // ncdirect_canquadrant, // ncdirect_cantruecolor, // ncdirect_capabilities, +// ncdirect_hline_interp, +// ncdirect_vline_interp, // // // constants // NCDIRECT_OPTION_INHIBIT_CBREAK, @@ -189,7 +191,6 @@ pub use ffi::{ ncdirect_double_box, ncdirect_flush, ncdirect_getc, - ncdirect_hline_interp, ncdirect_init, ncdirect_inputready_fd, ncdirect_off_styles, @@ -213,7 +214,6 @@ pub use ffi::{ ncdirect_stream, ncdirect_styles, ncdirect_supported_styles, - ncdirect_vline_interp, }; // ncdirectf -------------------------------------------------------------------- @@ -377,6 +377,7 @@ pub use ffi::{ // // // functions // ncplane_channels, +// ncplane_gradient, // ncplane_set_bchannel, // ncplane_set_fchannel, // ncplane_set_channels, @@ -419,7 +420,6 @@ pub use ffi::{ ncplane_fadeout, ncplane_fadeout_iteration, ncplane_format, - ncplane_gradient, ncplane_greyscale, ncplane_highgradient, ncplane_highgradient_sized, diff --git a/rust/src/direct/methods.rs b/rust/src/direct/methods.rs index 108e62a69..f2b91e498 100644 --- a/rust/src/direct/methods.rs +++ b/rust/src/direct/methods.rs @@ -740,6 +740,7 @@ impl NcDirect { crate::ncdirect_rounded_box(self, ul, ur, ll, lr, y_len as i32, x_len as i32, ctlword) }] } + /// Draws horizontal lines using the specified [NcChannels]s, interpolating /// between them as we go. /// @@ -759,7 +760,7 @@ impl NcDirect { h1: NcChannels, h2: NcChannels, ) -> NcResult<()> { - error![unsafe { crate::ncdirect_hline_interp(self, cstring![egc], len as i32, h1, h2) }] + error![crate::ncdirect_hline_interp(self, egc, len, h1, h2)] } /// Draws horizontal lines using the specified [NcChannels]s, interpolating @@ -781,6 +782,6 @@ impl NcDirect { h1: NcChannels, h2: NcChannels, ) -> NcResult<()> { - error![unsafe { crate::ncdirect_vline_interp(self, cstring![egc], len as i32, h1, h2) }] + error![crate::ncdirect_vline_interp(self, egc, len, h1, h2)] } } diff --git a/rust/src/direct/reimplemented.rs b/rust/src/direct/reimplemented.rs index 21fdea585..63409a378 100644 --- a/rust/src/direct/reimplemented.rs +++ b/rust/src/direct/reimplemented.rs @@ -3,7 +3,8 @@ use core::ptr::null; use crate::{ - NcCapabilities, NcComponent, NcDirect, NcInput, NcIntResult, NcRgb, NcSignalSet, NcTime, + cstring, NcCapabilities, NcChannels, NcComponent, NcDim, NcDirect, NcInput, NcIntResult, NcRgb, + NcSignalSet, NcTime, }; /// Can we directly specify RGB values per cell, or only use palettes? @@ -117,3 +118,58 @@ pub fn ncdirect_set_bg_rgb8( let rgb = (red as NcRgb) << 16 | (green as NcRgb) << 8 | blue as NcRgb; unsafe { crate::ncdirect_set_bg_rgb(ncd, rgb) } } + +/// Draws horizontal lines using the specified [NcChannels]s, interpolating +/// between them as we go. +/// +/// The string at `egc` may not use more than one column. +/// +/// All lines start at the current cursor position. +/// +/// For a horizontal line, `len` cannot exceed the screen width minus the +/// cursor's offset. +// TODO:MAYBE saturate the `len` value +/// +/// *Method: NcDirect.[hline_interp()][NcDirect#method.hline_interp].* +#[inline] +pub fn ncdirect_hline_interp( + ncd: &mut NcDirect, + egc: &str, + len: NcDim, + h1: NcChannels, + h2: NcChannels, +) -> NcIntResult { + #[cfg(any(target_arch = "armv7l", target_arch = "i686"))] + let egc_ptr = cstring![egc] as *const i8; + #[cfg(not(any(target_arch = "armv7l", target_arch = "i686")))] + let egc_ptr = cstring![egc]; + + unsafe { crate::bindings::ffi::ncdirect_hline_interp(ncd, egc_ptr, len as i32, h1, h2) } +} + +/// Draws horizontal lines using the specified [NcChannels]s, interpolating +/// between them as we go. +/// +/// The string at `egc` may not use more than one column. +/// +/// All lines start at the current cursor position. +/// +/// For a vertical line, `len` may be as long as you'd like; the screen +/// will scroll as necessary. +/// +/// *Method: NcDirect.[vline_interp()][NcDirect#method.vline_interp].* +#[inline] +pub fn ncdirect_vline_interp( + ncd: &mut NcDirect, + egc: &str, + len: NcDim, + h1: NcChannels, + h2: NcChannels, +) -> NcIntResult { + #[cfg(any(target_arch = "armv7l", target_arch = "i686"))] + let egc_ptr = cstring![egc] as *const i8; + #[cfg(not(any(target_arch = "armv7l", target_arch = "i686")))] + let egc_ptr = cstring![egc]; + + unsafe { crate::bindings::ffi::ncdirect_vline_interp(ncd, egc_ptr, len as i32, h1, h2) } +} diff --git a/rust/src/notcurses/test/reimplemented.rs b/rust/src/notcurses/test/reimplemented.rs index bc811782e..0525fe3b4 100644 --- a/rust/src/notcurses/test/reimplemented.rs +++ b/rust/src/notcurses/test/reimplemented.rs @@ -146,7 +146,12 @@ fn notcurses_at_yx() { fn notcurses_debug() { unsafe { let nc = notcurses_init_test(); + + #[cfg(any(target_arch = "s390x", target_arch = "ppc64le"))] + let mut _p: *mut u8 = &mut 0; + #[cfg(not(any(target_arch = "s390x", target_arch = "ppc64le")))] let mut _p: *mut i8 = &mut 0; + let mut _size: *mut usize = &mut 0; let mut file = NcFile::from_libc(libc::open_memstream(&mut _p, _size)); crate::notcurses_debug(nc, file.as_nc_ptr()); diff --git a/rust/src/plane/methods.rs b/rust/src/plane/methods.rs index da9a41a39..ed2fdbc77 100644 --- a/rust/src/plane/methods.rs +++ b/rust/src/plane/methods.rs @@ -206,6 +206,13 @@ impl NcPlane { crate::ncplane_channels(self) } + /// Sets the current [`NcChannels`] for this `NcPlane`. + /// + /// *C style function: [ncplane_set_channels()][crate::ncplane_set_channels].* + pub fn set_channels(&mut self, channels: NcChannels) { + crate::ncplane_set_channels(self, channels); + } + /// Gets the foreground [`NcChannel`] from an [NcPlane]. /// /// *C style function: [ncplane_fchannel()][crate::ncplane_fchannel].* @@ -222,13 +229,6 @@ impl NcPlane { crate::ncchannels_bchannel(crate::ncplane_channels(self)) } - /// Sets the current [`NcChannels`] for this `NcPlane`. - /// - /// *C style function: [ncplane_set_channels()][crate::ncplane_set_channels].* - pub fn set_channels(&mut self, channels: NcChannels) { - crate::ncplane_set_channels(self, channels); - } - /// Sets the current foreground [`NcChannel`] for this `NcPlane`. /// Returns the updated [`NcChannels`]. /// @@ -790,9 +790,8 @@ impl NcPlane { /// Writes a string to the current location, using the current style. /// - /// Advances the cursor by some positive number of columns - /// (though not beyond the end of the plane), - /// and this number is returned on success. + /// Advances the cursor by some positive number of columns (though not + /// beyond the end of the plane), and this number is returned on success. /// /// On error, a non-positive number is returned, indicating /// the number of columns which were written before the error. @@ -854,7 +853,7 @@ impl NcPlane { ] } - /// Write a string to the provided location, using the current style. + /// Writes a string to the provided location, using the current style. /// /// They will be interpreted as a series of columns. /// @@ -1936,19 +1935,7 @@ impl NcPlane { y_stop: NcDim, x_stop: NcDim, ) -> NcResult { - let res = unsafe { - crate::ncplane_gradient( - self, - cstring![egc], - stylemask as u32, - ul, - ur, - ll, - lr, - y_stop as i32, - x_stop as i32, - ) - }; + let res = crate::ncplane_gradient(self, egc, stylemask, ul, ur, ll, lr, y_stop, x_stop); error![res, "", res as NcDim] } @@ -1963,10 +1950,10 @@ impl NcPlane { &mut self, egc: &str, stylemask: NcStyle, - ul: NcChannel, - ur: NcChannel, - ll: NcChannel, - lr: NcChannel, + ul: NcChannels, + ur: NcChannels, + ll: NcChannels, + lr: NcChannels, y_len: NcDim, x_len: NcDim, ) -> NcResult { diff --git a/rust/src/plane/reimplemented.rs b/rust/src/plane/reimplemented.rs index a987e8bb5..9b5fb1b6e 100644 --- a/rust/src/plane/reimplemented.rs +++ b/rust/src/plane/reimplemented.rs @@ -740,6 +740,65 @@ pub fn ncplane_rounded_box_sized( // gradient -------------------------------------------------------------------- +/// Draws a gradient with its upper-left corner at the current cursor position, +/// stopping at `ystop`×`xstop`. +/// +/// The glyph composed of `egc` and `stylemask` is used for all cells. The +/// `NcChannels` specified by `ul`, `ur`, `ll`, and `lr` are composed into +/// foreground and background gradients. +/// +/// - To do a vertical gradient, `ul` ought equal `ur` and `ll` ought equal `lr`. +/// - To do a horizontal gradient, `ul` ought equal `ll` and `ur` ought equal `ul`. +/// - To color everything the same, all four channels should be equivalent. The +/// resulting alpha values are equal to incoming alpha values. Returns the number +/// of cells filled on success, or -1 on failure. +/// +/// Palette-indexed color is not supported. +/// +/// Preconditions for gradient operations (error otherwise): +/// - all: only RGB colors, unless all four channels match as default +/// - all: all alpha values must be the same +/// - 1x1: all four colors must be the same +/// - 1xN: both top and both bottom colors must be the same (vertical gradient) +/// - Nx1: both left and both right colors must be the same (horizontal gradient) +/// +/// *Method: NcPlane.[gradient()][NcPlane#method.gradient].* +#[inline] +pub fn ncplane_gradient( + plane: &mut NcPlane, + egc: &str, + stylemask: NcStyle, + ul: NcChannels, + ur: NcChannels, + ll: NcChannels, + lr: NcChannels, + y_len: NcDim, + x_len: NcDim, +) -> NcIntResult { + if y_len < 1 || x_len < 1 { + return NCRESULT_ERR; + } + + #[cfg(any(target_arch = "armv7l", target_arch = "i686"))] + let egc_ptr = cstring![egc] as *const i8; + #[cfg(not(any(target_arch = "armv7l", target_arch = "i686")))] + let egc_ptr = cstring![egc]; + + unsafe { + crate::bindings::ffi::ncplane_gradient( + plane, + egc_ptr, + stylemask as u32, + ul, + ur, + ll, + lr, + y_len as i32, + x_len as i32, + ) + } +} + /// Draw a gradient with its upper-left corner at the current cursor position, /// having dimensions `y_len` * `x_len`. /// @@ -751,10 +810,10 @@ pub fn ncplane_gradient_sized( plane: &mut NcPlane, egc: &str, stylemask: NcStyle, - ul: NcChannel, - ur: NcChannel, - ll: NcChannel, - lr: NcChannel, + ul: NcChannels, + ur: NcChannels, + ll: NcChannels, + lr: NcChannels, y_len: NcDim, x_len: NcDim, ) -> NcIntResult { @@ -764,16 +823,16 @@ pub fn ncplane_gradient_sized( let (mut y, mut x) = (0, 0); unsafe { crate::ncplane_cursor_yx(plane, &mut y, &mut x); - crate::ncplane_gradient( + ncplane_gradient( plane, - cstring![egc], - stylemask as u32, - ul as u64, - ur as u64, - ll as u64, - lr as u64, - y + y_len as i32 - 1, - x + x_len as i32 - 1, + egc, + stylemask, + ul, + ur, + ll, + lr, + y as u32 + y_len - 1, + x as u32 + x_len - 1, ) } }