From ad352e4a1e8a67748a66160418194123166023ca Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sat, 5 Jan 2019 20:14:16 +0100 Subject: [PATCH] Rounded corners and antialiasing --- docs/emgui_wasm_bg.wasm | Bin 350870 -> 354769 bytes docs/frontend.js | 113 +---------------------- docs/frontend.ts | 183 +------------------------------------ emgui/src/painter.rs | 197 ++++++++++++++++++++++++++++++---------- emgui/src/types.rs | 9 ++ 5 files changed, 170 insertions(+), 332 deletions(-) diff --git a/docs/emgui_wasm_bg.wasm b/docs/emgui_wasm_bg.wasm index 04cd0991ea76643db540a46af5c675ecf6088162..3bc1b878805c6ef7a1e767903e4e4b6ddec7be31 100644 GIT binary patch delta 26886 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 OIp(Us!Z!QBd;br!bQ{J1 delta 22976 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 HeV+bbI|uBm diff --git a/docs/frontend.js b/docs/frontend.js index ff2f2b4c..9e92e013 100644 --- a/docs/frontend.js +++ b/docs/frontend.js @@ -1,75 +1,3 @@ -// ---------------------------------------------------------------------------- -// Canvas painting: -function style_from_color(color) { - return "rgba(" + color.r + ", " + color.g + ", " + color.b + ", " + color.a / 255.0 + ")"; -} -function paint_command(canvas, cmd) { - var ctx = canvas.getContext("2d"); - // console.log(`cmd: ${JSON.stringify(cmd)}`); - switch (cmd.kind) { - case "circle": - ctx.beginPath(); - ctx.arc(cmd.center.x, cmd.center.y, cmd.radius, 0, 2 * Math.PI, false); - if (cmd.fill_color) { - ctx.fillStyle = style_from_color(cmd.fill_color); - ctx.fill(); - } - if (cmd.outline) { - ctx.lineWidth = cmd.outline.width; - ctx.strokeStyle = style_from_color(cmd.outline.color); - ctx.stroke(); - } - return; - case "clear": - ctx.fillStyle = style_from_color(cmd.fill_color); - ctx.clearRect(0, 0, canvas.width, canvas.height); - return; - case "line": - ctx.beginPath(); - ctx.moveTo(cmd.points[0].x, cmd.points[0].y); - for (var _i = 0, _a = cmd.points; _i < _a.length; _i++) { - var point = _a[_i]; - ctx.lineTo(point.x, point.y); - } - ctx.lineWidth = cmd.width; - ctx.strokeStyle = style_from_color(cmd.color); - ctx.stroke(); - return; - case "rect": - var x = cmd.pos.x; - var y = cmd.pos.y; - var width = cmd.size.x; - var height = cmd.size.y; - var r = Math.min(cmd.corner_radius, width / 2, height / 2); - ctx.beginPath(); - ctx.moveTo(x + r, y); - ctx.lineTo(x + width - r, y); - ctx.quadraticCurveTo(x + width, y, x + width, y + r); - ctx.lineTo(x + width, y + height - r); - ctx.quadraticCurveTo(x + width, y + height, x + width - r, y + height); - ctx.lineTo(x + r, y + height); - ctx.quadraticCurveTo(x, y + height, x, y + height - r); - ctx.lineTo(x, y + r); - ctx.quadraticCurveTo(x, y, x + r, y); - ctx.closePath(); - if (cmd.fill_color) { - ctx.fillStyle = style_from_color(cmd.fill_color); - ctx.fill(); - } - if (cmd.outline) { - ctx.lineWidth = cmd.outline.width; - ctx.strokeStyle = style_from_color(cmd.outline.color); - ctx.stroke(); - } - return; - case "text": - ctx.fillStyle = style_from_color(cmd.fill_color); - ctx.font = cmd.font_size + "px " + cmd.font_name; - ctx.textBaseline = "middle"; - ctx.fillText(cmd.text, cmd.pos.x, cmd.pos.y); - return; - } -} // we'll defer our execution until the wasm is ready to go function wasm_loaded() { console.log("wasm loaded"); @@ -79,55 +7,24 @@ function wasm_loaded() { // initialization and return to us a promise when it's done wasm_bindgen("./emgui_wasm_bg.wasm") .then(wasm_loaded)["catch"](console.error); -function rust_gui(input) { - return JSON.parse(wasm_bindgen.show_gui(JSON.stringify(input))); -} // ---------------------------------------------------------------------------- -function js_gui(input) { - var commands = []; - commands.push({ - fillStyle: "#111111", - kind: "clear" - }); - commands.push({ - fillStyle: "#ff1111", - kind: "rect", - pos: { x: 100, y: 100 }, - radius: 20, - size: { x: 200, y: 100 } - }); - return commands; -} -var WEB_GL = true; var g_webgl_painter = null; function paint_gui(canvas, input) { - if (WEB_GL) { - if (g_webgl_painter === null) { - g_webgl_painter = wasm_bindgen.new_webgl_painter("canvas"); - } - wasm_bindgen.paint_webgl(g_webgl_painter, JSON.stringify(input)); - } - else { - var commands = rust_gui(input); - for (var _i = 0, commands_1 = commands; _i < commands_1.length; _i++) { - var cmd = commands_1[_i]; - commands.unshift({ - fill_color: { r: 0, g: 0, b: 0, a: 0 }, - kind: "clear" - }); - paint_command(canvas, cmd); - } + if (g_webgl_painter === null) { + g_webgl_painter = wasm_bindgen.new_webgl_painter("canvas"); } + wasm_bindgen.paint_webgl(g_webgl_painter, JSON.stringify(input)); } // ---------------------------------------------------------------------------- var g_mouse_pos = { x: -1000.0, y: -1000.0 }; var g_mouse_down = false; function auto_resize_canvas(canvas) { - if (WEB_GL) { + if (true) { canvas.setAttribute("width", window.innerWidth); canvas.setAttribute("height", window.innerHeight); } else { + // TODO: this stuff var pixels_per_point = window.devicePixelRatio || 1; var ctx = canvas.getContext("2d"); ctx.scale(pixels_per_point, pixels_per_point); diff --git a/docs/frontend.ts b/docs/frontend.ts index 6a3d33c9..09fe4ccc 100644 --- a/docs/frontend.ts +++ b/docs/frontend.ts @@ -3,145 +3,6 @@ interface Vec2 { y: number; } -// ---------------------------------------------------------------------------- -// Paint module: - -/// 0-255 sRGBA -interface Color { - r: number; - g: number; - b: number; - a: number; -} - -interface Outline { - color: Color; - width: number; -} - -interface Clear { - kind: "clear"; - fill_color: Color; -} - -interface Line { - kind: "line"; - color: Color; - points: Vec2[]; - width: number; -} - -interface Circle { - kind: "circle"; - center: Vec2; - fill_color: Color | null; - outline: Outline | null; - radius: number; -} - -interface Rect { - kind: "rect"; - corner_radius: number; - fill_color: Color | null; - outline: Outline | null; - pos: Vec2; - size: Vec2; -} - -interface Text { - kind: "text"; - fill_color: Color | null; - font_name: string; // e.g. "Palatino" - font_size: number; // Height in pixels, e.g. 12 - pos: Vec2; - stroke_color: Color | null; - text: string; -} - -type PaintCmd = Circle | Clear | Line | Rect | Text; - -// ---------------------------------------------------------------------------- -// Canvas painting: - -function style_from_color(color: Color): string { - return `rgba(${color.r}, ${color.g}, ${color.b}, ${color.a / 255.0})`; -} - -function paint_command(canvas, cmd: PaintCmd) { - const ctx = canvas.getContext("2d"); - - // console.log(`cmd: ${JSON.stringify(cmd)}`); - - switch (cmd.kind) { - case "circle": - ctx.beginPath(); - ctx.arc(cmd.center.x, cmd.center.y, cmd.radius, 0, 2 * Math.PI, false); - if (cmd.fill_color) { - ctx.fillStyle = style_from_color(cmd.fill_color); - ctx.fill(); - } - if (cmd.outline) { - ctx.lineWidth = cmd.outline.width; - ctx.strokeStyle = style_from_color(cmd.outline.color); - ctx.stroke(); - } - return; - - case "clear": - ctx.fillStyle = style_from_color(cmd.fill_color); - ctx.clearRect(0, 0, canvas.width, canvas.height); - return; - - case "line": - ctx.beginPath(); - ctx.moveTo(cmd.points[0].x, cmd.points[0].y); - for (const point of cmd.points) { - ctx.lineTo(point.x, point.y); - } - ctx.lineWidth = cmd.width; - ctx.strokeStyle = style_from_color(cmd.color); - ctx.stroke(); - return; - - case "rect": - const x = cmd.pos.x; - const y = cmd.pos.y; - const width = cmd.size.x; - const height = cmd.size.y; - const r = Math.min(cmd.corner_radius, width / 2, height / 2); - ctx.beginPath(); - ctx.moveTo(x + r, y); - ctx.lineTo(x + width - r, y); - ctx.quadraticCurveTo(x + width, y, x + width, y + r); - ctx.lineTo(x + width, y + height - r); - ctx.quadraticCurveTo(x + width, y + height, x + width - r, y + height); - ctx.lineTo(x + r, y + height); - ctx.quadraticCurveTo(x, y + height, x, y + height - r); - ctx.lineTo(x, y + r); - ctx.quadraticCurveTo(x, y, x + r, y); - ctx.closePath(); - if (cmd.fill_color) { - ctx.fillStyle = style_from_color(cmd.fill_color); - ctx.fill(); - } - if (cmd.outline) { - ctx.lineWidth = cmd.outline.width; - ctx.strokeStyle = style_from_color(cmd.outline.color); - ctx.stroke(); - } - return; - - case "text": - ctx.fillStyle = style_from_color(cmd.fill_color); - ctx.font = `${cmd.font_size}px ${cmd.font_name}`; - ctx.textBaseline = "middle"; - ctx.fillText(cmd.text, cmd.pos.x, cmd.pos.y); - return; - } -} - -// ---------------------------------------------------------------------------- - /// What the integration gives to the gui. interface RawInput { /// Is the button currently down? @@ -171,50 +32,15 @@ wasm_bindgen("./emgui_wasm_bg.wasm") .then(wasm_loaded) .catch(console.error); -function rust_gui(input: RawInput): PaintCmd[] { - return JSON.parse(wasm_bindgen.show_gui(JSON.stringify(input))); -} - // ---------------------------------------------------------------------------- -function js_gui(input: RawInput): PaintCmd[] { - const commands = []; - - commands.push({ - fillStyle: "#111111", - kind: "clear", - }); - - commands.push({ - fillStyle: "#ff1111", - kind: "rect", - pos: { x: 100, y: 100 }, - radius: 20, - size: { x: 200, y: 100 }, - }); - - return commands; -} - -const WEB_GL = true; let g_webgl_painter = null; function paint_gui(canvas, input: RawInput) { - if (WEB_GL) { - if (g_webgl_painter === null) { - g_webgl_painter = wasm_bindgen.new_webgl_painter("canvas"); - } - wasm_bindgen.paint_webgl(g_webgl_painter, JSON.stringify(input)); - } else { - const commands = rust_gui(input); - for (const cmd of commands) { - commands.unshift({ - fill_color: { r: 0, g: 0, b: 0, a: 0 }, - kind: "clear", - }); - paint_command(canvas, cmd); - } + if (g_webgl_painter === null) { + g_webgl_painter = wasm_bindgen.new_webgl_painter("canvas"); } + wasm_bindgen.paint_webgl(g_webgl_painter, JSON.stringify(input)); } // ---------------------------------------------------------------------------- @@ -223,10 +49,11 @@ let g_mouse_pos = { x: -1000.0, y: -1000.0 }; let g_mouse_down = false; function auto_resize_canvas(canvas) { - if (WEB_GL) { + if (true) { canvas.setAttribute("width", window.innerWidth); canvas.setAttribute("height", window.innerHeight); } else { + // TODO: this stuff const pixels_per_point = window.devicePixelRatio || 1; const ctx = canvas.getContext("2d"); diff --git a/emgui/src/painter.rs b/emgui/src/painter.rs index 171f03ae..2e534c4b 100644 --- a/emgui/src/painter.rs +++ b/emgui/src/painter.rs @@ -1,5 +1,8 @@ #![allow(unused_variables)] +const ANTI_ALIAS: bool = true; +const AA_SIZE: f32 = 1.0; + /// Outputs render info in a format suitable for e.g. OpenGL. use crate::{ font::Font, @@ -33,15 +36,17 @@ pub enum PathType { use self::PathType::*; impl Frame { + fn triangle(&mut self, a: u32, b: u32, c: u32) { + self.indices.push(a); + self.indices.push(b); + self.indices.push(c); + } + /// Uniformly colored rectangle pub fn add_rect(&mut self, top_left: Vertex, bottom_right: Vertex) { let idx = self.vertices.len() as u32; - self.indices.push(idx + 0); - self.indices.push(idx + 1); - self.indices.push(idx + 2); - self.indices.push(idx + 2); - self.indices.push(idx + 1); - self.indices.push(idx + 3); + self.triangle(idx + 0, idx + 1, idx + 2); + self.triangle(idx + 2, idx + 1, idx + 3); let top_right = Vertex { pos: vec2(bottom_right.pos.x, top_left.pos.y), @@ -60,19 +65,37 @@ impl Frame { } pub fn fill_closed_path(&mut self, points: &[Vec2], normals: &[Vec2], color: Color) { - // TODO: use normals for anti-aliasing assert_eq!(points.len(), normals.len()); let n = points.len() as u32; - let idx = self.vertices.len() as u32; - self.vertices.extend(points.iter().map(|&pos| Vertex { + let vert = |pos, color| Vertex { pos, uv: (0, 0), color, - })); - for i in 2..n { - self.indices.push(idx); - self.indices.push(idx + i - 1); - self.indices.push(idx + i); + }; + if ANTI_ALIAS { + let color_outer = color.transparent(); + let idx_inner = self.vertices.len() as u32; + let idx_outer = idx_inner + 1; + for i in 2..n { + self.triangle(idx_inner + 2 * (i - 1), idx_inner, idx_inner + 2 * i); + } + let mut i0 = n - 1; + for i1 in 0..n { + let dm = normals[i1 as usize] * AA_SIZE * 0.5; + self.vertices.push(vert(points[i1 as usize] - dm, color)); + self.vertices + .push(vert(points[i1 as usize] + dm, color_outer)); + self.triangle(idx_inner + i1 * 2, idx_inner + i0 * 2, idx_outer + 2 * i0); + self.triangle(idx_outer + i0 * 2, idx_outer + i1 * 2, idx_inner + 2 * i1); + i0 = i1; + } + } else { + let idx = self.vertices.len() as u32; + self.vertices + .extend(points.iter().map(|&pos| vert(pos, color))); + for i in 2..n { + self.triangle(idx, idx + i - 1, idx + i); + } } } @@ -84,33 +107,87 @@ impl Frame { color: Color, width: f32, ) { - // TODO: anti-aliasing assert_eq!(points.len(), normals.len()); let n = points.len() as u32; let hw = width / 2.0; - let idx = self.vertices.len() as u32; - let last_index = if path_type == Closed { n } else { n - 1 }; - for i in 0..last_index { - self.indices.push(idx + (2 * i + 0) % (2 * n)); - self.indices.push(idx + (2 * i + 1) % (2 * n)); - self.indices.push(idx + (2 * i + 2) % (2 * n)); - self.indices.push(idx + (2 * i + 2) % (2 * n)); - self.indices.push(idx + (2 * i + 1) % (2 * n)); - self.indices.push(idx + (2 * i + 3) % (2 * n)); - } - for (&p, &n) in points.iter().zip(normals) { - self.vertices.push(Vertex { - pos: p + hw * n, - uv: (0, 0), - color, - }); - self.vertices.push(Vertex { - pos: p - hw * n, - uv: (0, 0), - color, - }); + let vert = |pos, color| Vertex { + pos, + uv: (0, 0), + color, + }; + + if ANTI_ALIAS { + let color_outer = color.transparent(); + let thin_line = width <= 1.0; + let mut color_inner = color; + if thin_line { + // Fade out as it gets thinner: + color_inner.a = (color_inner.a as f32 * width).round() as u8; + } + // TODO: line caps ? + let mut i0 = n - 1; + for i1 in 0..n { + let connect_with_previous = path_type == PathType::Closed || i1 > 0; + if thin_line { + let hw = (width - AA_SIZE) * 0.5; + let p = points[i1 as usize]; + let n = normals[i1 as usize]; + self.vertices.push(vert(p + n * AA_SIZE, color_outer)); + self.vertices.push(vert(p, color_inner)); + self.vertices.push(vert(p - n * AA_SIZE, color_outer)); + + if connect_with_previous { + self.triangle(idx + 3 * i0 + 0, idx + 3 * i0 + 1, idx + 3 * i1 + 0); + self.triangle(idx + 3 * i0 + 1, idx + 3 * i1 + 0, idx + 3 * i1 + 1); + + self.triangle(idx + 3 * i0 + 1, idx + 3 * i0 + 2, idx + 3 * i1 + 1); + self.triangle(idx + 3 * i0 + 2, idx + 3 * i1 + 1, idx + 3 * i1 + 2); + } + } else { + let hw = (width - AA_SIZE) * 0.5; + let p = points[i1 as usize]; + let n = normals[i1 as usize]; + self.vertices + .push(vert(p + n * (hw + AA_SIZE), color_outer)); + self.vertices.push(vert(p + n * (hw + 0.0), color_inner)); + self.vertices.push(vert(p - n * (hw + 0.0), color_inner)); + self.vertices + .push(vert(p - n * (hw + AA_SIZE), color_outer)); + + if connect_with_previous { + self.triangle(idx + 4 * i0 + 0, idx + 4 * i0 + 1, idx + 4 * i1 + 0); + self.triangle(idx + 4 * i0 + 1, idx + 4 * i1 + 0, idx + 4 * i1 + 1); + + self.triangle(idx + 4 * i0 + 1, idx + 4 * i0 + 2, idx + 4 * i1 + 1); + self.triangle(idx + 4 * i0 + 2, idx + 4 * i1 + 1, idx + 4 * i1 + 2); + + self.triangle(idx + 4 * i0 + 2, idx + 4 * i0 + 3, idx + 4 * i1 + 2); + self.triangle(idx + 4 * i0 + 3, idx + 4 * i1 + 2, idx + 4 * i1 + 3); + } + } + i0 = i1; + } + } else { + let last_index = if path_type == Closed { n } else { n - 1 }; + for i in 0..last_index { + self.triangle( + idx + (2 * i + 0) % (2 * n), + idx + (2 * i + 1) % (2 * n), + idx + (2 * i + 2) % (2 * n), + ); + self.triangle( + idx + (2 * i + 2) % (2 * n), + idx + (2 * i + 1) % (2 * n), + idx + (2 * i + 3) % (2 * n), + ); + } + + for (&p, &n) in points.iter().zip(normals) { + self.vertices.push(vert(p + hw * n, color)); + self.vertices.push(vert(p - hw * n, color)); + } } } } @@ -200,11 +277,11 @@ impl Painter { } } PaintCmd::Rect { + corner_radius, fill_color, outline, pos, size, - .. } => { path_points.clear(); path_normals.clear(); @@ -212,15 +289,43 @@ impl Painter { let min = *pos; let max = *pos + *size; - // TODO: rounded corners - path_points.push(vec2(min.x, min.y)); - path_normals.push(vec2(-1.0, -1.0)); - path_points.push(vec2(max.x, min.y)); - path_normals.push(vec2(1.0, -1.0)); - path_points.push(vec2(max.x, max.y)); - path_normals.push(vec2(1.0, 1.0)); - path_points.push(vec2(min.x, max.y)); - path_normals.push(vec2(-1.0, 1.0)); + let cr = corner_radius.min(size.x * 0.5).min(size.y * 0.5); + + if cr < 1.0 { + path_points.push(vec2(min.x, min.y)); + path_normals.push(vec2(-1.0, -1.0)); + path_points.push(vec2(max.x, min.y)); + path_normals.push(vec2(1.0, -1.0)); + path_points.push(vec2(max.x, max.y)); + path_normals.push(vec2(1.0, 1.0)); + path_points.push(vec2(min.x, max.y)); + path_normals.push(vec2(-1.0, 1.0)); + } else { + let n = 8; + + let mut add_arc = |c, quadrant| { + let quadrant = quadrant as f32; + + const RIGHT_ANGLE: f32 = TAU / 4.0; + for i in 0..=n { + let angle = remap( + i as f32, + 0.0, + n as f32, + quadrant * RIGHT_ANGLE, + (quadrant + 1.0) * RIGHT_ANGLE, + ); + let normal = vec2(angle.cos(), angle.sin()); + path_points.push(c + cr * normal); + path_normals.push(normal); + } + }; + + add_arc(vec2(max.x - cr, max.y - cr), 0); + add_arc(vec2(min.x + cr, max.y - cr), 1); + add_arc(vec2(min.x + cr, min.y + cr), 2); + add_arc(vec2(max.x - cr, min.y + cr), 3); + } if let Some(color) = fill_color { frame.fill_closed_path(&path_points, &path_normals, *color); diff --git a/emgui/src/types.rs b/emgui/src/types.rs index ec6b6529..09449461 100644 --- a/emgui/src/types.rs +++ b/emgui/src/types.rs @@ -59,6 +59,15 @@ pub struct Color { impl Color { pub const WHITE: Color = srgba(255, 255, 255, 255); + + pub fn transparent(self) -> Color { + Color { + r: self.r, + g: self.g, + b: self.b, + a: 0, + } + } } pub const fn srgba(r: u8, g: u8, b: u8, a: u8) -> Color {