<commit_before>use compositor::{Action, Server, Shell, View};
use wlroots::{CompositorHandle, Origin, SurfaceHandle, SurfaceHandler, XdgV6ShellHandler,
              XdgV6ShellManagerHandler, XdgV6ShellState::*, XdgV6ShellSurfaceHandle};

use std::rc::Rc;
use wlroots::xdg_shell_v6_events::{MoveEvent, ResizeEvent};

#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct XdgV6 {
    shell_surface: XdgV6ShellSurfaceHandle
}

impl XdgV6 {
    pub fn new() -> Self {
        XdgV6 { ..XdgV6::default() }
    }
}

impl XdgV6ShellHandler for XdgV6 {
    fn resize_request(&mut self,
                      compositor: CompositorHandle,
                      _: SurfaceHandle,
                      shell_surface: XdgV6ShellSurfaceHandle,
                      event: &ResizeEvent) {
        with_handles!([(compositor: {compositor})] => {
            let server: &mut Server = compositor.into();
            let Server { ref mut seat,
                         ref mut views,
                         ref mut cursor,
                         .. } = *server;
            let resizing_shell = shell_surface.into();

            if let Some(view) = views.iter().find(|view| view.shell == resizing_shell).cloned() {
                seat.begin_resize(cursor, view.clone(), views, event.edges())
            }
        }).unwrap();
    }

    fn move_request(&mut self,
                    compositor: CompositorHandle,
                    _: SurfaceHandle,
                    shell_surface: XdgV6ShellSurfaceHandle,
                    _: &MoveEvent) {
        with_handles!([(compositor: {compositor})] => {
            let server: &mut Server = compositor.into();
            let ref mut seat = server.seat;
            let ref mut cursor = server.cursor;

            if let Some(ref mut view) = seat.focused {
                let shell: Shell = shell_surface.into();
                let action = &mut seat.action;
                if view.shell == shell {
                    with_handles!([(cursor: {cursor})] => {
                        let (lx, ly) = cursor.coords();
                        let Origin { x: shell_x, y: shell_y } = view.origin.get();
                        let (view_sx, view_sy) = (lx - shell_x as f64, ly - shell_y as f64);
                        let start = Origin::new(view_sx as _, view_sy as _);
                        *action = Some(Action::Moving { start: start });
                    }).unwrap();
                }
            }
        }).unwrap();
    }

    fn on_commit(&mut self,
                 compositor: CompositorHandle,
                 _: SurfaceHandle,
                 shell_surface: XdgV6ShellSurfaceHandle) {
        let configure_serial = {
            with_handles!([(shell_surface: {shell_surface.clone()})] => {
                shell_surface.configure_serial()
            }).unwrap()
        };

        let surface = shell_surface.into();
        with_handles!([(compositor: {compositor})] => {
            let server: &mut Server = compositor.into();
            let Server { ref mut seat,
                         ref mut views,
                         ref mut cursor,
                         .. } = *server;

            if let Some(view) = views.iter().find(|view| view.shell == surface).cloned() {
                if let Some(move_resize) = view.pending_move_resize.get() {
                    if move_resize.serial >= configure_serial {
                        let Origin {mut x, mut y} = view.origin.get();
                        if move_resize.update_x {
                            x  = move_resize.area.origin.x + move_resize.area.size.width -
                                 view.get_size().width;
                        }
                        if move_resize.update_y {
                            y  = move_resize.area.origin.y + move_resize.area.size.height -
                                 view.get_size().height;
                        }

                        view.origin.set(Origin { x, y });

                        if move_resize.serial == configure_serial {
                            view.pending_move_resize.set(None);
                        }
                    }
                }
            }
        }).unwrap();
    }

    fn map_request(&mut self,
                   compositor: CompositorHandle,
                   _: SurfaceHandle,
                   shell_surface_handle: XdgV6ShellSurfaceHandle) {
        dehandle!(
            @shell_surface = {shell_surface_handle.clone()};
            let is_toplevel = match shell_surface.state().unwrap() {
                TopLevel(_) => true,
                _ => false
            };
            @compositor = {compositor};
            let server: &mut Server = compositor.into();
            let Server { ref mut seat,
                         ref mut views,
                         ref cursor,
                         ref mut xcursor_manager,
                         .. } = *server;
            if is_toplevel {
                let view = Rc::new(View::new(Shell::XdgV6(shell_surface_handle.into())));
                views.push(view.clone());
                seat.focus_view(view, views);
            };
            @cursor = {cursor};
            seat.update_cursor_position(cursor, xcursor_manager, views, None)
        );
    }

    fn unmap_request(&mut self,
                     compositor: CompositorHandle,
                     _: SurfaceHandle,
                     shell_surface: XdgV6ShellSurfaceHandle) {
        dehandle!(
            @compositor = {compositor};
            let server: &mut Server = compositor.into();
            let Server { ref mut seat,
                         ref mut views,
                         ref cursor,
                         ref mut xcursor_manager,
                         .. } = *server;
            let destroyed_shell = shell_surface.into();
            if let Some(pos) = views.iter().position(|view| view.shell == destroyed_shell) {
                views.remove(pos);
            };

            if views.len() > 0 {
                seat.focus_view(views[0].clone(), views);
            } else {
                seat.clear_focus();
            };
            @cursor = {cursor};
            seat.update_cursor_position(cursor, xcursor_manager, views, None)
        );
    }
}

pub struct XdgV6ShellManager;

impl XdgV6ShellManagerHandler for XdgV6ShellManager {
    fn new_surface(&mut self,
                   _: CompositorHandle,
                   _: XdgV6ShellSurfaceHandle)
                   -> (Option<Box<XdgV6ShellHandler>>, Option<Box<SurfaceHandler>>) {
        (Some(Box::new(XdgV6::new())), None)
    }
}
<commit_msg>Hotfixed the top level bug<commit_after>use compositor::{Action, Server, Shell, View};
use wlroots::{CompositorHandle, Origin, SurfaceHandle, SurfaceHandler, XdgV6ShellHandler,
              XdgV6ShellManagerHandler, XdgV6ShellState::*, XdgV6ShellSurfaceHandle};

use std::rc::Rc;
use wlroots::xdg_shell_v6_events::{MoveEvent, ResizeEvent};

#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct XdgV6 {
    shell_surface: XdgV6ShellSurfaceHandle
}

impl XdgV6 {
    pub fn new() -> Self {
        XdgV6 { ..XdgV6::default() }
    }
}

impl XdgV6ShellHandler for XdgV6 {
    fn resize_request(&mut self,
                      compositor: CompositorHandle,
                      _: SurfaceHandle,
                      shell_surface: XdgV6ShellSurfaceHandle,
                      event: &ResizeEvent) {
        with_handles!([(compositor: {compositor})] => {
            let server: &mut Server = compositor.into();
            let Server { ref mut seat,
                         ref mut views,
                         ref mut cursor,
                         .. } = *server;
            let resizing_shell = shell_surface.into();

            if let Some(view) = views.iter().find(|view| view.shell == resizing_shell).cloned() {
                seat.begin_resize(cursor, view.clone(), views, event.edges())
            }
        }).unwrap();
    }

    fn move_request(&mut self,
                    compositor: CompositorHandle,
                    _: SurfaceHandle,
                    shell_surface: XdgV6ShellSurfaceHandle,
                    _: &MoveEvent) {
        with_handles!([(compositor: {compositor})] => {
            let server: &mut Server = compositor.into();
            let ref mut seat = server.seat;
            let ref mut cursor = server.cursor;

            if let Some(ref mut view) = seat.focused {
                let shell: Shell = shell_surface.into();
                let action = &mut seat.action;
                if view.shell == shell {
                    with_handles!([(cursor: {cursor})] => {
                        let (lx, ly) = cursor.coords();
                        let Origin { x: shell_x, y: shell_y } = view.origin.get();
                        let (view_sx, view_sy) = (lx - shell_x as f64, ly - shell_y as f64);
                        let start = Origin::new(view_sx as _, view_sy as _);
                        *action = Some(Action::Moving { start: start });
                    }).unwrap();
                }
            }
        }).unwrap();
    }

    fn on_commit(&mut self,
                 compositor: CompositorHandle,
                 _: SurfaceHandle,
                 shell_surface: XdgV6ShellSurfaceHandle) {
        let configure_serial = {
            with_handles!([(shell_surface: {shell_surface.clone()})] => {
                shell_surface.configure_serial()
            }).unwrap()
        };

        let surface = shell_surface.into();
        with_handles!([(compositor: {compositor})] => {
            let server: &mut Server = compositor.into();
            let Server { ref mut seat,
                         ref mut views,
                         ref mut cursor,
                         .. } = *server;

            if let Some(view) = views.iter().find(|view| view.shell == surface).cloned() {
                if let Some(move_resize) = view.pending_move_resize.get() {
                    if move_resize.serial >= configure_serial {
                        let Origin {mut x, mut y} = view.origin.get();
                        if move_resize.update_x {
                            x  = move_resize.area.origin.x + move_resize.area.size.width -
                                 view.get_size().width;
                        }
                        if move_resize.update_y {
                            y  = move_resize.area.origin.y + move_resize.area.size.height -
                                 view.get_size().height;
                        }

                        view.origin.set(Origin { x, y });

                        if move_resize.serial == configure_serial {
                            view.pending_move_resize.set(None);
                        }
                    }
                }
            }
        }).unwrap();
    }

    fn map_request(&mut self,
                   compositor: CompositorHandle,
                   _: SurfaceHandle,
                   shell_surface_handle: XdgV6ShellSurfaceHandle) {
        let is_toplevel = with_handles!([(shell_surface: {&shell_surface_handle})] => {
            match shell_surface.state().unwrap() {
                TopLevel(_) => true,
                _ => false
            }
        }).unwrap();
        dehandle!(
            @compositor = {compositor};
            let server: &mut Server = compositor.into();
            let Server { ref mut seat,
                         ref mut views,
                         ref cursor,
                         ref mut xcursor_manager,
                         .. } = *server;
            if is_toplevel {
                let view = Rc::new(View::new(Shell::XdgV6(shell_surface_handle.into())));
                views.push(view.clone());
                seat.focus_view(view, views);
            };
            @cursor = {cursor};
            seat.update_cursor_position(cursor, xcursor_manager, views, None)
        );
    }

    fn unmap_request(&mut self,
                     compositor: CompositorHandle,
                     _: SurfaceHandle,
                     shell_surface: XdgV6ShellSurfaceHandle) {
        dehandle!(
            @compositor = {compositor};
            let server: &mut Server = compositor.into();
            let Server { ref mut seat,
                         ref mut views,
                         ref cursor,
                         ref mut xcursor_manager,
                         .. } = *server;
            let destroyed_shell = shell_surface.into();
            if let Some(pos) = views.iter().position(|view| view.shell == destroyed_shell) {
                views.remove(pos);
            };

            if views.len() > 0 {
                seat.focus_view(views[0].clone(), views);
            } else {
                seat.clear_focus();
            };
            @cursor = {cursor};
            seat.update_cursor_position(cursor, xcursor_manager, views, None)
        );
    }
}

pub struct XdgV6ShellManager;

impl XdgV6ShellManagerHandler for XdgV6ShellManager {
    fn new_surface(&mut self,
                   _: CompositorHandle,
                   _: XdgV6ShellSurfaceHandle)
                   -> (Option<Box<XdgV6ShellHandler>>, Option<Box<SurfaceHandler>>) {
        (Some(Box::new(XdgV6::new())), None)
    }
}
<|endoftext|>


<commit_before>use compositor::{Action, Server, Shell, View};
use wlroots::{CompositorHandle, Origin, SurfaceHandle, XdgV6ShellHandler,
              XdgV6ShellManagerHandler, XdgV6ShellState::*, XdgV6ShellSurfaceHandle};

use wlroots::xdg_shell_v6_events::MoveEvent;

#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct XdgV6 {
    shell_surface: XdgV6ShellSurfaceHandle
}

impl XdgV6 {
    pub fn new() -> Self {
        XdgV6 { ..XdgV6::default() }
    }
}

impl XdgV6ShellHandler for XdgV6 {
    fn move_request(&mut self,
                    compositor: CompositorHandle,
                    _surface: SurfaceHandle,
                    shell_surface: XdgV6ShellSurfaceHandle,
                    _event: &MoveEvent) {
        with_handles!([(compositor: {compositor})] => {
            let server: &mut Server = compositor.into();
            let ref mut seat = server.seat;
            let ref mut cursor = server.cursor;

            if let Some(ref mut view) = seat.focused {
                let shell: Shell = shell_surface.into();
                let action = &mut seat.action;
                if view.shell == shell {
                    with_handles!([(cursor: {cursor})] => {
                        let (lx, ly) = cursor.coords();
                        let Origin { x: shell_x, y: shell_y } = view.origin;
                        let (view_sx, view_sy) = (lx - shell_x as f64, ly - shell_y as f64);
                        let start = Origin::new(view_sx as _, view_sy as _);
                        *action = Some(Action::Moving { start: start });
                    }).unwrap();
                }
            }
        }).unwrap();
    }
}

pub struct XdgV6ShellManager;

impl XdgV6ShellManagerHandler for XdgV6ShellManager {
    fn new_surface(&mut self,
                   compositor: CompositorHandle,
                   mut shell_surface: XdgV6ShellSurfaceHandle)
                   -> Option<Box<XdgV6ShellHandler>> {
        let is_toplevel = with_handles!([(shell_surface: {&mut shell_surface})] => {
            match shell_surface.state().unwrap() {
                TopLevel(_) => true,
                _ => false
            }
        }).unwrap();

        if is_toplevel {
            with_handles!([(compositor: {compositor})] => {
                let server: &mut Server = compositor.into();
                let Server { ref mut seat,
                             ref mut views,
                             .. } = *server;
                views.insert(0, View::new(Shell::XdgV6(shell_surface.into())));
                seat.focused = Some(views[0].clone());

                with_handles!([(seat: {&mut seat.seat})] => {
                    if let Some(keyboard) = seat.get_keyboard() {
                        with_handles!([(keyboard: {keyboard}),
                                       (surface: {views[0].shell.surface()})] => {
                                           seat.keyboard_notify_enter(surface,
                                                                      &mut keyboard.keycodes(),
                                                                      &mut keyboard.get_modifier_masks());
                        }).unwrap();
                    }
                    views[0].activate(true);
                }).unwrap();
            }).unwrap();
        }

        Some(Box::new(XdgV6::new()))
    }

    fn surface_destroyed(&mut self,
                         compositor: CompositorHandle,
                         shell_surface: XdgV6ShellSurfaceHandle) {
        with_handles!([(compositor: {compositor})] => {
            let server: &mut Server = compositor.into();
            let Server { ref mut seat,
                         ref mut views,
                         .. } = *server;
            let destroyed_shell = shell_surface.into();
            if let Some(pos) = views.iter().position(|view| view.shell == destroyed_shell) {
                views.remove(pos);
            }

            seat.focused = seat.focused.take().and_then(|mut focused| {
                if focused.shell == destroyed_shell {
                    with_handles!([(seat: {&mut seat.seat})] => {
                        if views.len() > 0 {
                            if let Some(keyboard) = seat.get_keyboard() {
                                with_handles!([(keyboard: {keyboard}),
                                    (surface: {focused.surface()})] => {
                                    seat.keyboard_notify_enter(surface,
                                                               &mut keyboard.keycodes(),
                                                               &mut keyboard.get_modifier_masks());
                                }).unwrap();
                            }
                            views[0].activate(true);
                            Some(views[0].clone())
                        } else {
                            seat.keyboard_clear_focus();
                            None
                        }
                    }).unwrap()
                } else {
                    Some(focused)
                }
            });

        }).unwrap();
    }
}
<commit_msg>use xdg-v6 map and unmap<commit_after>use compositor::{Action, Server, Shell, View};
use wlroots::{CompositorHandle, Origin, SurfaceHandle, XdgV6ShellHandler,
              XdgV6ShellManagerHandler, XdgV6ShellState::*, XdgV6ShellSurfaceHandle};

use wlroots::xdg_shell_v6_events::MoveEvent;

#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct XdgV6 {
    shell_surface: XdgV6ShellSurfaceHandle
}

impl XdgV6 {
    pub fn new() -> Self {
        XdgV6 { ..XdgV6::default() }
    }
}

impl XdgV6ShellHandler for XdgV6 {
    fn move_request(&mut self,
                    compositor: CompositorHandle,
                    _surface: SurfaceHandle,
                    shell_surface: XdgV6ShellSurfaceHandle,
                    _event: &MoveEvent) {
        with_handles!([(compositor: {compositor})] => {
            let server: &mut Server = compositor.into();
            let ref mut seat = server.seat;
            let ref mut cursor = server.cursor;

            if let Some(ref mut view) = seat.focused {
                let shell: Shell = shell_surface.into();
                let action = &mut seat.action;
                if view.shell == shell {
                    with_handles!([(cursor: {cursor})] => {
                        let (lx, ly) = cursor.coords();
                        let Origin { x: shell_x, y: shell_y } = view.origin;
                        let (view_sx, view_sy) = (lx - shell_x as f64, ly - shell_y as f64);
                        let start = Origin::new(view_sx as _, view_sy as _);
                        *action = Some(Action::Moving { start: start });
                    }).unwrap();
                }
            }
        }).unwrap();
    }

    fn map_request(&mut self,
                   compositor: CompositorHandle,
                   _surface: SurfaceHandle,
                   mut shell_surface: XdgV6ShellSurfaceHandle) {
        let is_toplevel = with_handles!([(shell_surface: {&mut shell_surface})] => {
            match shell_surface.state().unwrap() {
                TopLevel(_) => true,
                _ => false
            }
        }).unwrap();

        if is_toplevel {
            with_handles!([(compositor: {compositor})] => {
                let server: &mut Server = compositor.into();
                let Server { ref mut seat,
                             ref mut views,
                             .. } = *server;
                views.insert(0, View::new(Shell::XdgV6(shell_surface.into())));

                seat.focused.take().map(|mut focused| {
                    focused.activate(false);
                });

                seat.focused = Some(views[0].clone());

                with_handles!([(seat: {&mut seat.seat})] => {
                    if let Some(keyboard) = seat.get_keyboard() {
                        with_handles!([(keyboard: {keyboard}),
                                       (surface: {views[0].shell.surface()})] => {
                                           seat.keyboard_notify_enter(surface,
                                                                      &mut keyboard.keycodes(),
                                                                      &mut keyboard.get_modifier_masks());
                        }).unwrap();
                    }
                    views[0].activate(true);
                }).unwrap();
            }).unwrap();
        }
    }

    fn unmap_request(&mut self,
                   compositor: CompositorHandle,
                   _surface: SurfaceHandle,
                   shell_surface: XdgV6ShellSurfaceHandle) {
        with_handles!([(compositor: {compositor})] => {
            let server: &mut Server = compositor.into();
            let Server { ref mut seat,
                         ref mut views,
                         .. } = *server;
            let destroyed_shell = shell_surface.into();
            if let Some(pos) = views.iter().position(|view| view.shell == destroyed_shell) {
                views.remove(pos);
            }

            seat.focused = seat.focused.take().and_then(|mut focused| {
                if focused.shell == destroyed_shell {
                    with_handles!([(seat: {&mut seat.seat})] => {
                        if views.len() > 0 {
                            if let Some(keyboard) = seat.get_keyboard() {
                                with_handles!([(keyboard: {keyboard}),
                                    (surface: {focused.surface()})] => {
                                    seat.keyboard_notify_enter(surface,
                                                               &mut keyboard.keycodes(),
                                                               &mut keyboard.get_modifier_masks());
                                }).unwrap();
                            }
                            views[0].activate(true);
                            Some(views[0].clone())
                        } else {
                            seat.keyboard_clear_focus();
                            None
                        }
                    }).unwrap()
                } else {
                    Some(focused)
                }
            });

        }).unwrap();

    }
}

pub struct XdgV6ShellManager;

impl XdgV6ShellManagerHandler for XdgV6ShellManager {
    fn new_surface(&mut self,
                   _compositor: CompositorHandle,
                   _shell_surface: XdgV6ShellSurfaceHandle)
                   -> Option<Box<XdgV6ShellHandler>> {
        Some(Box::new(XdgV6::new()))
    }

    fn surface_destroyed(&mut self,
                         _compositor: CompositorHandle,
                         _shell_surface: XdgV6ShellSurfaceHandle) {
    }
}
<|endoftext|>


<commit_before>use eframe::egui;
use egui::emath::Vec2;

use std::fs::File;
use std::io::Write;

use cubes_rs::Pieces;

fn main() {
    let options = eframe::NativeOptions {
        initial_window_size: Some(Vec2 { x: 180., y: 300. }),
        ..Default::default()
    };

    eframe::run_native(
        "Polycubes",
        options,
        Box::new(|_cc| Box::new(MyApp::default())),
    );
}

struct MyApp {
    name: String,
    cube: [[[bool; 3]; 3]; 3],
    pieces: Pieces,
}

impl Default for MyApp {
    fn default() -> Self {
        Self {
            name: "".to_owned(),
            cube: [[[false; 3]; 3]; 3],
            pieces: Pieces { data: Vec::new() },
        }
    }
}

impl eframe::App for MyApp {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        egui::CentralPanel::default().show(ctx, |ui| {
            ui.heading("polycube piece");
            ui.horizontal(|ui| {
                ui.set_width(100.);
                ui.text_edit_singleline(&mut self.name);
            });

            for x in 0..3 {
                if x > 0 {
                    ui.horizontal(|ui| {
                        ui.label("");
                    });
                }
                for y in 0..3 {
                    ui.horizontal(|ui| {
                        for z in 0..3 {
                            if ui.toggle_value(&mut self.cube[x][y][z], "    ").clicked() {

                            }
                        }
                    });
                }
            }

            ui.horizontal(|ui| {
                if ui.button("save piece").clicked() {
                    self.pieces.data.push(Vec::new());
                    let len = self.pieces.data.len() - 1;

                    for x in 0..3 {
                        for y in 0..3 {
                            for z in 0..3 {
                                if self.cube[x][y][z] {
                                    println!("{:?} {:?} {:?}", x, y, z);
                                    self.pieces.data[len].push([x as i32, y as i32, z as i32]);
                                }
                            }
                        }
                    }
                    println!();
                }

                if ui.button("save all").clicked() {
                    let mut buffer = File::create(format!("puzzles/{}", self.name)).unwrap();
                    let encoded: Vec<u8> = bincode::serialize(&self.pieces).unwrap();
                    buffer.write_all(&encoded).unwrap();
                }
            });
        });
    }
}<commit_msg>Fix renaming.<commit_after>use eframe::egui;
use egui::emath::Vec2;

use std::fs::File;
use std::io::Write;

use cubes_rs::Puzzle;

fn main() {
    let options = eframe::NativeOptions {
        initial_window_size: Some(Vec2 { x: 180., y: 300. }),
        ..Default::default()
    };

    eframe::run_native(
        "Polycubes",
        options,
        Box::new(|_cc| Box::new(MyApp::default())),
    );
}

struct MyApp {
    name: String,
    cube: [[[bool; 3]; 3]; 3],
    pieces: Puzzle,
}

impl Default for MyApp {
    fn default() -> Self {
        Self {
            name: "".to_owned(),
            cube: [[[false; 3]; 3]; 3],
            pieces: Puzzle { data: Vec::new() },
        }
    }
}

impl eframe::App for MyApp {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        egui::CentralPanel::default().show(ctx, |ui| {
            ui.heading("polycube piece");
            ui.horizontal(|ui| {
                ui.set_width(100.);
                ui.text_edit_singleline(&mut self.name);
            });

            for x in 0..3 {
                if x > 0 {
                    ui.horizontal(|ui| {
                        ui.label("");
                    });
                }
                for y in 0..3 {
                    ui.horizontal(|ui| {
                        for z in 0..3 {
                            if ui.toggle_value(&mut self.cube[x][y][z], "    ").clicked() {

                            }
                        }
                    });
                }
            }

            ui.horizontal(|ui| {
                if ui.button("save piece").clicked() {
                    self.pieces.data.push(Vec::new());
                    let len = self.pieces.data.len() - 1;

                    for x in 0..3 {
                        for y in 0..3 {
                            for z in 0..3 {
                                if self.cube[x][y][z] {
                                    println!("{:?} {:?} {:?}", x, y, z);
                                    self.pieces.data[len].push([x as i32, y as i32, z as i32]);
                                }
                            }
                        }
                    }
                    println!();
                }

                if ui.button("save all").clicked() {
                    let mut buffer = File::create(format!("puzzles/{}", self.name)).unwrap();
                    let encoded: Vec<u8> = bincode::serialize(&self.pieces).unwrap();
                    buffer.write_all(&encoded).unwrap();
                }
            });
        });
    }
}<|endoftext|>


<commit_before>use libimagerror::trace::trace_error;
use libimagutil::iter::FoldResult;

use store::FileLockEntry;
use storeid::StoreId;
use hook::Hook;
use hook::result::HookResult;
use hook::accessor::{StoreIdAccessor, MutableHookDataAccessor, NonMutableHookDataAccessor};
use hook::accessor::HookDataAccessor as HDA;

use hook::error::HookError as HE;
use hook::error::HookErrorKind as HEK;
use configuration::AspectConfig;

#[derive(Debug)]
pub struct Aspect {
    cfg: Option<AspectConfig>,
    name: String,
    hooks: Vec<Box<Hook>>,
}

impl Aspect {

    pub fn new(name: String, cfg: Option<AspectConfig>) -> Aspect {
        Aspect {
            cfg: cfg,
            name: name,
            hooks: vec![],
        }
    }

    pub fn name(&self) -> &String {
        &self.name
    }

    pub fn register_hook(&mut self, h: Box<Hook>) {
        self.hooks.push(h);
    }

}

impl StoreIdAccessor for Aspect {
    fn access(&self, id: &StoreId) -> HookResult<()> {
        let accessors : Vec<HDA> = self.hooks.iter().map(|h| h.accessor()).collect();
        if !accessors.iter().all(|a| is_match!(*a, HDA::StoreIdAccess(_))) {
            return Err(HE::new(HEK::AccessTypeViolation, None));
        }

        accessors.iter().fold_defresult(|accessor| {
            let res = match accessor {
                &HDA::StoreIdAccess(accessor) => accessor.access(id),
                _ => unreachable!(),
            };
            trace_hook_errors(res)
        })
    }
}

impl MutableHookDataAccessor for Aspect {
    fn access_mut(&self, fle: &mut FileLockEntry) -> HookResult<()> {
        if !self.cfg.as_ref().map(|c| c.allow_mutable_hooks()).unwrap_or(false) {
            return Err(HE::new(HEK::MutableHooksNotAllowed, None));
        }

        let accessors : Vec<HDA> = self.hooks.iter().map(|h| h.accessor()).collect();

        fn is_file_accessor(a: &HDA) -> bool {
            is_match!(*a, HDA::MutableAccess(_) | HDA::NonMutableAccess(_))
        }

        if !accessors.iter().all(|a| is_file_accessor(a)) {
            return Err(HE::new(HEK::AccessTypeViolation, None));
        }

        // TODO: Naiive implementation.
        // More sophisticated version would check whether there are _chunks_ of
        // NonMutableAccess accessors and execute these chunks in parallel. We do not have
        // performance concerns yet, so this is okay.
        accessors.iter().fold_defresult(|accessor| {
            let res = match accessor {
                &HDA::MutableAccess(ref accessor)    => accessor.access_mut(fle),
                &HDA::NonMutableAccess(ref accessor) => accessor.access(fle),
                _ => unreachable!(),
            };
            trace_hook_errors(res)
        })
    }
}

impl NonMutableHookDataAccessor for Aspect {
    fn access(&self, fle: &FileLockEntry) -> HookResult<()> {
        let accessors : Vec<HDA> = self.hooks.iter().map(|h| h.accessor()).collect();
        if !accessors.iter().all(|a| is_match!(*a, HDA::NonMutableAccess(_))) {
            return Err(HE::new(HEK::AccessTypeViolation, None));
        }

        accessors.iter().fold_defresult(|accessor| {
            let res = match accessor {
                &HDA::NonMutableAccess(accessor) => accessor.access(fle),
                _ => unreachable!(),
            };
            trace_hook_errors(res)
        })
    }
}

fn trace_hook_errors(res: HookResult<()>) -> HookResult<()> {
    res.or_else(|e| {
        if !e.is_aborting() {
            trace_error(&e);
            // ignore error if it is not aborting, as we printed it already
            Ok(())
        } else {
            Err(e)
        }
    })
}

<commit_msg>Execute StoreIdAccess accessors in MutableHookDataAccessor impl for Aspect as well<commit_after>use libimagerror::trace::trace_error;
use libimagutil::iter::FoldResult;

use store::FileLockEntry;
use storeid::StoreId;
use hook::Hook;
use hook::result::HookResult;
use hook::accessor::{StoreIdAccessor, MutableHookDataAccessor, NonMutableHookDataAccessor};
use hook::accessor::HookDataAccessor as HDA;

use hook::error::HookError as HE;
use hook::error::HookErrorKind as HEK;
use configuration::AspectConfig;

#[derive(Debug)]
pub struct Aspect {
    cfg: Option<AspectConfig>,
    name: String,
    hooks: Vec<Box<Hook>>,
}

impl Aspect {

    pub fn new(name: String, cfg: Option<AspectConfig>) -> Aspect {
        Aspect {
            cfg: cfg,
            name: name,
            hooks: vec![],
        }
    }

    pub fn name(&self) -> &String {
        &self.name
    }

    pub fn register_hook(&mut self, h: Box<Hook>) {
        self.hooks.push(h);
    }

}

impl StoreIdAccessor for Aspect {
    fn access(&self, id: &StoreId) -> HookResult<()> {
        let accessors : Vec<HDA> = self.hooks.iter().map(|h| h.accessor()).collect();
        if !accessors.iter().all(|a| is_match!(*a, HDA::StoreIdAccess(_))) {
            return Err(HE::new(HEK::AccessTypeViolation, None));
        }

        accessors.iter().fold_defresult(|accessor| {
            let res = match accessor {
                &HDA::StoreIdAccess(accessor) => accessor.access(id),
                _ => unreachable!(),
            };
            trace_hook_errors(res)
        })
    }
}

impl MutableHookDataAccessor for Aspect {
    fn access_mut(&self, fle: &mut FileLockEntry) -> HookResult<()> {
        if !self.cfg.as_ref().map(|c| c.allow_mutable_hooks()).unwrap_or(false) {
            return Err(HE::new(HEK::MutableHooksNotAllowed, None));
        }

        let accessors : Vec<HDA> = self.hooks.iter().map(|h| h.accessor()).collect();

        // TODO: Naiive implementation.
        // More sophisticated version would check whether there are _chunks_ of
        // NonMutableAccess accessors and execute these chunks in parallel. We do not have
        // performance concerns yet, so this is okay.
        accessors.iter().fold_defresult(|accessor| {
            let res = match accessor {
                &HDA::StoreIdAccess(ref accessor)    => accessor.access(fle.get_location()),
                &HDA::MutableAccess(ref accessor)    => accessor.access_mut(fle),
                &HDA::NonMutableAccess(ref accessor) => accessor.access(fle),
            };
            trace_hook_errors(res)
        })
    }
}

impl NonMutableHookDataAccessor for Aspect {
    fn access(&self, fle: &FileLockEntry) -> HookResult<()> {
        let accessors : Vec<HDA> = self.hooks.iter().map(|h| h.accessor()).collect();
        if !accessors.iter().all(|a| is_match!(*a, HDA::NonMutableAccess(_))) {
            return Err(HE::new(HEK::AccessTypeViolation, None));
        }

        accessors.iter().fold_defresult(|accessor| {
            let res = match accessor {
                &HDA::NonMutableAccess(accessor) => accessor.access(fle),
                _ => unreachable!(),
            };
            trace_hook_errors(res)
        })
    }
}

fn trace_hook_errors(res: HookResult<()>) -> HookResult<()> {
    res.or_else(|e| {
        if !e.is_aborting() {
            trace_error(&e);
            // ignore error if it is not aborting, as we printed it already
            Ok(())
        } else {
            Err(e)
        }
    })
}

<|endoftext|>


<commit_before>//! A chat server that broadcasts a message to all connections.

extern crate tokio_core;
extern crate futures;

use std::collections::HashMap;
use std::rc::Rc;
use std::cell::RefCell;
use std::iter;
use std::env;
use std::io::{Error, ErrorKind, BufReader};

use tokio_core::net::TcpListener;
use tokio_core::reactor::Core;
use tokio_core::io::{self, Io};

use futures::stream::{self, Stream};
use futures::Future;

fn main() {
    let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
    let addr = addr.parse().unwrap();
    // We are single-threaded, so we can just use Rc and RefCell.
    let connections = Rc::new(RefCell::new(HashMap::new()));

    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let socket = TcpListener::bind(&addr, &handle).unwrap();
    println!("Listening on: {}", addr);

    let future = socket.incoming().for_each(move |(stream, addr)| {
        let connections = connections.clone();
        let handle_inner = handle.clone();
        // We create a new future in which we create all other futures.
        // This makes `stream` be bound on the outer future's task, allowing
        // `ReadHalf` and `WriteHalf` to be shared between inner futures.
        let main_fn = move || {
            println!("New Connection: {}", addr);
            let (reader, writer) = stream.split();
            // channel to send messages to this connection from other futures
            let (tx, rx) = tokio_core::channel::channel(&handle_inner).unwrap();
            // add sender to hashmap of all current connections
            connections.borrow_mut().insert(addr, tx);

            let reader = BufReader::new(reader);
            let connections_inner = connections.clone();
            // https://users.rust-lang.org/t/loop-futures-for-client-handling/6950/2
            // First we need to get an infinite iterator
            let iter = stream::iter::<_, _, std::io::Error>(iter::repeat(()).map(Ok));
            // Then we fold it as infinite loop
            let socket_reader = iter.fold(reader, move |reader, _| {
                // read line
                let amt = io::read_until(reader, '\n' as u8, vec![]);
                // check if we hit EOF and need to close the connection
                let amt = amt.and_then(|(reader, vec)| {
                    // EOF was hit without reading a delimiter
                    if vec.len() == 0 {
                        let err = Error::new(ErrorKind::BrokenPipe, "Broken Pipe");
                        Err(err)
                    } else {
                        Ok((reader, vec))
                    }
                });
                // convert bytes into string
                let amt = amt.map(|(reader, vec)| (reader, String::from_utf8(vec)));
                let connections = connections_inner.clone();
                amt.map(move |(reader, message)| {
                    println!("{}: {:?}", addr, message);
                    let conns = connections.borrow_mut();
                    if let Ok(msg) = message {
                        // For each open connection except the sender, send the string
                        // via the channel
                        let iter = conns.iter().filter(|&(&k,_)| k != addr).map(|(_,v)| v);
                        for tx in iter {
                            tx.send(format!("{}: {}", addr, msg)).unwrap();
                        }
                    } else {
                        let tx = conns.get(&addr).unwrap();
                        tx.send("You didn't send valid UTF-8.".to_string()).unwrap();
                    }
                    reader
                })
            });

            // Whenever we receive a string on the Receiver, we write it to `WriteHalf<TcpStream>`.
            let socket_writer = rx.fold(writer, |writer, msg| {
                let amt = io::write_all(writer, msg.into_bytes());
                let amt = amt.map(|(writer, _)| writer);
                amt
            });

            // In order to fuse the reading and writing futures in the end, we need to have the
            // same output type. As we don't need the values anymore, we can just map them
            // to `()`.
            let socket_reader = socket_reader.map(|_| ());
            let socket_writer = socket_writer.map(|_| ());

            let amt = socket_reader.select(socket_writer);
            amt.then(move |_| {
                connections.borrow_mut().remove(&addr);
                println!("Connection {} closed.", addr);
                Ok(())
            })
        };
        handle.spawn_fn(main_fn);
        Ok(())
    });

    // exectue server
    core.run(future).unwrap();
}

<commit_msg>Touch up the chat example<commit_after>//! A chat server that broadcasts a message to all connections.
//!
//! This is a simple line-based server which accepts connections, reads lines
//! from those connections, and broadcasts the lines to all other connected
//! clients. In a sense this is a bit of a "poor man's chat server".

extern crate tokio_core;
extern crate futures;

use std::collections::HashMap;
use std::rc::Rc;
use std::cell::RefCell;
use std::iter;
use std::env;
use std::io::{Error, ErrorKind, BufReader};

use tokio_core::net::TcpListener;
use tokio_core::reactor::Core;
use tokio_core::io::{self, Io};

use futures::stream::{self, Stream};
use futures::Future;

fn main() {
    let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
    let addr = addr.parse().unwrap();

    // Create the event loop and TCP listener we'll accept connections on.
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let socket = TcpListener::bind(&addr, &handle).unwrap();
    println!("Listening on: {}", addr);

    // This is a single-threaded server, so we can just use Rc and RefCell to
    // store the map of all connections we know about.
    let connections = Rc::new(RefCell::new(HashMap::new()));

    let srv = socket.incoming().for_each(move |(stream, addr)| {
        println!("New Connection: {}", addr);

        // Create a channel for for our stream, which other sockets will use to
        // send us message. Then register our address with the stream to send
        // data to us.
        let (tx, rx) = tokio_core::channel::channel(&handle).unwrap();
        connections.borrow_mut().insert(addr, tx);

        // Note that below we're calling `spawn` to spawn a new future for this
        // connection. As a result we use `futures::lazy` here to ensure that
        // the call to `.split()` happens on the right task.
        //
        // This `split` will give us a read/write half to work with each portion
        // of the socket separately.
        let pair = futures::lazy(|| Ok(stream.split()));

        // Define here what we do for the actual I/O. That is, read a bunch of
        // lines from the socket and dispatch them while we also write any lines
        // from other sockets.
        let connections_inner = connections.clone();
        let pair = pair.map(move |(reader, writer)| {
            let reader = BufReader::new(reader);

            // Model the read portion of this socket by mapping an infinite
            // iterator to each line off the socket. This "loop" is then
            // terminated with an error once we hit EOF on the socket.
            let iter = stream::iter(iter::repeat(()).map(Ok));
            let socket_reader = iter.fold(reader, move |reader, _| {
                // Read a line off the socket, failing if we're at EOF
                let line = io::read_until(reader, b'\n', Vec::new());
                let line = line.and_then(|(reader, vec)| {
                    if vec.len() == 0 {
                        Err(Error::new(ErrorKind::BrokenPipe, "broken pipe"))
                    } else {
                        Ok((reader, vec))
                    }
                });

                // Convert the bytes we read into a string, and then send that
                // string to all other connected clients.
                let line = line.map(|(reader, vec)| {
                    (reader, String::from_utf8(vec))
                });
                let connections = connections_inner.clone();
                line.map(move |(reader, message)| {
                    println!("{}: {:?}", addr, message);
                    let conns = connections.borrow_mut();
                    if let Ok(msg) = message {
                        // For each open connection except the sender, send the
                        // string via the channel
                        let iter = conns.iter()
                                        .filter(|&(&k, _)| k != addr)
                                        .map(|(_, v)| v);
                        for tx in iter {
                            tx.send(format!("{}: {}", addr, msg)).unwrap();
                        }
                    } else {
                        let tx = conns.get(&addr).unwrap();
                        tx.send("You didn't send valid UTF-8.".to_string()).unwrap();
                    }
                    reader
                })
            });

            // Whenever we receive a string on the Receiver, we write it to
            // `WriteHalf<TcpStream>`.
            let socket_writer = rx.fold(writer, |writer, msg| {
                let amt = io::write_all(writer, msg.into_bytes());
                let amt = amt.map(|(writer, _)| writer);
                amt
            });

            (socket_reader, socket_writer)
        });

        // Now that we've got futures representing each half of the socket, join
        // them together and then spawn off the result. Here we use the `select`
        // combinator to wait for either half to be done to tear down the other.
        let connections = connections.clone();
        let addr = addr;
        handle.spawn(pair.and_then(|(reader, writer)| {
            let reader = reader.map(|_| ());
            let writer = writer.map(|_| ());

            reader.select(writer)
        }).then(move |_| {
            connections.borrow_mut().remove(&addr);
            println!("Connection {} closed.", addr);
            Ok(())
        }));

        Ok(())
    });

    // execute server
    core.run(srv).unwrap();
}

<|endoftext|>


<commit_before>extern crate image;
extern crate bspline;

use std::ops::{Mul, Add, Index, IndexMut};
use std::iter;

#[derive(Copy, Clone, Debug)]
struct Point {
    x: f32,
    y: f32,
}
impl Point {
    fn new(x: f32, y: f32) -> Point {
        Point { x: x, y: y }
    }
}
impl Mul<f32> for Point {
    type Output = Point;
    fn mul(self, rhs: f32) -> Point {
        Point { x: self.x * rhs, y: self.y * rhs }
    }
}
impl Add for Point {
    type Output = Point;
    fn add(self, rhs: Point) -> Point {
        Point { x: self.x + rhs.x, y: self.y + rhs.y }
    }
}

/// Clamp `x` to be between `min` and `max`
pub fn clamp<T: PartialOrd>(x: T, min: T, max: T) -> T {
    if x < min { min } else if x > max { max } else { x }
}

#[derive(Debug, Copy, Clone)]
pub struct Colorf {
    pub r: f32,
    pub g: f32,
    pub b: f32,
}

impl Colorf {
    /// Create an RGB color
    pub fn new(r: f32, g: f32, b: f32) -> Colorf {
        Colorf { r: r, g: g, b: b }
    }
    pub fn broadcast(x: f32) -> Colorf {
        Colorf { r: x, g: x, b: x }
    }
    /// Clamp the color values between [0, 1]
    pub fn clamp(&self) -> Colorf {
        Colorf { r: clamp(self.r, 0.0, 1.0),
                 g: clamp(self.g, 0.0, 1.0),
                 b: clamp(self.b, 0.0, 1.0) }
    }
    /// Convert the linear RGB color to sRGB
    pub fn to_srgb(&self) -> Colorf {
        let a = 0.055f32;
        let b = 1f32 / 2.4;
        let mut srgb = Colorf::broadcast(0.0);
        for i in 0..3 {
            if self[i] <= 0.0031308 {
                srgb[i] = 12.92 * self[i];
            } else {
                srgb[i] = (1.0 + a) * f32::powf(self[i], b) - a;
            }
        }
        srgb
    }
}
impl Add for Colorf {
    type Output = Colorf;
    /// Add two colors together
    fn add(self, rhs: Colorf) -> Colorf {
        Colorf { r: self.r + rhs.r, g: self.g + rhs.g, b: self.b + rhs.b }
    }
}
impl Mul<f32> for Colorf {
    type Output = Colorf;
    /// Scale the color by the float
    fn mul(self, rhs: f32) -> Colorf {
        Colorf { r: self.r * rhs, g: self.g * rhs, b: self.b * rhs }
    }
}
impl Index<usize> for Colorf {
    type Output = f32;
    /// Access the channels by index
    ///
    /// - 0 = r
    /// - 1 = g
    /// - 2 = b
    fn index(&self, i: usize) -> &f32 {
        match i {
            0 => &self.r,
            1 => &self.g,
            2 => &self.b,
            _ => panic!("Invalid index into color"),
        }
    }
}
impl IndexMut<usize> for Colorf {
    /// Access the channels by index
    ///
    /// - 0 = r
    /// - 1 = g
    /// - 2 = b
    fn index_mut(&mut self, i: usize) -> &mut f32 {
        match i {
            0 => &mut self.r,
            1 => &mut self.g,
            2 => &mut self.b,
            _ => panic!("Invalid index into color"),
        }
    }
}

/// Evaluate the B-spline and plot it to the image buffer passed. The colors and points splines
/// should have the same t range.
fn plot_2d(spline: &bspline::BSpline<Point>, colors: &bspline::BSpline<Colorf>, plot: &mut [u8],
           plot_dim: (usize, usize), scale: (f32, f32), offset: (f32, f32), t_range: (f32, f32),
           show_control_pts: bool) {
    let step_size = 0.001;
    let steps = ((t_range.1 - t_range.0) / step_size) as usize;
    for s in 0..steps {
        let t = step_size * s as f32 + t_range.0;
        let pt = spline.point(t);
        let color = colors.point(t).to_srgb();
        let ix = ((pt.x + offset.0) * scale.0) as isize;
        let iy = ((pt.y + offset.1) * scale.1) as isize;
        for y in iy - 4..iy + 4 {
            for x in ix - 4..ix + 4 {
                if y >= 0 && y < plot_dim.1 as isize && x >= 0 && x < plot_dim.0 as isize {
                    let px = (plot_dim.1 - 1 - y as usize) * plot_dim.0 * 3 + x as usize * 3;
                    for i in 0..3 {
                        plot[px + i] = (color[i] * 255.0) as u8;
                    }
                }
            }
        }
    }
    // Draw the control points
    if show_control_pts {
        for pt in spline.control_points() {
            let ix = ((pt.x + offset.0) * scale.0) as isize;
            let iy = ((pt.y + offset.1) * scale.1) as isize;
            // Plot a black marker for each control point
            for y in iy - 3..iy + 3 {
                for x in ix - 3..ix + 3 {
                    if y >= 0 && y < plot_dim.1 as isize && x >= 0 && x < plot_dim.0 as isize {
                        let px = (plot_dim.1 - 1 - y as usize) * plot_dim.0 * 3 + x as usize * 3;
                        plot[px] = 0;
                        plot[px + 1] = 0;
                        plot[px + 2] = 0;
                    }
                }
            }
        }
    }
}

/// Plot the text 'bspline' to create the logo for the library
fn main() {
    let points = vec![// Draw the b
                      Point::new(-4.0, 4.0), Point::new(-4.0, -1.0), Point::new(-4.0, -1.0),
                      Point::new(-2.0, 0.0), Point::new(-4.0, 1.35), Point::new(-4.0, 1.35),
                      // Draw the s
                      Point::new(-1.0, 1.5), Point::new(-1.0, 1.5), Point::new(-2.8, 1.0),
                      Point::new(-0.5, 0.0), Point::new(-2.5, -0.5), Point::new(-2.5, -0.5),
                      // Draw the p
                      Point::new(0.0, -1.0), Point::new(0.0, 1.8), Point::new(0.0, 1.8),
                      Point::new(0.0, 1.8), Point::new(-0.2, -1.8), Point::new(-0.2, -1.8),
                      Point::new(-0.2, -1.8), Point::new(0.25, 2.5), Point::new(1.5, 1.2),
                      Point::new(0.0, -0.5), Point::new(0.0, -0.5), Point::new(1.0, -0.3),
                      Point::new(1.0, -0.3), Point::new(2.5, 1.5),
                      // Draw the l
                      Point::new(2.0, 3.0), Point::new(2.0, 3.0), Point::new(1.5, 1.5),
                      Point::new(2.5, -0.5), Point::new(2.5, -0.5),
                      // Draw the i
                      Point::new(2.8, 1.3), Point::new(2.8, 1.3), Point::new(2.8, 1.3),
                      // Draw the n
                      Point::new(3.1, -0.5), Point::new(3.1, -0.5), Point::new(3.4, 1.2),
                      Point::new(3.4, 1.2), Point::new(3.4, 1.2), Point::new(3.4, -0.5),
                      Point::new(3.4, -0.5), Point::new(3.4, -0.5), Point::new(4.0, 2.3),
                      Point::new(4.2, -0.5), Point::new(4.2, -0.5),
                      // Draw the e
                      Point::new(5.5, 0.8), Point::new(5.5, 0.8), Point::new(4.5, 1.3), Point::new(4.5, -0.3),
                      Point::new(6.5, -0.3)];
    let knots = vec![0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 4.0, 5.0, 6.0, 7.0, 7.0,
                     8.0, 9.0, 9.0, 9.0, 10.0, 10.0, 10.0, 11.0, 12.0, 13.0, 13.0,
                     14.0, 14.0, 15.0, 16.0, 16.0, 17.0, 18.0, 18.0, 19.0, 19.0, 19.0,
                     20.0, 20.0, 21.0, 21.0, 21.0, 22.0, 22.0, 22.0, 23.0, 24.0, 24.0,
                     25.0, 25.0, 26.0, 27.0, 28.0, 28.0, 28.0, 28.0];

    let colors = vec![Colorf::new(1.0, 0.0, 0.0), Colorf::new(1.0, 0.0, 0.0),
                      Colorf::new(0.0, 0.0, 1.0), Colorf::new(0.0, 1.0, 0.0),
                      Colorf::new(0.0, 1.0, 0.0)];
    let color_knots = vec![0.0, 0.0, 0.0, 14.0, 28.0, 28.0, 28.0];

    let t_start = knots[0];
    let t_end = knots[knots.len() - 1];

    let plot_dim = (720, 540);
    let scale = (plot_dim.0 as f32 / 14.0, plot_dim.1 as f32 / 10.0);
    let offset = (6.0, 5.0);

    let mut plot: Vec<_> = iter::repeat(255u8).take(plot_dim.0 * plot_dim.1 * 3).collect();

    let spline = bspline::BSpline::new(3, points, knots);
    let color_spline = bspline::BSpline::new(2, colors, color_knots);

    plot_2d(&spline, &color_spline, &mut plot[..], plot_dim, scale, offset, (t_start, t_end), false);
    match image::save_buffer("logo.png", &plot[..], plot_dim.0 as u32, plot_dim.1 as u32, image::RGB(8)) {
        Ok(_) => println!("B-spline logo saved to logo.png"),
        Err(e) => println!("Error saving logo.png,  {}", e),
    }
}

<commit_msg>Clean up color spline for the logo<commit_after>extern crate image;
extern crate bspline;

use std::ops::{Mul, Add, Index, IndexMut};
use std::iter;

#[derive(Copy, Clone, Debug)]
struct Point {
    x: f32,
    y: f32,
}
impl Point {
    fn new(x: f32, y: f32) -> Point {
        Point { x: x, y: y }
    }
}
impl Mul<f32> for Point {
    type Output = Point;
    fn mul(self, rhs: f32) -> Point {
        Point { x: self.x * rhs, y: self.y * rhs }
    }
}
impl Add for Point {
    type Output = Point;
    fn add(self, rhs: Point) -> Point {
        Point { x: self.x + rhs.x, y: self.y + rhs.y }
    }
}

/// Clamp `x` to be between `min` and `max`
pub fn clamp<T: PartialOrd>(x: T, min: T, max: T) -> T {
    if x < min { min } else if x > max { max } else { x }
}

#[derive(Debug, Copy, Clone)]
pub struct Colorf {
    pub r: f32,
    pub g: f32,
    pub b: f32,
}

impl Colorf {
    /// Create an RGB color
    pub fn new(r: f32, g: f32, b: f32) -> Colorf {
        Colorf { r: r, g: g, b: b }
    }
    pub fn broadcast(x: f32) -> Colorf {
        Colorf { r: x, g: x, b: x }
    }
    /// Clamp the color values between [0, 1]
    pub fn clamp(&self) -> Colorf {
        Colorf { r: clamp(self.r, 0.0, 1.0),
                 g: clamp(self.g, 0.0, 1.0),
                 b: clamp(self.b, 0.0, 1.0) }
    }
    /// Convert the linear RGB color to sRGB
    pub fn to_srgb(&self) -> Colorf {
        let a = 0.055f32;
        let b = 1f32 / 2.4;
        let mut srgb = Colorf::broadcast(0.0);
        for i in 0..3 {
            if self[i] <= 0.0031308 {
                srgb[i] = 12.92 * self[i];
            } else {
                srgb[i] = (1.0 + a) * f32::powf(self[i], b) - a;
            }
        }
        srgb
    }
}
impl Add for Colorf {
    type Output = Colorf;
    /// Add two colors together
    fn add(self, rhs: Colorf) -> Colorf {
        Colorf { r: self.r + rhs.r, g: self.g + rhs.g, b: self.b + rhs.b }
    }
}
impl Mul<f32> for Colorf {
    type Output = Colorf;
    /// Scale the color by the float
    fn mul(self, rhs: f32) -> Colorf {
        Colorf { r: self.r * rhs, g: self.g * rhs, b: self.b * rhs }
    }
}
impl Index<usize> for Colorf {
    type Output = f32;
    /// Access the channels by index
    ///
    /// - 0 = r
    /// - 1 = g
    /// - 2 = b
    fn index(&self, i: usize) -> &f32 {
        match i {
            0 => &self.r,
            1 => &self.g,
            2 => &self.b,
            _ => panic!("Invalid index into color"),
        }
    }
}
impl IndexMut<usize> for Colorf {
    /// Access the channels by index
    ///
    /// - 0 = r
    /// - 1 = g
    /// - 2 = b
    fn index_mut(&mut self, i: usize) -> &mut f32 {
        match i {
            0 => &mut self.r,
            1 => &mut self.g,
            2 => &mut self.b,
            _ => panic!("Invalid index into color"),
        }
    }
}

/// Evaluate the B-spline and plot it to the image buffer passed. The colors and points splines
/// should have the same t range.
fn plot_2d(spline: &bspline::BSpline<Point>, colors: &bspline::BSpline<Colorf>, plot: &mut [u8],
           plot_dim: (usize, usize), scale: (f32, f32), offset: (f32, f32), t_range: (f32, f32),
           show_control_pts: bool) {
    let step_size = 0.001;
    let steps = ((t_range.1 - t_range.0) / step_size) as usize;
    for s in 0..steps {
        let t = step_size * s as f32 + t_range.0;
        let pt = spline.point(t);
        let color = colors.point(t).to_srgb();
        let ix = ((pt.x + offset.0) * scale.0) as isize;
        let iy = ((pt.y + offset.1) * scale.1) as isize;
        for y in iy - 4..iy + 4 {
            for x in ix - 4..ix + 4 {
                if y >= 0 && y < plot_dim.1 as isize && x >= 0 && x < plot_dim.0 as isize {
                    let px = (plot_dim.1 - 1 - y as usize) * plot_dim.0 * 3 + x as usize * 3;
                    for i in 0..3 {
                        plot[px + i] = (color[i] * 255.0) as u8;
                    }
                }
            }
        }
    }
    // Draw the control points
    if show_control_pts {
        for pt in spline.control_points() {
            let ix = ((pt.x + offset.0) * scale.0) as isize;
            let iy = ((pt.y + offset.1) * scale.1) as isize;
            // Plot a black marker for each control point
            for y in iy - 3..iy + 3 {
                for x in ix - 3..ix + 3 {
                    if y >= 0 && y < plot_dim.1 as isize && x >= 0 && x < plot_dim.0 as isize {
                        let px = (plot_dim.1 - 1 - y as usize) * plot_dim.0 * 3 + x as usize * 3;
                        plot[px] = 0;
                        plot[px + 1] = 0;
                        plot[px + 2] = 0;
                    }
                }
            }
        }
    }
}

/// Plot the text 'bspline' to create the logo for the library
fn main() {
    let points = vec![// Draw the b
                      Point::new(-4.0, 4.0), Point::new(-4.0, -1.0), Point::new(-4.0, -1.0),
                      Point::new(-2.0, 0.0), Point::new(-4.0, 1.35), Point::new(-4.0, 1.35),
                      // Draw the s
                      Point::new(-1.0, 1.5), Point::new(-1.0, 1.5), Point::new(-2.8, 1.0),
                      Point::new(-0.5, 0.0), Point::new(-2.5, -0.5), Point::new(-2.5, -0.5),
                      // Draw the p
                      Point::new(0.0, -1.0), Point::new(0.0, 1.8), Point::new(0.0, 1.8),
                      Point::new(0.0, 1.8), Point::new(-0.2, -1.8), Point::new(-0.2, -1.8),
                      Point::new(-0.2, -1.8), Point::new(0.25, 2.5), Point::new(1.5, 1.2),
                      Point::new(0.0, -0.5), Point::new(0.0, -0.5), Point::new(1.0, -0.3),
                      Point::new(1.0, -0.3), Point::new(2.5, 1.5),
                      // Draw the l
                      Point::new(2.0, 3.0), Point::new(2.0, 3.0), Point::new(1.5, 1.5),
                      Point::new(2.5, -0.5), Point::new(2.5, -0.5),
                      // Draw the i
                      Point::new(2.8, 1.3), Point::new(2.8, 1.3), Point::new(2.8, 1.3),
                      // Draw the n
                      Point::new(3.1, -0.5), Point::new(3.1, -0.5), Point::new(3.4, 1.2),
                      Point::new(3.4, 1.2), Point::new(3.4, 1.2), Point::new(3.4, -0.5),
                      Point::new(3.4, -0.5), Point::new(3.4, -0.5), Point::new(4.0, 2.3),
                      Point::new(4.2, -0.5), Point::new(4.2, -0.5),
                      // Draw the e
                      Point::new(5.5, 0.8), Point::new(5.5, 0.8), Point::new(4.5, 1.3), Point::new(4.5, -0.3),
                      Point::new(6.5, -0.3)];
    let knots = vec![0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 4.0, 5.0, 6.0, 7.0, 7.0,
                     8.0, 9.0, 9.0, 9.0, 10.0, 10.0, 10.0, 11.0, 12.0, 13.0, 13.0,
                     14.0, 14.0, 15.0, 16.0, 16.0, 17.0, 18.0, 18.0, 19.0, 19.0, 19.0,
                     20.0, 20.0, 21.0, 21.0, 21.0, 22.0, 22.0, 22.0, 23.0, 24.0, 24.0,
                     25.0, 25.0, 26.0, 27.0, 28.0, 28.0, 28.0, 28.0];

    let colors = vec![Colorf::new(1.0, 0.0, 0.0), Colorf::new(0.0, 0.0, 1.0), Colorf::new(0.0, 1.0, 0.0)];
    let color_knots = vec![0.0, 0.0, 0.0, 28.0, 28.0, 28.0];

    let t_start = knots[3];
    let t_end = knots[knots.len() - 1 - 3];

    let plot_dim = (720, 540);
    let scale = (plot_dim.0 as f32 / 14.0, plot_dim.1 as f32 / 10.0);
    let offset = (6.0, 4.5);

    let mut plot: Vec<_> = iter::repeat(255u8).take(plot_dim.0 * plot_dim.1 * 3).collect();

    let spline = bspline::BSpline::new(3, points, knots);
    let color_spline = bspline::BSpline::new(2, colors, color_knots);

    plot_2d(&spline, &color_spline, &mut plot[..], plot_dim, scale, offset, (t_start, t_end), false);
    match image::save_buffer("logo.png", &plot[..], plot_dim.0 as u32, plot_dim.1 as u32, image::RGB(8)) {
        Ok(_) => println!("B-spline logo saved to logo.png"),
        Err(e) => println!("Error saving logo.png,  {}", e),
    }
}

<|endoftext|>


<commit_before>extern crate image;
extern crate bspline;

use std::ops::{Mul, Add, Index, IndexMut};
use std::iter;

#[derive(Copy, Clone, Debug)]
struct Point {
    x: f32,
    y: f32,
}
impl Point {
    fn new(x: f32, y: f32) -> Point {
        Point { x: x, y: y }
    }
}
impl Mul<f32> for Point {
    type Output = Point;
    fn mul(self, rhs: f32) -> Point {
        Point { x: self.x * rhs, y: self.y * rhs }
    }
}
impl Add for Point {
    type Output = Point;
    fn add(self, rhs: Point) -> Point {
        Point { x: self.x + rhs.x, y: self.y + rhs.y }
    }
}

/// Clamp `x` to be between `min` and `max`
pub fn clamp<T: PartialOrd>(x: T, min: T, max: T) -> T {
    if x < min { min } else if x > max { max } else { x }
}

#[derive(Debug, Copy, Clone)]
pub struct Colorf {
    pub r: f32,
    pub g: f32,
    pub b: f32,
}

impl Colorf {
    /// Create an RGB color
    pub fn new(r: f32, g: f32, b: f32) -> Colorf {
        Colorf { r: r, g: g, b: b }
    }
    pub fn broadcast(x: f32) -> Colorf {
        Colorf { r: x, g: x, b: x }
    }
    /// Clamp the color values between [0, 1]
    pub fn clamp(&self) -> Colorf {
        Colorf { r: clamp(self.r, 0.0, 1.0),
                 g: clamp(self.g, 0.0, 1.0),
                 b: clamp(self.b, 0.0, 1.0) }
    }
    /// Convert the linear RGB color to sRGB
    pub fn to_srgb(&self) -> Colorf {
        let a = 0.055f32;
        let b = 1f32 / 2.4;
        let mut srgb = Colorf::broadcast(0.0);
        for i in 0..3 {
            if self[i] <= 0.0031308 {
                srgb[i] = 12.92 * self[i];
            } else {
                srgb[i] = (1.0 + a) * f32::powf(self[i], b) - a;
            }
        }
        srgb
    }
}
impl Add for Colorf {
    type Output = Colorf;
    /// Add two colors together
    fn add(self, rhs: Colorf) -> Colorf {
        Colorf { r: self.r + rhs.r, g: self.g + rhs.g, b: self.b + rhs.b }
    }
}
impl Mul<f32> for Colorf {
    type Output = Colorf;
    /// Scale the color by the float
    fn mul(self, rhs: f32) -> Colorf {
        Colorf { r: self.r * rhs, g: self.g * rhs, b: self.b * rhs }
    }
}
impl Index<usize> for Colorf {
    type Output = f32;
    /// Access the channels by index
    ///
    /// - 0 = r
    /// - 1 = g
    /// - 2 = b
    fn index(&self, i: usize) -> &f32 {
        match i {
            0 => &self.r,
            1 => &self.g,
            2 => &self.b,
            _ => panic!("Invalid index into color"),
        }
    }
}
impl IndexMut<usize> for Colorf {
    /// Access the channels by index
    ///
    /// - 0 = r
    /// - 1 = g
    /// - 2 = b
    fn index_mut(&mut self, i: usize) -> &mut f32 {
        match i {
            0 => &mut self.r,
            1 => &mut self.g,
            2 => &mut self.b,
            _ => panic!("Invalid index into color"),
        }
    }
}

/// Evaluate the B-spline and plot it to the image buffer passed. The colors and points splines
/// should have the same t range.
fn plot_2d(spline: &bspline::BSpline<Point>, colors: &bspline::BSpline<Colorf>, plot: &mut [u8],
           plot_dim: (usize, usize), scale: (f32, f32), offset: (f32, f32), t_range: (f32, f32)) {
    let step_size = 0.001;
    let steps = ((t_range.1 - t_range.0) / step_size) as usize;
    for s in 0..steps {
        let t = step_size * s as f32 + t_range.0;
        let pt = spline.point(t);
        let color = colors.point(t).to_srgb();
        let ix = ((pt.x + offset.0) * scale.0) as isize;
        let iy = ((pt.y + offset.1) * scale.1) as isize;
        for y in iy - 1..iy + 1 {
            for x in ix - 1..ix + 1 {
                if y >= 0 && y < plot_dim.1 as isize && x >= 0 && x < plot_dim.0 as isize {
                    let px = (plot_dim.1 - 1 - y as usize) * plot_dim.0 * 3 + x as usize * 3;
                    for i in 0..3 {
                        plot[px + i] = (color[i] * 255.0) as u8;
                    }
                }
            }
        }
    }
    // Draw the control points
    for pt in spline.control_points() {
        let ix = ((pt.x + offset.0) * scale.0) as isize;
        let iy = ((pt.y + offset.1) * scale.1) as isize;
        // Plot a 4x4 red marker for each control point
        for y in iy - 2..iy + 2 {
            for x in ix - 2..ix + 2 {
                if y >= 0 && y < plot_dim.1 as isize && x >= 0 && x < plot_dim.0 as isize {
                    let px = (plot_dim.1 - 1 - y as usize) * plot_dim.0 * 3 + x as usize * 3;
                    plot[px] = 0;
                    plot[px + 1] = 0;
                    plot[px + 2] = 0;
                }
            }
        }
    }
}

/// Plot the text 'bspline' to create the logo for the library
fn main() {
    let points = vec![// Draw the b
                      Point::new(-4.0, 4.0), Point::new(-4.0, -1.0), Point::new(-4.0, -1.0),
                      Point::new(-2.0, 0.0), Point::new(-4.0, 1.35), Point::new(-4.0, 1.35),
                      // Draw the s
                      Point::new(-1.0, 1.5), Point::new(-1.0, 1.5), Point::new(-2.8, 1.0),
                      Point::new(-0.5, 0.0), Point::new(-2.5, -0.5), Point::new(-2.5, -0.5),
                      // Draw the p
                      Point::new(0.0, -1.0), Point::new(0.0, 1.8), Point::new(0.0, 1.8),
                      Point::new(0.0, 1.8), Point::new(-0.2, -1.8), Point::new(-0.2, -1.8),
                      Point::new(-0.2, -1.8), Point::new(0.25, 2.5), Point::new(1.5, 1.2),
                      Point::new(0.0, -0.5), Point::new(0.0, -0.5), Point::new(1.0, -0.3),
                      Point::new(1.0, -0.3), Point::new(2.5, 1.5),
                      // Draw the l
                      Point::new(2.0, 3.0), Point::new(2.0, 3.0), Point::new(1.5, 1.5),
                      Point::new(2.5, -0.5), Point::new(2.5, -0.5),
                      // Draw the i
                      Point::new(2.8, 1.3), Point::new(2.8, 1.3), Point::new(2.8, 1.3),
                      // Draw the n
                      Point::new(3.1, -0.5), Point::new(3.1, -0.5), Point::new(3.4, 1.2),
                      Point::new(3.4, 1.2), Point::new(3.4, 1.2), Point::new(3.4, -0.5),
                      Point::new(3.4, -0.5), Point::new(3.4, -0.5), Point::new(4.0, 2.3),
                      Point::new(4.2, -0.5), Point::new(4.2, -0.5),
                      // Draw the e
                      Point::new(5.5, 0.8), Point::new(5.5, 0.8), Point::new(4.5, 1.3), Point::new(4.5, -0.3),
                      Point::new(6.5, -0.3)];
    let knots = vec![0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 4.0, 5.0, 6.0, 7.0, 7.0,
                     8.0, 9.0, 9.0, 9.0, 10.0, 10.0, 10.0, 11.0, 12.0, 13.0, 13.0,
                     14.0, 14.0, 15.0, 16.0, 16.0, 17.0, 18.0, 18.0, 19.0, 19.0, 19.0,
                     20.0, 20.0, 21.0, 21.0, 21.0, 22.0, 22.0, 22.0, 23.0, 24.0, 24.0,
                     25.0, 25.0, 26.0, 27.0, 28.0, 28.0, 28.0, 28.0];

    let colors = vec![Colorf::new(1.0, 0.0, 0.0), Colorf::new(1.0, 0.0, 0.0),
                      Colorf::new(0.0, 0.0, 1.0), Colorf::new(0.0, 1.0, 0.0),
                      Colorf::new(0.0, 1.0, 0.0)];
    let color_knots = vec![0.0, 0.0, 0.0, 14.0, 28.0, 28.0, 28.0];

    let t_start = knots[0];
    let t_end = knots[knots.len() - 1];

    let plot_dim = (720, 540);
    let scale = (plot_dim.0 as f32 / 14.0, plot_dim.1 as f32 / 10.0);
    let offset = (6.0, 5.0);

    let mut plot: Vec<_> = iter::repeat(255u8).take(plot_dim.0 * plot_dim.1 * 3).collect();

    println!("Plotting Cubic B-spline with:\n\tpoints = {:?}\n\tknots = {:?}",
             points, knots);
    println!("\tStarting at {}, ending at {}", t_start, t_end);
    let spline = bspline::BSpline::new(3, points, knots);
    let color_spline = bspline::BSpline::new(2, colors, color_knots);

    plot_2d(&spline, &color_spline, &mut plot[..], plot_dim, scale, offset, (t_start, t_end));
    match image::save_buffer("logo.png", &plot[..], plot_dim.0 as u32, plot_dim.1 as u32, image::RGB(8)) {
        Ok(_) => println!("B-spline logo saved to logo.png"),
        Err(e) => println!("Error saving logo.png,  {}", e),
    }
}

<commit_msg>Make control points optionally drawn<commit_after>extern crate image;
extern crate bspline;

use std::ops::{Mul, Add, Index, IndexMut};
use std::iter;

#[derive(Copy, Clone, Debug)]
struct Point {
    x: f32,
    y: f32,
}
impl Point {
    fn new(x: f32, y: f32) -> Point {
        Point { x: x, y: y }
    }
}
impl Mul<f32> for Point {
    type Output = Point;
    fn mul(self, rhs: f32) -> Point {
        Point { x: self.x * rhs, y: self.y * rhs }
    }
}
impl Add for Point {
    type Output = Point;
    fn add(self, rhs: Point) -> Point {
        Point { x: self.x + rhs.x, y: self.y + rhs.y }
    }
}

/// Clamp `x` to be between `min` and `max`
pub fn clamp<T: PartialOrd>(x: T, min: T, max: T) -> T {
    if x < min { min } else if x > max { max } else { x }
}

#[derive(Debug, Copy, Clone)]
pub struct Colorf {
    pub r: f32,
    pub g: f32,
    pub b: f32,
}

impl Colorf {
    /// Create an RGB color
    pub fn new(r: f32, g: f32, b: f32) -> Colorf {
        Colorf { r: r, g: g, b: b }
    }
    pub fn broadcast(x: f32) -> Colorf {
        Colorf { r: x, g: x, b: x }
    }
    /// Clamp the color values between [0, 1]
    pub fn clamp(&self) -> Colorf {
        Colorf { r: clamp(self.r, 0.0, 1.0),
                 g: clamp(self.g, 0.0, 1.0),
                 b: clamp(self.b, 0.0, 1.0) }
    }
    /// Convert the linear RGB color to sRGB
    pub fn to_srgb(&self) -> Colorf {
        let a = 0.055f32;
        let b = 1f32 / 2.4;
        let mut srgb = Colorf::broadcast(0.0);
        for i in 0..3 {
            if self[i] <= 0.0031308 {
                srgb[i] = 12.92 * self[i];
            } else {
                srgb[i] = (1.0 + a) * f32::powf(self[i], b) - a;
            }
        }
        srgb
    }
}
impl Add for Colorf {
    type Output = Colorf;
    /// Add two colors together
    fn add(self, rhs: Colorf) -> Colorf {
        Colorf { r: self.r + rhs.r, g: self.g + rhs.g, b: self.b + rhs.b }
    }
}
impl Mul<f32> for Colorf {
    type Output = Colorf;
    /// Scale the color by the float
    fn mul(self, rhs: f32) -> Colorf {
        Colorf { r: self.r * rhs, g: self.g * rhs, b: self.b * rhs }
    }
}
impl Index<usize> for Colorf {
    type Output = f32;
    /// Access the channels by index
    ///
    /// - 0 = r
    /// - 1 = g
    /// - 2 = b
    fn index(&self, i: usize) -> &f32 {
        match i {
            0 => &self.r,
            1 => &self.g,
            2 => &self.b,
            _ => panic!("Invalid index into color"),
        }
    }
}
impl IndexMut<usize> for Colorf {
    /// Access the channels by index
    ///
    /// - 0 = r
    /// - 1 = g
    /// - 2 = b
    fn index_mut(&mut self, i: usize) -> &mut f32 {
        match i {
            0 => &mut self.r,
            1 => &mut self.g,
            2 => &mut self.b,
            _ => panic!("Invalid index into color"),
        }
    }
}

/// Evaluate the B-spline and plot it to the image buffer passed. The colors and points splines
/// should have the same t range.
fn plot_2d(spline: &bspline::BSpline<Point>, colors: &bspline::BSpline<Colorf>, plot: &mut [u8],
           plot_dim: (usize, usize), scale: (f32, f32), offset: (f32, f32), t_range: (f32, f32),
           show_control_pts: bool) {
    let step_size = 0.001;
    let steps = ((t_range.1 - t_range.0) / step_size) as usize;
    for s in 0..steps {
        let t = step_size * s as f32 + t_range.0;
        let pt = spline.point(t);
        let color = colors.point(t).to_srgb();
        let ix = ((pt.x + offset.0) * scale.0) as isize;
        let iy = ((pt.y + offset.1) * scale.1) as isize;
        for y in iy - 1..iy + 1 {
            for x in ix - 1..ix + 1 {
                if y >= 0 && y < plot_dim.1 as isize && x >= 0 && x < plot_dim.0 as isize {
                    let px = (plot_dim.1 - 1 - y as usize) * plot_dim.0 * 3 + x as usize * 3;
                    for i in 0..3 {
                        plot[px + i] = (color[i] * 255.0) as u8;
                    }
                }
            }
        }
    }
    // Draw the control points
    if show_control_pts {
        for pt in spline.control_points() {
            let ix = ((pt.x + offset.0) * scale.0) as isize;
            let iy = ((pt.y + offset.1) * scale.1) as isize;
            // Plot a 4x4 red marker for each control point
            for y in iy - 2..iy + 2 {
                for x in ix - 2..ix + 2 {
                    if y >= 0 && y < plot_dim.1 as isize && x >= 0 && x < plot_dim.0 as isize {
                        let px = (plot_dim.1 - 1 - y as usize) * plot_dim.0 * 3 + x as usize * 3;
                        plot[px] = 0;
                        plot[px + 1] = 0;
                        plot[px + 2] = 0;
                    }
                }
            }
        }
    }
}

/// Plot the text 'bspline' to create the logo for the library
fn main() {
    let points = vec![// Draw the b
                      Point::new(-4.0, 4.0), Point::new(-4.0, -1.0), Point::new(-4.0, -1.0),
                      Point::new(-2.0, 0.0), Point::new(-4.0, 1.35), Point::new(-4.0, 1.35),
                      // Draw the s
                      Point::new(-1.0, 1.5), Point::new(-1.0, 1.5), Point::new(-2.8, 1.0),
                      Point::new(-0.5, 0.0), Point::new(-2.5, -0.5), Point::new(-2.5, -0.5),
                      // Draw the p
                      Point::new(0.0, -1.0), Point::new(0.0, 1.8), Point::new(0.0, 1.8),
                      Point::new(0.0, 1.8), Point::new(-0.2, -1.8), Point::new(-0.2, -1.8),
                      Point::new(-0.2, -1.8), Point::new(0.25, 2.5), Point::new(1.5, 1.2),
                      Point::new(0.0, -0.5), Point::new(0.0, -0.5), Point::new(1.0, -0.3),
                      Point::new(1.0, -0.3), Point::new(2.5, 1.5),
                      // Draw the l
                      Point::new(2.0, 3.0), Point::new(2.0, 3.0), Point::new(1.5, 1.5),
                      Point::new(2.5, -0.5), Point::new(2.5, -0.5),
                      // Draw the i
                      Point::new(2.8, 1.3), Point::new(2.8, 1.3), Point::new(2.8, 1.3),
                      // Draw the n
                      Point::new(3.1, -0.5), Point::new(3.1, -0.5), Point::new(3.4, 1.2),
                      Point::new(3.4, 1.2), Point::new(3.4, 1.2), Point::new(3.4, -0.5),
                      Point::new(3.4, -0.5), Point::new(3.4, -0.5), Point::new(4.0, 2.3),
                      Point::new(4.2, -0.5), Point::new(4.2, -0.5),
                      // Draw the e
                      Point::new(5.5, 0.8), Point::new(5.5, 0.8), Point::new(4.5, 1.3), Point::new(4.5, -0.3),
                      Point::new(6.5, -0.3)];
    let knots = vec![0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 4.0, 5.0, 6.0, 7.0, 7.0,
                     8.0, 9.0, 9.0, 9.0, 10.0, 10.0, 10.0, 11.0, 12.0, 13.0, 13.0,
                     14.0, 14.0, 15.0, 16.0, 16.0, 17.0, 18.0, 18.0, 19.0, 19.0, 19.0,
                     20.0, 20.0, 21.0, 21.0, 21.0, 22.0, 22.0, 22.0, 23.0, 24.0, 24.0,
                     25.0, 25.0, 26.0, 27.0, 28.0, 28.0, 28.0, 28.0];

    let colors = vec![Colorf::new(1.0, 0.0, 0.0), Colorf::new(1.0, 0.0, 0.0),
                      Colorf::new(0.0, 0.0, 1.0), Colorf::new(0.0, 1.0, 0.0),
                      Colorf::new(0.0, 1.0, 0.0)];
    let color_knots = vec![0.0, 0.0, 0.0, 14.0, 28.0, 28.0, 28.0];

    let t_start = knots[0];
    let t_end = knots[knots.len() - 1];

    let plot_dim = (720, 540);
    let scale = (plot_dim.0 as f32 / 14.0, plot_dim.1 as f32 / 10.0);
    let offset = (6.0, 5.0);

    let mut plot: Vec<_> = iter::repeat(255u8).take(plot_dim.0 * plot_dim.1 * 3).collect();

    let spline = bspline::BSpline::new(3, points, knots);
    let color_spline = bspline::BSpline::new(2, colors, color_knots);

    plot_2d(&spline, &color_spline, &mut plot[..], plot_dim, scale, offset, (t_start, t_end), false);
    match image::save_buffer("logo.png", &plot[..], plot_dim.0 as u32, plot_dim.1 as u32, image::RGB(8)) {
        Ok(_) => println!("B-spline logo saved to logo.png"),
        Err(e) => println!("Error saving logo.png,  {}", e),
    }
}

<|endoftext|>