From 2bc7429dd052935f44ef15359b0e6bd7dc2d6d65 Mon Sep 17 00:00:00 2001 From: wjian23 Date: Sun, 17 Sep 2023 22:20:27 +0800 Subject: [PATCH 1/7] =?UTF-8?q?feat(gpu):=20=F0=9F=8E=B8=20radial=20gradie?= =?UTF-8?q?nt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 2 +- gpu/src/gpu_backend.rs | 93 +++++++- gpu/src/lib.rs | 66 ++++++ gpu/src/wgpu_impl.rs | 49 ++++- .../wgpu_impl/draw_radial_gradient_pass.rs | 200 ++++++++++++++++++ .../shaders/radial_gradient_triangles.wgsl | 192 +++++++++++++++++ painter/src/color.rs | 16 ++ painter/src/lib.rs | 2 +- painter/src/painter.rs | 39 +++- painter/src/style.rs | 4 +- painter/src/svg.rs | 109 ++++++++-- ribir/src/winit_shell_wnd.rs | 1 + 12 files changed, 737 insertions(+), 36 deletions(-) create mode 100644 gpu/src/wgpu_impl/draw_radial_gradient_pass.rs create mode 100644 gpu/src/wgpu_impl/shaders/radial_gradient_triangles.wgsl diff --git a/Cargo.toml b/Cargo.toml index 3e287e292..89e0ba599 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -82,7 +82,7 @@ tiny-skia-path = {version = "0.11.0"} unicode-bidi = "0.3.7" unicode-script = "0.5.4" unicode-segmentation = "1.9.0" -usvg = {version = "0.33.0", default-features = false} +usvg = { version= "0.35.0", default-features = false } webbrowser = "0.8.8" wgpu = {version = "0.16.0"} winit = {version = "0.28.5", default-features = false, features = ["x11", "wayland", "wayland-dlopen"]} diff --git a/gpu/src/gpu_backend.rs b/gpu/src/gpu_backend.rs index 1dd406889..7549750aa 100644 --- a/gpu/src/gpu_backend.rs +++ b/gpu/src/gpu_backend.rs @@ -1,5 +1,8 @@ use self::textures_mgr::{TextureID, TexturesMgr}; -use crate::{ColorAttr, GPUBackendImpl, ImgPrimitive, MaskLayer}; +use crate::{ + ColorAttr, GPUBackendImpl, GradientStopPrimitive, ImgPrimitive, MaskLayer, RadialGradientAttr, + RadialGradientPrimitive, +}; use ribir_geom::{rect_corners, DeviceRect, DeviceSize, Point}; use ribir_painter::{ image::ColorFormat, AntiAliasing, Color, PaintCommand, PaintPath, PainterBackend, PixelImage, @@ -8,6 +11,7 @@ use ribir_painter::{ use std::{error::Error, future::Future, ops::Range, pin::Pin}; mod atlas; + mod textures_mgr; use textures_mgr::*; @@ -16,6 +20,9 @@ pub struct GPUBackend { tex_mgr: TexturesMgr, color_vertices_buffer: VertexBuffers, img_vertices_buffer: VertexBuffers, + radial_gradient_vertices_buffer: VertexBuffers, + gradient_stops: Vec, + radial_gradient_prims: Vec, img_prims: Vec, draw_indices: Vec, tex_ids_map: TextureIdxMap, @@ -29,7 +36,7 @@ pub struct GPUBackend { enum DrawIndices { Color(Range), Img(Range), - _Gradient(Range), + RadialGradient(Range), } struct ClipLayer { @@ -124,6 +131,17 @@ where self.gpu_impl.load_img_primitives(&self.img_prims); self.gpu_impl.load_img_vertices(&self.img_vertices_buffer); } + if !self.radial_gradient_vertices_buffer.indices.is_empty() { + self + .gpu_impl + .load_radial_gradient_primitives(&self.radial_gradient_prims); + self + .gpu_impl + .load_radial_gradient_stops(&self.gradient_stops); + self + .gpu_impl + .load_radial_gradient_vertices(&self.radial_gradient_vertices_buffer); + } self.tex_mgr.submit(&mut self.gpu_impl); self.layers_submit(output, surface); @@ -146,9 +164,12 @@ where tex_ids_map: <_>::default(), mask_layers: vec![], clip_layer_stack: vec![], + radial_gradient_prims: vec![], skip_clip_cnt: 0, color_vertices_buffer: VertexBuffers::with_capacity(256, 512), img_vertices_buffer: VertexBuffers::with_capacity(256, 512), + radial_gradient_vertices_buffer: VertexBuffers::with_capacity(256, 512), + gradient_stops: vec![], img_prims: vec![], draw_indices: vec![], viewport: DeviceRect::zero(), @@ -196,6 +217,47 @@ where add_draw_rect_vertices(rect, output_tex_size, prim_idx, buffer); } } + PaintCommand::RadialGradient { + path, + stops, + start, + start_radius, + end, + end_radius, + spread, + transform, + } => { + let ts = transform.then(&path.transform); + if let Some((rect, mask_head)) = self.new_mask_layer(path) { + self.update_to_radial_gradient_indices(); + let prim: RadialGradientPrimitive = RadialGradientPrimitive { + transform: ts.inverse().unwrap().to_array(), + stop_start: self.gradient_stops.len() as u32, + stop_cnt: stops.len() as u32, + start_center: start.to_array(), + start_radius, + end_center: end.to_array(), + end_radius, + mask_head, + spread: spread as u32, + }; + self.gradient_stops.extend(stops.into_iter().map(|stop| { + let color = stop.color.into_f32_components(); + GradientStopPrimitive { + red: color[0], + green: color[1], + blue: color[2], + alpha: color[3], + offset: stop.offset, + } + })); + let prim_idx = self.radial_gradient_prims.len() as u32; + self.radial_gradient_prims.push(prim); + let buffer = &mut self.radial_gradient_vertices_buffer; + let attr = RadialGradientAttr { prim_idx }; + add_draw_rect_vertices(rect, output_tex_size, attr, buffer); + } + } PaintCommand::Clip(path) => { if self.skip_clip_cnt == 0 { if let Some(viewport) = path @@ -235,6 +297,10 @@ where self.img_vertices_buffer.indices.clear(); self.img_prims.clear(); self.mask_layers.clear(); + self.radial_gradient_vertices_buffer.indices.clear(); + self.radial_gradient_vertices_buffer.vertices.clear(); + self.radial_gradient_prims.clear(); + self.gradient_stops.clear(); } fn update_to_color_indices(&mut self) { @@ -253,12 +319,27 @@ where } } + fn update_to_radial_gradient_indices(&mut self) { + if !matches!( + self.draw_indices.last(), + Some(DrawIndices::RadialGradient(_)) + ) { + self.expand_indices_range(); + let start = self.radial_gradient_vertices_buffer.indices.len() as u32; + self + .draw_indices + .push(DrawIndices::RadialGradient(start..start)); + } + } + fn expand_indices_range(&mut self) -> Option<&DrawIndices> { let cmd = self.draw_indices.last_mut()?; match cmd { DrawIndices::Color(rg) => rg.end = self.color_vertices_buffer.indices.len() as u32, DrawIndices::Img(rg) => rg.end = self.img_vertices_buffer.indices.len() as u32, - DrawIndices::_Gradient(_) => todo!(), + DrawIndices::RadialGradient(rg) => { + rg.end = self.radial_gradient_vertices_buffer.indices.len() as u32 + } }; Some(&*cmd) @@ -322,7 +403,11 @@ where .for_each(|indices| match indices { DrawIndices::Color(rg) => self.gpu_impl.draw_color_triangles(output, rg, color.take()), DrawIndices::Img(rg) => self.gpu_impl.draw_img_triangles(output, rg, color.take()), - DrawIndices::_Gradient(_) => todo!(), + DrawIndices::RadialGradient(rg) => { + self + .gpu_impl + .draw_radial_gradient_triangles(output, rg, color.take()) + } }); } } diff --git a/gpu/src/lib.rs b/gpu/src/lib.rs index b7388324e..e8035ca6a 100644 --- a/gpu/src/lib.rs +++ b/gpu/src/lib.rs @@ -87,6 +87,7 @@ pub trait GPUBackendImpl { texture: &mut Self::Texture, scissor: DeviceRect, ); + /// load textures that will be use in this draw phase fn load_textures(&mut self, textures: &[&Self::Texture]); /// load the mask layers that the current draw phase will use, called at @@ -99,6 +100,15 @@ pub trait GPUBackendImpl { fn load_img_primitives(&mut self, primitives: &[ImgPrimitive]); /// Load the vertices and indices buffer that `draw_img_triangles` will use. fn load_img_vertices(&mut self, buffers: &VertexBuffers); + + /// Load the primitives that `draw_radial_gradient_triangles` will use. + fn load_radial_gradient_primitives(&mut self, primitives: &[RadialGradientPrimitive]); + /// Load the gradient color stops that `draw_radial_gradient_triangles` will + /// use. + fn load_radial_gradient_stops(&mut self, stops: &[GradientStopPrimitive]); + /// Load the vertices and indices buffer that `draw_radial_gradient_triangles` + /// will use. + fn load_radial_gradient_vertices(&mut self, buffers: &VertexBuffers); /// Draw pure color triangles in the texture. And use the clear color clear /// the texture first if it's a Some-Value fn draw_color_triangles( @@ -115,6 +125,14 @@ pub trait GPUBackendImpl { indices: Range, clear: Option, ); + /// Draw triangles fill with color radial gradient. And use the clear color + /// clear the texture first if it's a Some-Value + fn draw_radial_gradient_triangles( + &mut self, + texture: &mut Self::Texture, + indices: Range, + clear: Option, + ); fn copy_texture_from_texture( &mut self, @@ -136,6 +154,54 @@ pub struct ColorAttr { pub mask_head: i32, } +#[repr(packed)] +#[derive(AsBytes, PartialEq, Clone, Copy, Debug)] +pub struct RadialGradientAttr { + pub prim_idx: u32, +} + +#[repr(packed)] +#[derive(AsBytes, PartialEq, Clone, Copy, Debug)] +pub struct GradientStopPrimitive { + pub red: f32, + pub green: f32, + pub blue: f32, + pub alpha: f32, + pub offset: f32, +} + +#[repr(u32)] +enum SpreadMethod { + Pad, + Reflect, + Repeat, +} + +#[repr(packed)] +#[derive(AsBytes, PartialEq, Clone, Copy)] +pub struct RadialGradientPrimitive { + /// A 2x3 column-major matrix, transform a vertex position to the radial path + /// position + pub transform: [f32; 6], + /// The origin of the image placed in texture. + pub stop_start: u32, + /// The size of the image image. + pub stop_cnt: u32, + /// The index of texture, `load_color_primitives` method provide all textures + /// a draw phase need. + pub start_center: [f32; 2], + /// The index of the head mask layer. + pub end_center: [f32; 2], + + pub start_radius: f32, + + pub end_radius: f32, + + pub mask_head: i32, + + pub spread: u32, +} + #[repr(packed)] #[derive(AsBytes, PartialEq, Clone, Copy)] pub struct ImgPrimitive { diff --git a/gpu/src/wgpu_impl.rs b/gpu/src/wgpu_impl.rs index 639458b40..4bafa333e 100644 --- a/gpu/src/wgpu_impl.rs +++ b/gpu/src/wgpu_impl.rs @@ -1,9 +1,13 @@ use self::{ draw_alpha_triangles_pass::DrawAlphaTrianglesPass, draw_color_triangles_pass::DrawColorTrianglesPass, draw_img_triangles_pass::DrawImgTrianglesPass, - draw_texture_pass::DrawTexturePass, storage::Storage, + draw_radial_gradient_pass::DrawRadialGradientTrianglesPass, draw_texture_pass::DrawTexturePass, + storage::Storage, +}; +use crate::{ + gpu_backend::Texture, ColorAttr, GPUBackendImpl, GradientStopPrimitive, ImgPrimitive, MaskLayer, + RadialGradientAttr, RadialGradientPrimitive, }; -use crate::{gpu_backend::Texture, ColorAttr, GPUBackendImpl, ImgPrimitive, MaskLayer}; use futures::{channel::oneshot, Future}; use ribir_geom::{DevicePoint, DeviceRect, DeviceSize}; use ribir_painter::{image::ColorFormat, AntiAliasing, Color, PixelImage, VertexBuffers}; @@ -15,6 +19,7 @@ mod vertex_buffer; mod draw_alpha_triangles_pass; mod draw_color_triangles_pass; mod draw_img_triangles_pass; +mod draw_radial_gradient_pass; mod draw_texture_pass; pub struct WgpuImpl { @@ -29,6 +34,7 @@ pub struct WgpuImpl { draw_alpha_triangles_pass: DrawAlphaTrianglesPass, draw_color_triangles_pass: DrawColorTrianglesPass, draw_img_triangles_pass: DrawImgTrianglesPass, + draw_radial_gradient_pass: draw_radial_gradient_pass::DrawRadialGradientTrianglesPass, textures_bind: TexturesBind, mask_layers_storage: Storage, @@ -127,6 +133,24 @@ impl GPUBackendImpl for WgpuImpl { .load_img_primitives(&self.device, &self.queue, primitives); } + fn load_radial_gradient_primitives(&mut self, primitives: &[RadialGradientPrimitive]) { + self + .draw_radial_gradient_pass + .load_radial_gradient_primitives(&self.device, &mut self.queue, primitives); + } + + fn load_radial_gradient_stops(&mut self, stops: &[GradientStopPrimitive]) { + self + .draw_radial_gradient_pass + .load_gradient_stops(&self.device, &mut self.queue, stops); + } + + fn load_radial_gradient_vertices(&mut self, buffers: &VertexBuffers) { + self + .draw_radial_gradient_pass + .load_triangles_vertices(buffers, &self.device, &mut self.queue); + } + fn load_mask_layers(&mut self, layers: &[crate::MaskLayer]) { self .mask_layers_storage @@ -144,6 +168,25 @@ impl GPUBackendImpl for WgpuImpl { ); } + fn draw_radial_gradient_triangles( + &mut self, + texture: &mut Self::Texture, + indices: Range, + clear: Option, + ) { + let encoder = command_encoder!(self); + + self.draw_radial_gradient_pass.draw_triangles( + texture, + indices, + clear, + &self.device, + encoder, + &self.textures_bind, + &self.mask_layers_storage, + ); + } + fn draw_alpha_triangles_with_scissor( &mut self, indices: &Range, @@ -539,6 +582,7 @@ impl WgpuImpl { let draw_color_triangles_pass = DrawColorTrianglesPass::new(&device); let draw_img_triangles_pass = DrawImgTrianglesPass::new(&device); + let radial_gradient_pass = DrawRadialGradientTrianglesPass::new(&device); let mask_layers_storage = Storage::new(&device, wgpu::ShaderStages::FRAGMENT, 512); WgpuImpl { device, @@ -551,6 +595,7 @@ impl WgpuImpl { draw_alpha_triangles_pass, draw_color_triangles_pass, draw_img_triangles_pass, + draw_radial_gradient_pass: radial_gradient_pass, textures_bind: TexturesBind::default(), mask_layers_storage, } diff --git a/gpu/src/wgpu_impl/draw_radial_gradient_pass.rs b/gpu/src/wgpu_impl/draw_radial_gradient_pass.rs new file mode 100644 index 000000000..1cb96f91f --- /dev/null +++ b/gpu/src/wgpu_impl/draw_radial_gradient_pass.rs @@ -0,0 +1,200 @@ +use super::{storage::Storage, vertex_buffer::VerticesBuffer}; +use crate::{ + GradientStopPrimitive, MaskLayer, RadialGradientAttr, RadialGradientPrimitive, TexturesBind, + WgpuTexture, +}; +use ribir_painter::{AntiAliasing, Color, Vertex, VertexBuffers}; +use std::{mem::size_of, ops::Range}; + +pub struct DrawRadialGradientTrianglesPass { + label: &'static str, + vertices_buffer: VerticesBuffer, + pipeline: Option, + shader: wgpu::ShaderModule, + format: Option, + prims_storage: Storage, + stops_storage: Storage, + textures_count: usize, + anti_aliasing: AntiAliasing, +} + +impl DrawRadialGradientTrianglesPass { + pub fn new(device: &wgpu::Device) -> Self { + let vertices_buffer = VerticesBuffer::new(512, 1024, device); + let label = "radial triangles pass"; + let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { + label: Some(label), + source: wgpu::ShaderSource::Wgsl( + include_str!("./shaders/radial_gradient_triangles.wgsl").into(), + ), + }); + let prims_storage = Storage::new(device, wgpu::ShaderStages::FRAGMENT, 64); + let stops_storage = Storage::new(device, wgpu::ShaderStages::FRAGMENT, 64); + + Self { + label, + vertices_buffer, + pipeline: None, + shader, + format: None, + textures_count: 0, + prims_storage, + stops_storage, + anti_aliasing: AntiAliasing::None, + } + } + + pub fn load_triangles_vertices( + &mut self, + buffers: &VertexBuffers, + device: &wgpu::Device, + queue: &mut wgpu::Queue, + ) { + self.vertices_buffer.write_buffer(buffers, device, queue); + } + + pub fn load_radial_gradient_primitives( + &mut self, + device: &wgpu::Device, + queue: &mut wgpu::Queue, + primitives: &[RadialGradientPrimitive], + ) { + self.prims_storage.write_buffer(device, queue, primitives); + } + + pub fn load_gradient_stops( + &mut self, + device: &wgpu::Device, + queue: &mut wgpu::Queue, + stops: &[GradientStopPrimitive], + ) { + self.stops_storage.write_buffer(device, queue, stops); + } + + #[allow(clippy::too_many_arguments)] + pub fn draw_triangles( + &mut self, + texture: &mut WgpuTexture, + indices: Range, + clear: Option, + device: &wgpu::Device, + encoder: &mut wgpu::CommandEncoder, + textures_bind: &TexturesBind, + mask_layer_storage: &Storage, + ) { + self.update( + texture.format(), + texture.anti_aliasing, + device, + textures_bind, + mask_layer_storage.layout(), + ); + let pipeline = self.pipeline.as_ref().unwrap(); + + let color_attachments = texture.color_attachments(clear); + let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some(self.label), + color_attachments: &[Some(color_attachments)], + depth_stencil_attachment: None, + }); + + rpass.set_vertex_buffer(0, self.vertices_buffer.vertices().slice(..)); + rpass.set_index_buffer( + self.vertices_buffer.indices().slice(..), + wgpu::IndexFormat::Uint32, + ); + rpass.set_bind_group(0, mask_layer_storage.bind_group(), &[]); + rpass.set_bind_group(1, self.stops_storage.bind_group(), &[]); + rpass.set_bind_group(2, self.prims_storage.bind_group(), &[]); + rpass.set_bind_group(3, textures_bind.assert_bind(), &[]); + + rpass.set_pipeline(pipeline); + rpass.draw_indexed(indices, 0, 0..1); + } + + fn update( + &mut self, + format: wgpu::TextureFormat, + anti_aliasing: AntiAliasing, + device: &wgpu::Device, + textures_bind: &TexturesBind, + mask_bind_layout: &wgpu::BindGroupLayout, + ) { + if self.format != Some(format) + || textures_bind.textures_count() != self.textures_count + || anti_aliasing != self.anti_aliasing + { + self.pipeline.take(); + self.format = Some(format); + self.textures_count = textures_bind.textures_count(); + self.anti_aliasing = anti_aliasing; + } + + if self.pipeline.is_none() { + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("update triangles pipeline layout"), + bind_group_layouts: &[ + mask_bind_layout, + self.stops_storage.layout(), + self.prims_storage.layout(), + textures_bind.assert_layout(), + ], + push_constant_ranges: &[], + }); + let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some(self.label), + layout: Some(&pipeline_layout), + vertex: wgpu::VertexState { + module: &self.shader, + entry_point: "vs_main", + buffers: &[wgpu::VertexBufferLayout { + array_stride: size_of::>() as wgpu::BufferAddress, + step_mode: wgpu::VertexStepMode::Vertex, + attributes: &[ + // position + wgpu::VertexAttribute { + offset: 0, + shader_location: 0, + format: wgpu::VertexFormat::Float32x2, + }, + // prim_idx + wgpu::VertexAttribute { + offset: 8, + shader_location: 1, + format: wgpu::VertexFormat::Uint32, + }, + ], + }], + }, + fragment: Some(wgpu::FragmentState { + module: &self.shader, + entry_point: "fs_main", + targets: &[Some(wgpu::ColorTargetState { + format, + blend: Some(wgpu::BlendState::ALPHA_BLENDING), + write_mask: wgpu::ColorWrites::all(), + })], + }), + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + front_face: wgpu::FrontFace::Ccw, + // Always draw rect with transform, there is no distinction between front and back, + // everything needs to be drawn. + cull_mode: None, + unclipped_depth: false, + polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, + }, + depth_stencil: None, + multisample: wgpu::MultisampleState { + count: anti_aliasing as u32, + mask: !0, + alpha_to_coverage_enabled: false, + }, + multiview: None, + }); + self.pipeline = Some(pipeline); + } + } +} diff --git a/gpu/src/wgpu_impl/shaders/radial_gradient_triangles.wgsl b/gpu/src/wgpu_impl/shaders/radial_gradient_triangles.wgsl new file mode 100644 index 000000000..c94585a41 --- /dev/null +++ b/gpu/src/wgpu_impl/shaders/radial_gradient_triangles.wgsl @@ -0,0 +1,192 @@ +struct Vertex { + @location(0) pos: vec2, + @location(1) prim_idx: u32, +}; + +struct FragInput { + @builtin(position) pos: vec4, + @location(0) prim_idx: u32, +} + +@vertex +fn vs_main(v: Vertex) -> FragInput { + var input: FragInput; + // convert from gpu-backend coords(0..1) to wgpu corrds(-1..1) + let pos = v.pos * vec2(2., -2.) + vec2(-1., 1.); + input.pos = vec4(pos, 0.0, 1.0); + input.prim_idx = v.prim_idx; + return input; +} + + +struct MaskLayer { + transform: mat3x2, + min: vec2, + max: vec2, + mask_tex_idx: u32, + prev_mask_idx: i32, +} + +struct Stop { + red: f32, + green: f32, + blue: f32, + alpha: f32, + offset: f32, +} + +struct Primitive { + transform: mat3x2, + stop_start: i32, + stop_cnt: i32, + start_center: vec2, + end_center: vec2, + start_radius: f32, + end_radius: f32, + mask_head: i32, + spread: u32, // 0 for pad, 1 for reflect, 2 for repeat +} + +@group(0) @binding(0) +var mask_layers: array; + +@group(1) @binding(0) +var stops: array; + +@group(2) @binding(0) +var prims: array; + +@group(3) @binding(0) +var textures: binding_array>; +@group(3) @binding(1) +var samplers: binding_array; + + +fn calc_mask_alpha(pos: vec2, mask_idx: i32) -> f32 { + var alpha = 1.; + var mask_idx = mask_idx; + loop { + if mask_idx < 0 { + break; + } + let mask = mask_layers[u32(mask_idx)]; + + var mask_pos = mask.transform * vec3(pos, 1.); + if any(mask_pos < mask.min) || any(mask.max < mask_pos) { + alpha = 0.; + break; + } + + let mask_tex_idx = mask.mask_tex_idx; + let texture = textures[mask_tex_idx]; + let s_sampler = samplers[mask_tex_idx]; + + let tex_size = textureDimensions(texture); + mask_pos = mask_pos / vec2(f32(tex_size.x), f32(tex_size.y)); + let a = textureSample(texture, s_sampler, mask_pos).r; + alpha = alpha * a; + if alpha == 0. { + break; + } + mask_idx = mask.prev_mask_idx; + } + return alpha; +} + + +fn calc_offset(x: f32, y: f32, x_0: f32, y_0: f32, r_0: f32, x_1: f32, y_1: f32, r_1: f32) -> f32 { + /* + see definition at https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-createradialgradient + with offset ω, Radial gradients must be rendered by following these steps: + 1. If x0 = x1 and y0 = y1 and r0 = r1, then the radial gradient must paint nothing. Return. + Let x(ω) = (x1-x0)ω + x0 + Let y(ω) = (y1-y0)ω + y0 + Let r(ω) = (r1-r0)ω + r0 + 2. Let the color at ω be the color at that position on the gradient (with the colors coming from the interpolation + and extrapolation described above). + 3. For all values of ω where r(ω) > 0, starting with the value of ω nearest to positive infinity and ending with + the value of ω nearest to negative infinity, draw the circumference of the circle with radius r(ω) at position + (x(ω), y(ω)), with the color at ω, but only painting on the parts of the bitmap that have not yet been painted + on by earlier circles in this step for this rendering of the gradient. + + so the offset ω meet the following equation: (x(ω) - x)^2 + (y(ω) - y)^2 = r(ω)^2. + we sovle the equation and get the offset ω with the min r. + define: + dx_0 = x - x_0; + dx_1_0 = x_1 - x_0; + dy_0 = y - y_0; + dy_1_0 = y_1 - y_0; + dr_1_0 = r_1 - r_0; + the (x(ω) - x)^2 + (y(ω) - y)^2 = r(ω)^2 can be rewrite as: + (dx_1_0^2 + dy_1_0^2 - dr_1_0^2) * ω^2 - 2 * (dx_1_0 * dx_0 + dy_1_0 * dy_0 + dr_1_0 * r_0) * ω + (dx_0^2 + dy_0^2 - r_0^2) = 0 + the ω can be solve by the quadratic formula: + ω = (-b ± sqrt(b^2 - 4ac)) / 2a + where a = dx_1_0^2 + dy_1_0^2 - dr_1_0^2 + b = -2 * (dx_1_0 * dx_0 + dy_1_0 * dy_0 + dr_1_0 * r_0) + c = dx_0^2 + dy_0^2 - r_0^2 + */ + let dx_0 = x - x_0; + let dx_1_0 = x_1 - x_0; + let dy_0 = y - y_0; + let dy_1_0 = y_1 - y_0; + let dr_1_0 = r_1 - r_0; + let a = dx_1_0 * dx_1_0 + dy_1_0 * dy_1_0 - dr_1_0 * dr_1_0; + let b = -2. * (dx_1_0 * dx_0 + dy_1_0 * dy_0 + dr_1_0 * r_0); + let c = dx_0 * dx_0 + dy_0 * dy_0 - r_0 * r_0; + + let delta = b * b - 4. * a * c; + + if (abs(a) < 0.1) { + if (abs(b) < 0.1) { + return -1.; + } else { + return -c / b; + } + } else if (delta < 0.) { + return -1.; + } + + let sqrt_delta = sqrt(delta); + let _2a = 2. * a; + let w1 = (-b + sqrt_delta) / _2a; + let w2 = (-b - sqrt_delta) / _2a; + + return max(w1, w2); +} + +@fragment +fn fs_main(input: FragInput) -> @location(0) vec4 { + let prim = prims[input.prim_idx]; + let pos = prim.transform * vec3(input.pos.xy, 1.); + let alpha = calc_mask_alpha(input.pos.xy, prim.mask_head); + + var offset = calc_offset(pos.x, pos.y, prim.start_center.x, prim.start_center.y, prim.start_radius, prim.end_center.x, prim.end_center.y, prim.end_radius); + if (offset < 0.) { + discard; + } + + if (prim.spread == 0u) { + // pad + offset = min(1., max(0., offset)); + } else if (prim.spread == 1u) { + //reflect + offset = 1. - abs(fract(offset / 2.) - 0.5) * 2.; + } else { + //repeat + offset = fract(offset); + } + + var prev = stops[prim.stop_start]; + var next = stops[prim.stop_start + 1]; + for (var i = 2; i < prim.stop_cnt && next.offset < offset; i++) { + prev = next; + next = stops[prim.stop_start + i]; + } + + offset = max(prev.offset, min(next.offset, offset)); + let weight1 = (next.offset - offset) / (next.offset - prev.offset); + let weight2 = 1. - weight1; + let prev_color = vec4(prev.red, prev.green, prev.blue, prev.alpha); + let next_color = vec4(next.red, next.green, next.blue, next.alpha); + return (prev_color * weight1 + next_color * weight2) * vec4(1., 1., 1., alpha); +} diff --git a/painter/src/color.rs b/painter/src/color.rs index 9751a7f63..b4a875e94 100644 --- a/painter/src/color.rs +++ b/painter/src/color.rs @@ -1,4 +1,5 @@ use material_color_utilities_rs::htc; +use ribir_geom::{Point, Transform}; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)] @@ -9,6 +10,21 @@ pub struct Color { pub alpha: u8, } +#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] +pub struct GradientStop { + pub color: Color, + pub offset: f32, +} +#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] +pub struct RadialGradient { + pub start_center: Point, + pub start_radius: f32, + pub end_center: Point, + pub end_radius: f32, + pub stops: Vec, + pub transform: Transform, +} + /// Describe the light tone of a color, should between [0, 1.0], 0.0 gives /// absolute black and 1.0 give the brightest white. #[derive(Clone, Debug, Copy)] diff --git a/painter/src/lib.rs b/painter/src/lib.rs index 42be21cea..a16d491ae 100644 --- a/painter/src/lib.rs +++ b/painter/src/lib.rs @@ -5,7 +5,7 @@ pub mod color; mod painter; pub mod path; pub mod path_builder; -pub use crate::color::{Color, LightnessTone}; +pub use crate::color::{Color, GradientStop, LightnessTone}; pub use crate::painter::*; pub use path::*; pub mod image; diff --git a/painter/src/painter.rs b/painter/src/painter.rs index 564610447..b78ad9693 100644 --- a/painter/src/painter.rs +++ b/painter/src/painter.rs @@ -1,11 +1,12 @@ -use crate::{path::*, path_builder::PathBuilder, Brush, Color, PixelImage, Svg}; +use crate::{ + color::GradientStop, path::*, path_builder::PathBuilder, Brush, Color, PixelImage, Svg, +}; use ribir_algo::ShareResource; use ribir_geom::{Angle, DeviceRect, Point, Rect, Size, Transform, Vector}; use serde::{Deserialize, Serialize}; use std::ops::{Deref, DerefMut}; - /// The painter is a two-dimensional grid. The coordinate (0, 0) is at the /// upper-left corner of the canvas. Along the X-axis, values increase towards /// the right edge of the canvas. Along the Y-axis, values increase towards the @@ -73,6 +74,14 @@ pub struct PaintPath { pub transform: Transform, } +#[repr(u32)] +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum SpreadMethod { + Pad, + Reflect, + Repeat, +} + #[derive(Debug, Clone, Serialize, Deserialize)] pub enum PaintCommand { ColorPath { @@ -84,6 +93,16 @@ pub enum PaintCommand { img: ShareResource, opacity: f32, }, + RadialGradient { + path: PaintPath, + stops: Vec, + start: Point, + start_radius: f32, + end: Point, + end_radius: f32, + spread: SpreadMethod, + transform: Transform, + }, // Todo: keep rectangle clip. Clip(PaintPath), PopClip, @@ -289,7 +308,16 @@ impl Painter { color: color.apply_alpha(opacity), }, Brush::Image(img) => PaintCommand::ImgPath { path, img, opacity }, - Brush::Gradient => todo!(), + Brush::RadialGradient(radial_gradient) => PaintCommand::RadialGradient { + path: path, + stops: radial_gradient.stops, + start: radial_gradient.start_center, + start_radius: radial_gradient.start_radius, + end: radial_gradient.end_center, + end_radius: radial_gradient.end_radius, + transform: radial_gradient.transform, + spread: SpreadMethod::Pad, + }, }; self.commands.push(cmd); } @@ -438,10 +466,9 @@ impl Painter { } pub fn draw_svg(&mut self, svg: &Svg) -> &mut Self { + self.scale(svg.view_scale.x, svg.view_scale.y); svg.paths.iter().for_each(|c| { - self - .scale(svg.view_scale.x, svg.view_scale.y) - .set_brush(c.brush.clone()); + self.set_brush(c.brush.clone()); match &c.style { PathPaintStyle::Fill => self.fill_path(c.path.clone()), PathPaintStyle::Stroke(options) => self diff --git a/painter/src/style.rs b/painter/src/style.rs index d95641b8c..9b6b5f107 100644 --- a/painter/src/style.rs +++ b/painter/src/style.rs @@ -1,4 +1,4 @@ -use crate::{Color, PixelImage}; +use crate::{color::RadialGradient, Color, PixelImage}; use ribir_algo::ShareResource; use serde::{Deserialize, Serialize}; @@ -7,7 +7,7 @@ pub enum Brush { Color(Color), /// Image brush always use a repeat mode to brush the path. Image(ShareResource), - Gradient, // todo, + RadialGradient(RadialGradient), } impl Brush { diff --git a/painter/src/svg.rs b/painter/src/svg.rs index 35baaf153..541a728ed 100644 --- a/painter/src/svg.rs +++ b/painter/src/svg.rs @@ -1,23 +1,41 @@ -use crate::{Brush, Color, LineCap, LineJoin, Path, PathPaintStyle, StrokeOptions}; +use crate::{ + color::RadialGradient, Brush, Color, GradientStop, LineCap, LineJoin, Path, PathPaintStyle, + StrokeOptions, +}; use ribir_geom::{Point, Size, Transform, Vector}; use serde::{Deserialize, Serialize}; -use std::{error::Error, io::Read}; +use std::{error::Error, io::Read, rc::Rc, time::Instant}; use usvg::{Options, Tree, TreeParsing}; -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Clone)] pub struct Svg { pub size: Size, pub view_scale: Vector, pub paths: Box<[SvgPath]>, } -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Clone)] pub struct SvgPath { pub path: Path, pub brush: Brush, pub style: PathPaintStyle, } +/// Fits size into a viewbox. +fn fit_view_box(s: usvg::Size, vb: &usvg::ViewBox) -> usvg::Size { + let s = vb.rect.size(); + + if vb.aspect.align == usvg::Align::None { + s + } else { + if vb.aspect.slice { + s.expand_to(s) + } else { + s.scale_to(s) + } + } +} + // todo: we need to support currentColor to change svg color. impl Svg { pub fn parse_from_bytes(svg_data: &[u8]) -> Result> { @@ -25,7 +43,8 @@ impl Svg { let tree = Tree::from_data(svg_data, &opt).unwrap(); let view_rect = tree.view_box.rect; let size = tree.size; - let fit_size = size.fit_view_box(&tree.view_box); + let fit_size = fit_view_box(size, &tree.view_box); + let view_scale = Vector::new( size.width() / fit_size.width(), size.height() / fit_size.height(), @@ -46,7 +65,7 @@ impl Svg { let path = usvg_path_to_path(p); let path = path.transform(t_stack.current_transform()); if let Some(ref fill) = p.fill { - let brush = brush_from_usvg_paint(&fill.paint, fill.opacity); + let brush = brush_from_usvg_paint(&fill.paint, fill.opacity, &size); paths.push(SvgPath { path: path.clone(), @@ -73,7 +92,7 @@ impl Svg { miter_limit: stroke.miterlimit.get() as f32, }; - let brush = brush_from_usvg_paint(&stroke.paint, stroke.opacity); + let brush = brush_from_usvg_paint(&stroke.paint, stroke.opacity, &size); paths.push(SvgPath { path, brush, @@ -136,35 +155,85 @@ impl Svg { fn usvg_path_to_path(path: &usvg::Path) -> Path { let mut builder = lyon_algorithms::path::Path::svg_builder(); path.data.segments().for_each(|seg| match seg { - usvg::PathSegment::MoveTo { x, y } => { - builder.move_to(point(x, y)); + usvg::tiny_skia_path::PathSegment::MoveTo(pt) => { + builder.move_to(point(pt.x, pt.y)); + } + usvg::tiny_skia_path::PathSegment::LineTo(pt) => { + builder.line_to(point(pt.x, pt.y)); } - usvg::PathSegment::LineTo { x, y } => { - builder.line_to(point(x, y)); + usvg::tiny_skia_path::PathSegment::CubicTo(pt1, pt2, pt3) => { + builder.cubic_bezier_to( + point(pt1.x, pt1.y), + point(pt2.x, pt2.y), + point(pt3.x, pt3.y), + ); } - usvg::PathSegment::CurveTo { x1, y1, x2, y2, x, y } => { - builder.cubic_bezier_to(point(x1, y1), point(x2, y2), point(x, y)); + usvg::tiny_skia_path::PathSegment::QuadTo(pt1, pt2) => { + builder.quadratic_bezier_to(point(pt1.x, pt1.y), point(pt2.x, pt2.y)); } - usvg::PathSegment::ClosePath => builder.close(), + usvg::tiny_skia_path::PathSegment::Close => builder.close(), }); builder.build().into() } -fn point(x: f64, y: f64) -> lyon_algorithms::math::Point { - Point::new(x as f32, y as f32).to_untyped() -} +fn point(x: f32, y: f32) -> lyon_algorithms::math::Point { Point::new(x, y).to_untyped() } fn matrix_convert(t: usvg::Transform) -> Transform { - let usvg::Transform { a, b, c, d, e, f } = t; - Transform::new(a as f32, b as f32, c as f32, d as f32, e as f32, f as f32) + let usvg::Transform { sx, kx, ky, sy, tx, ty } = t; + Transform::new(sx, ky, kx, sy, tx, ty) } -fn brush_from_usvg_paint(paint: &usvg::Paint, opacity: usvg::Opacity) -> Brush { +fn brush_from_usvg_paint(paint: &usvg::Paint, opacity: usvg::Opacity, size: &usvg::Size) -> Brush { match paint { usvg::Paint::Color(usvg::Color { red, green, blue }) => Color::from_rgb(*red, *green, *blue) .with_alpha(opacity.get() as f32) .into(), + usvg::Paint::LinearGradient(gradient) => { + let mut stops = gradient.stops.clone(); + stops.sort_by(|s1, s2| s1.offset.cmp(&s2.offset)); + let mut offset = 0.; + let mut red = 0.; + let mut green = 0.; + let mut blue = 0.; + for stop in stops.iter() { + let color = stop.color; + let weight = stop.offset.get() - offset; + offset = stop.offset.get(); + red += (color.red as f32 - red) * weight; + blue += (color.blue as f32 - blue) * weight; + green += (color.green as f32 - green) * weight; + } + Color::from_rgb(red as u8, green as u8, blue as u8).into() + } + usvg::Paint::RadialGradient(gradient) => { + let mut stops = gradient.stops.clone(); + stops.sort_by(|s1, s2| s1.offset.cmp(&s2.offset)); + + let stops = stops + .iter() + .map(|stop| { + let usvg::Color { red, green, blue } = stop.color; + GradientStop { + offset: stop.offset.get(), + color: Color::from_rgb(red, green, blue), + } + }) + .collect(); + let size_scale = match gradient.units { + usvg::Units::UserSpaceOnUse => (1., 1.), + usvg::Units::ObjectBoundingBox => (size.width(), size.height()), + }; + let radial = RadialGradient { + start_center: Point::new(gradient.fx * size_scale.0, gradient.fy * size_scale.1), + start_radius: 0., + end_center: Point::new(gradient.cx * size_scale.0, gradient.cy * size_scale.1), + end_radius: gradient.r.get() * size_scale.0, + stops, + transform: matrix_convert(gradient.transform), + }; + Brush::RadialGradient(radial) + } paint => { log::warn!("[painter]: not support `{paint:?}` in svg, use black instead!"); Color::BLACK.into() diff --git a/ribir/src/winit_shell_wnd.rs b/ribir/src/winit_shell_wnd.rs index 802c994d8..69eb18918 100644 --- a/ribir/src/winit_shell_wnd.rs +++ b/ribir/src/winit_shell_wnd.rs @@ -117,6 +117,7 @@ impl ShellWindow for WinitShellWnd { commands.iter_mut().for_each(|c| match c { PaintCommand::ColorPath { path, .. } | PaintCommand::ImgPath { path, .. } + | PaintCommand::RadialGradient { path, .. } | PaintCommand::Clip(path) => path.scale(self.winit_wnd.scale_factor() as f32), PaintCommand::PopClip => {} }); From 888160e54e6f602f79c6ad59d154216146e0b3e6 Mon Sep 17 00:00:00 2001 From: wjian23 Date: Mon, 18 Sep 2023 16:48:58 +0800 Subject: [PATCH 2/7] =?UTF-8?q?feat(gpu):=20=F0=9F=8E=B8=20linear=20gradie?= =?UTF-8?q?nt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gpu/src/gpu_backend.rs | 207 ++++++++++++++---- gpu/src/lib.rs | 93 ++++++-- gpu/src/wgpu_impl.rs | 63 +++++- gpu/src/wgpu_impl/draw_img_triangles_pass.rs | 6 +- .../wgpu_impl/draw_linear_gradient_pass.rs | 200 +++++++++++++++++ .../wgpu_impl/draw_radial_gradient_pass.rs | 16 +- .../shaders/linear_gradient_triangles.wgsl | 138 ++++++++++++ .../shaders/radial_gradient_triangles.wgsl | 22 +- painter/src/color.rs | 20 +- painter/src/painter.rs | 46 ++-- painter/src/style.rs | 6 +- painter/src/svg.rs | 126 ++++++----- ribir/src/winit_shell_wnd.rs | 1 + .../tests/draw_linear_gradient_wgpu.png | Bin 0 -> 1503 bytes .../tests/draw_radial_gradient_wgpu.png | Bin 0 -> 4516 bytes 15 files changed, 777 insertions(+), 167 deletions(-) create mode 100644 gpu/src/wgpu_impl/draw_linear_gradient_pass.rs create mode 100644 gpu/src/wgpu_impl/shaders/linear_gradient_triangles.wgsl create mode 100644 test_cases/ribir_gpu/gpu_backend/tests/draw_linear_gradient_wgpu.png create mode 100644 test_cases/ribir_gpu/gpu_backend/tests/draw_radial_gradient_wgpu.png diff --git a/gpu/src/gpu_backend.rs b/gpu/src/gpu_backend.rs index 7549750aa..81ee678f8 100644 --- a/gpu/src/gpu_backend.rs +++ b/gpu/src/gpu_backend.rs @@ -1,6 +1,7 @@ use self::textures_mgr::{TextureID, TexturesMgr}; use crate::{ - ColorAttr, GPUBackendImpl, GradientStopPrimitive, ImgPrimitive, MaskLayer, RadialGradientAttr, + ColorAttr, GPUBackendImpl, GradientStopPrimitive, ImagePrimIndex, ImgPrimitive, + LinearGradientPrimIndex, LinearGradientPrimitive, MaskLayer, RadialGradientPrimIndex, RadialGradientPrimitive, }; use ribir_geom::{rect_corners, DeviceRect, DeviceSize, Point}; @@ -19,11 +20,14 @@ pub struct GPUBackend { gpu_impl: Impl, tex_mgr: TexturesMgr, color_vertices_buffer: VertexBuffers, - img_vertices_buffer: VertexBuffers, - radial_gradient_vertices_buffer: VertexBuffers, - gradient_stops: Vec, - radial_gradient_prims: Vec, + img_vertices_buffer: VertexBuffers, img_prims: Vec, + radial_gradient_vertices_buffer: VertexBuffers, + radial_gradient_stops: Vec, + radial_gradient_prims: Vec, + linear_gradient_prims: Vec, + linear_gradient_stops: Vec, + linear_gradient_vertices_buffer: VertexBuffers, draw_indices: Vec, tex_ids_map: TextureIdxMap, viewport: DeviceRect, @@ -37,6 +41,7 @@ enum DrawIndices { Color(Range), Img(Range), RadialGradient(Range), + LinearGradient(Range), } struct ClipLayer { @@ -137,11 +142,22 @@ where .load_radial_gradient_primitives(&self.radial_gradient_prims); self .gpu_impl - .load_radial_gradient_stops(&self.gradient_stops); + .load_radial_gradient_stops(&self.radial_gradient_stops); self .gpu_impl .load_radial_gradient_vertices(&self.radial_gradient_vertices_buffer); } + if !self.linear_gradient_vertices_buffer.indices.is_empty() { + self + .gpu_impl + .load_linear_gradient_primitives(&self.linear_gradient_prims); + self + .gpu_impl + .load_linear_gradient_stops(&self.linear_gradient_stops); + self + .gpu_impl + .load_linear_gradient_vertices(&self.linear_gradient_vertices_buffer); + } self.tex_mgr.submit(&mut self.gpu_impl); self.layers_submit(output, surface); @@ -164,12 +180,15 @@ where tex_ids_map: <_>::default(), mask_layers: vec![], clip_layer_stack: vec![], - radial_gradient_prims: vec![], skip_clip_cnt: 0, color_vertices_buffer: VertexBuffers::with_capacity(256, 512), img_vertices_buffer: VertexBuffers::with_capacity(256, 512), radial_gradient_vertices_buffer: VertexBuffers::with_capacity(256, 512), - gradient_stops: vec![], + radial_gradient_prims: vec![], + radial_gradient_stops: vec![], + linear_gradient_vertices_buffer: VertexBuffers::with_capacity(256, 512), + linear_gradient_stops: vec![], + linear_gradient_prims: vec![], img_prims: vec![], draw_indices: vec![], viewport: DeviceRect::zero(), @@ -214,48 +233,80 @@ where }; self.img_prims.push(prim); let buffer = &mut self.img_vertices_buffer; - add_draw_rect_vertices(rect, output_tex_size, prim_idx, buffer); + add_draw_rect_vertices(rect, output_tex_size, ImagePrimIndex(prim_idx), buffer); } } - PaintCommand::RadialGradient { - path, - stops, - start, - start_radius, - end, - end_radius, - spread, - transform, - } => { - let ts = transform.then(&path.transform); + PaintCommand::RadialGradient { path, radial_gradient } => { + let ts = path.transform; if let Some((rect, mask_head)) = self.new_mask_layer(path) { self.update_to_radial_gradient_indices(); let prim: RadialGradientPrimitive = RadialGradientPrimitive { - transform: ts.inverse().unwrap().to_array(), - stop_start: self.gradient_stops.len() as u32, - stop_cnt: stops.len() as u32, - start_center: start.to_array(), - start_radius, - end_center: end.to_array(), - end_radius, + transform: radial_gradient + .transform + .then(&ts) + .inverse() + .unwrap() + .to_array(), + stop_start: self.radial_gradient_stops.len() as u32, + stop_cnt: radial_gradient.stops.len() as u32, + start_center: radial_gradient.start_center.to_array(), + start_radius: radial_gradient.start_radius, + end_center: radial_gradient.end_center.to_array(), + end_radius: radial_gradient.end_radius, mask_head, - spread: spread as u32, + spread: radial_gradient.spread_method as u32, }; - self.gradient_stops.extend(stops.into_iter().map(|stop| { - let color = stop.color.into_f32_components(); - GradientStopPrimitive { - red: color[0], - green: color[1], - blue: color[2], - alpha: color[3], - offset: stop.offset, - } - })); + self.radial_gradient_stops.extend( + radial_gradient + .stops + .into_iter() + .map(Into::::into), + ); let prim_idx = self.radial_gradient_prims.len() as u32; self.radial_gradient_prims.push(prim); let buffer = &mut self.radial_gradient_vertices_buffer; - let attr = RadialGradientAttr { prim_idx }; - add_draw_rect_vertices(rect, output_tex_size, attr, buffer); + + add_draw_rect_vertices( + rect, + output_tex_size, + RadialGradientPrimIndex(prim_idx), + buffer, + ); + } + } + PaintCommand::LinearGradient { path, linear_gradient } => { + let ts = path.transform; + if let Some((rect, mask_head)) = self.new_mask_layer(path) { + self.update_to_linear_gradient_indices(); + let prim: LinearGradientPrimitive = LinearGradientPrimitive { + transform: linear_gradient + .transform + .then(&ts) + .inverse() + .unwrap() + .to_array(), + stop_start: self.linear_gradient_stops.len() as u32, + stop_cnt: linear_gradient.stops.len() as u32, + start_position: linear_gradient.start.to_array(), + end_position: linear_gradient.end.to_array(), + mask_head, + spread: linear_gradient.spread_method as u32, + }; + self.linear_gradient_stops.extend( + linear_gradient + .stops + .into_iter() + .map(Into::::into), + ); + let prim_idx = self.linear_gradient_prims.len() as u32; + self.linear_gradient_prims.push(prim); + let buffer = &mut self.linear_gradient_vertices_buffer; + add_draw_rect_vertices( + rect, + output_tex_size, + LinearGradientPrimIndex(prim_idx), + buffer, + ); } } PaintCommand::Clip(path) => { @@ -300,7 +351,10 @@ where self.radial_gradient_vertices_buffer.indices.clear(); self.radial_gradient_vertices_buffer.vertices.clear(); self.radial_gradient_prims.clear(); - self.gradient_stops.clear(); + self.radial_gradient_stops.clear(); + self.linear_gradient_prims.clear(); + self.linear_gradient_vertices_buffer.indices.clear(); + self.linear_gradient_stops.clear(); } fn update_to_color_indices(&mut self) { @@ -332,6 +386,19 @@ where } } + fn update_to_linear_gradient_indices(&mut self) { + if !matches!( + self.draw_indices.last(), + Some(DrawIndices::LinearGradient(_)) + ) { + self.expand_indices_range(); + let start = self.linear_gradient_vertices_buffer.indices.len() as u32; + self + .draw_indices + .push(DrawIndices::LinearGradient(start..start)); + } + } + fn expand_indices_range(&mut self) -> Option<&DrawIndices> { let cmd = self.draw_indices.last_mut()?; match cmd { @@ -340,6 +407,9 @@ where DrawIndices::RadialGradient(rg) => { rg.end = self.radial_gradient_vertices_buffer.indices.len() as u32 } + DrawIndices::LinearGradient(rg) => { + rg.end = self.linear_gradient_vertices_buffer.indices.len() as u32 + } }; Some(&*cmd) @@ -408,6 +478,11 @@ where .gpu_impl .draw_radial_gradient_triangles(output, rg, color.take()) } + DrawIndices::LinearGradient(rg) => { + self + .gpu_impl + .draw_linear_gradient_triangles(output, rg, color.take()) + } }); } } @@ -466,7 +541,10 @@ mod tests { use ribir_algo::ShareResource; use ribir_dev_helper::*; use ribir_geom::*; - use ribir_painter::{Brush, Color, Painter, Path, PixelImage}; + use ribir_painter::{ + color::{LinearGradient, RadialGradient}, + Brush, Color, GradientStop, Painter, Path, PixelImage, + }; fn painter(bounds: Size) -> Painter { Painter::new(Rect::from_size(bounds)) } @@ -603,4 +681,49 @@ mod tests { painter } + + painter_backend_eq_image_test!(draw_radial_gradient); + fn draw_radial_gradient() -> Painter { + let mut painter = painter(Size::new(64., 64.)); + let brush = Brush::RadialGradient(RadialGradient { + start_center: Point::new(16., 32.), + start_radius: 0., + end_center: Point::new(32., 32.), + end_radius: 32., + stops: vec![ + GradientStop::new(Color::RED, 0.), + GradientStop::new(Color::BLUE, 1.), + ], + transform: Transform::translation(16., 0.), + ..Default::default() + }); + + painter + .set_brush(brush) + .rect(&Rect::from_size(Size::new(64., 64.))) + .fill(); + + painter + } + + painter_backend_eq_image_test!(draw_linear_gradient); + fn draw_linear_gradient() -> Painter { + let mut painter = painter(Size::new(32., 32.)); + let brush = Brush::LinearGradient(LinearGradient { + start: Point::new(0., 0.), + end: Point::new(16., 16.), + stops: vec![ + GradientStop::new(Color::RED, 0.), + GradientStop::new(Color::BLUE, 1.), + ], + ..Default::default() + }); + + painter + .set_brush(brush) + .rect(&Rect::from_size(Size::new(64., 64.))) + .fill(); + + painter + } } diff --git a/gpu/src/lib.rs b/gpu/src/lib.rs index e8035ca6a..25ef5c13a 100644 --- a/gpu/src/lib.rs +++ b/gpu/src/lib.rs @@ -1,7 +1,7 @@ pub mod error; pub use gpu_backend::Texture; use ribir_geom::{DevicePoint, DeviceRect, DeviceSize}; -use ribir_painter::{image::ColorFormat, AntiAliasing, Color, VertexBuffers}; +use ribir_painter::{image::ColorFormat, AntiAliasing, Color, GradientStop, VertexBuffers}; use std::ops::Range; mod gpu_backend; use zerocopy::AsBytes; @@ -99,7 +99,7 @@ pub trait GPUBackendImpl { /// Load the vertices and indices buffer that `draw_img_triangles` will use. fn load_img_primitives(&mut self, primitives: &[ImgPrimitive]); /// Load the vertices and indices buffer that `draw_img_triangles` will use. - fn load_img_vertices(&mut self, buffers: &VertexBuffers); + fn load_img_vertices(&mut self, buffers: &VertexBuffers); /// Load the primitives that `draw_radial_gradient_triangles` will use. fn load_radial_gradient_primitives(&mut self, primitives: &[RadialGradientPrimitive]); @@ -108,7 +108,16 @@ pub trait GPUBackendImpl { fn load_radial_gradient_stops(&mut self, stops: &[GradientStopPrimitive]); /// Load the vertices and indices buffer that `draw_radial_gradient_triangles` /// will use. - fn load_radial_gradient_vertices(&mut self, buffers: &VertexBuffers); + fn load_radial_gradient_vertices(&mut self, buffers: &VertexBuffers); + + /// Load the primitives that `draw_linear_gradient_triangles` will use. + fn load_linear_gradient_primitives(&mut self, primitives: &[LinearGradientPrimitive]); + /// Load the gradient color stops that `draw_linear_gradient_triangles` will + /// use. + fn load_linear_gradient_stops(&mut self, stops: &[GradientStopPrimitive]); + /// Load the vertices and indices buffer that `draw_linear_gradient_triangles` + /// will use. + fn load_linear_gradient_vertices(&mut self, buffers: &VertexBuffers); /// Draw pure color triangles in the texture. And use the clear color clear /// the texture first if it's a Some-Value fn draw_color_triangles( @@ -134,6 +143,15 @@ pub trait GPUBackendImpl { clear: Option, ); + /// Draw triangles fill with color linear gradient. And use the clear color + /// clear the texture first if it's a Some-Value + fn draw_linear_gradient_triangles( + &mut self, + texture: &mut Self::Texture, + indices: Range, + clear: Option, + ); + fn copy_texture_from_texture( &mut self, dist_tex: &mut Self::Texture, @@ -156,9 +174,15 @@ pub struct ColorAttr { #[repr(packed)] #[derive(AsBytes, PartialEq, Clone, Copy, Debug)] -pub struct RadialGradientAttr { - pub prim_idx: u32, -} +pub struct ImagePrimIndex(u32); + +#[repr(packed)] +#[derive(AsBytes, PartialEq, Clone, Copy, Debug)] +pub struct RadialGradientPrimIndex(u32); + +#[repr(packed)] +#[derive(AsBytes, PartialEq, Clone, Copy, Debug)] +pub struct LinearGradientPrimIndex(u32); #[repr(packed)] #[derive(AsBytes, PartialEq, Clone, Copy, Debug)] @@ -170,35 +194,62 @@ pub struct GradientStopPrimitive { pub offset: f32, } -#[repr(u32)] -enum SpreadMethod { - Pad, - Reflect, - Repeat, +impl From for GradientStopPrimitive { + fn from(stop: GradientStop) -> Self { + let color = stop.color.into_f32_components(); + GradientStopPrimitive { + red: color[0], + green: color[1], + blue: color[2], + alpha: color[3], + offset: stop.offset, + } + } } #[repr(packed)] -#[derive(AsBytes, PartialEq, Clone, Copy)] +#[derive(AsBytes, PartialEq, Clone, Copy, Debug)] pub struct RadialGradientPrimitive { - /// A 2x3 column-major matrix, transform a vertex position to the radial path + /// A 2x3 column-major matrix, transform a vertex position to the texture /// position pub transform: [f32; 6], - /// The origin of the image placed in texture. + /// The color stop's start index pub stop_start: u32, - /// The size of the image image. + /// The size of the color stop pub stop_cnt: u32, - /// The index of texture, `load_color_primitives` method provide all textures - /// a draw phase need. + /// position of the start center pub start_center: [f32; 2], - /// The index of the head mask layer. + /// position of the end center pub end_center: [f32; 2], - + /// the radius of the start circle. pub start_radius: f32, - + /// the radius of the end circle. pub end_radius: f32, - + /// The index of the head mask layer. pub mask_head: i32, + /// the spread method of the gradient. 0 for pad, 1 for reflect and 2 + /// for repeat + pub spread: u32, +} +#[repr(packed)] +#[derive(AsBytes, PartialEq, Clone, Copy, Debug)] +pub struct LinearGradientPrimitive { + /// A 2x3 column-major matrix, transform a vertex position to the texture + /// position + pub transform: [f32; 6], + /// The color stop's start index + pub stop_start: u32, + /// The size of the color stop + pub stop_cnt: u32, + /// position of the start center + pub start_position: [f32; 2], + /// position of the end center + pub end_position: [f32; 2], + /// The index of the head mask layer. + pub mask_head: i32, + /// the spread method of the gradient. 0 for pad, 1 for reflect and 2 + /// for repeat pub spread: u32, } diff --git a/gpu/src/wgpu_impl.rs b/gpu/src/wgpu_impl.rs index 4bafa333e..61f9e42c8 100644 --- a/gpu/src/wgpu_impl.rs +++ b/gpu/src/wgpu_impl.rs @@ -1,12 +1,14 @@ use self::{ draw_alpha_triangles_pass::DrawAlphaTrianglesPass, draw_color_triangles_pass::DrawColorTrianglesPass, draw_img_triangles_pass::DrawImgTrianglesPass, + draw_linear_gradient_pass::DrawLinearGradientTrianglesPass, draw_radial_gradient_pass::DrawRadialGradientTrianglesPass, draw_texture_pass::DrawTexturePass, storage::Storage, }; use crate::{ - gpu_backend::Texture, ColorAttr, GPUBackendImpl, GradientStopPrimitive, ImgPrimitive, MaskLayer, - RadialGradientAttr, RadialGradientPrimitive, + gpu_backend::Texture, ColorAttr, GPUBackendImpl, GradientStopPrimitive, ImagePrimIndex, + ImgPrimitive, LinearGradientPrimIndex, LinearGradientPrimitive, MaskLayer, + RadialGradientPrimIndex, RadialGradientPrimitive, }; use futures::{channel::oneshot, Future}; use ribir_geom::{DevicePoint, DeviceRect, DeviceSize}; @@ -19,6 +21,7 @@ mod vertex_buffer; mod draw_alpha_triangles_pass; mod draw_color_triangles_pass; mod draw_img_triangles_pass; +mod draw_linear_gradient_pass; mod draw_radial_gradient_pass; mod draw_texture_pass; @@ -34,7 +37,8 @@ pub struct WgpuImpl { draw_alpha_triangles_pass: DrawAlphaTrianglesPass, draw_color_triangles_pass: DrawColorTrianglesPass, draw_img_triangles_pass: DrawImgTrianglesPass, - draw_radial_gradient_pass: draw_radial_gradient_pass::DrawRadialGradientTrianglesPass, + draw_radial_gradient_pass: DrawRadialGradientTrianglesPass, + draw_linear_gradient_pass: DrawLinearGradientTrianglesPass, textures_bind: TexturesBind, mask_layers_storage: Storage, @@ -121,7 +125,7 @@ impl GPUBackendImpl for WgpuImpl { .load_triangles_vertices(buffers, &self.device, &self.queue); } - fn load_img_vertices(&mut self, buffers: &VertexBuffers) { + fn load_img_vertices(&mut self, buffers: &VertexBuffers) { self .draw_img_triangles_pass .load_triangles_vertices(buffers, &self.device, &self.queue); @@ -136,19 +140,37 @@ impl GPUBackendImpl for WgpuImpl { fn load_radial_gradient_primitives(&mut self, primitives: &[RadialGradientPrimitive]) { self .draw_radial_gradient_pass - .load_radial_gradient_primitives(&self.device, &mut self.queue, primitives); + .load_radial_gradient_primitives(&self.device, &self.queue, primitives); } fn load_radial_gradient_stops(&mut self, stops: &[GradientStopPrimitive]) { self .draw_radial_gradient_pass - .load_gradient_stops(&self.device, &mut self.queue, stops); + .load_gradient_stops(&self.device, &self.queue, stops); } - fn load_radial_gradient_vertices(&mut self, buffers: &VertexBuffers) { + fn load_radial_gradient_vertices(&mut self, buffers: &VertexBuffers) { self .draw_radial_gradient_pass - .load_triangles_vertices(buffers, &self.device, &mut self.queue); + .load_triangles_vertices(buffers, &self.device, &self.queue); + } + + fn load_linear_gradient_primitives(&mut self, primitives: &[LinearGradientPrimitive]) { + self + .draw_linear_gradient_pass + .load_linear_gradient_primitives(&self.device, &self.queue, primitives); + } + + fn load_linear_gradient_stops(&mut self, stops: &[GradientStopPrimitive]) { + self + .draw_linear_gradient_pass + .load_gradient_stops(&self.device, &self.queue, stops); + } + + fn load_linear_gradient_vertices(&mut self, buffers: &VertexBuffers) { + self + .draw_linear_gradient_pass + .load_triangles_vertices(buffers, &self.device, &self.queue); } fn load_mask_layers(&mut self, layers: &[crate::MaskLayer]) { @@ -187,6 +209,25 @@ impl GPUBackendImpl for WgpuImpl { ); } + fn draw_linear_gradient_triangles( + &mut self, + texture: &mut Self::Texture, + indices: Range, + clear: Option, + ) { + let encoder = command_encoder!(self); + + self.draw_linear_gradient_pass.draw_triangles( + texture, + indices, + clear, + &self.device, + encoder, + &self.textures_bind, + &self.mask_layers_storage, + ); + } + fn draw_alpha_triangles_with_scissor( &mut self, indices: &Range, @@ -582,7 +623,8 @@ impl WgpuImpl { let draw_color_triangles_pass = DrawColorTrianglesPass::new(&device); let draw_img_triangles_pass = DrawImgTrianglesPass::new(&device); - let radial_gradient_pass = DrawRadialGradientTrianglesPass::new(&device); + let draw_radial_gradient_pass = DrawRadialGradientTrianglesPass::new(&device); + let draw_linear_gradient_pass = DrawLinearGradientTrianglesPass::new(&device); let mask_layers_storage = Storage::new(&device, wgpu::ShaderStages::FRAGMENT, 512); WgpuImpl { device, @@ -595,7 +637,8 @@ impl WgpuImpl { draw_alpha_triangles_pass, draw_color_triangles_pass, draw_img_triangles_pass, - draw_radial_gradient_pass: radial_gradient_pass, + draw_radial_gradient_pass, + draw_linear_gradient_pass, textures_bind: TexturesBind::default(), mask_layers_storage, } diff --git a/gpu/src/wgpu_impl/draw_img_triangles_pass.rs b/gpu/src/wgpu_impl/draw_img_triangles_pass.rs index ee8b44b32..8e91e026a 100644 --- a/gpu/src/wgpu_impl/draw_img_triangles_pass.rs +++ b/gpu/src/wgpu_impl/draw_img_triangles_pass.rs @@ -1,11 +1,11 @@ use super::{storage::Storage, vertex_buffer::VerticesBuffer}; -use crate::{ImgPrimitive, MaskLayer, TexturesBind, WgpuTexture}; +use crate::{ImagePrimIndex, ImgPrimitive, MaskLayer, TexturesBind, WgpuTexture}; use ribir_painter::{AntiAliasing, Color, Vertex, VertexBuffers}; use std::{mem::size_of, ops::Range}; pub struct DrawImgTrianglesPass { label: &'static str, - vertices_buffer: VerticesBuffer, + vertices_buffer: VerticesBuffer, pipeline: Option, shader: wgpu::ShaderModule, @@ -40,7 +40,7 @@ impl DrawImgTrianglesPass { pub fn load_triangles_vertices( &mut self, - buffers: &VertexBuffers, + buffers: &VertexBuffers, device: &wgpu::Device, queue: &wgpu::Queue, ) { diff --git a/gpu/src/wgpu_impl/draw_linear_gradient_pass.rs b/gpu/src/wgpu_impl/draw_linear_gradient_pass.rs new file mode 100644 index 000000000..2e3989d1f --- /dev/null +++ b/gpu/src/wgpu_impl/draw_linear_gradient_pass.rs @@ -0,0 +1,200 @@ +use super::{storage::Storage, vertex_buffer::VerticesBuffer}; +use crate::{ + GradientStopPrimitive, LinearGradientPrimIndex, LinearGradientPrimitive, MaskLayer, TexturesBind, + WgpuTexture, +}; +use ribir_painter::{AntiAliasing, Color, Vertex, VertexBuffers}; +use std::{mem::size_of, ops::Range}; + +pub struct DrawLinearGradientTrianglesPass { + label: &'static str, + vertices_buffer: VerticesBuffer, + pipeline: Option, + shader: wgpu::ShaderModule, + format: Option, + prims_storage: Storage, + stops_storage: Storage, + textures_count: usize, + anti_aliasing: AntiAliasing, +} + +impl DrawLinearGradientTrianglesPass { + pub fn new(device: &wgpu::Device) -> Self { + let vertices_buffer = VerticesBuffer::new(512, 1024, device); + let label = "linear gradient triangles pass"; + let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { + label: Some(label), + source: wgpu::ShaderSource::Wgsl( + include_str!("./shaders/linear_gradient_triangles.wgsl").into(), + ), + }); + let prims_storage = Storage::new(device, wgpu::ShaderStages::FRAGMENT, 64); + let stops_storage = Storage::new(device, wgpu::ShaderStages::FRAGMENT, 64); + + Self { + label, + vertices_buffer, + pipeline: None, + shader, + format: None, + textures_count: 0, + prims_storage, + stops_storage, + anti_aliasing: AntiAliasing::None, + } + } + + pub fn load_triangles_vertices( + &mut self, + buffers: &VertexBuffers, + device: &wgpu::Device, + queue: &wgpu::Queue, + ) { + self.vertices_buffer.write_buffer(buffers, device, queue); + } + + pub fn load_linear_gradient_primitives( + &mut self, + device: &wgpu::Device, + queue: &wgpu::Queue, + primitives: &[LinearGradientPrimitive], + ) { + self.prims_storage.write_buffer(device, queue, primitives); + } + + pub fn load_gradient_stops( + &mut self, + device: &wgpu::Device, + queue: &wgpu::Queue, + stops: &[GradientStopPrimitive], + ) { + self.stops_storage.write_buffer(device, queue, stops); + } + + #[allow(clippy::too_many_arguments)] + pub fn draw_triangles( + &mut self, + texture: &WgpuTexture, + indices: Range, + clear: Option, + device: &wgpu::Device, + encoder: &mut wgpu::CommandEncoder, + textures_bind: &TexturesBind, + mask_layer_storage: &Storage, + ) { + self.update( + texture.format(), + texture.anti_aliasing, + device, + textures_bind, + mask_layer_storage.layout(), + ); + let pipeline = self.pipeline.as_ref().unwrap(); + + let color_attachments = texture.color_attachments(clear); + let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some(self.label), + color_attachments: &[Some(color_attachments)], + depth_stencil_attachment: None, + }); + + rpass.set_vertex_buffer(0, self.vertices_buffer.vertices().slice(..)); + rpass.set_index_buffer( + self.vertices_buffer.indices().slice(..), + wgpu::IndexFormat::Uint32, + ); + rpass.set_bind_group(0, mask_layer_storage.bind_group(), &[]); + rpass.set_bind_group(1, self.stops_storage.bind_group(), &[]); + rpass.set_bind_group(2, self.prims_storage.bind_group(), &[]); + rpass.set_bind_group(3, textures_bind.assert_bind(), &[]); + + rpass.set_pipeline(pipeline); + rpass.draw_indexed(indices, 0, 0..1); + } + + fn update( + &mut self, + format: wgpu::TextureFormat, + anti_aliasing: AntiAliasing, + device: &wgpu::Device, + textures_bind: &TexturesBind, + mask_bind_layout: &wgpu::BindGroupLayout, + ) { + if self.format != Some(format) + || textures_bind.textures_count() != self.textures_count + || anti_aliasing != self.anti_aliasing + { + self.pipeline.take(); + self.format = Some(format); + self.textures_count = textures_bind.textures_count(); + self.anti_aliasing = anti_aliasing; + } + + if self.pipeline.is_none() { + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("update triangles pipeline layout"), + bind_group_layouts: &[ + mask_bind_layout, + self.stops_storage.layout(), + self.prims_storage.layout(), + textures_bind.assert_layout(), + ], + push_constant_ranges: &[], + }); + let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some(self.label), + layout: Some(&pipeline_layout), + vertex: wgpu::VertexState { + module: &self.shader, + entry_point: "vs_main", + buffers: &[wgpu::VertexBufferLayout { + array_stride: size_of::>() as wgpu::BufferAddress, + step_mode: wgpu::VertexStepMode::Vertex, + attributes: &[ + // position + wgpu::VertexAttribute { + offset: 0, + shader_location: 0, + format: wgpu::VertexFormat::Float32x2, + }, + // prim_idx + wgpu::VertexAttribute { + offset: 8, + shader_location: 1, + format: wgpu::VertexFormat::Uint32, + }, + ], + }], + }, + fragment: Some(wgpu::FragmentState { + module: &self.shader, + entry_point: "fs_main", + targets: &[Some(wgpu::ColorTargetState { + format, + blend: Some(wgpu::BlendState::ALPHA_BLENDING), + write_mask: wgpu::ColorWrites::all(), + })], + }), + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + front_face: wgpu::FrontFace::Ccw, + // Always draw rect with transform, there is no distinction between front and back, + // everything needs to be drawn. + cull_mode: None, + unclipped_depth: false, + polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, + }, + depth_stencil: None, + multisample: wgpu::MultisampleState { + count: anti_aliasing as u32, + mask: !0, + alpha_to_coverage_enabled: false, + }, + multiview: None, + }); + self.pipeline = Some(pipeline); + } + } +} diff --git a/gpu/src/wgpu_impl/draw_radial_gradient_pass.rs b/gpu/src/wgpu_impl/draw_radial_gradient_pass.rs index 1cb96f91f..c2ab29ee8 100644 --- a/gpu/src/wgpu_impl/draw_radial_gradient_pass.rs +++ b/gpu/src/wgpu_impl/draw_radial_gradient_pass.rs @@ -1,6 +1,6 @@ use super::{storage::Storage, vertex_buffer::VerticesBuffer}; use crate::{ - GradientStopPrimitive, MaskLayer, RadialGradientAttr, RadialGradientPrimitive, TexturesBind, + GradientStopPrimitive, MaskLayer, RadialGradientPrimIndex, RadialGradientPrimitive, TexturesBind, WgpuTexture, }; use ribir_painter::{AntiAliasing, Color, Vertex, VertexBuffers}; @@ -8,7 +8,7 @@ use std::{mem::size_of, ops::Range}; pub struct DrawRadialGradientTrianglesPass { label: &'static str, - vertices_buffer: VerticesBuffer, + vertices_buffer: VerticesBuffer, pipeline: Option, shader: wgpu::ShaderModule, format: Option, @@ -46,9 +46,9 @@ impl DrawRadialGradientTrianglesPass { pub fn load_triangles_vertices( &mut self, - buffers: &VertexBuffers, + buffers: &VertexBuffers, device: &wgpu::Device, - queue: &mut wgpu::Queue, + queue: &wgpu::Queue, ) { self.vertices_buffer.write_buffer(buffers, device, queue); } @@ -56,7 +56,7 @@ impl DrawRadialGradientTrianglesPass { pub fn load_radial_gradient_primitives( &mut self, device: &wgpu::Device, - queue: &mut wgpu::Queue, + queue: &wgpu::Queue, primitives: &[RadialGradientPrimitive], ) { self.prims_storage.write_buffer(device, queue, primitives); @@ -65,7 +65,7 @@ impl DrawRadialGradientTrianglesPass { pub fn load_gradient_stops( &mut self, device: &wgpu::Device, - queue: &mut wgpu::Queue, + queue: &wgpu::Queue, stops: &[GradientStopPrimitive], ) { self.stops_storage.write_buffer(device, queue, stops); @@ -74,7 +74,7 @@ impl DrawRadialGradientTrianglesPass { #[allow(clippy::too_many_arguments)] pub fn draw_triangles( &mut self, - texture: &mut WgpuTexture, + texture: &WgpuTexture, indices: Range, clear: Option, device: &wgpu::Device, @@ -148,7 +148,7 @@ impl DrawRadialGradientTrianglesPass { module: &self.shader, entry_point: "vs_main", buffers: &[wgpu::VertexBufferLayout { - array_stride: size_of::>() as wgpu::BufferAddress, + array_stride: size_of::>() as wgpu::BufferAddress, step_mode: wgpu::VertexStepMode::Vertex, attributes: &[ // position diff --git a/gpu/src/wgpu_impl/shaders/linear_gradient_triangles.wgsl b/gpu/src/wgpu_impl/shaders/linear_gradient_triangles.wgsl new file mode 100644 index 000000000..1d2040327 --- /dev/null +++ b/gpu/src/wgpu_impl/shaders/linear_gradient_triangles.wgsl @@ -0,0 +1,138 @@ +struct Vertex { + @location(0) pos: vec2, + @location(1) prim_idx: u32, +}; + +struct FragInput { + @builtin(position) pos: vec4, + @location(0) prim_idx: u32, +} + +@vertex +fn vs_main(v: Vertex) -> FragInput { + var input: FragInput; + // convert from gpu-backend coords(0..1) to wgpu corrds(-1..1) + let pos = v.pos * vec2(2., -2.) + vec2(-1., 1.); + input.pos = vec4(pos, 0.0, 1.0); + input.prim_idx = v.prim_idx; + return input; +} + + +struct MaskLayer { + transform: mat3x2, + min: vec2, + max: vec2, + mask_tex_idx: u32, + prev_mask_idx: i32, +} + +struct Stop { + red: f32, + green: f32, + blue: f32, + alpha: f32, + offset: f32, +} + +struct Primitive { + transform: mat3x2, + stop_start: i32, + stop_cnt: i32, + start_position: vec2, + end_position: vec2, + mask_head: i32, + spread: u32, // 0 for pad, 1 for reflect, 2 for repeat +} + +@group(0) @binding(0) +var mask_layers: array; + +@group(1) @binding(0) +var stops: array; + +@group(2) @binding(0) +var prims: array; + +@group(3) @binding(0) +var textures: binding_array>; +@group(3) @binding(1) +var samplers: binding_array; + +fn calc_mask_alpha(pos: vec2, mask_idx: i32) -> f32 { + var alpha = 1.; + var mask_idx = mask_idx; + loop { + if mask_idx < 0 { + break; + } + let mask = mask_layers[u32(mask_idx)]; + + var mask_pos = mask.transform * vec3(pos, 1.); + if any(mask_pos < mask.min) || any(mask.max < mask_pos) { + alpha = 0.; + break; + } + + let mask_tex_idx = mask.mask_tex_idx; + let texture = textures[mask_tex_idx]; + let s_sampler = samplers[mask_tex_idx]; + + let tex_size = textureDimensions(texture); + mask_pos = mask_pos / vec2(f32(tex_size.x), f32(tex_size.y)); + let a = textureSample(texture, s_sampler, mask_pos).r; + alpha = alpha * a; + if alpha == 0. { + break; + } + mask_idx = mask.prev_mask_idx; + } + return alpha; +} + +fn calc_offset(x: f32, y: f32, x_0: f32, y_0: f32, x_1: f32, y_1: f32) -> f32 { + let dx_0 = x - x_0; + let dy_0 = y - y_0; + let dx_1_0 = x_1 - x_0; + let dy_1_0 = y_1 - y_0; + + return (dx_0 * dx_1_0 + dy_0 * dy_1_0) / (dx_1_0 * dx_1_0 + dy_1_0 * dy_1_0); +} + +@fragment +fn fs_main(input: FragInput) -> @location(0) vec4 { + let prim = prims[input.prim_idx]; + let pos = prim.transform * vec3(input.pos.xy, 1.); + let alpha = calc_mask_alpha(input.pos.xy, prim.mask_head); + + if (prim.start_position.x == prim.end_position.x && + prim.start_position.y == prim.end_position.y) { + return vec4(1., 1., 1., alpha); + } + var offset = calc_offset(pos.x, pos.y, prim.start_position.x, prim.start_position.y, prim.end_position.x, prim.end_position.y); + + if (prim.spread == 0u) { + // pad + offset = min(1., max(0., offset)); + } else if (prim.spread == 1u) { + //reflect + offset = 1. - abs(fract(offset / 2.) - 0.5) * 2.; + } else { + //repeat + offset = fract(offset); + } + + var prev = stops[prim.stop_start]; + var next = stops[prim.stop_start + 1]; + for (var i = 2; i < prim.stop_cnt && next.offset < offset; i++) { + prev = next; + next = stops[prim.stop_start + i]; + } + + offset = max(prev.offset, min(next.offset, offset)); + let weight1 = (next.offset - offset) / (next.offset - prev.offset); + let weight2 = 1. - weight1; + let prev_color = vec4(prev.red, prev.green, prev.blue, prev.alpha); + let next_color = vec4(next.red, next.green, next.blue, next.alpha); + return (prev_color * weight1 + next_color * weight2) * vec4(1., 1., 1., alpha); +} diff --git a/gpu/src/wgpu_impl/shaders/radial_gradient_triangles.wgsl b/gpu/src/wgpu_impl/shaders/radial_gradient_triangles.wgsl index c94585a41..874f47ed7 100644 --- a/gpu/src/wgpu_impl/shaders/radial_gradient_triangles.wgsl +++ b/gpu/src/wgpu_impl/shaders/radial_gradient_triangles.wgsl @@ -94,7 +94,8 @@ fn calc_mask_alpha(pos: vec2, mask_idx: i32) -> f32 { } -fn calc_offset(x: f32, y: f32, x_0: f32, y_0: f32, r_0: f32, x_1: f32, y_1: f32, r_1: f32) -> f32 { +// input the center and radius of the circles, return the tag of resolvable (1. mean resolvable and -1. unresolvable) and the offset if tag is resolvable. +fn calc_offset(x: f32, y: f32, x_0: f32, y_0: f32, r_0: f32, x_1: f32, y_1: f32, r_1: f32) -> vec2 { /* see definition at https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-createradialgradient with offset ω, Radial gradients must be rendered by following these steps: @@ -138,12 +139,12 @@ fn calc_offset(x: f32, y: f32, x_0: f32, y_0: f32, r_0: f32, x_1: f32, y_1: f32, if (abs(a) < 0.1) { if (abs(b) < 0.1) { - return -1.; + return vec2(-1., 0.); } else { - return -c / b; + return vec2(1., -c / b); } } else if (delta < 0.) { - return -1.; + return vec2(-1., 0.); } let sqrt_delta = sqrt(delta); @@ -151,7 +152,7 @@ fn calc_offset(x: f32, y: f32, x_0: f32, y_0: f32, r_0: f32, x_1: f32, y_1: f32, let w1 = (-b + sqrt_delta) / _2a; let w2 = (-b - sqrt_delta) / _2a; - return max(w1, w2); + return vec2(1., max(w1, w2)); } @fragment @@ -160,11 +161,14 @@ fn fs_main(input: FragInput) -> @location(0) vec4 { let pos = prim.transform * vec3(input.pos.xy, 1.); let alpha = calc_mask_alpha(input.pos.xy, prim.mask_head); - var offset = calc_offset(pos.x, pos.y, prim.start_center.x, prim.start_center.y, prim.start_radius, prim.end_center.x, prim.end_center.y, prim.end_radius); - if (offset < 0.) { - discard; + let res = calc_offset(pos.x, pos.y, prim.start_center.x, prim.start_center.y, prim.start_radius, prim.end_center.x, prim.end_center.y, prim.end_radius); + + if (res[0] < 0. || ( + prim.start_radius != prim.end_radius && + res[1] < (prim.start_radius / (prim.start_radius - prim.end_radius)))) { + return vec4(1., 1., 1., alpha); } - + var offset = res[1]; if (prim.spread == 0u) { // pad offset = min(1., max(0., offset)); diff --git a/painter/src/color.rs b/painter/src/color.rs index b4a875e94..3144f9d2a 100644 --- a/painter/src/color.rs +++ b/painter/src/color.rs @@ -2,6 +2,8 @@ use material_color_utilities_rs::htc; use ribir_geom::{Point, Transform}; use serde::{Deserialize, Serialize}; +use crate::SpreadMethod; + #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)] pub struct Color { pub red: u8, @@ -15,7 +17,13 @@ pub struct GradientStop { pub color: Color, pub offset: f32, } -#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] + +impl GradientStop { + #[inline] + pub fn new(color: Color, offset: f32) -> Self { Self { color, offset } } +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)] pub struct RadialGradient { pub start_center: Point, pub start_radius: f32, @@ -23,6 +31,16 @@ pub struct RadialGradient { pub end_radius: f32, pub stops: Vec, pub transform: Transform, + pub spread_method: SpreadMethod, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)] +pub struct LinearGradient { + pub start: Point, + pub end: Point, + pub stops: Vec, + pub transform: Transform, + pub spread_method: SpreadMethod, } /// Describe the light tone of a color, should between [0, 1.0], 0.0 gives diff --git a/painter/src/painter.rs b/painter/src/painter.rs index b78ad9693..569eec15a 100644 --- a/painter/src/painter.rs +++ b/painter/src/painter.rs @@ -1,5 +1,8 @@ use crate::{ - color::GradientStop, path::*, path_builder::PathBuilder, Brush, Color, PixelImage, Svg, + color::{LinearGradient, RadialGradient}, + path::*, + path_builder::PathBuilder, + Brush, Color, PixelImage, Svg, }; use ribir_algo::ShareResource; use ribir_geom::{Angle, DeviceRect, Point, Rect, Size, Transform, Vector}; @@ -75,13 +78,24 @@ pub struct PaintPath { } #[repr(u32)] -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, Serialize, Deserialize, Default, PartialEq)] pub enum SpreadMethod { + #[default] Pad, Reflect, Repeat, } +impl From for SpreadMethod { + fn from(value: usvg::SpreadMethod) -> Self { + match value { + usvg::SpreadMethod::Pad => SpreadMethod::Pad, + usvg::SpreadMethod::Reflect => SpreadMethod::Reflect, + usvg::SpreadMethod::Repeat => SpreadMethod::Repeat, + } + } +} + #[derive(Debug, Clone, Serialize, Deserialize)] pub enum PaintCommand { ColorPath { @@ -95,13 +109,11 @@ pub enum PaintCommand { }, RadialGradient { path: PaintPath, - stops: Vec, - start: Point, - start_radius: f32, - end: Point, - end_radius: f32, - spread: SpreadMethod, - transform: Transform, + radial_gradient: RadialGradient, + }, + LinearGradient { + path: PaintPath, + linear_gradient: LinearGradient, }, // Todo: keep rectangle clip. Clip(PaintPath), @@ -308,16 +320,12 @@ impl Painter { color: color.apply_alpha(opacity), }, Brush::Image(img) => PaintCommand::ImgPath { path, img, opacity }, - Brush::RadialGradient(radial_gradient) => PaintCommand::RadialGradient { - path: path, - stops: radial_gradient.stops, - start: radial_gradient.start_center, - start_radius: radial_gradient.start_radius, - end: radial_gradient.end_center, - end_radius: radial_gradient.end_radius, - transform: radial_gradient.transform, - spread: SpreadMethod::Pad, - }, + Brush::RadialGradient(radial_gradient) => { + PaintCommand::RadialGradient { path, radial_gradient } + } + Brush::LinearGradient(linear_gradient) => { + PaintCommand::LinearGradient { path, linear_gradient } + } }; self.commands.push(cmd); } diff --git a/painter/src/style.rs b/painter/src/style.rs index 9b6b5f107..b576ad209 100644 --- a/painter/src/style.rs +++ b/painter/src/style.rs @@ -1,4 +1,7 @@ -use crate::{color::RadialGradient, Color, PixelImage}; +use crate::{ + color::{LinearGradient, RadialGradient}, + Color, PixelImage, +}; use ribir_algo::ShareResource; use serde::{Deserialize, Serialize}; @@ -8,6 +11,7 @@ pub enum Brush { /// Image brush always use a repeat mode to brush the path. Image(ShareResource), RadialGradient(RadialGradient), + LinearGradient(LinearGradient), } impl Brush { diff --git a/painter/src/svg.rs b/painter/src/svg.rs index 541a728ed..b50eb78bf 100644 --- a/painter/src/svg.rs +++ b/painter/src/svg.rs @@ -1,11 +1,11 @@ use crate::{ - color::RadialGradient, Brush, Color, GradientStop, LineCap, LineJoin, Path, PathPaintStyle, - StrokeOptions, + color::{LinearGradient, RadialGradient}, + Brush, Color, GradientStop, LineCap, LineJoin, Path, PathPaintStyle, StrokeOptions, }; use ribir_geom::{Point, Size, Transform, Vector}; use serde::{Deserialize, Serialize}; -use std::{error::Error, io::Read, rc::Rc, time::Instant}; -use usvg::{Options, Tree, TreeParsing}; +use std::{error::Error, io::Read}; +use usvg::{Options, Stop, Tree, TreeParsing}; #[derive(Serialize, Deserialize, Clone)] pub struct Svg { @@ -21,18 +21,16 @@ pub struct SvgPath { pub style: PathPaintStyle, } -/// Fits size into a viewbox. -fn fit_view_box(s: usvg::Size, vb: &usvg::ViewBox) -> usvg::Size { +/// Fits size into a viewbox. copy from resvg +fn fit_view_box(size: usvg::Size, vb: &usvg::ViewBox) -> usvg::Size { let s = vb.rect.size(); if vb.aspect.align == usvg::Align::None { s + } else if vb.aspect.slice { + size.expand_to(s) } else { - if vb.aspect.slice { - s.expand_to(s) - } else { - s.scale_to(s) - } + size.scale_to(s) } } @@ -50,7 +48,7 @@ impl Svg { size.height() / fit_size.height(), ) .to_f32(); - let t = Transform::translation(-view_rect.x() as f32, -view_rect.y() as f32); + let t = Transform::translation(-view_rect.x(), -view_rect.y()); let mut t_stack = TransformStack::new(t); let mut paths = vec![]; @@ -86,10 +84,10 @@ impl Svg { usvg::LineJoin::Round => LineJoin::Round, }; let options = StrokeOptions { - width: stroke.width.get() as f32, + width: stroke.width.get(), line_cap: cap, line_join: join, - miter_limit: stroke.miterlimit.get() as f32, + miter_limit: stroke.miterlimit.get(), }; let brush = brush_from_usvg_paint(&stroke.paint, stroke.opacity, &size); @@ -131,7 +129,7 @@ impl Svg { }); Ok(Svg { - size: Size::new(size.width() as f32, size.height() as f32), + size: Size::new(size.width(), size.height()), paths: paths.into_boxed_slice(), view_scale, }) @@ -187,52 +185,45 @@ fn matrix_convert(t: usvg::Transform) -> Transform { fn brush_from_usvg_paint(paint: &usvg::Paint, opacity: usvg::Opacity, size: &usvg::Size) -> Brush { match paint { usvg::Paint::Color(usvg::Color { red, green, blue }) => Color::from_rgb(*red, *green, *blue) - .with_alpha(opacity.get() as f32) + .with_alpha(opacity.get()) .into(), - usvg::Paint::LinearGradient(gradient) => { - let mut stops = gradient.stops.clone(); - stops.sort_by(|s1, s2| s1.offset.cmp(&s2.offset)); - let mut offset = 0.; - let mut red = 0.; - let mut green = 0.; - let mut blue = 0.; - for stop in stops.iter() { - let color = stop.color; - let weight = stop.offset.get() - offset; - offset = stop.offset.get(); - red += (color.red as f32 - red) * weight; - blue += (color.blue as f32 - blue) * weight; - green += (color.green as f32 - green) * weight; - } - Color::from_rgb(red as u8, green as u8, blue as u8).into() + usvg::Paint::LinearGradient(linear) => { + let stops = convert_to_gradient_stops(&linear.stops); + let size_scale = match linear.units { + usvg::Units::UserSpaceOnUse => (1., 1.), + usvg::Units::ObjectBoundingBox => (size.width(), size.height()), + }; + let gradient = LinearGradient { + start: Point::new(linear.x1 * size_scale.0, linear.y1 * size_scale.1), + end: Point::new(linear.y2 * size_scale.0, linear.y2 * size_scale.1), + stops, + transform: matrix_convert(linear.transform), + spread_method: linear.spread_method.into(), + }; + Brush::LinearGradient(gradient) } - usvg::Paint::RadialGradient(gradient) => { - let mut stops = gradient.stops.clone(); - stops.sort_by(|s1, s2| s1.offset.cmp(&s2.offset)); - - let stops = stops - .iter() - .map(|stop| { - let usvg::Color { red, green, blue } = stop.color; - GradientStop { - offset: stop.offset.get(), - color: Color::from_rgb(red, green, blue), - } - }) - .collect(); - let size_scale = match gradient.units { + usvg::Paint::RadialGradient(radial_gradient) => { + let stops = convert_to_gradient_stops(&radial_gradient.stops); + let size_scale = match radial_gradient.units { usvg::Units::UserSpaceOnUse => (1., 1.), usvg::Units::ObjectBoundingBox => (size.width(), size.height()), }; - let radial = RadialGradient { - start_center: Point::new(gradient.fx * size_scale.0, gradient.fy * size_scale.1), + let gradient = RadialGradient { + start_center: Point::new( + radial_gradient.fx * size_scale.0, + radial_gradient.fy * size_scale.1, + ), start_radius: 0., - end_center: Point::new(gradient.cx * size_scale.0, gradient.cy * size_scale.1), - end_radius: gradient.r.get() * size_scale.0, + end_center: Point::new( + radial_gradient.cx * size_scale.0, + radial_gradient.cy * size_scale.1, + ), + end_radius: radial_gradient.r.get() * size_scale.0, stops, - transform: matrix_convert(gradient.transform), + transform: matrix_convert(radial_gradient.transform), + spread_method: radial_gradient.spread_method.into(), }; - Brush::RadialGradient(radial) + Brush::RadialGradient(gradient) } paint => { log::warn!("[painter]: not support `{paint:?}` in svg, use black instead!"); @@ -241,6 +232,35 @@ fn brush_from_usvg_paint(paint: &usvg::Paint, opacity: usvg::Opacity, size: &usv } } +fn convert_to_gradient_stops(stops: &Vec) -> Vec { + assert!(!stops.is_empty()); + + let mut stops: Vec<_> = stops + .iter() + .map(|stop| { + let usvg::Color { red, green, blue } = stop.color; + GradientStop { + offset: stop.offset.get(), + color: Color::from_rgb(red, green, blue), + } + }) + .collect(); + + stops.sort_by(|s1, s2| s1.offset.partial_cmp(&s2.offset).unwrap()); + + if let Some(first) = stops.first() { + if first.offset != 0. { + stops.insert(0, GradientStop { offset: 0., color: first.color }); + } + } + if let Some(last) = stops.last() { + if last.offset < 1. { + stops.push(GradientStop { offset: 1., color: last.color }); + } + } + stops +} + struct TransformStack { stack: Vec, } diff --git a/ribir/src/winit_shell_wnd.rs b/ribir/src/winit_shell_wnd.rs index 69eb18918..b40d8a444 100644 --- a/ribir/src/winit_shell_wnd.rs +++ b/ribir/src/winit_shell_wnd.rs @@ -118,6 +118,7 @@ impl ShellWindow for WinitShellWnd { PaintCommand::ColorPath { path, .. } | PaintCommand::ImgPath { path, .. } | PaintCommand::RadialGradient { path, .. } + | PaintCommand::LinearGradient { path, .. } | PaintCommand::Clip(path) => path.scale(self.winit_wnd.scale_factor() as f32), PaintCommand::PopClip => {} }); diff --git a/test_cases/ribir_gpu/gpu_backend/tests/draw_linear_gradient_wgpu.png b/test_cases/ribir_gpu/gpu_backend/tests/draw_linear_gradient_wgpu.png new file mode 100644 index 0000000000000000000000000000000000000000..c1d472eacd9137f4805c675c19ff600ee4adf118 GIT binary patch literal 1503 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 Date: Wed, 20 Sep 2023 14:11:14 +0800 Subject: [PATCH 3/7] =?UTF-8?q?refactor(painter):=20=F0=9F=92=A1=20impleme?= =?UTF-8?q?nt=20svg=20implement=20by=20paintcommand?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gpu/src/gpu_backend.rs | 64 ++------- gpu/src/gpu_backend/textures_mgr.rs | 11 +- painter/src/color.rs | 4 +- painter/src/painter.rs | 34 +++-- painter/src/svg.rs | 124 ++++++++---------- .../messages_with_default_by_wgpu.png | Bin 29618 -> 30006 bytes .../messages_with_material_by_wgpu.png | Bin 30889 -> 31605 bytes .../tests/draw_linear_gradient_wgpu.png | Bin 1503 -> 0 bytes .../tests/draw_radial_gradient_wgpu.png | Bin 4516 -> 0 bytes .../tests/draw_svg_gradient_wgpu.png | Bin 0 -> 2085 bytes .../tests/transform_img_brush_wgpu.png | Bin 32730 -> 32560 bytes .../tests/checked_with_default_by_wgpu.png | Bin 494 -> 660 bytes .../indeterminate_with_default_by_wgpu.png | Bin 428 -> 512 bytes .../tests/unchecked_with_default_by_wgpu.png | Bin 415 -> 452 bytes .../storybook_with_default_by_wgpu.png | Bin 34428 -> 35671 bytes .../storybook_with_material_by_wgpu.png | Bin 36754 -> 37104 bytes tests/assets/fill_with_gradient.svg | 16 +++ tests/include_svg_test.rs | 2 +- 18 files changed, 110 insertions(+), 145 deletions(-) delete mode 100644 test_cases/ribir_gpu/gpu_backend/tests/draw_linear_gradient_wgpu.png delete mode 100644 test_cases/ribir_gpu/gpu_backend/tests/draw_radial_gradient_wgpu.png create mode 100644 test_cases/ribir_gpu/gpu_backend/tests/draw_svg_gradient_wgpu.png create mode 100644 tests/assets/fill_with_gradient.svg diff --git a/gpu/src/gpu_backend.rs b/gpu/src/gpu_backend.rs index 81ee678f8..3ef379e19 100644 --- a/gpu/src/gpu_backend.rs +++ b/gpu/src/gpu_backend.rs @@ -241,12 +241,7 @@ where if let Some((rect, mask_head)) = self.new_mask_layer(path) { self.update_to_radial_gradient_indices(); let prim: RadialGradientPrimitive = RadialGradientPrimitive { - transform: radial_gradient - .transform - .then(&ts) - .inverse() - .unwrap() - .to_array(), + transform: ts.inverse().unwrap().to_array(), stop_start: self.radial_gradient_stops.len() as u32, stop_cnt: radial_gradient.stops.len() as u32, start_center: radial_gradient.start_center.to_array(), @@ -279,12 +274,7 @@ where if let Some((rect, mask_head)) = self.new_mask_layer(path) { self.update_to_linear_gradient_indices(); let prim: LinearGradientPrimitive = LinearGradientPrimitive { - transform: linear_gradient - .transform - .then(&ts) - .inverse() - .unwrap() - .to_array(), + transform: ts.inverse().unwrap().to_array(), stop_start: self.linear_gradient_stops.len() as u32, stop_cnt: linear_gradient.stops.len() as u32, start_position: linear_gradient.start.to_array(), @@ -541,10 +531,7 @@ mod tests { use ribir_algo::ShareResource; use ribir_dev_helper::*; use ribir_geom::*; - use ribir_painter::{ - color::{LinearGradient, RadialGradient}, - Brush, Color, GradientStop, Painter, Path, PixelImage, - }; + use ribir_painter::{Brush, Color, Painter, Path, PixelImage, Svg}; fn painter(bounds: Size) -> Painter { Painter::new(Rect::from_size(bounds)) } @@ -682,48 +669,13 @@ mod tests { painter } - painter_backend_eq_image_test!(draw_radial_gradient); - fn draw_radial_gradient() -> Painter { + painter_backend_eq_image_test!(draw_svg_gradient); + fn draw_svg_gradient() -> Painter { let mut painter = painter(Size::new(64., 64.)); - let brush = Brush::RadialGradient(RadialGradient { - start_center: Point::new(16., 32.), - start_radius: 0., - end_center: Point::new(32., 32.), - end_radius: 32., - stops: vec![ - GradientStop::new(Color::RED, 0.), - GradientStop::new(Color::BLUE, 1.), - ], - transform: Transform::translation(16., 0.), - ..Default::default() - }); - - painter - .set_brush(brush) - .rect(&Rect::from_size(Size::new(64., 64.))) - .fill(); - - painter - } - - painter_backend_eq_image_test!(draw_linear_gradient); - fn draw_linear_gradient() -> Painter { - let mut painter = painter(Size::new(32., 32.)); - let brush = Brush::LinearGradient(LinearGradient { - start: Point::new(0., 0.), - end: Point::new(16., 16.), - stops: vec![ - GradientStop::new(Color::RED, 0.), - GradientStop::new(Color::BLUE, 1.), - ], - ..Default::default() - }); - - painter - .set_brush(brush) - .rect(&Rect::from_size(Size::new(64., 64.))) - .fill(); + let svg = + Svg::parse_from_bytes(include_bytes!("../../tests/assets/fill_with_gradient.svg")).unwrap(); + painter.draw_svg(&svg); painter } } diff --git a/gpu/src/gpu_backend/textures_mgr.rs b/gpu/src/gpu_backend/textures_mgr.rs index d4ee365d0..7b7e45b40 100644 --- a/gpu/src/gpu_backend/textures_mgr.rs +++ b/gpu/src/gpu_backend/textures_mgr.rs @@ -59,6 +59,11 @@ macro_rules! id_to_texture { }; } +fn get_transform_pref_scale(transform: &Transform) -> f32 { + let Transform { m11, m12, m21, m22, .. } = *transform; + (m11.abs() + m12.abs()).max(m21.abs() + m22.abs()) +} + impl TexturesMgr where T::Host: GPUBackendImpl, @@ -109,7 +114,7 @@ where .then(path_ts) } - let prefer_scale: f32 = transform.m11.abs().max(transform.m22.abs()); + let prefer_scale: f32 = get_transform_pref_scale(transform); let key = PathKey::from_path(path); if let Some(h) = self @@ -217,7 +222,7 @@ where let tex_width = tex_size.width as f32; let tex_height = tex_size.height as f32; - let scale = ts.m11.max(ts.m22); + let scale = get_transform_pref_scale(ts); path.tessellate(TOLERANCE / scale, buffer, |pos| { let pos = ts.transform_point(pos); @@ -520,7 +525,7 @@ impl PartialEq for PathKey { impl Eq for PathKey {} pub fn prefer_cache_size(path: &Path, transform: &Transform) -> DeviceSize { - let prefer_scale: f32 = transform.m11.max(transform.m22); + let prefer_scale: f32 = get_transform_pref_scale(transform); let prefer_cache_size = path .bounds() .scale(prefer_scale, prefer_scale) diff --git a/painter/src/color.rs b/painter/src/color.rs index 3144f9d2a..19a0fa7c2 100644 --- a/painter/src/color.rs +++ b/painter/src/color.rs @@ -1,5 +1,5 @@ use material_color_utilities_rs::htc; -use ribir_geom::{Point, Transform}; +use ribir_geom::Point; use serde::{Deserialize, Serialize}; use crate::SpreadMethod; @@ -30,7 +30,6 @@ pub struct RadialGradient { pub end_center: Point, pub end_radius: f32, pub stops: Vec, - pub transform: Transform, pub spread_method: SpreadMethod, } @@ -39,7 +38,6 @@ pub struct LinearGradient { pub start: Point, pub end: Point, pub stops: Vec, - pub transform: Transform, pub spread_method: SpreadMethod, } diff --git a/painter/src/painter.rs b/painter/src/painter.rs index 569eec15a..d9de6126d 100644 --- a/painter/src/painter.rs +++ b/painter/src/painter.rs @@ -120,6 +120,20 @@ pub enum PaintCommand { PopClip, } +impl PaintCommand { + pub fn transform(mut self, transform: &Transform) -> Self { + match &mut self { + PaintCommand::ColorPath { path, .. } + | PaintCommand::ImgPath { path, .. } + | PaintCommand::RadialGradient { path, .. } + | PaintCommand::LinearGradient { path, .. } + | PaintCommand::Clip(path) => path.transform(transform), + PaintCommand::PopClip => {} + } + self + } +} + #[derive(Clone)] struct PainterState { /// The line width use to stroke path. @@ -474,16 +488,11 @@ impl Painter { } pub fn draw_svg(&mut self, svg: &Svg) -> &mut Self { - self.scale(svg.view_scale.x, svg.view_scale.y); - svg.paths.iter().for_each(|c| { - self.set_brush(c.brush.clone()); - match &c.style { - PathPaintStyle::Fill => self.fill_path(c.path.clone()), - PathPaintStyle::Stroke(options) => self - .set_strokes(options.clone()) - .stroke_path(c.path.clone()), - }; - }); + let transform = *self.get_transform(); + svg + .paint_commands + .iter() + .for_each(|c| self.commands.push(c.clone().transform(&transform))); self } @@ -596,6 +605,11 @@ impl PaintPath { self.transform = self.transform.then_scale(scale, scale); self.paint_bounds = self.paint_bounds.scale(scale, scale); } + + pub fn transform(&mut self, transform: &Transform) { + self.transform = self.transform.then(transform); + self.paint_bounds = self.transform.outer_transformed_rect(self.path.bounds()); + } } #[cfg(test)] diff --git a/painter/src/svg.rs b/painter/src/svg.rs index b50eb78bf..676c5438b 100644 --- a/painter/src/svg.rs +++ b/painter/src/svg.rs @@ -1,8 +1,8 @@ use crate::{ color::{LinearGradient, RadialGradient}, - Brush, Color, GradientStop, LineCap, LineJoin, Path, PathPaintStyle, StrokeOptions, + Brush, Color, GradientStop, LineCap, LineJoin, PaintCommand, Path, StrokeOptions, }; -use ribir_geom::{Point, Size, Transform, Vector}; +use ribir_geom::{Point, Rect, Size, Transform}; use serde::{Deserialize, Serialize}; use std::{error::Error, io::Read}; use usvg::{Options, Stop, Tree, TreeParsing}; @@ -10,15 +10,7 @@ use usvg::{Options, Stop, Tree, TreeParsing}; #[derive(Serialize, Deserialize, Clone)] pub struct Svg { pub size: Size, - pub view_scale: Vector, - pub paths: Box<[SvgPath]>, -} - -#[derive(Serialize, Deserialize, Clone)] -pub struct SvgPath { - pub path: Path, - pub brush: Brush, - pub style: PathPaintStyle, + pub paint_commands: Vec, } /// Fits size into a viewbox. copy from resvg @@ -43,33 +35,28 @@ impl Svg { let size = tree.size; let fit_size = fit_view_box(size, &tree.view_box); - let view_scale = Vector::new( - size.width() / fit_size.width(), - size.height() / fit_size.height(), - ) - .to_f32(); - let t = Transform::translation(-view_rect.x(), -view_rect.y()); - - let mut t_stack = TransformStack::new(t); - let mut paths = vec![]; - + let bound_rect = Rect::from_size(Size::new(f32::INFINITY, f32::INFINITY)); + let mut painter = crate::Painter::new(bound_rect); + painter.apply_transform( + &Transform::translation(-view_rect.x(), -view_rect.y()).then_scale( + size.width() / fit_size.width(), + size.height() / fit_size.height(), + ), + ); tree.root.traverse().for_each(|edge| match edge { rctree::NodeEdge::Start(node) => { use usvg::NodeKind; - + painter.save(); match &*node.borrow() { NodeKind::Path(p) => { - t_stack.push(matrix_convert(p.transform)); + painter.apply_transform(&matrix_convert(p.transform)); let path = usvg_path_to_path(p); - let path = path.transform(t_stack.current_transform()); if let Some(ref fill) = p.fill { - let brush = brush_from_usvg_paint(&fill.paint, fill.opacity, &size); - - paths.push(SvgPath { - path: path.clone(), - brush, - style: PathPaintStyle::Fill, - }); + let (brush, transform) = brush_from_usvg_paint(&fill.paint, fill.opacity, &size); + let mut painter = painter.save_guard(); + painter.set_brush(brush.clone()); + painter.apply_transform(&transform); + painter.fill_path(path.clone().transform(&transform.inverse().unwrap())); //&o_ts.then(&n_ts.inverse().unwrap()))); } if let Some(ref stroke) = p.stroke { @@ -90,12 +77,12 @@ impl Svg { miter_limit: stroke.miterlimit.get(), }; - let brush = brush_from_usvg_paint(&stroke.paint, stroke.opacity, &size); - paths.push(SvgPath { - path, - brush, - style: PathPaintStyle::Stroke(options), - }); + let (brush, transform) = brush_from_usvg_paint(&stroke.paint, stroke.opacity, &size); + let mut painter = painter.save_guard(); + painter.set_brush(brush.clone()); + painter.apply_transform(&transform); + painter.set_strokes(options); + painter.stroke_path(path.transform(&transform.inverse().unwrap())); }; } NodeKind::Image(_) => { @@ -103,7 +90,7 @@ impl Svg { log::warn!("[painter]: not support draw embed image in svg, ignored!"); } NodeKind::Group(ref g) => { - t_stack.push(matrix_convert(g.transform)); + painter.apply_transform(&matrix_convert(g.transform)); // todo; if g.opacity.get() != 1. { log::warn!("[painter]: not support `opacity` in svg, ignored!"); @@ -124,14 +111,13 @@ impl Svg { } } rctree::NodeEdge::End(_) => { - t_stack.pop(); + painter.restore(); } }); Ok(Svg { size: Size::new(size.width(), size.height()), - paths: paths.into_boxed_slice(), - view_scale, + paint_commands: painter.finish(), }) } @@ -182,11 +168,18 @@ fn matrix_convert(t: usvg::Transform) -> Transform { Transform::new(sx, ky, kx, sy, tx, ty) } -fn brush_from_usvg_paint(paint: &usvg::Paint, opacity: usvg::Opacity, size: &usvg::Size) -> Brush { +fn brush_from_usvg_paint( + paint: &usvg::Paint, + opacity: usvg::Opacity, + size: &usvg::Size, +) -> (Brush, Transform) { match paint { - usvg::Paint::Color(usvg::Color { red, green, blue }) => Color::from_rgb(*red, *green, *blue) - .with_alpha(opacity.get()) - .into(), + usvg::Paint::Color(usvg::Color { red, green, blue }) => ( + Color::from_rgb(*red, *green, *blue) + .with_alpha(opacity.get()) + .into(), + Transform::identity(), + ), usvg::Paint::LinearGradient(linear) => { let stops = convert_to_gradient_stops(&linear.stops); let size_scale = match linear.units { @@ -195,12 +188,15 @@ fn brush_from_usvg_paint(paint: &usvg::Paint, opacity: usvg::Opacity, size: &usv }; let gradient = LinearGradient { start: Point::new(linear.x1 * size_scale.0, linear.y1 * size_scale.1), - end: Point::new(linear.y2 * size_scale.0, linear.y2 * size_scale.1), + end: Point::new(linear.x2 * size_scale.0, linear.y2 * size_scale.1), stops, - transform: matrix_convert(linear.transform), spread_method: linear.spread_method.into(), }; - Brush::LinearGradient(gradient) + + ( + Brush::LinearGradient(gradient), + matrix_convert(linear.transform), + ) } usvg::Paint::RadialGradient(radial_gradient) => { let stops = convert_to_gradient_stops(&radial_gradient.stops); @@ -213,21 +209,24 @@ fn brush_from_usvg_paint(paint: &usvg::Paint, opacity: usvg::Opacity, size: &usv radial_gradient.fx * size_scale.0, radial_gradient.fy * size_scale.1, ), - start_radius: 0., + start_radius: 0., // usvg not support fr end_center: Point::new( radial_gradient.cx * size_scale.0, radial_gradient.cy * size_scale.1, ), end_radius: radial_gradient.r.get() * size_scale.0, stops, - transform: matrix_convert(radial_gradient.transform), spread_method: radial_gradient.spread_method.into(), }; - Brush::RadialGradient(gradient) + + ( + Brush::RadialGradient(gradient), + matrix_convert(radial_gradient.transform), + ) } paint => { log::warn!("[painter]: not support `{paint:?}` in svg, use black instead!"); - Color::BLACK.into() + (Color::BLACK.into(), Transform::identity()) } } } @@ -241,7 +240,7 @@ fn convert_to_gradient_stops(stops: &Vec) -> Vec { let usvg::Color { red, green, blue } = stop.color; GradientStop { offset: stop.offset.get(), - color: Color::from_rgb(red, green, blue), + color: Color::new(red, green, blue, stop.opacity.to_u8()), } }) .collect(); @@ -260,22 +259,3 @@ fn convert_to_gradient_stops(stops: &Vec) -> Vec { } stops } - -struct TransformStack { - stack: Vec, -} - -impl TransformStack { - fn new(t: Transform) -> Self { TransformStack { stack: vec![t] } } - - fn push(&mut self, mut t: Transform) { - if let Some(p) = self.stack.last() { - t = p.then(&t); - } - self.stack.push(t); - } - - fn pop(&mut self) -> Option { self.stack.pop() } - - fn current_transform(&self) -> &Transform { self.stack.last().unwrap() } -} diff --git a/test_cases/messages/messages_with_default_by_wgpu.png b/test_cases/messages/messages_with_default_by_wgpu.png index fb90c998b6d38f47493b491b2bb36820f212036e..6e329c37f8d46ebda357ab17f628f4f80676a87b 100644 GIT binary patch delta 21349 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 delta 20932 zcmaL930zX?_dkAJN^K*v$;y;=D>GWva-qd?%F3FioUxL2D=ShfK!IyonVC{qS(#$v zl+!pyo1uxIxus@QnpT>isJH{7vU7jWy;k#?|M&I!e?B7#UY`3r=Q-y*=e*DR+!viD zPo*YTW|)T2p3ItVk~nqb2)Gab=UaDU_JfbFxBKrt{c$^zxmAN(oVCvA4=EbD_u-9V;-i{a>p z>osr$n?fNjVh;9(h)&idXW*fq#sehVXh@s(R+pEQnVh!E=Y@G4Sg!-C3EA8Q8O(bOV)%V8@Uo)>s;096Bd6 zF*;FXhfMueR?IejW-HKXVe;BitqU@!Mu8l!8_js5?5DTB}d zP#*;uTNx&BT>qd<4UggJEAyuijp@WvL!hxWFaeLe$4i*_{%QDE9DOH8{zK?0-A%G~ zc4PZ!(M6qS`^}x$N-4}PZmuZ$MDBT!CQH;diTkxQIR9<1l0XB?^UnGyGQ&f$9xQGz zQ>^2&{Ubj5qiU&T`2)TC3RD&b${#mYZ*hCajOwEY0^)&!9$5y|AE?vw$^ZGV58nZ# zF**`mi#|AC;x4d(wLx$x%P42bFLC4}JcvKGFGN5@;soLzk-}b`M1L1Uw-oec3SPl~ zexJ<`QNx(5Y1#ga?Wyel3V1)5i!ExLtUvnTPpEl7n0;*Jq4y?S!UTog0##hp8v1^y zEv_FG+rM|VV7!ij{uLz>h=Xfppdy03vu?oUdHH2|VZh=HbzsS-8x^7>0r7fUaNF0Y z>Y=7XlNUKupl^@>qPB?m%8CEVNlu_?k|LI4%EyJvD3Dl)G!v-km6d{qN`-`|-QOTX zl~VoPh=xVtv{!H@V)R35x+{GK+^f1=e?pQSD9zT?QPt@VoB%qqYKdPQFf1Yg6LG~7}Z^HLAH1@#XO&+xh84xS#!J&DG&sX5=6`Ub!MfDBS zZ9xkrZ)}N<@CQdFu;4M!4+|b%fa;mtNuYIt=#{Pv8=__#u?n@~|Is~FMCoy^B7md( zf{Frm`Qb`!Tju)F$DxXO`#~%^Z4d5{xtOR?O~6bBvk;Bu9Zs_a_|d-+FZAdrdOlf0 zIQQV=VWVw0P`(ibLwbrGPpA{q{Oj;7wD0jo>p;a%foF9F4M{%?CL;;50<-)dPRNY$ z!(7c6=o-lV7s$ni)R6k)yxK0Fiz)(mRJprgp#F!De{8EN0##reV^aw5IB7$YH!m1E z4H{%$8zo;g(M0_khj!GzVmAK>2CK+4rhqf9YCGcOq2J0naA)=pW&6)t>^K!b*a?E} z7I#hc(WU+dj$+84L#RUs*8Jbw?gB@;zrl9Z(52s9f7*~>fgc|R1|nQYlrA}*m^LC9 z7JSZQG$!@U$RNc^rS~_J6}B>YC^iPr_X&4)q-zNM#f}~c9Bm(=QWT1x4S_emJLdtuk3Ku#=A9=tPmGM^uPf8a(a>Vk*;*A+HLKuLVcf>y5p(*52mU ztLCl}4e$(j`V6V9qk6zUoSe#zff2UpLdNUhkdGr(;uz2C@$sV_R1{bk=DuP@b1SLi zCt8EZ;5iiQtozky!>G-Gr^8BDc+;V4@a+S$B})|z8^GA!3lnUt3rjmsxcKX)yyenX zb-EhHNE=lj-MlitNkkMSCYC4j-v=ul;l8qeb~xS4{HgNerPiY*3onl|`s=fY<&iwC>JoeHb{%(>IErv^q#u5O`_&1S~Zs%<}mQ7Ox~YCOwr|6=kZ6fsQu|w^z+7k z=f=Af8kZs=zTz@;T*_SNy2C)Uq>zR zrycyU4s?wT6cGd6J!A$5a|dU$mD}h02SazQR<6h;J)ps9mWq}4#LP=mORw6NNR65$ z>Noz>g~-Ri&ijFvg!+CzDMKV>n5f_5b&L3&nSx6e;X)OS%va^{lVyfSvNlhVG@pik z1Yw`m(W~lOeth=hBXjXce)~wxAUFyFk%2&5BwO3TZks`bwdv|yw&r)}L`3Nlb(By? zZ&cVfnnaTH_essfSDCyDC*^Inv4bbm@dyxb=prG7E~Us@}v1}hqL!(JN%Yqv7_tk-YJtx zuMWLToOI#pUi9T-c-6v$QIgl;`G@iy+J#>WT=E-tn zEVPX>SbHK+xr}5JiOF&qNx4kZDEmL3<%%-FLDn~%gJ^k!!TA$Z5y@O;u!BlnrbOK< z)W8sW((6=oS5-u{E6pbGN_zT?|0uza)PTi^wUy@PtK;(Bu-U){;G;z;JK2g+f#YR5 zqpZvAu&F8+%v>02`NnMhFzEc8f;gl*NuDIro#xF!uc?mVO+aoKyM@TzI9mcN z#~&oaY=I$9AX!7y7tzw{BEHs1UIuf_#6`sJBDI#R9*!+#ElGafL*Imx{se+%8q>wa zg^Id0VNZMe#U%K?e@m{R32(5ru+Z_Q5*7Q2Z!7b=EBiRvyB3%ce4O}pyy?Y|H~f!m0R;Ts|Exd$vc7RC$^0cvM> z>1TM|B^du8G!s8m^50a-H;Lr&ys3EP3BJsiU+fFX%h}q8dz7O|$N*4W!3e}bFxVw1 zEu%M-DQ=LAt@^B#4}|`14ozDy(iNIM zLRERpd;B;BXRDxta?7hFTg@6oJ%x1ek<55PFUJ|Da`YQGqY4TOO^`tM`g#ytE!|WT zkSl6xnwFfL+#nk*5|1{a7P(T_paKl7+f7l(22Ak%tMq*Y<2V+xCLQ_&i$qdl#lA%r zdvbR@{cV1Z2#mIK=T6LFI01(tX9@e7=>68l}m_4=|qK%Mncr=Z&c=sl5Iaym^zBw zK$IIAWSFlM0b34Koes3Xl=OaAc%$ZP;|*?j99PUF=>|wb5>i4!Giw9KyOmg=@@R7C zb)W3}&JOS>b-ex9sK{-tITa&#b>8Pl;QFfQ@%FHUeEY2YVP zxdmNrp+L2>LB?eoTysQzhJHWgIY+Onk}_7kuUW7#h;Jc?k!tmOjy1~BLOQE-NKlc2~9&OWj3Tn@Y1Eq?LV*~7Li4w>ytn-H`(`@qrinsLi- ztIoGN@vM*?MCJ3aZvg`Pl9*Wd*$-I+-5ox4A#S|OhFi<`ZunC3da1;1(S7Q}7?r-4 zz;ouPuLV)#J2pSoaH)ADjm5V}%5SZlz3LTbaK{|)Jy6u2Mey~F(~CE5iF|BwILkz? z6dC4uNSeoxbxiop*Cdznjg1`?{vDM*oh-&e#lMjdOJm}$@FLYA;|B7|a~H>2|1siF zl<9cI{H$fAOY7Zt@+y5i6TY18XIK<~*d%Fi@KgTtvU>fOq%Eb(h5{s847Kqfo^ISK zwTFd%Xrf;R+e9JWD!wKrtYZm$dCvI&)5yPW{BCvBeC;lm2M@nq{`H`XtRrtseO9FJ@PVH=mkgjc-Ka;4Iaib?yhbt^G*%)OYPbGj1owf?aeP%rSX~M&C@OEUs zwca+of$VX?;^;OB^V*#3EdgsPf2wx7Qn?JT&$Ss^6CTU)`}F_$M|4gs_{2uu`kvfm zTf8)cxc>Rg`2jO_nB`7+7g{B5`6kf!md5;-!J0a41D1gT?5Kg- zsF0w6z9)RdHJ2$2xWRSr!laN@ijzq5%41XF{2uBWz z+0CS2O@C4gpA_L+@z2x4@xPcJKk@iU*xe*ebW1mjKUvD`Je?y;5?wBWshf=1Uy7LV zz!Ry$h;Nn331r3K(4>dmKr9c&+0KSpFLKpo96!6^4s&kmcy&(v;asFh6n5ek^|E&Z zE#YC;VQKH0ad!xx>KmHdDGuvZ&4hAAoj$~vX=o4{+{lUvWTDW|z*4Tn?tvLB685Vx zx@9zJbHjkbgZqrAJ-RCd|9&9n40L$%k%)-vB~i%^hKVN{1m`kftGQ`iTZqx)7A9)5R5`AjBC8n8)K4XBjCiL~vYSw;XmZ)Q5KJ%@+60-}0bqN~lz@>?#^#h}UqQd} z_xTeb{X3jtj;wEi?6rZ}9>W|TNuecCTF!dui-RgICuxFE-gw%drq=@;ke7P94ETf(RyXU_0qH7>X;_ zXdbe)zXK>xkfh76s^`s;>G-np^YBPp8VCvZxVTJckX3v2BvQNgDH@$xcM6Jz|ef3jNd1V3t8J8+w=nfvCDXIX;%elnS@q6<}0W=xC^h=7>{q8g4C zRhcnBBIi!(U(2qH6R7v2XR1ChwO&epo1r|5S2xjtC3u1q0Ebtf#lIb>BbANpOBQI{ z^{4_uMGO04+3F*_ft`Y3LLr4IRrR@$l{Z1O&3DB0*8p_Jhp4?uSJ=W1D&1c!t$8D2 z5G5y3V{Ii077Uw$(3?<&Gm0t7c#%4bUgN_sB@FIkHO2AU!!-2*Lj*_}_^CTjk&j3_Ts-@|Jiu#o7CIdT>?IbDjO)aP2#nevFpZ zKwX8|?#BNyF#%AYvapB`iK(yr^uhscAa5FHrZ)Ut#g`C3wc zF2rl`<-3sw4*?j)Yj8ht$Oxp&UfZD?=(uoFbo3e~$QGF~-_>*vO~O4nxI{3Vpi&rT zJ;?X`HA=zPO|?0Gtoe({N~^=`4;9_MVg*TFQ+wxU<}(ge7oRkGFzVjFO#QItZhnkX zpmDhy{*~Q)_DeLMjcmj;bSJN*Udiqla;=A+O_B|ski7|WKXWVwsIhA+%tXaoAt?Py z5fue7YNg*S{3?r%`L+rJ>UFLoC(yj>Rl38#&%G+(MIU&)OQM%cG5D36)`x$ijQK!< z%_;@jus$(VdiBh6@9eZV+t}7?x2mR^PM>PC*d%Qk6nf{@pvuIJarCg&gJFps;wy^Ah;oBx!0bTWKfnvz z^n=&)1}?N@vkTy)IslA{-37`BG+l?#x&5;Fu3O;@2gON^cE{VD#lgW9#n5I1BBce%e!*>?VLv zXP2@{RCP*}?;*)1-5&Tv)rc5JQjLL9h1>Lk`zMJ$&{%6|j!mS;>1*-Zg4~QZGu)6Y zxa_$Ar)ts7<84i$2i?^mmiyBgrt@I16NEq!LGFbB5w_ zP{Z&7kg8<%aYDYUfyX<4dWo$9^_vYcL!&I8x~j45c;hwHT3b;oFrogiZTa|(=#ZO0slZ)fn^ zEh8NTRarGD$6vydvWHxcTT4XhlyA|L=u!oI)&@V|_`D-|@FTnz=866qc&+rDM4TjIsY z+LPwZm)>}1kINpnyUc(()foLOEUff5OckC*=We%K|HkjoKpi|LawafSx!Y647+FOu zPQ4{j7^sGkLwLDLP|PT@777oY(u;is-@nhomOj!xVTMdgAyx`X{5|^yXzjI&u$T`3 ztI=Y?Yf<;tvYm!jKlvkA^-RB$@g|X(!qrx?#WB6iDM%gfLneO&27Id;BQ&zX4z^|z zhIZ&+u|*ERXW>U$+p&6EYNkMM<)xe}C<7M8*C}`(Nk((z#t)Q4iY3<=DCj3g^K2Am zYQ~~q!B`Xq_Un5d?Mp}Rj%<|C4g0A{UHD4)1^SJlISV{!ct*@Hv%Ukg|r1F6sXX}y`IVje?v~~n!SIViyF0*SsRMQ4n=k;?A5;ih z(RvGZ#S1cW26HIS08)}iVH8&<<>~$1-(1DN)P?XW2Ux8{40=F|Nz^ogK8he7rg=qB zn>G%lh=xVtbqc%%DCWan@wRO;q*tcSCLzmGjn^}#TSan=cQ{QJz};%vS=u>);{_TJ z0AW=WTt6xd528RFMilPH>wZgRlR+h|ZH-rZG+H1w6DRXqld}ZLu%>5Wl%fzcqp4U=u04x@(cOcI|)tDhB>c=6wnd;s$CA$YJE1~P8F|oZw%Tvvw zE`|s(s2haFDKkR^6snFZMemlYeCw`JVPGaYyonr}Vs8jba$a)anUQyg~Ive&i}-(jXC>d7+pIjV0bG2D&MP_Pr*U)z!l z=9dfwiYU^XeCZ}CfK|g0{BB?Vb+{a)%b>VPER`XJc=<}sz#UG>F&D{N#Y>KI1zpO8 zEeMxL`dqg335ziwz+TEcL6JYb)xU2sOi+G+x_f#Q;T&B!>ZXtkfGdT{v=Ar9Kc{ol5@aY!&Mq`hLH5f-!DPc^pk@p~#@w&`GE|A4c_TXH0g#{1M4T)u4 zEAh33v526MJqb~`xq9?og{CYF71%kbettQ5O4ek*Jj3+sVk@|R=Rac>EXp=5@D;o- zqNZV91XIK6|5Gy_GDv!724gY|k<{Zz1%i^c(&3e@*DNYFmWCW~Nmk&S(9(d0)juGT zkEWL-!OO`i7jh*E_#ne?ASMp|?i^_O)4R1Bt%5C}S*DTo%NY8yup^WtU5Z=CH7>1- z+lC%s#JCDL67$HSqdHf7>G|kcs-3PTRx5qOM7yOBoFlJ;p+M7>lRxb_dOn7!j|b7O z=DJ7{6gb$U7Gmz~e(ZwuaI7m4D`B=u*u1pXTUZc21l8)P$x zZRxp&!TKjv_57;(lPJc=#!8|ojhzHI3eME-XYIM;odqAdW48=P@2 zDXgq((cQdw73`*%;n7_xx$E_0Q=Pw-zvYtpT#R6tJ7JM@tzrp5cSi58t?|<>4b;yH zyh~w7DNRT+Tc=@5W_Wd`fBO7+@5JGJox3102?%9RSXd&OZy@uRX021oR1Y>ZXtdqmC7cv}#x^zH&SPWTFVLZ!h`6%k0!`0q9alDyaWf6*PZvp_exBGsu3E%w8y#rYC|-t! zS72b+d>*oy%xr7Y>py3l6p+;~WuTP+rJ)aZ-exm8G>oZg#Xo}hahr*wRZ@{@CSRLg5%B1 z&)4qGh5~#8f}h_!Fk9HekMnC9l<5|JyEEx*1)O$d;^87_hHRDu)SFbW+M*5KEDE9~ls* z*t%T26l4=+7<~6A`~@Jef#f3y8i5s#bjhq z_9Q#os-U!VI9nZyFEY!ocF(uqX#eKC@nO`&fH;U=rV`gYOr%%4GDZs&c7hUDri8mF z8DNR^{2sec4GrevN`7}Hh@kOmKuUZW6&$>V@5 zjhclVM$tv9NKiZ%NI+hjoU16cgL0H_^VAg_{kR85n$x{HC7>2-I0KC$ zn`~Ir;vyPH748awkj_yK(4&tY?WaGHx_B_3RWoRGz{0-K-k0AM)= z^9}RnA*)>S5<)fx%--e;mEJrxYhwL~r9tS%OP+4`zI=kS>Fi;wD)$21~nbBc7B&pm3$h_uvY(|M*GDV0}i;$tF`rztk2cAmNeB3OrQ} zW$yXa^@;=;tUl8q129ZJh?zC?6MW6=z+Z2d`x#q=AS_XTh0tBKL$mu*6bUzz|3p%p z=Jj^*CjfJj4KDz-f3_0j>ZS3njRhrfc|2(Zp9sq201RN%l!2ey?At~hcm}GcFd;eF?!as|q9MI90B#;XK8f); zsdW+o0pxJPoBJg ziO(9z$y;u_@Q;r^cAuGfbJyf`d`Y$-sX7Qg<92#qbV*y(BPVYw=nwN*=8>U)-v6Cd zespPO;l{*VMP1+}=^%Cx`{+=l9)pQd>$ec2kVCF023D8#wULdpQOtHaur0xB0G7)Z zj+!CRR|-l2c1r)-nVCmTYVz4^7||LBH5`!LAk?qM{lG9OT*{x!8hu5gQPL zF)?VkJ&q56ssAh7B!CHaw;I(7eW|bKWu0?IsbNf*`JT^{iH6z4SF!u;jyccUH0;jY zS&@IVc zP{ovSmG~yiyuVp@j;P92R17f1WDo_R*y!1B-;}}>W<;+FMV}yEv9HHXsTAzd67=Xa z7Fp{p>bqAs=t9`9LXYnHZP`tm`HpU`Z-0MLy5vGBi{FUblJ~0ikHuY4e5W_svsUh%Za`bBdrh(0#w~+X^cb8W=<$rLJ z>tF%mLk9(h(WGQtQhc@ z9C@fm_g-8R7uKm@bpeh}0^qeO0#r>bm>o&Xc!9A?FiZ?8M$bB4rY6yDCz*-?hL2M} zCFtfsOcezg!tF)Pi&(U!AUzYk`VO;V?nnhAZvQzHup`1#q%_dBqQ-#=&f{He?QGHD zaS@F99>q!$IBzOQ`Vx{7EvtM-VA1kIGZS#B31t8i_eV(@=sMB#>ntD~5Zg2w)IgXL zS0=z%0X*x0o&P66;K^$&V|sAZn`OmG`3;rNF2#m9YbyPXJ2nq`LUzwq4;247V&&XF zmciQ^4j0sXVog3U({%_Gv)>5v~x_CNVptz@;lk12BqV z4gmo;qXm>#dHk-3u;$_r2q5HdF{|5(A5cIw0h%Xxz>h_1y#Y?dfo;S$aYsRE4?T68 z&hoXHg6k+AyeB)rOg;#c5tjxTh|0F92g%3@bWNs_Jw3+(V8aKF_dVXQ7ordN!)6dL za*kO6$?#Dm2X!|Z9n^7#V<+xJG}~c!GdTHIp$&&` zKRSU6!Ay zTQG)KZ@}BIPHLJkomwV&Qsj zg@A*FMQli18mO`(`|z6W-1plTZ9cSY_O{iP=Z@^VHMz*`X~3pYUEcS%m`?Y7!(w*$ zKK^`KPwGb%cMJ|kyYC-9Y-lDJPZo*iD{bE@bTDP5-SB`rd++{+o8c2X*@;6)G+5Q?Q>?KCclXAkU!;b#=BhA93Jp5}d0 zaB=EPhp^CO0&^f~2vYqUd4guK@IBZKj%8`81klvg*Dayxrjb`Jj=cxooHH+A@f1$q zns1OfhXdl<1O+ND;|@L|W3M|m$GU+q-O?)3(t5;n^OZkC*DW`gt8^9q5g~8qAJS8( z@DKL>*2a$AqVp`nU#zwpfgLxnoJC8zC>9jh89$NxqFE6ub~|6UoE~*C?dEFdRpT}*dU$@i-%(eEu7!dVnf>(#1gHVUO6`lMT2Uv^Rbd04bG&Tr_z*_ueG4VY* zyGFGmGw#uZ4KU!-I-d`S0{Kx!DM zrlu!vRvvO?4)bgwVz`ig$m?>75O2xOfptL%(xHofWabRE~}+_`*VpSxN;6&^-p9u!f1t z{g{gZ7nM+kL&Uhgi$26lAya65HmN_?oovzYLBiCbTbqsLXLRN~cSqmE?*n4{f^ z-(5+~<1*Z#M#PL5NnvJC+G60A7|no4J-S!bBhnt{8N2cwkO1)Q-`UFL`pSrzJ#y`%_FG-<%U32c%gW(1Fs+4E~vT<|DibDMhLet?zQmvnU z19Zvz9Ap`L1)5{6?`0%WQ-TwoEb7v5`hOt|{6cTbfLEaO$&m#t<0qD4JISye^3YiM zwSbk67YY;Ea@hOjBgrt$C4z2oWAAZMf{xMPNH>MZsuyI70<<(CM;A-iahZ0I3^|L( zKEv9U1hpV|F2Wh#;rc8Dx`+mR53Hu|LbBr$Z=i)V+O@`=mUYoEsbC z)w0UlJm~G+<}bmU!z82YLYmc!dU;(AseLs&e-Cu?^#@8kc~yLx)A?~grNM9FxYU!5 z$Vb5D^O5rb*P=mYFKV*S(WORE(|kO%TQ5sq$HC1%wmp^2(w*}YJ2LwmA>e|C2*51F zk_=+n(irCJn3JIV7A8@$cs6d-B^d`ImJ0pZ1e3g9H-PmHHDf z44DHk^G2emjIU*eXa_X|CF zvHdRg3^Daf>(Isd%U6v{0Ar*3{X!4n&$1GX!lX9^kcrV>3ErdtVea= zE(F5^9XHK-9Fz@+wI*Z7A(OC@UzGj>0a=U^Xy1SX zpQP}TAxsahBe5ygqxn5+-xQxz{W-@Er|k)^{pp{ROynT|On`V_>-qM0l@+_dPv7Dv z{~IvH^+D=jueE zmQg&^QbPsTeEeHuXS{IG#U&b5$L%s>R`Y+4mixV zY*`IXZFM;pJ`Vau4tkzkLt5^-c~sle&->mQmxc%e=DCVa+FS2KYo;*W;dfAmjxO-GP+g_MKrj3efYF>a1(Qu zw>Pw9Ce+xG!A!!_lIvRh13Oo}6Xr-BMJ&%<9whm+$k^XIl3rTf+dOvShd11yyPh!U zk$RuZoBk}tKCp*tycs4XoNQ`dz!j7w_iZN1E5UiY+Z?i9W&JH8szbYskTH059_(Xf z0yquhV}X)F(-bB!TbX*r#=G@wt;D?O4$%{SZQBrzlTObe5jWE%@s8A~kK)oYu z5g9Oo-IoXZg1rQM(h1|HnaF=h_9VbZlaUixg9%D=-(5EpXuzWi1>5{bTCegSvGxzA zRnDt^KIiQ}0(h9#$FpOWE&r!{?X#PBz|O*ciFfkkJF~+JjWxf?@Q*zx z2|ii=^OKxDJh-{q``wK+%hi9Z8#@k~6;;NWjM$)O*q=WH`A47Z*O}IrL<%^L@ePbRopPRr(@fApq}Tv zW77`)GJOsZ3bs9uw8FKmqK7x3sWUg2L)V}=q9^ zXwp2)er)njnN_6A<%Wp8tk#9^Pur_f-TmUBG;gr28|I!%`x#?B7|7eC_7G@`%l-H- zN)My`)^=Molo7GO-^GiW;5J|xhdu;+c={v&H)V=_2=%E&TJ5W)%Z@s4+-A0CW7txc zUKK7creVoOaDa7ea|B2K_}H;YKVc4dDBd+zZ`Dx#z7N!Dy7$!_Qao6Nm$8z6LA#y3 zb}ha7Oe+Ov=d;Z$@}UV_P?IA%x?#+$F{}HXHR;hm5uZ(YnB8|oph?081(AiNm6fUW zP&f?7gFfykwEGn_ z0R>4F?qv*m)yDYz^HaCq4EQ;>#pgnc(oa5rjW2Zb$eHTyP4Qi>u7Ja1*coVs?xgj& zaptB|&4EY(Q|%C114GNY0Bm<>4ElQA5+b^K7znP)mPKrE|-7-lPC{7ag zygypT8f8_mq}FCh;g`oJMn`5h6+B3CQ=BJlLXW#~rc=jGyEqnF3w#>Xu=IQD85>Yr zA_Jm;++tC02Q`H6W$Sv~EeaSUqx}@!byh*1ttK));dC&VuL(Ty*p4I64i|_#5KSyu zMo|3?{XEt(a;*2o=_XrdI{bCvTkV2qk8(RG+CIm|VJoe`pP<##fsxvxqBHj2a41}w zFy+%fAO1Nu#u_plD~&PsECD(@Ep^sv;D)A$2qrf(w>M{>Ii&Xi9As)lD*GF72Lt2| zO{}*8`W4_nl%pVq0%ddRgHh1Q6OSnHCBgZ%!E)Kad6N1d?`;=vHVRV}4;6qwL#jz* z^937yMSc>h1|THASb5YOtpiV2bi&4^s~0vzIQpqO@b~J!w3UbqW)H1@9(!?Y(ps>< zlZsS0Pi-J;LrV?54V1z8cpwD78$e;jA7896&cM=q!fU`_vJGi2US!N?s$<~Gwbv*S zTuSptn!zYi9vK(;$Xqot_6kV8IKZ^QCL9Zdmk?Cb@P0o7 zag0s+stJM%NXB+bHT*Q>2$>a^m*nQ=_Gk8m@!l7Ov}biKN~S{fmo>=GYSJAF;Rk@E zYdvJcIKWMK9VeSlZEm`QZL!HpU|^P)u-tC!+249(eRd>+=AQ+-#UC0S{Ait7Q?hpS zXPb@%U6I)n9_6=P4xm@jGEJr;@cR`2MDmTxZ@Z(_>H-k zU~J|<)J$%87)oiiizMov3B)LR3Q^DdQ z?Pk@5kM;tPae~m;?FZ_m&HGIzmR;onwr4X85O4b-!yeG!x;Sy~l)1pQPFG8ahG63o%uI0osH}KX zF#@RpkwlkiCR1ZijT_-G z=lJSBHpP!xl)cV-Ww6IPA9}Hmf>;ub*H3Mfk0#+FgE{#Zx*p}-MCO4Ulu!=9QIYZm zS$7ixPw2?^8gjz10F~u^T(%QFHE#QKb1qUUoMCm|GWNMu?3FE+P(5#|bK<~4Py(9- zT69}4eGDx*n!7K1m%Jx< zO#MXgs1QOC`290z9s>-V^Q2O|;XV7?V$XpN;hnqTXC;+AZ#p)dRD5s{Iv)q!Kr6=) zE*`%Sa$us*j-rC26Mq|Rmbq6vST6%`N^`n~4JbQJ#{rv3gLMQjfw{48+BB9JIH@{y z5)W{<&F-6H*fdUGz>kgr5%1pn`pAhbW*F#`CU zitvfAH{P9nyw`sNG}UVTxhUP-b2E>HH8s!b_8tKMe*FTZddNTP3uVIO{Lgk_0-QP$ zCjrpWPgFz&la0^vQU8rq7tH?sb;xU*Mj@tt^yX^y2biE40Tc=t@@D1A4)c}M0G}%> zewcIO!%YpeI>s&!K_%ji!P}s4$U+sE24Uc*^lgd+69q>;kJGmS`^*n8+|+0h2LohX z8P%>sVFS?$>rX#bW=}yc9^r9iHHabat(=y+Gawi|CWUE%*y)Wj#F`b+ATh~ly_rk{ zII@}1i2;b?j;aWjifTI{ZrG6Ktj7SkbS^EA+eR?z{jQov&RlI$urq(4UcQ~AS%&#( zv?o51dFuFhLnaaV*0uGrlhk!E&{zT`N`u!vd$+G{__N1*7Mpo%{b3_+*8q=is6oCIDL^+=%{* zY(>AfA%)UF1~);!yF+TP!Uku7!I4GaA|{Av(J#E1vqF|5dOkU~6CO1W+bTdg8X6Kz z8i;H_k51g^vkC}nCec_1)~3Uj^0M>u_i>O#=na7s|7W5T3PDdeSlEw?!ElB|O0ZMn zmJL&3+xA2+amI2+&uq3_LoOKEw^s%p8&nsQKaQiGj6;cE;V%H*j&HSqKDQGYAC(#S*G_im*)WxZT(4KF^gp5V9tj#(wF%hygIUi|xfj$*(svEOBfw<- zAQ)>%tr|@hDSR9(Ll$wchmQQALs{_5_82B;2@|G;ejGXQfUMf*(X(Eveu!7wHMV^X zyrg4%u+T3hYtIl$(@FXj#$JM~g$ZjTgrKFqDYknG+w6)9Ub~*N{+wDNGdLN=uBjC> z9KuFh=z<%&iUMy3lRtr`rH=L3WC?>G>fmRAe!TZPi5JTFH3Rw{QbReH{#mBnM__om zc=VEc+w7R?6lh{?Jjd7|IuIN&ynv`5_zLlgA_Sv2hEf)I$W5y-=TwMQ!O>-X&4dUu zvic^=M2yPx_hV;vg?)9QG`^^`rAu}KodyptK>ZyXuohZDK@I|CX&AV+b>4DN?yy2D zU2{OiTlBg*br5uj2JiHNp>ZEPjKdblKcRM)!kCh|(+ zfSXrWrs#U`qxuKge{LEseotUJvj;wsE0)zA-(RGn8}Ohxx<8NpDT6mVX~6x4}w3{*Gt!Ufo5?LN)Z@}+4LGVG7F&6q}QPP z#})w80}po%$X1{HC^-D&v*Hp*v4`JZ%^V#mFjm*oZq(5%lj}Wk{m+Pc?tGUO3wH17 zs~6~JGIdGp;;&qpVv%gX2D-cAS$Ps20E_6Kw7=i0g~TuIDC!27rCEz!={PZY9T#c@+x;tuWB+`zOa{@>uI(J+_(cj80OJg!fEBgn)UiY0x?#E#Alq$AUhzy)iCeSmq9jwuj!qN2rCGx-8pUjjr2)vBp>b|c{hfxOp0 zdY?Qbleo$;GI?)Gqa$Ws>)^)_hD*>L8}3k~R>Sm1CN zG^~MyLS-UuB^eKD{t;?_g+S*%=_bk<0X}Z*uaCm7Vh#mA_?GypntdvjXiV9uxkio% zPG!T)9kd=-=1gH8{^b)7OsgjYA50-q~0RDIRI<08vZJp_4~A&6Q>Vfdi^E+A0{6kfEKsX^x4XzFE@ z5HH!bph1EfIJpUpQij(>k}g{WiO~vcZl~a*@m^(mUd-y5giOGO zcGb(>6?e$$lU}O*@Kqh72q%DTu)o*|diHBB5VX4?eupp2@@HnnVD>@>m)LL=!*Nn( zTztZ|AQxJUiaDvVDW7zKWqeb&wt4L!YF6|rRlXT6{L^|=FXO?^i<8)L{%smsC55^Es4c2fw{^XrrTmCN%?&nl zN>R9}82r8*9=zgfo7B*ECGoCDzEuH3)g31C)J^HmqN&q`C-p6+kpiSLk6OH62%QwB zM4)m%uNz%dY;3$E&?dT5yM0N*Cy8Obc|rI{A##B$W-+@uPAEYp!sn3t^t56Y)9tFR9iU}BbB#FiU;%_Tm1wW)gr5c{ehh; z8pY0dvjRV)KqOZS@?)4gmeazch3ZSL!?D8!Q>MfW*Yb^Ct#KmDNLPl=R+33naj8#| z_^EZ_5+8XpAkg$|7atcH?z_j^m+Z&mZ&IDLIH6e}M diff --git a/test_cases/messages/messages_with_material_by_wgpu.png b/test_cases/messages/messages_with_material_by_wgpu.png index 18fa093dfdead869c172a9fb9ab345e9511f40f2..d5d9a660cc48a9e554c59620168d163d9e8d88fa 100644 GIT binary patch delta 15037 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 delta 14232 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%0D7n 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

-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 AC;$Ke literal 0 HcmV?d00001 diff --git a/test_cases/ribir_gpu/gpu_backend/tests/transform_img_brush_wgpu.png b/test_cases/ribir_gpu/gpu_backend/tests/transform_img_brush_wgpu.png index bfd516ffd2de60e8751fb234781900501b8ec1fe..a86f6bdc7c27a0a1472cbb3b3e584bea21ecce0f 100644 GIT binary patch delta 6396 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 diff --git a/test_cases/ribir_widgets/checkbox/tests/checked_with_default_by_wgpu.png b/test_cases/ribir_widgets/checkbox/tests/checked_with_default_by_wgpu.png index 96269f69d97f1e686435b79260ae087f27b8fa7b..a7b3d041a985ca2576a39f501a421b6be4b3aae0 100644 GIT binary patch delta 378 zcmaFIJcV_FG80quMAeP;jPJky`x9MzyS&Dl;d0iK{Svdn7FRB_dOssf`F~jHJw}7I zZvVOif9`KQ^`DpJzu*0DviHyZXJGly2WGX`+-Uz`&oH%qasKbV{O8VgZ=8QLe6Ozm z$F5MJxbLm?zPZnz-`@B5_Rk6YzXj|b{Jl3n|5sc7qk0A{{Uac~4D}yC4!H9kn<5UN zBKAG^e}7h#|E9=LbKv)0dxWJRZ8ew8YlQzd2UIHVdnvt-vw{ET27bl|a7TayJO3xH z_`{8me#m_9{okL<@_(rPV_)=1>4y)9$pBHg@WK|Uv&L5|k8hFsxqa1VzJ^TGPw_oK ze}~LFy}kDM_RsqTpn>zF9}+B;4g3}Rzdx_nG+FERdB6PR4U8I-_cBTYv8+f=d#Wzp$Pzqzs@WG delta 203 zcmbQj`i^;mG85z0iK-jx`$Z-zFeQjQJFdODoo&Sz1|aZs^>bP0l+XkK DL{VZq diff --git a/test_cases/ribir_widgets/checkbox/tests/indeterminate_with_default_by_wgpu.png b/test_cases/ribir_widgets/checkbox/tests/indeterminate_with_default_by_wgpu.png index 8f70df7772b41f07df6a80ff923ca4391d5c5022..cbf092282eb5942acec645dbe5678f3e2d60c46f 100644 GIT binary patch delta 226 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 Cc~xKl literal 34428 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 diff --git a/test_cases/storybook/storybook_with_material_by_wgpu.png b/test_cases/storybook/storybook_with_material_by_wgpu.png index 236373d4fb634cf20be6f439d393127bf372e31a..98c52840b4beb35703e74f89127eeed37f50259b 100644 GIT binary patch delta 13610 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 delta 13254 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 diff --git a/tests/assets/fill_with_gradient.svg b/tests/assets/fill_with_gradient.svg new file mode 100644 index 000000000..7723165eb --- /dev/null +++ b/tests/assets/fill_with_gradient.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/include_svg_test.rs b/tests/include_svg_test.rs index e63a91416..35eb415c8 100644 --- a/tests/include_svg_test.rs +++ b/tests/include_svg_test.rs @@ -3,5 +3,5 @@ use ribir::prelude::{include_svg, Svg}; #[test] fn include_svg() { let svg: Svg = include_svg!("./assets/test1.svg"); - assert_eq!(svg.paths.len(), 2); + assert_eq!(svg.paint_commands.len(), 2); } From 2108ba86cb64f1d7fd96ec6e4a2c0204716efecd Mon Sep 17 00:00:00 2001 From: Adoo Date: Wed, 13 Sep 2023 09:55:00 +0800 Subject: [PATCH 4/7] =?UTF-8?q?fix(gpu):=20=F0=9F=90=9B=20use=20`textureSa?= =?UTF-8?q?mpleLevel`=20to=20avoid=20unroll=20the=20loop=20in=20shader?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gpu/Cargo.toml | 2 +- gpu/src/wgpu_impl/shaders/color_triangles.wgsl | 3 +-- gpu/src/wgpu_impl/shaders/img_triangles.wgsl | 2 +- gpu/src/wgpu_impl/shaders/linear_gradient_triangles.wgsl | 2 +- gpu/src/wgpu_impl/shaders/radial_gradient_triangles.wgsl | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/gpu/Cargo.toml b/gpu/Cargo.toml index c4eff7bce..876b57153 100644 --- a/gpu/Cargo.toml +++ b/gpu/Cargo.toml @@ -23,7 +23,7 @@ ribir_geom = {path = "../geom", version = "0.0.1-alpha.4" } ribir_painter = {path = "../painter", features = ["tessellation"], version = "0.0.1-alpha.4" } slab = "0.4.8" wgpu = {workspace = true, optional = true} -zerocopy.workspace = true +zerocopy = {workspace=true, features = ["derive"]} [dev-dependencies] paste.workspace = true diff --git a/gpu/src/wgpu_impl/shaders/color_triangles.wgsl b/gpu/src/wgpu_impl/shaders/color_triangles.wgsl index 128b916c2..b78b3f77c 100644 --- a/gpu/src/wgpu_impl/shaders/color_triangles.wgsl +++ b/gpu/src/wgpu_impl/shaders/color_triangles.wgsl @@ -11,7 +11,6 @@ struct FragInput { } - @vertex fn vs_main(v: Vertex) -> FragInput { var input: FragInput; @@ -63,7 +62,7 @@ fn fs_main(input: FragInput) -> @location(0) vec4 { let tex_size = textureDimensions(texture); mask_pos = mask_pos / vec2(f32(tex_size.x), f32(tex_size.y)); - let alpha = textureSample(texture, s_sampler, mask_pos).r; + let alpha = textureSampleLevel(texture, s_sampler, mask_pos, 0.).r; if alpha == 0. { color.a = 0.; break; diff --git a/gpu/src/wgpu_impl/shaders/img_triangles.wgsl b/gpu/src/wgpu_impl/shaders/img_triangles.wgsl index 367e95e44..72f9b7160 100644 --- a/gpu/src/wgpu_impl/shaders/img_triangles.wgsl +++ b/gpu/src/wgpu_impl/shaders/img_triangles.wgsl @@ -88,7 +88,7 @@ fn fs_main(f: VertexOutput) -> @location(0) vec4 { let mask_sampler = samplers[mask_tex_idx]; let mask_tex_size = textureDimensions(mask_tex); mask_pos = mask_pos / vec2(f32(mask_tex_size.x), f32(mask_tex_size.y)); - let alpha = textureSample(mask_tex, mask_sampler, mask_pos).r; + let alpha = textureSampleLevel(mask_tex, mask_sampler, mask_pos, 0.).r; if alpha == 0. { color.a = 0.; break; diff --git a/gpu/src/wgpu_impl/shaders/linear_gradient_triangles.wgsl b/gpu/src/wgpu_impl/shaders/linear_gradient_triangles.wgsl index 1d2040327..aff24c66e 100644 --- a/gpu/src/wgpu_impl/shaders/linear_gradient_triangles.wgsl +++ b/gpu/src/wgpu_impl/shaders/linear_gradient_triangles.wgsl @@ -80,7 +80,7 @@ fn calc_mask_alpha(pos: vec2, mask_idx: i32) -> f32 { let tex_size = textureDimensions(texture); mask_pos = mask_pos / vec2(f32(tex_size.x), f32(tex_size.y)); - let a = textureSample(texture, s_sampler, mask_pos).r; + let a = textureSampleLevel(texture, s_sampler, mask_pos, 0.).r; alpha = alpha * a; if alpha == 0. { break; diff --git a/gpu/src/wgpu_impl/shaders/radial_gradient_triangles.wgsl b/gpu/src/wgpu_impl/shaders/radial_gradient_triangles.wgsl index 874f47ed7..cb1e82578 100644 --- a/gpu/src/wgpu_impl/shaders/radial_gradient_triangles.wgsl +++ b/gpu/src/wgpu_impl/shaders/radial_gradient_triangles.wgsl @@ -83,7 +83,7 @@ fn calc_mask_alpha(pos: vec2, mask_idx: i32) -> f32 { let tex_size = textureDimensions(texture); mask_pos = mask_pos / vec2(f32(tex_size.x), f32(tex_size.y)); - let a = textureSample(texture, s_sampler, mask_pos).r; + let a = textureSampleLevel(texture, s_sampler, mask_pos, 0.).r; alpha = alpha * a; if alpha == 0. { break; From 979ea2a97f8dc4541d51ba535eddec858b1f9d4f Mon Sep 17 00:00:00 2001 From: wjian23 Date: Tue, 26 Sep 2023 10:36:58 +0800 Subject: [PATCH 5/7] =?UTF-8?q?feat(text):=20=F0=9F=8E=B8=20svg=20emoji?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 1 + painter/src/svg.rs | 16 +-- text/Cargo.toml | 3 + text/src/font_db.rs | 87 +++++++++---- text/src/lib.rs | 1 + text/src/svg_font_document.rs | 231 ++++++++++++++++++++++++++++++++++ text/src/text_render.rs | 20 +-- 7 files changed, 323 insertions(+), 36 deletions(-) create mode 100644 text/src/svg_font_document.rs diff --git a/Cargo.toml b/Cargo.toml index 89e0ba599..3bfe2f466 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -87,6 +87,7 @@ webbrowser = "0.8.8" wgpu = {version = "0.16.0"} winit = {version = "0.28.5", default-features = false, features = ["x11", "wayland", "wayland-dlopen"]} zerocopy = "0.7.3" +quick-xml = "0.30.0" [workspace.metadata.release] shared-version = true diff --git a/painter/src/svg.rs b/painter/src/svg.rs index 676c5438b..439f8e2c5 100644 --- a/painter/src/svg.rs +++ b/painter/src/svg.rs @@ -54,9 +54,10 @@ impl Svg { if let Some(ref fill) = p.fill { let (brush, transform) = brush_from_usvg_paint(&fill.paint, fill.opacity, &size); let mut painter = painter.save_guard(); - painter.set_brush(brush.clone()); - painter.apply_transform(&transform); - painter.fill_path(path.clone().transform(&transform.inverse().unwrap())); //&o_ts.then(&n_ts.inverse().unwrap()))); + painter + .set_brush(brush.clone()) + .apply_transform(&transform) + .fill_path(path.clone().transform(&transform.inverse().unwrap())); //&o_ts.then(&n_ts.inverse().unwrap()))); } if let Some(ref stroke) = p.stroke { @@ -79,10 +80,11 @@ impl Svg { let (brush, transform) = brush_from_usvg_paint(&stroke.paint, stroke.opacity, &size); let mut painter = painter.save_guard(); - painter.set_brush(brush.clone()); - painter.apply_transform(&transform); - painter.set_strokes(options); - painter.stroke_path(path.transform(&transform.inverse().unwrap())); + painter + .set_brush(brush.clone()) + .apply_transform(&transform) + .set_strokes(options) + .stroke_path(path.transform(&transform.inverse().unwrap())); }; } NodeKind::Image(_) => { diff --git a/text/Cargo.toml b/text/Cargo.toml index 31023eda8..14b9698d2 100644 --- a/text/Cargo.toml +++ b/text/Cargo.toml @@ -27,6 +27,9 @@ rustybuzz.workspace = true unicode-bidi.workspace = true unicode-script.workspace = true unicode-segmentation.workspace = true +quick-xml.workspace = true +ahash.workspace = true + [features] default = ["raster_png_font"] diff --git a/text/src/font_db.rs b/text/src/font_db.rs index 4937437d1..1c82e48cc 100644 --- a/text/src/font_db.rs +++ b/text/src/font_db.rs @@ -1,10 +1,14 @@ use fontdb::{Database, Query}; pub use fontdb::{FaceInfo, Family, ID}; use lyon_path::math::Point; +use ribir_algo::ShareResource; use ribir_painter::{PixelImage, Svg}; use rustybuzz::ttf_parser::{GlyphId, OutlineBuilder}; +use std::cell::RefCell; +use std::rc::Rc; use std::{collections::HashMap, ops::Deref, sync::Arc}; +use crate::svg_font_document::SvgDocument; use crate::{FontFace, FontFamily}; /// A wrapper of fontdb and cache font data. pub struct FontDB { @@ -13,12 +17,18 @@ pub struct FontDB { cache: HashMap>, } +type FontGlyphCache = Rc>>>; #[derive(Clone)] pub struct Face { pub face_id: ID, pub source_data: Arc + Sync + Send>, pub face_data_index: u32, pub rb_face: rustybuzz::Face<'static>, + #[cfg(feature = "raster_png_font")] + raster_image_glyphs: FontGlyphCache>, + outline_glyphs: FontGlyphCache, + svg_glyphs: FontGlyphCache, + svg_docs: FontGlyphCache<*const u8, SvgDocument>, } impl FontDB { @@ -263,6 +273,11 @@ impl Face { face_data_index: face_index, rb_face, face_id, + outline_glyphs: <_>::default(), + #[cfg(feature = "raster_png_font")] + raster_image_glyphs: <_>::default(), + svg_glyphs: <_>::default(), + svg_docs: <_>::default(), }) } @@ -273,35 +288,65 @@ impl Face { // todo: should return its tight bounds pub fn outline_glyph(&self, glyph_id: GlyphId) -> Option { - let mut builder = GlyphOutlineBuilder::default(); - let rect = self - .rb_face - .outline_glyph(glyph_id, &mut builder as &mut dyn OutlineBuilder); - rect.map(move |_| builder.into_path()) + self + .outline_glyphs + .borrow_mut() + .entry(glyph_id) + .or_insert_with(|| { + let mut builder = GlyphOutlineBuilder::default(); + let rect = self + .rb_face + .outline_glyph(glyph_id, &mut builder as &mut dyn OutlineBuilder); + rect.map(move |_| builder.into_path()) + }) + .as_ref() + .cloned() } #[cfg(feature = "raster_png_font")] - pub fn glyph_raster_image(&self, glyph_id: GlyphId, pixels_per_em: u16) -> Option { + pub fn glyph_raster_image( + &self, + glyph_id: GlyphId, + pixels_per_em: u16, + ) -> Option> { use rustybuzz::ttf_parser::RasterImageFormat; self - .rb_face - .glyph_raster_image(glyph_id, pixels_per_em) - .and_then(|img| { - if img.format == RasterImageFormat::PNG { - Some(PixelImage::from_png(img.data)) - } else { - None - } + .raster_image_glyphs + .borrow_mut() + .entry(glyph_id) + .or_insert_with(|| { + self + .rb_face + .glyph_raster_image(glyph_id, pixels_per_em) + .and_then(|img| { + if img.format == RasterImageFormat::PNG { + Some(ShareResource::new(PixelImage::from_png(img.data))) + } else { + None + } + }) }) + .clone() } - pub fn glyph_svg_image(&self, _: GlyphId) -> Option { - None - // todo: need to extract glyph svg image, but the svg parse cost too long. - // self - // .rb_face - // .glyph_svg_image(glyph_id) - // .and_then(|data| Svg::parse_from_bytes(data).ok()) + pub fn glyph_svg_image(&self, glyph_id: GlyphId) -> Option { + self + .svg_glyphs + .borrow_mut() + .entry(glyph_id) + .or_insert_with(|| { + self.rb_face.glyph_svg_image(glyph_id).and_then(|data| { + self + .svg_docs + .borrow_mut() + .entry(&data[0] as *const u8) + .or_insert_with(|| SvgDocument::parse(unsafe { std::str::from_utf8_unchecked(data) })) + .as_ref() + .and_then(|doc| doc.glyph_svg(glyph_id, self)) + .and_then(|content| Svg::parse_from_bytes(content.as_bytes()).ok()) + }) + }) + .clone() } #[inline] diff --git a/text/src/lib.rs b/text/src/lib.rs index 7837963d6..ad8622143 100644 --- a/text/src/lib.rs +++ b/text/src/lib.rs @@ -21,6 +21,7 @@ mod typography_store; pub use typography_store::{TypographyStore, VisualGlyphs}; mod text_render; pub use text_render::{draw_glyphs, draw_glyphs_in_rect, TextStyle}; +mod svg_font_document; mod text_writer; pub use text_writer::{ diff --git a/text/src/svg_font_document.rs b/text/src/svg_font_document.rs new file mode 100644 index 000000000..b78929adc --- /dev/null +++ b/text/src/svg_font_document.rs @@ -0,0 +1,231 @@ +use log::warn; +use quick_xml::events::attributes::Attribute; +use quick_xml::events::{BytesStart, Event}; +use quick_xml::name::QName; +use quick_xml::reader::Reader; +use rustybuzz::ttf_parser::GlyphId; + +use ahash::{HashMap, HashSet}; +use std::borrow::Cow; + +use std::io::prelude::*; + +use crate::font_db::Face; + +pub(crate) struct SvgDocument { + elems: HashMap, +} + +impl SvgDocument { + pub(crate) fn parse(content: &str) -> Option { + let mut reader = Reader::from_str(content); + let mut buf = Vec::new(); + let mut doc = Self { elems: HashMap::default() }; + loop { + match reader.read_event_into(&mut buf) { + Ok(ref e @ Event::Start(ref tag)) | Ok(ref e @ Event::Empty(ref tag)) => { + if tag.name() != QName(b"defs") { + let has_child = matches!(e, Event::Start(_)); + doc.collect_named_obj(&mut reader, content, tag, has_child); + } + } + Ok(Event::Eof) => break, // exits the loop when reaching end of file + Err(e) => { + warn!("Error at position {}: {:?}", reader.buffer_position(), e); + return None; + } + + _ => (), // There are several other `Event`s we do not consider here + } + } + Some(doc) + } + + pub fn glyph_svg(&self, glyph: GlyphId, face: &Face) -> Option { + let key = format!("glyph{}", glyph.0); + if !self.elems.contains_key(&key) { + return None; + } + + let mut all_links = HashSet::default(); + let mut elems = vec![key.clone()]; + + while let Some(curr) = elems.pop() { + if let Some(content) = self.elems.get(&curr) { + elems.extend(Self::collect_link(content, &mut all_links)); + } + } + + let units_per_em = face.units_per_em() as i32; + let ascender = face.rb_face.ascender() as i32; + let mut writer = std::io::Cursor::new(Vec::new()); + + writer.write_all(format!( + "", + units_per_em, units_per_em, + 0, -ascender, units_per_em, units_per_em + ).as_bytes()).ok()?; + writer.write_all("".as_bytes()).ok()?; + for link in all_links { + if let Some(content) = self.elems.get(&link) { + writer.write_all(content.as_bytes()).ok()?; + } + } + writer.write_all("".as_bytes()).ok()?; + writer + .write_all(self.elems.get(&key).unwrap().as_bytes()) + .ok()?; + writer.write_all("".as_bytes()).ok()?; + + Some( + std::str::from_utf8(&writer.into_inner()) + .unwrap() + .to_string(), + ) + } + + fn collect_named_obj( + &mut self, + reader: &mut Reader<&[u8]>, + source: &str, + e: &BytesStart, + has_children: bool, + ) { + if let Some(id) = e + .attributes() + .find(|a| a.as_ref().map_or(false, |a| a.key == QName(b"id"))) + .map(|a| a.unwrap().value) + { + unsafe { + let content = Self::extra_elem(reader, e, source, has_children); + self + .elems + .insert(std::str::from_utf8_unchecked(&id).to_string(), content); + } + }; + } + + unsafe fn extra_elem( + reader: &mut Reader<&[u8]>, + e: &BytesStart, + source: &str, + has_children: bool, + ) -> String { + let content = if has_children { + let mut buf = Vec::new(); + let rg = reader + .read_to_end_into(e.name().to_owned(), &mut buf) + .unwrap(); + &source[rg.start..rg.end] + } else { + "" + }; + + let name = e.name(); + let name = reader.decoder().decode(name.as_ref()).unwrap(); + + format!( + "<{}>{}", + std::str::from_utf8_unchecked(e), + content, + name + ) + } + + fn collect_link(content: &str, all_links: &mut HashSet) -> Vec { + let mut reader = Reader::from_str(content); + let mut buf = Vec::new(); + let mut new_links = Vec::new(); + loop { + match reader.read_event_into(&mut buf) { + Ok(Event::Start(ref e)) | Ok(Event::Empty(ref e)) => { + Self::collect_link_from_attrs(e, all_links, &mut new_links); + } + Ok(Event::Eof) => break, // exits the loop when reaching end of file + Err(e) => panic!("Error at position {}: {:?}", reader.buffer_position(), e), + + _ => (), // There are several other `Event`s we do not consider here + } + } + new_links + } + + #[inline] + fn extra_link_from_iri_func(val: Cow<'_, [u8]>) -> Option { + let val: &str = std::str::from_utf8(&val) + .unwrap() + .trim() + .strip_prefix("url(")? + .trim_start() + .strip_prefix('#')? + .strip_suffix(')')?; + Some(val.to_string()) + } + + #[inline] + fn extra_link_from_href(attr: &Attribute) -> Option { + if attr.key == QName(b"xlink:href") || attr.key == QName(b"href") { + let href = std::str::from_utf8(&attr.value).unwrap(); + return Some(href.trim().strip_prefix('#')?.to_string()); + } + None + } + + fn collect_link_from_attrs( + elem: &BytesStart, + all_links: &mut HashSet, + new_links: &mut Vec, + ) { + let attributes = elem.attributes(); + + attributes.for_each(|attr| { + let attr = attr.unwrap(); + if let Some(link) = + Self::extra_link_from_href(&attr).or_else(|| Self::extra_link_from_iri_func(attr.value)) + { + if all_links.contains(&link) { + return; + } + all_links.insert(link.clone()); + new_links.push(link); + } + }); + } +} + +#[cfg(test)] +mod tests { + use rustybuzz::ttf_parser::GlyphId; + + use crate::font_db::FontDB; + + #[test] + fn test_svg_document() { + let content = r##" + + + + + + + + + + + + + "##; + let doc = super::SvgDocument::parse(content).unwrap(); + let mut db = FontDB::default(); + let dummy_face = db.face_data_or_insert(db.default_font()).unwrap(); + assert_eq!(doc.elems.len(), 4); + assert!(doc.glyph_svg(GlyphId(2428), dummy_face).is_some()); + assert!(doc.glyph_svg(GlyphId(0), dummy_face).is_none()); + } +} diff --git a/text/src/text_render.rs b/text/src/text_render.rs index 3a45d68c3..8c6e8a28c 100644 --- a/text/src/text_render.rs +++ b/text/src/text_render.rs @@ -1,5 +1,4 @@ use crate::{font_db::FontDB, Em, FontFace, FontSize, GlyphBound, Pixel, VisualGlyphs}; -use ribir_algo::ShareResource; use ribir_geom::{Rect, Size}; use ribir_painter::{Brush, Painter, Path, PathPaintStyle}; use std::{cell::RefCell, rc::Rc}; @@ -94,10 +93,19 @@ pub fn draw_glyphs( } } else if let Some(svg) = face.glyph_svg_image(g.glyph_id) { let mut painter = painter.save_guard(); + + let grid_scale = face + .vertical_height() + .map(|h| h as f32 / face.units_per_em() as f32) + .unwrap_or(1.) + .max(1.); + let size = svg.size; + let bound_size = g.bound.size; + let scale = + (bound_size.width / size.width).min(bound_size.height / size.height) / grid_scale; painter - .translate(0., unit) - .scale(scale, scale) .translate(g.bound.min_x(), g.bound.min_y()) + .scale(scale, scale) .draw_svg(&svg); } else if let Some(img) = face.glyph_raster_image(g.glyph_id, (unit / font_size) as u16) { let m_width = img.width() as f32; @@ -110,11 +118,7 @@ pub fn draw_glyphs( painter .translate(x_offset, y_offset) .scale(scale, scale) - .draw_img( - ShareResource::new(img), - &Rect::from_size(Size::new(m_width, m_height)), - &None, - ); + .draw_img(img, &Rect::from_size(Size::new(m_width, m_height)), &None); } } }); From 0179b74582ca2a30edb808d972e1efd5413a3c23 Mon Sep 17 00:00:00 2001 From: wjian23 Date: Tue, 26 Sep 2023 11:00:08 +0800 Subject: [PATCH 6/7] =?UTF-8?q?fix(gpu):=20=F0=9F=90=9B=20expand=20alpha?= =?UTF-8?q?=20mask=20texture=20slice=20to=20avoid=20cut=20edge,=20E.g.=20g?= =?UTF-8?q?lyph=20in=20text=20"=F0=9F=9F=A1=F0=9F=9F=A1=F0=9F=9F=A1?= =?UTF-8?q?=F0=9F=9F=A1"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/painter_backend_eq_image_test.rs | 2 +- gpu/src/gpu_backend/textures_mgr.rs | 23 +++++++++++++----- .../counter/counter_with_default_by_wgpu.png | Bin 8758 -> 8791 bytes .../counter/counter_with_material_by_wgpu.png | Bin 8529 -> 8553 bytes .../messages_with_default_by_wgpu.png | Bin 30006 -> 30657 bytes .../messages_with_material_by_wgpu.png | Bin 31605 -> 32316 bytes .../tests/draw_svg_gradient_wgpu.png | Bin 2085 -> 2118 bytes .../tests/transform_img_brush_wgpu.png | Bin 32560 -> 33991 bytes .../tests/checked_with_default_by_wgpu.png | Bin 660 -> 430 bytes .../indeterminate_with_default_by_wgpu.png | Bin 512 -> 342 bytes .../tests/unchecked_with_default_by_wgpu.png | Bin 452 -> 310 bytes .../storybook_with_default_by_wgpu.png | Bin 35671 -> 36153 bytes .../storybook_with_material_by_wgpu.png | Bin 37104 -> 37724 bytes .../todos/todos_with_default_by_wgpu.png | Bin 12114 -> 12245 bytes .../todos/todos_with_material_by_wgpu.png | Bin 12339 -> 12423 bytes 15 files changed, 18 insertions(+), 7 deletions(-) diff --git a/dev-helper/src/painter_backend_eq_image_test.rs b/dev-helper/src/painter_backend_eq_image_test.rs index 06622d073..495321fed 100644 --- a/dev-helper/src/painter_backend_eq_image_test.rs +++ b/dev-helper/src/painter_backend_eq_image_test.rs @@ -86,7 +86,7 @@ pub fn assert_texture_eq_png(img: PixelImage, file_path: &std::path::Path) { ) .unwrap(); - const TOLERANCE: f64 = 0.0000025; + const TOLERANCE: f64 = 0.000008; let (v, _) = dssim.compare(&expected, dissim_mig); let v: f64 = v.into(); diff --git a/gpu/src/gpu_backend/textures_mgr.rs b/gpu/src/gpu_backend/textures_mgr.rs index 7b7e45b40..3e1e95137 100644 --- a/gpu/src/gpu_backend/textures_mgr.rs +++ b/gpu/src/gpu_backend/textures_mgr.rs @@ -123,13 +123,14 @@ where .filter(|h| h.attr >= prefer_scale) .copied() { - let slice = alpha_tex_slice(&self.alpha_atlas, &h).cut_blank_edge(); - let matrix = cache_to_view_matrix(key.path(), transform, slice.rect.origin, h.attr); - (slice, matrix) + let mask_slice = alpha_tex_slice(&self.alpha_atlas, &h).cut_blank_edge(); + let matrix = cache_to_view_matrix(key.path(), transform, mask_slice.rect.origin, h.attr); + (mask_slice.expand_for_paste(), matrix) } else { let path = key.path().clone(); let scale_bounds = path.bounds().scale(prefer_scale, prefer_scale); let prefer_cache_size = path_add_edges(scale_bounds.round_out().size.to_i32().cast_unit()); + let h = self .alpha_atlas .allocate(key, prefer_scale, prefer_cache_size, gpu_impl); @@ -146,7 +147,7 @@ where .fill_task .push(FillTask { slice, path, ts, clip_rect: None }); - (mask_slice, matrix) + (mask_slice.expand_for_paste(), matrix) } } @@ -179,7 +180,10 @@ where }; let offset = (clip_view.origin - slice.rect.origin).to_f32(); - (slice, Transform::translation(offset.x, offset.y)) + ( + slice.expand_for_paste(), + Transform::translation(offset.x, offset.y), + ) } pub(super) fn store_image( @@ -395,6 +399,13 @@ impl TextureSlice { self.rect = self.rect.inner_rect(blank_side); self } + + pub fn expand_for_paste(mut self) -> TextureSlice { + const EXPANDED_EDGE: i32 = 1; + let blank_side = SideOffsets2D::new_all_same(EXPANDED_EDGE); + self.rect = self.rect.outer_rect(blank_side); + self + } } #[derive(Debug, Clone)] @@ -638,7 +649,7 @@ pub mod tests { let (slice2, ts2) = mgr.store_clipped_path(clip_view, path, &mut wgpu); assert_eq!(slice1, slice2); assert_eq!(ts1, ts2); - assert_eq!(slice1.rect, ribir_geom::rect(2, 2, 100, 100)); + assert_eq!(slice1.rect, ribir_geom::rect(1, 1, 102, 102)); assert_eq!(ts1, Transform::new(1., 0., 0., 1., 8., 8.)); } diff --git a/test_cases/counter/counter_with_default_by_wgpu.png b/test_cases/counter/counter_with_default_by_wgpu.png index 20a7e2d3e55675069ef68404bd5e591f9c636bd4..30c8f9ad41044922589be1659b41449cc31b9151 100644 GIT binary patch literal 8791 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 diff --git a/test_cases/counter/counter_with_material_by_wgpu.png b/test_cases/counter/counter_with_material_by_wgpu.png index 6479606dd8c6ce07ea9e03748be1df30fe6c77a8..8476bfb0d6367988da250d0b144a0d77c148196d 100644 GIT binary patch literal 8553 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 z zYS?$+j&ko(>;~aD_V=cp@G0uJvxtV7%Gv|;Bqdv)(}8L^4_2X&RT?K7*d-Ms!Q>fO zn!F5{1uiYN^=-&0E?FuZpYt^&7{Z9uQJi+!O`=gx(GW0%oD$3kpUhHdL)4b-oD|9F zPzGbXZnQ_3`$V#-K<*9;i339be?nfVFHs~fEz$u)J#hnzDGwNN#sYC_U8N}FzDzGb z5_=Apu@3F|9K_A%Y1P}C&l`-R`G7CnGFyT%oOZz=8g#`Vn(&sQ5!KHcr}8zut{Kxo z_U7{+d!Q}rP$Jo20!%2 z(hGlB_8C0q6J@f;k}odR(;WrWnBcb;p(ur0V_9dJZdp@Tj=5N#?9VZ+vCP4`$MRN_6H(4@z2;E8CPvH)kEKhv1&{< zT!i_N+&bm;Mc8h>&eX748)2e_0m}zF1z$-sQ%L2Gd3+?ovt1(00v0C@Sv7 z+z4K|a*p|^$+E~=_G5GJ=syjq!H^wlg~T{NhA2U%x7;Wr>%b0f1px;L&{(SFQWDlQ z>Z%u3XyV|21V>zYBSzTaz}4asiFZN^4`)m``jJw$v}&|KogK{E`&Y=eA8M%J`}$2P zp-dBQj1u^I^DJ}8dU&kE$`}+kE+k}<)Y!@pc%L&Qn_NJ6WAO7Za_X{@sgh{B6SRpM zeFL$4WsteqWM15F>gSEUE**-i3|3lw0(`X($R}sbo$|D>ZLI&?TYD@B*oV^FDUeC9 z7-d3rA_vXQJ)_qR2YmY_dw*vvF$^R!$e8cs3)$f2C{9G+hEcqnpg=9QsY2;P_e8P-R@&Y{&})=@g`KymL5up3*!q>k+d-+>DrTk;$j`)s z22fAxYI2s>4Gql_u}OqfEdb*rk%_s8KyDxeI%-LkoLJg*qe}k)Lil^!se%3jr$ETS zpKaN{fsB#Y>XTHt=?$&Bno3=tKvUHIGC3c64Gld|)f=wPP$am-s=*4mkbUz!-*T!< z2THjW%r(MTCk8?AxW>s3gK`8o~!65*r(o$ zoE|{310&Snai|RI%oe-Ut$c2UB)y2c5`=K=WD6GqQbNz+=BdN;S1z7OAKO629g_BU z^5l~5uQy>Go%Go!j|Zu}pgjj=o9?#vUp(FM<-$`^u;)B=EBRkvcs!hXIQ5j&|MLpr zQItnf9z}T+g{~*~!=YzH!%GYPOpkADzwlF?=OSVIqV5?do^j$CC!TTQ87H1;`pf@8 dNYC>cS$d`|yL##*_+KT6*tP4Ti`OI^{x{3WB=-OS diff --git a/test_cases/messages/messages_with_default_by_wgpu.png b/test_cases/messages/messages_with_default_by_wgpu.png index 6e329c37f8d46ebda357ab17f628f4f80676a87b..a44fb667b7399c0633b21948fb78a03de2142481 100644 GIT binary patch literal 30657 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

LFYKj*u0X^4Qw4bz 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 literal 30006 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 diff --git a/test_cases/messages/messages_with_material_by_wgpu.png b/test_cases/messages/messages_with_material_by_wgpu.png index d5d9a660cc48a9e554c59620168d163d9e8d88fa..55db4d5442161cbff717d54f3690da12481f4c69 100644 GIT binary patch literal 32316 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 J|6oVv{{Tih6AJ(U diff --git a/test_cases/ribir_gpu/gpu_backend/tests/draw_svg_gradient_wgpu.png b/test_cases/ribir_gpu/gpu_backend/tests/draw_svg_gradient_wgpu.png index 4be63f2fbe9b94c32798bde749ecbd3ea93efd0a..9bb1dc953fc8263a24733c6422ae9aff346a930a 100644 GIT binary patch literal 2118 zcmeAS@N?(olHy`uVBq!ia0vp^P9V&|1|%PcFuY)3;NbOiaSW+oeEWcLf{N!P6;Gk= zRWom;0XwS?QDX zREt3?oH1Z0SHr1LhLCkk3yMS;rmkjK5yR?$OX`pHUb8)AY!L~LY!MR}#XvZvffa-$ z6B>aSP58jh{m-}m{J!|p`wzE1+}eNXb96GhGru!Gh(xfUZ1!ZR42m3*=y#jO`*zV8JA#zwnH#V>Q1Pd5k(TS7*kRll& z3SuQ6uNTq!&nL!X+at?k3ngWHU@U^75M4e~|7)P7m=`E%0hW%ii^5VDdWyM#mKLC? z2dgL|bwN^$GaI>{fp}@lAxOZ0c_ar2EHHay;VA}tTEH%fp1NQuW+B$JfL#mvJSt2RE*4UU?`4nA2AogwD`{2nV;WJcOcB z=fU=$x&M+Ch$_o4in)J#dw%LKYB898GRCa5quyTYf3T#NlZuOz$_a($Gn-{T$Tyw( zZ?M#Hu7Z$PvquMuWXc4`XOVnA_#L0tcjUELIc5f^ceGqm5Sk*uHuH4Kzr}$+^RM*= zsK0PqAv}dGwP{j-l!hXY(FujmI%1%3H`nCdCHRYRm*6Xw(xyubOf-0v6or%=pBc?e z-}s~7>FIt)dj}9ScQSXHyTC6%Y6{y@M-`VQ9-{<-@Q6R|i$2ABwB3|S%YMNQgl-^f zu5fxa15EO z;1RF{`p-0RL&TvP*3G78u3g{4nk@A)(O7<0YWb%*X;X-jNLy zlCNOG(N;v-jsWV{)@ds--KZ~B3z9HgZ4eMvo zFU((#GJ%o#krB7fi3Xk%4?qFL0#th)s40oH8|Za#U_mr}VZOroiUsI- tpgrLd0ui9va027n5Av*q;7av}d&Q67-EQ(wa-H`{3okD%FZVwWveGB% zsTPA)IAg$0u7*>g3?b{778HpxOkK^eB8Jrgm((A23%>Qag{=o{CWBB+;zu2^^GQhj zgB2(8Kg&0t+JAZ1@nm*qerJ9ViC{t5?8#6W6gebO|6i_kzYFgld;Q_P`_uamE%to7 zaqz<73x`1@f(2zCyaAO#kwX@B)c)hX@YDMQO3XNT!Fe^<6q7FoWd;z8OqLjYBT7{C z-{OFu-vxSPd2B%#g_P|<!J`}98bOue9L%TAwXn^rpi`5pLk{;2>VB}E}6M>ffn zc~2Yu3xxb@*W`W0GBH5P#YyFaLNkxi`Jw~$99sXKOO&s0dNo@)s!U;$^8R83!Civ81Yfa~HeCW5!V7dx$^^#d9fuy-3r+p+WOU}5LA0~I zgS~^f6UZ9B04b13Dkm1OFdCgtY6P3(s+72|>84a#_6v3(bbH~pLKx&&pm`I3rs+-I zd4`Eu43sa#J6etkJ=31CHgQ{9T>}V$9G?j?6XdWH3dJ*zriy{%Xugh+nD-3*#ElSx zuV3iDz#pLg!cBu0Xs`k>$etO^Jgu|g08{sWjgWuBCk^5cCUJfiJu}@P{%{WOX45as zCCZR613IIFMKWc=&NGjUxPu-%02Vm^T|SHIOoM3&H;4vm`O9#Z<1Pm@6jB137$kWV zfW~thfr8ThWDYOT@bC>0hrqUAXz6J20EQYv_vxSq4LlwnnfHwK z3Hw@(asmClet|p?N-vlV3CD@R2$m3-9+}|Cmg2w$3Ltfm+P0ruV%iZpK(B)X3!+IL zs6`#*d5;M@4>bVYrE{WzC!_VhMhCdQJYdgcUty}TtTS33Sp742y85}Sb4q9e0QrB% AC;$Ke diff --git a/test_cases/ribir_gpu/gpu_backend/tests/transform_img_brush_wgpu.png b/test_cases/ribir_gpu/gpu_backend/tests/transform_img_brush_wgpu.png index a86f6bdc7c27a0a1472cbb3b3e584bea21ecce0f..4608176a8682bd1a5c4db3461a71650a6e6b409b 100644 GIT binary patch delta 23355 zcmZU52UL^i`!-8(0V-8gMzmJ3q6AB2C!w{Kwp7xVDh?#56{?JYi~u2dL8@pGQ;UMk zXsx0mL`2z1*r<%C$R-JUlMq67^1k1jfd159%@+jRc8 zR;n|hRASTXeopkLGco)4C8lj7%{=A5X@sAp`wPegVc@;)K@$83AB zcHYuI2CR2MDQE+sX24h$Q*)GZFiuj*^sPy9ie`eej{2mJxI6(E@%DRG_6mRWo zjbXhm1ToN$qDew%a$UasB0kJvNpkF0bC}oT)#GvYarVgg8vXFaOCB-~o#yALvYB9x z6)>Ge?ra9f_BrH8tAk>qj--t98N(bpv5iCIwKAvnsUA`1{~lX3D-`l8m?Srsn#Z#) zvBs9!ZgktCwl*vyu(C{K+(vHuZny(29^{^HVj-&faVkzKBM8bJR93Ro}xUpe1x6nMf)U};N(q(Q#R6Seh*mX4F~l!>dTLaV*==kd@4i`)=s zsT#0S_FCZfWg~d5CAr)~8*R$Bx4 zzw63@*+Om~ls%kmC739UsSiN#a$F?~%rZsk-Lb~~oRNxBC&%u9;ugVP$78gZ6f7|& z>2Iz~$$alp-fl{y;ON{@sv)(NdBM#m643ZH)Z5rOGm25TaAhozhed*8H02y$)x8f% zo)KA!8@m`PIsq5I``yHy%-vtnHVvN}FlLO<8Wx=x%2)#>$8Ct~RNt2N*_tIIGR2KF z=m)0w7!BGX3+9U1n21(uJcHku{Jd+UQ45cr6d^PM%HQH6A6vEOZ_B%mQDinHFZvy5 zw*^d>?Up`P+l%|&T5{-7^6Ny*9GyEK0LEJDtg6 zaYPPU(KL-GO*EfycSwA=XT@eK`|&j?Ps?la$!|Rr>oM|%CCq?)FGCIJRp{yB!D1O< z-4ZT<+%j-)9#?RWGn|HJJ8f#>#n!T`-sYn&Q5CgTl^6qWQi zHPkE#Fx9VMoIX5mZfJ7wV#DKYP5Xekh7TTI3cHJB$z6aCAO~GEpx27{s>_55US$+= z_USFRR@b4u4#Fhvc||%Jq~KLw`c=sGI>gNclIuN4^XE!{u}&+lhr7GucZWLL>l?+{ z?Z=NRTbfiQz!GlZbOk{5d)s{VA&`V2aSPA!iXlGGj`b^js~DX zJbHrDXQTWqG_2$nU71Yh?Z?bq#}kJuU56Pi`JER}vXAWEusiBnJC=ii+|$V_3V8_0 zO+kp3qH2&bX)Tr4+Po^xNTzePb6Vb6pp5M(e2u4kH3xZX%H1y8Iq?v!?8rE$g1RXGdsY@#%A)GXm$SnkcC8W$^flO_ce_}{S}{}f3JIi7n==?}-+%Kz29Gs1= z>HGJEAFiv8?3$TNrp}Gy34;s|z;GeHycUSp($)RTP0J8ILchOhF&E-5Lv#yGU-4<GHkO;w!1nt2vSQpp|3wPHtxoGzj# zq&|3#vM)M_nQFGi&Qs6@Xo%*1-V}Ebxa}jnaFCk+4s4+AL=#IPp7>TxU zfFi3%su~vYF^>}y?QLiHc2tSEwH05Uft3}M9tA84q7qi#vTj+wVx#SAEm(K2%C0>OGCKt-ySFsWl9t;(!o0zMPe}^HU;9Q19X}x(oRBbubr4*HRu=g z<>vb8myR)$Sf=O-l{lWtQ*Is5(`Zj4*y=A~!2q>*!X?QrNP&s>(6Hl!WCxD_?a!Bm z&{XU3a~p(`SQbHc)9j1lC{n5P4_pk*3YqV+fL@lp`?1 zh{FL%i5p#R32 z8jpuhUpkX%Rs(r0QADM~7u|j^j{;!EB4zRX_^fNemdaf#Y5>7G5SE=~(9ZX>d zuporyrm@mCk8vB-rqJy1Gu3b~tp3bzDH_y&^h?)dGROjkDDhI7hPHfgoQP$P`pb8& z9h68H(yLT?4Dl6yRcWQtVqoK%>h_S>ZbQWU0FWL%=b`GMDH{j{>C<_-dC|TwiYx}6 z+H+QD4qWZC$ZP@o`a`Vw_b1tYIO)i}`pM4oTDyLVA5Eq!TXE-SegoJDaLS9j%F%H7 z@`1@FPfKEZ9lg%Vvpr(@jMh+(2CU#?0Bv2v_vfhfry*q`jLFcW@wxZsxP3V1yQV06 zU-4Vco8kCnYup|_52|7XRQ0zr$5(+<+mlXKE&mnv0Gn^>Gg^Ff%;KZ%!`0XeD+&gy zMM2it{^fJM+ESAiq2eutv4G`Lv7|KK{vPNl!pliMP$QNsXET@WhF$6iqdp%sGM#r< zFed;aoAPv<;9X+yW?bOvr>QsW^w2*>>RYTb#&JJ6m2gE(pRfXBL*DFYGGjfjfX`O zYm%azf3a+8nS6;Y1CH;jKHzE=-c{wi&Vd`%RE}6S=BA}>PKPCty4du`%#9N`u{;+b z-a;KTYqq$#B4Jg*p{tevR@35FpX>4ErIv< zMS2gXn5O93!x#T2N+jboxn53qEW=H%+l z8yDl11`C8+cyIr8AMCHEQdCV($8ja#3x3?!fiY`$#>eZJGhR(sjYv>D8dYqUZeyv` zd9vaYH#aREz02djsmET-gqSanB~GNn(#8KY<5zj>X^lr&)rA8gR^MZOY|O4JKX6tSyf6?RV@}0WNGDTTy%@ue?tvE{k?m_XS>%= zrpMhg0LE(WjoRhTmsK+LeqTJh>1+6CG4S5VzkE15NoV3FZmA^Fn?b)pbVfWo`#Rxpadtllab67M_~AP z9p8Y5l$a`y@Iaa*4XK)~wt<7h5KeMxW#^`A39>a7hgG7te7WD)LJb$}X-D(l?aK?G z#0kvMt0v+tyGJw~0opgBB=7mGq$z)r5E z;~2*##J$8R6R9z^R)t-4Ic{3ou!H$*%}p);R3rJK#nqx0es}x(x7LhTr_ty-GeE4M zK^@t1nw$P^YB#I$ykjH>{<>y-3kt6jaRl>0XRH2arB(aWz=**{h?w z=<&{%^Fj7|hsS&ky!Uw88nZsHO%1SKZp-oe57aHcYcxVJ$anzv?O225C9S>(4(Ljhu7f^Ywk?j zk<2u=KyHRruvL8vT{z%V^VVMi#@-XJ(;te8AGJRzd||+j8$%U3g%4$76wOwo^{;hd zmxJRli{5Mv%8}3nt_mAC8*i<%#(Vi17Pb7-@>+EYP&=T{N%%&hNC#?MmtCnj(9i@; z+A+wR`%)8ftuK)|^qKvZWR)44z?b#e0J$h-h^DWUi-GTU=Yxhm5NXyrSnN;koJL4} z@zMgW@&t31?i!p61GL5W$(DauwC!uqIegR`87mKiuet z_a8c*ne~L5mDc_M^oRJQvPSc;SVPK4mOszo^9M~1-*en?jxvb-G3WHd+Tk1^FtC| zET&04mhq-TiEKvj5V6@ z1-IRC&=(Y_JrArM1m&ebg5`3z>h0>wL9{jAs=W6Z8Pa~AkuiV9Yr&ZT4zifnNrm2Z zZ`yOo5{Zt5#$1`m3R9xYo4k;u0`V%gftH!i*1|Q=7rGi;zZKw7?Nfw~IyL?EoIZ z?Mj)N@grTE7;Gs<{pgK5*!SIvyj}w)R?S5LNjMEvR{zU69-IGoKO_Mb|OBCKWj=B zU(4eN9gImu)7(>xy~G&5R+!kB>t0hgcvZlKvMFZ$5=~Dv*?a{!^WN!z51CP-aihW) z(=?1M%Ar5Bbw4zO%$-~BW&k6CTYS98jLxj? z!Ba@dZAq2ribTodU96+(I{Q5)#k}*Vn%~BWB-!qv&N*Nexj`|;z-wKYuY9Xz?WgW^ zih%VshoCd>Spv}bfhBNX#lr_^>xN0#rerx199jXZ9wFU;(NULp>e>tRCJ$k`*0bzV zfZwJ3)(^21mWwpl56)oU`)qY{!x*)5Ar+M?FEA#~q|kr}b!aR*aNBb~acCG)o@M@2 z;uKT2-;9uTO91iX)iPvTs!m#I{%(-Vm=Vsue$oDz;aoG zFRzAAW?7h0L-{$TWSxolu)qMpF{Hwo5+|`zie{Mr*Um<{#a0`o4t2NcbM}1PP~-77 zn4;%KjF+k_PZbW11!lvNk&9268(RXO6v_cUVSuot+43nS8}20QDvgvzi#bDaW&E?; zRCR)lU{*?$^4W)c+9XMV!@RAkxP zi+53NtztxpXvmn8aY8tuN{>l2rFL|nv9i9r;_#u>vq1Ikr0oqtNBLcz0ynjrIy$>-hyPTUo@2wWEeYeP zNM%DEf;@Gi1RIPVQqm15thDiXr=PMJ5!@UiQ+zqSjCVJw4Hi=0Hk<_Kx`;*I=x*Fz!yT_Kq_l_on^~|=UGuqxx7g;Nl^r|T z%Ce-SJ?5DKNpSp9DYb{ZQSIt+$>RJbyaUMZy40mFwUAn9pc0gru)cRihFy#lRtk0?G^YsdIPy7` z9vQ{2K|7N#d6TBQMu#jU=Xr&S*W{)e-k;HPQ`@PaNfI|oEHP&AN3I$`Dr2_rc@w^3 zY@}%RTV)3pHAqZXOk3suPV_lQ*sR-<-~{JUz0cJAcmq%%E2#|OLLEu{=Vwj?zB3bx z4`W{}ShyMd>Nd{nfimnIEa5IdobYFN19yOZjALiiKDCfh(6yB>Zmw%5S)Pg(pf}(S>#dayv+MeApME;;pcD zme~Tg^1C-$*O>AD=}i2c{7*it*x3P z@~r)S`pb`W9NU1Dy)p*h-mUDU07LD3<+;9qgyHIyJKeGwAwm>3x0ftU1qV4S{nDN) zVo!V5OjT#OLQDqen<4XVeZ6m(6ZmKmizuR2MTC(O>9?n2-vSq3{A*ab+jEa&KkC%6 zeg4V00m>;8w1R=bD4bvd0QtZp2D$0RmP1f5+^tl=BaWr63f9$15Tv1EFz{;WeKPRY z3V7Lvk&Odm54ozh{P{rDN4mJxL}m^-j9msw=5I(8~{`tSsfaK5ej?*82adoB{82{DTyC75C~VYmWLv&c{3$`OXQx&Qzk-~9)@ z-~_3u3)G6bl$uw{71WU@wlT&hu}6ViI-bPJxLo_ha*M&Q#K!~mo!_^es7gG${zvpb zQFit$^SfeyiIUV3uqq^aVt>!8^?)LPSz8xUbv=d20FmSg1M*;?*v3L-8ESqjUcaU6 z)5Ua`;6aI7*n{7f5**v>#aHgR{rxeFvH`FB9d$}2$g8je2;6oF00GkHS;lAH*n8%1 zoIo?~yf@zRTL(sM;0ehxKx7~x4bK0rY?b{36qtp$%A5%tGU(7X4XeolW^@DnW+a{q z*fA)We=r&PuW@^Cb(v2X_>l0XabJ-|3k+6JawP_KCHlD9X`mRm$0DNrX6vm=R|H9C zU^X)NNK=9X7(sUZ`XO~2Z>enlWMHTg=!4fVs|Q2J3Y0h&ROpK3-`6W6G?=|N)vkhUVhE?sGN{bZDAAtel%DAvhPXSBN)M2f9&R3F zB?PPCV@1EJgex5+m>+`1>hD9QN@V9F8g%Oud!yK4`tWVpgPgn{>>hgOJ2!QL?O__ zEc>U$>X&8z6w!-o&XK-}$O;O%g;D*>mEIuooh78|NLMR0f7H}-tB}wXMfIc!619`T zIloBC>#6!k7rf}Ux0C9n#G*gagIRvC%k=(9w_PK#FWU~Hgm+VjY1pxJP>c)>I&3f@%F)M_g3meg(gyMeRJ`7WyJ8BRV8 zM_4|nP^UV~ts1yw;=vU!#z6fc>O#du6LjjhgBvMZ;64Lfx@p^xl@7oZrr+BJ_0Ix| zfOBTuK^D=&3^xzX`K5nr+Cqr!?Af{ZZi=Cqyl^~}^ddT<`Z2Z0VfAkNm67?w?{b82 zNDX3DoGycqL3O8B&2n#9_lwSe8~E}m>Vg+nScwR9p)p4*94bZ+m7+)crx;1*zMCiP z9d7Lzv(3=^(!PYU{l>sUOfl3}Fe+~}$ca(8;86;pd(t#UCrV4Z2JWwooC+tikCWOJ zDj43%@XcFK?F*a9G$|{1_$!brg_m4zSo)^^w71g{s_wTcWUZB;<`NGKnQmaQ5WKB|LkjHCERjqam zGe@{-vjuigxH%c{YAjBP!wg$-24;Qb&B%UYG^?Cwqr50~$Q5w-A{%5Fcb1Ud;qUSs z7}S#7{N=)rcK#i&1h&4NsY!)sU za)?qZd9kX}_yyc>`l%~2j{$ZurzybjCZMP;qWY9@wZlwMarR~chiIL-(kbOxVnVVz zKq$&Q{7hfiqrXY#LYi&ggR5)5ywb2c12dvmN*cuheZ%BwK4YDuwg!md7Dah&^;D)= zDNc2VQZ6_HNxP_XlUAMx;4V#hAE|syg)$HoA_O=n&ZC7mLthPR6`wvnQgiu-hR6|V zQRDu?nC0!Mo~j9xT(MNai<<(F$kMWw(B1y3s?s@F}^8t8_cUNj2jFaFcv0@DjmN8)Efm-W%713fLI&A@ZC7Q%>Pd z)=!?MRTdQ;#fZH)!|fQ^Hl{KMACqB*o*kOWb?9>}`QCrc!Eb=icYE5OGZ%~@6-LT2 z3e+46iiQD!)PD}D}u58X>s!FLO zE&@HO$w{$l*hTuoSv%=N)>gv@RH&nN4>wIG(oGv~dv1vrb#{*BlYkltna5I%%>wmy zxq@Hs*ZIYO>-Kcje;=+KvEQH2+j?t{e^5|}?bV@?w(lE*o{6;cx9=txzgTW#VdE5b zt|sHWye%Av;^S2^mhz>8i^cn%np!bpOZlxpPI%0h{rd`r{}u!V1PotduS(~YM})}~ z4s=k!JO^xckQe0M_1M;g4SJJieeDD{jMsT0WZ*heIL=g*AvYgxr|LA7e+^fuFd;L- zO%?cxt;cC$buQ*y$Nk*ku*rV3!XUkDTtb!h5TLeU4d~LoRby!~yqVRuw44TOBqlgI zIG&rpg}@Q|K34hub zQrB>@y!SXKEyHl9+7mU=Sq=B<>Z~ky1rUfr4~ZCZJ~#t(a-E~*yEBMVSFq5n}-^e@t2UKWs@D z=vilL+j*?;VKEr{V=>9nQR{%8UI{OHs)z5x4R_3rsaHNfkGga8NldGLq-8O{h5f9m5gF4(VK6-^-|cr> z7w$~!EeF)0n$SRnz*O?UT4dyKAG0=}F3mE^-@uf40P{I`*)^JMEp5I6DLIA(E004r zEKt9hZ~pORY=`5yl+#U#ftJ18p+ltlH@t;^?MK@amZ`Hs^o~9@7wpEx@oG#$5LkHs z26y+s$)dF_SYB0Boq2y0sL{yg%NyZGGZxNT)-5Rs-adj zzF*C4Y~d|OX5UAZ1JDw`VY_D)$AAHP(;N%1aJ-or#>+Sx>=U#VQI{;}iPLhwv&gjz8%x~0F6!nx*n}8z<1(Ik1!BKV*E6+$o z`r=&W%{g9HAu%te*~$h0tY05PQf7r3M+c8FX)yv8{tEeUwh*CLWfmd{{R`x*5 z3U%5`U*|e<6AO?8t$fiKes4eNo3X!%kaUxpsmQW4@EfjXD!@*-jN*=d1i!dlx6|Vi z)0Ok?}$?&MSEx_jLC*!s4IuRgcWD+RroE62k)DK?zFkDD5|1x z0|{pxX{#wJlXbNI>Pb5A?{5Dah5OgGjM@F_(tn{aDWs@oKJ?Skx4AM%Hpsv#H7T;L;7<{)17v=5Jw1O#`Yek(g8Nv2R;ZT`&I zam2!=2ff~P;(AleTbhq_R1(82jh;lxCaBS2eO+2F!`FEO@aXstqmbB^E7;f(1!^p@ zO8CoaLiTVWCT1uAGwThGX;9Zyjk<_7*ohoIM%@fDhuQryDVHqtmUnxDN+Qzdu~~S{ z78{FeSL-rGvDE9^&O?_2@s4e2B}iAWk1wrH6g;UMwYUbfKihE61n7~Byesa$wSNa& z;G{a`>G)H?{m7F?3XcZ090|fdB?#6TZ9UN2U3PZ7mrj*krjimP+Ta<%(nuKAg!|f` z|9QX^zcHisv&+bRfhDZDKl_m4B(9Xr1g{&DI&!G4Z>Q24iVj}8f8DA}A$t_?6?`^1%C*d@d^%47rUR%@0t-;@+bxquf-=Vjjcb?v=ySFOI{LPD#zcG#; z$)VSS4JiAzUo911P=;ts0PI9M3y&S=6Th_dsdQv~W#&ge7i8(u)_5whL2U0He8q5> zvw6?oCovm4J?u+M=elp{v8&ds@89lleyjv19l^y?9v;-P&`kU_eej4AO?8Oy*1o8& zk-H_9;nKqr*V6-Oc1=!X!AYjr9Z;1{+ZpF@s?waM*Q7TBjiF^j^7MYcI#msh1ocp2 zbGpc~F0cb9FUCG0>HqGURra+yEd^w;x8deb6spE@406iuRSrInuBCv30bIE?Ak(PC zRil#AuuAej>R>_drh)b>Y2k7HJ;Yasf@WJb>h1q*Yq2Y{d8*$Mc)sDOS@es$__2Yn zT>x=EJ#Ry?)0s}YJyxChjcxm^$_1Hbjy?x{x?P&ee(c{-QSd7C_kY~>Sh$-SUHR7i z;f_ytHYM5(3-Z9R07y(M4O+hwj*-opDZ;vqINnW5&=M(1JI*KFVJhl5J=c>JFO#|F zO-jL8PQi4EWB>^H?$zrsvERVZ)3Dit7Fou<$5f*PwyFoE%IWe6m#@Xf%v*4m1`=sHm9ANj1I;&J(8=5X1bjI@*<@|hSsaJ~=a5#`xZKDym= zt`BowGJep2T)W>gPM!h{^7-mQrG--Fa^Er*NJg~$UpmtS$7?&+hy2*#3}-#DBzS$Gn59yl%__^d?D2`FjYVHyBZFseJ zeR+CJ!D&g{p3^y4%w2M%C4j%H`68_ISKUCr5 zxuz$s7s6#_82LO#{%^^5mOByu=(YIY1pUZF;8aQY_|&!2$JzFEHzIzXylXpS_+Z-6`N-3vunSoT zRp=L1Q3Mun-D};-FPGJQ`IhA(|CV)QTXA7P(NWnfMNwefO_#hKjz73Kwt_b~eENHH zne&Mu46%qRe^v?1Z0ATD@nwGn;47ZtGDO=38_RY@(0h&;yGkz^TK-yiI`&026})1l zs=d-sG|0*0kytgHd0K*rE0FH?-R++U&DJ>pm>KBXf>&O}I7?@U5Lp9dOk<6K;oc6s zWORuI!jCmzv%{P^HqBd_?H$?pU4h*-gi9NbL@4qp_&m!Z_?U^FgE^)cE^?tHO6(PE z^nxiB;|#bSIN~&^a0|Je=41{?4+oo8Lnc2On zvhx3j?{W>XCs)u;owK7Ex~}}NwJ5f?_eX{a6R~uWU2YUlv6d_~YbBEjpQr6P60z;( zZ$1Rut3e|#_T>4S_n{hRDVC0o-qhaQW8lK~0CC((t81?6z-xE}7Lpm{Yu}Upj?0GTBVZ@&M)dz zR-@b4i&FuK#atqo&m-58n9?Dfd=A%^xHCUFsebJ0FRKhBmQTu``;~P2MTSv=R>^Zx zgDj}wPfD9&>HgsXt4x4rqP4a^%PlKzyL5&Ry7Q$qO{(5ujB(i}HG~;{S6%())L!E2 zR%0iX5y5qM25CcS#Kpd|&IS+RisNMA2A4h^v-8@q(c6~N_}t1lj++@aQy$UY$*mfB z?!cZ8=gPhDj?Z^&(G~_Jt$l;1a$-eEjG=w_J0`PR>uj?ffk(}Od{r@>g^qi>piW~< zL$&RxaB%0+KDNCjUN+00Ia-iSAODnqnOzZ-!#Ncdlsfv1^}4gFyA>HV*u;_KA%vR| z^SdzT7ar7gwV_UD-8yvs$4;X4Ifv7yPuIxbqMOfzwkBHE#sxG!33_(60T`;^5gcEF z{_NDL%+1YVBlY{Sb6wO0cevv9Vu7xq>ohLl=f{??GmV$ zTHzj(Uj6y%UdJE1TC9I;ZtUEU?c@}IuDNGrb2g8{7F}hc3D8rp1(s2Q+HX4*Dan9coERK#)R141x)lRmg?kUKAG?AqR)Uak zq10vOp=E*}htbFTtZw01<&uGrlEOYeex(sp{yDssj)<Faa$KUYJ$4(+6?J!Uj zMwF1=hKv2;rv!cV5^q7LGcd6YA1y4F%%FKg7wI^sNVZr(js7i8C#yW>$qxrsXrIaM zc05!DUi$jzhWj2Vlh+zkb2}NIrOUJG?usz~h8x`q=$joAopfLyq`bu33dBL?%IQ**Wf2sVD=|l=c9840tb$XZb`{tfZL=)*W zH@&-zAV_B_8h`~)nz)cQf0G>;i4U8s-Tv%{9}MqXUQ+ENd0%;JXZhm;{rtKstqt}R zGQ58`T6>YWsmgtS*%kCR+*QQZ^ZLlJnZa?UV3rAz8pC{aO<=CO;@>|I%DF7gfFFOZ zzlVqfTht6y)!;kaNQrxe!d9GQJa2f@{iNYpkU6s?lwD`~W2ML8$`r5cQ<0KCn;>>g zKw;-Bt#evnblaeQz3I41aeBpQN1<#0FhSA<6#>W-zx7%ycd!9lr;3rN5TzRLzSSWA zIE?%OA2FFnrc(`=!O;^AtBNoFq;Ey=^m4Gu738y|ck`gBU|e{_Sy@@Bs;E>pU5Te} zGfMN2Z-rY214HwFP5PZW9o~2zF!b8$Ujvd1%(-ZwZ8C|mvC@=xa(?aiTMVqQ<^jGJ z3T9uGvFH><2@_;AL8B(*_3Cwa!|w(ru_H740@?Ce*llX-=UFv$R`jk&)cK*_q_?7*Y1YST-<)fm zcy)k_N6n`oz()blRKJO_%?zflOc$ms@3qsFV7%Mknp)~ctn>}Jqcm1R`2wn3=+%#{1`B= zSIwI;(kxOQm_!z}PKJ$dV!~S^QqFK}+1y_S)EItKT>pLm;}6we@F4ViT(igvXgYGx z!2I#%6U>(p5pJLS{LlXFjup`_{MjQdiI%I(#@^PDqStI+dA69o_cUb8SJAnOLat)@ zaC>~b-n!qb?|F4)$H|8CD5#l9Y;+@~bzD`)>W@$!mRcoJKv z2+Fw-h@b-rhcD(Sdn~iMf`{_(aZLpPX*|7~x8Irbh5Ky-{ejyzp2jripO8#;F*$-# zSAql`474_8Tq8o!{9?Xhn6Ac3Uq|&8zbI}~3l#nlAryT|Y^BAWMtCY7CvB(A{fTT~ zG5E;1xi>O8la%5O6j1;Mm^pumoHtEDw2k$HWmW+}y!ysFM^Y4z^Zba4jqt$hmx^36 z=ek}UZ|j){K8n}rw}ZTGEc%-x-c3|&dRZ@i2|r@m5AaYDf&_2itX}$kLKu2i$a*@!kn~7YJ)oLA zAUCQP^JDL<9)pTLas;_|3>!~gi9kuwO&67RhX%Ukfv8S`0lZiVbR68y^>N@B*&)2`K(RmjGs zIUt9~f@(L=*CXoKlyU4{S_F|W_;Amg_&%~*Ad$Kg0EHh?`Pdc1{GWh}yQgwzaON4hX3FzTA zE-4uwn}@^5UU+r&hbv}xH?6PZtWCE$F$9nH@1J~me%}+osjvRaD5QC4>po=L%RovI zA^J)|&xR9S-Pui2FU0(5MC7FMUY-`bcl^Vi(R;W_n0H^xW6O*s>~JxjRyp{t4`FW3 zE(gxavZ@8YyaGMw0s-K7`TDGxY0IgRYZw&#kgG6e)Pa1KM|#^pBM)(1hx-yN{C3}q zX1t-#0~zjkW;pPu>eu9xMDSGB#Dk%|8F&$lJf>(xF2)s7^Rn=N)cY{1eDz+@Qo|df zRM}VASM#gYqa(GlnY}#${R-;e`USx&3R|Oz!_gs6-VO)# z|V>WqqVx^+g zLZ!}CLFx|pBOq11Txl-Nh8<`Oy7Ey29PZ&2(Iq2RR8>uDfmc{v2GGYn6>i5#iIq=O zlIOe71qC~x?sRfDRyl%%>aga@x?vmNis4OtrVvB*CKyASrnxFFxwqnmEqrI?R#43_ zpWJO-^-lce_b4RiD`wc$f`;s^tnk5^WuDYn+k3Sa=_F6)+x<9RFo&1I9iWiMB+NQ7 z{5mR^$*<*F0+=GzU+rBvaTzZ7O1@QqkoQ$zpBXYL;u(3@ld@;T1wwjmTY&3CO&_8< zs*M)&I%B5t3$zN)+e6GIz00qv@nFuNu;tR@@YBPj4(Y!sISn4WJzFi=l4H9)36ZW} zhH*37X<>hcj~_O#j1u=2$28pwFjs3Ua+w;kHpq=n+QRPz|1-sheW@?i=hOu76zWn? zNfJI4f+^8T&8r-^AuIz1{@V}E2lrPEPP!uW6JSqX*%wFiwWCJk9^A`fet+>nS_a7Rz)BP6Cwpi7oKekscr z5MHN{U!_866}+E;>;h0Pz|->d!NILorH!=MWF$Ey%$%Za5(+oTSXH&j^mlc>3JEaF zV&0*47z78k_$vF$={Q2H@p8YT=WcXC)k!L4Dl}C~?U!{axbGVKQ8BZf-squytg1#k zaO7$f+mfQ)h!pbxm<1m;xF%C(B2f@;WP$O{mVsv8-Zu%t!%jtoj<> z+CyIj2Hw{{^99U-8ZTNsV==}Fe0Y>Ehpxigj_|yCNd3}&>A?Z3_M>>5{3E5hey zt0z0oZ3N^^5HHXd{#g~uU%J>sO}Vc0=$=ack=zrODHH?$>K4cN*@p*ZH<+YaYN65L zN_W7N!c(Tupqof%>9DGaDKKLWZnIIUV5}0~gZ1FcPy2W798FM>C$XoBuRGT&0@9h4 z#|n-4mBWnVxbcHHkuJYV#bL55qvxJY_6Rt!uPZlp;^)$;7&PvuPhb50 z*!aK&Q6QdORtE+*!(&JFvN;UIz=}i}X6oY*v8%EP4VAZyHIsVNt6Chu20n+boaOeb zI$c64=Y#`$Zo@Ar^!)sE^d842wl=`kJl>H6G@pll7hOWAN)Q#ol@6$&s48(X)46OG zO9fLMpdJUz@LdVg2Ktv8*~A&x<2y+Lr?6Bdah&G_)dv=01Ze?$wrW;%E^g%$?bU1F zpoZ2LDqhG0WjsDGT!=g`q@Tqd3lbqEzu-fK-ZwgL_T@(NN~iowGaB|{I;lfI%Utj9 zy9u9-ow_Lpv`ndG${7#rX1F>8F<-+;=@9%_XAHXiah7JyXOg(BoI$!J7^#Ywdw`MB z2P>({cM9?gvH4DTTCZ7i(Kq_+q#|zT)P5ZNQv#F^x`3Bmu_A{UkpXGg0GKRgc3PpO z#bjWv4xEcj80_E^gRUa0bucNeJmc>XnG+bvvpzBN z;qwjZ&3E`6P~jTQGsnmA$J0Z&+2ej?-sK!TLO9gLT!2wd+`& zN5&W+48Y3DVfPg2!(}+sF<3K2i?_J_eI`&yY!SP2<{p?(y3U5_1>Em8^}%X2JX3wyqinc>~1+>Jzx6l|z4M z;+6YRybk@Jc=hTgH_n#gly^MRr}hDO*k3-6_cg;)_6PbYJ3eS+Ob5ki>imzr9K&i{DM=c)JA|O;0|o zHosgKUWe$G4Hz(|iU{=RK6zMkqKJ!{MetOGsSZK(wz#Y${DXXO17dP&aXwrgCb$1aG57?4OpMp!r6Hdc3ea%b0p_Snm7w4~Ty5Q74^hg6Z zGG>6eK~)TKr3;^)Saq(_)QD_+OM8Q}qiSH50K9ItAS&QR&PrxbxtD{gLi-5dn_?N86OT5Lp`PlCQSE4z+z%Syz~SA zx171SCH6%s?HmzkQ;mWFxY+(0xblF`XgCjaU5&v@KlB8;=WFI`HUMw(t3`$>5wkuP z1;1Uk3SDr9ElWed3K$at zX?BafKhwBd*v0sx{+6iW6_RYaU?c^IZ6H)k+TGu0{AQ!Og6K}@eH@=68eB*>-y;B>c?fdt*%I6wq8qG zvqZsgJapzxI8T=9QZ74W2`GD~ zMb%TeBAEI^`{1TEJg48DD8r3?oO4|0mgZ0>f5X@t_%&qp{ zT=?we3b}6(j(D{L+$xH0f~TnU&&^y1lkns3_H?NiDx${KuDN~jZu{W7jeLB!N_r|a z`0UO;AckL@E=hrFM#y_HnoU-Z0arebX6iud_K*-jupTR$89W6yrBt}ZSjNJ!yzJvx z2L9~QS1;qh4|#ULE;Q3s7?N8)`YwMu{3>xvZfdk=ReihW#HaYxF>G%GjK}6ld!@JI&8NX49gZ{z+v{mC`vhM%u;@ab( zPS^Ng8A(kymqOEJTWcMLXhv>RZM#;gX~~WvBbM26Ei@SXl&wiNwyY>+Y}%uPlx&QO zVHHQYrd%3~h;hF(#+YG#zw`cPoO5=}XXd}(Z{Fv9-{*av=Y5{<_u*`YJh-#G%JH%j z-Q9729M%zUpZMueLqL#W*0scAxb06!hf8AntLc2$Q-Jy~5(;H;NAf^c#z#3TLv9RI zMH$(ku37F|MvK5X3fCF;G6!}DLU-P{pOwXHAO*Cz8}9YgJAOstTf0H6csP38tfLH~ zA(=E;%fjUIDT!bv~%0fRs<}} zn-GT#v>!m0MOfGLbyh<{v(wbfiPc9u~DW<3}Rz?wBc4JpR~*C>Uq=pn0Sj z3CN})!SWCianTTx8I_Yd$vRT8e3IJx{>K3}FsUYO)_QGNilUa?uXz-E0~(qu@UWpGE@Ds}=@rfPQbdb^_LTR%vh zJGd|Y)jVifP-YbFyU?(Lm}*4dcFN7)kzLZ+eeb8*x4-0lYw*&haLv`AtGelu`d6#+ z0tP-*6ik-pjXw@Q+w}68d6j)@p4~$a_CD$B!AM^JPp1YHLE}wgxn) zz$8lW%Wl49QPC(6^_w@N!Q^>M8j}Z0GP+I-*21F+FOxRDZoe;7H!gB`ITF}>gw8AU z9GLEQTpNCOPts~9|H{@@_apqaOFAjr1N=XBx6OUu<%4vaKiP2UD z%1{v~Xi^NYGh!UIhX7msZ=4n&-lwxD0P+3T_{bp#Z;275vW?#z&yNIopu22w!{J7o z<0(1&sLT{2yZYLZz{{(?KfZ^%qHX{FlehOAd|TP_&;6FIp|@VDHaSM8-qvCX&K)!4 zZ6OhD7FdipfW?J>L$$IVXr(@|CxoA?7fGP)#NWz6NN`$CI2AJCG6i)0OaTRe1f*;& zG%0>Uw9O(D`9j(Ha9dpf-;C4#H0s6nkeCN0uU)c)8F)vt$GPNkm1_ry`3`FzJ?HEz zc@;|>=)5_WX++*j`>I58K_+C`TsO(!>}|Vcz&QNiu)|M81XTC0nCk>2?-sz&aAkA+ zD*{<=X|~Cg<{cN98j^DD3VGnYX$^Ip7T%N8LALkc$JH22#fq-fU^8s}&NS-Qoc4Kj zkMGgaY}-EYLh6%ax|iE|HzcT})8kS2;sz(C>0QFXVCM~IPVeSs<*kCmEsTm0QFg4j z%f?*H5D*OQgQvzeBkLi+))JA?QYx@5{3;&+R8`8ZAOY7Sk3w;jimALNhrwPv;EFoS zkG(sxT0=-1R(6$T%oRD9*YV!?MXk{2MPr*M>Ea?>DQj@QN%*TDw&s2A($cIOw3**O zJdJU^58`A?&<^OJ%aN{o4MSc~+mj$Ga%^p?Y%rBPiDS2Opliy0m)o}^;d|HUu8wCgFXbF=^n(S|T}Z;zOwS>loy0P)r~nt&PxD$laG)z@oMk`EnyQegX4z%UW~Jx4 zm|i;NTUk-lo;0wZRP5+=%`fcJ`?T9gE)$|ZXL1JoX|h%Vd^+^guNm|GVq^wq$E=g& z{TYM_@2lThwZ43mYoOR9^7-mTV6m>8%gq&C!S{)2suYB~`!dsz| zX%QP4vT__5_E~i9+c13(6!^_(yPzjh6|CUH$6dxIJ=b$9bRv7taIhqY`PP=y%=5%99_iXDjQ!05*iNAq5WI3@19U-IFUTW0w1u@0 zoX3@YBw>rNDW_@CiK#JN{HJu`uryh4(vL_lE%vnuvfgzATYu9Hw}WU(FC|gA^J~el zYb{Q79cOHUJX_4~W&E+&*Rj~+sUkl64%($Swvbw)1UI+L>Cizr%d_x@8aK=VGa;+u z#VU5#&=cLMH)QGYIUMtV{v6|GBS~LyRaU~}{T=Oz7}3->(ZUMzr3<*vT~HUKkR=KHym+F@TD7{25LWlMjCIs8E3hxDw?(tZk$ z+;{)M4WPT8kMLIP`D7-0XDsAKv@GfnuYNsK z`DO75f#|5op!HuRS0(M`ye7DKVmDQD-lfkFT$(@!QM5vU^R+-!lp|t9-5FOgw>PiX zZ=hN-liXPIpo=4%uaoso(hF}4;8zA4P(X-t{b+H)NwrRl)|S3gRc_^@WW~wwABDCg zN*K#bJ}HG(B3#kocv_g&o-E8O%DNLJbPEGjyhIjXAQo|Iky zTP-a%)+!TXDXSASn6@`&2V~uM3NSs?6`q5eP`zld%xc<^xaUNP&9}?vae!d#uh;Z2 ze%*7m4JdB_5FSuJOu=T?x+9>~6Uf53Bgy&=+-l_$!=1e~6;spe7EhNvVe~}LESx`- zgHe$;p@2{f|8zv(h?fYzYDtJ+s~1g|3E^30KmIYJ7ydJu@6XhTKbaw}yfhg97gpcnS2dcU(P%l|#T*>M3iUd-L2* zbPk$(K>tM*)eyCifqV$3IEcte4dK4!kB|5#piQc_V9vZWstWcJg@OiAs8&N&KHg|g z-~YqKo{mOW{9{ROjv5E7joH%1r0O>amC*QT!4M*>MERx|6$XX@MAlsrd23>{xl#lH zs)}=uQCUChR__M>Ym@wrnUB`1$_-&yyz(H1B)Pd7X1!XS~y#s8tAR z-r252kQD7)qXh(Yop$pK>pBfphI+uixOs}GCbd8g?Qhz58F>X2lmF!vM1D-ZR~mC_ z>Bk!%KtB_;iQ3+lF^3lZF06}MBd%>nR18@M0!^M&?L9HVrGLG$7AU60(q#Tpe~mc3 zG5F)up9wA_quB+R$X)PJ`>`y9F%T+N6Yytx)1byXu6*Gs|I;lKNjeA}7^owS zDmsqlUIc`XGhL#*OYQAmHwkg9U_R5qm+v4M!-yUex?CfE4OuWMV6z)?ie4MFw#K*K zSEyyUW~=_Zt=&AA4ajwU(Z2r*fGbGF47QxjL3r^<1pcp>Qh+v#b(ub%>Xqt;Urp(8 zMi1D9#i8Z1)Qt=OSA}~zi|*mna5SR!N9{*luhq~BUN{cIud!Dd{l>;q#b?K)hQ|5ys-|2@ zl~W5p3dAfy%6u!BF5M%2O}j}O!yMkaXgeUl#}5$C5>-$5N?$;dYXAt{2vP}Q>ahV@ z9ErfQ{a7Hg5_M?PmAMngA3mku4z`}r#mv%&7eEXhOMrfITn@zhZo*y9S-D)z?L`(RaFB>4u3N15L~&+ClU@d;16O~YzG zMtYyT^k=3t4;%SrQK9Jd!@#$3GMg{Y#+p#@#$=bE3y8>>F}yL4iv+U8_wm$1Vi-w& zgsuqv0BpA$-QVnKc=(4nS%f+SXrhUSR_&AboxT!s(eIrId}Y$Wy#LN zY@lJx_}R(*HsM{ak(a5%&eV)W(6d$xs9Cj2yOoOp0K$4e8J&FTZ~Wj^GB4}456)pI z&}*X0w4N3{v;oce6$n%KYTHje2$a2{OQp>OWxi`!a{X#;Pu9M?kd&K=FX}FI-(^2W zONYN8*?lVrAS^SW{~>raBJu{8rC7%gW#Fd0`Y!H^eH_u?6F7#Tj*3yyN+e5uxh7QT z6DaMWD-+V?BVGPbTfS>`dP+*ro&R3vCMHiG$R(FbAEhb+7M+5+d>C30CqryobUhUj z$Ic-|_Zt9ECSkY^h{jK44P39kTm3i_8L}5G6ad1*66Uobv)H8K#;H-vR2WizJ~gV} zh&8%d!Z=%Ev4-1pp~$-^B#ST$%Fq>aTwrbkAS+$8!?Qz5*)iP97!}rPNgIa|Hj^#2rR{1Sy)-x~g8y_Q1 zKRu9!BNh_+q6VrINWwIdFq+cLP!-o-ks2-dP~>@isM)X$u#8*QL6n5@2Pj z#)wKW@=a0s@oBpbOb_RAXXe}UgD)Dl6KAH8iZs$%N4;Y;0AuIy$ab%Z!$^nMeIGmG zN=?J2q@|$PjW`z)(8Xg?%OHbN=fRi-=gLMlK!=wLiHDY47(LNvWyYF2&XS1Gqp#@p z6J5UPTZC+*DZa&{ZM}~rSyjPl7{$N2Rf^t99=QFfmX`QN%Co=BJDpX}@VAXB>w(Dd zEhl14$7Aq|0>tV=y3w1Wy44Yr_~VyzI6WmovV*Oia>AW3WTfoQ=VXg#xUT-E_Fppg z@c3lH-TX)Vz__le3lSwpQ7oj9TQ#-y3}d%@YwVA)w$xsA=a81<>U@~os4)z^TufEq z2H*?6bE{^#=-Cb6oDETVDi;|#D+-KcajRwjZt};58XN1im2zI+jO7;e4jG__Xe?e` zbUL_YTr=c`rsneHTVpl0z(?qnrOqn~V(CNiU!*wpMGAHpYw9_ZkA;+%`wcow36K#G z-QuU5mWiHoY5x8ve(84Ju4>U+OOGF?aZ^=I2<1e)c5dv*D(&TKcDQ}NHCAW+FI!_3 z^Qw|VD+R!SZ>?`MoCcs}UjVnkOJt21W?)3gUQ^msWhX%zhE(lFsQzvz4=5Xal1w(O z=N{Gd4+tpC^eepyyvR~ZGsAq1p(QNGa`iFGcLY6LkOrdR(j^#^l7L%k2sS%X=xKSd7kE6CYxK?lnnl9kAQRzWtmxMjL4mxsD(GcHpn3v0x z_|*JbVCe=Q6BDbm=6hgXrolZ690Yb$^Onuxi6~LT$P#tDGK;W4{b57)I zVy9lxcy3y2qorGh`Fcz5r<$kCbxKxsEk=OI#%&!2niJH?8qukHEk`-IrE;Mq?^0(S#i(qYDs zIn}J3SKqv3hJP(dHXpU+)MWzb!xAKpe-SLXbVoZ=$na8_GY9vM@kQDES#z5|FHOq> z1;9$`te2~@6D_yv-rsKCF_q<|nkGApwqjL^ermgT6YWxgr8jJ(HD9#2(qnKw0Yl3h zpi{(UL{aZdukwF6j{Hc|z27}ERXT)>Y)8v^SPI*QFvS6R0kM(OdwrRc6vE)%Y9SV! zYBA1V3mk~9UkQSlM9|t*mF7;}|77D!kMr=6HEI-Eeu$Yzyv~}%GXa~wq1;8jDEmL@ zkJ_@Oryp$_^*)o*h-ydOo}R$StW*1*(BuY{lG0+T;5kX~gfWc{=DSt3nL9i@%8^9O z=`v?e0wg65C9ytPS5vc5OJ~K3Lx(gpb@UHut~wE;_0>}i%`7dKd4?{c8Vp0_OJPG- ze~E37U)JnhIKAX^=<8ox;qbC+F&cj$@I_ol;c4dF zh!HsGW)JFpM_IWdTrNUT#q}(Of;E~4aPpvW4m3n3&OAx)@RVB(+R|EMU}rG=1=j3> zOTfRa0W20^Y6r)tsp7$6HT8uKe?iW~s-QLcC$`n`1rw+Ug=_Tm237Bw>2i0 zF;{5hI8uue45rJAF|s87ITYPh*F{hT2ayHGQv+xH{DFpL3p@hyPsqz2T{`Hz4zQFb zi;g6A=8tOp{#2vY058j=j`XyE6=-EwZnZ(s7JdDi&eSLN;urDwc-O2K6Z$=x4aJYt z!AgD3@-1J^fz`)eP~WbG)3l+bbN-i(@1{)qS4};qwIIn3@2%zAVjbr5FX(&NLu9|iL6Jw6 z0zHzm4p9y!6P0t7!0IzFq6(uD-SF?|uFmWsHZ+;ys+*#zsRo-CU_xv4IA611nT22l zpQJvp#&N+iR$B`qtG^uaC6^#aFJgvk`E%sdN>%EMZVOFKou}toUy+qF=`uDE?4w5g zc_~msOGjtx(;5Ha-ZkpbJ}(9A$ZA<&+`*b#15C}=Dk9eE;I7qki&Y;K^rfUQv|)wI z!*&E#Pp5>SSGC1zXxT=>qRikt%7lY7ewAndr(vh|nXQLn!o6Tk!JexY0M^pNd-*oa zkj6z(9Q55NCzc`xYQ7i(;GC>VEiB4#m@V;A?L!KVQpI$nu0QWr3N zMoc48)y*ORA7+D8Wn=<}uG%>0_*7HxuS41}&SD}!odk3E_^n$t)JTEfwX{}vJHF1P za^>=SB=AxyNLYZN@auxeyGvYydV48Su)cM9(if5D28aysNkrKrw0wm(Y^AL+^>l(N zUH%abrR7Go)&k%VQPV-KRxN$E1oO6y^CpCW2osL^7!30cL(4*o68rH77|uFkaDOLX zk=IYWI%K|(a%eE~#I$>Z249Mt%HLxU$`~7kfUhjTfIXM5NMLMkJ*0Z=IH|`R8KsUJ z5ag*W9ouCq^z~x^Sg`-=%4(3pk$)aXH3zr3P)E!iq*e%vy+px%nELKKwBX+8O~d~I z8{%Y`FD}PFp+T87w->Yd4)~#gPAr9^h%tpdOmi(p(T9!z2zb4+0p|3Tm?&K5A0!o)eMsX5XpRAUP8yWri0hK4b-gadsw;fVYH($ z;VxP_02~EkU>)e_Scb?4vC!0IB5v|=XR&j&RFAkU^bo>-p0$ej@nw^&MsF~E!&2rk z-}qFEE5Va&ly~{i5KBHFii|o4gIQB2NLs;{-lIx&(ZcJl9;A3X*lS@RmHl9E7V^`g zZkKcnc-%dd_ODyigXXBHn>OH-1PSe|G5rwI`1Jy;_b23mj5TAB#!`VnJ)*hlPHMzl zJMseC%w8bIE{jy>%<$@7YFlg798&~wORojq#aQ5Uc@@1t<^T)rkX z;#GXqR7)D*P6t2omG$Wt#|}K@+*)V2K+))MTt(J-gQ;Ho2>(SPU^DbWOCvZ=e>nR;^``+gjkA7eGmcLI`@2X_I6acOHd-2~plkFjn^>sHH7 zlx;(X3Li)QW2pscEvyj2Di_a%_+QTx=ogW_1e=q5|v&JvmPHQLIy!S*lg8OMm9V}|bX1DJFcnC9urTMAY~WGRbW2g zTF#+aWcNc6-V0rlkRLomM73?cc)XR4eoWamjHCoJnFR6pL=f*wn^vv=pbf)Xzh=n2 zy476ShfujJvVA3NfOR!9 zhxw9CXn6ojv>JK$k-}pgj1EoX>fV0pFiQ2w6_nvGj@1;e)JJVuKq^eH;gC=hq-+>7 zs+ux)nA{5~Q;BmM@RhpMWuY}IMjjctRyD_&Myp!wL06)Db-aShS{}JoLo*#vqZg#A z71ZGkBENt)2gZlT*ISXo4BhDQNNZz<=?NTw`T)EA3jL?DXZWIYVAL7t;X~c5XpO>J zIKc@}R%-0RiJ(-cZ6nvmtkesRN#a_pzy^rm(l8a_Gnt2UZyze>Jv_yq9c&($*$qhI z0asaVy=oMxWmTZRb#T4fg&`X_V&!f~fOOaFUu-CY+to}!Q#(@0CJK(@1|q}~mdb%C zwTs!fP$}h&N)c4Z9gsL;-LUnLy}QQnE$~xg91Cnknv7(1^p090nn`rEo&ZU|tpAhiYyuJ*+E|6o- zTSBg1x)z(}=}__Tp*z+9slc0B`c)4(QE+Exk1!8=snPPwyL|ex??*_wGxO{@L7`E ztI;ct!J$syZH0c}<90=Qnc$%nO7a#iO83q`of~XTtdC{!8WV&m00+#-U2q2-&{?pl zoO;;aOyI9IPis~jstN5(&Smi$67w@nCD-i;bE8c8X*BdT7D~VY@=mNzX;{`9k2H%Z z6VGi2KVsX@6f8Ft45$8i?Tpwp+n7ugm;sGM)fhTxxQT1%=2vBPb+TfEhrC!Mq1NHO zBo?qIC@L-XbY%U$c zQn?wdAUR7D?o!ekyhL$AJ0~GA;t_=LCx95!izHV>7>OpTHT_~B}hxY90>ltp!BypzFvTHqE z%i~o2yt>@gC~-zSPsK9;+x?izr#{F~MSuZ;K)FK2PsbHRNaBPFC@8!z%J@X=+MeaR z=h@<}#KHqQmtta0=U)`uBPj<_4i$bXshOh+=pdCwZ?awcI!3Eug1et39C}D~K`loO=r%p8D+S6pD*hTK{}^veHx+r2nm|SkA?sP@zQl7w%ke_D2JJ`x(9gY_Mh^`{a5^XU9~|qqDlIMD zTwG+DYHMHdBmK1L+>8Oc?ZR*{AZXnK0X2XaK?P{^DLx8X)1$NItEU2gI6uQF=ZvXc zwP+?DtsFCexYWo`ByxAk^|b|*38{iPv)i3`P4ZEe%ysbun0C`&IR`r7UJbkn9}l34 zMSxI_QvGK`80|y?EE>kPQvR^9X-edR!B3UYn8gbBywMp>&3@RNTEkC=NcWtd0+V3gBcAGm48GnhP>wM}aFN zf7y=o2=u-Rnie70L6ZFzDv-^GU-)6&lv9ptZ9Cuw7Tf@Y>ysdQSECPR_-m4?jEa|& zZnNK_E=Lc4E+SV59*`X+Q@G$Fp=IE9Z(V(TxGFtlv7bYyblFf?BnMH7 zqSScX9~+tr4#f69J~En)9-bFj;^YwqbOGyOt)L$)^p#Ys?dqBquJ-05Dcm=Ln^WGh zdnna70?(k~S*U8^W}x}Z*q-K{cD^omc8B_%@GUr-HK?q8Vw@8HVfVTleUjVxMU|DV zYvVsB>!s{Evu8^tJuqa*j41Y_LKLbZyCx2uMXM@-A5C|D`uptoNOc&ffE-CpT~ZYkkt$?|^qJ0~PP7U}-bl z6^z~)q@}Jm;PMZEbrIWTZ4*e9J0U~Zt)PH}9_n<>as+?I$c|&AXVH)qI+P11)M-}? zBNU8l(!A7M`YvwWgInBp0-xk~525}GvnTS8X7baJU!%eo#9G5^mnB4EDi6^3+mF_0)u03iAq> z?@rDSO~lMu6S$0IjaZ>)On?a*;a>99to*Fbj_KL^#jc$3@ol|s5All7q#tZZQ^-A! zXq&EII#zx?>*SI11phd=c=`P3K$vQ!sq$WG7D4=k%6GB=7-U8GeAx--j(g^7R+LG3 zNX2fnG!CO`=7$c?710?zJ+G09Z{ZOIQF#{wc95&u^oZAjuhB9CjQe+3CG2|k)h06| z>y&U|dbBP<*bGhOf*>hd%!pUyv6iK15BI7m!4*uUn{tj0mE?S+2LvL0@tiGxw8G~< zVT_WhXUx00$VWqu(6URp+W+ff)zmOyEVSb-Qg2qi2=n+ZdwR-$pb$Uw$sygs0)Sr7(V*LL z_RrL=kkHE`(!{-eR~w7Cb{&k0Rz3S!9H_)0B|p_)k)Im0U5xHELq{oHt%Omfbzpcr z+sJpka<9dceqU&CJphQ7p?AVulWM9ClbMEXr=foqdr(mIDm4TSX*U$Fd|6{W9;0#V zUxr&`eKXkIkwc0or&g<6W3u0@3oY{I^aYf<`k&xfJ>M(@A39t9$K@huxjG4ujAN=Uz0Cyn)Fxyjds6l<2I33 zED{P%T)DIEn`6&?ZoMxv9>3(!*^`0AwfQ>inDQ5SRDHjm6U8G{3tZ8&pJYc}OFd&Y zFE&g8c*0eFfxpvB_74(#Ly``YL|IRP&>_sbFF&S|M3G7HRZ_bwWu2L-t=52qGF6RsyxKsv9}xwD!)Ra_ z)BR+6*{Qf-Re+ZgXsn4gsEy>y<+ z`Y-E3$gRreVnCIa3LU_FW(P*kP6KnRkaImqJ6sTd??;2HA9G|`KeZWlAANt}=ZS+~ z)%rU+mDKMYj~w4*vMrv!vAoE0;d zc(aqL3MfiLIH<-*b44VjOyX5`#%ApA!yX5XH^*CZMULB@N5FM-W>D7N08F@&%n~H( zvd`mM?Tn!pm-ikqd&6&e;0)F zzCJ~@7x0-mr42WOvB{fS3XyBLJ2U&;!~KC{e+POctm54>IuO#2ikd}Hnm_M~S-UV~ zSLcX|0`^d9`B*@u-|R{E)B{m@`0RZ_t&iBoRB0hbkwXRhMUUcLuwJcMVF^cld~7{} zRYwC0hrmHnH8kZ+>F}c}{h&#ds@JT?QTzMs<7%>~5ntTSyNi-p&u6JzF_ za#j&dQ7gb$9SAV$K;X6%2%5d1OlAX)5s6Z*`0s+BZ_`%8Z7Uy*$~^zzh+mf6VbnO8 zMqB9`^vQ}jJcp8u_HT=`FCQrKvc6Vupe30;P&0I8xQ=EiJIj{&D|I&D~XWx}>1 z=$AbQj{w%|4j(Yh+MJ3O*`O6X{BCI6PlT6XYIsJAsr5NU7>B)ZB$)2bW-IFLP7f!Yl{Hn3XovGpP)A&*g z?>OHLaHDf;%(BqNn@ z8C4p&saQ|`Q;@%JQqMWdks1aqd^tSP$+TF-czwd4Fyu;FQoQ*KVRAb=O1Oly+NCCBiL>2XocfU?4J(F&2;~8R1-r4zPUq5LN|9D`fZ%aqw0diHtN`k_f z2UbngxQ4%rbEOK;F_$S2#YW_TeltPB8h#il(DIeYH4PuE%JmVP5j@NqWssPG*ewy>WZb(t|jU!$d) zdd{Lf@a!U+D&b`V!k;Buh+4m^k-QZqyxA4!75QE&MuF-*3mVN00r`*BBHF4&MAxZB zT-te0r!Z|OkJ5G1UtVk~^zhNnwgqSu;ICbmjF#ma`PYd%N^$81qjA}d-M5XOZh!Yr z(U$dH-uqZX4Po>0(ZwwmSuH6A6*3Hl`Cd?*}T=m|LH5ct;%$##(h5exp*=y98 zMf$)YJ85Z*=o?XwjSOMoB%Z&Y{+|ExvIR3_?bwNfC$%mW9|0_>6!gCS@{q9RqWr+j z^G7OP&Yd&_#LGX28Jq0s?Xj(GPbJts+E7`^dH3zgWsmrtXmkt_lOXc*aH8;nBk8r{c0i`QeL*ft*TifugmNNw`FK|UTE zE13STbxot{mm_x5_c{F8;R-dR5r!IudxH3<07*5+8!MyNtjwk!-MZt%%gWIQE>P%Nh3c_he8S+7XVTZd!O> zIp0}2g#BJ2V>~}o>iseK_j|#NTFW_+zL67Jw_$#tbGu8AHqJ~Gk zaLeJm-m1#WrPlay|87sfpjkANpWY#fm_&GdrS93xCm}YRgy8jp`IV4@NK?|>4bnt` zfl+2|FO?m*mTr*or02!HI|ttM^bSr*vZ4Pfi9v9!E=_k-rVF>epB(|~^ zf8gGXz5CC24s7rLo50!O-pnzcnlADp^$zsb=>$aU0LSiE$6Ji2h&-ep?Fci$RI!w% z9SCnd*1)qc%b>Ss+Dt=*PA=4X6Pm3esWnHCZYo-p3v|)HmH;} zS}1!I;GB;a+sSLxImI+g+E?!DzoGa@N=qd6r|C=n{(H_~`h3gR6hwS*%HX#dK1|-9 zeR0z{89OVP@aq!QP&C(GYHK5--B#^v6gzQ3)^IBjNSa}7JE=ZY$`1!QN;wF}i@ zs(e}*r!w|6%!7Pboq4R_%p+VH zGJ8G6LH{6TZC^)BrXgwH^NLHN|CWif@Ce=|ZiSw>nmdz6oaMMGV#$gYvb5Np7^UlM zAbwSB8d=12ANuyJe?VH^%1_3o`#T20H_!)yR&&{+q{uKjn3V*ngFN}Aby=eopQXbpFt4HzR6g_|nB|0~m6+X(; z&HMAd{)wi< zZfK$;!J{A)n1hQf!9_nHO?l0fH;fX#7G?a{mM0~3h_LdAdDFMH1-KiXmXU#3w#m93x zn0SG&i$|r3hZ1kGA&i{jMSRi|=I>2uy1DnoMYgo$2G_LOyU+7YUqIIIS9z82t|ou2 zV@OFLP~w$}({R{YP-e?|MESgzbgf;N7(S6qcfe0<>*O6O3+5uGlVD53n=r7YLtsl6 z&*vpTJvV=509{YVG4`}=`e8HNKse6G3U4AgvQx9cJaTmV$LFJLrns3oM&ehCQf$vy zOvHN&8~#peb$St(nB2a(Rb_qbM#eIQ#3U$6VVjGTUzqYLi*Iq>5o?@fADk7jvb5Bk z?I>~N^@DPSDU|LiJqTO$HJ~&8Nf?q$bQFa*-iRD)bPau;Ir6n;2L`^vI)gO=lL<0S4NvP zi8OjY?%l26hU~JyYU9&tvNF1UHph7fr?}Tb!%FMB)L%hju>}QgQFPAH7dT zmHyg~$QGBa_5eEd*fO+X^{n!V0W|hGahhJm%@(5XJX&eEV(_I{B=upAeN7|_XERCH zhJH0Tvo=07>3tei<^=~j)D}2x!wGE7*lu;41Johjpw}E2^6UMWaPXu-f0ijOThK}r zC-EH$;#VUgW*$ihZOsmIK4RBBWueWKk)GhlYqz^XYij@dD9SwMto!4-oda6&R#Vr&vb#B8 zmJ6Z9W*hAPvyU-=tjRG;d=_!kYiJ|p7BQNIkq+hv@ql6r3A})eR#}hgsa)ttbXI%0 zD%iE7XCN`zsc4JjtZS`UyiZJf@;uZ*RkeNPO@`C^6XoK6P=|X9JPwwnPrUpXW_2%d zIt{*C5)TgGd3+vgZK!&^!<*mm$|tp2He^G2&jx3KMD)5(;=PCpUOul($Yh-{(L+ma zVI_Cqv4&tuq!MQ}nbOf$S05jqpaKat?M*?G^gvao!qMmP3+qCS-9>YDqh&ZeMU;qJmznFmjN{|Wj3IMt{Ni;`HVCH+`tieeK3Sa z4|CA7VP5R#%+cXmp8SEAcpd2jwRJlQ-$xvf-M8aWa=2dN&v7s8P=#Kmhrb=sX{9(+ z5PtUj{pqJa{Qlt32j&veM@LG`dMKgD*)`u6Z9$Zc^$2qK_+~7ABbyrwr{S899fJH! zq-+=wA%a)3%%DkI;C5anwwgE1r%04YW0L|fG$ceYY*YQS>{Vj+RsWHu_^{U&wbQ`W zcOdg|W?=c4z*Rl!z$75jy2_i`xOgcS&?6>^&F%4*SR)85m7mv{s6GVBP;)JQoE?S?_}<+cb` z+(VCiMY@11n_EQ+8!j%*&4H_u0ObryH4ERNst>FHtyydeM&4R2)P=x$epJ&Fs$vss z&V@>ty_;K5&Jp*YO)2%k0q>`z9jm`Ldc`}WH1YD3m+jzVKd&qxjc)40pIPr- zytksD=s>C<*KwrTaZ=s7(}b^oJUI9MDD~6PDuIb>r4R{kWK6NVaP_aqXj|Kg5a`pa zO)UHQeN}oSn+*l&Z|}FU$Y^|L0z|%ZaP<(r$0|P!DE>{ts2ZpdO=NAmnlncPQ91Zg zt5ha|1O6WIYE!)!P&V%Wc(T#wJJzHui4>*2ZpgU-zvY3)|36DqJGTWA(rgHAHZ0j3 z5Z+0S`cAS{FZZ6~*wlWk6<2_jcz;`ar9`=>PkByM6VsRFw{-}SOO+=3#UD%IN3Rz+a zFjI#7uHcaNmcppdN9~oz5r~Hd{BZdbYUt#g*sf$Oj*+BGUE3CW6z<5)IX6045XM{L zi4CW&vRI};g3W$`5s60OGq2*610?7(F$(aeQf;1iXcie?qFVxX9NAtn!PBMjXl%%3Mu`m)Q1UXNO6`dwkI_ zN@xzS6nQwb^t35nWkP1PGbyew>y2^E#} zFye3XErqyNr@-+1!0rG?(Mp=M#i!W@L*`D7l^3TIOjbNy!H^%p;-)ve=wuiDgxf=N z2*yVCVV-bZ9m6}0RyQ048~IQV3z!|MJ@oPG!fNqhc%0R+eG~R$0GaF4Ts(U6({o#q z+_#LoQrG`qX+H^H0Yk!f!9%`=aj|kCfmTeS8`3Uc90z9qB~eeq{kn@UC~m}&`AMMO3SOTsYRyF>xphdzjnCO{v683Sl$jtGKgQEcY(QKGg{ z&5cac&`zW5O347xVpEbXFrFIK?S|%|2vC90fTm|d8QYFj-8X~whB0yg(AHhGvLnmB z>2aNtOJFiav6Ic4(sk5Iu-;>A0_^IfGgwDBK|I$+&y0?Lf^uAvi+i`&tpwfaj6g4tlk#E26u$~ zF_zGZ3?Hz{uBDK9ELkUdb_5IOJLRdt9d1)ME|@=&wD}4%F&qKkPXNB8 zp*+qPoCo9*pr&xQv2n%*k&X=}1lV9;!K|I+^TO*;(VbZ8ff;XaNS$g3<#fU$8wE^3 z*jNMqC$=T3s}g3|kReZZ#QId+caNsyk?derWI9ZwA-j2EL4^045npy@ zt*X`pt?5xcO(i5_?W5VVr?Y3T!>gC#Vlq&Fqu80MXRHfv@U3}$^!|75ZNAR&@vhb4 z3O@|np;}5o52K(t8Vv(gq((dvcAhji8r~IOy#}qy!O$4gXda%Yj2B`w{jmX955+kE zJG+~&QcwlHtjdFDOg-`JL^_qzkwo41y4f!FK%vFXvDEMfT*uu<`Xh#sS*p7IqmG4+ z!DBss)S=3%1_N+_42||DvkSFu9r1S`?tZL8ItY)6Q2R_j% ze6TZ{NOO*WDAyIFgh;Z0VQV@uytP=u1I3Znj>~#9fSU>9rh--U=n-YOheSdRrW=&Y zm~T;gOXcbKS2krb^CR5%0j~BE_psvrw&4sU*ERT3_;m1q*b6aENMB}pkJJ5IOYRLn4& z?C_)z2~Q=M{YxdO*>8E|R(zH6QL25!bkkly=tl-*WgWT9pw3q|l<;6^B?7q7Nxa4i z7o5J*#OxLo1IGh??aOYi(lOv4c$Rm={>s~jCx*I-62Ypv-fAnxXLMRlPQ?36DbV)T}ByY`=-w*lm>on zw6Fh0PfW$>m&NZxKNkf@X=YpwxYeEp%$WvvLF(mH_}e*j;$-L_mhQBn1Zj|e5)l4L z!m@w`n@_B&RQRsD?oz)Ly2ugnIP{B5DVpR z%#d&G1#8)faW(LSoF>+y-4(A_+jen~ux;+U@*?%ff;*+_YRi73S&2Walu) zg&hSb$Klj!D42M5%wEaFTY#%B>F9V2lwSg`p+u2%3X7#|qOb~atXWQMa-)mH#SXy= z$GS-S@{iBhp4e{({LxnW=x*Dp89o zuWl+_L^Ql!pkB9tH;roSGt2ALS7Un|BCc|FVq_&=Vo|BFa5eVwt{7c#^&mM0m+S@HWzE<+{rsB<3k+;m9 zTkBq>_YM}I39C@TkEzyfD$D};b%U*a@r$(sN${9{A=Ld~pEr$2OOl3J4Y;0svxv%i7Rie9CWi2>8>5?Us^u;$eR9V2g z5*ov4S;0OgX3_iz*v)p%yBP$#8RmSd(f zyn(NCWtP=>6k#eWBE}w`B89Qd2WGc8XR`MOdpf@DJ{}k)Z6DeFh{WXuP{BFY8RQ;G zWdPB(WS=KwgqB{%6-TdnnKa$lj=&S0RUann)-g)YAWiRV66R+YbO2}e>K?)Vo+kUF z852E})_58+n2!Tc+L|%o3qb-N)5li9_xIq%7)Rr^P0s{lBSQ&@if^`Bs|N3?;Y4fQy4bM15WDgcW?IX3L-8;Hz*p3r~T9ON$d0B~_va0_Wl>3e8!y>8WY;cKAOie|{w%GG7k&k(Q<$=-xbdnOD8fyL?q4wI|y_DW^M%_A%;*H#YBVc%4H; zoe=+W(`BxB@1%cRvTRq`Nt;#Ni5Qu9ZSJ+e5gsvmfUg{qsKm~I<5&P@%r3q8A&Ojb zfHOF=&7#G>^e4KTnAdwT*uMiE#elyv2QpHxq5lV^!=Nx+V$DE>+o*cCCb)6^nXZED z^3kx4sG*=%`Gd;p+_wjOcBuSoqly~+|HwevxqNH&N&okz(RKBOJNn-pT%Bo_8bYZI zA%mZQG(uk0R140wqU`8bw)O+h`yUnWW1Y7@x2=s`EfB!s2P}y12aBJuBtEs)JVY&i z3}yOBay-(cfEcPenkDxzEspHpXI4tf@)q_4@4C1D^qBBKQv2~+myWgnzaq{(D#>gM z;651jno5sl+#2dj2aWvMom-kkztU2-mI)h%q%Un)LvQ? zWaOjN$g#5WQRdr9QkIYLg@z^|eBV7ED6$rR@v-(f-`RVgefHV=mk|EM`$Da0^PBd= z-q-RUe2xxxAoNrYLs9H^8=Y+i4_1vBG%Ramafy_--#!x3k=M{-s+s`~48Z>xfN7iP zrp=*Z(3)X0=Q=V$)k&>@T^W^!kiQ1@46>zm*mZtZcpGk<@~4jG_pCF%fjKLCfAPy% zv;KbP>20v$uq{L;vS<(7%FE=t$R+K*rvZ08bX3oCY z0DD9S=0b9-T+o8&)nU_RMAcP6btIyyALYj$g5qEFy}S^7q*ZZpS;vjOsnXD5VPyNm zn1rbOvrgUxJ5z6M5)TdiyI2}lYg)HNxG8o#Y_>S!5fqjEhv^Q;GS|jy0++AI1!B#$ zV&A9MsK~m5LiuqgwEAzXFnybhAW(5_#D6oQMAB!%8A9`Wc1TgkDm(Yz3VE(|-0Ocz zrnbI3v(BzSd@5}9O?yx4wc+%`J~yupksE{bL-VWLJx|xhRc_!$Uc}>7(}OU-Vi*T) zLwCaXwnZRnPt*DIw9M5BRH&SyE`RBZWNMU;N5dGyR6c=(RKz5#%Rx%4d|SGRZd z-)U6TWAm4HHRpd$-n|yzcEe;p?O@@7V7J_u(T4a2ZhisjO4o@RSg~W(+sk`C7lbvY zIT!6KB5cV8F&Sf5wyE${9tD0Nwxp`PG}{axQc^)+YNRv&5R&;>+wX#><1a^uga^{+ zy=lzntXI7$d#;yMgm414+6RARY#0i)8i@%?wEu9WfF9vZE;|shq0=ep{HEdbnyyuEc4Fs-yum- zzqBWV2N$7N1t8jV20)-6=k*dfnXPB~XmoJ8Mlg|82c7isJ1$iQu=jgj-c%G}8T-p) z3^2%nNjt6u*7|hLwMe4maQvGmm@9kVMKn#5{p%fMwIJV1hvgD@;vAj(q|~u2;an{z z6*S5snVLNT;=zVM;u4+2^Vxd;@c?)NsgmK`?OL2#tBR?kB}%G~kq94VT;q9<-Bv}f zpOTrE37lR(a=V?j_K!y~!-wn@&4PP zGpc5)TH)vApf6+BtRmc@J8pvZGs4i010ED-!z1s_9TM zbEGTZph=He-DXTtRi^G~=_RQ@JS6I?41vHo6~lp03!{^FKmf_R)8#UXddx=T6zv-Q z`|LaXiPn0!-8I*}gYJUG3!Q{%mbHPm?v=RgZpve=D>>jKtbVF|l`fym-juZX;tPKU zQkbs({@k|TSTrD|UE{$hkpzw5@j$m0@K#S0RS>5wJi&DPy9rmFTne@N+0 zuZIJ@{!t5W6e^4)RVC2(i^Vow+n&}c)0RsWpGfGxoBCYd@*V3K&g<_{h(v=ujXr+4 z96XsTu-I4UDu$-+;XRK+-?xfpEdg$YwG>?JStS@y)zrBaLVflER)s`Zwxs2n-!V6N zXRYK`Q6MG6Z4x)*7A(IT5p+->waSttdIwcDjokb1yRcKCc-h0a^6TnDpW^t7CwK>^ z>FE78NRLy_fo^gy6Jv@}EKukG*p@_ZeF4i)b8P@=h<=ym?Gfp=!#XSOlvBp~m|ZvY ztu!4z;E;;`2}Cr_b2iKY6u^_Z|Il{2IBZ^op3OCA0dPeBS`Mnfmui&<(MvhLWPVmu z|H+^iW}03Q5EO!q84~y3N7l`~pB-icyXKRu{?id8Lv8Uq`s52KKn`HE?hS>kk>)S< z`7BS8AxiE*aU|AXXPyqDuohGSpsO`ii|4J-_x(t4vIg`3LN8)$o5)x@ItbBEIj%qN zuXr~^*+0y^BnWJx`{oAbZZ@D;5LiQ7u3Z5bl>E;{9SC+sL)<(EfzRqi9|6;&^xuc< z=0<(UNTx&i`67?AQ3S+S+Is*9G1Lq=-qJ|+t8Toc9PogNd=a1Jt=-A_tmP>S1En1$ znVZOM!LM2!1ywCZi?o7(#~Z2IGSP8xn)H*R OACFz0JNZ8cocuq5LDX~r diff --git a/test_cases/ribir_widgets/checkbox/tests/checked_with_default_by_wgpu.png b/test_cases/ribir_widgets/checkbox/tests/checked_with_default_by_wgpu.png index a7b3d041a985ca2576a39f501a421b6be4b3aae0..17c19c631f77706b0f59ff1c0d00bad2499a6eee 100644 GIT binary patch delta 405 zcmV;G0c!q~1+D{-BYy#PNkl_-)s0_6HwuU4L^|(evZdITzik|w_phb>-F2!!|&@Y=>U!Ubj`QL!JsQbsQkfMn1mlK{>^A_!tKJi}MohaP0T~@04zeXJ&CSiFW%ulvT<3k#!plp`%l*%Ttn^8m z8@Bl8{r*$`c|-o?FZjezdha9S`|tn$MAzOfud!yhob_bC#H_HzmCLN&&j?fgA69yg z(O|9HzwW@F`x}9pSpNIn|0a9?+lf$$?#qAfZ1=|bN5l8( z`hV;S6^i@bTJM|t{Q2#Dk8l5+!2eso?!n)C^YeeTmj6TTAN!(DN28hCi7q&>9HNIMTe2di2?W;cXHDsE8ithmh z)x6W&YmaaLyk7tsG(Y+wfl}GPU$OuD^LkB_wQisH%TN6;z2eV(ho}G9wEmk1Ktc>0 g%=OGvkowSHQy2efn>#}WFtsswy85}Sb4q9e0OW{r6#xJL diff --git a/test_cases/ribir_widgets/checkbox/tests/indeterminate_with_default_by_wgpu.png b/test_cases/ribir_widgets/checkbox/tests/indeterminate_with_default_by_wgpu.png index cbf092282eb5942acec645dbe5678f3e2d60c46f..f52ebd31107cb73b19a6fb7d063b04604b5704cd 100644 GIT binary patch delta 315 zcmZo*xyCd>rC!$4#WAFU@$J+`u0sYqF3WvB*xyY*`(H%lN{^`6F}GYgQ1E2O|HrQ;2ysV> z3JEH@b-^r6c27|3(ZTvOp3XTh*Qsx}a-YT-q#gTjn|XizmbZKNT>Ec!J3njb zHJ3|8!98cz7Vi9(E41?Mhl@<+oie^Ezq5rBuM07GG`md5=$ICI-Kwh2L#Sort0+sC zPCbmjA>af7=Xaj L)z4*}Q$iB}!LNg^ literal 512 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2o;fFdp}GaSW+oeEWcLf{N!P6;Gk= zRWom;0XwS?QBB zH*E3G`~9c>^M?G(U+{^c^xj9t_uv2hiLSj}USrL0IqS)OiCJNbE0iv)F zK;3Y?m5g=|{@$Da-}S;4sk6pcE01rH`ni48XTF9^(@*g|sK(k%&;Q+*|GZw&WUbq0 zAE5K(6Qg?nh%f%cApfE6{rUev8Bx8@>g~1un+ISx>Cb(Kr~lcgAoW0=@m-s3)t=k) RoPjaR;OXk;vd$@?2>{cW89D#} diff --git a/test_cases/ribir_widgets/checkbox/tests/unchecked_with_default_by_wgpu.png b/test_cases/ribir_widgets/checkbox/tests/unchecked_with_default_by_wgpu.png index ed05a369d52369dbc5ab1857fa9d94dbfab2b673..d5ad9403f15b10217d7b44e7681b9719de01581f 100644 GIT binary patch delta 284 zcmX@Yyp3ssay`RePZ!6K3dXn7-*Yt^@EqCwFyXzW{OP^V6Pj~H{}%jERarLgDa(Hr zpQ@elQ@?$x+`E5i^W$5N{KeddYhv{-7e~!Y+Wyh-7?;JS#4O(L(VZO;y+8cJ+owdF zS~jtxBg1t#imE?Q&!TwyRAo6 f3BkU~J5f}A(^*ZP*jpRC7=Xaj)z4*}Q$iB}L|Av} literal 452 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2o;fFm`*oIEGX(zJ0(rLB(^DilaP0T~@04zeXJ&CSiFW%ulvT<3k#!plp`%l*%Ttn^8m z8@Bl8{r*$`c|-o?FZjezdha9S`|tn$MAzOfud!yhob_bC#H_HzmCLN&&j?fgA69yg z(O|9HzwW@F`x{}J>Y1nhmtOJbzQfc1Y+C=#12Cj)rsx0e%YR<4XtLJrvk%Y;`NXK+ zKjMo&G013aP)1bmvwC~1dhr-bn$!b%#z!Jb6$=9UrvhV#!PC{xWt~$(6971! B_YD95 diff --git a/test_cases/storybook/storybook_with_default_by_wgpu.png b/test_cases/storybook/storybook_with_default_by_wgpu.png index 8286c8048091a6180706d58ca346d0a8d6945fd8..cf6ac28b6084155ed0310a4d75185282dfd8cbd7 100644 GIT binary patch literal 36153 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 Cc~xKl diff --git a/test_cases/storybook/storybook_with_material_by_wgpu.png b/test_cases/storybook/storybook_with_material_by_wgpu.png index 98c52840b4beb35703e74f89127eeed37f50259b..70e31a7e7359bc2259aa0436d4b181a4769f9522 100644 GIT binary patch literal 37724 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 diff --git a/test_cases/todos/todos_with_default_by_wgpu.png b/test_cases/todos/todos_with_default_by_wgpu.png index 0c8a017de5b9de47e7b2b8480d80157a1f4f8d87..7808708a252007e17d157794590f4d1d1af04262 100644 GIT binary patch literal 12245 zcmeHNdvp`kx*sS|6d@uY7b}fdk5)v82-xH4V^B~IqC`c^y@%3(E~v_~0V|}TNrrb1 zQV8;@iX!||kL%pET-SSb zt>&M}?3vm7d;GrN_kDY2$CHcZkG}qv>oE))z2MLDp2n~tdogV2=8+@7NYt+8F--CH zf_V=;lRu=VWyqdCEZF;p1vl+H_GbC~dGl7STJ`J_@YBK{bN<)(y$YvRso*NBRz3RY zyshPj-n`!R_$rllomQ)K!6hGm?(nlm%es!09zWG}j7YjiwQODe64kPhW`2h>Rx0#- zkcGz9)svGCp!-UXM{Gx5f%kz6;`(Rcv+x47yH*-g#TuWAPnz~?PwFH7F;QPt9JpEI z58JDk+A|2=N%Tu1wtis$tGjKQ+boX6nLPYLztA~P{=9sT^yT4<$9|i}f3wDw5NmS9 z{wSFwM$Y+pi-@c6$WgqCF;KF#q*m{=c{1FdWo!exS;0OnuqJVT)bM?Y;dU!uYyE<( zcIwZk1ooGt?}{4gRfZ`tf}Pth3HR`&mu88Jez3CQyh*sM^cg5-uKhlm-K}vJ*q!CR z)B383`YA}soo$ygd&cQHRK`cl78Cb|vVDqDcZ=e@%1~b%@D<|wC4ZR{s)$eIv9ByG zQ3qYf7W0=)!Z3<4;Ack#hO2$=^M1KFMa-55XIQ>iY!1v4?u`GHe7j-HGs37?{Hd7R zKbhLi`QMQlOv@)~=cIunyW(QNtgdG;Qp3%ZU%t}*Tx`v*ujOSDYxg>$-G$T^Tq5VR#S z^=|yH`WNDCx&8lzEq@U(e=2E25ne&_ckr6fXq;b^6}t7}=eN`$Y9-#46?o;X;=3BQ zRoiyY!1!iqd{k(SA|BbSkJ^Y-JUA0~5hXU=AzM4d23KZ@t~K_0jc<=j*?n!^21$`->2L#3 z#1(5Y1+5_n5njdhP(p?oBnJOxKCBUw$yg)lB%R-V=4IiP?JHWuPbr~?^8CFq*Q*XR zlCgqx!LMu?jvh1uF-)Zb9sO7~2{CM=HTJ!xt-;undQwek`Ljy?Mp@q( zoPVCLl<^~J{sLWDUeTB~#P`o*AO{0CUmT!Bz2GIT)A&YM&rPlPdg>a|CGv{a(e9RY zy7yHZhGS-bQ6u}QBKnd8NU=AX;hALfuT+QY^|1!xPRx~G^RoWCV#92;7*bzX=@PCg zd@obsWli)nDp1F6l;z6>pG@3Jafhjn6WQIfxpx(j`>|}0Pj)D|{Yoi!ekG4x*ULbH zM)`w@0&nFSJ9CWYXa%rJswVWTW=thWvx#}(s}J@v0fqRf{@WbGJ+2-I8TPb-zu(*l zeV^cikmJ8m#_pB%R~>k0F@8>K^fG}5G{J**I_gMK#pnQpVOGfQXf336h>0KYi7Z5z zxe4C0dueyYx14A9zy(=+Rpv6U!`!Ib-MNEOEz!&rNXA^@T7iR4D zdRIF-li0Vc-2KUsi-nl)O$(>vA?%pw33YU|v3@r59j7K(Lnym z*bCEiM}WxMmS%U)VYXc<+|U`EgomHUDGYu7QZD z0!2AZHH8H03>-;p23h!^hFfLtSn8OB;XtR#3dZe>L6;2MhZ5aN94H7o*W|V+%pUzKe$33o}oXJs-Gb1 z+oon$>MwZpe^Nw0RgA7w89N&MOUY1L6J28L%Hdk&LiPixsaXCwn?BLq`LcV5CGw#h z6g$vc6BWGy7(<{e5$}|TFW{#UI}x{5kzb>rem4UBlYBWIIv8*WzN@&PthjZXj?oh8 z>C3+NY~wEBu{;c#+{f#$6dNaCNlBx6K}uzMiacKggYkgC`7?NpjIT7UAqlq78GIfO zC#2if-pVrh7q{fLj>~L4$^kR|NA`GRH=ChRJH!VnmdEt9CHkQlNOab-CHmSFAMIbK zW}bkf>3dI7bCUzh$H-*5BPlpH1+!m0=a}Vk*^J%Vp&yr(RmF_q9HQvOm$E{H3zF8F z`cV?+%jb7ct%!AxAh*E3i1LJK?pQNbys$XT(g8^5*yjf^doYbmpu@TJS>ixWy5|80 zSmrIO7_qh+yLRNXn9DWrGGqU{CJ-~{YOr;!x%V8O|_ps=O07+a{u=1RQNQO52^`OFT+{HJNYjy{3OgGa_Z9- z@ZaB*+;?Ot8?lOyC0~9>c50iF-D>KDp6BSkPvp_D`mZJ$9*jm4F|e$!uY{`A5{xY{ z$CQ8e%nQj^jSGME=tO98p{!%i2p%qy~Tt2772JIgW{f6g(pnWJMDhDJ6%r01}zaf+_A3X2a2K zz_!-b$?n$XG7570T2d+YDcgd$xRB*t;!Rj)>=M3%_$V>s^34*HS3pugaFH??Bno|H zqFu(g3*_Qn)QG^&2Gyu;(12}2h1({#7^4np#4z27@G3Hd2GK)>`_yDIU>3pQ*ql_pSj~9Bl=Z8P4wY zxP#6Io78#r=SCk*t&X>hMr*RtO(cg$hOSNs3=g*O1P*zV^G3 zEOkATRI$>rsOgKz!je&tLS#LPSmH)$8$#UV;7Z)1H)@0rwH~Ugm}rx;S7>o{_INpC z#xJxAZ7DDsb(7i;dRD|BP8TDi0N;uE1iS4_n-fFhfvLUr|=WdH2ke%DO z*Jwily6WOTws?TOmWX#r`yE0d2XD>Z1I^HKi0EoQNg-8gG|Y497Zu`J+;@o*8`5pa zxMhZ>0^yH^(bdNzsdGW2FYTQ?*3Wl;>PO4J+)BZlr93lUG9Xz6PuJEj!TNV)gvEw4 zGIE?)_>^w!;R^3fa0ziy&hfMwVmne8y6|L|I2+X7dB`!ePbw{V=|ShUO&h#gs<*NJ zl`csufK($3|G$twZDVwCWWN!E82%kO$n@1Kg)6XK|$zl%5zl!64n1(!!qqOm=!DY z%Dv_SuE@n^IeHo$o2=1Onl=>?O3lxe`^U;pCplWX*VYq7h){EkonBooEedqq(u(>+ z!KVB7**27F+shsq2K%AfSZ3c`{4G$VnY^8cG;L*u%Z0{SmcSIbt1gu~ONlWLyI;vY zZf@L3vd_axJ4=uq4Tw#Q(PQzYkOfmg;Tz7Nf(bm>LL0C6!XjL;1a%gs+TJ$Rk#6x% zvYd|zeM<3dHFrSmO)<6=o}@rU>wKmABby&}IJd?1%F)+&15LeU-t5elgv_Gu&C3=0^{YW{>QA`^5YSzr^4Oc zoDVv+r0hK^eRZ*SW~OJK?nwMEXIkI9t|0(glF?ZqsyjxB70789%o$D>SS&baY!x_~ z0@seb9@^AK8530*vdyK_3m|gLEW-r)?H9_XL%FvmC;Q=cPZJHYtc$a|qR$C4pa9l)pE($nByD93=>TTI#sxi2$b7Eot8@lGw@22 z$SVD(2OL7Y2TiMq{$10uDQ<0V7}lIWX|_R8kp$ZPZqUb;bFkgO`VFl1Tw6VVg&@#! zC+czHJG%ftmM_JGX9NpURtggsI>R=qHq<5N)r-kA(7Fc9+qeb=2-X4`nU`7DdRGP$ z7$Wzr&^Ou)30NE(2|olvxxtfaoGp*MBd-JXvNJDOm+EiI=BwrBCK|r-2E-ex#Klx} z7XeDQ-jDRq9*DnDR_eETAdXpNqPX}7#;%?L9~@n#Z9X9h!!+e77%Xe*#p!XKeRI&Nv20Mqm|bj?}A@5m#7m?wb}z*9i_mFzyM;sB@{qh^{L zVgx(uuSH{5EW(2pMyEcXFz}ab$Y7ezCF&~+*Vc>oqA)_G)3uf?vG#FTd%YfAd6%^5 z0^>-*)oA#aavj`V$4?d2igV+}P4B93&j5cKIbW`kAh*@WzXx)f-5v?tliyk=zs`kEa5{bF()22gJQ zW_@#mVVs&-N1go=}Zj4k%N+l(ticJ8rVAmvNrZnxuv4{{9uW9%iYv)|N@2Ktw zDMp?Bn;1W!xp;zu?^%A?M)6Pgx!boG4D3n~?$u=>i%Y@wP}#k2YE%?Q7n*JA%G8@>NG zz#6nEe1rPif73b$DfIGY&{6$wWPht)1PtPI5T}ED`kVi7XE00$!*noA2gCHY{dwUa yOAWHrAWIFh)F4a27mB~pZ@_;MNfW~klrMMR^I*jk@VP#=;E_f1jz7G7^M3=-)@-2w literal 12114 zcmeHNdvsG(x=$%sv;z?hLNaPGM7gq!xePUhFX~<&8s|y z+Tqbr9u+DL3`?t2TD_=gX_`|WZJ-ZRz*@17lQwMwh4$ppBquqqyZ26;;#}AKF?YEZ zcdh21lkA+c_qV_A_x--#x0Ae=SEf$5Z|Z#lfndV&|5);>KoIevKrm*<_4vLeXuxbAFXYcYG(-b)Z!sa0xw?s^E`g#9V?3)^0^xlrIbkC5erivS++U5ecGZ#A;idRwOIsI26 z_KLwqo5@_NfVq*+jV1hA>|(TgoXq(N;}Y>R_;iuy8N;PjMecdrFI)yzI z+6IeexIhj9~uyi^3xlo`rJeCi>7yKXR5zk{UBqA|8lJvkK*$1)R!yde^8Z8Z{fUdRc5D3456zpU0uSpzqNN6(jk)2SBuMMWDh!XTmw% z31aSDxN6ddP7iy_5Xm>=ZqM1O}`L^9uz)oJ{E4lv8EwQ}t}qIaJ%n~-~wUxS`Ua6>3|D0E^eOZqpE%wwSiMOw5jSWxV|B4YEByq`<# zr()Y7X}C^e!5Gsc1lLbATA2o`hv;|c1}rG{2pcg8`#r~qK-D@g-jZA8$#?SYq04X1 z;pY*K%e=6-Fw#Ij!6hR&?qGa!J|1UVaSLv_e#Sw;Z+366@&66iv47i|;gGpoaaNtg zxg@r6=s_KA)aRFQBn>@VdbaCAMRnYnmaB2@e298}*RurhG4EP5~&b;pI*A~{y)A#{v@C&QsbBT7UpYAK; zUXAyCnd@GNbGPuC7ENQKbKxfs>Vn1ku{mYzPx7u7U4LS^j8HHaCCvTSen=52;OwZ5 z{`QW0b3|OH$R4G$r7DNV@(^om4;PgPn+M}pD0e0**Qeh+l)jzTat{5ya_2o|^)suk z&fJO%d1rplEu5QKLCh`6jFb7^kTtgGS?L((-py^b1={OUk5|SY5-_)|+!(_54pGB) zxMvZ2g;b6|!nVhJqh5KsCHp1wjXmbyhY%y-v2bzWzi5JW@j|M*WrV17ib{DFz+g? zKBOeXmn7`>RyPERsj=1cIACe=avEQWz$Z;ElT)3FE&h;-Gi03n)%O_MHnOm$XF=l5C_`we2 zpx;5dixxj1KpCB@{n6r_KseKY?9g=<{Et+z|ZS(37jD z)YseE1h!d(dz!M)s7lcF73+36e5)|;nRTY}dYGnJK+_hWkRX=hGsp73N6E9N4|-g6 z95`QM?@1qcLx2L3KG2iCJGQr-V6_$Ry_FwZvse_o9~39{YT20AH*P$~0<4&iWj?IZ z>41m!im2_PPGE=yT&YO|et>1A?zTmj<9Kd=Bp)x#ZknYzpP-qC9Jr@zv)&g=eJiJD z3(|qG$&&;QN(45bLk>{~C4sSAvU%W^8II+H=+oLX-X8*6)$1W9&wP!WhBzTA2#Z*l9vnp1@P_!=kfsF-x7=I30QW3# zW{|#>j8s)SH^UB=DG3D2_}>rsA)9DgjoMhgpbBCe5bGc$)^%P!{*eA8%w&sTyd>dH}KfQbNYCIpCY@cET>KkZ;8;guin8!(QWJjBt)G|S;v=fMdn+gU7$=Ztv(nR!+<`ov(LIB%K*wtey#<7C;##9q0hQ(%KV2=<$foaL*+{|R`p4yg!(?@RRa?E2VZN8JPZNP- zM17bk){lERAVd^{$|App;927Gum=U`6G)2GNN2N*{X_!<;dF_%?;172+#>HQqS^%Q z)y-e7IbDA9)3^YzA*CaDn#iMBKr#pVc_O#R(Y-t>~wZ7y_@P@E&{@7C3-K+P;y|^QrQD`pKf!pHnetdG*&( zxt@SAD;d$QPn+K?%|84KwF(NM0II!QiN+(TiW7*K=dkK5y4R4MSkx-!FJjJX1mBX> zB-N0uXDX8I71}m6_k1qBg_{`?G*O^AR+&5t@JP~^0dy2toFEJJeeKE(x}S+KhpS^w)4EhOdso8--u4*>Cbz;`77}a6->HxhGOHkZ2lL*gCf~nD}Tp z?B#~X{vfg?jelZn=rCZX*4fGk zgoBNkH-nLTkp-e9AxWt}4j+%S!JSgZV2^={(gkV$XlxDISu=ibsB_{^q)_hwKJ*Pu z5{k%@t>|C^Z%E|7uXOD&xmv3pBA8WVt>%gg`r9-InS#DOBJyPoxg~TCz|TRqM!V5& zVbuI;yHWj22i2dxH)_Nbhi@`L`;v_LYOBbxRo|G#ZwhO7*-fal%KK!FI30D2!ruQ^ zhaGG&jTCSG^pHOjkpM0|d*AV)zC(X1RPEuF1OO_miw zF}>lTW$AwpsdFIuD^DkcuB~p-wkNuvC<2(J z-WPU)dg?9j!)lFsTH%?Cc|1wR5&FzHav7-C1@5-#I{=l7dUT@T2~lIQrp}V(X-ssr zr3@~{jzTTr=q;3wu_4`_A?CXBdw@L43SfKd_$-3nrw4U!;52A+TKyWU& z`CA#~h6X|jb7U;=!#|%`Ss7ohuO%m0gHg?p8x_T%VA`Px7hWe~ZN0B;^Bc$e( zRt~Hg@J|xC9yN8wnd7CbBO5xQqwjRb$Fvr7K8dg~notc@coyE!4a&l_yz#o;&ANm1 z8&Al+tI11fi(u;~+sMV(;K@L(ocVKxIq*dKN3nXB#l2KESixY6w@wbnuA)zG90|-K z6b&o2SJJzExQo$&k0fRN}GE^_ zUmZ5xxzOL1B^Eg&M73G;*)sYG1T9p2(J>BC3ll)g>;(XAZxc_aVDaSUn_Y4E(L%X7 zFSZw`@k~@$M>^>l2KNyLTiC-__?aeY*P(RJxi(UbyCeeTCoP&eK%TkMNpFS;bWsyR zi6H0z5!}tc9kvB}Rj{>vTZ{W0!Z#tQDOGbZ*ST9xWkZN1>g-bFOHEy|CMl87#8~@l zWXxAkRn6wD_cNHcil7ph%Vb9#N=qaLVH>Y^R~p}K=4TV0WULx_IhpW;bOACS4YhHD z68>W=Z4&p6gjlfEn(TK+h@2bNd9iCW&Z~!^7BB{zgzTFcI6JZQEJ%lqVGyZ~lWZ;4 z3FCIFs$(C>KV#>1vqP=Ri3;wuQvZe0fPcGXyYhqq4Wls`cE`h0hD!BoNy5G0n+5iNVsSg4n$;uV{VH5K)_!KdKPY;%0d=yu?-c)Yk6ZBpOUyXkE(0@~)3dGuF;d4766aUTg z>RI2x$YK!HAL6sMzn3Omrd^xq7lEH%nfqbxN_(xW6j zO46e>>W;4V?)k&vXo(&z(W51Lv_y}V=>J2B<|h5oGAs2Q)$IZQl@}~ux^hYBi?8qa EAKf7yaU2e3!iwK6dxOIXJHp|N$R0BqobhRd42QE| z)rw^aZ%V>?O<{+hTXE#M6^|ddaH2GE*|JTWHodhL{E6Y8=f*$c?*q8BKmd2yv}yVB zWgnL2ofv2M-6nxJLo7}*z%75b;nZ8_O1du;7G3GSKu((@Sf6ostzf-dlxPW_D-860 zxelGnxT~9S9Nkw~A1%n)WuDX_;FPNPZE7r;$&n8e5Ax^@HZ>c zgNm}_AJNl99#(q4Qd)RAR~GG&IFBl8^~8f{2iA6o*VnO>-*K)uXp&K9oyG?RME7R8 z-o~Uvb-|A%#wN|pWT)2V%hxPOBAjdJdkX(^QC)D$Fv+!1)e+9KSImca^kFXj zeDG3<@%7l2>R5S0;~#?(y&ujVB)SWTPi;)S&9aC7O6mO{0a73;bMKwOH zEz7wCcdxA8Frb-uR{xkQ6WpQs|N2JSw2JD zTmuZBn1&L7oqn9%@QC&=id>%}<=H7AmvN#T`*Iw|h4d^Yxj9XLN>-gCdxA5#;={dT z7X5GI-=w=2vIi$*q`L7#9y1tbMmZK}opW{JJ430!P8pPBNH<4zNX}rU$B(ZdFAs%s zuI6TwW)|?Vt>%%)DT$|Rk}MnXfuoYuErWWpNAgmyd?NCGp=v|P&%XSdi_2Y@X((}A zF+(94k(sBKu59(ljYmVfJ(34;c*v+xU6T}&U%}w4Mk&=CGIE@H(ADj`Qm@=!j>0E& ziWt=Pq1{h!dEs-GBXUd;8T`SVu1fOXF*r{d=`ziNp%A|s7g8<(Z3Qx97s8TIjO8ms zyX+|$4CsfT_pwQL8+iwU3kncJ@3z*?d31@=mxlBuYX+V3p><$iV%*0{UkPSKVZ6He zgNB1lv%&uo3fA;exHx=pC^HK4N4;KnJA}X!ejK)bY6Sj!YK2?)pt6-tq>LTY260)EF;1u~GJ6GG5W87buKl1a3HOZS~f6vCuWQ6VsIJ0V9##0sSLcD(| zUb{`*QoojU6J0sPF+Cm_yDsC&@|-f4!cKmV4)CdUqbhV)lQmUMuIASEd9C?s$pN)> zSLkDesY&NArB5hnX`qlXaRbk*TXsYU{EfZ}j9DG!DUP;_+@pl{^O~w;O+1Ptw3wb` z3f8%GhR{9?=|Do_iFQ^06p>><^E`?-QUy|RHhLOD@r||YE4lO614-I@r5-Vf=PSRP z8eCTA<~i_+NLfX$6Rs}%p+NpD?n%e%L6FSdewXEA1NHb-HZgeE7|xDES9N+d=@Yva z<1SYmj(N{uH=%&(zFslM4gh)&ME%hwfXd_0{;u@<-_9a@YEpsuZ!1k))}ACG(08@0 zPHX~ed5T^2rIgy+YYfDzv~69Lnc0%hu75zGe{BtJx{3>8AvE#p?ZqBW@>rJ|8n6Vxw@T62C5D z2W*b3|IxS=2?W1&LV+F%D3&*R+R*nO8uIJMJGUqY_M@~>F}12{zt%KfdkhblamxjE zMlh5N!9&5AzzpQ^$SPzj=pN>Vfr*2f-86uYt|iEFy=r4cEMXS7UK93PnhD>GI8bX~ zk{&=6xn4k6B3%qpiF8Jj*I#H{S6Ou+Qksgn7AmV3=ci2rHpXfi@&`WPQ@imaD{}`V zsmg&Z%1RV8aPwwc1HU(&0#V1~@PV*<3gRqZ$?hb|Us4+h9+ILY-AXrR)~RI?e@NFM zuR!Bonoypsweajv_`*bW%a{7&NxW54(v1IlhW#B&6M%cVXwvpu-jqCLSSyiK*uzAjCo`!z7 zuJZpNa@uq7kFC}T0HVo@kVp5=N=9FtOmoX~h^|D}Y^BqI zJRNJ4O*T>og*PMRw{u~P+s}Icl;nLo#rKVHcWl<>*v?&j#pYG{&SM3R6q`F$Gq6=R z8Wpl>nu;Dr0@gn%P8~yK8`@_HowJIK1@a%PcIXz)NuKynG~ZF9fzkkFRTWtpeW?>z z`wJPBLq5j7gZnPy*OSZc@;2l}c5EgG^oOs(QnKCAJ|9Vss1hUyCtpfCiO3is^kfKY zkXEoR#8DM$`y|Y9sX4P}8(fk9A zL~o<%8=>z7$?3G|v`r!DM`f~ld!t`4F%GK)`4xtJp$=*LHn*vm!GP$9Et1qwDI-Lh-d1 zx&4seqNO5Z`kZiKWH1y$YzBP1`XL<45Du?pZIc)tx`&;lbxhNJjy6ga+D9p?R%$y| z+5t+v%m6H%!JcS!&NGHJ#oa=A3;_GwZ`+9>3c^-_XpDA(uH_?8=-C}XoSz)dCIkh9 zh0EB!6z@M*;ve8~s9RkBzoqK@6H}hR2R0fF06@+3E{u9_(a|Q6Zg+(DQxW|N(Ycw( zhtN9uU6S1?WU7R1Jgqs8%9VjaGbM&T5))P~COv9rosQYcd?)fx#waC9H;J%_h#COWN`ZUzEjM)!K7K9Y1;)9$hp zf>suUg|ijGdU{aATvv5==82Fg5Y+K4Yxw!V?qhc*#5(dHUT8eoCN$sq>L@al(N~6F zLlAxj^WK&LqmF|}gxX9RIBWwl6GUcNL#&)9q>l@4=zASLi4M^Iyu6WtaJAuplAiw$wL7iLD~~x6Z2lm zVT`G;wS&q9yBq0dEuE)32vM$+Sl<}zOs>W-i$wINw(=k+)I;-w#EMw<6$mtbp4Q7z#mnAj1vayi4 zvV@UYV;fx_%ibwnF#`a&Y7XHNO+Lj?v~q|z#Ir|%`Ok7c3N3ji&cgEK{_Wm83%FJ=Y{5hFr6mFo~%17@Jk(6$hs|Zu|y%TIGO-Z?+|C`#n@4 ze&wKb;4Rz08=AYNWlwN$*GRH5#!ng3?~-FsxPTtpt?EaV+a2TEixJTQ#ortcv9l4; zXCua-z9ldr$oq>%Je)MSu|C)$P-J%PfvyMfxzH8?@hj;q3j>Rh<_`f_bq4f!!O2w) zir)*HgWF?+ZXiDsQElRO_NnaPZ3XD-9101EJsUJK*NzGbIS{NXuc7gZ8$)dh#dZZn zd2Fx?^GEo;76&E;@ZciKrJ*inY>;yn2DO<#bm6~kZ(@+u7?BgTH|`N3ec*&`P=}wx zgzfL??;g$q+mGU1o2fs?$Y=gVaZ`F4qw94hG3lPIY4B;MtLVL4>#jdgb}>EaIm(M= zMi+UNZDxMoQTjADlZ>LPb6kwf-$*V7osX{G&j$tUv)IgYjn{%{JEv2s|F>eFXil4OZ z@Vgrw7mZ%`IyYuJpzW%oDsg6VR2Lu(lO=Zr@>%&!9>T_T!h+Xqi#NK~OLN4ML@tx*+$Mjw4N!41CwTGsq7Uz2;3eRS-IM+G=z`b`mPMl=TV**NF z2iN=5K+Hwz;jy@zR4IJLNu4W_GRI+_H06z>`Tb9TGD-SlU4UiuK;pRoam#6Cw|iV} zA$t>aI?O9dYCl#PqLrHKTQyTTKXQ)S5BT~qmG?r7r6k@mJITC}-#J-IRbsUQ`Q6;@ zx*nD85Sl`SXt~y%tjjM9q|0jyWFx?Xs_=41v>l*&M#tR>8AM~v(#}P4@idi9PT-H- z3>;n>dUx}?W)}ApmD0H~qespgV)c+oAwz&{Z$F^3T)fAB(RzXPYuo2)KTG60+v3zJ z)+_1+twSSi=d$m%b{$N?c7pbl+j+3H%T0S#>?Y7w5U0okA)f*`?gy>GSVX^|xYt6` za%477;AudN@R}^GwbTiS?O!-ZZkv6gs4k?+I`^|PDe?h~)_b}?w-ZVx0j~_4e^TJL zxzaFCP2BwzNo_>PIe}SNpbfi$Y`{qHvRe`IaB)jUtRS9? z=6$-FN-XeuZFiyen26dd8f}`LB%O+y#nAbPE55!g!0jYied3{@#OsjQ3<@))>t$he zg#1>b9dOnR&C@nVl+7>_#Fm_=S7285rEJ!!rIK4e>fM+=cr5Z7d**7}4@f&^V)dYz zi*!{d@=vmJlBBf_)MpBM8MwigrSnA4fZeSq@(Rv4**nqXEyLI3mMVC(FG045BC4vBC#N04QNUQc)XF!Ww(MJt{M#DJ3AT0oPEOVKh)MJ5mk< z0xhyq4l{!<1;ENG1S^c1*QC$dX zU{0Y^g#iy05^4$Z8~}!B*ONj=6-p?MkaZhxpd@R<0u_kY{#Dp1Nku5cpfEt6Ph-4i zW6W?^LLEz@!&BUAg=2SmWCrml6S85e&7aWfiZ>p&Y_Ea?7iYeWF49!;H1h;y)n77r ze+|~Z_<`^p$64vlPq* z4hnskA)`$IsCG-w#b(L_GlzhV=+pY5P|F{2CE)F$0F}=y@){gqknw)AEre=OT@cE` zDCl#oCyV?iq=aQgYuh&Id&t0C?`egpsI;%Mq)eZs!418jt!;XlU|wQ#eyMfIsjC*t z+?X?$l<`=h#+ay^6XUCmMQ?Q6_^%$Br8=MW7UFC~pme>aSkFeQ`R*NWdV=&o)xRi) z-N4L+17*Y_e!<20Cw@`)KcErAlEPT~sotm#I||0%FW}Ypu%m_@H5{iu`(LOGr|EE- z4yWmGng)Nk^>h6l-7rcGqtq};4WraBN`W6X4})}Q*!4GG=KUZ4*8Bf;jnd;IyggrU X`zHOH3h)mGoE5LFT2}PxyV?Hn&|mR#1_Kf|#^TW}qk) zDg@-CV4*=->`D)f96!>JGy{|p3bX;STU<&fZQ7=^w3CmfnaNCM?)$#6Da-D;=X&n( z9zCc1XEHOH_kBKo&-47AXVOi7UX(U|+>~(=iDdlz=jOdAkwkqWk&Mb8a|^h_Sya44 zk`$ajZ|+Ols6I#3w)^IPa^L*h3J>qCPMbGx*|KG?ybS&{@Go%gm-u@RF0E9;U6w6- z_StzKR2T0ZXMcW~QnOa0QP|;@&%d$%m4lT%hs(;VdJYqD4=6L%HodIO@T=20!`I4$ zzP~L&*VZpbqGHT-dOC=0#^9I6&J@y@#|E_C9mX>@{92+1YulRA-|@7p<6uSDBsYKVrLL9Y zJ1_*NygF!{>qWc|hFRbh$Vyh+@G_mtwhX}*!}{E+?97<|?0OCgJ5JL(nq0~mMI zcrwP@ktp9~2whUNKa*{X*Ld&2yf0X0X+MWU{1~pbJ{0Loij-90&P}g z+sr*F{S`Z;>^8$F#}~y}9mUqGE3{e3SKgaO4J=gEhV`?rcMxAi7K&mbmJ$~YeRK4& zcuh+^Fnn4z3IOr$UE(b_2*aoA{~2S#5gBmyxOK%@Rom6UFHCLWn2EjX--GLaA17|g z0ad^utLo~r z!{{t~a2lf?fNJn9_R!-X1nBxTdBx_O1t?h{eO2C%(o#Q$j%lkzICbIuHWntL%-bQx zs&`s_ZxHx+7I>;=ad-0t|Bgyya-%#?sp-hBgxvw7T&cS zFA*P*GaKY*R+_IIe_8b7?r37CZBGAK5Y)$Gb<@?JJJfcFBOhFh_h905Wr+4g_7PQK zA?*|S88vn3mN`kA5#Fd?5QgK>)35@pX(AgBEhs|q(Hgo!8C<2`o40M>}E^(A~qsT)LOJ)efMWNZ7())G`-Ze~9+F#nlV2$bVYevdtG6w*}(2mblhdH*aD1V=zy|e{Bf-Q(1N^Fvx57^9wrn($&~)U z+s45sc%WRo1QR{R6N^i{FUfii%JyAWllvixyILxJ{EC{+bnEEvDyej9X9|MrrCS`( zDM*QTN2B73iZ4pdn3>LE1>(;4dGH$rH!qXjrP^L5xRBM$^TPprPd-tKun$vQ z4y*(c1QXYwK#Q#?MWSq%Uei?Ui-1=G!?>YTcgE&}9&XY37V4bI_+zSpXH<=SX6krh z&kotur8#}g`1saq4Xt~kA^*uav$*6`UQKhg=O3of6jVjj?psW@X#M##cZ<~#BP%S@ z)fYK%7*4ei3sI~3Tb?LkPA2-GG!~%jEwm?rJ_8_9>}|t@hxiqtYj)vIwf`0Rqm`N4 zjG-T~r*D(QCiRDr2MNv%PFSl7>>5^U1E!0?JQK0A&>Li3wY8UXpH7qQYsUMU9p9?B z$Cw|Dp@;gbX&EjC#BH%1F;>UdTBueg_pNF}^c356Qsiu&?HGFx5)U{)-2j$J@q(=L zCBFb@W!)(koN`bFgybN?z40@z8sP@XkrYlG`4*8QlcfV&D5goG8-lwyg?3M%8w+bL zE!ED2{A9B^w=CJUzN&n+R(raz9f?z4q#KKzmW(@-9pIkR?fyu77nL?e=m)!ZKgHIx z&?{TJX6E45{$A@R2IeC}C-n|N7(p!1?f55>J8hd>gAkzmWcp8IJ62MI8QNXSocj~r znq7Q!$%8qs4=Zv});B2!RQG4fgGRcxl})SYc|s49KIN{ZPl}Un68{7tGXYg{AJ+D? zeBdBLmaKEJtRw=qO17(*p}moi6DPNNXHx5p>|U%Bfw9b-oA$1+1!-0ot6?jRT=sB{ z7OOz;Dmp*{m|WRISP_~Ji-9phJo*lh24;$eWa=bgPGa)y?f0v^_cI_4?iN55*(yG- zW_Q!;RsuQ>)9GF#`@((MWQ10-V*9X~RXs#?I9kT$i&Mkl0E>&-^BESr0JHb7!;&@w zB0{?`q0Pe|lk&6n*28cZtv_ql#iLXP?qH+8B8g*3Lc7TwPk9z1kc6Qxaa5CBI@_rd z9>aUhc=WnZXf*CkBsQw~Q>HE)k~#+T7k`mNQoCiUocmh7@xIL4Z(#Q*0g11clfsk8 zf?y>{zm-dP=ZK}T*YZ1iU$3=)#uJ+UyH%kkmHp9$*J#ZB6wI6_vCsvh8|L3j%Ls8D z9W1Avg(Tyv=n*%Dtz0I_7hgkWAWs3vDcATKl94G;ax;3TV|HNon~niCwhFSbJ)onT z4m-Ms?e=8C*X#ww%xP&#ubCzf9+V$X!#fIAlW|!UC3fMO!U?k~%A~UPX|mmR&SLNQ zbVZ}vl-={ge3T>TP%8#18R!DfOG9tTKz;bISZ&?J=>aAmf+j*wL&mosQn)Ua_iH(~ z^tn-v<;0+E+sQR~R6wslJQp#G_PUH#!1{K?)*W4HV?dsn@L)#ON#F<0)AFb3JWRyl zYB+YCI`nsw3uXmvvqrB*W`(t+4Y2uwoVkF7kc9ws6yVKW``IqFFdNES%&pC^De=xC zcMR!1Yk{=`b4OvPYy_X?c_V4?&dfakpGlntkx_s?Ta1xi+fRHTMkB6eAC3=|`(|U^ z0&B+t*fGu_u)#+831XL8_)_ECKy^iHv#^0prsHQVXJ)3JH|ws_9wqT!Tp+JZlQ+G! zqffOjI=B~O;_$0Bu|ymf4%O_NlyeM`;DAkm!0CO8nm7r?FQ!k$cxS4Dd3+Og<(6a7 z`t}v>hfS+v?0w5|hnhKriJ(&ST*=&=oWsSs4vYVBlQILO?ZGDy2a#<_*1Q%L z_K*}W#vCfNs?L3xmk|CmvuCc6nPNFt)^cJE2L+TdEAe%zpoerFY3)0t-C-uO%Yzy) zp?DJ+0I*NL{A{xLL$&8ABxE$%Aa$S6oh=d)kO5)<9^A=G{Mg3f`Nc#uC7`=Zb{sGUg^HpwEoM%tn<5u?-Hyip6cx;K^pko0*+=WbQHN znv2>OwhDEu$vs}qFXFMEMl8hNkdBqeio^1?$hs$~HWcOTN@sQ_h2{u7hAbzW6LF1^ zT~D?Z;XGa0Lv0C*EzUwulc%8JSCMM=d&+4Nx@VVMPOrJV!1D?{_@abAC*{YJ15U#J zvUpE~nv>r{(z&XMycUNu`x*KFIL8T_?|% zj_|iW3L9B|ESYzwc*GyWhue>bn~iN@84iXI4?TM1Sv1G-W7lB$VZ@&nf$ePA(}`h% zX$qpgrRvt<8{rCU3agnr0k)jTz2tdB)yaCeb9PhA2SfS*X{qa=^#3^uyP+Ec1G=9# zwA-u@4j9`mS_igVlFfFl$2(HQd@9sb>Rv>1t1Vq|vVAVpdp+m&%Lf)M@yly%`j$lB zTx>u{^=_BCST<-9m*F6-?&tJO0WnKG@T|#RgkM#9^2k86WvY?cgw?LFoGJtTmS?c# zy^C9P7nAkl5xoVZ^v~9wGV9LhTuA$Dx^szMcY%DTDR?-k6E${O%_<_E3La4b__06GnX|x6AP8=JUiyhCUHl%|1s=GUZ;7>w?xD6U3+8n$)b5}GYXdjn>uJ{!PksTa16spg0cR9-N&=^K_04L*4$8%Fu& zBw@Gt4eruDpgXtO#JrKfo-XjUScP74uL?8>E>N2{r4cNue0r zW7i5ZOT0TvJr7~NO#m(zK?9J82C+!oh_n)S4aIHX;UJV|OXxExmfFjs+)!>yZHi@P zM3vP|g&#Y_qeEWd^xo*utz6M7uzyBK{A=Qz4>^5{P5-bW_xr_6kq&|o5s$c<3%zTa z#0)?-jK|8XJu^JC2jF&M%i88EOZ=&5$}Rp*N-$5ehfTp3t!;7EyVjMacD}7UXVcvq zxt`Dss6A=`D=B}o%4WuUo58YwKw|rRfEupVHM(^7AjCnmdGal`Jd0d904;pC9N#B8 z#|TEQU7a)IJ3|Be(-9C-lZn}!)V1B9dmOfG=cZxoDxoa3bGpL0RMs^Ke1U{CrUSP6 zl|8Bt&xnhS{9JjhaA-0*jz+dn@iWzRgGZkL!;4{fI%WMkat;`{3PslpYkOf%$26>w zF!!3st%#l+7Hh14V{Aoe*dXhkrkx9h)7Je?o53gE3KD8aKIm784X8{bkdt+hSmoyM zZPHF)&jmoj-ATdElblk~tzZJd-D>v9tcteW^4tk83D}UrIR{XR*&**<&OqHkZE!|} z8jU=M1+tCjl)AcDAL!SPOLQ={P#~e$0<-52{~30|oCw5Hp)iNVSBG=MVp-=TZIe=e zzXYa($?K2}VJ^zC2XxBaXD6dvk!N*PdneHD@0R%QJ?ItBClcrFUlDKD751cAeM!uA znvdxZ4CTPPC2^==ar1x5f+{Dn@b^1PP87DoXozAU^kIbDwGLQA+O?&%+YjDAM6wxM z$@S+U(wWd5>@_*lNq=u;kK6{w6xk%`%N357RsLPt0|A{~bF%~boNc8;bCD9^oc19L z4J_;4Aj_}ruPSy8CeR)s)r^vZ`1nx4gKubNU-#x>nBn|7%aRbwZZ!!{3tofTB^ILU zjcOY4`1P-mo*7UQf|S=(YqJfaLg=xJ>%;F6-bwO#lTMMNKK<>#)%w4d@}ZY{zx?~R z5lP_-(BHs|(h*0EIBEo^zxv-ZjD+b(n2v<$NSKCy=JWFgI3uhN&I*YU()(NdA>T;h y8!3Dvg>R(rjTFA0{o-b%?*H2AK0ocbZ+A$lUW Date: Tue, 26 Sep 2023 16:13:41 +0800 Subject: [PATCH 7/7] =?UTF-8?q?fix(gpu):=20=F0=9F=90=9B=20naga=20compile?= =?UTF-8?q?=20wgsl=20failed=20in=20macos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shaders/linear_gradient_triangles.wgsl | 36 +++++------ .../shaders/radial_gradient_triangles.wgsl | 60 +++++++++---------- 2 files changed, 44 insertions(+), 52 deletions(-) diff --git a/gpu/src/wgpu_impl/shaders/linear_gradient_triangles.wgsl b/gpu/src/wgpu_impl/shaders/linear_gradient_triangles.wgsl index aff24c66e..65f0aea83 100644 --- a/gpu/src/wgpu_impl/shaders/linear_gradient_triangles.wgsl +++ b/gpu/src/wgpu_impl/shaders/linear_gradient_triangles.wgsl @@ -59,16 +59,29 @@ var textures: binding_array>; @group(3) @binding(1) var samplers: binding_array; -fn calc_mask_alpha(pos: vec2, mask_idx: i32) -> f32 { + +fn calc_offset(x: f32, y: f32, x_0: f32, y_0: f32, x_1: f32, y_1: f32) -> f32 { + let dx_0 = x - x_0; + let dy_0 = y - y_0; + let dx_1_0 = x_1 - x_0; + let dy_1_0 = y_1 - y_0; + + return (dx_0 * dx_1_0 + dy_0 * dy_1_0) / (dx_1_0 * dx_1_0 + dy_1_0 * dy_1_0); +} + +@fragment +fn fs_main(input: FragInput) -> @location(0) vec4 { + let prim = prims[input.prim_idx]; + let pos = prim.transform * vec3(input.pos.xy, 1.); var alpha = 1.; - var mask_idx = mask_idx; + var mask_idx = prim.mask_head; loop { if mask_idx < 0 { break; } let mask = mask_layers[u32(mask_idx)]; - var mask_pos = mask.transform * vec3(pos, 1.); + var mask_pos = mask.transform * vec3(input.pos.xy, 1.); if any(mask_pos < mask.min) || any(mask.max < mask_pos) { alpha = 0.; break; @@ -87,23 +100,6 @@ fn calc_mask_alpha(pos: vec2, mask_idx: i32) -> f32 { } mask_idx = mask.prev_mask_idx; } - return alpha; -} - -fn calc_offset(x: f32, y: f32, x_0: f32, y_0: f32, x_1: f32, y_1: f32) -> f32 { - let dx_0 = x - x_0; - let dy_0 = y - y_0; - let dx_1_0 = x_1 - x_0; - let dy_1_0 = y_1 - y_0; - - return (dx_0 * dx_1_0 + dy_0 * dy_1_0) / (dx_1_0 * dx_1_0 + dy_1_0 * dy_1_0); -} - -@fragment -fn fs_main(input: FragInput) -> @location(0) vec4 { - let prim = prims[input.prim_idx]; - let pos = prim.transform * vec3(input.pos.xy, 1.); - let alpha = calc_mask_alpha(input.pos.xy, prim.mask_head); if (prim.start_position.x == prim.end_position.x && prim.start_position.y == prim.end_position.y) { diff --git a/gpu/src/wgpu_impl/shaders/radial_gradient_triangles.wgsl b/gpu/src/wgpu_impl/shaders/radial_gradient_triangles.wgsl index cb1e82578..80abc8583 100644 --- a/gpu/src/wgpu_impl/shaders/radial_gradient_triangles.wgsl +++ b/gpu/src/wgpu_impl/shaders/radial_gradient_triangles.wgsl @@ -62,37 +62,6 @@ var textures: binding_array>; var samplers: binding_array; -fn calc_mask_alpha(pos: vec2, mask_idx: i32) -> f32 { - var alpha = 1.; - var mask_idx = mask_idx; - loop { - if mask_idx < 0 { - break; - } - let mask = mask_layers[u32(mask_idx)]; - - var mask_pos = mask.transform * vec3(pos, 1.); - if any(mask_pos < mask.min) || any(mask.max < mask_pos) { - alpha = 0.; - break; - } - - let mask_tex_idx = mask.mask_tex_idx; - let texture = textures[mask_tex_idx]; - let s_sampler = samplers[mask_tex_idx]; - - let tex_size = textureDimensions(texture); - mask_pos = mask_pos / vec2(f32(tex_size.x), f32(tex_size.y)); - let a = textureSampleLevel(texture, s_sampler, mask_pos, 0.).r; - alpha = alpha * a; - if alpha == 0. { - break; - } - mask_idx = mask.prev_mask_idx; - } - return alpha; -} - // input the center and radius of the circles, return the tag of resolvable (1. mean resolvable and -1. unresolvable) and the offset if tag is resolvable. fn calc_offset(x: f32, y: f32, x_0: f32, y_0: f32, r_0: f32, x_1: f32, y_1: f32, r_1: f32) -> vec2 { @@ -159,7 +128,34 @@ fn calc_offset(x: f32, y: f32, x_0: f32, y_0: f32, r_0: f32, x_1: f32, y_1: f32, fn fs_main(input: FragInput) -> @location(0) vec4 { let prim = prims[input.prim_idx]; let pos = prim.transform * vec3(input.pos.xy, 1.); - let alpha = calc_mask_alpha(input.pos.xy, prim.mask_head); + + var alpha = 1.; + var mask_idx = prim.mask_head; + loop { + if mask_idx < 0 { + break; + } + let mask = mask_layers[u32(mask_idx)]; + + var mask_pos = mask.transform * vec3(input.pos.xy, 1.); + if any(mask_pos < mask.min) || any(mask.max < mask_pos) { + alpha = 0.; + break; + } + + let mask_tex_idx = mask.mask_tex_idx; + let texture = textures[mask_tex_idx]; + let s_sampler = samplers[mask_tex_idx]; + + let tex_size = textureDimensions(texture); + mask_pos = mask_pos / vec2(f32(tex_size.x), f32(tex_size.y)); + let a = textureSampleLevel(texture, s_sampler, mask_pos, 0.).r; + alpha = alpha * a; + if alpha == 0. { + break; + } + mask_idx = mask.prev_mask_idx; + } let res = calc_offset(pos.x, pos.y, prim.start_center.x, prim.start_center.y, prim.start_radius, prim.end_center.x, prim.end_center.y, prim.end_radius);