diff --git a/index.html b/index.html index 4a1e2c4..0eef48f 100644 --- a/index.html +++ b/index.html @@ -44,7 +44,8 @@
+ +
diff --git a/src/bin/svg-wasm.rs b/src/bin/svg-wasm.rs index e6feb39..675baa5 100644 --- a/src/bin/svg-wasm.rs +++ b/src/bin/svg-wasm.rs @@ -77,6 +77,7 @@ fn span(text: &str) -> HtmlElement { pub fn run() { let document = web!(document); + let print_labels = get_labels(); let mode = get_mode(); let var_count = get_var_number(); let vars = (0..var_count).map(|x| 2usize.pow(x as u32)).collect::>(); @@ -100,7 +101,7 @@ pub fn run() { macro_rules! render_svg { ($sol:expr, $mask:expr) => { - let svg = svg::get_svg(if var_count < 5 { 64 } else { 80 }, &function, &vars, $mask); + let svg = svg::get_svg(if var_count < 5 { 64 } else { 80 }, print_labels, &function, &vars, $mask); let svg_container = document.create_element("div").unwrap(); svg_container.set_class_name("solution"); svg_container.set_inner_html(&svg); @@ -175,6 +176,14 @@ fn get_var_number() -> usize { get_var_number_el().value().parse().unwrap() } +fn get_labels_el() -> HtmlInputElement { + web!(document).get_element_by_id("labels").unwrap().unchecked_into() +} + +fn get_labels() -> bool { + get_labels_el().checked() +} + fn get_mode_el() -> HtmlSelectElement { web!(document).get_element_by_id("mode-select").unwrap().unchecked_into() } diff --git a/src/bin/svg.rs b/src/bin/svg.rs index c894876..5a4d3f0 100644 --- a/src/bin/svg.rs +++ b/src/bin/svg.rs @@ -45,5 +45,5 @@ fn main() { .collect() }; - println!("{}", svg::get_svg(SIZE_FACTOR, &function, &vars, &block_masks)); + println!("{}", svg::get_svg(SIZE_FACTOR, false, &function, &vars, &block_masks)); } diff --git a/src/ui/svg.rs b/src/ui/svg.rs index a53b900..9b2e854 100644 --- a/src/ui/svg.rs +++ b/src/ui/svg.rs @@ -15,9 +15,12 @@ const COLORS: &'static [Color] = &[ rgb(128, 0, 128), // dark red ]; -pub fn get_svg(size_factor: usize, function: &FunctionSpec, vars: &[Variable], block_masks: &[(usize, usize)]) -> String { +pub fn get_svg(size_factor: usize, print_labels: bool, + function: &FunctionSpec, vars: &[Variable], block_masks: &[(usize, usize)]) -> String { + let size2 = (size_factor / 2) as f32; let size4 = size_factor / 4; let size8 = size_factor / 8; + let size16 = (size_factor / 16) as f32; let delta = size_factor as f32 / 32.0; let mut svg = String::new(); @@ -32,7 +35,118 @@ pub fn get_svg(size_factor: usize, function: &FunctionSpec, vars: &[Variable], b } } - svg += &BeginSvg { w: w * size_factor + 3, h: h * size_factor + 3 }.to_string(); + let (start_x, start_y, w_add, h_add) = if print_labels { + let mut a = 0.0; + let mut b = 0.0; + let mut c = 0.0; + let mut d = 0.0; + for i in 0..vars.len() { + match i % 4 { + 0 => { + b -= size2; + d += size2; + }, + 1 => { + a -= size2; + c += size2; + }, + 2 => { + d += size2; + }, + 3 => { + c += size2; + }, + _ => unreachable!() + } + } + (a, b, c, d) + } else { + (0.0, 0.0, 0.0, 0.0) + }; + + let w_base = (w * size_factor + 3) as f32; + let h_base = (h * size_factor + 3) as f32; + svg += &BeginSvg { + w: w_base + w_add, h: h_base + h_add, + x: start_x, y: start_y + }.to_string(); + + if print_labels { + for i in 0..vars.len() { + let offset = (i / 4) as f32 * size2 + size16; + let initial_window = 2usize.pow(((i + 2) / 4) as u32); + let mut start = vec![false; initial_window]; + start.extend(vec![true; initial_window]); + let desired_len = if i % 2 == 0 { w } else { h }; + while start.len() < desired_len { + let j = start.len(); + for k in 0..j { + start.push(start[j-k-1]); + } + } + let mut segments = vec![]; + let mut j = 0; + while j < desired_len { + if let Some((idx, _)) = start[j..].iter().find_position(|x| **x) { + j += idx; + let j2 = start[j..].iter().find_position(|x| !**x).map(|x| x.0).unwrap_or(desired_len-j); + segments.push((j, j+j2-1)); + j += j2; + } else { + break; + } + } + let var_name = print_var(vars[i]); + match i % 4 { + 0 => { + for (x1, x2) in segments { + svg += &line_segment(x1 * size_factor, -offset, (x2 + 1) * size_factor, -offset) + .width(2.0) + .to_string(); + svg += &text((x1 + x2 + 1) * size_factor / 2, -offset - size16, var_name) + .align(Align::Center) + .size(SIZE_FONT) + .to_string(); + } + }, + 1 => { + for (y1, y2) in segments { + svg += &line_segment(-offset, y1 * size_factor, -offset, (y2 + 1) * size_factor) + .width(2.0) + .to_string(); + svg += &text(-offset - size8 as f32, (y1 + y2 + 1) * size_factor / 2, var_name) + .align(Align::Center) + .size(SIZE_FONT) + .to_string(); + } + }, + 2 => { + for (x1, x2) in segments { + svg += &line_segment(x1 * size_factor, h_base + offset, (x2 + 1) * size_factor, h_base + offset) + .width(2.0) + .to_string(); + svg += &text((x1 + x2 + 1) * size_factor / 2, h_base + offset + size4 as f32, var_name) + .align(Align::Center) + .size(SIZE_FONT) + .to_string(); + } + }, + 3 => { + for (y1, y2) in segments { + svg += &line_segment(w_base + offset, y1 * size_factor, w_base + offset, (y2 + 1) * size_factor) + .width(2.0) + .to_string(); + svg += &text(w_base + offset + size8 as f32, (y1 + y2 + 1) * size_factor / 2, var_name) + .align(Align::Center) + .size(SIZE_FONT) + .to_string(); + } + }, + _ => unreachable!() + } + } + } + for (i, &(x, y)) in grid.iter().enumerate() { svg += &rectangle(1 + x * size_factor, 1 + y * size_factor, size_factor, size_factor) .fill(white())