From ca59b05f3fa1b9cdedd059399cdc3f84469a8764 Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Mon, 13 Apr 2026 12:38:47 +0200 Subject: [PATCH] vertex now is 88 bytes instead of 124 --- frontends/rioterm/src/renderer/mod.rs | 12 +- sugarloaf/src/lib.rs | 6 +- sugarloaf/src/renderer/batch.rs | 88 +------ sugarloaf/src/renderer/mod.rs | 58 +---- sugarloaf/src/renderer/renderer.metal | 281 +------------------- sugarloaf/src/renderer/renderer.wgsl | 284 +-------------------- sugarloaf/src/renderer/text_run_manager.rs | 4 +- sugarloaf/src/sugarloaf.rs | 12 - sugarloaf/src/sugarloaf/primitives.rs | 130 +--------- 9 files changed, 41 insertions(+), 834 deletions(-) diff --git a/frontends/rioterm/src/renderer/mod.rs b/frontends/rioterm/src/renderer/mod.rs index 892ce974..2b3c150d 100644 --- a/frontends/rioterm/src/renderer/mod.rs +++ b/frontends/rioterm/src/renderer/mod.rs @@ -1351,21 +1351,14 @@ impl Renderer { let width = quad.width / scale_factor; let height = quad.height / scale_factor; - // Scale corner radii and border widths let corner_radii = [ quad.corner_radii.top_left / scale_factor, quad.corner_radii.top_right / scale_factor, quad.corner_radii.bottom_right / scale_factor, quad.corner_radii.bottom_left / scale_factor, ]; - let border_widths = [ - quad.border_widths.top / scale_factor, - quad.border_widths.right / scale_factor, - quad.border_widths.bottom / scale_factor, - quad.border_widths.left / scale_factor, - ]; - // Render quad with rounded corners and borders + // Render quad with rounded corners sugarloaf.quad( None, x, @@ -1374,9 +1367,6 @@ impl Renderer { height, quad.background_color, corner_radii, - border_widths, - quad.border_color, - quad.border_style as i32, -0.1, // Negative depth = closer to camera (in front) 1, // Higher order renders on top ); diff --git a/sugarloaf/src/lib.rs b/sugarloaf/src/lib.rs index 80236f61..31886c6b 100644 --- a/sugarloaf/src/lib.rs +++ b/sugarloaf/src/lib.rs @@ -19,9 +19,9 @@ pub use crate::sugarloaf::{ Graphics, ResizeCommand, ResizeParameter, MAX_GRAPHIC_DIMENSIONS, }, primitives::{ - contains_braille_dot, drawable_character, is_private_user_area, BorderStyle, - Corners, CursorKind, DrawableChar, Edges, ImageProperties, Object, Quad, Rect, - RichText, RichTextLinesRange, RichTextRenderData, SugarCursor, + contains_braille_dot, drawable_character, is_private_user_area, Corners, + CursorKind, DrawableChar, ImageProperties, Object, Quad, Rect, RichText, + RichTextLinesRange, RichTextRenderData, SugarCursor, }, Colorspace, Sugarloaf, SugarloafBackend, SugarloafErrors, SugarloafRenderer, SugarloafWindow, SugarloafWindowSize, SugarloafWithErrors, diff --git a/sugarloaf/src/renderer/batch.rs b/sugarloaf/src/renderer/batch.rs index 33fc418f..11fd7997 100644 --- a/sugarloaf/src/renderer/batch.rs +++ b/sugarloaf/src/renderer/batch.rs @@ -36,18 +36,15 @@ pub struct Vertex { pub layers: [i32; 2], pub corner_radii: [f32; 4], // [top_left, top_right, bottom_right, bottom_left] / for underlines: [thickness, 0, 0, 0] pub rect_size: [f32; 2], // For underlines: [width, height] - pub border_widths: [f32; 4], // [top, right, bottom, left] - pub border_color: [f32; 4], // Border color RGBA - pub border_style: i32, // 0 = solid, 1 = dashed (for borders) pub underline_style: i32, // 0 = none, 1 = regular, 2 = dashed, 3 = dotted, 4 = curly pub clip_rect: [f32; 4], // [x, y, width, height] in physical pixels (0,0,0,0 = no clip) } impl Vertex { /// Vertex size in bytes: - /// pos[3] + color[4] + uv[2] + layers[2] + corner_radii[4] + rect_size[2] + border_widths[4] + border_color[4] + border_style + underline_style + clip_rect[4] - /// = 12 + 16 + 8 + 8 + 16 + 8 + 16 + 16 + 4 + 4 + 16 = 124 bytes - pub const SIZE: usize = 124; + /// pos[3] + color[4] + uv[2] + layers[2] + corner_radii[4] + rect_size[2] + underline_style + clip_rect[4] + /// = 12 + 16 + 8 + 8 + 16 + 8 + 4 + 16 = 88 bytes + pub const SIZE: usize = 88; /// Convert vertex to bytes for caching #[inline] @@ -174,9 +171,6 @@ impl Batch { layers, corner_radii: [0.0; 4], rect_size: [0.0, 0.0], - border_widths: [0.0; 4], - border_color: [0.0; 4], - border_style: 0, underline_style: 0, clip_rect: [0.0; 4], }; @@ -187,9 +181,6 @@ impl Batch { layers, corner_radii: [0.0; 4], rect_size: [0.0, 0.0], - border_widths: [0.0; 4], - border_color: [0.0; 4], - border_style: 0, underline_style: 0, clip_rect: [0.0; 4], }; @@ -200,9 +191,6 @@ impl Batch { layers, corner_radii: [0.0; 4], rect_size: [0.0, 0.0], - border_widths: [0.0; 4], - border_color: [0.0; 4], - border_style: 0, underline_style: 0, clip_rect: [0.0; 4], }; @@ -213,9 +201,6 @@ impl Batch { layers, corner_radii: [0.0; 4], rect_size: [0.0, 0.0], - border_widths: [0.0; 4], - border_color: [0.0; 4], - border_style: 0, underline_style: 0, clip_rect: [0.0; 4], }; @@ -273,9 +258,6 @@ impl Batch { layers, corner_radii: [0.0; 4], rect_size: [0.0, 0.0], - border_widths: [0.0; 4], - border_color: [0.0; 4], - border_style: 0, underline_style: 0, clip_rect: [0.0; 4], }); @@ -286,9 +268,6 @@ impl Batch { layers, corner_radii: [0.0; 4], rect_size: [0.0, 0.0], - border_widths: [0.0; 4], - border_color: [0.0; 4], - border_style: 0, underline_style: 0, clip_rect: [0.0; 4], }); @@ -299,9 +278,6 @@ impl Batch { layers, corner_radii: [0.0; 4], rect_size: [0.0, 0.0], - border_widths: [0.0; 4], - border_color: [0.0; 4], - border_style: 0, underline_style: 0, clip_rect: [0.0; 4], }); @@ -383,9 +359,6 @@ impl Batch { layers, corner_radii: [0.0; 4], rect_size: [0.0, 0.0], - border_widths: [0.0; 4], - border_color: [0.0; 4], - border_style: 0, underline_style: 0, clip_rect: [0.0; 4], }; @@ -396,9 +369,6 @@ impl Batch { layers, corner_radii: [0.0; 4], rect_size: [0.0, 0.0], - border_widths: [0.0; 4], - border_color: [0.0; 4], - border_style: 0, underline_style: 0, clip_rect: [0.0; 4], }; @@ -409,9 +379,6 @@ impl Batch { layers, corner_radii: [0.0; 4], rect_size: [0.0, 0.0], - border_widths: [0.0; 4], - border_color: [0.0; 4], - border_style: 0, underline_style: 0, clip_rect: [0.0; 4], }; @@ -422,9 +389,6 @@ impl Batch { layers, corner_radii: [0.0; 4], rect_size: [0.0, 0.0], - border_widths: [0.0; 4], - border_color: [0.0; 4], - border_style: 0, underline_style: 0, clip_rect: [0.0; 4], }; @@ -472,10 +436,7 @@ impl Batch { self.image = image; self.mask = mask; let layers = [self.image.unwrap_or(0), self.mask.unwrap_or(0)]; - self.push_rect( - rect, depth, color, coords, layers, [0.0; 4], [0.0; 4], [0.0; 4], 0, 0, - clip_rect, - ); + self.push_rect(rect, depth, color, coords, layers, [0.0; 4], 0, clip_rect); true } @@ -491,9 +452,6 @@ impl Batch { mask: Option, subpix: bool, corner_radii: [f32; 4], - border_widths: [f32; 4], - border_color: [f32; 4], - border_style: i32, clip_rect: [f32; 4], ) -> bool { if !self.vertices.is_empty() && subpix != self.subpix { @@ -516,9 +474,6 @@ impl Batch { coords, layers, corner_radii, - border_widths, - border_color, - border_style, 0, clip_rect, ); @@ -559,9 +514,6 @@ impl Batch { None, layers, corner_radii, - [0.0; 4], - [0.0; 4], - 0, underline_style, clip_rect, ); @@ -578,9 +530,6 @@ impl Batch { coords: Option<&[f32; 4]>, layers: [i32; 2], corner_radii: [f32; 4], - border_widths: [f32; 4], - border_color: [f32; 4], - border_style: i32, underline_style: i32, clip_rect: [f32; 4], ) { @@ -604,9 +553,6 @@ impl Batch { layers, corner_radii, rect_size: [w, h], - border_widths, - border_color, - border_style, underline_style, clip_rect, }; @@ -617,9 +563,6 @@ impl Batch { layers, corner_radii, rect_size: [w, h], - border_widths, - border_color, - border_style, underline_style, clip_rect, }; @@ -630,9 +573,6 @@ impl Batch { layers, corner_radii, rect_size: [w, h], - border_widths, - border_color, - border_style, underline_style, clip_rect, }; @@ -643,9 +583,6 @@ impl Batch { layers, corner_radii, rect_size: [w, h], - border_widths, - border_color, - border_style, underline_style, clip_rect, }; @@ -1034,9 +971,6 @@ impl BatchManager { None, false, corner_radii, - [0.0; 4], - [0.0; 4], - 0, cr, ) { @@ -1052,14 +986,11 @@ impl BatchManager { None, false, corner_radii, - [0.0; 4], - [0.0; 4], - 0, cr, ); } - /// Add a quad with per-corner radii and per-edge border widths + /// Add a quad with per-corner radii #[inline] #[allow(clippy::too_many_arguments)] pub fn quad( @@ -1068,9 +999,6 @@ impl BatchManager { depth: f32, background_color: &[f32; 4], corner_radii: [f32; 4], - border_widths: [f32; 4], - border_color: [f32; 4], - border_style: i32, order: u8, ) { let cr = self.clip_rect; @@ -1085,9 +1013,6 @@ impl BatchManager { None, false, corner_radii, - border_widths, - border_color, - border_style, cr, ) { @@ -1103,9 +1028,6 @@ impl BatchManager { None, false, corner_radii, - border_widths, - border_color, - border_style, cr, ); } diff --git a/sugarloaf/src/renderer/mod.rs b/sugarloaf/src/renderer/mod.rs index 58bd2c8b..40a302bf 100644 --- a/sugarloaf/src/renderer/mod.rs +++ b/sugarloaf/src/renderer/mod.rs @@ -115,19 +115,16 @@ impl MetalRenderer { .expect("Failed to get fragment function"); // Create vertex descriptor for rich text rendering - // Vertex layout (116 bytes total): + // Vertex layout (88 bytes total): // - pos: [f32; 3] = 12 bytes (offset 0) // - color: [f32; 4] = 16 bytes (offset 12) // - uv: [f32; 2] = 8 bytes (offset 28) // - layers: [i32; 2] = 8 bytes (offset 36) // - corner_radii: [f32; 4] = 16 bytes (offset 44) // - rect_size: [f32; 2] = 8 bytes (offset 60) - // - border_widths: [f32; 4] = 16 bytes (offset 68) - // - border_color: [f32; 4] = 16 bytes (offset 84) - // - border_style: i32 = 4 bytes (offset 100) - // - underline_style: i32 = 4 bytes (offset 104) - // - _padding: [i32; 2] = 8 bytes (offset 108) - // Total: 116 bytes + // - underline_style: i32 = 4 bytes (offset 68) + // - clip_rect: [f32; 4] = 16 bytes (offset 72) + // Total: 88 bytes let vertex_descriptor = VertexDescriptor::new(); let attributes = vertex_descriptor.attributes(); @@ -179,46 +176,22 @@ impl MetalRenderer { attributes.object_at(5).unwrap().set_offset(60); attributes.object_at(5).unwrap().set_buffer_index(0); - // Border widths (attribute 6) - vec4 + // Underline style (attribute 6) - i32 attributes .object_at(6) .unwrap() - .set_format(MTLVertexFormat::Float4); + .set_format(MTLVertexFormat::Int); attributes.object_at(6).unwrap().set_offset(68); attributes.object_at(6).unwrap().set_buffer_index(0); - // Border color (attribute 7) - vec4 + // Clip rect (attribute 7) - vec4 attributes .object_at(7) .unwrap() .set_format(MTLVertexFormat::Float4); - attributes.object_at(7).unwrap().set_offset(84); + attributes.object_at(7).unwrap().set_offset(72); attributes.object_at(7).unwrap().set_buffer_index(0); - // Border style (attribute 8) - i32 - attributes - .object_at(8) - .unwrap() - .set_format(MTLVertexFormat::Int); - attributes.object_at(8).unwrap().set_offset(100); - attributes.object_at(8).unwrap().set_buffer_index(0); - - // Underline style (attribute 9) - i32 - attributes - .object_at(9) - .unwrap() - .set_format(MTLVertexFormat::Int); - attributes.object_at(9).unwrap().set_offset(104); - attributes.object_at(9).unwrap().set_buffer_index(0); - - // Clip rect (attribute 10) - vec4 - attributes - .object_at(10) - .unwrap() - .set_format(MTLVertexFormat::Float4); - attributes.object_at(10).unwrap().set_offset(108); - attributes.object_at(10).unwrap().set_buffer_index(0); - // Set up buffer layout let layouts = vertex_descriptor.layouts(); layouts @@ -1907,7 +1880,7 @@ impl Renderer { ); } - /// Add a quad with per-corner radii and per-edge border widths + /// Add a quad with per-corner radii #[inline] #[allow(clippy::too_many_arguments)] pub fn quad( @@ -1918,9 +1891,6 @@ impl Renderer { height: f32, background_color: [f32; 4], corner_radii: [f32; 4], - border_widths: [f32; 4], - border_color: [f32; 4], - border_style: i32, depth: f32, order: u8, ) { @@ -1934,9 +1904,6 @@ impl Renderer { depth, &background_color, corner_radii, - border_widths, - border_color, - border_style, order, ); } @@ -2560,11 +2527,8 @@ impl WgpuRenderer { 3 => Sint32x2, // layers 4 => Float32x4, // corner_radii 5 => Float32x2, // rect_size - 6 => Float32x4, // border_widths - 7 => Float32x4, // border_color - 8 => Sint32, // border_style - 9 => Sint32, // underline_style - 10 => Float32x4, // clip_rect + 6 => Sint32, // underline_style + 7 => Float32x4, // clip_rect ), }], }, diff --git a/sugarloaf/src/renderer/renderer.metal b/sugarloaf/src/renderer/renderer.metal index 4e38af82..eff0a987 100644 --- a/sugarloaf/src/renderer/renderer.metal +++ b/sugarloaf/src/renderer/renderer.metal @@ -14,11 +14,8 @@ struct VertexInput { int2 layers [[attribute(3)]]; // Layers (8 bytes) float4 corner_radii [[attribute(4)]]; // Corner radii / for underlines: [thickness, 0, 0, 0] (16 bytes) float2 rect_size [[attribute(5)]]; // Rect size / underline [width, height] (8 bytes) - float4 border_widths [[attribute(6)]]; // Border widths [top, right, bottom, left] (16 bytes) - float4 border_color [[attribute(7)]]; // Border color RGBA (16 bytes) - int border_style [[attribute(8)]]; // 0 = solid, 1 = dashed (4 bytes) - int underline_style [[attribute(9)]]; // 0 = none, 1 = regular, 2 = dashed, 3 = dotted, 4 = curly (4 bytes) - float4 clip_rect [[attribute(10)]]; // [x, y, width, height] in pixels (16 bytes) + int underline_style [[attribute(6)]]; // 0 = none, 1 = regular, 2 = dashed, 3 = dotted, 4 = curly (4 bytes) + float4 clip_rect [[attribute(7)]]; // [x, y, width, height] in pixels (16 bytes) }; // Vertex output / Fragment input structure @@ -30,9 +27,6 @@ struct VertexOutput { int mask_layer; float4 corner_radii; float2 rect_size; - float4 border_widths; - float4 border_color; - int border_style [[flat]]; int underline_style [[flat]]; float4 clip_rect [[flat]]; }; @@ -49,14 +43,10 @@ vertex VertexOutput vs_main( out.mask_layer = input.layers.y; out.corner_radii = input.corner_radii; out.rect_size = input.rect_size; - out.border_widths = input.border_widths; - out.border_color = input.border_color; - out.border_style = input.border_style; out.underline_style = input.underline_style; out.clip_rect = input.clip_rect; - // Transform position - use float4 constructor with z=0.0, w=1.0 - out.position = globals.transform * float4(input.v_pos.xy, 0.0, 1.0); + out.position = globals.transform * float4(input.v_pos, 1.0); return out; } @@ -95,25 +85,6 @@ float quad_sdf(float2 corner_center_to_point, float corner_radius) { } } -// Approximates distance to the nearest point on a quarter ellipse. -// Sufficient for anti-aliasing when the ellipse is not very eccentric. -// The components of `point` are expected to be positive. -// Negative on the outside and positive on the inside. -float quarter_ellipse_sdf(float2 point, float2 radii) { - // Scale the space to treat the ellipse like a unit circle. - float2 circle_vec = point / radii; - float unit_circle_sdf = length(circle_vec) - 1.0; - // Approximate up-scaling of the length by using the average of the radii. - return unit_circle_sdf * (radii.x + radii.y) * -0.5; -} - -// Alpha blend: place `above` on top of `below` -float4 over(float4 below, float4 above) { - float alpha = above.a + below.a * (1.0 - above.a); - float3 color = (above.rgb * above.a + below.rgb * below.a * (1.0 - above.a)) / alpha; - return float4(color, alpha); -} - constant float PI_F = 3.1415926; // Modulus that has the same sign as `a`. @@ -121,32 +92,6 @@ float fmod_pos(float a, float b) { return a - b * trunc(a / b); } -// Returns the dash velocity of a corner given the dash velocity of the two -// sides, by returning the slower velocity (larger dashes). -float corner_dash_velocity(float dv1, float dv2) { - if (dv1 == 0.0) { - return dv2; - } else if (dv2 == 0.0) { - return dv1; - } else { - return min(dv1, dv2); - } -} - -// Returns alpha used to render antialiased dashes. -// `t` is within the dash when `fmod(t, period) < length`. -float dash_alpha(float t, float period, float dash_length, float dash_velocity, float antialias_threshold) { - float half_period = period / 2.0; - float half_length = dash_length / 2.0; - // Value in [-half_period, half_period]. - // The dash is in [-half_length, half_length]. - float centered = fmod_pos(t + half_period - half_length, period) - half_period; - // Signed distance for the dash, negative values are inside the dash. - float signed_distance = abs(centered) - half_length; - // Antialiased alpha based on the signed distance. - return saturate(antialias_threshold - signed_distance / dash_velocity); -} - // Calculate underline alpha for pattern rendering float underline_alpha(float x_pos, float y_pos, float rect_height, float thickness, int style) { // style 1: regular solid line @@ -241,14 +186,12 @@ fragment float4 fs_main( out = float4(out.xyz, input.f_color.a * mask_alpha); } - // Check if we have any rounding or borders + // Check if we have any rounding bool has_corners = input.corner_radii.x != 0.0 || input.corner_radii.y != 0.0 || input.corner_radii.z != 0.0 || input.corner_radii.w != 0.0; - bool has_borders = input.border_widths.x != 0.0 || input.border_widths.y != 0.0 || - input.border_widths.z != 0.0 || input.border_widths.w != 0.0; - // Fast path: no rounding and no borders - if (!has_corners && !has_borders) { + // Fast path: no rounding + if (!has_corners) { return out; } @@ -256,8 +199,7 @@ fragment float4 fs_main( float2 half_size = size / 2.0; // Convert UV (0-1) to local position centered at rect center - float2 local_pos = (input.f_uv - 0.5) * size; - float2 center_to_point = local_pos; + float2 center_to_point = (input.f_uv - 0.5) * size; // Antialiasing threshold float antialias_threshold = 0.5; @@ -265,21 +207,12 @@ fragment float4 fs_main( // Pick the corner radius for this quadrant float corner_radius = pick_corner_radius(center_to_point, input.corner_radii); - // Pick the border widths for this quadrant - float2 border = float2( - center_to_point.x < 0.0 ? input.border_widths.w : input.border_widths.y, // left or right - center_to_point.y < 0.0 ? input.border_widths.x : input.border_widths.z // top or bottom - ); - // Vector from corner to point (mirrored to bottom-right quadrant) float2 corner_to_point = abs(center_to_point) - half_size; // Vector from corner center (for rounded corner) to point float2 corner_center_to_point = corner_to_point + corner_radius; - // Check if near rounded corner - bool is_near_rounded_corner = corner_center_to_point.x >= 0.0 && corner_center_to_point.y >= 0.0; - // Outer SDF: distance to the outer edge of the quad float outer_sdf = quad_sdf(corner_center_to_point, corner_radius); @@ -288,203 +221,5 @@ fragment float4 fs_main( discard_fragment(); } - // 0-width borders are reduced so that `inner_sdf >= antialias_threshold`. - // The purpose of this is to not draw antialiasing pixels in this case. - float2 reduced_border = float2( - border.x == 0.0 ? -antialias_threshold : border.x, - border.y == 0.0 ? -antialias_threshold : border.y - ); - - // Vector from straight border inner corner to point. - float2 straight_border_inner_corner_to_point = corner_to_point + reduced_border; - - // Whether the point is beyond the inner edge of the straight border. - bool is_beyond_inner_straight_border = - straight_border_inner_corner_to_point.x > 0.0 || - straight_border_inner_corner_to_point.y > 0.0; - - // Whether the point is far enough inside the quad, such that the pixels are - // not affected by the straight border. - bool is_within_inner_straight_border = - straight_border_inner_corner_to_point.x < -antialias_threshold && - straight_border_inner_corner_to_point.y < -antialias_threshold; - - // Fast path for points that must be part of the background. - if (is_within_inner_straight_border && !is_near_rounded_corner) { - return input.f_color; - } - - // Approximate signed distance of the point to the inside edge of the quad's - // border. It is negative outside this edge (within the border), and - // positive inside. - float inner_sdf = 0.0; - if (corner_center_to_point.x <= 0.0 || corner_center_to_point.y <= 0.0) { - // Fast path for straight borders. - inner_sdf = -max(straight_border_inner_corner_to_point.x, - straight_border_inner_corner_to_point.y); - } else if (is_beyond_inner_straight_border) { - // Fast path for points that must be outside the inner edge. - inner_sdf = -1.0; - } else if (reduced_border.x == reduced_border.y) { - // Fast path for circular inner edge. - inner_sdf = -(outer_sdf + reduced_border.x); - } else { - // Elliptical inner edge - use quarter_ellipse_sdf for accuracy. - float2 ellipse_radii = max(float2(0.0), float2(corner_radius) - reduced_border); - inner_sdf = quarter_ellipse_sdf(corner_center_to_point, ellipse_radii); - } - - // Negative when inside the border - float border_sdf = max(inner_sdf, outer_sdf); - - // Check if we have corners - bool unrounded = input.corner_radii.x == 0.0 && - input.corner_radii.y == 0.0 && - input.corner_radii.z == 0.0 && - input.corner_radii.w == 0.0; - - float4 color = input.f_color; - if (border_sdf < antialias_threshold) { - float4 border_color = input.border_color; - - // Dashed border logic when border_style == 1 - if (input.border_style == 1) { - // Position along the perimeter in "dash space" - float t = 0.0; - float max_t = 0.0; - - // Border width is proportional to dash size - // Dash pattern: (2 * border width) dash, (1 * border width) gap - float dash_length_per_width = 2.0; - float dash_gap_per_width = 1.0; - float dash_period_per_width = dash_length_per_width + dash_gap_per_width; - - // Dash velocity = dash periods per pixel - float dash_velocity_val = 0.0; - float dv_numerator = 1.0 / dash_period_per_width; - - // Convert UV to point position relative to bounds origin - float2 point = input.f_uv * size; - - if (unrounded) { - // For unrounded corners, dashes are laid out separately on each side - bool is_horizontal = corner_center_to_point.x < corner_center_to_point.y; - float border_width = is_horizontal ? border.x : border.y; - dash_velocity_val = dv_numerator / border_width; - t = (is_horizontal ? point.x : point.y) * dash_velocity_val; - max_t = (is_horizontal ? size.x : size.y) * dash_velocity_val; - } else { - // For rounded corners, dashes flow around the entire perimeter - float r_tr = input.corner_radii.y; - float r_br = input.corner_radii.z; - float r_bl = input.corner_radii.w; - float r_tl = input.corner_radii.x; - - float w_t = input.border_widths.x; - float w_r = input.border_widths.y; - float w_b = input.border_widths.z; - float w_l = input.border_widths.w; - - // Straight side dash velocities - float dv_t = w_t <= 0.0 ? 0.0 : dv_numerator / w_t; - float dv_r = w_r <= 0.0 ? 0.0 : dv_numerator / w_r; - float dv_b = w_b <= 0.0 ? 0.0 : dv_numerator / w_b; - float dv_l = w_l <= 0.0 ? 0.0 : dv_numerator / w_l; - - // Straight side lengths in dash space - float s_t = (size.x - r_tl - r_tr) * dv_t; - float s_r = (size.y - r_tr - r_br) * dv_r; - float s_b = (size.x - r_br - r_bl) * dv_b; - float s_l = (size.y - r_bl - r_tl) * dv_l; - - float corner_dv_tr = corner_dash_velocity(dv_t, dv_r); - float corner_dv_br = corner_dash_velocity(dv_b, dv_r); - float corner_dv_bl = corner_dash_velocity(dv_b, dv_l); - float corner_dv_tl = corner_dash_velocity(dv_t, dv_l); - - // Corner lengths in dash space - float c_tr = r_tr * (PI_F / 2.0) * corner_dv_tr; - float c_br = r_br * (PI_F / 2.0) * corner_dv_br; - float c_bl = r_bl * (PI_F / 2.0) * corner_dv_bl; - float c_tl = r_tl * (PI_F / 2.0) * corner_dv_tl; - - // Cumulative dash space up to each segment - float upto_tr = s_t; - float upto_r = upto_tr + c_tr; - float upto_br = upto_r + s_r; - float upto_b = upto_br + c_br; - float upto_bl = upto_b + s_b; - float upto_l = upto_bl + c_bl; - float upto_tl = upto_l + s_l; - max_t = upto_tl + c_tl; - - if (is_near_rounded_corner) { - float radians = atan2(corner_center_to_point.y, corner_center_to_point.x); - float corner_t = radians * corner_radius; - - if (center_to_point.x >= 0.0) { - if (center_to_point.y < 0.0) { - dash_velocity_val = corner_dv_tr; - t = upto_r - corner_t * dash_velocity_val; - } else { - dash_velocity_val = corner_dv_br; - t = upto_br + corner_t * dash_velocity_val; - } - } else { - if (center_to_point.y >= 0.0) { - dash_velocity_val = corner_dv_bl; - t = upto_l - corner_t * dash_velocity_val; - } else { - dash_velocity_val = corner_dv_tl; - t = upto_tl + corner_t * dash_velocity_val; - } - } - } else { - // Straight borders - bool is_horizontal = corner_center_to_point.x < corner_center_to_point.y; - if (is_horizontal) { - if (center_to_point.y < 0.0) { - dash_velocity_val = dv_t; - t = (point.x - r_tl) * dash_velocity_val; - } else { - dash_velocity_val = dv_b; - t = upto_bl - (point.x - r_bl) * dash_velocity_val; - } - } else { - if (center_to_point.x < 0.0) { - dash_velocity_val = dv_l; - t = upto_tl - (point.y - r_tl) * dash_velocity_val; - } else { - dash_velocity_val = dv_r; - t = upto_r + (point.y - r_tr) * dash_velocity_val; - } - } - } - } - - float dash_len = dash_length_per_width / dash_period_per_width; - - // Straight borders should start and end with a dash - max_t -= unrounded ? dash_len : 0.0; - if (max_t >= 1.0) { - float dash_count = floor(max_t); - float dash_period = max_t / dash_count; - border_color.a *= dash_alpha(t, dash_period, dash_len, dash_velocity_val, antialias_threshold); - } else if (unrounded) { - float dash_gap = max_t - dash_len; - if (dash_gap > 0.0) { - float dash_period = dash_len + dash_gap; - border_color.a *= dash_alpha(t, dash_period, dash_len, dash_velocity_val, antialias_threshold); - } - } - } - - // Blend the border on top of the background and then linearly interpolate - // between the two as we slide inside the background. - float4 blended_border = over(input.f_color, border_color); - color = mix(input.f_color, blended_border, - saturate(antialias_threshold - inner_sdf)); - } - - return color * float4(1.0, 1.0, 1.0, saturate(antialias_threshold - outer_sdf)); + return out * float4(1.0, 1.0, 1.0, saturate(antialias_threshold - outer_sdf)); } diff --git a/sugarloaf/src/renderer/renderer.wgsl b/sugarloaf/src/renderer/renderer.wgsl index adc0c490..b90d9e47 100644 --- a/sugarloaf/src/renderer/renderer.wgsl +++ b/sugarloaf/src/renderer/renderer.wgsl @@ -15,11 +15,8 @@ struct VertexInput { @location(3) layers: vec2, @location(4) corner_radii: vec4, // [top_left, top_right, bottom_right, bottom_left] / for underlines: [thickness, 0, 0, 0] @location(5) rect_size: vec2, // For underlines: [width, height] - @location(6) border_widths: vec4, // [top, right, bottom, left] - @location(7) border_color: vec4, // Border color RGBA - @location(8) border_style: i32, // 0 = solid, 1 = dashed - @location(9) underline_style: i32, // 0 = none, 1 = regular, 2 = dashed, 3 = dotted, 4 = curly - @location(10) clip_rect: vec4, // [x, y, width, height] in pixels (0,0,0,0 = no clip) + @location(6) underline_style: i32, // 0 = none, 1 = regular, 2 = dashed, 3 = dotted, 4 = curly + @location(7) clip_rect: vec4, // [x, y, width, height] in pixels (0,0,0,0 = no clip) } struct VertexOutput { @@ -30,11 +27,8 @@ struct VertexOutput { @location(3) mask_layer: i32, @location(4) corner_radii: vec4, @location(5) rect_size: vec2, - @location(6) border_widths: vec4, - @location(7) border_color: vec4, - @location(8) @interpolate(flat) border_style: i32, - @location(9) @interpolate(flat) underline_style: i32, - @location(10) @interpolate(flat) clip_rect: vec4, + @location(6) @interpolate(flat) underline_style: i32, + @location(7) @interpolate(flat) clip_rect: vec4, } @vertex @@ -46,13 +40,10 @@ fn vs_main(input: VertexInput) -> VertexOutput { out.mask_layer = input.layers.y; out.corner_radii = input.corner_radii; out.rect_size = input.rect_size; - out.border_widths = input.border_widths; - out.border_color = input.border_color; - out.border_style = input.border_style; out.underline_style = input.underline_style; out.clip_rect = input.clip_rect; - out.position = globals.transform * vec4(input.v_pos.xy, 0.0, 1.0); + out.position = globals.transform * vec4(input.v_pos, 1.0); return out; } @@ -90,25 +81,6 @@ fn quad_sdf(corner_center_to_point: vec2, corner_radius: f32) -> f32 { } } -// Approximates distance to the nearest point on a quarter ellipse. -// Sufficient for anti-aliasing when the ellipse is not very eccentric. -// The components of `point` are expected to be positive. -// Negative on the outside and positive on the inside. -fn quarter_ellipse_sdf(point: vec2, radii: vec2) -> f32 { - // Scale the space to treat the ellipse like a unit circle. - let circle_vec = point / radii; - let unit_circle_sdf = length(circle_vec) - 1.0; - // Approximate up-scaling of the length by using the average of the radii. - return unit_circle_sdf * (radii.x + radii.y) * -0.5; -} - -// Alpha blend: place `above` on top of `below` -fn over(below: vec4, above: vec4) -> vec4 { - let alpha = above.a + below.a * (1.0 - above.a); - let color = (above.rgb * above.a + below.rgb * below.a * (1.0 - above.a)) / alpha; - return vec4(color, alpha); -} - const M_PI_F: f32 = 3.1415926; // Modulus that has the same sign as `a`. @@ -116,32 +88,6 @@ fn fmod(a: f32, b: f32) -> f32 { return a - b * trunc(a / b); } -// Returns the dash velocity of a corner given the dash velocity of the two -// sides, by returning the slower velocity (larger dashes). -fn corner_dash_velocity(dv1: f32, dv2: f32) -> f32 { - if (dv1 == 0.0) { - return dv2; - } else if (dv2 == 0.0) { - return dv1; - } else { - return min(dv1, dv2); - } -} - -// Returns alpha used to render antialiased dashes. -// `t` is within the dash when `fmod(t, period) < length`. -fn dash_alpha(t: f32, period: f32, dash_length: f32, dash_velocity: f32, antialias_threshold: f32) -> f32 { - let half_period = period / 2.0; - let half_length = dash_length / 2.0; - // Value in [-half_period, half_period]. - // The dash is in [-half_length, half_length]. - let centered = fmod(t + half_period - half_length, period) - half_period; - // Signed distance for the dash, negative values are inside the dash. - let signed_distance = abs(centered) - half_length; - // Antialiased alpha based on the signed distance. - return saturate(antialias_threshold - signed_distance / dash_velocity); -} - // Calculate underline alpha for pattern rendering fn underline_alpha(x_pos: f32, y_pos: f32, rect_height: f32, thickness: f32, style: i32) -> f32 { // style 1: regular solid line @@ -232,14 +178,12 @@ fn fs_main(input: VertexOutput) -> @location(0) vec4 { out = vec4(out.xyz, input.f_color.a * tex_alpha); } - // Check if we have any rounding or borders + // Check if we have any rounding let has_corners = input.corner_radii.x != 0.0 || input.corner_radii.y != 0.0 || input.corner_radii.z != 0.0 || input.corner_radii.w != 0.0; - let has_borders = input.border_widths.x != 0.0 || input.border_widths.y != 0.0 || - input.border_widths.z != 0.0 || input.border_widths.w != 0.0; - // Fast path: no rounding and no borders - if (!has_corners && !has_borders) { + // Fast path: no rounding + if (!has_corners) { return out; } @@ -247,8 +191,7 @@ fn fs_main(input: VertexOutput) -> @location(0) vec4 { let half_size = size / 2.0; // Convert UV (0-1) to local position centered at rect center - let local_pos = (input.f_uv - 0.5) * size; - let center_to_point = local_pos; + let center_to_point = (input.f_uv - 0.5) * size; // Antialiasing threshold let antialias_threshold = 0.5; @@ -256,21 +199,12 @@ fn fs_main(input: VertexOutput) -> @location(0) vec4 { // Pick the corner radius for this quadrant let corner_radius = pick_corner_radius(center_to_point, input.corner_radii); - // Pick the border widths for this quadrant - let border = vec2( - select(input.border_widths.y, input.border_widths.w, center_to_point.x < 0.0), // right or left - select(input.border_widths.z, input.border_widths.x, center_to_point.y < 0.0) // bottom or top - ); - // Vector from corner to point (mirrored to bottom-right quadrant) let corner_to_point = abs(center_to_point) - half_size; // Vector from corner center (for rounded corner) to point let corner_center_to_point = corner_to_point + corner_radius; - // Check if near rounded corner - let is_near_rounded_corner = corner_center_to_point.x >= 0.0 && corner_center_to_point.y >= 0.0; - // Outer SDF: distance to the outer edge of the quad let outer_sdf = quad_sdf(corner_center_to_point, corner_radius); @@ -279,203 +213,5 @@ fn fs_main(input: VertexOutput) -> @location(0) vec4 { discard; } - // 0-width borders are reduced so that `inner_sdf >= antialias_threshold`. - // The purpose of this is to not draw antialiasing pixels in this case. - let reduced_border = vec2( - select(border.x, -antialias_threshold, border.x == 0.0), - select(border.y, -antialias_threshold, border.y == 0.0) - ); - - // Vector from straight border inner corner to point. - let straight_border_inner_corner_to_point = corner_to_point + reduced_border; - - // Whether the point is beyond the inner edge of the straight border. - let is_beyond_inner_straight_border = - straight_border_inner_corner_to_point.x > 0.0 || - straight_border_inner_corner_to_point.y > 0.0; - - // Whether the point is far enough inside the quad, such that the pixels are - // not affected by the straight border. - let is_within_inner_straight_border = - straight_border_inner_corner_to_point.x < -antialias_threshold && - straight_border_inner_corner_to_point.y < -antialias_threshold; - - // Fast path for points that must be part of the background. - if (is_within_inner_straight_border && !is_near_rounded_corner) { - return input.f_color; - } - - // Approximate signed distance of the point to the inside edge of the quad's - // border. It is negative outside this edge (within the border), and - // positive inside. - var inner_sdf = 0.0; - if (corner_center_to_point.x <= 0.0 || corner_center_to_point.y <= 0.0) { - // Fast path for straight borders. - inner_sdf = -max(straight_border_inner_corner_to_point.x, - straight_border_inner_corner_to_point.y); - } else if (is_beyond_inner_straight_border) { - // Fast path for points that must be outside the inner edge. - inner_sdf = -1.0; - } else if (reduced_border.x == reduced_border.y) { - // Fast path for circular inner edge. - inner_sdf = -(outer_sdf + reduced_border.x); - } else { - // Elliptical inner edge - use quarter_ellipse_sdf for accuracy. - let ellipse_radii = max(vec2(0.0), vec2(corner_radius) - reduced_border); - inner_sdf = quarter_ellipse_sdf(corner_center_to_point, ellipse_radii); - } - - // Negative when inside the border - let border_sdf = max(inner_sdf, outer_sdf); - - // Check if we have corners - let unrounded = input.corner_radii.x == 0.0 && - input.corner_radii.y == 0.0 && - input.corner_radii.z == 0.0 && - input.corner_radii.w == 0.0; - - var color = input.f_color; - if (border_sdf < antialias_threshold) { - var border_color = input.border_color; - - // Dashed border logic when border_style == 1 - if (input.border_style == 1) { - // Position along the perimeter in "dash space" - var t = 0.0; - var max_t = 0.0; - - // Border width is proportional to dash size - // Dash pattern: (2 * border width) dash, (1 * border width) gap - let dash_length_per_width = 2.0; - let dash_gap_per_width = 1.0; - let dash_period_per_width = dash_length_per_width + dash_gap_per_width; - - // Dash velocity = dash periods per pixel - var dash_velocity = 0.0; - let dv_numerator = 1.0 / dash_period_per_width; - - // Convert UV to point position relative to bounds origin - let point = input.f_uv * size; - - if (unrounded) { - // For unrounded corners, dashes are laid out separately on each side - let is_horizontal = corner_center_to_point.x < corner_center_to_point.y; - let border_width = select(border.y, border.x, is_horizontal); - dash_velocity = dv_numerator / border_width; - t = select(point.y, point.x, is_horizontal) * dash_velocity; - max_t = select(size.y, size.x, is_horizontal) * dash_velocity; - } else { - // For rounded corners, dashes flow around the entire perimeter - let r_tr = input.corner_radii.y; - let r_br = input.corner_radii.z; - let r_bl = input.corner_radii.w; - let r_tl = input.corner_radii.x; - - let w_t = input.border_widths.x; - let w_r = input.border_widths.y; - let w_b = input.border_widths.z; - let w_l = input.border_widths.w; - - // Straight side dash velocities - let dv_t = select(dv_numerator / w_t, 0.0, w_t <= 0.0); - let dv_r = select(dv_numerator / w_r, 0.0, w_r <= 0.0); - let dv_b = select(dv_numerator / w_b, 0.0, w_b <= 0.0); - let dv_l = select(dv_numerator / w_l, 0.0, w_l <= 0.0); - - // Straight side lengths in dash space - let s_t = (size.x - r_tl - r_tr) * dv_t; - let s_r = (size.y - r_tr - r_br) * dv_r; - let s_b = (size.x - r_br - r_bl) * dv_b; - let s_l = (size.y - r_bl - r_tl) * dv_l; - - let corner_dv_tr = corner_dash_velocity(dv_t, dv_r); - let corner_dv_br = corner_dash_velocity(dv_b, dv_r); - let corner_dv_bl = corner_dash_velocity(dv_b, dv_l); - let corner_dv_tl = corner_dash_velocity(dv_t, dv_l); - - // Corner lengths in dash space - let c_tr = r_tr * (M_PI_F / 2.0) * corner_dv_tr; - let c_br = r_br * (M_PI_F / 2.0) * corner_dv_br; - let c_bl = r_bl * (M_PI_F / 2.0) * corner_dv_bl; - let c_tl = r_tl * (M_PI_F / 2.0) * corner_dv_tl; - - // Cumulative dash space up to each segment - let upto_tr = s_t; - let upto_r = upto_tr + c_tr; - let upto_br = upto_r + s_r; - let upto_b = upto_br + c_br; - let upto_bl = upto_b + s_b; - let upto_l = upto_bl + c_bl; - let upto_tl = upto_l + s_l; - max_t = upto_tl + c_tl; - - if (is_near_rounded_corner) { - let radians = atan2(corner_center_to_point.y, corner_center_to_point.x); - let corner_t = radians * corner_radius; - - if (center_to_point.x >= 0.0) { - if (center_to_point.y < 0.0) { - dash_velocity = corner_dv_tr; - t = upto_r - corner_t * dash_velocity; - } else { - dash_velocity = corner_dv_br; - t = upto_br + corner_t * dash_velocity; - } - } else { - if (center_to_point.y >= 0.0) { - dash_velocity = corner_dv_bl; - t = upto_l - corner_t * dash_velocity; - } else { - dash_velocity = corner_dv_tl; - t = upto_tl + corner_t * dash_velocity; - } - } - } else { - // Straight borders - let is_horizontal = corner_center_to_point.x < corner_center_to_point.y; - if (is_horizontal) { - if (center_to_point.y < 0.0) { - dash_velocity = dv_t; - t = (point.x - r_tl) * dash_velocity; - } else { - dash_velocity = dv_b; - t = upto_bl - (point.x - r_bl) * dash_velocity; - } - } else { - if (center_to_point.x < 0.0) { - dash_velocity = dv_l; - t = upto_tl - (point.y - r_tl) * dash_velocity; - } else { - dash_velocity = dv_r; - t = upto_r + (point.y - r_tr) * dash_velocity; - } - } - } - } - - let dash_len = dash_length_per_width / dash_period_per_width; - - // Straight borders should start and end with a dash - max_t -= select(0.0, dash_len, unrounded); - if (max_t >= 1.0) { - let dash_count = floor(max_t); - let dash_period = max_t / dash_count; - border_color.a *= dash_alpha(t, dash_period, dash_len, dash_velocity, antialias_threshold); - } else if (unrounded) { - let dash_gap = max_t - dash_len; - if (dash_gap > 0.0) { - let dash_period = dash_len + dash_gap; - border_color.a *= dash_alpha(t, dash_period, dash_len, dash_velocity, antialias_threshold); - } - } - } - - // Blend the border on top of the background and then linearly interpolate - // between the two as we slide inside the background. - let blended_border = over(input.f_color, border_color); - color = mix(input.f_color, blended_border, - saturate(antialias_threshold - inner_sdf)); - } - - return color * vec4(1.0, 1.0, 1.0, saturate(antialias_threshold - outer_sdf)); + return out * vec4(1.0, 1.0, 1.0, saturate(antialias_threshold - outer_sdf)); } diff --git a/sugarloaf/src/renderer/text_run_manager.rs b/sugarloaf/src/renderer/text_run_manager.rs index 20b3aab5..85dfe1d3 100644 --- a/sugarloaf/src/renderer/text_run_manager.rs +++ b/sugarloaf/src/renderer/text_run_manager.rs @@ -136,8 +136,8 @@ mod tests { #[test] fn test_vertex_positioning() { - // Create mock vertex data for one complete vertex (116 bytes) - // Vertex structure: pos[3] + color[4] + uv[2] + layers[2] + corner_radii[4] + rect_size[2] + border_widths[4] + border_color[4] + // Create mock vertex data for one complete vertex (88 bytes) + // Vertex structure: pos[3] + color[4] + uv[2] + layers[2] + corner_radii[4] + rect_size[2] + underline_style + clip_rect[4] let mut vertices = Vec::new(); // Position: (10.0, 20.0, 0.0) - 12 bytes diff --git a/sugarloaf/src/sugarloaf.rs b/sugarloaf/src/sugarloaf.rs index 61d0194d..827069ec 100644 --- a/sugarloaf/src/sugarloaf.rs +++ b/sugarloaf/src/sugarloaf.rs @@ -656,9 +656,6 @@ impl Sugarloaf<'_> { height: f32, background_color: [f32; 4], corner_radii: [f32; 4], - border_widths: [f32; 4], - border_color: [f32; 4], - border_style: i32, depth: f32, order: u8, ) { @@ -673,12 +670,6 @@ impl Sugarloaf<'_> { corner_radii[2] * scale, corner_radii[3] * scale, ]; - let scaled_border_widths = [ - border_widths[0] * scale, - border_widths[1] * scale, - border_widths[2] * scale, - border_widths[3] * scale, - ]; // For now, quad is always rendered immediately (no caching support yet) self.renderer.quad( @@ -688,9 +679,6 @@ impl Sugarloaf<'_> { scaled_height, background_color, scaled_corner_radii, - scaled_border_widths, - border_color, - border_style, depth, order, ); diff --git a/sugarloaf/src/sugarloaf/primitives.rs b/sugarloaf/src/sugarloaf/primitives.rs index a2eac0a3..a2582ba1 100644 --- a/sugarloaf/src/sugarloaf/primitives.rs +++ b/sugarloaf/src/sugarloaf/primitives.rs @@ -72,65 +72,6 @@ impl From<[f32; 4]> for Corners { } } -/// Edge widths for borders. -/// Each edge can have a different width. -#[derive(Clone, Copy, Debug, PartialEq, Default)] -#[repr(C)] -pub struct Edges { - pub top: f32, - pub right: f32, - pub bottom: f32, - pub left: f32, -} - -impl Edges { - /// Create edges with the same width for all edges. - #[inline] - pub fn all(width: f32) -> Self { - Self { - top: width, - right: width, - bottom: width, - left: width, - } - } - - /// Create edges with zero width (no borders). - #[inline] - pub fn zero() -> Self { - Self::default() - } - - /// Check if all edges are zero (no borders). - #[inline] - pub fn is_zero(&self) -> bool { - self.top == 0.0 && self.right == 0.0 && self.bottom == 0.0 && self.left == 0.0 - } - - /// Convert to array [top, right, bottom, left]. - #[inline] - pub fn to_array(&self) -> [f32; 4] { - [self.top, self.right, self.bottom, self.left] - } -} - -impl From for Edges { - fn from(width: f32) -> Self { - Self::all(width) - } -} - -impl From<[f32; 4]> for Edges { - fn from(arr: [f32; 4]) -> Self { - Self { - top: arr[0], - right: arr[1], - bottom: arr[2], - left: arr[3], - } - } -} - #[derive(Debug, PartialEq, Copy, Clone)] #[repr(u8)] pub enum CursorKind { @@ -250,17 +191,7 @@ impl Rect { } } -/// Border style for quads -#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] -#[repr(u32)] -pub enum BorderStyle { - #[default] - Solid = 0, - Dashed = 1, -} - -/// A quad with per-corner radii and per-edge border widths. -/// This is used for rounded panel borders. +/// A quad with per-corner radii. #[derive(Clone, Copy, Debug, PartialEq)] pub struct Quad { pub x: f32, @@ -269,13 +200,9 @@ pub struct Quad { pub height: f32, pub background_color: [f32; 4], pub corner_radii: Corners, - pub border_widths: Edges, - pub border_color: [f32; 4], - pub border_style: BorderStyle, } impl Quad { - #[allow(clippy::too_many_arguments)] pub fn new( x: f32, y: f32, @@ -283,58 +210,6 @@ impl Quad { height: f32, background_color: [f32; 4], corner_radii: Corners, - border_widths: Edges, - border_color: [f32; 4], - ) -> Self { - Self { - x, - y, - width, - height, - background_color, - corner_radii, - border_widths, - border_color, - border_style: BorderStyle::Solid, - } - } - - /// Create a quad with uniform corner radius and uniform border width - #[allow(clippy::too_many_arguments)] - pub fn with_uniform_border( - x: f32, - y: f32, - width: f32, - height: f32, - background_color: [f32; 4], - corner_radius: f32, - border_width: f32, - border_color: [f32; 4], - ) -> Self { - Self { - x, - y, - width, - height, - background_color, - corner_radii: Corners::all(corner_radius), - border_widths: Edges::all(border_width), - border_color, - border_style: BorderStyle::Solid, - } - } - - /// Create a quad with dashed border - #[allow(clippy::too_many_arguments)] - pub fn with_dashed_border( - x: f32, - y: f32, - width: f32, - height: f32, - background_color: [f32; 4], - corner_radii: Corners, - border_widths: Edges, - border_color: [f32; 4], ) -> Self { Self { x, @@ -343,9 +218,6 @@ impl Quad { height, background_color, corner_radii, - border_widths, - border_color, - border_style: BorderStyle::Dashed, } } } -- 2.51.2