<commit_before>use std::collections::vec_deque::IntoIter as VecDequeIter;

use CreationError;
use CursorState;
use EventsLoop;
use MouseCursor;
use Window;
use WindowBuilder;
use WindowId;

use libc;
use platform;

impl WindowBuilder {
    /// Initializes a new `WindowBuilder` with default values.
    #[inline]
    pub fn new() -> WindowBuilder {
        WindowBuilder {
            window: Default::default(),
            platform_specific: Default::default(),
        }
    }

    /// Requests the window to be of specific dimensions.
    ///
    /// Width and height are in pixels.
    #[inline]
    pub fn with_dimensions(mut self, width: u32, height: u32) -> WindowBuilder {
        self.window.dimensions = Some((width, height));
        self
    }

    /// Sets a minimum dimension size for the window
    ///
    /// Width and height are in pixels.
    #[inline]
    pub fn with_min_dimensions(mut self, width: u32, height: u32) -> WindowBuilder {
        self.window.min_dimensions = Some((width, height));
        self
    }

    /// Sets a maximum dimension size for the window
    ///
    /// Width and height are in pixels.
    #[inline]
    pub fn with_max_dimensions(mut self, width: u32, height: u32) -> WindowBuilder {
        self.window.max_dimensions = Some((width, height));
        self
    }

    /// Requests a specific title for the window.
    #[inline]
    pub fn with_title<T: Into<String>>(mut self, title: T) -> WindowBuilder {
        self.window.title = title.into();
        self
    }

    /// Sets the window fullscreen state. None means a normal window, Some(MonitorId)
    /// means a fullscreen window on that specific monitor
    #[inline]
    pub fn with_fullscreen(mut self, monitor: Option<MonitorId>) -> WindowBuilder {
        self.window.fullscreen = monitor;
        self
    }

    /// Requests maximized mode.
    #[inline]
    pub fn with_maximized(mut self, maximized: bool) -> WindowBuilder {
        self.window.maximized = maximized;
        self
    }

    /// Sets whether the window will be initially hidden or visible.
    #[inline]
    pub fn with_visibility(mut self, visible: bool) -> WindowBuilder {
        self.window.visible = visible;
        self
    }

    /// Sets whether the background of the window should be transparent.
    #[inline]
    pub fn with_transparency(mut self, transparent: bool) -> WindowBuilder {
        self.window.transparent = transparent;
        self
    }

    /// Sets whether the window should have a border, a title bar, etc.
    #[inline]
    pub fn with_decorations(mut self, decorations: bool) -> WindowBuilder {
        self.window.decorations = decorations;
        self
    }

    /// Enables multitouch.
    #[inline]
    pub fn with_multitouch(mut self) -> WindowBuilder {
        self.window.multitouch = true;
        self
    }

    /// Builds the window.
    ///
    /// Error should be very rare and only occur in case of permission denied, incompatible system,
    /// out of memory, etc.
    pub fn build(mut self, events_loop: &EventsLoop) -> Result<Window, CreationError> {
        // resizing the window to the dimensions of the monitor when fullscreen
        if self.window.dimensions.is_none() {
            if let Some(ref monitor) = self.window.fullscreen {
                self.window.dimensions = Some(monitor.get_dimensions());
            }
        }

        // default dimensions
        if self.window.dimensions.is_none() {
            self.window.dimensions = Some((1024, 768));
        }

        // building
        let w = try!(platform::Window::new(&events_loop.events_loop, &self.window, &self.platform_specific));

        Ok(Window { window: w })
    }
}

impl Window {
    /// Creates a new Window for platforms where this is appropriate.
    ///
    /// This function is equivalent to `WindowBuilder::new().build(events_loop)`.
    ///
    /// Error should be very rare and only occur in case of permission denied, incompatible system,
    ///  out of memory, etc.
    #[inline]
    pub fn new(events_loop: &EventsLoop) -> Result<Window, CreationError> {
        let builder = WindowBuilder::new();
        builder.build(events_loop)
    }

    /// Modifies the title of the window.
    ///
    /// This is a no-op if the window has already been closed.
    #[inline]
    pub fn set_title(&self, title: &str) {
        self.window.set_title(title)
    }

    /// Shows the window if it was hidden.
    ///
    /// ## Platform-specific
    ///
    /// - Has no effect on Android
    ///
    #[inline]
    pub fn show(&self) {
        self.window.show()
    }

    /// Hides the window if it was visible.
    ///
    /// ## Platform-specific
    ///
    /// - Has no effect on Android
    ///
    #[inline]
    pub fn hide(&self) {
        self.window.hide()
    }

    /// Returns the position of the top-left hand corner of the window relative to the
    ///  top-left hand corner of the desktop.
    ///
    /// Note that the top-left hand corner of the desktop is not necessarily the same as
    ///  the screen. If the user uses a desktop with multiple monitors, the top-left hand corner
    ///  of the desktop is the top-left hand corner of the monitor at the top-left of the desktop.
    ///
    /// The coordinates can be negative if the top-left hand corner of the window is outside
    ///  of the visible screen region.
    ///
    /// Returns `None` if the window no longer exists.
    #[inline]
    pub fn get_position(&self) -> Option<(i32, i32)> {
        self.window.get_position()
    }

    /// Modifies the position of the window.
    ///
    /// See `get_position` for more information about the coordinates.
    ///
    /// This is a no-op if the window has already been closed.
    #[inline]
    pub fn set_position(&self, x: i32, y: i32) {
        self.window.set_position(x, y)
    }

    /// Returns the size in pixels of the client area of the window.
    ///
    /// The client area is the content of the window, excluding the title bar and borders.
    /// These are the dimensions that need to be supplied to `glViewport`.
    ///
    /// Returns `None` if the window no longer exists.
    #[inline]
    pub fn get_inner_size(&self) -> Option<(u32, u32)> {
        self.window.get_inner_size()
    }

    /// Returns the size in points of the client area of the window.
    ///
    /// The client area is the content of the window, excluding the title bar and borders.
    /// To get the dimensions of the frame buffer when calling `glViewport`, multiply with hidpi factor.
    ///
    /// Returns `None` if the window no longer exists.
    ///
    /// DEPRECATED
    #[inline]
    #[deprecated]
    pub fn get_inner_size_points(&self) -> Option<(u32, u32)> {
        self.window.get_inner_size().map(|(x, y)| {
            let hidpi = self.hidpi_factor();
            ((x as f32 / hidpi) as u32, (y as f32 / hidpi) as u32)
        })
    }

    /// Returns the size in pixels of the client area of the window.
    ///
    /// The client area is the content of the window, excluding the title bar and borders.
    /// These are the dimensions of the frame buffer, and the dimensions that you should use
    ///  when you call `glViewport`.
    ///
    /// Returns `None` if the window no longer exists.
    ///
    /// DEPRECATED
    #[inline]
    #[deprecated]
    pub fn get_inner_size_pixels(&self) -> Option<(u32, u32)> {
        self.window.get_inner_size()
    }

    /// Returns the size in pixels of the window.
    ///
    /// These dimensions include title bar and borders. If you don't want these, you should use
    ///  use `get_inner_size` instead.
    ///
    /// Returns `None` if the window no longer exists.
    #[inline]
    pub fn get_outer_size(&self) -> Option<(u32, u32)> {
        self.window.get_outer_size()
    }

    /// Modifies the inner size of the window.
    ///
    /// See `get_inner_size` for more information about the values.
    ///
    /// This is a no-op if the window has already been closed.
    #[inline]
    pub fn set_inner_size(&self, x: u32, y: u32) {
        self.window.set_inner_size(x, y)
    }

    /// Sets a minimum dimension size for the window.
    ///
    /// Width and height are in pixels.
    #[inline]
    pub fn set_min_dimensions(&self, dimensions: Option<(u32, u32)>) {
        self.window.set_min_dimensions(dimensions)
    }

    /// Sets a maximum dimension size for the window.
    ///
    /// Width and height are in pixels.
    #[inline]
    pub fn set_max_dimensions(&self, dimensions: Option<(u32, u32)>) {
        self.window.set_max_dimensions(dimensions)
    }

    /// DEPRECATED. Gets the native platform specific display for this window.
    /// This is typically only required when integrating with
    /// other libraries that need this information.
    #[deprecated]
    #[inline]
    pub unsafe fn platform_display(&self) -> *mut libc::c_void {
        self.window.platform_display()
    }

    /// DEPRECATED. Gets the native platform specific window handle. This is
    /// typically only required when integrating with other libraries
    /// that need this information.
    #[deprecated]
    #[inline]
    pub unsafe fn platform_window(&self) -> *mut libc::c_void {
        self.window.platform_window()
    }

    /// Modifies the mouse cursor of the window.
    /// Has no effect on Android.
    pub fn set_cursor(&self, cursor: MouseCursor) {
        self.window.set_cursor(cursor);
    }

    /// Returns the ratio between the backing framebuffer resolution and the
    /// window size in screen pixels. This is typically one for a normal display
    /// and two for a retina display.
    #[inline]
    pub fn hidpi_factor(&self) -> f32 {
        self.window.hidpi_factor()
    }

    /// Changes the position of the cursor in window coordinates.
    #[inline]
    pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> {
        self.window.set_cursor_position(x, y)
    }

    /// Sets how winit handles the cursor. See the documentation of `CursorState` for details.
    ///
    /// Has no effect on Android.
    #[inline]
    pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> {
        self.window.set_cursor_state(state)
    }

    /// Sets the window to maximized or back
    #[inline]
    pub fn set_maximized(&self, maximized: bool) {
        self.window.set_maximized(maximized)
    }

    /// Sets the window to fullscreen or back
    #[inline]
    pub fn set_fullscreen(&self, monitor: Option<MonitorId>) {
        self.window.set_fullscreen(monitor)
    }

    /// Turn window decorations on or off.
    #[inline]
    pub fn set_decorations(&self, decorations: bool) {
        self.window.set_decorations(decorations)
    }

    /// Returns the current monitor the window is on or the primary monitor is nothing
    /// matches
    pub fn get_current_monitor(&self) -> MonitorId {
        self.window.get_current_monitor()
    }

    #[inline]
    pub fn id(&self) -> WindowId {
        WindowId(self.window.id())
    }
}

/// An iterator for the list of available monitors.
// Implementation note: we retrieve the list once, then serve each element by one by one.
// This may change in the future.
pub struct AvailableMonitorsIter {
    pub(crate) data: VecDequeIter<platform::MonitorId>,
}

impl Iterator for AvailableMonitorsIter {
    type Item = MonitorId;

    #[inline]
    fn next(&mut self) -> Option<MonitorId> {
        self.data.next().map(|id| MonitorId { inner: id })
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.data.size_hint()
    }
}

/// Identifier for a monitor.
#[derive(Clone)]
pub struct MonitorId {
    pub(crate) inner: platform::MonitorId
}

impl MonitorId {
    /// Returns a human-readable name of the monitor.
    ///
    /// Returns `None` if the monitor doesn't exist anymore.
    #[inline]
    pub fn get_name(&self) -> Option<String> {
        self.inner.get_name()
    }

    /// Returns the number of pixels currently displayed on the monitor.
    #[inline]
    pub fn get_dimensions(&self) -> (u32, u32) {
        self.inner.get_dimensions()
    }

    /// Returns the top-left corner position of the monitor relative to the larger full
    /// screen area.
    #[inline]
    pub fn get_position(&self) -> (i32, i32) {
        self.inner.get_position()
    }

    /// Returns the ratio between the monitor's physical pixels and logical pixels.
    #[inline]
    pub fn get_hidpi_factor(&self) -> f32 {
        self.inner.get_hidpi_factor()
    }
}
<commit_msg>[ci skip] Doc fix for struct winit::Window (#452)<commit_after>use std::collections::vec_deque::IntoIter as VecDequeIter;

use CreationError;
use CursorState;
use EventsLoop;
use MouseCursor;
use Window;
use WindowBuilder;
use WindowId;

use libc;
use platform;

impl WindowBuilder {
    /// Initializes a new `WindowBuilder` with default values.
    #[inline]
    pub fn new() -> WindowBuilder {
        WindowBuilder {
            window: Default::default(),
            platform_specific: Default::default(),
        }
    }

    /// Requests the window to be of specific dimensions.
    ///
    /// Width and height are in pixels.
    #[inline]
    pub fn with_dimensions(mut self, width: u32, height: u32) -> WindowBuilder {
        self.window.dimensions = Some((width, height));
        self
    }

    /// Sets a minimum dimension size for the window
    ///
    /// Width and height are in pixels.
    #[inline]
    pub fn with_min_dimensions(mut self, width: u32, height: u32) -> WindowBuilder {
        self.window.min_dimensions = Some((width, height));
        self
    }

    /// Sets a maximum dimension size for the window
    ///
    /// Width and height are in pixels.
    #[inline]
    pub fn with_max_dimensions(mut self, width: u32, height: u32) -> WindowBuilder {
        self.window.max_dimensions = Some((width, height));
        self
    }

    /// Requests a specific title for the window.
    #[inline]
    pub fn with_title<T: Into<String>>(mut self, title: T) -> WindowBuilder {
        self.window.title = title.into();
        self
    }

    /// Sets the window fullscreen state. None means a normal window, Some(MonitorId)
    /// means a fullscreen window on that specific monitor
    #[inline]
    pub fn with_fullscreen(mut self, monitor: Option<MonitorId>) -> WindowBuilder {
        self.window.fullscreen = monitor;
        self
    }

    /// Requests maximized mode.
    #[inline]
    pub fn with_maximized(mut self, maximized: bool) -> WindowBuilder {
        self.window.maximized = maximized;
        self
    }

    /// Sets whether the window will be initially hidden or visible.
    #[inline]
    pub fn with_visibility(mut self, visible: bool) -> WindowBuilder {
        self.window.visible = visible;
        self
    }

    /// Sets whether the background of the window should be transparent.
    #[inline]
    pub fn with_transparency(mut self, transparent: bool) -> WindowBuilder {
        self.window.transparent = transparent;
        self
    }

    /// Sets whether the window should have a border, a title bar, etc.
    #[inline]
    pub fn with_decorations(mut self, decorations: bool) -> WindowBuilder {
        self.window.decorations = decorations;
        self
    }

    /// Enables multitouch.
    #[inline]
    pub fn with_multitouch(mut self) -> WindowBuilder {
        self.window.multitouch = true;
        self
    }

    /// Builds the window.
    ///
    /// Error should be very rare and only occur in case of permission denied, incompatible system,
    /// out of memory, etc.
    pub fn build(mut self, events_loop: &EventsLoop) -> Result<Window, CreationError> {
        // resizing the window to the dimensions of the monitor when fullscreen
        if self.window.dimensions.is_none() {
            if let Some(ref monitor) = self.window.fullscreen {
                self.window.dimensions = Some(monitor.get_dimensions());
            }
        }

        // default dimensions
        if self.window.dimensions.is_none() {
            self.window.dimensions = Some((1024, 768));
        }

        // building
        let w = try!(platform::Window::new(&events_loop.events_loop, &self.window, &self.platform_specific));

        Ok(Window { window: w })
    }
}

impl Window {
    /// Creates a new Window for platforms where this is appropriate.
    ///
    /// This function is equivalent to `WindowBuilder::new().build(events_loop)`.
    ///
    /// Error should be very rare and only occur in case of permission denied, incompatible system,
    ///  out of memory, etc.
    #[inline]
    pub fn new(events_loop: &EventsLoop) -> Result<Window, CreationError> {
        let builder = WindowBuilder::new();
        builder.build(events_loop)
    }

    /// Modifies the title of the window.
    ///
    /// This is a no-op if the window has already been closed.
    #[inline]
    pub fn set_title(&self, title: &str) {
        self.window.set_title(title)
    }

    /// Shows the window if it was hidden.
    ///
    /// ## Platform-specific
    ///
    /// - Has no effect on Android
    ///
    #[inline]
    pub fn show(&self) {
        self.window.show()
    }

    /// Hides the window if it was visible.
    ///
    /// ## Platform-specific
    ///
    /// - Has no effect on Android
    ///
    #[inline]
    pub fn hide(&self) {
        self.window.hide()
    }

    /// Returns the position of the top-left hand corner of the window relative to the
    ///  top-left hand corner of the desktop.
    ///
    /// Note that the top-left hand corner of the desktop is not necessarily the same as
    ///  the screen. If the user uses a desktop with multiple monitors, the top-left hand corner
    ///  of the desktop is the top-left hand corner of the monitor at the top-left of the desktop.
    ///
    /// The coordinates can be negative if the top-left hand corner of the window is outside
    ///  of the visible screen region.
    ///
    /// Returns `None` if the window no longer exists.
    #[inline]
    pub fn get_position(&self) -> Option<(i32, i32)> {
        self.window.get_position()
    }

    /// Modifies the position of the window.
    ///
    /// See `get_position` for more information about the coordinates.
    ///
    /// This is a no-op if the window has already been closed.
    #[inline]
    pub fn set_position(&self, x: i32, y: i32) {
        self.window.set_position(x, y)
    }

    /// Returns the size in pixels of the client area of the window.
    ///
    /// The client area is the content of the window, excluding the title bar and borders.
    /// These are the dimensions that need to be supplied to `glViewport`.
    ///
    /// Returns `None` if the window no longer exists.
    #[inline]
    pub fn get_inner_size(&self) -> Option<(u32, u32)> {
        self.window.get_inner_size()
    }

    /// Returns the size in points of the client area of the window.
    ///
    /// The client area is the content of the window, excluding the title bar and borders.
    /// To get the dimensions of the frame buffer when calling `glViewport`, multiply with hidpi factor.
    ///
    /// Returns `None` if the window no longer exists.
    ///
    /// DEPRECATED
    #[inline]
    #[deprecated]
    pub fn get_inner_size_points(&self) -> Option<(u32, u32)> {
        self.window.get_inner_size().map(|(x, y)| {
            let hidpi = self.hidpi_factor();
            ((x as f32 / hidpi) as u32, (y as f32 / hidpi) as u32)
        })
    }

    /// Returns the size in pixels of the client area of the window.
    ///
    /// The client area is the content of the window, excluding the title bar and borders.
    /// These are the dimensions of the frame buffer, and the dimensions that you should use
    ///  when you call `glViewport`.
    ///
    /// Returns `None` if the window no longer exists.
    ///
    /// DEPRECATED
    #[inline]
    #[deprecated]
    pub fn get_inner_size_pixels(&self) -> Option<(u32, u32)> {
        self.window.get_inner_size()
    }

    /// Returns the size in pixels of the window.
    ///
    /// These dimensions include title bar and borders. If you don't want these, you should use
    ///  use `get_inner_size` instead.
    ///
    /// Returns `None` if the window no longer exists.
    #[inline]
    pub fn get_outer_size(&self) -> Option<(u32, u32)> {
        self.window.get_outer_size()
    }

    /// Modifies the inner size of the window.
    ///
    /// See `get_inner_size` for more information about the values.
    ///
    /// This is a no-op if the window has already been closed.
    #[inline]
    pub fn set_inner_size(&self, x: u32, y: u32) {
        self.window.set_inner_size(x, y)
    }

    /// Sets a minimum dimension size for the window.
    ///
    /// Width and height are in pixels.
    #[inline]
    pub fn set_min_dimensions(&self, dimensions: Option<(u32, u32)>) {
        self.window.set_min_dimensions(dimensions)
    }

    /// Sets a maximum dimension size for the window.
    ///
    /// Width and height are in pixels.
    #[inline]
    pub fn set_max_dimensions(&self, dimensions: Option<(u32, u32)>) {
        self.window.set_max_dimensions(dimensions)
    }

    /// DEPRECATED. Gets the native platform specific display for this window.
    /// This is typically only required when integrating with
    /// other libraries that need this information.
    #[deprecated]
    #[inline]
    pub unsafe fn platform_display(&self) -> *mut libc::c_void {
        self.window.platform_display()
    }

    /// DEPRECATED. Gets the native platform specific window handle. This is
    /// typically only required when integrating with other libraries
    /// that need this information.
    #[deprecated]
    #[inline]
    pub unsafe fn platform_window(&self) -> *mut libc::c_void {
        self.window.platform_window()
    }

    /// Modifies the mouse cursor of the window.
    /// Has no effect on Android.
    pub fn set_cursor(&self, cursor: MouseCursor) {
        self.window.set_cursor(cursor);
    }

    /// Returns the ratio between the backing framebuffer resolution and the
    /// window size in screen pixels. This is typically one for a normal display
    /// and two for a retina display.
    #[inline]
    pub fn hidpi_factor(&self) -> f32 {
        self.window.hidpi_factor()
    }

    /// Changes the position of the cursor in window coordinates.
    #[inline]
    pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> {
        self.window.set_cursor_position(x, y)
    }

    /// Sets how winit handles the cursor. See the documentation of `CursorState` for details.
    ///
    /// Has no effect on Android.
    #[inline]
    pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> {
        self.window.set_cursor_state(state)
    }

    /// Sets the window to maximized or back
    #[inline]
    pub fn set_maximized(&self, maximized: bool) {
        self.window.set_maximized(maximized)
    }

    /// Sets the window to fullscreen or back
    #[inline]
    pub fn set_fullscreen(&self, monitor: Option<MonitorId>) {
        self.window.set_fullscreen(monitor)
    }

    /// Turn window decorations on or off.
    #[inline]
    pub fn set_decorations(&self, decorations: bool) {
        self.window.set_decorations(decorations)
    }

    /// Returns the monitor on which the window currently resides
    pub fn get_current_monitor(&self) -> MonitorId {
        self.window.get_current_monitor()
    }

    #[inline]
    pub fn id(&self) -> WindowId {
        WindowId(self.window.id())
    }
}

/// An iterator for the list of available monitors.
// Implementation note: we retrieve the list once, then serve each element by one by one.
// This may change in the future.
pub struct AvailableMonitorsIter {
    pub(crate) data: VecDequeIter<platform::MonitorId>,
}

impl Iterator for AvailableMonitorsIter {
    type Item = MonitorId;

    #[inline]
    fn next(&mut self) -> Option<MonitorId> {
        self.data.next().map(|id| MonitorId { inner: id })
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.data.size_hint()
    }
}

/// Identifier for a monitor.
#[derive(Clone)]
pub struct MonitorId {
    pub(crate) inner: platform::MonitorId
}

impl MonitorId {
    /// Returns a human-readable name of the monitor.
    ///
    /// Returns `None` if the monitor doesn't exist anymore.
    #[inline]
    pub fn get_name(&self) -> Option<String> {
        self.inner.get_name()
    }

    /// Returns the number of pixels currently displayed on the monitor.
    #[inline]
    pub fn get_dimensions(&self) -> (u32, u32) {
        self.inner.get_dimensions()
    }

    /// Returns the top-left corner position of the monitor relative to the larger full
    /// screen area.
    #[inline]
    pub fn get_position(&self) -> (i32, i32) {
        self.inner.get_position()
    }

    /// Returns the ratio between the monitor's physical pixels and logical pixels.
    #[inline]
    pub fn get_hidpi_factor(&self) -> f32 {
        self.inner.get_hidpi_factor()
    }
}
<|endoftext|>


<commit_before>pub fn synthesis_full() -> Window {
    Window::new(&WINDOW_SYNTHESIS[..])
}

pub fn synthesis_trunc() -> Window {
    Window::new(&WINDOW_SYNTHESIS[1..WINDOW_SYNTHESIS.len()-1])
}

pub struct Window {
    coefs: &'static [f32],
    offset: isize,
}

impl Window {
    pub fn new(coefs: &'static [f32]) -> Window {
        Window {
            coefs: coefs,
            offset: coefs.len() as isize / 2,
        }
    }

    pub fn get(&self, n: isize) -> f32 {
        match self.coefs.get((n + self.offset) as usize) {
            Some(&coef) => coef,
            None => 0.0,
        }
    }
}

// w_S(n)
static WINDOW_SYNTHESIS: [f32; 211] = [
    0.000000,
    0.020000,
    0.040000,
    0.060000,
    0.080000,
    0.100000,
    0.120000,
    0.140000,
    0.160000,
    0.180000,
    0.200000,
    0.220000,
    0.240000,
    0.260000,
    0.280000,
    0.300000,
    0.320000,
    0.340000,
    0.360000,
    0.380000,
    0.400000,
    0.420000,
    0.440000,
    0.460000,
    0.480000,
    0.500000,
    0.520000,
    0.540000,
    0.560000,
    0.580000,
    0.60000,
    0.620000,
    0.640000,
    0.660000,
    0.680000,
    0.700000,
    0.720000,
    0.740000,
    0.760000,
    0.780000,
    0.800000,
    0.820000,
    0.840000,
    0.860000,
    0.880000,
    0.900000,
    0.920000,
    0.940000,
    0.960000,
    0.980000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.00000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    0.980000,
    0.960000,
    0.940000,
    0.920000,
    0.900000,
    0.880000,
    0.860000,
    0.840000,
    0.820000,
    0.800000,
    0.780000,
    0.760000,
    0.740000,
    0.720000,
    0.700000,
    0.680000,
    0.660000,
    0.640000,
    0.620000,
    0.600000,
    0.580000,
    0.560000,
    0.540000,
    0.520000,
    0.500000,
    0.480000,
    0.460000,
    0.440000,
    0.420000,
    0.400000,
    0.380000,
    0.360000,
    0.340000,
    0.320000,
    0.300000,
    0.280000,
    0.260000,
    0.240000,
    0.220000,
    0.200000,
    0.180000,
    0.160000,
    0.140000,
    0.120000,
    0.100000,
    0.080000,
    0.060000,
    0.040000,
    0.020000,
    0.00000,
];

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_syn_trunc() {
        let w = synthesis_trunc();

        assert_eq!(w.get(-200), 0.0);
        assert_eq!(w.get(-105), 0.0);
        assert_eq!(w.get(-104), 0.02);
        assert_eq!(w.get(-56), 0.98);
        assert_eq!(w.get(-88), 0.34);
        assert_eq!(w.get(104), 0.02);
        assert_eq!(w.get(105), 0.0);
        assert_eq!(w.get(200), 0.0);
    }

    #[test]
    fn test_syn_full() {
        let w = synthesis_full();

        assert_eq!(w.get(-200), 0.0);
        assert_eq!(w.get(-106), 0.0);
        assert_eq!(w.get(-105), 0.0);
        assert_eq!(w.get(-68), 0.74);
        assert_eq!(w.get(77), 0.56);
        assert_eq!(w.get(105), 0.0);
        assert_eq!(w.get(106), 0.0);
        assert_eq!(w.get(200), 0.0);
    }
}
<commit_msg>Add two more window tests<commit_after>pub fn synthesis_full() -> Window {
    Window::new(&WINDOW_SYNTHESIS[..])
}

pub fn synthesis_trunc() -> Window {
    Window::new(&WINDOW_SYNTHESIS[1..WINDOW_SYNTHESIS.len()-1])
}

pub struct Window {
    coefs: &'static [f32],
    offset: isize,
}

impl Window {
    pub fn new(coefs: &'static [f32]) -> Window {
        Window {
            coefs: coefs,
            offset: coefs.len() as isize / 2,
        }
    }

    pub fn get(&self, n: isize) -> f32 {
        match self.coefs.get((n + self.offset) as usize) {
            Some(&coef) => coef,
            None => 0.0,
        }
    }
}

// w_S(n)
static WINDOW_SYNTHESIS: [f32; 211] = [
    0.000000,
    0.020000,
    0.040000,
    0.060000,
    0.080000,
    0.100000,
    0.120000,
    0.140000,
    0.160000,
    0.180000,
    0.200000,
    0.220000,
    0.240000,
    0.260000,
    0.280000,
    0.300000,
    0.320000,
    0.340000,
    0.360000,
    0.380000,
    0.400000,
    0.420000,
    0.440000,
    0.460000,
    0.480000,
    0.500000,
    0.520000,
    0.540000,
    0.560000,
    0.580000,
    0.60000,
    0.620000,
    0.640000,
    0.660000,
    0.680000,
    0.700000,
    0.720000,
    0.740000,
    0.760000,
    0.780000,
    0.800000,
    0.820000,
    0.840000,
    0.860000,
    0.880000,
    0.900000,
    0.920000,
    0.940000,
    0.960000,
    0.980000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.00000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    1.000000,
    0.980000,
    0.960000,
    0.940000,
    0.920000,
    0.900000,
    0.880000,
    0.860000,
    0.840000,
    0.820000,
    0.800000,
    0.780000,
    0.760000,
    0.740000,
    0.720000,
    0.700000,
    0.680000,
    0.660000,
    0.640000,
    0.620000,
    0.600000,
    0.580000,
    0.560000,
    0.540000,
    0.520000,
    0.500000,
    0.480000,
    0.460000,
    0.440000,
    0.420000,
    0.400000,
    0.380000,
    0.360000,
    0.340000,
    0.320000,
    0.300000,
    0.280000,
    0.260000,
    0.240000,
    0.220000,
    0.200000,
    0.180000,
    0.160000,
    0.140000,
    0.120000,
    0.100000,
    0.080000,
    0.060000,
    0.040000,
    0.020000,
    0.00000,
];

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_syn_trunc() {
        let w = synthesis_trunc();

        assert_eq!(w.get(-200), 0.0);
        assert_eq!(w.get(-105), 0.0);
        assert_eq!(w.get(-104), 0.02);
        assert_eq!(w.get(-56), 0.98);
        assert_eq!(w.get(-88), 0.34);
        assert_eq!(w.get(0), 1.0);
        assert_eq!(w.get(104), 0.02);
        assert_eq!(w.get(105), 0.0);
        assert_eq!(w.get(200), 0.0);
    }

    #[test]
    fn test_syn_full() {
        let w = synthesis_full();

        assert_eq!(w.get(-200), 0.0);
        assert_eq!(w.get(-106), 0.0);
        assert_eq!(w.get(-105), 0.0);
        assert_eq!(w.get(-68), 0.74);
        assert_eq!(w.get(0), 1.0);
        assert_eq!(w.get(77), 0.56);
        assert_eq!(w.get(105), 0.0);
        assert_eq!(w.get(106), 0.0);
        assert_eq!(w.get(200), 0.0);
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use cg;
use darling::{Error, FromMetaItem};
use quote::Tokens;
use syn::{self, Ident};
use synstructure;

pub fn derive(input: syn::DeriveInput) -> Tokens {
    let name = &input.ident;
    let trait_path = parse_quote!(style_traits::ToCss);
    let (impl_generics, ty_generics, mut where_clause) =
        cg::trait_parts(&input, &trait_path);

    let input_attrs = cg::parse_input_attrs::<CssInputAttrs>(&input);
    let s = synstructure::Structure::new(&input);

    let match_body = s.each_variant(|variant| {
        let bindings = variant.bindings();
        let identifier = cg::to_css_identifier(variant.ast().ident.as_ref());
        let ast = variant.ast();
        let variant_attrs = cg::parse_variant_attrs::<CssVariantAttrs>(&ast);
        let separator = if variant_attrs.comma { ", " } else { " " };

        if variant_attrs.dimension {
            assert_eq!(bindings.len(), 1);
            assert!(
                variant_attrs.function.is_none() && variant_attrs.keyword.is_none(),
                "That makes no sense"
            );
        }

        let mut expr = if let Some(keyword) = variant_attrs.keyword {
            assert!(bindings.is_empty());
            let keyword = keyword.to_string();
            quote! {
                ::std::fmt::Write::write_str(dest, #keyword)
            }
        } else if !bindings.is_empty() {
            let mut expr = quote! {};
            if variant_attrs.iterable {
                assert_eq!(bindings.len(), 1);
                let binding = &bindings[0];
                expr = quote! {
                    #expr

                    for item in #binding.iter() {
                        writer.item(&item)?;
                    }
                };
            } else {
                for binding in bindings {
                    let attrs = cg::parse_field_attrs::<CssFieldAttrs>(&binding.ast());
                    if !attrs.ignore_bound {
                        where_clause.add_trait_bound(&binding.ast().ty);
                    }
                    expr = quote! {
                        #expr
                        writer.item(#binding)?;
                    };
                }
            }

            quote! {{
                let mut writer = ::style_traits::values::SequenceWriter::new(dest, #separator);
                #expr
                Ok(())
            }}
        } else {
            quote! {
                ::std::fmt::Write::write_str(dest, #identifier)
            }
        };

        if variant_attrs.dimension {
            expr = quote! {
                #expr?;
                ::std::fmt::Write::write_str(dest, #identifier)
            }
        } else if let Some(function) = variant_attrs.function {
            let mut identifier = function.name.map_or(identifier, |name| name.to_string());
            identifier.push_str("(");
            expr = quote! {
                ::std::fmt::Write::write_str(dest, #identifier)?;
                #expr?;
                ::std::fmt::Write::write_str(dest, ")")
            }
        }
        Some(expr)
    });

    let mut impls = quote! {
        impl #impl_generics ::style_traits::ToCss for #name #ty_generics #where_clause {
            #[allow(unused_variables)]
            #[inline]
            fn to_css<W>(
                &self,
                dest: &mut ::style_traits::CssWriter<W>,
            ) -> ::std::fmt::Result
            where
                W: ::std::fmt::Write
            {
                match *self {
                    #match_body
                }
            }
        }
    };

    if input_attrs.derive_debug {
        impls.append_all(quote! {
            impl #impl_generics ::std::fmt::Debug for #name #ty_generics #where_clause {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    ::style_traits::ToCss::to_css(
                        self,
                        &mut ::style_traits::CssWriter::new(f),
                    )
                }
            }
        });
    }

    impls
}

#[darling(attributes(css), default)]
#[derive(Default, FromDeriveInput)]
struct CssInputAttrs {
    derive_debug: bool,
    function: Option<Function>,
    comma: bool,
    // Here because structs variants are also their whole type definition.
    iterable: bool,
}

#[darling(attributes(css), default)]
#[derive(Default, FromVariant)]
pub struct CssVariantAttrs {
    pub function: Option<Function>,
    pub iterable: bool,
    pub comma: bool,
    pub dimension: bool,
    pub keyword: Option<String>,
    pub aliases: Option<String>,
}

#[darling(attributes(css), default)]
#[derive(Default, FromField)]
struct CssFieldAttrs {
    ignore_bound: bool,
}

pub struct Function {
    name: Option<Ident>,
}

impl FromMetaItem for Function {
    fn from_word() -> Result<Self, Error> {
        Ok(Self { name: None })
    }

    fn from_string(name: &str) -> Result<Self, Error> {
        let name = Ident::from(name);
        Ok(Self { name: Some(name) })
    }
}
<commit_msg>Auto merge of #20198 - servo:derive-all-the-things, r=emilio<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use cg;
use darling::util::Override;
use quote::Tokens;
use syn::{self, Ident};
use synstructure;

pub fn derive(input: syn::DeriveInput) -> Tokens {
    let name = &input.ident;
    let trait_path = parse_quote!(style_traits::ToCss);
    let (impl_generics, ty_generics, mut where_clause) =
        cg::trait_parts(&input, &trait_path);

    let input_attrs = cg::parse_input_attrs::<CssInputAttrs>(&input);
    let s = synstructure::Structure::new(&input);

    let match_body = s.each_variant(|variant| {
        let bindings = variant.bindings();
        let identifier = cg::to_css_identifier(variant.ast().ident.as_ref());
        let ast = variant.ast();
        let variant_attrs = cg::parse_variant_attrs::<CssVariantAttrs>(&ast);
        let separator = if variant_attrs.comma { ", " } else { " " };

        if variant_attrs.dimension {
            assert_eq!(bindings.len(), 1);
            assert!(
                variant_attrs.function.is_none() && variant_attrs.keyword.is_none(),
                "That makes no sense"
            );
        }

        let mut expr = if let Some(keyword) = variant_attrs.keyword {
            assert!(bindings.is_empty());
            let keyword = keyword.to_string();
            quote! {
                ::std::fmt::Write::write_str(dest, #keyword)
            }
        } else if !bindings.is_empty() {
            let mut expr = quote! {};
            if variant_attrs.iterable {
                assert_eq!(bindings.len(), 1);
                let binding = &bindings[0];
                expr = quote! {
                    #expr

                    for item in #binding.iter() {
                        writer.item(&item)?;
                    }
                };
            } else {
                for binding in bindings {
                    let attrs = cg::parse_field_attrs::<CssFieldAttrs>(&binding.ast());
                    if !attrs.ignore_bound {
                        where_clause.add_trait_bound(&binding.ast().ty);
                    }
                    expr = quote! {
                        #expr
                        writer.item(#binding)?;
                    };
                }
            }

            quote! {{
                let mut writer = ::style_traits::values::SequenceWriter::new(dest, #separator);
                #expr
                Ok(())
            }}
        } else {
            quote! {
                ::std::fmt::Write::write_str(dest, #identifier)
            }
        };

        if variant_attrs.dimension {
            expr = quote! {
                #expr?;
                ::std::fmt::Write::write_str(dest, #identifier)
            }
        } else if let Some(function) = variant_attrs.function {
            let mut identifier = function.explicit().map_or(identifier, |name| name.to_string());
            identifier.push_str("(");
            expr = quote! {
                ::std::fmt::Write::write_str(dest, #identifier)?;
                #expr?;
                ::std::fmt::Write::write_str(dest, ")")
            }
        }
        Some(expr)
    });

    let mut impls = quote! {
        impl #impl_generics ::style_traits::ToCss for #name #ty_generics #where_clause {
            #[allow(unused_variables)]
            #[inline]
            fn to_css<W>(
                &self,
                dest: &mut ::style_traits::CssWriter<W>,
            ) -> ::std::fmt::Result
            where
                W: ::std::fmt::Write
            {
                match *self {
                    #match_body
                }
            }
        }
    };

    if input_attrs.derive_debug {
        impls.append_all(quote! {
            impl #impl_generics ::std::fmt::Debug for #name #ty_generics #where_clause {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    ::style_traits::ToCss::to_css(
                        self,
                        &mut ::style_traits::CssWriter::new(f),
                    )
                }
            }
        });
    }

    impls
}

#[darling(attributes(css), default)]
#[derive(Default, FromDeriveInput)]
struct CssInputAttrs {
    derive_debug: bool,
    // Here because structs variants are also their whole type definition.
    function: Option<Override<Ident>>,
    // Here because structs variants are also their whole type definition.
    comma: bool,
    // Here because structs variants are also their whole type definition.
    iterable: bool,
}

#[darling(attributes(css), default)]
#[derive(Default, FromVariant)]
pub struct CssVariantAttrs {
    pub function: Option<Override<Ident>>,
    pub iterable: bool,
    pub comma: bool,
    pub dimension: bool,
    pub keyword: Option<String>,
    pub aliases: Option<String>,
}

#[darling(attributes(css), default)]
#[derive(Default, FromField)]
struct CssFieldAttrs {
    ignore_bound: bool,
}
<|endoftext|>


<commit_before>pub mod misc;
pub mod options;
pub mod threads;
pub mod thread_search;
pub mod rmoves;
pub mod sync;

use pleco::tools::tt::TranspositionTable;
use pleco::Board;
use pleco::BitMove;

use std::io;

use self::misc::{PreLimits,UCITimer};
use self::options::{AllOptions,UciOptionMut};
use self::threads::ThreadPool;

use num_cpus;

const MAX_PLY: u16 = 126;
const THREAD_STACK_SIZE: usize = MAX_PLY as usize + 7;
pub const MAX_THREADS: usize = 256;
pub const DEFAULT_TT_SIZE: usize = 256;

lazy_static! {
    pub static ref TT_TABLE: TranspositionTable = TranspositionTable::new(DEFAULT_TT_SIZE);
}

pub static ID_NAME: &str = "Pleco";
pub static ID_AUTHORS: &str = "Stephen Fleischman";
pub static VERSION: &str = "0.0.3";

#[derive(PartialEq)]
enum SearchType {
    None,
    Search,
    Ponder,
}

pub struct PlecoSearcher {
    options: AllOptions,
    thread_pool: ThreadPool,
    search_mode: SearchType,
    board: Option<Board>,
    limit: Option<PreLimits>
}

impl PlecoSearcher {

    pub fn init(use_stdout: bool) -> Self {
        unsafe {
            TT_TABLE.clear();
        }
        let mut pool = ThreadPool::new();
        pool.stdout(use_stdout);
        pool.set_thread_count(num_cpus::get());
        PlecoSearcher {
            options: AllOptions::default(),
            thread_pool: pool,
            search_mode: SearchType::None,
            board: None,
            limit: None,
        }
    }

    pub fn uci(&mut self) {
        let mut full_command = String::new();
        'main: loop {
            full_command.clear();
            io::stdin().read_line(&mut full_command).ok().unwrap();
            let args: Vec<&str> = full_command.split_whitespace().collect();
            let command: &str = args.first().unwrap_or(&"");
            match command {
                "" => continue,
                "uci" => self.uci_startup(),
                "setoption" => self.apply_option(&full_command),
                "options" | "alloptions" => self.options.print_curr(),
                "ucinewgame" => self.clear_search(),
                "isready" => println!("readyok"),
                "position" => self.parse_position(&args[1..]),
                "go" => self.uci_go(&args[1..]),
                "quit" | "stop" => {
                    self.halt();
                    break;
                },
                _ => println!("Unknown Command: {}",full_command)
            }

        }
    }

    pub fn clear_search(&mut self) {

    }

    fn parse_position(&mut self, args: &[&str]) {
        let start: &str = args[0];
        self.board = if start == "startpos" {
            Some(Board::default())
        } else if start == "fen" {
            let fen_string: String = args[1..].iter()
                .take_while(|p: &&&str| **p != "moves")
                .map(|p| (*p).to_string())
                .collect::<Vec<String>>()
                .join(" ");
            Board::new_from_fen(&fen_string).ok()
        } else {
            None
        };

        let mut moves_start: Option<usize> =  None;
        for (i, mov) in args.iter().enumerate() {
            if *mov == "moves" {
                moves_start = Some(i);
            }
        };

        if let Some(start) = moves_start {
            if let Some(ref mut board) = self.board {
                let all_moves = board.generate_moves()
                    .iter()
                    .map(|m| m.stringify())
                    .collect::<Vec<String>>();

                args[start..].iter()
                    .take_while(|m| all_moves.contains(&(**m).to_string()))
                    .for_each(|p| {
                        assert!(board.apply_uci_move(*p));
                    });
            }
        }
    }

    // when "go" is passed into stdin, followed by several time control parameters
    // "searchmoves" "move"+
    // "ponder"
    // "wtime" "[msec]"
    // "btime" "[msec]"
    // "winc" "[msec]"
    // "binc" "[msec]"
    // "movestogo" "[u32]"
    // "depth" "[u16]"
    // "nodes" "[u64]"
    // "mate" "[moves]"
    // movetime "msec"
    // "infinite"
    fn uci_go(&mut self, args: &[&str]) {
        let mut token_idx: usize = 0;
        let mut limit = PreLimits::blank();
        let mut timer = UCITimer::blank();
        while let Some(token) = args.get(token_idx) {
            match *token {
                "infinite" => {limit.infinite = true;},
                "ponder" => {limit.ponder = true;},
                "wtime" => {
                    if let Some(wtime_s) =  args.get(token_idx + 1) {
                        if let Ok(wtime) = wtime_s.parse::<i32>() {
                            timer.time_msec[0] = wtime;
                        }
                        token_idx += 1;
                    }
                },
                "btime" => {
                    if let Some(btime_s) =  args.get(token_idx + 1) {
                        if let Ok(btime) = btime_s.parse::<i32>() {
                            timer.time_msec[1] = btime;
                        }
                        token_idx += 1;
                    }
                },
                "winc" => {
                    if let Some(winc_s) =  args.get(token_idx + 1) {
                        if let Ok(winc) = winc_s.parse::<i32>() {
                            timer.inc_msec[0] = winc;
                        }
                        token_idx += 1;
                    }
                },
                "binc" => {
                    if let Some(binc_s) =  args.get(token_idx + 1) {
                        if let Ok(binc) = binc_s.parse::<i32>() {
                            timer.inc_msec[1] = binc;
                        }
                        token_idx += 1;
                    }
                },
                "movestogo" => {
                    if let Some(movestogo_s) =  args.get(token_idx + 1) {
                        if let Ok(movestogo) = movestogo_s.parse::<i32>() {
                            timer.time_msec[0] = movestogo;
                        }
                        token_idx += 1;
                    }
                },
                "depth" => {
                    if let Some(depth_s) =  args.get(token_idx + 1) {
                        if let Ok(depth) = depth_s.parse::<u16>() {
                            limit.depth = Some(depth);
                        }
                        token_idx += 1;
                    }
                },
                "nodes" => {
                    if let Some(nodes_s) =  args.get(token_idx + 1) {
                        if let Ok(nodes) = nodes_s.parse::<u64>() {
                            limit.nodes = Some(nodes);
                        }
                        token_idx += 1;
                    }
                },
                "mate" => {
                    if let Some(mate_s) =  args.get(token_idx + 1) {
                        if let Ok(mate) = mate_s.parse::<u16>() {
                            limit.mate = Some(mate);
                        }
                        token_idx += 1;
                    }
                },
                "movetime" => {
                    if let Some(movetime_s) =  args.get(token_idx + 1) {
                        if let Ok(movetime) = movetime_s.parse::<u64>() {
                            limit.move_time = Some(movetime);
                        }
                        token_idx += 1;
                    }
                },
                "searchmoves" => {},
                _ => {}
            }
            token_idx += 1;
        }
    }

    fn apply_option(&mut self, option: &str) {
        let c = self.options.apply_option(option);
        match c {
            UciOptionMut::Button(c)   => {(c)(self);},
            UciOptionMut::Check(c, v) => {(c)(self, v);},
            UciOptionMut::Spin(c, v)  => {(c)(self, v);},
            UciOptionMut::Combo(c, v) => {(c)(self, v);},
            UciOptionMut::Text(c, v)  => {(c)(self, v);},
            UciOptionMut::None => {},
        }

    }

    fn uci_startup(&self) {
        println!("id name {}",ID_NAME);
        println!("id authors {}", ID_AUTHORS);
        self.options.print_all();
        println!("uciok");
    }

    pub fn search(&mut self, board: &Board, limit: &PreLimits) {
        TT_TABLE.new_search();
        self.search_mode = SearchType::Search;
        self.thread_pool.uci_search(&board, &limit);
    }

    pub fn halt(&mut self) {
        self.thread_pool.stop_searching();
        self.search_mode = SearchType::None;
    }

    pub fn stop_search_get_move(&mut self) -> BitMove {
        if self.is_searching() {
            self.halt();
            return self.thread_pool.get_move();
        } else {
            return BitMove::null();
        }
    }

    pub fn await_move(&mut self) -> BitMove {
        if self.is_searching() {
            return self.thread_pool.get_move();
        } else {
            return BitMove::null();
        }
    }

    pub fn is_searching(&self) -> bool {
        if self.search_mode == SearchType::None {
            return false;
        }
        true
    }

    pub fn hash_percent(&self) -> f64 {
        TT_TABLE.hash_percent()
    }

    pub fn clear_tt(&mut self) {
        unsafe {TT_TABLE.clear() };
    }

    pub fn resize_tt(&mut self, mb: usize) {
        unsafe {TT_TABLE.resize_to_megabytes(mb)};
    }

    pub fn use_stdout(&mut self, stdout: bool) {
        self.thread_pool.stdout(stdout);
    }

}

//fn parse_board_position(tokens: Vec<String>) -> Board {
//    let mut token_stack = tokens.clone();
//    token_stack.reverse();
//    token_stack.pop();
//
//    let start_str = token_stack.pop().unwrap();
//    let start = &start_str;
//    let mut board = if start == "startpos" {
//        Some(Board::default())
//    } else if start == "fen" {
//        let fen_string: &str = &token_stack.pop().unwrap();
//        Board::new_from_fen(fen_string).ok()
//    } else {
//        panic!()
//    };
//
//    if !token_stack.is_empty() {
//        let next = &token_stack.pop().unwrap();
//        if next == "moves" {
//            while !token_stack.is_empty() {
//                let bit_move = &token_stack.pop().unwrap();
//                let mut all_moves: Vec<BitMove> = board.generate_moves();
//                'check_legality: loop {
//                    if all_moves.is_empty() {
//                        panic!();
//                    }
//                    let curr_move: BitMove = all_moves.pop().unwrap();
//                    if &curr_move.stringify() == bit_move {
//                        board.apply_move(curr_move);
//                        break 'check_legality
//                    }
//                }
//            }
//        }
//    }
//    board
//}
//
//fn parse_limit(tokens: Vec<String>) -> UCILimit {
//    let mut token_stack = tokens.clone();
//    token_stack.reverse();
//
//    let mut white_time: i64 = i64::max_value();
//    let mut black_time: i64 = i64::max_value();
//    let mut white_inc: i64 = i64::max_value();
//    let mut black_inc: i64 = i64::max_value();
//
//    while !token_stack.is_empty() {
//        let token = token_stack.pop().unwrap();
//        if token == "inf" {
//            return UCILimit::Infinite;
//        } else if token == "wtime" {
//            white_time = unwrap_val_or(&mut token_stack, i64::max_value());
//        } else if token == "btime" {
//            black_time = unwrap_val_or(&mut token_stack, i64::max_value());
//        } else if token == "winc" {
//            white_inc = unwrap_val_or(&mut token_stack, 0);
//        } else if token == "binc" {
//            black_inc = unwrap_val_or(&mut token_stack, 0);
//        } else if token == "depth" {
//            return UCILimit::Depth(token_stack.pop().unwrap().parse::<u16>().unwrap());
//        } else if token == "mate" {
//            unimplemented!()
//        } else if token == "nodes" {
//            unimplemented!()
//        } else if token == "movestogo" {
//            unimplemented!()
//        } else if token == "movetime" {
//            unimplemented!()
//        }
//    }
//    UCILimit::Time(
//        Timer::new(white_time, black_time, white_inc, black_inc)
//    )
//}

<commit_msg>sadffad<commit_after>pub mod misc;
pub mod options;
pub mod threads;
pub mod thread_search;
pub mod rmoves;
pub mod sync;

use pleco::tools::tt::TranspositionTable;
use pleco::Board;
use pleco::BitMove;

use std::io;

use self::misc::{PreLimits,UCITimer};
use self::options::{AllOptions,UciOptionMut};
use self::threads::ThreadPool;

use num_cpus;

const MAX_PLY: u16 = 126;
const THREAD_STACK_SIZE: usize = MAX_PLY as usize + 7;
pub const MAX_THREADS: usize = 16;
pub const DEFAULT_TT_SIZE: usize = 256;

lazy_static! {
    pub static ref TT_TABLE: TranspositionTable = TranspositionTable::new(DEFAULT_TT_SIZE);
}

pub static ID_NAME: &str = "Pleco";
pub static ID_AUTHORS: &str = "Stephen Fleischman";
pub static VERSION: &str = "0.0.3";

#[derive(PartialEq)]
enum SearchType {
    None,
    Search,
    Ponder,
}

pub struct PlecoSearcher {
    options: AllOptions,
    thread_pool: ThreadPool,
    search_mode: SearchType,
    board: Option<Board>,
    limit: Option<PreLimits>
}

impl PlecoSearcher {

    pub fn init(use_stdout: bool) -> Self {
        unsafe {
            TT_TABLE.clear();
        }
        let mut pool = ThreadPool::new();
        pool.stdout(use_stdout);
        pool.set_thread_count(num_cpus::get());
        PlecoSearcher {
            options: AllOptions::default(),
            thread_pool: pool,
            search_mode: SearchType::None,
            board: None,
            limit: None,
        }
    }

    pub fn uci(&mut self) {
        let mut full_command = String::new();
        'main: loop {
            full_command.clear();
            io::stdin().read_line(&mut full_command).ok().unwrap();
            let args: Vec<&str> = full_command.split_whitespace().collect();
            let command: &str = args.first().unwrap_or(&"");
            match command {
                "" => continue,
                "uci" => self.uci_startup(),
                "setoption" => self.apply_option(&full_command),
                "options" | "alloptions" => self.options.print_curr(),
                "ucinewgame" => self.clear_search(),
                "isready" => println!("readyok"),
                "position" => self.parse_position(&args[1..]),
                "go" => self.uci_go(&args[1..]),
                "quit" | "stop" => {
                    self.halt();
                    break;
                },
                _ => println!("Unknown Command: {}",full_command)
            }

        }
    }

    pub fn clear_search(&mut self) {

    }

    fn parse_position(&mut self, args: &[&str]) {
        let start: &str = args[0];
        self.board = if start == "startpos" {
            Some(Board::default())
        } else if start == "fen" {
            let fen_string: String = args[1..].iter()
                .take_while(|p: &&&str| **p != "moves")
                .map(|p| (*p).to_string())
                .collect::<Vec<String>>()
                .join(" ");
            Board::new_from_fen(&fen_string).ok()
        } else {
            None
        };

        let mut moves_start: Option<usize> =  None;
        for (i, mov) in args.iter().enumerate() {
            if *mov == "moves" {
                moves_start = Some(i);
            }
        };

        if let Some(start) = moves_start {
            if let Some(ref mut board) = self.board {
                let all_moves = board.generate_moves()
                    .iter()
                    .map(|m| m.stringify())
                    .collect::<Vec<String>>();

                args[start..].iter()
                    .take_while(|m| all_moves.contains(&(**m).to_string()))
                    .for_each(|p| {
                        assert!(board.apply_uci_move(*p));
                    });
            }
        }
    }

    // when "go" is passed into stdin, followed by several time control parameters
    // "searchmoves" "move"+
    // "ponder"
    // "wtime" "[msec]"
    // "btime" "[msec]"
    // "winc" "[msec]"
    // "binc" "[msec]"
    // "movestogo" "[u32]"
    // "depth" "[u16]"
    // "nodes" "[u64]"
    // "mate" "[moves]"
    // movetime "msec"
    // "infinite"
    fn uci_go(&mut self, args: &[&str]) {
        let mut token_idx: usize = 0;
        let mut limit = PreLimits::blank();
        let mut timer = UCITimer::blank();
        while let Some(token) = args.get(token_idx) {
            match *token {
                "infinite" => {limit.infinite = true;},
                "ponder" => {limit.ponder = true;},
                "wtime" => {
                    if let Some(wtime_s) =  args.get(token_idx + 1) {
                        if let Ok(wtime) = wtime_s.parse::<i32>() {
                            timer.time_msec[0] = wtime;
                        }
                        token_idx += 1;
                    }
                },
                "btime" => {
                    if let Some(btime_s) =  args.get(token_idx + 1) {
                        if let Ok(btime) = btime_s.parse::<i32>() {
                            timer.time_msec[1] = btime;
                        }
                        token_idx += 1;
                    }
                },
                "winc" => {
                    if let Some(winc_s) =  args.get(token_idx + 1) {
                        if let Ok(winc) = winc_s.parse::<i32>() {
                            timer.inc_msec[0] = winc;
                        }
                        token_idx += 1;
                    }
                },
                "binc" => {
                    if let Some(binc_s) =  args.get(token_idx + 1) {
                        if let Ok(binc) = binc_s.parse::<i32>() {
                            timer.inc_msec[1] = binc;
                        }
                        token_idx += 1;
                    }
                },
                "movestogo" => {
                    if let Some(movestogo_s) =  args.get(token_idx + 1) {
                        if let Ok(movestogo) = movestogo_s.parse::<i32>() {
                            timer.time_msec[0] = movestogo;
                        }
                        token_idx += 1;
                    }
                },
                "depth" => {
                    if let Some(depth_s) =  args.get(token_idx + 1) {
                        if let Ok(depth) = depth_s.parse::<u16>() {
                            limit.depth = Some(depth);
                        }
                        token_idx += 1;
                    }
                },
                "nodes" => {
                    if let Some(nodes_s) =  args.get(token_idx + 1) {
                        if let Ok(nodes) = nodes_s.parse::<u64>() {
                            limit.nodes = Some(nodes);
                        }
                        token_idx += 1;
                    }
                },
                "mate" => {
                    if let Some(mate_s) =  args.get(token_idx + 1) {
                        if let Ok(mate) = mate_s.parse::<u16>() {
                            limit.mate = Some(mate);
                        }
                        token_idx += 1;
                    }
                },
                "movetime" => {
                    if let Some(movetime_s) =  args.get(token_idx + 1) {
                        if let Ok(movetime) = movetime_s.parse::<u64>() {
                            limit.move_time = Some(movetime);
                        }
                        token_idx += 1;
                    }
                },
                "searchmoves" => {},
                _ => {}
            }
            token_idx += 1;
        }
    }

    fn apply_option(&mut self, option: &str) {
        let c = self.options.apply_option(option);
        match c {
            UciOptionMut::Button(c)   => {(c)(self);},
            UciOptionMut::Check(c, v) => {(c)(self, v);},
            UciOptionMut::Spin(c, v)  => {(c)(self, v);},
            UciOptionMut::Combo(c, v) => {(c)(self, v);},
            UciOptionMut::Text(c, v)  => {(c)(self, v);},
            UciOptionMut::None => {},
        }

    }

    fn uci_startup(&self) {
        println!("id name {}",ID_NAME);
        println!("id authors {}", ID_AUTHORS);
        self.options.print_all();
        println!("uciok");
    }

    pub fn search(&mut self, board: &Board, limit: &PreLimits) {
        TT_TABLE.new_search();
        self.search_mode = SearchType::Search;
        self.thread_pool.uci_search(&board, &limit);
    }

    pub fn halt(&mut self) {
        self.thread_pool.stop_searching();
        self.search_mode = SearchType::None;
    }

    pub fn stop_search_get_move(&mut self) -> BitMove {
        if self.is_searching() {
            self.halt();
            return self.thread_pool.get_move();
        } else {
            return BitMove::null();
        }
    }

    pub fn await_move(&mut self) -> BitMove {
        if self.is_searching() {
            return self.thread_pool.get_move();
        } else {
            return BitMove::null();
        }
    }

    pub fn is_searching(&self) -> bool {
        if self.search_mode == SearchType::None {
            return false;
        }
        true
    }

    pub fn hash_percent(&self) -> f64 {
        TT_TABLE.hash_percent()
    }

    pub fn clear_tt(&mut self) {
        unsafe {TT_TABLE.clear() };
    }

    pub fn resize_tt(&mut self, mb: usize) {
        unsafe {TT_TABLE.resize_to_megabytes(mb)};
    }

    pub fn use_stdout(&mut self, stdout: bool) {
        self.thread_pool.stdout(stdout);
    }

}

//fn parse_board_position(tokens: Vec<String>) -> Board {
//    let mut token_stack = tokens.clone();
//    token_stack.reverse();
//    token_stack.pop();
//
//    let start_str = token_stack.pop().unwrap();
//    let start = &start_str;
//    let mut board = if start == "startpos" {
//        Some(Board::default())
//    } else if start == "fen" {
//        let fen_string: &str = &token_stack.pop().unwrap();
//        Board::new_from_fen(fen_string).ok()
//    } else {
//        panic!()
//    };
//
//    if !token_stack.is_empty() {
//        let next = &token_stack.pop().unwrap();
//        if next == "moves" {
//            while !token_stack.is_empty() {
//                let bit_move = &token_stack.pop().unwrap();
//                let mut all_moves: Vec<BitMove> = board.generate_moves();
//                'check_legality: loop {
//                    if all_moves.is_empty() {
//                        panic!();
//                    }
//                    let curr_move: BitMove = all_moves.pop().unwrap();
//                    if &curr_move.stringify() == bit_move {
//                        board.apply_move(curr_move);
//                        break 'check_legality
//                    }
//                }
//            }
//        }
//    }
//    board
//}
//
//fn parse_limit(tokens: Vec<String>) -> UCILimit {
//    let mut token_stack = tokens.clone();
//    token_stack.reverse();
//
//    let mut white_time: i64 = i64::max_value();
//    let mut black_time: i64 = i64::max_value();
//    let mut white_inc: i64 = i64::max_value();
//    let mut black_inc: i64 = i64::max_value();
//
//    while !token_stack.is_empty() {
//        let token = token_stack.pop().unwrap();
//        if token == "inf" {
//            return UCILimit::Infinite;
//        } else if token == "wtime" {
//            white_time = unwrap_val_or(&mut token_stack, i64::max_value());
//        } else if token == "btime" {
//            black_time = unwrap_val_or(&mut token_stack, i64::max_value());
//        } else if token == "winc" {
//            white_inc = unwrap_val_or(&mut token_stack, 0);
//        } else if token == "binc" {
//            black_inc = unwrap_val_or(&mut token_stack, 0);
//        } else if token == "depth" {
//            return UCILimit::Depth(token_stack.pop().unwrap().parse::<u16>().unwrap());
//        } else if token == "mate" {
//            unimplemented!()
//        } else if token == "nodes" {
//            unimplemented!()
//        } else if token == "movestogo" {
//            unimplemented!()
//        } else if token == "movetime" {
//            unimplemented!()
//        }
//    }
//    UCILimit::Time(
//        Timer::new(white_time, black_time, white_inc, black_inc)
//    )
//}

<|endoftext|>


<commit_before>// Copyright © 2016, Peter Atashian
// Licensed under the MIT License <LICENSE.md>
use super::*;
pub type REGSAM = ACCESS_MASK;
STRUCT!{struct VALENTA {
    ve_valuename: LPSTR,
    ve_valuelen: DWORD,
    ve_valueptr: DWORD_PTR,
    ve_type: DWORD,
}}
pub type PVALENTA = *mut VALENTA;
STRUCT!{struct VALENTW {
    ve_valuename: LPWSTR,
    ve_valuelen: DWORD,
    ve_valueptr: DWORD_PTR,
    ve_type: DWORD,
}}
pub type PVALENTW = *mut VALENTW;
pub const HKEY_CLASSES_ROOT: HKEY = 0x80000000 as HKEY;
pub const HKEY_CURRENT_USER: HKEY = 0x80000001 as HKEY;
pub const HKEY_LOCAL_MACHINE: HKEY = 0x80000002 as HKEY;
pub const HKEY_USERS: HKEY = 0x80000003 as HKEY;
pub const HKEY_PERFORMANCE_DATA: HKEY = 0x80000004 as HKEY;
pub const HKEY_PERFORMANCE_TEXT: HKEY = 0x80000050 as HKEY;
pub const HKEY_PERFORMANCE_NLSTEXT: HKEY = 0x80000060 as HKEY;
pub const HKEY_CURRENT_CONFIG: HKEY = 0x80000005 as HKEY;
pub const HKEY_DYN_DATA: HKEY = 0x80000006 as HKEY;
pub const HKEY_CURRENT_USER_LOCAL_SETTINGS: HKEY = 0x80000007 as HKEY;
pub const REG_MUI_STRING_TRUNCATE: DWORD = 0x00000001;
pub const RRF_RT_REG_NONE: DWORD = 0x00000001;
pub const RRF_RT_REG_SZ: DWORD = 0x00000002;
pub const RRF_RT_REG_EXPAND_SZ: DWORD = 0x00000004;
pub const RRF_RT_REG_BINARY: DWORD = 0x00000008;
pub const RRF_RT_REG_DWORD: DWORD = 0x00000010;
pub const RRF_RT_REG_MULTI_SZ: DWORD = 0x00000020;
pub const RRF_RT_REG_QWORD: DWORD = 0x00000040;
pub const RRF_RT_DWORD: DWORD = RRF_RT_REG_BINARY|RRF_RT_REG_DWORD;
pub const RRF_RT_QWORD: DWORD = RRF_RT_REG_BINARY|RRF_RT_REG_QWORD;
pub const RRF_RT_ANY: DWORD = 0x0000ffff;
pub const RRF_NOEXPAND: DWORD = 0x10000000;
pub const RRF_ZEROONFAILURE: DWORD = 0x20000000;
<commit_msg>Fix #299<commit_after>// Copyright © 2016, Peter Atashian
// Licensed under the MIT License <LICENSE.md>
use super::*;
pub type REGSAM = ACCESS_MASK;
STRUCT!{struct VALENTA {
    ve_valuename: LPSTR,
    ve_valuelen: DWORD,
    ve_valueptr: DWORD_PTR,
    ve_type: DWORD,
}}
pub type PVALENTA = *mut VALENTA;
STRUCT!{struct VALENTW {
    ve_valuename: LPWSTR,
    ve_valuelen: DWORD,
    ve_valueptr: DWORD_PTR,
    ve_type: DWORD,
}}
pub type PVALENTW = *mut VALENTW;
pub const HKEY_CLASSES_ROOT: HKEY = 0x80000000u32 as i32 as usize as HKEY;
pub const HKEY_CURRENT_USER: HKEY = 0x80000001u32 as i32 as usize as HKEY;
pub const HKEY_LOCAL_MACHINE: HKEY = 0x80000002u32 as i32 as usize as HKEY;
pub const HKEY_USERS: HKEY = 0x80000003u32 as i32 as usize as HKEY;
pub const HKEY_PERFORMANCE_DATA: HKEY = 0x80000004u32 as i32 as usize as HKEY;
pub const HKEY_PERFORMANCE_TEXT: HKEY = 0x80000050u32 as i32 as usize as HKEY;
pub const HKEY_PERFORMANCE_NLSTEXT: HKEY = 0x80000060u32 as i32 as usize as HKEY;
pub const HKEY_CURRENT_CONFIG: HKEY = 0x80000005u32 as i32 as usize as HKEY;
pub const HKEY_DYN_DATA: HKEY = 0x80000006u32 as i32 as usize as HKEY;
pub const HKEY_CURRENT_USER_LOCAL_SETTINGS: HKEY = 0x80000007u32 as i32 as usize as HKEY;
pub const REG_MUI_STRING_TRUNCATE: DWORD = 0x00000001;
pub const RRF_RT_REG_NONE: DWORD = 0x00000001;
pub const RRF_RT_REG_SZ: DWORD = 0x00000002;
pub const RRF_RT_REG_EXPAND_SZ: DWORD = 0x00000004;
pub const RRF_RT_REG_BINARY: DWORD = 0x00000008;
pub const RRF_RT_REG_DWORD: DWORD = 0x00000010;
pub const RRF_RT_REG_MULTI_SZ: DWORD = 0x00000020;
pub const RRF_RT_REG_QWORD: DWORD = 0x00000040;
pub const RRF_RT_DWORD: DWORD = RRF_RT_REG_BINARY | RRF_RT_REG_DWORD;
pub const RRF_RT_QWORD: DWORD = RRF_RT_REG_BINARY | RRF_RT_REG_QWORD;
pub const RRF_RT_ANY: DWORD = 0x0000ffff;
pub const RRF_NOEXPAND: DWORD = 0x10000000;
pub const RRF_ZEROONFAILURE: DWORD = 0x20000000;
<|endoftext|>


<commit_before>extern crate clap;

use clap::{Arg, App};
use std::fs::{File, create_dir_all};
use std::io::Write;
use std::path::Path;

include!(concat!(env!("OUT_DIR"), "/resources.rs"));

fn main() {
  let options = App::new("spectra")
    .arg(Arg::with_name("bootstrap")
         .short("b")
         .long("bootstrap")
         .takes_value(false)
         .help("bootstrap default resources into the current application"))
    .get_matches();

  if options.is_present("bootstrap") {
    println!("bootstraping resources");

    for resource in &get_resources() {
      println!("--> {:?}", resource.0);
      copy_file(resource);
    }
  }
}

fn copy_file(entry: &(PathBuf, &'static [u8])) {
  let path = entry.0.as_path();
  let parent = path.parent().unwrap_or(&Path::new("."));

  create_dir_all(parent).unwrap();

  if let Ok(mut file) = File::create(path) {
    file.write_all(entry.1).unwrap();
  }
}
<commit_msg>bootstrap is now a subcommand!<commit_after>extern crate clap;

use clap::{App, SubCommand};
use std::fs::{File, create_dir_all};
use std::io::Write;
use std::path::Path;

include!(concat!(env!("OUT_DIR"), "/resources.rs"));

fn main() {
  let options = App::new("spectra")
    .subcommand(SubCommand::with_name("bootstrap")
         .about("Create default resources in your end-user project"))
    .get_matches();

  if options.subcommand_matches("bootstrap").is_some() {
    println!("bootstraping resources");

    for resource in &get_resources() {
      println!("--> {:?}", resource.0);
      copy_file(resource);
    }
  }
}

fn copy_file(entry: &(PathBuf, &'static [u8])) {
  let path = entry.0.as_path();
  let parent = path.parent().unwrap_or(&Path::new("."));

  create_dir_all(parent).unwrap();

  if let Ok(mut file) = File::create(path) {
    file.write_all(entry.1).unwrap();
  }
}
<|endoftext|>


<commit_before>use std::cmp::{max, min};

use cssparser::Parser;
use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{ElementResult, SetAttributes};
use crate::error::*;
use crate::node::Node;
use crate::parsers::{NonNegative, NumberOptionalNumber, Parse, ParseValue};
use crate::properties::ColorInterpolationFilters;
use crate::rect::IRect;
use crate::session::Session;
use crate::surface_utils::{
    iterators::{PixelRectangle, Pixels},
    shared_surface::ExclusiveImageSurface,
    EdgeMode, ImageSurfaceDataExt, Pixel,
};
use crate::xml::Attributes;

use super::bounds::BoundsBuilder;
use super::context::{FilterContext, FilterOutput};
use super::{
    FilterEffect, FilterError, FilterResolveError, Input, Primitive, PrimitiveParams,
    ResolvedPrimitive,
};

/// Enumeration of the possible morphology operations.
#[derive(Clone)]
enum Operator {
    Erode,
    Dilate,
}

enum_default!(Operator, Operator::Erode);

/// The `feMorphology` filter primitive.
#[derive(Default)]
pub struct FeMorphology {
    base: Primitive,
    params: Morphology,
}

/// Resolved `feMorphology` primitive for rendering.
#[derive(Clone, Default)]
pub struct Morphology {
    in1: Input,
    operator: Operator,
    radius: (f64, f64),
}

impl SetAttributes for FeMorphology {
    fn set_attributes(&mut self, attrs: &Attributes, session: &Session) -> ElementResult {
        self.params.in1 = self.base.parse_one_input(attrs, session);

        for (attr, value) in attrs.iter() {
            match attr.expanded() {
                expanded_name!("", "operator") => self.params.operator = attr.parse(value)?,
                expanded_name!("", "radius") => {
                    let NumberOptionalNumber(NonNegative(x), NonNegative(y)) = attr.parse(value)?;
                    self.params.radius = (x, y);
                }
                _ => (),
            }
        }

        Ok(())
    }
}

impl Morphology {
    pub fn render(
        &self,
        bounds_builder: BoundsBuilder,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes<'_>,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterOutput, FilterError> {
        // Although https://www.w3.org/TR/filter-effects/#propdef-color-interpolation-filters does not mention
        // feMorphology as being one of the primitives that does *not* use that property,
        // the SVG1.1 test for filters-morph-01-f.svg fails if we pass the value from the ComputedValues here (that
        // document does not specify the color-interpolation-filters property, so it defaults to linearRGB).
        // So, we pass Auto, which will get resolved to SRGB, and that makes that test pass.
        //
        // I suppose erosion/dilation doesn't care about the color space of the source image?

        let input_1 = ctx.get_input(
            acquired_nodes,
            draw_ctx,
            &self.in1,
            ColorInterpolationFilters::Auto,
        )?;
        let bounds: IRect = bounds_builder
            .add_input(&input_1)
            .compute(ctx)
            .clipped
            .into();

        let (rx, ry) = self.radius;
        let (rx, ry) = ctx.paffine().transform_distance(rx, ry);

        // The radii can become negative here due to the transform.
        // Additionally The radii being excessively large causes cpu hangups
        let (rx, ry) = (rx.abs().min(10.0), ry.abs().min(10.0));

        let mut surface = ExclusiveImageSurface::new(
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
            input_1.surface().surface_type(),
        )?;

        surface.modify(&mut |data, stride| {
            for (x, y, _pixel) in Pixels::within(input_1.surface(), bounds) {
                // Compute the kernel rectangle bounds.
                let kernel_bounds = IRect::new(
                    (f64::from(x) - rx).floor() as i32,
                    (f64::from(y) - ry).floor() as i32,
                    (f64::from(x) + rx).ceil() as i32 + 1,
                    (f64::from(y) + ry).ceil() as i32 + 1,
                );

                // Compute the new pixel values.
                let initial = match self.operator {
                    Operator::Erode => u8::max_value(),
                    Operator::Dilate => u8::min_value(),
                };

                let mut output_pixel = Pixel {
                    r: initial,
                    g: initial,
                    b: initial,
                    a: initial,
                };

                for (_x, _y, pixel) in
                    PixelRectangle::within(input_1.surface(), bounds, kernel_bounds, EdgeMode::None)
                {
                    let op = match self.operator {
                        Operator::Erode => min,
                        Operator::Dilate => max,
                    };

                    output_pixel.r = op(output_pixel.r, pixel.r);
                    output_pixel.g = op(output_pixel.g, pixel.g);
                    output_pixel.b = op(output_pixel.b, pixel.b);
                    output_pixel.a = op(output_pixel.a, pixel.a);
                }

                data.set_pixel(stride, output_pixel, x, y);
            }
        });

        Ok(FilterOutput {
            surface: surface.share()?,
            bounds,
        })
    }
}

impl FilterEffect for FeMorphology {
    fn resolve(
        &self,
        _acquired_nodes: &mut AcquiredNodes<'_>,
        _node: &Node,
    ) -> Result<ResolvedPrimitive, FilterResolveError> {
        Ok(ResolvedPrimitive {
            primitive: self.base.clone(),
            params: PrimitiveParams::Morphology(self.params.clone()),
        })
    }
}

impl Parse for Operator {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, ParseError<'i>> {
        Ok(parse_identifiers!(
            parser,
            "erode" => Operator::Erode,
            "dilate" => Operator::Dilate,
        )?)
    }
}
<commit_msg>feMorphology: same as for feGaussianBlur, explicitly ignore non-positive radiuses<commit_after>use std::cmp::{max, min};

use cssparser::Parser;
use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{ElementResult, SetAttributes};
use crate::error::*;
use crate::node::Node;
use crate::parsers::{NonNegative, NumberOptionalNumber, Parse, ParseValue};
use crate::properties::ColorInterpolationFilters;
use crate::rect::IRect;
use crate::session::Session;
use crate::surface_utils::{
    iterators::{PixelRectangle, Pixels},
    shared_surface::ExclusiveImageSurface,
    EdgeMode, ImageSurfaceDataExt, Pixel,
};
use crate::xml::Attributes;

use super::bounds::BoundsBuilder;
use super::context::{FilterContext, FilterOutput};
use super::{
    FilterEffect, FilterError, FilterResolveError, Input, Primitive, PrimitiveParams,
    ResolvedPrimitive,
};

/// Enumeration of the possible morphology operations.
#[derive(Clone)]
enum Operator {
    Erode,
    Dilate,
}

enum_default!(Operator, Operator::Erode);

/// The `feMorphology` filter primitive.
#[derive(Default)]
pub struct FeMorphology {
    base: Primitive,
    params: Morphology,
}

/// Resolved `feMorphology` primitive for rendering.
#[derive(Clone, Default)]
pub struct Morphology {
    in1: Input,
    operator: Operator,
    radius: (f64, f64),
}

impl SetAttributes for FeMorphology {
    fn set_attributes(&mut self, attrs: &Attributes, session: &Session) -> ElementResult {
        self.params.in1 = self.base.parse_one_input(attrs, session);

        for (attr, value) in attrs.iter() {
            match attr.expanded() {
                expanded_name!("", "operator") => self.params.operator = attr.parse(value)?,
                expanded_name!("", "radius") => {
                    let NumberOptionalNumber(NonNegative(x), NonNegative(y)) = attr.parse(value)?;
                    self.params.radius = (x, y);
                }
                _ => (),
            }
        }

        Ok(())
    }
}

impl Morphology {
    pub fn render(
        &self,
        bounds_builder: BoundsBuilder,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes<'_>,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterOutput, FilterError> {
        // Although https://www.w3.org/TR/filter-effects/#propdef-color-interpolation-filters does not mention
        // feMorphology as being one of the primitives that does *not* use that property,
        // the SVG1.1 test for filters-morph-01-f.svg fails if we pass the value from the ComputedValues here (that
        // document does not specify the color-interpolation-filters property, so it defaults to linearRGB).
        // So, we pass Auto, which will get resolved to SRGB, and that makes that test pass.
        //
        // I suppose erosion/dilation doesn't care about the color space of the source image?

        let input_1 = ctx.get_input(
            acquired_nodes,
            draw_ctx,
            &self.in1,
            ColorInterpolationFilters::Auto,
        )?;
        let bounds: IRect = bounds_builder
            .add_input(&input_1)
            .compute(ctx)
            .clipped
            .into();

        let (rx, ry) = self.radius;

        if rx <= 0.0 && ry <= 0.0 {
            return Ok(FilterOutput {
                surface: input_1.surface().clone(),
                bounds,
            });
        }

        let (rx, ry) = ctx.paffine().transform_distance(rx, ry);

        // The radii can become negative here due to the transform.
        // Additionally The radii being excessively large causes cpu hangups
        let (rx, ry) = (rx.abs().min(10.0), ry.abs().min(10.0));

        let mut surface = ExclusiveImageSurface::new(
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
            input_1.surface().surface_type(),
        )?;

        surface.modify(&mut |data, stride| {
            for (x, y, _pixel) in Pixels::within(input_1.surface(), bounds) {
                // Compute the kernel rectangle bounds.
                let kernel_bounds = IRect::new(
                    (f64::from(x) - rx).floor() as i32,
                    (f64::from(y) - ry).floor() as i32,
                    (f64::from(x) + rx).ceil() as i32 + 1,
                    (f64::from(y) + ry).ceil() as i32 + 1,
                );

                // Compute the new pixel values.
                let initial = match self.operator {
                    Operator::Erode => u8::max_value(),
                    Operator::Dilate => u8::min_value(),
                };

                let mut output_pixel = Pixel {
                    r: initial,
                    g: initial,
                    b: initial,
                    a: initial,
                };

                for (_x, _y, pixel) in
                    PixelRectangle::within(input_1.surface(), bounds, kernel_bounds, EdgeMode::None)
                {
                    let op = match self.operator {
                        Operator::Erode => min,
                        Operator::Dilate => max,
                    };

                    output_pixel.r = op(output_pixel.r, pixel.r);
                    output_pixel.g = op(output_pixel.g, pixel.g);
                    output_pixel.b = op(output_pixel.b, pixel.b);
                    output_pixel.a = op(output_pixel.a, pixel.a);
                }

                data.set_pixel(stride, output_pixel, x, y);
            }
        });

        Ok(FilterOutput {
            surface: surface.share()?,
            bounds,
        })
    }
}

impl FilterEffect for FeMorphology {
    fn resolve(
        &self,
        _acquired_nodes: &mut AcquiredNodes<'_>,
        _node: &Node,
    ) -> Result<ResolvedPrimitive, FilterResolveError> {
        Ok(ResolvedPrimitive {
            primitive: self.base.clone(),
            params: PrimitiveParams::Morphology(self.params.clone()),
        })
    }
}

impl Parse for Operator {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, ParseError<'i>> {
        Ok(parse_identifiers!(
            parser,
            "erode" => Operator::Erode,
            "dilate" => Operator::Dilate,
        )?)
    }
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate compiletest_rs as compiletest;
extern crate test;

use std::ffi::OsStr;
use std::fs;
use std::error::Error;
use std::env::{set_var, var};
use std::path::{Path, PathBuf};

fn clippy_driver_path() -> PathBuf {
    if let Some(path) = option_env!("CLIPPY_DRIVER_PATH") {
        PathBuf::from(path)
    } else {
        PathBuf::from(concat!("target/", env!("PROFILE"), "/clippy-driver"))
    }
}

fn host_libs() -> PathBuf {
    if let Some(path) = option_env!("HOST_LIBS") {
        PathBuf::from(path)
    } else {
        Path::new("target").join(env!("PROFILE"))
    }
}

fn rustc_test_suite() -> Option<PathBuf> {
    option_env!("RUSTC_TEST_SUITE").map(PathBuf::from)
}

fn rustc_lib_path() -> PathBuf {
    option_env!("RUSTC_LIB_PATH").unwrap().into()
}

fn config(mode: &str, dir: &str) -> compiletest::Config {
    let mut config = compiletest::Config::default();

    let cfg_mode = mode.parse().expect("Invalid mode");
    if let Ok(name) = var::<&str>("TESTNAME") {
        let s: String = name.to_owned();
        config.filter = Some(s)
    }

    if rustc_test_suite().is_some() {
        config.run_lib_path = rustc_lib_path();
        config.compile_lib_path = rustc_lib_path();
    }
    config.target_rustcflags = Some(format!("-L {0} -L {0}/deps -Dwarnings", host_libs().display()));

    config.mode = cfg_mode;
    config.build_base = if rustc_test_suite().is_some() {
        // we don't need access to the stderr files on travis
        let mut path = PathBuf::from(env!("OUT_DIR"));
        path.push("test_build_base");
        path
    } else {
        let mut path = std::env::current_dir().unwrap();
        path.push("target/debug/test_build_base");
        path
    };
    config.src_base = PathBuf::from(format!("tests/{}", dir));
    config.rustc_path = clippy_driver_path();
    config
}

fn run_mode(mode: &str, dir: &str) {
    compiletest::run_tests(&config(mode, dir));
}

fn run_ui_toml() -> Result<(), Box<Error>> {
    let base = PathBuf::from("tests/ui-toml/").canonicalize()?;
    for dir in fs::read_dir(&base)? {
        let dir = dir?;
        if !dir.file_type()?.is_dir() {
            continue;
        }
        let dir_path = dir.path();
        set_var("CARGO_MANIFEST_DIR", &dir_path);
        let config = config("ui", "ui-toml");
        for file in fs::read_dir(&dir_path)? {
            let file = file?;
            let file_path = file.path();
            if !file.file_type()?.is_file() {
                continue;
            }
            if file_path.extension() != Some(OsStr::new("rs")) {
                continue;
            }
            let paths = compiletest::common::TestPaths {
                file: file_path,
                base: base.clone(),
                relative_dir: dir_path.file_name().unwrap().into(),
            };
            compiletest::runtest::run(config.clone(), &paths);
        }
    }
    Ok(())
}

fn prepare_env() {
    set_var("CLIPPY_DISABLE_DOCS_LINKS", "true");
    set_var("CLIPPY_TESTS", "true");
    //set_var("RUST_BACKTRACE", "0");
}

#[test]
fn compile_test() {
    prepare_env();
    run_mode("run-pass", "run-pass");
    run_mode("ui", "ui");
    run_ui_toml().unwrap();
}
<commit_msg>Use compiletest::make_tests to allow it to setup the output folders<commit_after>#![feature(test)]

extern crate compiletest_rs as compiletest;
extern crate test;

use std::io;
use std::ffi::OsStr;
use std::fs;
use std::env::{set_var, var};
use std::path::{Path, PathBuf};

fn clippy_driver_path() -> PathBuf {
    if let Some(path) = option_env!("CLIPPY_DRIVER_PATH") {
        PathBuf::from(path)
    } else {
        PathBuf::from(concat!("target/", env!("PROFILE"), "/clippy-driver"))
    }
}

fn host_libs() -> PathBuf {
    if let Some(path) = option_env!("HOST_LIBS") {
        PathBuf::from(path)
    } else {
        Path::new("target").join(env!("PROFILE"))
    }
}

fn rustc_test_suite() -> Option<PathBuf> {
    option_env!("RUSTC_TEST_SUITE").map(PathBuf::from)
}

fn rustc_lib_path() -> PathBuf {
    option_env!("RUSTC_LIB_PATH").unwrap().into()
}

fn config(mode: &str, dir: PathBuf) -> compiletest::Config {
    let mut config = compiletest::Config::default();

    let cfg_mode = mode.parse().expect("Invalid mode");
    if let Ok(name) = var::<&str>("TESTNAME") {
        let s: String = name.to_owned();
        config.filter = Some(s)
    }

    if rustc_test_suite().is_some() {
        config.run_lib_path = rustc_lib_path();
        config.compile_lib_path = rustc_lib_path();
    }
    config.target_rustcflags = Some(format!("-L {0} -L {0}/deps -Dwarnings", host_libs().display()));

    config.mode = cfg_mode;
    config.build_base = if rustc_test_suite().is_some() {
        // we don't need access to the stderr files on travis
        let mut path = PathBuf::from(env!("OUT_DIR"));
        path.push("test_build_base");
        path
    } else {
        let mut path = std::env::current_dir().unwrap();
        path.push("target/debug/test_build_base");
        path
    };
    config.src_base = dir;
    config.rustc_path = clippy_driver_path();
    config
}

fn run_mode(mode: &str, dir: PathBuf) {
    compiletest::run_tests(&config(mode, dir));
}

fn run_ui_toml_tests(config: &compiletest::Config, mut tests: Vec<test::TestDescAndFn>) -> Result<bool, io::Error> {
    let mut result = true;
    let opts = compiletest::test_opts(config);
    for dir in fs::read_dir(&config.src_base)? {
        let dir = dir?;
        if !dir.file_type()?.is_dir() {
            continue;
        }
        let dir_path = dir.path();
        set_var("CARGO_MANIFEST_DIR", &dir_path);
        for file in fs::read_dir(&dir_path)? {
            let file = file?;
            let file_path = file.path();
            if !file.file_type()?.is_file() {
                continue;
            }
            if file_path.extension() != Some(OsStr::new("rs")) {
                continue;
            }
            let paths = compiletest::common::TestPaths {
                file: file_path,
                base: config.src_base.clone(),
                relative_dir: dir_path.file_name().unwrap().into(),
            };
            let test_name = compiletest::make_test_name(&config, &paths);
            let index = tests.iter()
                .position(|test| test.desc.name == test_name)
                .expect("The test should be in there");
            result &= test::run_tests_console(
                &opts,
                vec![tests.swap_remove(index)])?;
        }
    }
    Ok(result)
}

fn run_ui_toml() {
    let path = PathBuf::from("tests/ui-toml").canonicalize().unwrap();
    let config = config("ui", path);
    let tests = compiletest::make_tests(&config);

    let res = run_ui_toml_tests(&config, tests);
    match res {
        Ok(true) => {}
        Ok(false) => panic!("Some tests failed"),
        Err(e) => {
            println!("I/O failure during tests: {:?}", e);
        }
    }
}

fn prepare_env() {
    set_var("CLIPPY_DISABLE_DOCS_LINKS", "true");
    set_var("CLIPPY_TESTS", "true");
    //set_var("RUST_BACKTRACE", "0");
}

#[test]
fn compile_test() {
    prepare_env();
    run_mode("run-pass", "tests/run-pass".into());
    run_mode("ui", "tests/ui".into());
    run_ui_toml();
}
<|endoftext|>