<commit_before>//! We use code generation heavily in rust-analyzer.
//!
//! Rather then doing it via proc-macros, we use old-school way of just dumping
//! the source code.
//!
//! This module's submodules define specific bits that we generate.

mod gen_syntax;
mod gen_parser_tests;
mod gen_assists_docs;

use std::{fs, mem, path::Path};

use crate::Result;

pub use self::{
    gen_assists_docs::generate_assists_docs, gen_parser_tests::generate_parser_tests,
    gen_syntax::generate_syntax,
};

const GRAMMAR_DIR: &str = "crates/ra_parser/src/grammar";
const OK_INLINE_TESTS_DIR: &str = "crates/ra_syntax/test_data/parser/inline/ok";
const ERR_INLINE_TESTS_DIR: &str = "crates/ra_syntax/test_data/parser/inline/err";

pub const SYNTAX_KINDS: &str = "crates/ra_parser/src/syntax_kind/generated.rs";
pub const AST: &str = "crates/ra_syntax/src/ast/generated.rs";

const ASSISTS_DIR: &str = "crates/ra_assists/src/handlers";
const ASSISTS_TESTS: &str = "crates/ra_assists/src/doc_tests/generated.rs";
const ASSISTS_DOCS: &str = "docs/user/assists.md";

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Mode {
    Overwrite,
    Verify,
}

/// A helper to update file on disk if it has changed.
/// With verify = false,
fn update(path: &Path, contents: &str, mode: Mode) -> Result<()> {
    match fs::read_to_string(path) {
        Ok(ref old_contents) if normalize(old_contents) == normalize(contents) => {
            return Ok(());
        }
        _ => (),
    }
    if mode == Mode::Verify {
        anyhow::bail!("`{}` is not up-to-date", path.display());
    }
    eprintln!("updating {}", path.display());
    fs::write(path, contents)?;
    return Ok(());

    fn normalize(s: &str) -> String {
        s.replace("\r\n", "\n")
    }
}

fn extract_comment_blocks(text: &str) -> Vec<Vec<String>> {
    do_extract_comment_blocks(text, false)
}

fn extract_comment_blocks_with_empty_lines(text: &str) -> Vec<Vec<String>> {
    do_extract_comment_blocks(text, true)
}

fn do_extract_comment_blocks(text: &str, allow_blocks_with_empty_lins: bool) -> Vec<Vec<String>> {
    let mut res = Vec::new();

    let prefix = "// ";
    let lines = text.lines().map(str::trim_start);

    let mut block = vec![];
    for line in lines {
        if line == "//" && allow_blocks_with_empty_lins {
            block.push(String::new());
            continue;
        }

        let is_comment = line.starts_with(prefix);
        if is_comment {
            block.push(line[prefix.len()..].to_string());
        } else if !block.is_empty() {
            res.push(mem::replace(&mut block, Vec::new()));
        }
    }
    if !block.is_empty() {
        res.push(mem::replace(&mut block, Vec::new()))
    }
    res
}
<commit_msg>Reduce visibility<commit_after>//! We use code generation heavily in rust-analyzer.
//!
//! Rather then doing it via proc-macros, we use old-school way of just dumping
//! the source code.
//!
//! This module's submodules define specific bits that we generate.

mod gen_syntax;
mod gen_parser_tests;
mod gen_assists_docs;

use std::{fs, mem, path::Path};

use crate::Result;

pub use self::{
    gen_assists_docs::generate_assists_docs, gen_parser_tests::generate_parser_tests,
    gen_syntax::generate_syntax,
};

const GRAMMAR_DIR: &str = "crates/ra_parser/src/grammar";
const OK_INLINE_TESTS_DIR: &str = "crates/ra_syntax/test_data/parser/inline/ok";
const ERR_INLINE_TESTS_DIR: &str = "crates/ra_syntax/test_data/parser/inline/err";

const SYNTAX_KINDS: &str = "crates/ra_parser/src/syntax_kind/generated.rs";
const AST: &str = "crates/ra_syntax/src/ast/generated.rs";

const ASSISTS_DIR: &str = "crates/ra_assists/src/handlers";
const ASSISTS_TESTS: &str = "crates/ra_assists/src/doc_tests/generated.rs";
const ASSISTS_DOCS: &str = "docs/user/assists.md";

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Mode {
    Overwrite,
    Verify,
}

/// A helper to update file on disk if it has changed.
/// With verify = false,
fn update(path: &Path, contents: &str, mode: Mode) -> Result<()> {
    match fs::read_to_string(path) {
        Ok(ref old_contents) if normalize(old_contents) == normalize(contents) => {
            return Ok(());
        }
        _ => (),
    }
    if mode == Mode::Verify {
        anyhow::bail!("`{}` is not up-to-date", path.display());
    }
    eprintln!("updating {}", path.display());
    fs::write(path, contents)?;
    return Ok(());

    fn normalize(s: &str) -> String {
        s.replace("\r\n", "\n")
    }
}

fn extract_comment_blocks(text: &str) -> Vec<Vec<String>> {
    do_extract_comment_blocks(text, false)
}

fn extract_comment_blocks_with_empty_lines(text: &str) -> Vec<Vec<String>> {
    do_extract_comment_blocks(text, true)
}

fn do_extract_comment_blocks(text: &str, allow_blocks_with_empty_lins: bool) -> Vec<Vec<String>> {
    let mut res = Vec::new();

    let prefix = "// ";
    let lines = text.lines().map(str::trim_start);

    let mut block = vec![];
    for line in lines {
        if line == "//" && allow_blocks_with_empty_lins {
            block.push(String::new());
            continue;
        }

        let is_comment = line.starts_with(prefix);
        if is_comment {
            block.push(line[prefix.len()..].to_string());
        } else if !block.is_empty() {
            res.push(mem::replace(&mut block, Vec::new()));
        }
    }
    if !block.is_empty() {
        res.push(mem::replace(&mut block, Vec::new()))
    }
    res
}
<|endoftext|>


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

use app_units::Au;
use core_graphics::base::{kCGImageAlphaNoneSkipFirst, kCGImageAlphaPremultipliedLast};
use core_graphics::base::kCGBitmapByteOrder32Little;
use core_graphics::color_space::CGColorSpace;
use core_graphics::context::{CGContext, CGTextDrawingMode};
use core_graphics::data_provider::CGDataProvider;
use core_graphics::font::{CGFont, CGGlyph};
use core_graphics::geometry::{CGPoint, CGSize, CGRect};
use core_text::font::CTFont;
use core_text::font_descriptor::kCTFontDefaultOrientation;
use core_text;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use webrender_traits::{ColorU, FontKey, FontRenderMode, GlyphDimensions, GlyphOptions};

pub type NativeFontHandle = CGFont;

pub struct FontContext {
    cg_fonts: HashMap<FontKey, CGFont>,
    ct_fonts: HashMap<(FontKey, Au), CTFont>,
}

pub struct RasterizedGlyph {
    pub width: u32,
    pub height: u32,
    pub bytes: Vec<u8>,
}

impl RasterizedGlyph {
    pub fn blank() -> RasterizedGlyph {
        RasterizedGlyph {
            width: 0,
            height: 0,
            bytes: vec![],
        }
    }
}

struct GlyphMetrics {
    rasterized_left: i32,
    rasterized_descent: i32,
    rasterized_ascent: i32,
    rasterized_width: u32,
    rasterized_height: u32,
}

// According to the Skia source code, there's no public API to
// determine if subpixel AA is supported. So jrmuizel ported
// this function from Skia which is used to check if a glyph
// can be rendered with subpixel AA.
fn supports_subpixel_aa() -> bool {
    let mut cg_context = CGContext::create_bitmap_context(1, 1, 8, 4,
                                                          &CGColorSpace::create_device_rgb(),
                                                          kCGImageAlphaNoneSkipFirst |
                                                          kCGBitmapByteOrder32Little);
    let ct_font = core_text::font::new_from_name("Helvetica", 16.).unwrap();
    cg_context.set_should_smooth_fonts(true);
    cg_context.set_should_antialias(true);
    cg_context.set_allows_font_smoothing(true);
    cg_context.set_rgb_fill_color(1.0, 1.0, 1.0, 1.0);
    let point = CGPoint {x: -1., y: 0.};
    let glyph = '|' as CGGlyph;
    ct_font.draw_glyphs(&[glyph], &[point], cg_context.clone());
    let data = cg_context.data();
    data[0] != data[1] || data[1] != data[2]
}

fn get_glyph_metrics(ct_font: &CTFont, glyph: CGGlyph) -> GlyphMetrics {
    let bounds = ct_font.get_bounding_rects_for_glyphs(kCTFontDefaultOrientation, &[glyph]);

    let rasterized_left = bounds.origin.x.floor() as i32;
    let rasterized_width =
        (bounds.origin.x - (rasterized_left as f64) + bounds.size.width).ceil() as u32;
    let rasterized_descent = (-bounds.origin.y).ceil() as i32;
    let rasterized_ascent = (bounds.size.height + bounds.origin.y).ceil() as i32;
    let rasterized_height = (rasterized_descent + rasterized_ascent) as u32;

    GlyphMetrics {
        rasterized_ascent: rasterized_ascent,
        rasterized_descent: rasterized_descent,
        rasterized_left: rasterized_left,
        rasterized_width: rasterized_width,
        rasterized_height: rasterized_height,
    }
}

impl FontContext {
    pub fn new() -> FontContext {
        debug!("Test for subpixel AA support: {}", supports_subpixel_aa());

        FontContext {
            cg_fonts: HashMap::new(),
            ct_fonts: HashMap::new(),
        }
    }

    pub fn add_raw_font(&mut self, font_key: &FontKey, bytes: &[u8]) {
        if self.cg_fonts.contains_key(font_key) {
            return
        }

        let data_provider = CGDataProvider::from_buffer(bytes);
        let cg_font = match CGFont::from_data_provider(data_provider) {
            Err(_) => return,
            Ok(cg_font) => cg_font,
        };
        self.cg_fonts.insert((*font_key).clone(), cg_font);
    }

    pub fn add_native_font(&mut self, font_key: &FontKey, native_font_handle: CGFont) {
        if self.cg_fonts.contains_key(font_key) {
            return
        }

        self.cg_fonts.insert((*font_key).clone(), native_font_handle);
    }

    fn get_ct_font(&mut self,
                   font_key: FontKey,
                   size: Au) -> Option<CTFont> {
        match self.ct_fonts.entry(((font_key).clone(), size)) {
            Entry::Occupied(entry) => Some((*entry.get()).clone()),
            Entry::Vacant(entry) => {
                let cg_font = match self.cg_fonts.get(&font_key) {
                    None => return None,
                    Some(cg_font) => cg_font,
                };
                let ct_font = core_text::font::new_from_CGFont(
                        cg_font,
                        size.to_f64_px());
                entry.insert(ct_font.clone());
                Some(ct_font)
            }
        }
    }

    pub fn get_glyph_dimensions(&mut self,
                                font_key: FontKey,
                                size: Au,
                                character: u32) -> Option<GlyphDimensions> {
        self.get_ct_font(font_key, size).and_then(|ref ct_font| {
            let glyph = character as CGGlyph;
            let metrics = get_glyph_metrics(ct_font, glyph);
            if metrics.rasterized_width == 0 || metrics.rasterized_height == 0 {
                None
            } else {
                Some(GlyphDimensions {
                    left: metrics.rasterized_left,
                    top: metrics.rasterized_ascent,
                    width: metrics.rasterized_width as u32,
                    height: metrics.rasterized_height as u32,
                })
            }
        })
    }

    #[allow(dead_code)]
    fn print_glyph_data(&mut self, data: &Vec<u8>, width: usize, height: usize) {
        // Rust doesn't have step_by support on stable :(
        for i in 0..height {
            let current_height = i * width * 4;

            for pixel in data[current_height .. current_height + (width * 4)].chunks(4) {
                let b = pixel[0];
                let g = pixel[1];
                let r = pixel[2];
                let a = pixel[3];
                print!("({}, {}, {}, {}) ", r, g, b, a);
            }
            println!("");
        }
    }

    pub fn rasterize_glyph(&mut self,
                           font_key: FontKey,
                           size: Au,
                           color: ColorU,
                           character: u32,
                           render_mode: FontRenderMode,
                           glyph_options: Option<GlyphOptions>) -> Option<RasterizedGlyph> {
        match self.get_ct_font(font_key, size) {
            Some(ref ct_font) => {
                let glyph = character as CGGlyph;
                let metrics = get_glyph_metrics(ct_font, glyph);
                if metrics.rasterized_width == 0 || metrics.rasterized_height == 0 {
                    return Some(RasterizedGlyph::blank())
                }

                let context_flags = match render_mode {
                    FontRenderMode::Subpixel => kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst,
                    FontRenderMode::Alpha | FontRenderMode::Mono => kCGImageAlphaPremultipliedLast,
                };

                let mut cg_context = CGContext::create_bitmap_context(metrics.rasterized_width as usize,
                                                                      metrics.rasterized_height as usize,
                                                                      8,
                                                                      metrics.rasterized_width as usize * 4,
                                                                      &CGColorSpace::create_device_rgb(),
                                                                      context_flags);

                // Tested on mac OS Sierra, 10.12
                // For Mono + alpha, the only values that matter are the alpha values.
                // For subpixel, we need each individual rgb channel.
                // CG has two individual glyphs for subpixel AA (pre-10.11, this is not true):
                // 1) black text on white opaque background
                // 2) white text on black opaque background
                // Gecko does (1). Note, the BG must be opaque for subpixel AA to work.
                // See https://bugzilla.mozilla.org/show_bug.cgi?id=1230366#c35
                //
                // For grayscale / mono, CG still produces two glyphs, but it doesn't matter
                // 1) black text on transparent white - only alpha values filled
                // 2) white text on transparent black - channels == alpha
                //
                // If we draw grayscale/mono on an opaque background
                // the RGB channels are the alpha values from transparent backgrounds
                // with the alpha set as opaque.
                // At the end of all this, WR expects individual RGB channels and ignores alpha
                // for subpixel AA.
                // For alpha/mono, WR ignores all channels other than alpha.
                // Also note that WR expects text to be black bg with white text, so invert
                // when we draw the glyphs.
                let (antialias, smooth) = match render_mode {
                    FontRenderMode::Subpixel => (true, true),
                    FontRenderMode::Alpha => (true, false),
                    FontRenderMode::Mono => (false, false),
                };

                // These are always true in Gecko, even for non-AA fonts
                cg_context.set_allows_font_subpixel_positioning(true);
                cg_context.set_should_subpixel_position_fonts(true);

                cg_context.set_allows_font_smoothing(smooth);
                cg_context.set_should_smooth_fonts(smooth);
                cg_context.set_allows_antialiasing(antialias);
                cg_context.set_should_antialias(antialias);

                let rasterization_origin = CGPoint {
                    x: -metrics.rasterized_left as f64,
                    y: metrics.rasterized_descent as f64,
                };

                // Always draw black text on a white background
                // Fill the background
                cg_context.set_rgb_fill_color(1.0, 1.0, 1.0, 1.0);
                let rect = CGRect {
                    origin: CGPoint {
                        x: 0.0,
                        y: 0.0,
                    },
                    size: CGSize {
                        width: metrics.rasterized_width as f64,
                        height: metrics.rasterized_height as f64,
                    }
                };
                cg_context.fill_rect(rect);

                // Set the text color
                cg_context.set_rgb_fill_color(0.0, 0.0, 0.0, 1.0);
                cg_context.set_text_drawing_mode(CGTextDrawingMode::CGTextFill);
                ct_font.draw_glyphs(&[glyph], &[rasterization_origin], cg_context.clone());

                let mut rasterized_pixels = cg_context.data().to_vec();

                // We need to invert the pixels back since right now
                // transparent pixels are actually opaque white.
                for i in 0..metrics.rasterized_height {
                    let current_height = (i * metrics.rasterized_width * 4) as usize;
                    let end_row = current_height + (metrics.rasterized_width as usize * 4);

                    for mut pixel in rasterized_pixels[current_height .. end_row].chunks_mut(4) {
                        pixel[0] = 255 - pixel[0];
                        pixel[1] = 255 - pixel[1];
                        pixel[2] = 255 - pixel[2];

                        pixel[3] = match render_mode {
                            FontRenderMode::Subpixel => 255,
                            _ => {
                                assert_eq!(pixel[0], pixel[1]);
                                assert_eq!(pixel[0], pixel[2]);
                                pixel[0]
                            }
                        }; // end match
                    } // end row
                } // end height

                Some(RasterizedGlyph {
                    width: metrics.rasterized_width,
                    height: metrics.rasterized_height,
                    bytes: rasterized_pixels,
                })
            }
            None => {
                return Some(RasterizedGlyph::blank());
            }
        }
    }
}

<commit_msg>Auto merge of #774 - changm:cg-gamma, r=kvark<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use app_units::Au;
use core_graphics::base::{kCGImageAlphaNoneSkipFirst, kCGImageAlphaPremultipliedLast};
use core_graphics::base::kCGBitmapByteOrder32Little;
use core_graphics::color_space::CGColorSpace;
use core_graphics::context::{CGContext, CGTextDrawingMode};
use core_graphics::data_provider::CGDataProvider;
use core_graphics::font::{CGFont, CGGlyph};
use core_graphics::geometry::{CGPoint, CGSize, CGRect};
use core_text::font::CTFont;
use core_text::font_descriptor::kCTFontDefaultOrientation;
use core_text;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use webrender_traits::{ColorU, FontKey, FontRenderMode, GlyphDimensions, GlyphOptions};
use gamma_lut::{GammaLut, Color as ColorLut};

pub type NativeFontHandle = CGFont;

pub struct FontContext {
    cg_fonts: HashMap<FontKey, CGFont>,
    ct_fonts: HashMap<(FontKey, Au), CTFont>,
    gamma_lut: GammaLut,
}

pub struct RasterizedGlyph {
    pub width: u32,
    pub height: u32,
    pub bytes: Vec<u8>,
}

impl RasterizedGlyph {
    pub fn blank() -> RasterizedGlyph {
        RasterizedGlyph {
            width: 0,
            height: 0,
            bytes: vec![],
        }
    }
}

struct GlyphMetrics {
    rasterized_left: i32,
    rasterized_descent: i32,
    rasterized_ascent: i32,
    rasterized_width: u32,
    rasterized_height: u32,
}

// According to the Skia source code, there's no public API to
// determine if subpixel AA is supported. So jrmuizel ported
// this function from Skia which is used to check if a glyph
// can be rendered with subpixel AA.
fn supports_subpixel_aa() -> bool {
    let mut cg_context = CGContext::create_bitmap_context(1, 1, 8, 4,
                                                          &CGColorSpace::create_device_rgb(),
                                                          kCGImageAlphaNoneSkipFirst |
                                                          kCGBitmapByteOrder32Little);
    let ct_font = core_text::font::new_from_name("Helvetica", 16.).unwrap();
    cg_context.set_should_smooth_fonts(true);
    cg_context.set_should_antialias(true);
    cg_context.set_allows_font_smoothing(true);
    cg_context.set_rgb_fill_color(1.0, 1.0, 1.0, 1.0);
    let point = CGPoint {x: -1., y: 0.};
    let glyph = '|' as CGGlyph;
    ct_font.draw_glyphs(&[glyph], &[point], cg_context.clone());
    let data = cg_context.data();
    data[0] != data[1] || data[1] != data[2]
}

fn get_glyph_metrics(ct_font: &CTFont, glyph: CGGlyph) -> GlyphMetrics {
    let bounds = ct_font.get_bounding_rects_for_glyphs(kCTFontDefaultOrientation, &[glyph]);

    let rasterized_left = bounds.origin.x.floor() as i32;
    let rasterized_width =
        (bounds.origin.x - (rasterized_left as f64) + bounds.size.width).ceil() as u32;
    let rasterized_descent = (-bounds.origin.y).ceil() as i32;
    let rasterized_ascent = (bounds.size.height + bounds.origin.y).ceil() as i32;
    let rasterized_height = (rasterized_descent + rasterized_ascent) as u32;

    GlyphMetrics {
        rasterized_ascent: rasterized_ascent,
        rasterized_descent: rasterized_descent,
        rasterized_left: rasterized_left,
        rasterized_width: rasterized_width,
        rasterized_height: rasterized_height,
    }
}

impl FontContext {
    pub fn new() -> FontContext {
        debug!("Test for subpixel AA support: {}", supports_subpixel_aa());

        // Force CG to use sRGB color space to gamma correct.
        let contrast = 0.0;
        let gamma = 0.0;

        FontContext {
            cg_fonts: HashMap::new(),
            ct_fonts: HashMap::new(),
            gamma_lut: GammaLut::new(contrast, gamma, gamma),
        }
    }

    pub fn add_raw_font(&mut self, font_key: &FontKey, bytes: &[u8]) {
        if self.cg_fonts.contains_key(font_key) {
            return
        }

        let data_provider = CGDataProvider::from_buffer(bytes);
        let cg_font = match CGFont::from_data_provider(data_provider) {
            Err(_) => return,
            Ok(cg_font) => cg_font,
        };
        self.cg_fonts.insert((*font_key).clone(), cg_font);
    }

    pub fn add_native_font(&mut self, font_key: &FontKey, native_font_handle: CGFont) {
        if self.cg_fonts.contains_key(font_key) {
            return
        }

        self.cg_fonts.insert((*font_key).clone(), native_font_handle);
    }

    fn get_ct_font(&mut self,
                   font_key: FontKey,
                   size: Au) -> Option<CTFont> {
        match self.ct_fonts.entry(((font_key).clone(), size)) {
            Entry::Occupied(entry) => Some((*entry.get()).clone()),
            Entry::Vacant(entry) => {
                let cg_font = match self.cg_fonts.get(&font_key) {
                    None => return None,
                    Some(cg_font) => cg_font,
                };
                let ct_font = core_text::font::new_from_CGFont(
                        cg_font,
                        size.to_f64_px());
                entry.insert(ct_font.clone());
                Some(ct_font)
            }
        }
    }

    pub fn get_glyph_dimensions(&mut self,
                                font_key: FontKey,
                                size: Au,
                                character: u32) -> Option<GlyphDimensions> {
        self.get_ct_font(font_key, size).and_then(|ref ct_font| {
            let glyph = character as CGGlyph;
            let metrics = get_glyph_metrics(ct_font, glyph);
            if metrics.rasterized_width == 0 || metrics.rasterized_height == 0 {
                None
            } else {
                Some(GlyphDimensions {
                    left: metrics.rasterized_left,
                    top: metrics.rasterized_ascent,
                    width: metrics.rasterized_width as u32,
                    height: metrics.rasterized_height as u32,
                })
            }
        })
    }

    // Assumes the pixels here are linear values from CG
    fn gamma_correct_pixels(&self, pixels: &mut Vec<u8>, width: usize,
                            height: usize, render_mode: FontRenderMode,
                            color: ColorU) {
        // Then convert back to gamma corrected values.
        let color_lut = ColorLut::new(color.r,
                                     color.g,
                                     color.b,
                                     color.a);
        match render_mode {
            FontRenderMode::Alpha => {
                self.gamma_lut.preblend_grayscale_bgra(pixels, width,
                                                       height, color_lut);
            },
            FontRenderMode::Subpixel => {
                self.gamma_lut.preblend_bgra(pixels, width, height, color_lut);
            },
            _ => {} // Again, give mono untouched since only the alpha matters.
        }
    }

    #[allow(dead_code)]
    fn print_glyph_data(&mut self, data: &Vec<u8>, width: usize, height: usize) {
        // Rust doesn't have step_by support on stable :(
        println!("Width is: {:?} height: {:?}", width, height);
        for i in 0..height {
            let current_height = i * width * 4;

            for pixel in data[current_height .. current_height + (width * 4)].chunks(4) {
                let b = pixel[0];
                let g = pixel[1];
                let r = pixel[2];
                let a = pixel[3];
                print!("({}, {}, {}, {}) ", r, g, b, a);
            }
            println!("");
        }
    }

    pub fn rasterize_glyph(&mut self,
                           font_key: FontKey,
                           size: Au,
                           color: ColorU,
                           character: u32,
                           render_mode: FontRenderMode,
                           glyph_options: Option<GlyphOptions>) -> Option<RasterizedGlyph> {
        match self.get_ct_font(font_key, size) {
            Some(ref ct_font) => {
                let glyph = character as CGGlyph;
                let metrics = get_glyph_metrics(ct_font, glyph);
                if metrics.rasterized_width == 0 || metrics.rasterized_height == 0 {
                    return Some(RasterizedGlyph::blank())
                }

                let context_flags = match render_mode {
                    FontRenderMode::Subpixel => kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst,
                    FontRenderMode::Alpha | FontRenderMode::Mono => kCGImageAlphaPremultipliedLast,
                };

                let mut cg_context = CGContext::create_bitmap_context(metrics.rasterized_width as usize,
                                                                      metrics.rasterized_height as usize,
                                                                      8,
                                                                      metrics.rasterized_width as usize * 4,
                                                                      &CGColorSpace::create_device_rgb(),
                                                                      context_flags);

                // Tested on mac OS Sierra, 10.12
                // For Mono + alpha, the only values that matter are the alpha values.
                // For subpixel, we need each individual rgb channel.
                // CG has two individual glyphs for subpixel AA (pre-10.11, this is not true):
                // 1) black text on white opaque background
                // 2) white text on black opaque background
                // Gecko does (1). Note, the BG must be opaque for subpixel AA to work.
                // See https://bugzilla.mozilla.org/show_bug.cgi?id=1230366#c35
                //
                // For grayscale / mono, CG still produces two glyphs, but it doesn't matter
                // 1) black text on transparent white - only alpha values filled
                // 2) white text on transparent black - channels == alpha
                //
                // If we draw grayscale/mono on an opaque background
                // the RGB channels are the alpha values from transparent backgrounds
                // with the alpha set as opaque.
                // At the end of all this, WR expects individual RGB channels and ignores alpha
                // for subpixel AA.
                // For alpha/mono, WR ignores all channels other than alpha.
                // Also note that WR expects text to be black bg with white text, so invert
                // when we draw the glyphs.
                let (antialias, smooth) = match render_mode {
                    FontRenderMode::Subpixel => (true, true),
                    FontRenderMode::Alpha => (true, false),
                    FontRenderMode::Mono => (false, false),
                };

                // These are always true in Gecko, even for non-AA fonts
                cg_context.set_allows_font_subpixel_positioning(true);
                cg_context.set_should_subpixel_position_fonts(true);

                cg_context.set_allows_font_smoothing(smooth);
                cg_context.set_should_smooth_fonts(smooth);
                cg_context.set_allows_antialiasing(antialias);
                cg_context.set_should_antialias(antialias);

                let rasterization_origin = CGPoint {
                    x: -metrics.rasterized_left as f64,
                    y: metrics.rasterized_descent as f64,
                };

                // Always draw black text on a white background
                // Fill the background
                cg_context.set_rgb_fill_color(1.0, 1.0, 1.0, 1.0);
                let rect = CGRect {
                    origin: CGPoint {
                        x: 0.0,
                        y: 0.0,
                    },
                    size: CGSize {
                        width: metrics.rasterized_width as f64,
                        height: metrics.rasterized_height as f64,
                    }
                };
                cg_context.fill_rect(rect);

                // Set the text color
                cg_context.set_rgb_fill_color(0.0, 0.0, 0.0, 1.0);
                cg_context.set_text_drawing_mode(CGTextDrawingMode::CGTextFill);
                ct_font.draw_glyphs(&[glyph], &[rasterization_origin], cg_context.clone());

                let mut rasterized_pixels = cg_context.data().to_vec();

                // Convert to linear space for subpixel AA.
                // We explicitly do not do this for grayscale AA
                if render_mode == FontRenderMode::Subpixel {
                    self.gamma_lut.coregraphics_convert_to_linear_bgra(&mut rasterized_pixels,
                                                                       metrics.rasterized_width as usize,
                                                                       metrics.rasterized_height as usize);
                }

                // We need to invert the pixels back since right now
                // transparent pixels are actually opaque white.
                for i in 0..metrics.rasterized_height {
                    let current_height = (i * metrics.rasterized_width * 4) as usize;
                    let end_row = current_height + (metrics.rasterized_width as usize * 4);

                    for mut pixel in rasterized_pixels[current_height .. end_row].chunks_mut(4) {
                        pixel[0] = 255 - pixel[0];
                        pixel[1] = 255 - pixel[1];
                        pixel[2] = 255 - pixel[2];

                        pixel[3] = match render_mode {
                            FontRenderMode::Subpixel => 255,
                            _ => {
                                assert_eq!(pixel[0], pixel[1]);
                                assert_eq!(pixel[0], pixel[2]);
                                pixel[0]
                            }
                        }; // end match
                    } // end row
                } // end height

                self.gamma_correct_pixels(&mut rasterized_pixels,
                                          metrics.rasterized_width as usize,
                                          metrics.rasterized_height as usize,
                                          render_mode,
                                          color);

                Some(RasterizedGlyph {
                    width: metrics.rasterized_width,
                    height: metrics.rasterized_height,
                    bytes: rasterized_pixels,
                })
            }
            None => {
                return Some(RasterizedGlyph::blank());
            }
        }
    }
}

<|endoftext|>


<commit_before>//! Elements of the WebAssembly binary format.

use std::error;
use std::fmt;
use std::io;

macro_rules! buffered_read {
	($buffer_size: expr, $length: expr, $reader: expr) => {
		{
			let mut vec_buf = Vec::new();
			let mut total_read = 0;
			let mut buf = [0u8; $buffer_size];
			while total_read < $length {
				let next_to_read = if $length - total_read > $buffer_size { $buffer_size } else { $length - total_read };
				$reader.read_exact(&mut buf[0..next_to_read])?;
				vec_buf.extend_from_slice(&buf[0..next_to_read]);
				total_read += next_to_read;
			}
			vec_buf
		}
	}
}

mod primitives;
mod module;
mod section;
mod types;
mod import_entry;
mod export_entry;
mod global_entry;
mod ops;
mod func;
mod segment;
mod index_map;
mod name_section;

pub use self::module::{Module, peek_size, ImportCountType};
pub use self::section::{
	Section, FunctionSection, CodeSection, MemorySection, DataSection,
	ImportSection, ExportSection, GlobalSection, TypeSection, ElementSection,
	TableSection, CustomSection,
};
pub use self::import_entry::{ImportEntry, ResizableLimits, MemoryType, TableType, GlobalType, External};
pub use self::export_entry::{ExportEntry, Internal};
pub use self::global_entry::GlobalEntry;
pub use self::primitives::{
	VarUint32, VarUint7, Uint8, VarUint1, VarInt7, Uint32, VarInt32, VarInt64,
	Uint64, VarUint64, CountedList, CountedWriter, CountedListWriter,
};
pub use self::types::{Type, ValueType, BlockType, FunctionType, TableElementType};
pub use self::ops::{Opcode, Opcodes, InitExpr};
pub use self::func::{Func, FuncBody, Local};
pub use self::segment::{ElementSegment, DataSegment};
pub use self::index_map::IndexMap;
pub use self::name_section::{
	NameMap, NameSection, ModuleNameSection, FunctionNameSection,
	LocalNameSection,
};

/// Deserialization from serial i/o
pub trait Deserialize : Sized {
	/// Serialization error produced by deserialization routine.
	type Error: From<io::Error>;
	/// Deserialize type from serial i/o
	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error>;
}

/// Serialization to serial i/o
pub trait Serialize {
	/// Serialization error produced by serialization routine.
	type Error: From<io::Error>;
	/// Serialize type to serial i/o
	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error>;
}

/// Deserialization/serialization error
#[derive(Debug, Clone)]
pub enum Error {
	/// Unexpected end of input
	UnexpectedEof,
	/// Invalid magic
	InvalidMagic,
	/// Unsupported version
	UnsupportedVersion(u32),
	/// Inconsistence between declared and actual length
	InconsistentLength {
		/// Expected length of the definition
		expected: usize,
		/// Actual length of the definition
		actual: usize
	},
	/// Other static error
	Other(&'static str),
	/// Other allocated error
	HeapOther(String),
	/// Invalid/unknown value type declaration
	UnknownValueType(i8),
	/// Invalid/unknown table element type declaration
	UnknownTableElementType(i8),
	/// Non-utf8 string
	NonUtf8String,
	/// Unknown external kind code
	UnknownExternalKind(u8),
	/// Unknown internal kind code
	UnknownInternalKind(u8),
	/// Unknown opcode encountered
	UnknownOpcode(u8),
	/// Invalid VarUint1 value
	InvalidVarUint1(u8),
	/// Invalid VarInt32 value
	InvalidVarInt32,
	/// Invalid VarInt64 value
	InvalidVarInt64,
	/// Invalid VarUint32 value
	InvalidVarUint32,
	/// Invalid VarUint64 value
	InvalidVarUint64,
	/// Inconsistent metadata
	InconsistentMetadata,
	/// Invalid section id
	InvalidSectionId(u8),
	/// Sections are out of order
	SectionsOutOfOrder,
	/// Duplicated sections
	DuplicatedSections(u8),
	/// Invalid memory reference (should be 0)
	InvalidMemoryReference(u8),
	/// Invalid table reference (should be 0)
	InvalidTableReference(u8),
}

impl fmt::Display for Error {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		match *self {
			Error::UnexpectedEof => write!(f, "Unexpected end of input"),
			Error::InvalidMagic => write!(f, "Invalid magic number at start of file"),
			Error::UnsupportedVersion(v) => write!(f, "Unsupported wasm version {}", v),
			Error::InconsistentLength { expected, actual } => {
				write!(f, "Expected length {}, found {}", expected, actual)
			}
			Error::Other(msg) => write!(f, "{}", msg),
			Error::HeapOther(ref msg) => write!(f, "{}", msg),
			Error::UnknownValueType(ty) => write!(f, "Invalid or unknown value type {}", ty),
			Error::UnknownTableElementType(ty) => write!(f, "Unknown table element type {}", ty),
			Error::NonUtf8String => write!(f, "Non-UTF-8 string"),
			Error::UnknownExternalKind(kind) => write!(f, "Unknown external kind {}", kind),
			Error::UnknownInternalKind(kind) => write!(f, "Unknown internal kind {}", kind),
			Error::UnknownOpcode(opcode) => write!(f, "Unknown opcode {}", opcode),
			Error::InvalidVarUint1(val) => write!(f, "Not an unsigned 1-bit integer: {}", val),
			Error::InvalidVarInt32 => write!(f, "Not a signed 32-bit integer"),
			Error::InvalidVarUint32 => write!(f, "Not an unsigned 32-bit integer"),
			Error::InvalidVarInt64 => write!(f, "Not a signed 64-bit integer"),
			Error::InvalidVarUint64 => write!(f, "Not an unsigned 64-bit integer"),
			Error::InconsistentMetadata =>  write!(f, "Inconsistent metadata"),
			Error::InvalidSectionId(ref id) =>  write!(f, "Invalid section id: {}", id),
			Error::SectionsOutOfOrder =>  write!(f, "Sections out of order"),
			Error::DuplicatedSections(ref id) =>  write!(f, "Dupliated sections ({})", id),
			Error::InvalidMemoryReference(ref mem_ref) =>  write!(f, "Invalid memory reference ({})", mem_ref),
			Error::InvalidTableReference(ref table_ref) =>  write!(f, "Invalid table reference ({})", table_ref),
		}
	}
}

impl error::Error for Error {
	fn description(&self) -> &str {
		match *self {
			Error::UnexpectedEof => "Unexpected end of input",
			Error::InvalidMagic => "Invalid magic number at start of file",
			Error::UnsupportedVersion(_) => "Unsupported wasm version",
			Error::InconsistentLength { .. } => "Inconsistent length",
			Error::Other(msg) => msg,
			Error::HeapOther(ref msg) => &msg[..],
			Error::UnknownValueType(_) => "Invalid or unknown value type",
			Error::UnknownTableElementType(_) => "Unknown table element type",
			Error::NonUtf8String => "Non-UTF-8 string",
			Error::UnknownExternalKind(_) => "Unknown external kind",
			Error::UnknownInternalKind(_) => "Unknown internal kind",
			Error::UnknownOpcode(_) => "Unknown opcode",
			Error::InvalidVarUint1(_) => "Not an unsigned 1-bit integer",
			Error::InvalidVarInt32 => "Not a signed 32-bit integer",
			Error::InvalidVarUint32 => "Not an unsigned 32-bit integer",
			Error::InvalidVarInt64 => "Not a signed 64-bit integer",
			Error::InvalidVarUint64 => "Not an unsigned 64-bit integer",
			Error::InconsistentMetadata => "Inconsistent metadata",
			Error::InvalidSectionId(_) =>  "Invalid section id",
			Error::SectionsOutOfOrder =>  "Sections out of order",
			Error::DuplicatedSections(_) =>  "Duplicated section",
			Error::InvalidMemoryReference(_) =>  "Invalid memory reference",
			Error::InvalidTableReference(_) =>  "Invalid table reference",
		}
	}
}

impl From<io::Error> for Error {
	fn from(err: io::Error) -> Self {
		Error::HeapOther(format!("I/O Error: {}", err))
	}
}

/// Unparsed part of the module/section
pub struct Unparsed(pub Vec<u8>);

impl Deserialize for Unparsed {
	type Error = Error;

	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
		let len = VarUint32::deserialize(reader)?.into();
		let mut vec = vec![0u8; len];
		reader.read_exact(&mut vec[..])?;
		Ok(Unparsed(vec))
	}
}

impl From<Unparsed> for Vec<u8> {
	fn from(u: Unparsed) -> Vec<u8> {
		u.0
	}
}

/// Deserialize module from file.
pub fn deserialize_file<P: AsRef<::std::path::Path>>(p: P) -> Result<Module, Error> {
	use std::io::Read;

	let mut contents = Vec::new();
	::std::fs::File::open(p)?.read_to_end(&mut contents)?;

	deserialize_buffer(&contents)
}

/// Deserialize deserializable type from buffer.
pub fn deserialize_buffer<T: Deserialize>(contents: &[u8]) -> Result<T, T::Error> {
	let mut reader = io::Cursor::new(contents);
	let result = T::deserialize(&mut reader)?;
	if reader.position() != contents.len() as u64 {
		return Err(io::Error::from(io::ErrorKind::InvalidData).into())
	}
	Ok(result)
}

/// Create buffer with serialized value.
pub fn serialize<T: Serialize>(val: T) -> Result<Vec<u8>, T::Error> {
	let mut buf = Vec::new();
	val.serialize(&mut buf)?;
	Ok(buf)
}

/// Serialize module to the file
pub fn serialize_to_file<P: AsRef<::std::path::Path>>(p: P, module: Module) -> Result<(), Error>
{
	let mut io = ::std::fs::File::create(p)?;
	module.serialize(&mut io)
}
<commit_msg>add doc comment<commit_after>//! Elements of the WebAssembly binary format.

use std::error;
use std::fmt;
use std::io;

macro_rules! buffered_read {
	($buffer_size: expr, $length: expr, $reader: expr) => {
		{
			let mut vec_buf = Vec::new();
			let mut total_read = 0;
			let mut buf = [0u8; $buffer_size];
			while total_read < $length {
				let next_to_read = if $length - total_read > $buffer_size { $buffer_size } else { $length - total_read };
				$reader.read_exact(&mut buf[0..next_to_read])?;
				vec_buf.extend_from_slice(&buf[0..next_to_read]);
				total_read += next_to_read;
			}
			vec_buf
		}
	}
}

mod primitives;
mod module;
mod section;
mod types;
mod import_entry;
mod export_entry;
mod global_entry;
mod ops;
mod func;
mod segment;
mod index_map;
mod name_section;

pub use self::module::{Module, peek_size, ImportCountType};
pub use self::section::{
	Section, FunctionSection, CodeSection, MemorySection, DataSection,
	ImportSection, ExportSection, GlobalSection, TypeSection, ElementSection,
	TableSection, CustomSection,
};
pub use self::import_entry::{ImportEntry, ResizableLimits, MemoryType, TableType, GlobalType, External};
pub use self::export_entry::{ExportEntry, Internal};
pub use self::global_entry::GlobalEntry;
pub use self::primitives::{
	VarUint32, VarUint7, Uint8, VarUint1, VarInt7, Uint32, VarInt32, VarInt64,
	Uint64, VarUint64, CountedList, CountedWriter, CountedListWriter,
};
pub use self::types::{Type, ValueType, BlockType, FunctionType, TableElementType};
pub use self::ops::{Opcode, Opcodes, InitExpr};
pub use self::func::{Func, FuncBody, Local};
pub use self::segment::{ElementSegment, DataSegment};
pub use self::index_map::IndexMap;
pub use self::name_section::{
	NameMap, NameSection, ModuleNameSection, FunctionNameSection,
	LocalNameSection,
};

/// Deserialization from serial i/o
pub trait Deserialize : Sized {
	/// Serialization error produced by deserialization routine.
	type Error: From<io::Error>;
	/// Deserialize type from serial i/o
	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error>;
}

/// Serialization to serial i/o. Takes self by value to consume less memory
/// (parity-wasm IR is being partially freed by filling the result buffer).
pub trait Serialize {
	/// Serialization error produced by serialization routine.
	type Error: From<io::Error>;
	/// Serialize type to serial i/o
	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error>;
}

/// Deserialization/serialization error
#[derive(Debug, Clone)]
pub enum Error {
	/// Unexpected end of input
	UnexpectedEof,
	/// Invalid magic
	InvalidMagic,
	/// Unsupported version
	UnsupportedVersion(u32),
	/// Inconsistence between declared and actual length
	InconsistentLength {
		/// Expected length of the definition
		expected: usize,
		/// Actual length of the definition
		actual: usize
	},
	/// Other static error
	Other(&'static str),
	/// Other allocated error
	HeapOther(String),
	/// Invalid/unknown value type declaration
	UnknownValueType(i8),
	/// Invalid/unknown table element type declaration
	UnknownTableElementType(i8),
	/// Non-utf8 string
	NonUtf8String,
	/// Unknown external kind code
	UnknownExternalKind(u8),
	/// Unknown internal kind code
	UnknownInternalKind(u8),
	/// Unknown opcode encountered
	UnknownOpcode(u8),
	/// Invalid VarUint1 value
	InvalidVarUint1(u8),
	/// Invalid VarInt32 value
	InvalidVarInt32,
	/// Invalid VarInt64 value
	InvalidVarInt64,
	/// Invalid VarUint32 value
	InvalidVarUint32,
	/// Invalid VarUint64 value
	InvalidVarUint64,
	/// Inconsistent metadata
	InconsistentMetadata,
	/// Invalid section id
	InvalidSectionId(u8),
	/// Sections are out of order
	SectionsOutOfOrder,
	/// Duplicated sections
	DuplicatedSections(u8),
	/// Invalid memory reference (should be 0)
	InvalidMemoryReference(u8),
	/// Invalid table reference (should be 0)
	InvalidTableReference(u8),
}

impl fmt::Display for Error {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		match *self {
			Error::UnexpectedEof => write!(f, "Unexpected end of input"),
			Error::InvalidMagic => write!(f, "Invalid magic number at start of file"),
			Error::UnsupportedVersion(v) => write!(f, "Unsupported wasm version {}", v),
			Error::InconsistentLength { expected, actual } => {
				write!(f, "Expected length {}, found {}", expected, actual)
			}
			Error::Other(msg) => write!(f, "{}", msg),
			Error::HeapOther(ref msg) => write!(f, "{}", msg),
			Error::UnknownValueType(ty) => write!(f, "Invalid or unknown value type {}", ty),
			Error::UnknownTableElementType(ty) => write!(f, "Unknown table element type {}", ty),
			Error::NonUtf8String => write!(f, "Non-UTF-8 string"),
			Error::UnknownExternalKind(kind) => write!(f, "Unknown external kind {}", kind),
			Error::UnknownInternalKind(kind) => write!(f, "Unknown internal kind {}", kind),
			Error::UnknownOpcode(opcode) => write!(f, "Unknown opcode {}", opcode),
			Error::InvalidVarUint1(val) => write!(f, "Not an unsigned 1-bit integer: {}", val),
			Error::InvalidVarInt32 => write!(f, "Not a signed 32-bit integer"),
			Error::InvalidVarUint32 => write!(f, "Not an unsigned 32-bit integer"),
			Error::InvalidVarInt64 => write!(f, "Not a signed 64-bit integer"),
			Error::InvalidVarUint64 => write!(f, "Not an unsigned 64-bit integer"),
			Error::InconsistentMetadata =>  write!(f, "Inconsistent metadata"),
			Error::InvalidSectionId(ref id) =>  write!(f, "Invalid section id: {}", id),
			Error::SectionsOutOfOrder =>  write!(f, "Sections out of order"),
			Error::DuplicatedSections(ref id) =>  write!(f, "Dupliated sections ({})", id),
			Error::InvalidMemoryReference(ref mem_ref) =>  write!(f, "Invalid memory reference ({})", mem_ref),
			Error::InvalidTableReference(ref table_ref) =>  write!(f, "Invalid table reference ({})", table_ref),
		}
	}
}

impl error::Error for Error {
	fn description(&self) -> &str {
		match *self {
			Error::UnexpectedEof => "Unexpected end of input",
			Error::InvalidMagic => "Invalid magic number at start of file",
			Error::UnsupportedVersion(_) => "Unsupported wasm version",
			Error::InconsistentLength { .. } => "Inconsistent length",
			Error::Other(msg) => msg,
			Error::HeapOther(ref msg) => &msg[..],
			Error::UnknownValueType(_) => "Invalid or unknown value type",
			Error::UnknownTableElementType(_) => "Unknown table element type",
			Error::NonUtf8String => "Non-UTF-8 string",
			Error::UnknownExternalKind(_) => "Unknown external kind",
			Error::UnknownInternalKind(_) => "Unknown internal kind",
			Error::UnknownOpcode(_) => "Unknown opcode",
			Error::InvalidVarUint1(_) => "Not an unsigned 1-bit integer",
			Error::InvalidVarInt32 => "Not a signed 32-bit integer",
			Error::InvalidVarUint32 => "Not an unsigned 32-bit integer",
			Error::InvalidVarInt64 => "Not a signed 64-bit integer",
			Error::InvalidVarUint64 => "Not an unsigned 64-bit integer",
			Error::InconsistentMetadata => "Inconsistent metadata",
			Error::InvalidSectionId(_) =>  "Invalid section id",
			Error::SectionsOutOfOrder =>  "Sections out of order",
			Error::DuplicatedSections(_) =>  "Duplicated section",
			Error::InvalidMemoryReference(_) =>  "Invalid memory reference",
			Error::InvalidTableReference(_) =>  "Invalid table reference",
		}
	}
}

impl From<io::Error> for Error {
	fn from(err: io::Error) -> Self {
		Error::HeapOther(format!("I/O Error: {}", err))
	}
}

/// Unparsed part of the module/section
pub struct Unparsed(pub Vec<u8>);

impl Deserialize for Unparsed {
	type Error = Error;

	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
		let len = VarUint32::deserialize(reader)?.into();
		let mut vec = vec![0u8; len];
		reader.read_exact(&mut vec[..])?;
		Ok(Unparsed(vec))
	}
}

impl From<Unparsed> for Vec<u8> {
	fn from(u: Unparsed) -> Vec<u8> {
		u.0
	}
}

/// Deserialize module from file.
pub fn deserialize_file<P: AsRef<::std::path::Path>>(p: P) -> Result<Module, Error> {
	use std::io::Read;

	let mut contents = Vec::new();
	::std::fs::File::open(p)?.read_to_end(&mut contents)?;

	deserialize_buffer(&contents)
}

/// Deserialize deserializable type from buffer.
pub fn deserialize_buffer<T: Deserialize>(contents: &[u8]) -> Result<T, T::Error> {
	let mut reader = io::Cursor::new(contents);
	let result = T::deserialize(&mut reader)?;
	if reader.position() != contents.len() as u64 {
		return Err(io::Error::from(io::ErrorKind::InvalidData).into())
	}
	Ok(result)
}

/// Create buffer with serialized value.
pub fn serialize<T: Serialize>(val: T) -> Result<Vec<u8>, T::Error> {
	let mut buf = Vec::new();
	val.serialize(&mut buf)?;
	Ok(buf)
}

/// Serialize module to the file
pub fn serialize_to_file<P: AsRef<::std::path::Path>>(p: P, module: Module) -> Result<(), Error>
{
	let mut io = ::std::fs::File::create(p)?;
	module.serialize(&mut io)
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use ast::*;
use rich_number::RichNumber;
use prelude::setup_prelude;

pub struct EvalContext {
    symbol_table: HashMap<String, ContextItem>,
}

const FUNCTION_PRECEDENCE: u8 = 9;
const LOWEST_PRECEDENCE: u8 = 0;
const HIGHEST_PRECEDENCE: u8 = 9;

#[derive(PartialEq, Debug, Clone)]
pub enum ContextItem {
    Number(RichNumber),
    Definition {
        // number from 0 to 9 where 9 is the highest precedence
        precedence: u8,
        fixity: Fixity,
        function: Function,
    },
    Constant(String),
    Nothing,
}

#[derive(Eq, PartialEq, Debug, Clone)]
pub enum Fixity {
    Prefix,
    Infix,
    Postfix,
}

impl ContextItem {
    pub fn unwrap_number(self) -> RichNumber {
        match self {
            ContextItem::Number(num) => num,
            _ => panic!("Expected to unwrap a number"),
        }
    }
}

#[derive(PartialEq, Debug)]
pub enum EvalError {
    NotFound(String),
}

pub type EvalResult = Result<ContextItem, EvalError>;

impl EvalContext {
    pub fn new() -> EvalContext {
        EvalContext {
            symbol_table: HashMap::new(),
        }
    }

    pub fn prelude() -> EvalContext {
        let mut context = EvalContext::new();
        setup_prelude(&mut context);
        context
    }

    /// Gets a single value without evaluating it from the current context
    pub fn get(&self, name: &str) -> Option<ContextItem> {
        self.symbol_table.get(name).map(|item| (*item).clone())
    }

    /// Convenience method for setting a number in the context
    pub fn set_number(&mut self, name: &str, value: RichNumber) {
        self.set(name, ContextItem::Number(value))
    }

    /// Defines a function in the context
    pub fn define(&mut self, name: &str, fixity: Fixity, precedence: u8, function: Function) {
        debug_assert!(precedence >= LOWEST_PRECEDENCE && precedence <= HIGHEST_PRECEDENCE);

        self.set(name, ContextItem::Definition {
            fixity: fixity,
            precedence: precedence,
            function: function,
        })
    }

    /// Creates a constant value
    pub fn set_constant(&mut self, name: &str, value: String) {
        self.set(name, ContextItem::Constant(value));
    }

    /// Adds to the current context (silently replaces if already present)
    pub fn set(&mut self, name: &str, value: ContextItem) {
        self.symbol_table.insert(name.to_owned(), value);
    }

    pub fn apply(&mut self, statement: Statement) -> EvalResult {
        match statement {
            Statement::NamedFunction {name, definition} => {
                self.define(&name, Fixity::Prefix, FUNCTION_PRECEDENCE, definition);
                Ok(ContextItem::Nothing)
            },
            Statement::AnonymousFunction(function) => Ok(ContextItem::Nothing),
            Statement::Assignment {name, value} => {
                let value = try!(self.evaluate(value));
                self.set(&name, value);
                Ok(ContextItem::Nothing)
            },
            Statement::Expression(value) => self.evaluate(value),
        }
    }

    pub fn evaluate(&mut self, expr: Expr) -> EvalResult {
        unimplemented!();
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use ast::*;
    use api::parse;
    use rich_number::RichNumber;

    #[test]
    fn get_set_in_context() {
        let mut context = EvalContext::new();
        assert_eq!(context.get("a"), None);

        let value = RichNumber::from(2f64);
        context.set_number("a", value.clone());
        assert_eq!(context.get("a").map(|n| n.unwrap_number()), Some(value));
    }

    #[test]
    fn define_variable() {
        let mut context = EvalContext::new();
        apply_string(&mut context, "x = 3");

        assert_eq!(context.get("x").map(|n| n.unwrap_number()), Some(RichNumber::from(3f64)));
    }

    fn apply_string(mut context: &mut EvalContext, string: &str) {
        apply_program(context, parse(string).unwrap());
    }

    fn apply_program(mut context: &mut EvalContext, program: Program) {
        for statement in program {
            context.apply(statement);
        }
    }
}

<commit_msg>Avoiding using a magic literal<commit_after>use std::collections::HashMap;

use ast::*;
use rich_number::RichNumber;
use prelude::setup_prelude;

pub struct EvalContext {
    symbol_table: HashMap<String, ContextItem>,
}

const LOWEST_PRECEDENCE: u8 = 0;
const HIGHEST_PRECEDENCE: u8 = 9;
const FUNCTION_PRECEDENCE: u8 = HIGHEST_PRECEDENCE;

#[derive(PartialEq, Debug, Clone)]
pub enum ContextItem {
    Number(RichNumber),
    Definition {
        // number from 0 to 9 where 9 is the highest precedence
        precedence: u8,
        fixity: Fixity,
        function: Function,
    },
    Constant(String),
    Nothing,
}

#[derive(Eq, PartialEq, Debug, Clone)]
pub enum Fixity {
    Prefix,
    Infix,
    Postfix,
}

impl ContextItem {
    pub fn unwrap_number(self) -> RichNumber {
        match self {
            ContextItem::Number(num) => num,
            _ => panic!("Expected to unwrap a number"),
        }
    }
}

#[derive(PartialEq, Debug)]
pub enum EvalError {
    NotFound(String),
}

pub type EvalResult = Result<ContextItem, EvalError>;

impl EvalContext {
    pub fn new() -> EvalContext {
        EvalContext {
            symbol_table: HashMap::new(),
        }
    }

    pub fn prelude() -> EvalContext {
        let mut context = EvalContext::new();
        setup_prelude(&mut context);
        context
    }

    /// Gets a single value without evaluating it from the current context
    pub fn get(&self, name: &str) -> Option<ContextItem> {
        self.symbol_table.get(name).map(|item| (*item).clone())
    }

    /// Convenience method for setting a number in the context
    pub fn set_number(&mut self, name: &str, value: RichNumber) {
        self.set(name, ContextItem::Number(value))
    }

    /// Defines a function in the context
    pub fn define(&mut self, name: &str, fixity: Fixity, precedence: u8, function: Function) {
        debug_assert!(precedence >= LOWEST_PRECEDENCE && precedence <= HIGHEST_PRECEDENCE);

        self.set(name, ContextItem::Definition {
            fixity: fixity,
            precedence: precedence,
            function: function,
        })
    }

    /// Creates a constant value
    pub fn set_constant(&mut self, name: &str, value: String) {
        self.set(name, ContextItem::Constant(value));
    }

    /// Adds to the current context (silently replaces if already present)
    pub fn set(&mut self, name: &str, value: ContextItem) {
        self.symbol_table.insert(name.to_owned(), value);
    }

    pub fn apply(&mut self, statement: Statement) -> EvalResult {
        match statement {
            Statement::NamedFunction {name, definition} => {
                self.define(&name, Fixity::Prefix, FUNCTION_PRECEDENCE, definition);
                Ok(ContextItem::Nothing)
            },
            Statement::AnonymousFunction(function) => Ok(ContextItem::Nothing),
            Statement::Assignment {name, value} => {
                let value = try!(self.evaluate(value));
                self.set(&name, value);
                Ok(ContextItem::Nothing)
            },
            Statement::Expression(value) => self.evaluate(value),
        }
    }

    pub fn evaluate(&mut self, expr: Expr) -> EvalResult {
        unimplemented!();
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use ast::*;
    use api::parse;
    use rich_number::RichNumber;

    #[test]
    fn get_set_in_context() {
        let mut context = EvalContext::new();
        assert_eq!(context.get("a"), None);

        let value = RichNumber::from(2f64);
        context.set_number("a", value.clone());
        assert_eq!(context.get("a").map(|n| n.unwrap_number()), Some(value));
    }

    #[test]
    fn define_variable() {
        let mut context = EvalContext::new();
        apply_string(&mut context, "x = 3");

        assert_eq!(context.get("x").map(|n| n.unwrap_number()), Some(RichNumber::from(3f64)));
    }

    fn apply_string(mut context: &mut EvalContext, string: &str) {
        apply_program(context, parse(string).unwrap());
    }

    fn apply_program(mut context: &mut EvalContext, program: Program) {
        for statement in program {
            context.apply(statement);
        }
    }
}

<|endoftext|>


<commit_before>use kay::{Actor, Recipient, Fate};
use kay::swarm::{Swarm, CreateWith};
use compact::{CVec, CDict};
use descartes::{V2, N, P2, FiniteCurve};

use super::super::construction::materialized_reality::MaterializedReality;
use super::lane_stroke::LaneStroke;
use super::plan::{PlanDelta, PlanResultDelta, BuiltStrokes, LaneStrokeRef};

mod apply_intent;
use self::apply_intent::apply_intent;
mod rendering;
mod stroke_canvas;
mod selectable;
use self::selectable::Selectable;
mod deselecter;
use self::deselecter::Deselecter;
mod draggable;
use self::draggable::Draggable;
mod addable;
use self::addable::Addable;
mod interaction;
use self::interaction::Interaction;

#[derive(Compact, Clone, Default)]
pub struct PlanStep {
    plan_delta: PlanDelta,
    selections: CDict<SelectableStrokeRef, (N, N)>,
    intent: Intent,
}

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub enum SelectableStrokeRef {
    New(usize),
    Built(LaneStrokeRef),
}

impl SelectableStrokeRef {
    pub fn get_stroke<'a>(&self,
                          plan_delta: &'a PlanDelta,
                          still_built_strokes: &'a BuiltStrokes)
                          -> &'a LaneStroke {
        match *self {
            SelectableStrokeRef::New(node_idx) => &plan_delta.new_strokes[node_idx],
            SelectableStrokeRef::Built(old_ref) => {
                still_built_strokes.mapping
                    .get(old_ref)
                    .expect("Expected old_ref to exist!")
            }
        }
    }
}

#[derive(Copy, Clone)]
pub enum ContinuationMode {
    Append,
    Prepend,
}

#[derive(Compact, Clone)]
pub enum Intent {
    None,
    NewRoad(CVec<P2>),
    ContinueRoad(CVec<(SelectableStrokeRef, ContinuationMode)>, CVec<P2>, P2),
    ContinueRoadAround(SelectableStrokeRef, ContinuationMode, P2),
    Select(SelectableStrokeRef, N, N),
    MaximizeSelection,
    MoveSelection(V2),
    DeleteSelection,
    Deselect,
    CreateNextLane,
}

impl Default for Intent {
    fn default() -> Self {
        Intent::None
    }
}

#[derive(Compact, Clone)]
pub struct Settings {
    n_lanes_per_side: usize,
    create_both_sides: bool,
    select_parallel: bool,
    select_opposite: bool,
}

impl Default for Settings {
    fn default() -> Self {
        Settings {
            create_both_sides: true,
            n_lanes_per_side: 2,
            select_parallel: true,
            select_opposite: true,
        }
    }
}

#[derive(Default)]
pub struct CurrentPlan {
    built_strokes: Option<BuiltStrokes>,
    undo_history: CVec<PlanStep>,
    redo_history: CVec<PlanStep>,
    current: PlanStep,
    preview: Option<PlanStep>,
    preview_result_delta: Option<PlanResultDelta>,
    preview_result_delta_rendered: bool,
    interactables_valid: bool,
    settings: Settings,
    interaction: Interaction,
}
impl Actor for CurrentPlan {}

use super::super::construction::materialized_reality::Simulate;

impl CurrentPlan {
    fn still_built_strokes(&self) -> Option<BuiltStrokes> {
        self.built_strokes.as_ref().map(|built_strokes| {
            BuiltStrokes {
                mapping: built_strokes.mapping
                    .pairs()
                    .filter_map(|(built_ref, stroke)| if self.current
                        .plan_delta
                        .strokes_to_destroy
                        .contains_key(*built_ref) {
                        None
                    } else {
                        Some((*built_ref, stroke.clone()))
                    })
                    .collect(),
            }
        })
    }

    fn invalidate_preview(&mut self) {
        self.preview = None;
    }

    fn invalidate_interactables(&mut self) {
        self.interactables_valid = false;
    }

    pub fn update_preview(&mut self) -> &PlanStep {
        if self.preview.is_none() {
            let preview = apply_intent(&self.current,
                                       self.still_built_strokes().as_ref(),
                                       &self.settings);
            MaterializedReality::id() <<
            Simulate {
                requester: Self::id(),
                delta: preview.plan_delta.clone(),
            };
            self.preview = Some(preview);
        }
        self.preview.as_ref().unwrap()
    }

    pub fn update_interactables(&mut self) {
        Swarm::<Selectable>::all() << ClearInteractable;
        Swarm::<Draggable>::all() << ClearInteractable;
        Swarm::<Addable>::all() << ClearInteractable;
        Deselecter::id() << ClearInteractable;
        if !self.current.selections.is_empty() {
            Deselecter::id() << InitInteractable;
        }
        if let Some(still_built_strokes) = self.still_built_strokes() {
            for (i, stroke) in self.current.plan_delta.new_strokes.iter().enumerate() {
                let selectable = Selectable::new(SelectableStrokeRef::New(i),
                                                 stroke.path().clone());
                Swarm::<Selectable>::id() << CreateWith(selectable, InitInteractable);
            }
            for (old_stroke_ref, stroke) in still_built_strokes.mapping.pairs() {
                let selectable = Selectable::new(SelectableStrokeRef::Built(*old_stroke_ref),
                                                 stroke.path().clone());
                Swarm::<Selectable>::id() << CreateWith(selectable, InitInteractable);
            }
            for (&selection_ref, &(start, end)) in self.current.selections.pairs() {
                let stroke =
                    selection_ref.get_stroke(&self.current.plan_delta, &still_built_strokes);
                if let Some(subsection) = stroke.path().subsection(start, end) {
                    let draggable = Draggable::new(selection_ref, subsection.clone());
                    Swarm::<Draggable>::id() << CreateWith(draggable, InitInteractable);
                    if let Some(next_lane_path) = subsection.shift_orthogonally(5.0) {
                        let addable = Addable::new(next_lane_path);
                        Swarm::<Addable>::id() << CreateWith(addable, InitInteractable);
                    }
                }
            }
            self.interactables_valid = true;
        } else {
            // TODO: kinda stupid to get initial built strokes like this
            MaterializedReality::id() <<
            Apply {
                requester: Self::id(),
                delta: PlanDelta::default(),
            }
        }
    }

    fn commit(&mut self) {
        self.undo_history.push(self.current.clone());
        self.redo_history.clear();
        self.current = apply_intent(&self.current,
                                    self.still_built_strokes().as_ref(),
                                    &self.settings);
        self.invalidate_preview();
        self.invalidate_interactables();
    }

    // just the Intent changed, not the PlanDelta or selections
    fn commit_substep(&mut self) {
        self.undo_history.push(self.current.clone());
        self.redo_history.clear();
        self.invalidate_preview();
        self.invalidate_interactables();
    }

    // TODO: not really nice that this works differently
    // (needed for proper history)
    fn commit_immediate(&mut self) {
        let mut history_current = self.current.clone();
        history_current.intent = Intent::None;
        self.undo_history.push(history_current);
        self.redo_history.clear();
        self.current = apply_intent(&self.current,
                                    self.still_built_strokes().as_ref(),
                                    &self.settings);
        self.invalidate_preview();
        self.invalidate_interactables();
    }
}

#[derive(Copy, Clone)]
pub struct Undo;
use self::stroke_canvas::{StrokeCanvas, SetPoints};

impl Recipient<Undo> for CurrentPlan {
    fn receive(&mut self, _msg: &Undo) -> Fate {
        let previous_state = self.undo_history.pop().unwrap_or_default();
        self.redo_history.push(self.current.clone());
        self.current = previous_state;
        StrokeCanvas::id() <<
        SetPoints(match self.current.intent {
            Intent::ContinueRoad(_, ref points, _) |
            Intent::NewRoad(ref points) => points.clone(),
            _ => CVec::new(),
        });
        self.invalidate_preview();
        self.invalidate_interactables();
        Fate::Live
    }
}

#[derive(Copy, Clone)]
pub struct Redo;

impl Recipient<Redo> for CurrentPlan {
    fn receive(&mut self, _msg: &Redo) -> Fate {
        if let Some(next_state) = self.redo_history.pop() {
            self.undo_history.push(self.current.clone());
            self.current = next_state;
            StrokeCanvas::id() <<
            SetPoints(match self.current.intent {
                Intent::ContinueRoad(_, ref points, _) |
                Intent::NewRoad(ref points) => points.clone(),
                _ => CVec::new(),
            });
            self.invalidate_preview();
            self.invalidate_interactables();
        }
        Fate::Live
    }
}

#[derive(Copy, Clone)]
pub enum IntentProgress {
    Preview,
    SubStep,
    Finished,
    Immediate,
}

#[derive(Compact, Clone)]
pub struct ChangeIntent(pub Intent, pub IntentProgress);

impl Recipient<ChangeIntent> for CurrentPlan {
    fn receive(&mut self, msg: &ChangeIntent) -> Fate {
        match *msg {
            ChangeIntent(ref intent, progress) => {
                self.current.intent = intent.clone();
                match progress {
                    IntentProgress::Preview => {
                        self.invalidate_preview();
                    }
                    IntentProgress::SubStep => {
                        self.commit_substep();
                    }
                    IntentProgress::Finished => {
                        self.commit();
                    }
                    IntentProgress::Immediate => {
                        self.commit_immediate();
                    }
                }
                Fate::Live
            }
        }
    }
}

use self::stroke_canvas::{Stroke, StrokeState};

impl Recipient<Stroke> for CurrentPlan {
    fn receive(&mut self, msg: &Stroke) -> Fate {
        match *msg {
            Stroke(ref points, state) => {
                let maybe_new_intent = match self.current.intent {
                    Intent::ContinueRoad(ref continue_from, _, start_reference_point) => {
                        Some(Intent::ContinueRoad(continue_from.clone(),
                                                  points.clone(),
                                                  start_reference_point))
                    }
                    _ => {
                        if points.len() >= 2 {
                            Some(Intent::NewRoad(points.clone()))
                        } else {
                            None
                        }
                    }
                };
                if let Some(new_intent) = maybe_new_intent {
                    self.current.intent = new_intent;
                    match state {
                        StrokeState::Preview => {
                            self.invalidate_preview();
                        }
                        StrokeState::Intermediate => {
                            self.commit_substep();
                        }
                        StrokeState::Finished => {
                            self.commit();
                        }
                    }

                }
                Fate::Live
            }
        }
    }
}

#[derive(Copy, Clone)]
pub struct SetNLanes(usize);

impl Recipient<SetNLanes> for CurrentPlan {
    fn receive(&mut self, msg: &SetNLanes) -> Fate {
        match *msg {
            SetNLanes(n_lanes) => {
                self.settings.n_lanes_per_side = n_lanes;
                self.invalidate_preview();
                Fate::Live
            }
        }
    }
}

#[derive(Copy, Clone)]
pub struct ToggleBothSides;

impl Recipient<ToggleBothSides> for CurrentPlan {
    fn receive(&mut self, _msg: &ToggleBothSides) -> Fate {
        self.settings.create_both_sides = !self.settings.create_both_sides;
        self.invalidate_preview();
        Fate::Live
    }
}

use super::super::construction::materialized_reality::SimulationResult;

impl Recipient<SimulationResult> for CurrentPlan {
    fn receive(&mut self, msg: &SimulationResult) -> Fate {
        match *msg {
            SimulationResult(ref result_delta) => {
                self.preview_result_delta = Some(result_delta.clone());
                self.preview_result_delta_rendered = false;
                Fate::Live
            }
        }
    }
}

use super::super::construction::materialized_reality::BuiltStrokesChanged;

impl Recipient<BuiltStrokesChanged> for CurrentPlan {
    fn receive(&mut self, msg: &BuiltStrokesChanged) -> Fate {
        match *msg {
            BuiltStrokesChanged(ref built_strokes) => {
                self.built_strokes = Some(built_strokes.clone());
                Fate::Live
            }
        }
    }
}

#[derive(Copy, Clone)]
pub struct Materialize;

use super::super::construction::materialized_reality::Apply;

impl Recipient<Materialize> for CurrentPlan {
    fn receive(&mut self, _msg: &Materialize) -> Fate {
        MaterializedReality::id() <<
        Apply {
            requester: Self::id(),
            delta: self.current.plan_delta.clone(),
        };
        *self = CurrentPlan::default();
        Fate::Live
    }
}

#[derive(Copy, Clone)]
pub struct InitInteractable;
#[derive(Copy, Clone)]
pub struct ClearInteractable;

pub fn setup() {
    CurrentPlan::register_default();
    CurrentPlan::handle::<Undo>();
    CurrentPlan::handle::<Redo>();
    CurrentPlan::handle::<ChangeIntent>();
    CurrentPlan::handle::<Stroke>();
    CurrentPlan::handle::<Materialize>();
    CurrentPlan::handle::<SetNLanes>();
    CurrentPlan::handle::<ToggleBothSides>();
    CurrentPlan::handle::<BuiltStrokesChanged>();
    CurrentPlan::handle::<SimulationResult>();
    self::rendering::setup();
    self::stroke_canvas::setup();
    self::selectable::setup();
    self::deselecter::setup();
    self::draggable::setup();
    self::addable::setup();
    self::interaction::setup();
}
<commit_msg>Remove selectables when other operations are going on<commit_after>use kay::{Actor, Recipient, Fate};
use kay::swarm::{Swarm, CreateWith};
use compact::{CVec, CDict};
use descartes::{V2, N, P2, FiniteCurve};

use super::super::construction::materialized_reality::MaterializedReality;
use super::lane_stroke::LaneStroke;
use super::plan::{PlanDelta, PlanResultDelta, BuiltStrokes, LaneStrokeRef};

mod apply_intent;
use self::apply_intent::apply_intent;
mod rendering;
mod stroke_canvas;
mod selectable;
use self::selectable::Selectable;
mod deselecter;
use self::deselecter::Deselecter;
mod draggable;
use self::draggable::Draggable;
mod addable;
use self::addable::Addable;
mod interaction;
use self::interaction::Interaction;

#[derive(Compact, Clone, Default)]
pub struct PlanStep {
    plan_delta: PlanDelta,
    selections: CDict<SelectableStrokeRef, (N, N)>,
    intent: Intent,
}

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub enum SelectableStrokeRef {
    New(usize),
    Built(LaneStrokeRef),
}

impl SelectableStrokeRef {
    pub fn get_stroke<'a>(&self,
                          plan_delta: &'a PlanDelta,
                          still_built_strokes: &'a BuiltStrokes)
                          -> &'a LaneStroke {
        match *self {
            SelectableStrokeRef::New(node_idx) => &plan_delta.new_strokes[node_idx],
            SelectableStrokeRef::Built(old_ref) => {
                still_built_strokes.mapping
                    .get(old_ref)
                    .expect("Expected old_ref to exist!")
            }
        }
    }
}

#[derive(Copy, Clone)]
pub enum ContinuationMode {
    Append,
    Prepend,
}

#[derive(Compact, Clone)]
pub enum Intent {
    None,
    NewRoad(CVec<P2>),
    ContinueRoad(CVec<(SelectableStrokeRef, ContinuationMode)>, CVec<P2>, P2),
    ContinueRoadAround(SelectableStrokeRef, ContinuationMode, P2),
    Select(SelectableStrokeRef, N, N),
    MaximizeSelection,
    MoveSelection(V2),
    DeleteSelection,
    Deselect,
    CreateNextLane,
}

impl Default for Intent {
    fn default() -> Self {
        Intent::None
    }
}

#[derive(Compact, Clone)]
pub struct Settings {
    n_lanes_per_side: usize,
    create_both_sides: bool,
    select_parallel: bool,
    select_opposite: bool,
}

impl Default for Settings {
    fn default() -> Self {
        Settings {
            create_both_sides: true,
            n_lanes_per_side: 2,
            select_parallel: true,
            select_opposite: true,
        }
    }
}

#[derive(Default)]
pub struct CurrentPlan {
    built_strokes: Option<BuiltStrokes>,
    undo_history: CVec<PlanStep>,
    redo_history: CVec<PlanStep>,
    current: PlanStep,
    preview: Option<PlanStep>,
    preview_result_delta: Option<PlanResultDelta>,
    preview_result_delta_rendered: bool,
    interactables_valid: bool,
    settings: Settings,
    interaction: Interaction,
}
impl Actor for CurrentPlan {}

use super::super::construction::materialized_reality::Simulate;

impl CurrentPlan {
    fn still_built_strokes(&self) -> Option<BuiltStrokes> {
        self.built_strokes.as_ref().map(|built_strokes| {
            BuiltStrokes {
                mapping: built_strokes.mapping
                    .pairs()
                    .filter_map(|(built_ref, stroke)| if self.current
                        .plan_delta
                        .strokes_to_destroy
                        .contains_key(*built_ref) {
                        None
                    } else {
                        Some((*built_ref, stroke.clone()))
                    })
                    .collect(),
            }
        })
    }

    fn invalidate_preview(&mut self) {
        self.preview = None;
    }

    fn invalidate_interactables(&mut self) {
        self.interactables_valid = false;
    }

    pub fn update_preview(&mut self) -> &PlanStep {
        if self.preview.is_none() {
            let preview = apply_intent(&self.current,
                                       self.still_built_strokes().as_ref(),
                                       &self.settings);
            MaterializedReality::id() <<
            Simulate {
                requester: Self::id(),
                delta: preview.plan_delta.clone(),
            };
            self.preview = Some(preview);
        }
        self.preview.as_ref().unwrap()
    }

    pub fn update_interactables(&mut self) {
        Swarm::<Selectable>::all() << ClearInteractable;
        Swarm::<Draggable>::all() << ClearInteractable;
        Swarm::<Addable>::all() << ClearInteractable;
        Deselecter::id() << ClearInteractable;
        if !self.current.selections.is_empty() {
            Deselecter::id() << InitInteractable;
        }
        if let Some(still_built_strokes) = self.still_built_strokes() {
            if let Intent::None = self.current.intent {
                for (i, stroke) in self.current.plan_delta.new_strokes.iter().enumerate() {
                    let selectable = Selectable::new(SelectableStrokeRef::New(i),
                                                     stroke.path().clone());
                    Swarm::<Selectable>::id() << CreateWith(selectable, InitInteractable);
                }
                for (old_stroke_ref, stroke) in still_built_strokes.mapping.pairs() {
                    let selectable = Selectable::new(SelectableStrokeRef::Built(*old_stroke_ref),
                                                     stroke.path().clone());
                    Swarm::<Selectable>::id() << CreateWith(selectable, InitInteractable);
                }
            }
            for (&selection_ref, &(start, end)) in self.current.selections.pairs() {
                let stroke =
                    selection_ref.get_stroke(&self.current.plan_delta, &still_built_strokes);
                if let Some(subsection) = stroke.path().subsection(start, end) {
                    let draggable = Draggable::new(selection_ref, subsection.clone());
                    Swarm::<Draggable>::id() << CreateWith(draggable, InitInteractable);
                    if let Some(next_lane_path) = subsection.shift_orthogonally(5.0) {
                        let addable = Addable::new(next_lane_path);
                        Swarm::<Addable>::id() << CreateWith(addable, InitInteractable);
                    }
                }
            }
            self.interactables_valid = true;
        } else {
            // TODO: kinda stupid to get initial built strokes like this
            MaterializedReality::id() <<
            Apply {
                requester: Self::id(),
                delta: PlanDelta::default(),
            }
        }
    }

    fn commit(&mut self) {
        self.undo_history.push(self.current.clone());
        self.redo_history.clear();
        self.current = apply_intent(&self.current,
                                    self.still_built_strokes().as_ref(),
                                    &self.settings);
        self.invalidate_preview();
        self.invalidate_interactables();
    }

    // just the Intent changed, not the PlanDelta or selections
    fn commit_substep(&mut self) {
        self.undo_history.push(self.current.clone());
        self.redo_history.clear();
        self.invalidate_preview();
        self.invalidate_interactables();
    }

    // TODO: not really nice that this works differently
    // (needed for proper history)
    fn commit_immediate(&mut self) {
        let mut history_current = self.current.clone();
        history_current.intent = Intent::None;
        self.undo_history.push(history_current);
        self.redo_history.clear();
        self.current = apply_intent(&self.current,
                                    self.still_built_strokes().as_ref(),
                                    &self.settings);
        self.invalidate_preview();
        self.invalidate_interactables();
    }
}

#[derive(Copy, Clone)]
pub struct Undo;
use self::stroke_canvas::{StrokeCanvas, SetPoints};

impl Recipient<Undo> for CurrentPlan {
    fn receive(&mut self, _msg: &Undo) -> Fate {
        let previous_state = self.undo_history.pop().unwrap_or_default();
        self.redo_history.push(self.current.clone());
        self.current = previous_state;
        StrokeCanvas::id() <<
        SetPoints(match self.current.intent {
            Intent::ContinueRoad(_, ref points, _) |
            Intent::NewRoad(ref points) => points.clone(),
            _ => CVec::new(),
        });
        self.invalidate_preview();
        self.invalidate_interactables();
        Fate::Live
    }
}

#[derive(Copy, Clone)]
pub struct Redo;

impl Recipient<Redo> for CurrentPlan {
    fn receive(&mut self, _msg: &Redo) -> Fate {
        if let Some(next_state) = self.redo_history.pop() {
            self.undo_history.push(self.current.clone());
            self.current = next_state;
            StrokeCanvas::id() <<
            SetPoints(match self.current.intent {
                Intent::ContinueRoad(_, ref points, _) |
                Intent::NewRoad(ref points) => points.clone(),
                _ => CVec::new(),
            });
            self.invalidate_preview();
            self.invalidate_interactables();
        }
        Fate::Live
    }
}

#[derive(Copy, Clone)]
pub enum IntentProgress {
    Preview,
    SubStep,
    Finished,
    Immediate,
}

#[derive(Compact, Clone)]
pub struct ChangeIntent(pub Intent, pub IntentProgress);

impl Recipient<ChangeIntent> for CurrentPlan {
    fn receive(&mut self, msg: &ChangeIntent) -> Fate {
        match *msg {
            ChangeIntent(ref intent, progress) => {
                self.current.intent = intent.clone();
                match progress {
                    IntentProgress::Preview => {
                        self.invalidate_preview();
                    }
                    IntentProgress::SubStep => {
                        self.commit_substep();
                    }
                    IntentProgress::Finished => {
                        self.commit();
                    }
                    IntentProgress::Immediate => {
                        self.commit_immediate();
                    }
                }
                Fate::Live
            }
        }
    }
}

use self::stroke_canvas::{Stroke, StrokeState};

impl Recipient<Stroke> for CurrentPlan {
    fn receive(&mut self, msg: &Stroke) -> Fate {
        match *msg {
            Stroke(ref points, state) => {
                let maybe_new_intent = match self.current.intent {
                    Intent::ContinueRoad(ref continue_from, _, start_reference_point) => {
                        Some(Intent::ContinueRoad(continue_from.clone(),
                                                  points.clone(),
                                                  start_reference_point))
                    }
                    _ => {
                        if points.len() >= 2 {
                            self.invalidate_interactables();
                            Some(Intent::NewRoad(points.clone()))
                        } else {
                            None
                        }
                    }
                };
                if let Some(new_intent) = maybe_new_intent {
                    self.current.intent = new_intent;
                    match state {
                        StrokeState::Preview => {
                            self.invalidate_preview();
                        }
                        StrokeState::Intermediate => {
                            self.commit_substep();
                        }
                        StrokeState::Finished => {
                            self.commit();
                        }
                    }

                }
                Fate::Live
            }
        }
    }
}

#[derive(Copy, Clone)]
pub struct SetNLanes(usize);

impl Recipient<SetNLanes> for CurrentPlan {
    fn receive(&mut self, msg: &SetNLanes) -> Fate {
        match *msg {
            SetNLanes(n_lanes) => {
                self.settings.n_lanes_per_side = n_lanes;
                self.invalidate_preview();
                Fate::Live
            }
        }
    }
}

#[derive(Copy, Clone)]
pub struct ToggleBothSides;

impl Recipient<ToggleBothSides> for CurrentPlan {
    fn receive(&mut self, _msg: &ToggleBothSides) -> Fate {
        self.settings.create_both_sides = !self.settings.create_both_sides;
        self.invalidate_preview();
        Fate::Live
    }
}

use super::super::construction::materialized_reality::SimulationResult;

impl Recipient<SimulationResult> for CurrentPlan {
    fn receive(&mut self, msg: &SimulationResult) -> Fate {
        match *msg {
            SimulationResult(ref result_delta) => {
                self.preview_result_delta = Some(result_delta.clone());
                self.preview_result_delta_rendered = false;
                Fate::Live
            }
        }
    }
}

use super::super::construction::materialized_reality::BuiltStrokesChanged;

impl Recipient<BuiltStrokesChanged> for CurrentPlan {
    fn receive(&mut self, msg: &BuiltStrokesChanged) -> Fate {
        match *msg {
            BuiltStrokesChanged(ref built_strokes) => {
                self.built_strokes = Some(built_strokes.clone());
                Fate::Live
            }
        }
    }
}

#[derive(Copy, Clone)]
pub struct Materialize;

use super::super::construction::materialized_reality::Apply;

impl Recipient<Materialize> for CurrentPlan {
    fn receive(&mut self, _msg: &Materialize) -> Fate {
        MaterializedReality::id() <<
        Apply {
            requester: Self::id(),
            delta: self.current.plan_delta.clone(),
        };
        *self = CurrentPlan::default();
        Fate::Live
    }
}

#[derive(Copy, Clone)]
pub struct InitInteractable;
#[derive(Copy, Clone)]
pub struct ClearInteractable;

pub fn setup() {
    CurrentPlan::register_default();
    CurrentPlan::handle::<Undo>();
    CurrentPlan::handle::<Redo>();
    CurrentPlan::handle::<ChangeIntent>();
    CurrentPlan::handle::<Stroke>();
    CurrentPlan::handle::<Materialize>();
    CurrentPlan::handle::<SetNLanes>();
    CurrentPlan::handle::<ToggleBothSides>();
    CurrentPlan::handle::<BuiltStrokesChanged>();
    CurrentPlan::handle::<SimulationResult>();
    self::rendering::setup();
    self::stroke_canvas::setup();
    self::selectable::setup();
    self::deselecter::setup();
    self::draggable::setup();
    self::addable::setup();
    self::interaction::setup();
}
<|endoftext|>


<commit_before>use nom::{
  be_u8, be_u16,
  IResult,
  ErrorCode, Err,
};

use frame::{
  ChannelAssignment,
  Footer,
};

fn blocking_strategy(input: &[u8]) -> IResult<&[u8], bool> {
  match take!(input, 2) {
    IResult::Done(i, bytes)   => {
      let sync_code = ((bytes[0] as u16) << 6) +
                      (bytes[1] as u16) >> 2;
      let is_valid  = ((bytes[1] >> 1) & 0b01) == 0;

      if sync_code == 0b11111111111110 && is_valid {
        let is_variable_block_size = (bytes[1] & 0b01) == 1;

        IResult::Done(i, is_variable_block_size)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn block_sample(input: &[u8]) -> IResult<&[u8], (u32, u32)> {
  match take!(input, 1) {
    IResult::Done(i, bytes)   => {
      let sample_rate = bytes[0] & 0x0f;

      if sample_rate != 0x0f {
        let block_size = bytes[0] >> 4;

        IResult::Done(i, (block_size as u32, sample_rate as u32))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn channel_bits(input: &[u8]) -> IResult<&[u8], (ChannelAssignment, usize)> {
  match take!(input, 1) {
    IResult::Done(i, bytes)   => {
      let channel_assignment = match bytes[0] >> 4 {
        0b0000...0b0111 => ChannelAssignment::Independent,
        0b1000          => ChannelAssignment::LeftSide,
        0b1001          => ChannelAssignment::RightSide,
        0b1010          => ChannelAssignment::MiddleSide,
        _               => ChannelAssignment::Independent,
      };
      let bits_per_sample = (bytes[0] >> 1) & 0b0111;
      let is_valid        = (bytes[0] & 0b01) == 0;

      if is_valid {
        IResult::Done(i, (channel_assignment, bits_per_sample as usize))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn utf8_size(input: &[u8], is_u64: bool)
             -> IResult<&[u8], Option<(usize, u8)>> {
  map!(input, be_u8, |utf8_header| {
    match utf8_header {
      0b00000000...0b01111111 => Some((0, utf8_header)),
      0b11000000...0b11011111 => Some((1, utf8_header & 0b00011111)),
      0b11100000...0b11101111 => Some((2, utf8_header & 0b00001111)),
      0b11110000...0b11110111 => Some((3, utf8_header & 0b00000111)),
      0b11111000...0b11111011 => Some((4, utf8_header & 0b00000011)),
      0b11111100...0b11111101 => Some((5, utf8_header & 0b00000001)),
      0b11111110              => if is_u64 { Some((6, 0)) } else { None },
      _                       => None,
    }
  })
}

named!(footer <&[u8], Footer>, map!(be_u16, Footer));
<commit_msg>Add parser for number type<commit_after>use nom::{
  be_u8, be_u16,
  IResult,
  ErrorCode, Err,
};

use frame::{
  ChannelAssignment, NumberType,
  Footer,
};

fn blocking_strategy(input: &[u8]) -> IResult<&[u8], bool> {
  match take!(input, 2) {
    IResult::Done(i, bytes)   => {
      let sync_code = ((bytes[0] as u16) << 6) +
                      (bytes[1] as u16) >> 2;
      let is_valid  = ((bytes[1] >> 1) & 0b01) == 0;

      if sync_code == 0b11111111111110 && is_valid {
        let is_variable_block_size = (bytes[1] & 0b01) == 1;

        IResult::Done(i, is_variable_block_size)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn block_sample(input: &[u8]) -> IResult<&[u8], (u32, u32)> {
  match take!(input, 1) {
    IResult::Done(i, bytes)   => {
      let sample_rate = bytes[0] & 0x0f;

      if sample_rate != 0x0f {
        let block_size = bytes[0] >> 4;

        IResult::Done(i, (block_size as u32, sample_rate as u32))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn channel_bits(input: &[u8]) -> IResult<&[u8], (ChannelAssignment, usize)> {
  match take!(input, 1) {
    IResult::Done(i, bytes)   => {
      let channel_assignment = match bytes[0] >> 4 {
        0b0000...0b0111 => ChannelAssignment::Independent,
        0b1000          => ChannelAssignment::LeftSide,
        0b1001          => ChannelAssignment::RightSide,
        0b1010          => ChannelAssignment::MiddleSide,
        _               => ChannelAssignment::Independent,
      };
      let bits_per_sample = (bytes[0] >> 1) & 0b0111;
      let is_valid        = (bytes[0] & 0b01) == 0;

      if is_valid {
        IResult::Done(i, (channel_assignment, bits_per_sample as usize))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn utf8_size(input: &[u8], is_u64: bool)
             -> IResult<&[u8], Option<(usize, u8)>> {
  map!(input, be_u8, |utf8_header| {
    match utf8_header {
      0b00000000...0b01111111 => Some((0, utf8_header)),
      0b11000000...0b11011111 => Some((1, utf8_header & 0b00011111)),
      0b11100000...0b11101111 => Some((2, utf8_header & 0b00001111)),
      0b11110000...0b11110111 => Some((3, utf8_header & 0b00000111)),
      0b11111000...0b11111011 => Some((4, utf8_header & 0b00000011)),
      0b11111100...0b11111101 => Some((5, utf8_header & 0b00000001)),
      0b11111110              => if is_u64 { Some((6, 0)) } else { None },
      _                       => None,
    }
  })
}

fn sample_or_frame_number(input: &[u8], is_sample: bool,
                          (size, value): (usize, u8))
                          -> IResult<&[u8], NumberType> {
  let mut result   = value as u64;
  let mut is_error = false;

  match take!(input, size) {
    IResult::Done(i, bytes)   => {
      for i in (0..size) {
        let byte = bytes[i] as u64;

        match byte {
          0b10000000...10111111 => {
            result = (result << 6) + (byte & 0b00111111);
          }
          _                     => {
            is_error = true;
            break;
          }
        }
      }

      if is_error {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      } else if is_sample {
        IResult::Done(i, NumberType::Sample(result))
      } else {
        IResult::Done(i, NumberType::Frame(result as u32))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

named!(footer <&[u8], Footer>, map!(be_u16, Footer));
<|endoftext|>


<commit_before>//! This module provides tools for generating meshes for simple shapes like
//! cubes and spheres.
//!
//! The interface is iterator-based and begins with a unit shape and
//! manipulates its constituent primitives like points, lines, and polygons.
//! All shapes provide position information and some can additionally generate
//! index, texture, and conjoint point information as well.
//!
//! # Examples
//!
//! Generating position and index data for a scaled sphere mesh:
//!
//! ```
//! use plexus::generate::{IndexedPolygons, Points, SpatialPoints, Triangulate};
//! use plexus::generate::sphere::UVSphere;
//!
//! let sphere = UVSphere::with_unit_radius(16, 16);
//! let positions: Vec<_> = sphere
//!     .spatial_points() // Get the unique set of points.
//!     .map(|point| point * 10.0) // Scale the points by 10.
//!     .collect();
//! let indeces: Vec<_> = sphere
//!     .indexed_polygons() // Get indeces into the unique set of points as polygons.
//!     .triangulate() // Decompose the polygons into triangles.
//!     .points() // Decompose the triangles into points (indeces).
//!     .collect();
//! ```

pub mod cube;
mod decompose;
mod generate;
mod index;
pub mod sphere;
mod topology;

pub use self::decompose::{IntoLines, IntoVertices, IntoSubdivisions, IntoTetrahedrons,
                          IntoTriangles, Lines, Vertices, Subdivide, Tetrahedrons, Triangulate};
pub use self::generate::{IndexedPolygons, SpatialVertices, SpatialPolygons, TexturedPolygons};
pub use self::index::{HashIndexer, IndexTopology};
pub use self::topology::{Line, MapVertices, Polygon, Polygonal, Rotate, Topological, Triangle,
                         Quad};
<commit_msg>Update `generate` module documentation.<commit_after>//! Mesh generation from primitives like cubes and spheres.
//!
//! This module provides unit primitives that can be used to form complex
//! iterator expressions to generate meshes via a stream of topology and
//! geometry. This data can be collected into simple buffers for rendering or a
//! graph (half-edge) for further manipulation.
//!
//! Iterator expressions begin with a unit primitive and manipulate its
//! components like vertices, lines, and polygons. Generation and decomposition
//! operations are exposed via traits.
//!
//! # Examples
//!
//! Generating position and index buffers for a scaled sphere:
//!
//! ```
//! use plexus::generate::{IndexedPolygons, SpatialVertices, Triangulate, Vertices};
//! use plexus::generate::sphere::UVSphere;
//!
//! let sphere = UVSphere::<f32>::with_unit_radius(16, 16);
//! let positions: Vec<_> = sphere
//!     .spatial_vertices() // Generate the unique set of positional vertices.
//!     .map(|(x, y, z)| (x * 10.0, y * 10.0, z * 10.0)) // Scale the positions by 10.
//!     .collect();
//! let indeces: Vec<_> = sphere
//!     .indexed_polygons() // Generate polygons indexing the unique set of vertices.
//!     .triangulate() // Decompose the polygons into triangles.
//!     .vertices() // Decompose the triangles into vertices (indeces).
//!     .collect();
//! ```

// TODO: Primitives are parameterized over the type of scalars used for spatial
//       data. This can be interpreted as the vector space. Other data, like
//       texture coordinates, are not parameterized. It may be more consistent
//       to parameterize all of this data and to do so on the generator
//       functions, if possible. For example, `cube.spatial_vertices::<f32>()`.

pub mod cube;
mod decompose;
mod generate;
mod index;
pub mod sphere;
mod topology;

pub use self::decompose::{IntoLines, IntoVertices, IntoSubdivisions, IntoTetrahedrons,
                          IntoTriangles, Lines, Vertices, Subdivide, Tetrahedrons, Triangulate};
pub use self::generate::{IndexedPolygons, SpatialVertices, SpatialPolygons, TexturedPolygons};
pub use self::index::{HashIndexer, IndexTopology};
pub use self::topology::{Line, MapVertices, Polygon, Polygonal, Rotate, Topological, Triangle,
                         Quad};
<|endoftext|>