<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/. */

// The task that handles all rendering/painting.

use azure::{AzFloat, AzGLContext};
use azure::azure_hl::{B8G8R8A8, DrawTarget};
use display_list::DisplayList;
use servo_msg::compositor_msg::{RenderListener, IdleRenderState, RenderingRenderState, LayerBuffer};
use servo_msg::compositor_msg::{LayerBufferSet, Epoch};
use servo_msg::constellation_msg::PipelineId;
use font_context::FontContext;
use geom::matrix2d::Matrix2D;
use geom::size::Size2D;
use geom::rect::Rect;
use opts::Opts;
use render_context::RenderContext;

use std::cell::Cell;
use std::comm::{Chan, Port, SharedChan};
use extra::arc::Arc;

use servo_util::time::{ProfilerChan, profile};
use servo_util::time;

use buffer_map::BufferMap;

pub struct RenderLayer<T> {
    display_list: Arc<DisplayList<T>>,
    size: Size2D<uint>
}

pub enum Msg<T> {
    RenderMsg(RenderLayer<T>),
    ReRenderMsg(~[BufferRequest], f32, Epoch),
    UnusedBufferMsg(~[~LayerBuffer]),
    PaintPermissionGranted,
    PaintPermissionRevoked,
    ExitMsg(Chan<()>),
}

/// A request from the compositor to the renderer for tiles that need to be (re)displayed.
#[deriving(Clone)]
pub struct BufferRequest {
    // The rect in pixels that will be drawn to the screen
    screen_rect: Rect<uint>,

    // The rect in page coordinates that this tile represents
    page_rect: Rect<f32>,
}

pub fn BufferRequest(screen_rect: Rect<uint>, page_rect: Rect<f32>) -> BufferRequest {
    BufferRequest {
        screen_rect: screen_rect,
        page_rect: page_rect,
    }
}

#[deriving(Clone)]
pub struct RenderChan<T> {
    chan: SharedChan<Msg<T>>,
}

impl<T> RenderChan<T> {
    pub fn new(chan: Chan<Msg<T>>) -> RenderChan<T> {
        RenderChan {
            chan: SharedChan::new(chan),
        }
    }
    pub fn send(&self, msg: Msg<T>) {
        self.chan.send(msg);
    }
}

struct RenderTask<C,T> {
    id: PipelineId,
    port: Port<Msg<T>>,
    compositor: C,
    font_ctx: @mut FontContext,
    opts: Opts,

    /// A channel to the profiler.
    profiler_chan: ProfilerChan,

    share_gl_context: AzGLContext,

    /// The layer to be rendered
    render_layer: Option<RenderLayer<T>>,
    /// Permission to send paint messages to the compositor
    paint_permission: bool,
    /// Cached copy of last layers rendered
    last_paint_msg: Option<~LayerBufferSet>,
    /// A counter for epoch messages
    epoch: Epoch,
    /// A data structure to store unused LayerBuffers
    buffer_map: BufferMap<~LayerBuffer>,
}

impl<C: RenderListener + Send,T:Send+Freeze> RenderTask<C,T> {
    pub fn create(id: PipelineId,
                  port: Port<Msg<T>>,
                  compositor: C,
                  opts: Opts,
                  profiler_chan: ProfilerChan) {
        let compositor = Cell::new(compositor);
        let opts = Cell::new(opts);
        let port = Cell::new(port);
        let profiler_chan = Cell::new(profiler_chan);

        do spawn {
            let compositor = compositor.take();
            let share_gl_context = compositor.get_gl_context();
            let opts = opts.take();
            let profiler_chan = profiler_chan.take();

            // FIXME: rust/#5967
            let mut render_task = RenderTask {
                id: id,
                port: port.take(),
                compositor: compositor,
                font_ctx: @mut FontContext::new(opts.render_backend.clone(),
                                                false,
                                                profiler_chan.clone()),
                opts: opts,
                profiler_chan: profiler_chan,
                share_gl_context: share_gl_context,
                render_layer: None,

                paint_permission: false,
                last_paint_msg: None,
                epoch: Epoch(0),
                buffer_map: BufferMap::new(10000000),
            };

            render_task.start();
        }
    }

    fn start(&mut self) {
        debug!("render_task: beginning rendering loop");

        loop {
            match self.port.recv() {
                RenderMsg(render_layer) => {
                    if self.paint_permission {
                        self.epoch.next();
                        self.compositor.set_layer_page_size(self.id, render_layer.size, self.epoch);
                    }
                    self.render_layer = Some(render_layer);
                }
                ReRenderMsg(tiles, scale, epoch) => {
                    if self.epoch == epoch {
                        self.render(tiles, scale);
                    } else {
                        debug!("renderer epoch mismatch: %? != %?", self.epoch, epoch);
                    }
                }
                UnusedBufferMsg(unused_buffers) => {
                    // move_rev_iter is more efficient
                    for buffer in unused_buffers.move_rev_iter() {
                        self.buffer_map.insert(buffer);
                    }
                }
                PaintPermissionGranted => {
                    self.paint_permission = true;
                    match self.render_layer {
                        Some(ref render_layer) => {
                            self.epoch.next();
                            self.compositor.set_layer_page_size(self.id, render_layer.size, self.epoch);
                        }
                        None => {}
                    }
                    // FIXME: This sends the last paint request, anticipating what
                    // the compositor will ask for. However, even if it sends the right
                    // tiles, the compositor still asks for them, and they will be
                    // re-rendered redundantly.
                    match self.last_paint_msg {
                        Some(ref layer_buffer_set) => {
                            self.compositor.paint(self.id, layer_buffer_set.clone(), self.epoch);
                        }
                        None => {} // Nothing to do
                    }
                }
                PaintPermissionRevoked => {
                    self.paint_permission = false;
                }
                ExitMsg(response_ch) => {
                    response_ch.send(());
                    break;
                }
            }
        }
    }

    fn render(&mut self, tiles: ~[BufferRequest], scale: f32) {
        let render_layer;
        match self.render_layer {
            Some(ref r_layer) => {
                render_layer = r_layer;
            }
            _ => return, // nothing to do
        }

        self.compositor.set_render_state(RenderingRenderState);
        do time::profile(time::RenderingCategory, self.profiler_chan.clone()) {

            // FIXME: Try not to create a new array here.
            let mut new_buffers = ~[];

            // Divide up the layer into tiles.
            do time::profile(time::RenderingPrepBuffCategory, self.profiler_chan.clone()) {
                for tile in tiles.iter() {
                    let width = tile.screen_rect.size.width;
                    let height = tile.screen_rect.size.height;

                    let buffer = match self.buffer_map.find(tile.screen_rect.size) {
                        Some(buffer) => {
                            let mut buffer = buffer;
                            buffer.rect = tile.page_rect;
                            buffer.screen_pos = tile.screen_rect;
                            buffer.resolution = scale;
                            buffer
                        }
                        None => ~LayerBuffer {
                            draw_target: DrawTarget::new_with_fbo(self.opts.render_backend,
                                                                  self.share_gl_context,
                                                                  Size2D(width as i32, height as i32),
                                                                  B8G8R8A8),
                            rect: tile.page_rect,
                            screen_pos: tile.screen_rect,
                            resolution: scale,
                            stride: (width * 4) as uint
                        }
                    };

                    {
                        // Build the render context.
                        let ctx = RenderContext {
                            canvas: &buffer,
                            font_ctx: self.font_ctx,
                            opts: &self.opts
                        };

                        // Apply the translation to render the tile we want.
                        let matrix: Matrix2D<AzFloat> = Matrix2D::identity();
                        let matrix = matrix.scale(scale as AzFloat, scale as AzFloat);
                        let matrix = matrix.translate(-(buffer.rect.origin.x) as AzFloat,
                                                      -(buffer.rect.origin.y) as AzFloat);

                        ctx.canvas.draw_target.set_transform(&matrix);

                        // Clear the buffer.
                        ctx.clear();

                        // Draw the display list.
                        do profile(time::RenderingDrawingCategory, self.profiler_chan.clone()) {
                            render_layer.display_list.get().draw_into_context(&ctx);
                            ctx.canvas.draw_target.flush();
                        }
                    }

                    new_buffers.push(buffer);

                }

            }

            let layer_buffer_set = ~LayerBufferSet {
                buffers: new_buffers,
            };

            debug!("render_task: returning surface");
            if self.paint_permission {
                self.compositor.paint(self.id, layer_buffer_set.clone(), self.epoch);
            }
            debug!("caching paint msg");
            self.last_paint_msg = Some(layer_buffer_set);
            self.compositor.set_render_state(IdleRenderState);
        }
    }
}

<commit_msg>Don't send invalid cached paint messages to compositor<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/. */

// The task that handles all rendering/painting.

use azure::{AzFloat, AzGLContext};
use azure::azure_hl::{B8G8R8A8, DrawTarget};
use display_list::DisplayList;
use servo_msg::compositor_msg::{RenderListener, IdleRenderState, RenderingRenderState, LayerBuffer};
use servo_msg::compositor_msg::{LayerBufferSet, Epoch};
use servo_msg::constellation_msg::PipelineId;
use font_context::FontContext;
use geom::matrix2d::Matrix2D;
use geom::size::Size2D;
use geom::rect::Rect;
use opts::Opts;
use render_context::RenderContext;

use std::cell::Cell;
use std::comm::{Chan, Port, SharedChan};
use extra::arc::Arc;

use servo_util::time::{ProfilerChan, profile};
use servo_util::time;

use buffer_map::BufferMap;

pub struct RenderLayer<T> {
    display_list: Arc<DisplayList<T>>,
    size: Size2D<uint>
}

pub enum Msg<T> {
    RenderMsg(RenderLayer<T>),
    ReRenderMsg(~[BufferRequest], f32, Epoch),
    UnusedBufferMsg(~[~LayerBuffer]),
    PaintPermissionGranted,
    PaintPermissionRevoked,
    ExitMsg(Chan<()>),
}

/// A request from the compositor to the renderer for tiles that need to be (re)displayed.
#[deriving(Clone)]
pub struct BufferRequest {
    // The rect in pixels that will be drawn to the screen
    screen_rect: Rect<uint>,

    // The rect in page coordinates that this tile represents
    page_rect: Rect<f32>,
}

pub fn BufferRequest(screen_rect: Rect<uint>, page_rect: Rect<f32>) -> BufferRequest {
    BufferRequest {
        screen_rect: screen_rect,
        page_rect: page_rect,
    }
}

#[deriving(Clone)]
pub struct RenderChan<T> {
    chan: SharedChan<Msg<T>>,
}

impl<T> RenderChan<T> {
    pub fn new(chan: Chan<Msg<T>>) -> RenderChan<T> {
        RenderChan {
            chan: SharedChan::new(chan),
        }
    }
    pub fn send(&self, msg: Msg<T>) {
        self.chan.send(msg);
    }
}

struct RenderTask<C,T> {
    id: PipelineId,
    port: Port<Msg<T>>,
    compositor: C,
    font_ctx: @mut FontContext,
    opts: Opts,

    /// A channel to the profiler.
    profiler_chan: ProfilerChan,

    share_gl_context: AzGLContext,

    /// The layer to be rendered
    render_layer: Option<RenderLayer<T>>,
    /// Permission to send paint messages to the compositor
    paint_permission: bool,
    /// Cached copy of last layers rendered
    last_paint_msg: Option<~LayerBufferSet>,
    /// A counter for epoch messages
    epoch: Epoch,
    /// A data structure to store unused LayerBuffers
    buffer_map: BufferMap<~LayerBuffer>,
}

impl<C: RenderListener + Send,T:Send+Freeze> RenderTask<C,T> {
    pub fn create(id: PipelineId,
                  port: Port<Msg<T>>,
                  compositor: C,
                  opts: Opts,
                  profiler_chan: ProfilerChan) {
        let compositor = Cell::new(compositor);
        let opts = Cell::new(opts);
        let port = Cell::new(port);
        let profiler_chan = Cell::new(profiler_chan);

        do spawn {
            let compositor = compositor.take();
            let share_gl_context = compositor.get_gl_context();
            let opts = opts.take();
            let profiler_chan = profiler_chan.take();

            // FIXME: rust/#5967
            let mut render_task = RenderTask {
                id: id,
                port: port.take(),
                compositor: compositor,
                font_ctx: @mut FontContext::new(opts.render_backend.clone(),
                                                false,
                                                profiler_chan.clone()),
                opts: opts,
                profiler_chan: profiler_chan,
                share_gl_context: share_gl_context,
                render_layer: None,

                paint_permission: false,
                last_paint_msg: None,
                epoch: Epoch(0),
                buffer_map: BufferMap::new(10000000),
            };

            render_task.start();
        }
    }

    fn start(&mut self) {
        debug!("render_task: beginning rendering loop");

        loop {
            match self.port.recv() {
                RenderMsg(render_layer) => {
                    if self.paint_permission {
                        self.epoch.next();
                        self.compositor.set_layer_page_size(self.id, render_layer.size, self.epoch);
                    }
                    self.render_layer = Some(render_layer);
                    self.last_paint_msg = None;
                }
                ReRenderMsg(tiles, scale, epoch) => {
                    if self.epoch == epoch {
                        self.render(tiles, scale);
                    } else {
                        debug!("renderer epoch mismatch: %? != %?", self.epoch, epoch);
                    }
                }
                UnusedBufferMsg(unused_buffers) => {
                    // move_rev_iter is more efficient
                    for buffer in unused_buffers.move_rev_iter() {
                        self.buffer_map.insert(buffer);
                    }
                }
                PaintPermissionGranted => {
                    self.paint_permission = true;
                    match self.render_layer {
                        Some(ref render_layer) => {
                            self.epoch.next();
                            self.compositor.set_layer_page_size(self.id, render_layer.size, self.epoch);
                        }
                        None => {}
                    }
                    // FIXME: This sends the last paint request, anticipating what
                    // the compositor will ask for. However, even if it sends the right
                    // tiles, the compositor still asks for them, and they will be
                    // re-rendered redundantly.
                    match self.last_paint_msg {
                        Some(ref layer_buffer_set) => {
                            self.compositor.paint(self.id, layer_buffer_set.clone(), self.epoch);
                        }
                        None => {} // Nothing to do
                    }
                }
                PaintPermissionRevoked => {
                    self.paint_permission = false;
                }
                ExitMsg(response_ch) => {
                    response_ch.send(());
                    break;
                }
            }
        }
    }

    fn render(&mut self, tiles: ~[BufferRequest], scale: f32) {
        let render_layer;
        match self.render_layer {
            Some(ref r_layer) => {
                render_layer = r_layer;
            }
            _ => return, // nothing to do
        }

        self.compositor.set_render_state(RenderingRenderState);
        do time::profile(time::RenderingCategory, self.profiler_chan.clone()) {

            // FIXME: Try not to create a new array here.
            let mut new_buffers = ~[];

            // Divide up the layer into tiles.
            do time::profile(time::RenderingPrepBuffCategory, self.profiler_chan.clone()) {
                for tile in tiles.iter() {
                    let width = tile.screen_rect.size.width;
                    let height = tile.screen_rect.size.height;

                    let buffer = match self.buffer_map.find(tile.screen_rect.size) {
                        Some(buffer) => {
                            let mut buffer = buffer;
                            buffer.rect = tile.page_rect;
                            buffer.screen_pos = tile.screen_rect;
                            buffer.resolution = scale;
                            buffer
                        }
                        None => ~LayerBuffer {
                            draw_target: DrawTarget::new_with_fbo(self.opts.render_backend,
                                                                  self.share_gl_context,
                                                                  Size2D(width as i32, height as i32),
                                                                  B8G8R8A8),
                            rect: tile.page_rect,
                            screen_pos: tile.screen_rect,
                            resolution: scale,
                            stride: (width * 4) as uint
                        }
                    };

                    {
                        // Build the render context.
                        let ctx = RenderContext {
                            canvas: &buffer,
                            font_ctx: self.font_ctx,
                            opts: &self.opts
                        };

                        // Apply the translation to render the tile we want.
                        let matrix: Matrix2D<AzFloat> = Matrix2D::identity();
                        let matrix = matrix.scale(scale as AzFloat, scale as AzFloat);
                        let matrix = matrix.translate(-(buffer.rect.origin.x) as AzFloat,
                                                      -(buffer.rect.origin.y) as AzFloat);

                        ctx.canvas.draw_target.set_transform(&matrix);

                        // Clear the buffer.
                        ctx.clear();

                        // Draw the display list.
                        do profile(time::RenderingDrawingCategory, self.profiler_chan.clone()) {
                            render_layer.display_list.get().draw_into_context(&ctx);
                            ctx.canvas.draw_target.flush();
                        }
                    }

                    new_buffers.push(buffer);

                }

            }

            let layer_buffer_set = ~LayerBufferSet {
                buffers: new_buffers,
            };

            debug!("render_task: returning surface");
            if self.paint_permission {
                self.compositor.paint(self.id, layer_buffer_set.clone(), self.epoch);
            }
            debug!("caching paint msg");
            self.last_paint_msg = Some(layer_buffer_set);
            self.compositor.set_render_state(IdleRenderState);
        }
    }
}

<|endoftext|>


<commit_before>extern crate cursive;

use cursive::{Cursive, Printer};
use cursive::theme::{ColorStyle, Color};
use cursive::view::Boxable;
use cursive::views::Canvas;

fn main() {
    let mut siv = Cursive::new();

    siv.add_layer(Canvas::new(()).with_draw(draw).fixed_size((20, 10)));

    siv.add_global_callback('q', |s| s.quit());

    siv.run();
}

fn front_color(x: u8, y: u8, x_max: u8, y_max: u8) -> Color {
    Color::Rgb(x * (255 / x_max),
               y * (255 / y_max),
               (x + 2 * y) * (255 / (x_max + 2 * y_max)))
}

fn back_color(x: u8, y: u8, x_max: u8, y_max: u8) -> Color {

    Color::Rgb(128 + (2 * y_max + x - 2 * y) * (128 / (x_max + 2 * y_max)),
               255 - y * (255 / y_max),
               255 - x * (255 / x_max))
}

fn draw(p: &Printer, _: &()) {
    let x_max = p.size.x as u8;
    let y_max = p.size.y as u8;

    for x in 0..x_max {
        for y in 0..y_max {
            let style = ColorStyle::Custom {
                front: front_color(x, y, x_max, y_max),
                back: back_color(x, y, x_max, y_max),
            };

            p.with_color(style, |printer| { printer.print((x, y), "+"); });
        }
    }
}
<commit_msg>Fix colors example<commit_after>extern crate cursive;

use cursive::{Cursive, Printer};
use cursive::theme::{ColorStyle, Color};
use cursive::view::Boxable;
use cursive::views::Canvas;

fn main() {
    let mut siv = Cursive::new();

    siv.add_layer(Canvas::new(()).with_draw(draw).fixed_size((20, 10)));

    siv.add_global_callback('q', |s| s.quit());

    siv.run();
}

fn front_color(x: u8, y: u8, x_max: u8, y_max: u8) -> Color {
    Color::Rgb(x * (255 / x_max),
               y * (255 / y_max),
               (x + 2 * y) * (255 / (x_max + 2 * y_max)))
}

fn back_color(x: u8, y: u8, x_max: u8, y_max: u8) -> Color {

    Color::Rgb(128 + (2 * y_max + x - 2 * y) * (128 / (x_max + 2 * y_max)),
               255 - y * (255 / y_max),
               255 - x * (255 / x_max))
}

fn draw(_: &(), p: &Printer) {
    let x_max = p.size.x as u8;
    let y_max = p.size.y as u8;

    for x in 0..x_max {
        for y in 0..y_max {
            let style = ColorStyle::Custom {
                front: front_color(x, y, x_max, y_max),
                back: back_color(x, y, x_max, y_max),
            };

            p.with_color(style, |printer| { printer.print((x, y), "+"); });
        }
    }
}
<|endoftext|>


<commit_before>extern crate getopts;
extern crate typedopts;
extern crate serialize;

use std::os;
use getopts::{reqopt,optopt,optflag,getopts,OptGroup};
use typedopts::{DecodeResult,UnimplementedDecoder,MissingField,ExpectedType};

#[deriving(Decodable)]
enum Color {
  red,
  blue
}

#[deriving(Decodable)]
struct TestStruct1  {
  data_int: u8,
  data_str: ~str,
  color: Color,
  maybe: Option<int>
}

fn print_usage(program: &str, _opts: &[OptGroup]) {
    println!("Usage: {} [options]", program);
    println!("-o\t\tOutput");
    println!("-d --data_int\tNumber");
    println!("-h --help\tUsage");
}

fn main() {
  let args = os::args();

  let program = args[0].clone();

  let opts = ~[
    optopt("o", "", "set output file name", "NAME"),
    reqopt("d", "data_int", "number", "NB"),
    reqopt("s", "data_str", "str", "NB"),
    reqopt("c", "color", "scolored", ""),
    optopt("m", "maybe", "maybe int", ""),
    optflag("h", "help", "print this help menu")
  ];
  let matches = match getopts(args.tail(), opts) {
    Ok(m) => { m }
    Err(f) => { fail!(f.to_err_msg()) }
  };

  if matches.opt_present("h") {
    print_usage(program, opts);
    return;
  }

  let result: typedopts::DecodeResult<TestStruct1> = typedopts::decode(matches);

  match result {
    Ok(decoded) => {
      println!("got data: s -> {} n -> {}", decoded.data_str, decoded.data_int);
      match decoded.color {
        red  => println!("red"),
        blue => println!("blue")
      }

      match decoded.maybe {
        None    => println!("maybe is none"),
        Some(i) => println!("maybe is {}", i)
      }
    },
    Err(UnimplementedDecoder) => println!("this function is not implemented"),
    Err(MissingField(ref s))  => println!("the required field '{}' is not present", s),
    Err(ExpectedType(ref field, ref expected, ref value)) => {
      println!("Expected type '{}' for field '{}' but got value '{}'", expected, field, value)
    }
  }
}
<commit_msg>cosmetics on the examples<commit_after>extern crate getopts;
extern crate typedopts;
extern crate serialize;

use std::os;
use getopts::{reqopt,optopt,optflag,getopts,OptGroup};
use typedopts::{DecodeResult,UnimplementedDecoder,MissingField,ExpectedType};

#[deriving(Decodable)]
enum Color {
  red,
  blue
}

#[deriving(Decodable)]
struct TestStruct1  {
  data_int: u8,
  data_str: ~str,
  color: Color,
  maybe: Option<int>
}

fn print_usage(program: &str, _opts: &[OptGroup]) {
    println!("Usage: {} [options]", program);
    println!("-o\t\tOutput");
    println!("-d --data_int\tNumber");
    println!("-h --help\tUsage");
}

fn main() {
  let args = os::args();

  let program = args[0].clone();

  let opts = ~[
    optopt("o", "", "set output file name", "NAME"),
    reqopt("d", "data_int", "number", "NB"),
    reqopt("s", "data_str", "str", "NB"),
    reqopt("c", "color", "scolored", ""),
    optopt("m", "maybe", "maybe int", ""),
    optflag("h", "help", "print this help menu")
  ];
  let matches = match getopts(args.tail(), opts) {
    Ok(m) => { m }
    Err(f) => { println!("{}", f.to_err_msg()); return }
  };

  if matches.opt_present("h") {
    print_usage(program, opts);
    return;
  }

  let result: typedopts::DecodeResult<TestStruct1> = typedopts::decode(matches);

  match result {
    Ok(decoded) => {
      println!("got data: s -> {} n -> {}", decoded.data_str, decoded.data_int);
      match decoded.color {
        red  => println!("red"),
        blue => println!("blue")
      }

      match decoded.maybe {
        None    => println!("maybe is none"),
        Some(i) => println!("maybe is {}", i)
      }
    },
    Err(UnimplementedDecoder) => println!("this function is not implemented"),
    Err(MissingField(ref s))  => println!("the required field '{}' is not present", s),
    Err(ExpectedType(ref field, ref expected, ref value)) => {
      println!("Expected type '{}' for field '{}' but got value '{}'", expected, field, value)
    }
  }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate glium;
extern crate rand;
#[macro_use]
extern crate slog;
extern crate slog_async;
extern crate slog_term;
#[macro_use(define_roles)]
extern crate smithay;
extern crate wayland_protocols;
extern crate wayland_server;

mod helpers;

use glium::Surface;

use helpers::GliumDrawer;
use slog::{Drain, Logger};

use smithay::backend::graphics::glium::IntoGlium;
use smithay::backend::input::InputBackend;
use smithay::backend::winit;
use smithay::compositor::{self, CompositorHandler, CompositorToken, SubsurfaceRole, TraversalAction};
use smithay::compositor::roles::Role;
use smithay::shell::{self, PopupConfigure, PopupSurface, ShellClient, ShellHandler, ShellSurfaceRole,
                     ToplevelConfigure, ToplevelSurface};
use smithay::shm::{ShmGlobal, ShmToken};

use wayland_protocols::unstable::xdg_shell::server::{zxdg_shell_v6, zxdg_toplevel_v6};

use wayland_server::{Client, EventLoopHandle};
use wayland_server::protocol::{wl_compositor, wl_output, wl_seat, wl_shell, wl_shm, wl_subcompositor,
                               wl_surface};

define_roles!(Roles => [ ShellSurface, ShellSurfaceRole ] );

struct SurfaceHandler {
    shm_token: ShmToken,
}

#[derive(Default)]
struct SurfaceData {
    buffer: Option<(Vec<u8>, (u32, u32))>,
    location: Option<(i32, i32)>,
}

impl compositor::Handler<SurfaceData, Roles> for SurfaceHandler {
    fn commit(&mut self, _evlh: &mut EventLoopHandle, _client: &Client, surface: &wl_surface::WlSurface,
              token: CompositorToken<SurfaceData, Roles, SurfaceHandler>) {
        // we retrieve the contents of the associated buffer and copy it
        token.with_surface_data(surface, |attributes| {
            match attributes.buffer.take() {
                Some(Some((buffer, (_x, _y)))) => {
                    // we ignore hotspot coordinates in this simple example
                    self.shm_token
                        .with_buffer_contents(&buffer, |slice, data| {
                            let offset = data.offset as usize;
                            let stride = data.stride as usize;
                            let width = data.width as usize;
                            let height = data.height as usize;
                            let mut new_vec = Vec::with_capacity(width * height * 4);
                            for i in 0..height {
                                new_vec.extend(
                                    &slice[(offset + i * stride)..(offset + i * stride + width * 4)],
                                );
                            }
                            attributes.user_data.buffer =
                                Some((new_vec, (data.width as u32, data.height as u32)));
                        })
                        .unwrap();
                }
                Some(None) => {
                    // erase the contents
                    attributes.user_data.buffer = None;
                }
                None => {}
            }
        });
    }
}

struct ShellSurfaceHandler {
    token: CompositorToken<SurfaceData, Roles, SurfaceHandler>,
}

impl ShellSurfaceHandler {
    fn new(token: CompositorToken<SurfaceData, Roles, SurfaceHandler>) -> ShellSurfaceHandler {
        ShellSurfaceHandler { token }
    }
}

impl shell::Handler<SurfaceData, Roles, SurfaceHandler, ()> for ShellSurfaceHandler {
    fn new_client(&mut self, _evlh: &mut EventLoopHandle, _client: ShellClient<()>) {}
    fn client_pong(&mut self, _evlh: &mut EventLoopHandle, _client: ShellClient<()>) {}
    fn new_toplevel(&mut self, _evlh: &mut EventLoopHandle,
                    surface: ToplevelSurface<SurfaceData, Roles, SurfaceHandler, ()>)
                    -> ToplevelConfigure {
        let wl_surface = surface.get_surface().unwrap();
        self.token.with_surface_data(wl_surface, |data| {
            // place the window at a random location in the [0;300]x[0;300] square
            use rand::distributions::{IndependentSample, Range};
            let range = Range::new(0, 300);
            let mut rng = rand::thread_rng();
            let x = range.ind_sample(&mut rng);
            let y = range.ind_sample(&mut rng);
            data.user_data.location = Some((x, y))
        });
        ToplevelConfigure {
            size: None,
            states: vec![],
            serial: 42,
        }
    }
    fn new_popup(&mut self, _evlh: &mut EventLoopHandle,
                 _surface: PopupSurface<SurfaceData, Roles, SurfaceHandler, ()>)
                 -> PopupConfigure {
        PopupConfigure {
            size: (10, 10),
            position: (10, 10),
            serial: 42,
        }
    }
    fn move_(&mut self, _evlh: &mut EventLoopHandle,
             _surface: ToplevelSurface<SurfaceData, Roles, SurfaceHandler, ()>, _seat: &wl_seat::WlSeat,
             _serial: u32) {
    }
    fn resize(&mut self, _evlh: &mut EventLoopHandle,
              _surface: ToplevelSurface<SurfaceData, Roles, SurfaceHandler, ()>, _seat: &wl_seat::WlSeat,
              _serial: u32, _edges: zxdg_toplevel_v6::ResizeEdge) {
    }
    fn grab(&mut self, _evlh: &mut EventLoopHandle,
            _surface: PopupSurface<SurfaceData, Roles, SurfaceHandler, ()>, _seat: &wl_seat::WlSeat,
            _serial: u32) {
    }
    fn change_display_state(&mut self, _evlh: &mut EventLoopHandle,
                            _surface: ToplevelSurface<SurfaceData, Roles, SurfaceHandler, ()>,
                            _maximized: Option<bool>, _minimized: Option<bool>, _fullscreen: Option<bool>,
                            _output: Option<&wl_output::WlOutput>)
                            -> ToplevelConfigure {
        ToplevelConfigure {
            size: None,
            states: vec![],
            serial: 42,
        }
    }
    fn show_window_menu(&mut self, _evlh: &mut EventLoopHandle,
                        _surface: ToplevelSurface<SurfaceData, Roles, SurfaceHandler, ()>,
                        _seat: &wl_seat::WlSeat, _serial: u32, _x: i32, _y: i32) {
    }
}

type MyCompositorHandler = CompositorHandler<SurfaceData, Roles, SurfaceHandler>;
type MyShellHandler = ShellHandler<SurfaceData, Roles, SurfaceHandler, ShellSurfaceHandler, ()>;

fn main() {
    // A logger facility, here we use the terminal for this example
    let log = Logger::root(
        slog_async::Async::default(slog_term::term_full().fuse()).fuse(),
        o!(),
    );

    // Initialize a simple backend for testing
    let (renderer, mut input) = winit::init(log.clone()).unwrap();

    let (mut display, mut event_loop) = wayland_server::create_display();

    /*
     * Initialize wl_shm global
     */
    // Insert the ShmGlobal as a handler to your event loop
    // Here, we specify tha the standard Argb8888 and Xrgb8888 is the only supported.
    let shm_handler_id = event_loop.add_handler_with_init(ShmGlobal::new(vec![], log.clone()));
    // Register this handler to advertise a wl_shm global of version 1
    event_loop.register_global::<wl_shm::WlShm, ShmGlobal>(shm_handler_id, 1);
    // retreive the token
    let shm_token = {
        let state = event_loop.state();
        state.get_handler::<ShmGlobal>(shm_handler_id).get_token()
    };

    /*
     * Initialize the compositor global
     */
    let compositor_handler_id = event_loop.add_handler_with_init(MyCompositorHandler::new(
        SurfaceHandler {
            shm_token: shm_token.clone(),
        },
        log.clone(),
    ));
    // register it to handle wl_compositor and wl_subcompositor
    event_loop.register_global::<wl_compositor::WlCompositor, MyCompositorHandler>(compositor_handler_id, 4);
    event_loop
        .register_global::<wl_subcompositor::WlSubcompositor, MyCompositorHandler>(compositor_handler_id, 1);
    // retrieve the tokens
    let compositor_token = {
        let state = event_loop.state();
        state
            .get_handler::<MyCompositorHandler>(compositor_handler_id)
            .get_token()
    };

    /*
     * Initialize the shell global
     */
    let shell_handler_id = event_loop.add_handler_with_init(MyShellHandler::new(
        ShellSurfaceHandler::new(compositor_token),
        compositor_token,
        log.clone(),
    ));
    event_loop.register_global::<wl_shell::WlShell, MyShellHandler>(shell_handler_id, 1);
    event_loop.register_global::<zxdg_shell_v6::ZxdgShellV6, MyShellHandler>(shell_handler_id, 1);

    /*
     * Initialize glium
     */
    let context = renderer.into_glium();

    let drawer = GliumDrawer::new(&context);

    /*
     * Add a listening socket:
     */
    let name = display.add_socket_auto().unwrap().into_string().unwrap();
    println!("Listening on socket: {}", name);

    loop {
        input.dispatch_new_events().unwrap();

        let mut frame = context.draw();
        frame.clear(None, Some((0.8, 0.8, 0.9, 1.0)), false, None, None);
        // redraw the frame, in a simple but inneficient way
        {
            let screen_dimensions = context.get_framebuffer_dimensions();
            let state = event_loop.state();
            for toplevel_surface in state
                .get_handler::<MyShellHandler>(shell_handler_id)
                .toplevel_surfaces()
            {
                if let Some(wl_surface) = toplevel_surface.get_surface() {
                    // this surface is a root of a subsurface tree that needs to be drawn
                    let initial_place = compositor_token
                        .with_surface_data(wl_surface, |data| data.user_data.location.unwrap_or((0, 0)));
                    compositor_token
                        .with_surface_tree(
                            wl_surface,
                            initial_place,
                            |_surface, attributes, role, &(mut x, mut y)| {
                                if let Some((ref contents, (w, h))) = attributes.user_data.buffer {
                                    // there is actually something to draw !
                                    if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
                                        x += subdata.x;
                                        y += subdata.y;
                                    }
                                    drawer.draw(&mut frame, contents, (w, h), (x, y), screen_dimensions);
                                    TraversalAction::DoChildren((x, y))
                                } else {
                                    // we are not display, so our children are neither
                                    TraversalAction::SkipChildren
                                }
                            },
                        )
                        .unwrap();
                }
            }
        }
        frame.finish().unwrap();

        event_loop.dispatch(Some(16)).unwrap();
        display.flush_clients();
    }
}
<commit_msg>Update example to have weston-terminal not crashing<commit_after>#[macro_use]
extern crate glium;
extern crate rand;
#[macro_use]
extern crate slog;
extern crate slog_async;
extern crate slog_term;
#[macro_use(define_roles)]
extern crate smithay;
extern crate wayland_protocols;
extern crate wayland_server;

mod helpers;

use glium::Surface;

use helpers::GliumDrawer;
use slog::{Drain, Logger};

use smithay::backend::graphics::glium::IntoGlium;
use smithay::backend::input::InputBackend;
use smithay::backend::winit;
use smithay::compositor::{self, CompositorHandler, CompositorToken, SubsurfaceRole, TraversalAction};
use smithay::compositor::roles::Role;
use smithay::shell::{self, PopupConfigure, PopupSurface, ShellClient, ShellHandler, ShellSurfaceRole,
                     ToplevelConfigure, ToplevelSurface};
use smithay::shm::{ShmGlobal, ShmToken};

use wayland_protocols::unstable::xdg_shell::server::{zxdg_shell_v6, zxdg_toplevel_v6};

use wayland_server::{Client, EventLoopHandle};
use wayland_server::protocol::{wl_callback, wl_compositor, wl_output, wl_seat, wl_shell, wl_shm,
                               wl_subcompositor, wl_surface};

define_roles!(Roles => [ ShellSurface, ShellSurfaceRole ] );

struct SurfaceHandler {
    shm_token: ShmToken,
}

#[derive(Default)]
struct SurfaceData {
    buffer: Option<(Vec<u8>, (u32, u32))>,
    location: Option<(i32, i32)>,
}

impl compositor::Handler<SurfaceData, Roles> for SurfaceHandler {
    fn commit(&mut self, _evlh: &mut EventLoopHandle, _client: &Client, surface: &wl_surface::WlSurface,
              token: CompositorToken<SurfaceData, Roles, SurfaceHandler>) {
        // we retrieve the contents of the associated buffer and copy it
        token.with_surface_data(surface, |attributes| {
            match attributes.buffer.take() {
                Some(Some((buffer, (_x, _y)))) => {
                    // we ignore hotspot coordinates in this simple example
                    self.shm_token
                        .with_buffer_contents(&buffer, |slice, data| {
                            let offset = data.offset as usize;
                            let stride = data.stride as usize;
                            let width = data.width as usize;
                            let height = data.height as usize;
                            let mut new_vec = Vec::with_capacity(width * height * 4);
                            for i in 0..height {
                                new_vec.extend(
                                    &slice[(offset + i * stride)..(offset + i * stride + width * 4)],
                                );
                            }
                            attributes.user_data.buffer =
                                Some((new_vec, (data.width as u32, data.height as u32)));
                        })
                        .unwrap();
                    buffer.release();
                }
                Some(None) => {
                    // erase the contents
                    attributes.user_data.buffer = None;
                }
                None => {}
            }
        });
    }

    fn frame(&mut self, _evlh: &mut EventLoopHandle, _client: &Client, surface: &wl_surface::WlSurface,
             callback: wl_callback::WlCallback, _token: CompositorToken<SurfaceData, Roles, SurfaceHandler>) {
        callback.done(0);
    }
}

struct ShellSurfaceHandler {
    token: CompositorToken<SurfaceData, Roles, SurfaceHandler>,
}

impl ShellSurfaceHandler {
    fn new(token: CompositorToken<SurfaceData, Roles, SurfaceHandler>) -> ShellSurfaceHandler {
        ShellSurfaceHandler { token }
    }
}

impl shell::Handler<SurfaceData, Roles, SurfaceHandler, ()> for ShellSurfaceHandler {
    fn new_client(&mut self, _evlh: &mut EventLoopHandle, _client: ShellClient<()>) {}
    fn client_pong(&mut self, _evlh: &mut EventLoopHandle, _client: ShellClient<()>) {}
    fn new_toplevel(&mut self, _evlh: &mut EventLoopHandle,
                    surface: ToplevelSurface<SurfaceData, Roles, SurfaceHandler, ()>)
                    -> ToplevelConfigure {
        let wl_surface = surface.get_surface().unwrap();
        self.token.with_surface_data(wl_surface, |data| {
            // place the window at a random location in the [0;300]x[0;300] square
            use rand::distributions::{IndependentSample, Range};
            let range = Range::new(0, 300);
            let mut rng = rand::thread_rng();
            let x = range.ind_sample(&mut rng);
            let y = range.ind_sample(&mut rng);
            data.user_data.location = Some((x, y))
        });
        ToplevelConfigure {
            size: None,
            states: vec![],
            serial: 42,
        }
    }
    fn new_popup(&mut self, _evlh: &mut EventLoopHandle,
                 _surface: PopupSurface<SurfaceData, Roles, SurfaceHandler, ()>)
                 -> PopupConfigure {
        PopupConfigure {
            size: (10, 10),
            position: (10, 10),
            serial: 42,
        }
    }
    fn move_(&mut self, _evlh: &mut EventLoopHandle,
             _surface: ToplevelSurface<SurfaceData, Roles, SurfaceHandler, ()>, _seat: &wl_seat::WlSeat,
             _serial: u32) {
    }
    fn resize(&mut self, _evlh: &mut EventLoopHandle,
              _surface: ToplevelSurface<SurfaceData, Roles, SurfaceHandler, ()>, _seat: &wl_seat::WlSeat,
              _serial: u32, _edges: zxdg_toplevel_v6::ResizeEdge) {
    }
    fn grab(&mut self, _evlh: &mut EventLoopHandle,
            _surface: PopupSurface<SurfaceData, Roles, SurfaceHandler, ()>, _seat: &wl_seat::WlSeat,
            _serial: u32) {
    }
    fn change_display_state(&mut self, _evlh: &mut EventLoopHandle,
                            _surface: ToplevelSurface<SurfaceData, Roles, SurfaceHandler, ()>,
                            _maximized: Option<bool>, _minimized: Option<bool>, _fullscreen: Option<bool>,
                            _output: Option<&wl_output::WlOutput>)
                            -> ToplevelConfigure {
        ToplevelConfigure {
            size: None,
            states: vec![],
            serial: 42,
        }
    }
    fn show_window_menu(&mut self, _evlh: &mut EventLoopHandle,
                        _surface: ToplevelSurface<SurfaceData, Roles, SurfaceHandler, ()>,
                        _seat: &wl_seat::WlSeat, _serial: u32, _x: i32, _y: i32) {
    }
}

type MyCompositorHandler = CompositorHandler<SurfaceData, Roles, SurfaceHandler>;
type MyShellHandler = ShellHandler<SurfaceData, Roles, SurfaceHandler, ShellSurfaceHandler, ()>;

fn main() {
    // A logger facility, here we use the terminal for this example
    let log = Logger::root(
        slog_async::Async::default(slog_term::term_full().fuse()).fuse(),
        o!(),
    );

    // Initialize a simple backend for testing
    let (renderer, mut input) = winit::init(log.clone()).unwrap();

    let (mut display, mut event_loop) = wayland_server::create_display();

    /*
     * Initialize wl_shm global
     */
    // Insert the ShmGlobal as a handler to your event loop
    // Here, we specify tha the standard Argb8888 and Xrgb8888 is the only supported.
    let shm_handler_id = event_loop.add_handler_with_init(ShmGlobal::new(vec![], log.clone()));
    // Register this handler to advertise a wl_shm global of version 1
    event_loop.register_global::<wl_shm::WlShm, ShmGlobal>(shm_handler_id, 1);
    // retreive the token
    let shm_token = {
        let state = event_loop.state();
        state.get_handler::<ShmGlobal>(shm_handler_id).get_token()
    };

    /*
     * Initialize the compositor global
     */
    let compositor_handler_id = event_loop.add_handler_with_init(MyCompositorHandler::new(
        SurfaceHandler {
            shm_token: shm_token.clone(),
        },
        log.clone(),
    ));
    // register it to handle wl_compositor and wl_subcompositor
    event_loop.register_global::<wl_compositor::WlCompositor, MyCompositorHandler>(compositor_handler_id, 4);
    event_loop
        .register_global::<wl_subcompositor::WlSubcompositor, MyCompositorHandler>(compositor_handler_id, 1);
    // retrieve the tokens
    let compositor_token = {
        let state = event_loop.state();
        state
            .get_handler::<MyCompositorHandler>(compositor_handler_id)
            .get_token()
    };

    /*
     * Initialize the shell global
     */
    let shell_handler_id = event_loop.add_handler_with_init(MyShellHandler::new(
        ShellSurfaceHandler::new(compositor_token),
        compositor_token,
        log.clone(),
    ));
    event_loop.register_global::<wl_shell::WlShell, MyShellHandler>(shell_handler_id, 1);
    event_loop.register_global::<zxdg_shell_v6::ZxdgShellV6, MyShellHandler>(shell_handler_id, 1);

    /*
     * Initialize glium
     */
    let context = renderer.into_glium();

    let drawer = GliumDrawer::new(&context);

    /*
     * Add a listening socket:
     */
    let name = display.add_socket_auto().unwrap().into_string().unwrap();
    println!("Listening on socket: {}", name);

    loop {
        input.dispatch_new_events().unwrap();

        let mut frame = context.draw();
        frame.clear(None, Some((0.8, 0.8, 0.9, 1.0)), false, None, None);
        // redraw the frame, in a simple but inneficient way
        {
            let screen_dimensions = context.get_framebuffer_dimensions();
            let state = event_loop.state();
            for toplevel_surface in state
                .get_handler::<MyShellHandler>(shell_handler_id)
                .toplevel_surfaces()
            {
                if let Some(wl_surface) = toplevel_surface.get_surface() {
                    // this surface is a root of a subsurface tree that needs to be drawn
                    let initial_place = compositor_token
                        .with_surface_data(wl_surface, |data| data.user_data.location.unwrap_or((0, 0)));
                    compositor_token
                        .with_surface_tree(
                            wl_surface,
                            initial_place,
                            |_surface, attributes, role, &(mut x, mut y)| {
                                if let Some((ref contents, (w, h))) = attributes.user_data.buffer {
                                    // there is actually something to draw !
                                    if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
                                        x += subdata.x;
                                        y += subdata.y;
                                    }
                                    drawer.draw(&mut frame, contents, (w, h), (x, y), screen_dimensions);
                                    TraversalAction::DoChildren((x, y))
                                } else {
                                    // we are not display, so our children are neither
                                    TraversalAction::SkipChildren
                                }
                            },
                        )
                        .unwrap();
                }
            }
        }
        frame.finish().unwrap();

        event_loop.dispatch(Some(16)).unwrap();
        display.flush_clients();
    }
}
<|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/. */

/// Implementation of Quartz (CoreGraphics) fonts.

extern crate core_foundation;
extern crate core_graphics;
extern crate core_text;

use font::{FontHandleMethods, FontMetrics, FontTableMethods};
use font::FontTableTag;
use font::FractionalPixel;
use util::geometry::{Au, px_to_pt};
use platform::macos::font_context::FontContextHandle;
use text::glyph::GlyphId;
use style::computed_values::{font_stretch, font_weight};
use platform::font_template::FontTemplateData;

use core_foundation::base::CFIndex;
use core_foundation::data::CFData;
use core_foundation::string::UniChar;
use core_graphics::font::CGGlyph;
use core_graphics::geometry::CGRect;
use core_text::font::CTFont;
use core_text::font_descriptor::{SymbolicTraitAccessors, TraitAccessors};
use core_text::font_descriptor::{kCTFontDefaultOrientation};

use std::ptr;
use std::sync::Arc;

pub struct FontTable {
    data: CFData,
}

// Noncopyable.
impl Drop for FontTable {
    fn drop(&mut self) {}
}

impl FontTable {
    pub fn wrap(data: CFData) -> FontTable {
        FontTable { data: data }
    }
}

impl FontTableMethods for FontTable {
    fn with_buffer<F>(&self, blk: F) where F: FnOnce(*const u8, usize) {
        blk(self.data.bytes().as_ptr(), self.data.len() as usize);
    }
}

pub struct FontHandle {
    pub font_data: Arc<FontTemplateData>,
    pub ctfont: CTFont,
}

impl FontHandleMethods for FontHandle {
    fn new_from_template(_fctx: &FontContextHandle,
                         template: Arc<FontTemplateData>,
                         pt_size: Option<Au>)
                         -> Result<FontHandle, ()> {
        let size = match pt_size {
            Some(s) => s.to_f64_px(),
            None => 0.0
        };
        match template.ctfont() {
            Some(ref ctfont) => {
                Ok(FontHandle {
                    font_data: template.clone(),
                    ctfont: ctfont.clone_with_font_size(size),
                })
            }
            None => {
                Err(())
            }
        }
    }

    fn template(&self) -> Arc<FontTemplateData> {
        self.font_data.clone()
    }

    fn family_name(&self) -> String {
        self.ctfont.family_name()
    }

    fn face_name(&self) -> String {
        self.ctfont.face_name()
    }

    fn is_italic(&self) -> bool {
        self.ctfont.symbolic_traits().is_italic()
    }

    fn boldness(&self) -> font_weight::T {
        // -1.0 to 1.0
        let normalized = self.ctfont.all_traits().normalized_weight();
        // 0.0 to 9.0
        let normalized = (normalized + 1.0) / 2.0 * 9.0;
        if normalized < 1.0 { return font_weight::T::Weight100; }
        if normalized < 2.0 { return font_weight::T::Weight200; }
        if normalized < 3.0 { return font_weight::T::Weight300; }
        if normalized < 4.0 { return font_weight::T::Weight400; }
        if normalized < 5.0 { return font_weight::T::Weight500; }
        if normalized < 6.0 { return font_weight::T::Weight600; }
        if normalized < 7.0 { return font_weight::T::Weight700; }
        if normalized < 8.0 { return font_weight::T::Weight800; }
        return font_weight::T::Weight900;
    }

    fn stretchiness(&self) -> font_stretch::T {
        let normalized = self.ctfont.all_traits().normalized_width();   // [-1.0, 1.0]
        match (normalized + 1.0) / 2.0 * 9.0 {  // [0.0, 9.0]
            v if v < 1.0 => font_stretch::T::ultra_condensed,
            v if v < 2.0 => font_stretch::T::extra_condensed,
            v if v < 3.0 => font_stretch::T::condensed,
            v if v < 4.0 => font_stretch::T::semi_condensed,
            v if v < 5.0 => font_stretch::T::normal,
            v if v < 6.0 => font_stretch::T::semi_expanded,
            v if v < 7.0 => font_stretch::T::expanded,
            v if v < 8.0 => font_stretch::T::extra_expanded,
            _ => font_stretch::T::ultra_expanded,
        }
    }

    fn glyph_index(&self, codepoint: char) -> Option<GlyphId> {
        let characters: [UniChar; 1] = [codepoint as UniChar];
        let mut glyphs: [CGGlyph; 1] = [0 as CGGlyph];
        let count: CFIndex = 1;

        let result = self.ctfont.get_glyphs_for_characters(&characters[0],
                                                           &mut glyphs[0],
                                                           count);

        if !result {
            // No glyph for this character
            return None;
        }

        assert!(glyphs[0] != 0); // FIXME: error handling
        return Some(glyphs[0] as GlyphId);
    }

    fn glyph_h_kerning(&self, _first_glyph: GlyphId, _second_glyph: GlyphId)
                        -> FractionalPixel {
        // TODO: Implement on mac
        0.0
    }

    fn glyph_h_advance(&self, glyph: GlyphId) -> Option<FractionalPixel> {
        let glyphs = [glyph as CGGlyph];
        let advance = self.ctfont.get_advances_for_glyphs(kCTFontDefaultOrientation,
                                                          &glyphs[0],
                                                          ptr::null_mut(),
                                                          1);
        Some(advance as FractionalPixel)
    }

    fn metrics(&self) -> FontMetrics {
        let bounding_rect: CGRect = self.ctfont.bounding_box();
        let ascent = self.ctfont.ascent() as f64;
        let descent = self.ctfont.descent() as f64;
        let em_size = Au::from_f64_px(self.ctfont.pt_size() as f64);
        let leading = self.ctfont.leading() as f64;

        let scale = px_to_pt(self.ctfont.pt_size() as f64) / (ascent + descent);
        let line_gap = (ascent + descent + leading + 0.5).floor();

        let max_advance_width = Au::from_pt(bounding_rect.size.width as f64);
        let average_advance = self.glyph_index('0')
                                  .and_then(|idx| self.glyph_h_advance(idx))
                                  .map(|advance| Au::from_f64_px(advance))
                                  .unwrap_or(max_advance_width);

        let metrics =  FontMetrics {
            underline_size:   Au::from_pt(self.ctfont.underline_thickness() as f64),
            // TODO(Issue #201): underline metrics are not reliable. Have to pull out of font table
            // directly.
            //
            // see also: https://bugs.webkit.org/show_bug.cgi?id=16768
            // see also: https://bugreports.qt-project.org/browse/QTBUG-13364
            underline_offset: Au::from_pt(self.ctfont.underline_position() as f64),
            strikeout_size:   Au(0), // FIXME(Issue #942)
            strikeout_offset: Au(0), // FIXME(Issue #942)
            leading:          Au::from_pt(leading),
            x_height:         Au::from_pt(self.ctfont.x_height() as f64),
            em_size:          em_size,
            ascent:           Au::from_pt(ascent * scale),
            descent:          Au::from_pt(descent * scale),
            max_advance:      max_advance_width,
            average_advance:  average_advance,
            line_gap:         Au::from_f64_px(line_gap),
        };
        debug!("Font metrics (@{} pt): {:?}", self.ctfont.pt_size() as f64, metrics);
        return metrics;
    }

    fn get_table_for_tag(&self, tag: FontTableTag) -> Option<FontTable> {
        let result: Option<CFData> = self.ctfont.get_font_table(tag);
        result.and_then(|data| {
            Some(FontTable::wrap(data))
        })
    }
}
<commit_msg>Utilize match guard; make methods more similar<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/. */

/// Implementation of Quartz (CoreGraphics) fonts.

extern crate core_foundation;
extern crate core_graphics;
extern crate core_text;

use font::{FontHandleMethods, FontMetrics, FontTableMethods};
use font::FontTableTag;
use font::FractionalPixel;
use util::geometry::{Au, px_to_pt};
use platform::macos::font_context::FontContextHandle;
use text::glyph::GlyphId;
use style::computed_values::{font_stretch, font_weight};
use platform::font_template::FontTemplateData;

use core_foundation::base::CFIndex;
use core_foundation::data::CFData;
use core_foundation::string::UniChar;
use core_graphics::font::CGGlyph;
use core_graphics::geometry::CGRect;
use core_text::font::CTFont;
use core_text::font_descriptor::{SymbolicTraitAccessors, TraitAccessors};
use core_text::font_descriptor::{kCTFontDefaultOrientation};

use std::ptr;
use std::sync::Arc;

pub struct FontTable {
    data: CFData,
}

// Noncopyable.
impl Drop for FontTable {
    fn drop(&mut self) {}
}

impl FontTable {
    pub fn wrap(data: CFData) -> FontTable {
        FontTable { data: data }
    }
}

impl FontTableMethods for FontTable {
    fn with_buffer<F>(&self, blk: F) where F: FnOnce(*const u8, usize) {
        blk(self.data.bytes().as_ptr(), self.data.len() as usize);
    }
}

pub struct FontHandle {
    pub font_data: Arc<FontTemplateData>,
    pub ctfont: CTFont,
}

impl FontHandleMethods for FontHandle {
    fn new_from_template(_fctx: &FontContextHandle,
                         template: Arc<FontTemplateData>,
                         pt_size: Option<Au>)
                         -> Result<FontHandle, ()> {
        let size = match pt_size {
            Some(s) => s.to_f64_px(),
            None => 0.0
        };
        match template.ctfont() {
            Some(ref ctfont) => {
                Ok(FontHandle {
                    font_data: template.clone(),
                    ctfont: ctfont.clone_with_font_size(size),
                })
            }
            None => {
                Err(())
            }
        }
    }

    fn template(&self) -> Arc<FontTemplateData> {
        self.font_data.clone()
    }

    fn family_name(&self) -> String {
        self.ctfont.family_name()
    }

    fn face_name(&self) -> String {
        self.ctfont.face_name()
    }

    fn is_italic(&self) -> bool {
        self.ctfont.symbolic_traits().is_italic()
    }

    fn boldness(&self) -> font_weight::T {
        let normalized = self.ctfont.all_traits().normalized_weight();  // [-1.0, 1.0]
        let normalized = (normalized + 1.0) / 2.0 * 9.0;  // [0.0, 9.0]
        match normalized {
            v if v < 1.0 => font_weight::T::Weight100,
            v if v < 2.0 => font_weight::T::Weight200,
            v if v < 3.0 => font_weight::T::Weight300,
            v if v < 4.0 => font_weight::T::Weight400,
            v if v < 5.0 => font_weight::T::Weight500,
            v if v < 6.0 => font_weight::T::Weight600,
            v if v < 7.0 => font_weight::T::Weight700,
            v if v < 8.0 => font_weight::T::Weight800,
            _ => font_weight::T::Weight900,
        }
    }

    fn stretchiness(&self) -> font_stretch::T {
        let normalized = self.ctfont.all_traits().normalized_width();  // [-1.0, 1.0]
        let normalized = (normalized + 1.0) / 2.0 * 9.0;  // [0.0, 9.0]
        match normalized {
            v if v < 1.0 => font_stretch::T::ultra_condensed,
            v if v < 2.0 => font_stretch::T::extra_condensed,
            v if v < 3.0 => font_stretch::T::condensed,
            v if v < 4.0 => font_stretch::T::semi_condensed,
            v if v < 5.0 => font_stretch::T::normal,
            v if v < 6.0 => font_stretch::T::semi_expanded,
            v if v < 7.0 => font_stretch::T::expanded,
            v if v < 8.0 => font_stretch::T::extra_expanded,
            _ => font_stretch::T::ultra_expanded,
        }
    }

    fn glyph_index(&self, codepoint: char) -> Option<GlyphId> {
        let characters: [UniChar; 1] = [codepoint as UniChar];
        let mut glyphs: [CGGlyph; 1] = [0 as CGGlyph];
        let count: CFIndex = 1;

        let result = self.ctfont.get_glyphs_for_characters(&characters[0],
                                                           &mut glyphs[0],
                                                           count);

        if !result {
            // No glyph for this character
            return None;
        }

        assert!(glyphs[0] != 0); // FIXME: error handling
        return Some(glyphs[0] as GlyphId);
    }

    fn glyph_h_kerning(&self, _first_glyph: GlyphId, _second_glyph: GlyphId)
                        -> FractionalPixel {
        // TODO: Implement on mac
        0.0
    }

    fn glyph_h_advance(&self, glyph: GlyphId) -> Option<FractionalPixel> {
        let glyphs = [glyph as CGGlyph];
        let advance = self.ctfont.get_advances_for_glyphs(kCTFontDefaultOrientation,
                                                          &glyphs[0],
                                                          ptr::null_mut(),
                                                          1);
        Some(advance as FractionalPixel)
    }

    fn metrics(&self) -> FontMetrics {
        let bounding_rect: CGRect = self.ctfont.bounding_box();
        let ascent = self.ctfont.ascent() as f64;
        let descent = self.ctfont.descent() as f64;
        let em_size = Au::from_f64_px(self.ctfont.pt_size() as f64);
        let leading = self.ctfont.leading() as f64;

        let scale = px_to_pt(self.ctfont.pt_size() as f64) / (ascent + descent);
        let line_gap = (ascent + descent + leading + 0.5).floor();

        let max_advance_width = Au::from_pt(bounding_rect.size.width as f64);
        let average_advance = self.glyph_index('0')
                                  .and_then(|idx| self.glyph_h_advance(idx))
                                  .map(|advance| Au::from_f64_px(advance))
                                  .unwrap_or(max_advance_width);

        let metrics =  FontMetrics {
            underline_size:   Au::from_pt(self.ctfont.underline_thickness() as f64),
            // TODO(Issue #201): underline metrics are not reliable. Have to pull out of font table
            // directly.
            //
            // see also: https://bugs.webkit.org/show_bug.cgi?id=16768
            // see also: https://bugreports.qt-project.org/browse/QTBUG-13364
            underline_offset: Au::from_pt(self.ctfont.underline_position() as f64),
            strikeout_size:   Au(0), // FIXME(Issue #942)
            strikeout_offset: Au(0), // FIXME(Issue #942)
            leading:          Au::from_pt(leading),
            x_height:         Au::from_pt(self.ctfont.x_height() as f64),
            em_size:          em_size,
            ascent:           Au::from_pt(ascent * scale),
            descent:          Au::from_pt(descent * scale),
            max_advance:      max_advance_width,
            average_advance:  average_advance,
            line_gap:         Au::from_f64_px(line_gap),
        };
        debug!("Font metrics (@{} pt): {:?}", self.ctfont.pt_size() as f64, metrics);
        return metrics;
    }

    fn get_table_for_tag(&self, tag: FontTableTag) -> Option<FontTable> {
        let result: Option<CFData> = self.ctfont.get_font_table(tag);
        result.and_then(|data| {
            Some(FontTable::wrap(data))
        })
    }
}
<|endoftext|>


<commit_before>//! Facilities for working with Array `napi_value`s.

use raw::{Local, Env};

use nodejs_sys as napi;

pub unsafe extern "C" fn new(_out: &mut Local, _env: Env, _length: u32) { unimplemented!() }

/// Gets the length of a `napi_value` containing a JavaScript Array.
pub unsafe extern "C" fn len(env: Env, array: Local) -> u32 {
    let mut len = 0;
    assert_eq!(napi::napi_get_array_length(env, array, &mut len as *mut _), napi::napi_status::napi_ok);
    len
}
<commit_msg>Document panics for `neon_runtime::napi::array::len`<commit_after>//! Facilities for working with Array `napi_value`s.

use raw::{Local, Env};

use nodejs_sys as napi;

pub unsafe extern "C" fn new(_out: &mut Local, _env: Env, _length: u32) { unimplemented!() }

/// Gets the length of a `napi_value` containing a JavaScript Array.
///
/// # Panics
/// This function panics if `array` is not an Array, or if a previous n-api call caused a pending
/// exception.
pub unsafe extern "C" fn len(env: Env, array: Local) -> u32 {
    let mut len = 0;
    assert_eq!(napi::napi_get_array_length(env, array, &mut len as *mut _), napi::napi_status::napi_ok);
    len
}
<|endoftext|>


<commit_before>#![feature(phase)]
#![feature(globs)]
#![crate_name = "cube"]

extern crate shader_version;
extern crate vecmath;
extern crate event;
extern crate input;
extern crate cam;
extern crate gfx;
// extern crate glfw_window;
extern crate sdl2;
extern crate sdl2_window;
#[phase(plugin)]
extern crate gfx_macros;
extern crate native;
extern crate time;

use std::cell::RefCell;
// use glfw_window::GlfwWindow;
use sdl2_window::Sdl2Window;
use gfx::{ Device, DeviceHelper };
use event::{ Events, Window, WindowSettings };

//----------------------------------------
// Cube associated data

#[vertex_format]
struct Vertex {
    #[as_float]
    a_pos: [i8, ..3],
    #[as_float]
    a_tex_coord: [u8, ..2],
}

impl Vertex {
    fn new(pos: [i8, ..3], tc: [u8, ..2]) -> Vertex {
        Vertex {
            a_pos: pos,
            a_tex_coord: tc,
        }
    }
}

#[shader_param(CubeBatch)]
struct Params {
    u_model_view_proj: [[f32, ..4], ..4],
    t_color: gfx::shade::TextureParam,
}

static VERTEX_SRC: gfx::ShaderSource = shaders! {
GLSL_120: b"
    #version 120
    attribute vec3 a_pos;
    attribute vec2 a_tex_coord;
    varying vec2 v_TexCoord;
    uniform mat4 u_model_view_proj;
    void main() {
        v_TexCoord = a_tex_coord;
        gl_Position = u_model_view_proj * vec4(a_pos, 1.0);
    }
"
GLSL_150: b"
    #version 150 core
    in vec3 a_pos;
    in vec2 a_tex_coord;
    out vec2 v_TexCoord;
    uniform mat4 u_model_view_proj;
    void main() {
        v_TexCoord = a_tex_coord;
        gl_Position = u_model_view_proj * vec4(a_pos, 1.0);
    }
"
};

static FRAGMENT_SRC: gfx::ShaderSource = shaders! {
GLSL_120: b"
    #version 120
    varying vec2 v_TexCoord;
    uniform sampler2D t_color;
    void main() {
        vec4 tex = texture2D(t_color, v_TexCoord);
        float blend = dot(v_TexCoord-vec2(0.5,0.5), v_TexCoord-vec2(0.5,0.5));
        gl_FragColor = mix(tex, vec4(0.0,0.0,0.0,0.0), blend*1.0);
    }
"
GLSL_150: b"
    #version 150 core
    in vec2 v_TexCoord;
    out vec4 o_Color;
    uniform sampler2D t_color;
    void main() {
        vec4 tex = texture(t_color, v_TexCoord);
        float blend = dot(v_TexCoord-vec2(0.5,0.5), v_TexCoord-vec2(0.5,0.5));
        o_Color = mix(tex, vec4(0.0,0.0,0.0,0.0), blend*1.0);
    }
"
};

//----------------------------------------

// We need to run on the main thread, so ensure we are using the `native` runtime. This is
// technically not needed, since this is the default, but it's not guaranteed.
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
     native::start(argc, argv, main)
}

fn main() {
    let (win_width, win_height) = (640, 480);
    let mut window = Sdl2Window::new(
        shader_version::opengl::OpenGL_3_2,
        WindowSettings {
            title: "cube".to_string(),
            size: [win_width, win_height],
            fullscreen: false,
            exit_on_esc: true,
            samples: 4,
        }
    );

    window.capture_cursor(true);

    let mut device = gfx::GlDevice::new(|s| unsafe {
        std::mem::transmute(sdl2::video::gl_get_proc_address(s))
    });
    let frame = gfx::Frame::new(win_width as u16, win_height as u16);
    let state = gfx::DrawState::new().depth(gfx::state::LessEqual, true);

    let vertex_data = vec![
        //top (0, 0, 1)
        Vertex::new([-1, -1,  1], [0, 0]),
        Vertex::new([ 1, -1,  1], [1, 0]),
        Vertex::new([ 1,  1,  1], [1, 1]),
        Vertex::new([-1,  1,  1], [0, 1]),
        //bottom (0, 0, -1)
        Vertex::new([ 1,  1, -1], [0, 0]),
        Vertex::new([-1,  1, -1], [1, 0]),
        Vertex::new([-1, -1, -1], [1, 1]),
        Vertex::new([ 1, -1, -1], [0, 1]),
        //right (1, 0, 0)
        Vertex::new([ 1, -1, -1], [0, 0]),
        Vertex::new([ 1,  1, -1], [1, 0]),
        Vertex::new([ 1,  1,  1], [1, 1]),
        Vertex::new([ 1, -1,  1], [0, 1]),
        //left (-1, 0, 0)
        Vertex::new([-1,  1,  1], [0, 0]),
        Vertex::new([-1, -1,  1], [1, 0]),
        Vertex::new([-1, -1, -1], [1, 1]),
        Vertex::new([-1,  1, -1], [0, 1]),
        //front (0, 1, 0)
        Vertex::new([-1,  1, -1], [0, 0]),
        Vertex::new([ 1,  1, -1], [1, 0]),
        Vertex::new([ 1,  1,  1], [1, 1]),
        Vertex::new([-1,  1,  1], [0, 1]),
        //back (0, -1, 0)
        Vertex::new([ 1, -1,  1], [0, 0]),
        Vertex::new([-1, -1,  1], [1, 0]),
        Vertex::new([-1, -1, -1], [1, 1]),
        Vertex::new([ 1, -1, -1], [0, 1]),
    ];

    let mesh = device.create_mesh(vertex_data.as_slice());

    let slice = {
        let index_data = vec![
            0u8, 1, 2, 2, 3, 0,    //top
            4, 5, 6, 6, 7, 4,       //bottom
            8, 9, 10, 10, 11, 8,    //right
            12, 13, 14, 14, 16, 12, //left
            16, 17, 18, 18, 19, 16, //front
            20, 21, 22, 22, 23, 20, //back
        ];

        let buf = device.create_buffer_static(index_data.as_slice());
        gfx::IndexSlice8(gfx::TriangleList, buf, 0, 36)
    };

    let tinfo = gfx::tex::TextureInfo {
        width: 1,
        height: 1,
        depth: 1,
        levels: 1,
        kind: gfx::tex::Texture2D,
        format: gfx::tex::RGBA8,
    };
    let img_info = tinfo.to_image_info();
    let texture = device.create_texture(tinfo).unwrap();
    device.update_texture(
            &texture,
            &img_info,
            vec![0x20u8, 0xA0u8, 0xC0u8, 0x00u8].as_slice()
        ).unwrap();

    let sampler = device.create_sampler(
        gfx::tex::SamplerInfo::new(
            gfx::tex::Bilinear,
            gfx::tex::Clamp
        )
    );

    let program = device.link_program(
            VERTEX_SRC.clone(),
            FRAGMENT_SRC.clone()
        ).unwrap();

    let mut graphics = gfx::Graphics::new(device);
    let batch: CubeBatch = graphics.make_batch(&program, &mesh, slice, &state).unwrap();

    let mut data = Params {
        u_model_view_proj: vecmath::mat4_id(),
        t_color: (texture, Some(sampler)),
    };

    let model = vecmath::mat4_id();
    let projection = cam::CameraPerspective {
            fov: 90.0f32,
            near_clip: 0.1,
            far_clip: 1000.0,
            aspect_ratio: (win_width as f32) / (win_height as f32)
        }.projection();
    let mut first_person = cam::FirstPerson::new(
        [0.5f32, 0.5, 4.0],
        cam::FirstPersonSettings::keyboard_wasd()
    );

    let window = RefCell::new(window);
    for e in Events::new(&window) {
        use event::RenderEvent;

        first_person.event(&e);
        e.render(|args| {
            graphics.clear(
                gfx::ClearData {
                    color: [0.3, 0.3, 0.3, 1.0],
                    depth: 1.0,
                    stencil: 0,
                },
                gfx::COLOR | gfx::DEPTH,
                &frame
            );
            data.u_model_view_proj = cam::model_view_projection(
                    model,
                    first_person.camera(args.ext_dt).orthogonal(),
                    projection
                );
            graphics.draw(&batch, &data, &frame);
            graphics.end_frame();
        });
    }
}

<commit_msg>Upgraded to latest Gfx<commit_after>#![feature(phase)]
#![feature(globs)]
#![crate_name = "cube"]

extern crate shader_version;
extern crate vecmath;
extern crate event;
extern crate input;
extern crate cam;
extern crate gfx;
extern crate render;
// extern crate glfw_window;
extern crate sdl2;
extern crate sdl2_window;
#[phase(plugin)]
extern crate gfx_macros;
extern crate native;
extern crate time;

use std::cell::RefCell;
// use glfw_window::GlfwWindow;
use sdl2_window::Sdl2Window;
use gfx::{ Device, DeviceHelper, ToSlice };
use event::{ Events, Window, WindowSettings };

//----------------------------------------
// Cube associated data

#[vertex_format]
struct Vertex {
    #[as_float]
    a_pos: [i8, ..3],
    #[as_float]
    a_tex_coord: [u8, ..2],
}

impl Vertex {
    fn new(pos: [i8, ..3], tc: [u8, ..2]) -> Vertex {
        Vertex {
            a_pos: pos,
            a_tex_coord: tc,
        }
    }
}

#[shader_param(CubeBatch)]
struct Params {
    u_model_view_proj: [[f32, ..4], ..4],
    t_color: gfx::shade::TextureParam,
}

static VERTEX_SRC: gfx::ShaderSource<'static> = shaders! {
GLSL_120: b"
    #version 120
    attribute vec3 a_pos;
    attribute vec2 a_tex_coord;
    varying vec2 v_TexCoord;
    uniform mat4 u_model_view_proj;
    void main() {
        v_TexCoord = a_tex_coord;
        gl_Position = u_model_view_proj * vec4(a_pos, 1.0);
    }
"
GLSL_150: b"
    #version 150 core
    in vec3 a_pos;
    in vec2 a_tex_coord;
    out vec2 v_TexCoord;
    uniform mat4 u_model_view_proj;
    void main() {
        v_TexCoord = a_tex_coord;
        gl_Position = u_model_view_proj * vec4(a_pos, 1.0);
    }
"
};

static FRAGMENT_SRC: gfx::ShaderSource<'static> = shaders! {
GLSL_120: b"
    #version 120
    varying vec2 v_TexCoord;
    uniform sampler2D t_color;
    void main() {
        vec4 tex = texture2D(t_color, v_TexCoord);
        float blend = dot(v_TexCoord-vec2(0.5,0.5), v_TexCoord-vec2(0.5,0.5));
        gl_FragColor = mix(tex, vec4(0.0,0.0,0.0,0.0), blend*1.0);
    }
"
GLSL_150: b"
    #version 150 core
    in vec2 v_TexCoord;
    out vec4 o_Color;
    uniform sampler2D t_color;
    void main() {
        vec4 tex = texture(t_color, v_TexCoord);
        float blend = dot(v_TexCoord-vec2(0.5,0.5), v_TexCoord-vec2(0.5,0.5));
        o_Color = mix(tex, vec4(0.0,0.0,0.0,0.0), blend*1.0);
    }
"
};

//----------------------------------------

// We need to run on the main thread, so ensure we are using the `native` runtime. This is
// technically not needed, since this is the default, but it's not guaranteed.
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
     native::start(argc, argv, main)
}

fn main() {
    let (win_width, win_height) = (640, 480);
    let mut window = Sdl2Window::new(
        shader_version::opengl::OpenGL_3_2,
        WindowSettings {
            title: "cube".to_string(),
            size: [win_width, win_height],
            fullscreen: false,
            exit_on_esc: true,
            samples: 4,
        }
    );

    window.capture_cursor(true);

    let mut device = gfx::GlDevice::new(|s| unsafe {
        std::mem::transmute(sdl2::video::gl_get_proc_address(s))
    });
    let frame = gfx::Frame::new(win_width as u16, win_height as u16);
    let state = gfx::DrawState::new().depth(gfx::state::LessEqual, true);

    let vertex_data = vec![
        //top (0, 0, 1)
        Vertex::new([-1, -1,  1], [0, 0]),
        Vertex::new([ 1, -1,  1], [1, 0]),
        Vertex::new([ 1,  1,  1], [1, 1]),
        Vertex::new([-1,  1,  1], [0, 1]),
        //bottom (0, 0, -1)
        Vertex::new([ 1,  1, -1], [0, 0]),
        Vertex::new([-1,  1, -1], [1, 0]),
        Vertex::new([-1, -1, -1], [1, 1]),
        Vertex::new([ 1, -1, -1], [0, 1]),
        //right (1, 0, 0)
        Vertex::new([ 1, -1, -1], [0, 0]),
        Vertex::new([ 1,  1, -1], [1, 0]),
        Vertex::new([ 1,  1,  1], [1, 1]),
        Vertex::new([ 1, -1,  1], [0, 1]),
        //left (-1, 0, 0)
        Vertex::new([-1,  1,  1], [0, 0]),
        Vertex::new([-1, -1,  1], [1, 0]),
        Vertex::new([-1, -1, -1], [1, 1]),
        Vertex::new([-1,  1, -1], [0, 1]),
        //front (0, 1, 0)
        Vertex::new([-1,  1, -1], [0, 0]),
        Vertex::new([ 1,  1, -1], [1, 0]),
        Vertex::new([ 1,  1,  1], [1, 1]),
        Vertex::new([-1,  1,  1], [0, 1]),
        //back (0, -1, 0)
        Vertex::new([ 1, -1,  1], [0, 0]),
        Vertex::new([-1, -1,  1], [1, 0]),
        Vertex::new([-1, -1, -1], [1, 1]),
        Vertex::new([ 1, -1, -1], [0, 1]),
    ];

    let mesh = device.create_mesh(vertex_data.as_slice());

    let index_data: &[u8] = [
         0,  1,  2,  2,  3,  0, // top
         4,  5,  6,  6,  7,  4, // bottom
         8,  9, 10, 10, 11,  8, // right
        12, 13, 14, 14, 16, 12, // left
        16, 17, 18, 18, 19, 16, // front
        20, 21, 22, 22, 23, 20, // back
    ];

    let slice = device
        .create_buffer_static::<u8>(index_data)
        .to_slice(gfx::TriangleList);

    let tinfo = gfx::tex::TextureInfo {
        width: 1,
        height: 1,
        depth: 1,
        levels: 1,
        kind: gfx::tex::Texture2D,
        format: gfx::tex::RGBA8,
    };
    let img_info = tinfo.to_image_info();
    let texture = device.create_texture(tinfo).unwrap();
    device.update_texture(
            &texture,
            &img_info,
            vec![0x20u8, 0xA0u8, 0xC0u8, 0x00u8].as_slice()
        ).unwrap();

    let sampler = device.create_sampler(
        gfx::tex::SamplerInfo::new(
            gfx::tex::Bilinear,
            gfx::tex::Clamp
        )
    );

    let program = device.link_program(
            VERTEX_SRC.clone(),
            FRAGMENT_SRC.clone()
        ).unwrap();

    let mut graphics = gfx::Graphics::new(device);
    let batch: CubeBatch = graphics.make_batch(&program, &mesh, slice, &state).unwrap();

    let mut data = Params {
        u_model_view_proj: vecmath::mat4_id(),
        t_color: (texture, Some(sampler)),
    };

    let model = vecmath::mat4_id();
    let projection = cam::CameraPerspective {
            fov: 90.0f32,
            near_clip: 0.1,
            far_clip: 1000.0,
            aspect_ratio: (win_width as f32) / (win_height as f32)
        }.projection();
    let mut first_person = cam::FirstPerson::new(
        [0.5f32, 0.5, 4.0],
        cam::FirstPersonSettings::keyboard_wasd()
    );

    let window = RefCell::new(window);
    for e in Events::new(&window) {
        use event::RenderEvent;

        first_person.event(&e);
        e.render(|args| {
            graphics.clear(
                gfx::ClearData {
                    color: [0.3, 0.3, 0.3, 1.0],
                    depth: 1.0,
                    stencil: 0,
                },
                gfx::COLOR | gfx::DEPTH,
                &frame
            );
            data.u_model_view_proj = cam::model_view_projection(
                    model,
                    first_person.camera(args.ext_dt).orthogonal(),
                    projection
                );
            graphics.draw(&batch, &data, &frame);
            graphics.end_frame();
        });
    }
}

<|endoftext|>


<commit_before>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A very simple bit-vector that serves the needs of `primal`.

#![deny(unsafe_code)]
#![deny(warnings)]

extern crate hamming;

use std::fmt;
use std::hash;
use std::ops::Index;

mod inner;
mod iter;

pub use inner::BitVec;
pub use iter::{Iter, IntoOnes, Ones};

const BITS: usize = 8;

impl Index<usize> for BitVec {
    type Output = bool;

    #[inline]
    fn index(&self, i: usize) -> &bool {
        if self.get(i).expect("index out of bounds") {
            &true
        } else {
            &false
        }
    }
}

impl BitVec {
    /// Count the number of ones in the entire `BitVec`.
    #[inline]
    pub fn count_ones(&self) -> usize {
        hamming::weight(self.as_bytes()) as usize
    }

    /// Count the number of ones for the bits up to but not including
    /// the `bit`th bit.
    #[inline]
    pub fn count_ones_before(&self, bit: usize) -> usize {
        assert!(bit <= self.len());
        let (byte, bit) = (bit / BITS, bit % BITS);
        let mask = (1 << bit) - 1;

        let bytes = self.as_bytes();

        hamming::weight(&bytes[..byte]) as usize
            + bytes.get(byte).map_or(0, |b| (b & mask).count_ones() as usize)
    }

    /// Find the index of the `n`th (0-indexed) set bit.
    pub fn find_nth_bit(&self, mut n: usize) -> Option<usize> {
        if n >= self.len() {
            return None;
        }
        n += 1;
        let mut bytes = self.as_bytes();

        let mut byte_idx = 0;
        while bytes.len() > 240 {
            let ix = bytes.len() / 2;
            let (first, second) = bytes.split_at(ix);

            let count = hamming::weight(first) as usize;
            if count >= n {
                bytes = first;
            } else {
                n -= count;
                bytes = second;
                byte_idx += ix;
            }
        }

        let i = bytes.iter().position(|&b| {
            let count = b.count_ones() as usize;
            if count >= n {
                true
            } else {
                n -= count;
                false
            }
        })?;

        // clear the bottom n-1 set bits, so that the lowest one
        // is the one we care about
        let mut b = bytes[i];
        for _ in 1..n {
            b &= b - 1;
        }
        assert!(b != 0);

        Some((byte_idx + i) * BITS + b.trailing_zeros() as usize)
    }

    /// Sets all bits to 1.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use std::collections::BitVec;
    ///
    /// let before = 0b01100000;
    /// let after  = 0b11111111;
    ///
    /// let mut bv = BitVec::from_bytes(&[before]);
    /// bv.set_all();
    /// assert_eq!(bv, BitVec::from_bytes(&[after]));
    /// ```
    #[inline]
    pub fn set_all(&mut self) {
        for w in self.as_bytes_mut() { *w = !0; }
        self.fix_last_block();
    }

    /// Clears all bits in this vector.
    #[inline]
    pub fn clear(&mut self) {
        for w in self.as_bytes_mut() { *w = 0; }
    }

    /// Returns true if there are no bits in this vector
    #[inline]
    pub fn is_empty(&self) -> bool { self.len() == 0 }
}

impl Default for BitVec {
    #[inline]
    fn default() -> BitVec { BitVec::new() }
}

impl fmt::Debug for BitVec {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        for bit in self {
            write!(fmt, "{}", if bit { 1 } else { 0 })?;
        }
        Ok(())
    }
}

impl hash::Hash for BitVec {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        state.write_usize(self.len());
        state.write(self.as_bytes());
    }
}

impl PartialEq for BitVec {
    #[inline]
    fn eq(&self, other: &BitVec) -> bool {
        self.len() == other.len() && self.as_bytes() == other.as_bytes()
    }
}

impl Eq for BitVec {}

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

    #[test]
    fn count_ones_before() {
        let len = 10000;

        let ones = BitVec::from_elem(len, true);
        let zeros = BitVec::from_elem(len, false);
        let mut halves = zeros.clone();
        for i in 0..len / 2 {
            halves.set(i * 2, true);
        }
        for i in 0..len + 1 {
            assert_eq!(ones.count_ones_before(i), i);
            assert_eq!(zeros.count_ones_before(i), 0);
            assert_eq!(halves.count_ones_before(i), (i + 1) / 2);
        }
    }

    #[test]
    fn find_nth_bit() {
        let len = 5000;

        let ones = BitVec::from_elem(len, true);
        let mut halves = BitVec::from_elem(len * 2, false);
        for i in 0..len {
            halves.set(i * 2, true);
        }
        for i in 0..len {
            assert_eq!(ones.find_nth_bit(i), Some(i));
            assert_eq!(halves.find_nth_bit(i), Some(i * 2));
        }
        assert_eq!(ones.find_nth_bit(len + 1), None);
        assert_eq!(halves.find_nth_bit(len + 1), None);

        assert_eq!(BitVec::new().find_nth_bit(0), None);
        assert_eq!(BitVec::from_elem(len, false).find_nth_bit(0), None);
    }
}
<commit_msg>Increase primal-bit coverage<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A very simple bit-vector that serves the needs of `primal`.

#![deny(unsafe_code)]
#![deny(warnings)]

extern crate hamming;

use std::fmt;
use std::hash;
use std::ops::Index;

mod inner;
mod iter;

pub use inner::BitVec;
pub use iter::{Iter, IntoOnes, Ones};

const BITS: usize = 8;

impl Index<usize> for BitVec {
    type Output = bool;

    #[inline]
    fn index(&self, i: usize) -> &bool {
        if self.get(i).expect("index out of bounds") {
            &true
        } else {
            &false
        }
    }
}

impl BitVec {
    /// Count the number of ones in the entire `BitVec`.
    #[inline]
    pub fn count_ones(&self) -> usize {
        hamming::weight(self.as_bytes()) as usize
    }

    /// Count the number of ones for the bits up to but not including
    /// the `bit`th bit.
    #[inline]
    pub fn count_ones_before(&self, bit: usize) -> usize {
        assert!(bit <= self.len());
        let (byte, bit) = (bit / BITS, bit % BITS);
        let mask = (1 << bit) - 1;

        let bytes = self.as_bytes();

        hamming::weight(&bytes[..byte]) as usize
            + bytes.get(byte).map_or(0, |b| (b & mask).count_ones() as usize)
    }

    /// Find the index of the `n`th (0-indexed) set bit.
    pub fn find_nth_bit(&self, mut n: usize) -> Option<usize> {
        if n >= self.len() {
            return None;
        }
        n += 1;
        let mut bytes = self.as_bytes();

        let mut byte_idx = 0;
        while bytes.len() > 240 {
            let ix = bytes.len() / 2;
            let (first, second) = bytes.split_at(ix);

            let count = hamming::weight(first) as usize;
            if count >= n {
                bytes = first;
            } else {
                n -= count;
                bytes = second;
                byte_idx += ix;
            }
        }

        let i = bytes.iter().position(|&b| {
            let count = b.count_ones() as usize;
            if count >= n {
                true
            } else {
                n -= count;
                false
            }
        })?;

        // clear the bottom n-1 set bits, so that the lowest one
        // is the one we care about
        let mut b = bytes[i];
        for _ in 1..n {
            b &= b - 1;
        }
        assert!(b != 0);

        Some((byte_idx + i) * BITS + b.trailing_zeros() as usize)
    }

    /// Sets all bits to 1.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use std::collections::BitVec;
    ///
    /// let before = 0b01100000;
    /// let after  = 0b11111111;
    ///
    /// let mut bv = BitVec::from_bytes(&[before]);
    /// bv.set_all();
    /// assert_eq!(bv, BitVec::from_bytes(&[after]));
    /// ```
    #[inline]
    pub fn set_all(&mut self) {
        for w in self.as_bytes_mut() { *w = !0; }
        self.fix_last_block();
    }

    /// Clears all bits in this vector.
    #[inline]
    pub fn clear(&mut self) {
        for w in self.as_bytes_mut() { *w = 0; }
    }

    /// Returns true if there are no bits in this vector
    #[inline]
    pub fn is_empty(&self) -> bool { self.len() == 0 }
}

impl Default for BitVec {
    #[inline]
    fn default() -> BitVec { BitVec::new() }
}

impl fmt::Debug for BitVec {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        for bit in self {
            write!(fmt, "{}", if bit { 1 } else { 0 })?;
        }
        Ok(())
    }
}

impl hash::Hash for BitVec {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        state.write_usize(self.len());
        state.write(self.as_bytes());
    }
}

impl PartialEq for BitVec {
    #[inline]
    fn eq(&self, other: &BitVec) -> bool {
        self.len() == other.len() && self.as_bytes() == other.as_bytes()
    }
}

impl Eq for BitVec {}

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

    #[test]
    fn count_ones_before() {
        let len = 10000;

        let ones = BitVec::from_elem(len, true);
        let zeros = BitVec::from_elem(len, false);
        let mut halves = zeros.clone();
        for i in 0..len / 2 {
            halves.set(i * 2, true);
        }
        for i in 0..len + 1 {
            assert_eq!(ones.count_ones_before(i), i);
            assert_eq!(zeros.count_ones_before(i), 0);
            assert_eq!(halves.count_ones_before(i), (i + 1) / 2);
        }
    }

    #[test]
    fn find_nth_bit() {
        let len = 5000;

        let ones = BitVec::from_elem(len, true);
        let mut halves = BitVec::from_elem(len * 2, false);
        for i in 0..len {
            halves.set(i * 2, true);
        }
        for i in 0..len {
            assert_eq!(ones.find_nth_bit(i), Some(i));
            assert_eq!(halves.find_nth_bit(i), Some(i * 2));
        }
        assert_eq!(ones.find_nth_bit(len + 1), None);
        assert_eq!(halves.find_nth_bit(len + 1), None);

        assert_eq!(BitVec::new().find_nth_bit(0), None);
        assert_eq!(BitVec::from_elem(len, false).find_nth_bit(0), None);
    }

    #[test]
    fn get() {
        let len = 10000;

        let mut halves = BitVec::from_elem(len, false);
        for i in 0..len {
            assert_eq!(halves.get(i), Some(false));
        }
        for i in 0..len / 2 {
            halves.set(i * 2, true);
        }
        for i in 0..len {
            assert_eq!(halves.get(i), Some(i % 2 == 0));
        }
        assert_eq!(halves.get(len), None);
    }

    #[test]
    fn clone() {
        let len = 10000;

        let ones = BitVec::from_elem(len, true);
        let zeros = BitVec::from_elem(len, false);
        let mut halves = zeros.clone();
        for i in 0..len / 2 {
            halves.set(i * 2, true);
        }

        assert_eq!(ones.clone(), ones);
        assert_eq!(zeros.clone(), zeros);
        assert_eq!(halves.clone(), halves);

        let mut bv = BitVec::from_elem(len, false);
        bv.clone_from(&ones);
        assert_eq!(bv, ones);
        bv.clone_from(&zeros);
        assert_eq!(bv, zeros);
        bv.clone_from(&halves);
        assert_eq!(bv, halves);
    }

    #[test]
    fn len_is_empty() {
        let len = 10000;

        let ones = BitVec::from_elem(len, true);
        let zeros = BitVec::from_elem(len, false);
        let default = BitVec::default();

        assert_eq!(ones.len(), len);
        assert_eq!(zeros.len(), len);
        assert_eq!(default.len(), 0);

        assert!(!ones.is_empty());
        assert!(!zeros.is_empty());
        assert!(default.is_empty());
    }

    #[test]
    fn clear_set_all() {
        let len = 10000;

        let ones = BitVec::from_elem(len, true);
        let zeros = BitVec::from_elem(len, false);

        let mut bv = ones.clone();
        assert_eq!(bv, ones);
        bv.clear();
        assert_eq!(bv, zeros);
        bv.set_all();
        assert_eq!(bv, ones);
    }
}
<|endoftext|>


<commit_before><commit_msg>Fix road bug (fixes #284)<commit_after><|endoftext|>