From 9ab7c47dc7d834ee73bc068f9f34eea4d6946436 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Tue, 31 Dec 2019 21:35:42 +0100 Subject: [PATCH] Add `border_width` and `border_color` to `Quad` --- core/src/color.rs | 8 ++++ examples/custom_widget.rs | 2 + examples/tour.rs | 2 +- wgpu/src/primitive.rs | 4 ++ wgpu/src/quad.rs | 17 +++++++- wgpu/src/renderer.rs | 9 +++- wgpu/src/renderer/widget/button.rs | 8 +++- wgpu/src/renderer/widget/checkbox.rs | 44 ++++++++----------- wgpu/src/renderer/widget/container.rs | 4 +- wgpu/src/renderer/widget/radio.rs | 46 ++++++++------------ wgpu/src/renderer/widget/scrollable.rs | 8 +++- wgpu/src/renderer/widget/slider.rs | 58 +++++++++++-------------- wgpu/src/renderer/widget/text_input.rs | 33 +++++--------- wgpu/src/shader/quad.frag | 51 ++++++++++++++++++---- wgpu/src/shader/quad.frag.spv | Bin 3044 -> 4212 bytes wgpu/src/shader/quad.vert | 14 ++++-- wgpu/src/shader/quad.vert.spv | Bin 3020 -> 3372 bytes 17 files changed, 180 insertions(+), 128 deletions(-) diff --git a/core/src/color.rs b/core/src/color.rs index c28e784f..d72651d9 100644 --- a/core/src/color.rs +++ b/core/src/color.rs @@ -25,6 +25,14 @@ impl Color { a: 1.0, }; + /// A color with no opacity. + pub const TRANSPARENT: Color = Color { + r: 0.0, + g: 0.0, + b: 0.0, + a: 0.0, + }; + /// Creates a [`Color`] from its RGB8 components. /// /// [`Color`]: struct.Color.html diff --git a/examples/custom_widget.rs b/examples/custom_widget.rs index ca562ead..1f51ee54 100644 --- a/examples/custom_widget.rs +++ b/examples/custom_widget.rs @@ -63,6 +63,8 @@ mod circle { bounds: layout.bounds(), background: Background::Color(Color::BLACK), border_radius: self.radius, + border_width: 0, + border_color: Color::TRANSPARENT, }, MouseCursor::OutOfBounds, ) diff --git a/examples/tour.rs b/examples/tour.rs index c7f866e8..d006d397 100644 --- a/examples/tour.rs +++ b/examples/tour.rs @@ -27,7 +27,7 @@ impl Sandbox for Tour { scroll: scrollable::State::new(), back_button: button::State::new(), next_button: button::State::new(), - debug: false, + debug: true, } } diff --git a/wgpu/src/primitive.rs b/wgpu/src/primitive.rs index 6c61f800..f4609151 100644 --- a/wgpu/src/primitive.rs +++ b/wgpu/src/primitive.rs @@ -38,6 +38,10 @@ pub enum Primitive { background: Background, /// The border radius of the quad border_radius: u16, + /// The border width of the quad + border_width: u16, + /// The border color of the quad + border_color: Color, }, /// An image primitive Image { diff --git a/wgpu/src/quad.rs b/wgpu/src/quad.rs index c292dec3..fe3276a3 100644 --- a/wgpu/src/quad.rs +++ b/wgpu/src/quad.rs @@ -125,9 +125,19 @@ impl Pipeline { }, wgpu::VertexAttributeDescriptor { shader_location: 4, - format: wgpu::VertexFormat::Float, + format: wgpu::VertexFormat::Float4, offset: 4 * (2 + 2 + 4), }, + wgpu::VertexAttributeDescriptor { + shader_location: 5, + format: wgpu::VertexFormat::Float, + offset: 4 * (2 + 2 + 4 + 4), + }, + wgpu::VertexAttributeDescriptor { + shader_location: 6, + format: wgpu::VertexFormat::Float, + offset: 4 * (2 + 2 + 4 + 4 + 1), + }, ], }, ], @@ -233,7 +243,8 @@ impl Pipeline { bounds.x, bounds.y, bounds.width, - bounds.height, + // TODO: Address anti-aliasing adjustments properly + bounds.height + 1, ); render_pass.draw_indexed( @@ -277,7 +288,9 @@ pub struct Quad { pub position: [f32; 2], pub scale: [f32; 2], pub color: [f32; 4], + pub border_color: [f32; 4], pub border_radius: f32, + pub border_width: f32, } impl Quad { diff --git a/wgpu/src/renderer.rs b/wgpu/src/renderer.rs index 1b143d90..efda046b 100644 --- a/wgpu/src/renderer.rs +++ b/wgpu/src/renderer.rs @@ -223,6 +223,8 @@ impl Renderer { bounds, background, border_radius, + border_width, + border_color, } => { // TODO: Move some of this computations to the GPU (?) layer.quads.push(Quad { @@ -235,6 +237,8 @@ impl Renderer { Background::Color(color) => color.into_linear(), }, border_radius: *border_radius as f32, + border_width: *border_width as f32, + border_color: border_color.into_linear(), }); } Primitive::Image { handle, bounds } => { @@ -470,11 +474,12 @@ fn explain_layout( color: Color, primitives: &mut Vec, ) { - // TODO: Draw borders instead primitives.push(Primitive::Quad { bounds: layout.bounds(), - background: Background::Color([0.0, 0.0, 0.0, 0.05].into()), + background: Background::Color(Color::TRANSPARENT), border_radius: 0, + border_width: 1, + border_color: [0.6, 0.6, 0.6, 0.5].into(), }); for child in layout.children() { diff --git a/wgpu/src/renderer/widget/button.rs b/wgpu/src/renderer/widget/button.rs index 4fbd90d7..d00a43a5 100644 --- a/wgpu/src/renderer/widget/button.rs +++ b/wgpu/src/renderer/widget/button.rs @@ -1,5 +1,7 @@ use crate::{button::StyleSheet, defaults, Defaults, Primitive, Renderer}; -use iced_native::{Background, Element, Layout, MouseCursor, Point, Rectangle}; +use iced_native::{ + Background, Color, Element, Layout, MouseCursor, Point, Rectangle, +}; impl iced_native::button::Renderer for Renderer { type Style = Box; @@ -57,11 +59,15 @@ impl iced_native::button::Renderer for Renderer { [0.0, 0.0, 0.0, 0.5].into(), ), border_radius: styling.border_radius, + border_width: 0, + border_color: Color::TRANSPARENT, }, Primitive::Quad { bounds, background, border_radius: styling.border_radius, + border_width: 0, + border_color: Color::TRANSPARENT, }, content, ], diff --git a/wgpu/src/renderer/widget/checkbox.rs b/wgpu/src/renderer/widget/checkbox.rs index 54b4b1cc..1ed27ff7 100644 --- a/wgpu/src/renderer/widget/checkbox.rs +++ b/wgpu/src/renderer/widget/checkbox.rs @@ -1,6 +1,6 @@ use crate::{Primitive, Renderer}; use iced_native::{ - checkbox, Background, HorizontalAlignment, MouseCursor, Rectangle, + checkbox, Background, Color, HorizontalAlignment, MouseCursor, Rectangle, VerticalAlignment, }; @@ -18,30 +18,20 @@ impl checkbox::Renderer for Renderer { is_mouse_over: bool, (label, _): Self::Output, ) -> Self::Output { - let (checkbox_border, checkbox_box) = ( - Primitive::Quad { - bounds, - background: Background::Color([0.6, 0.6, 0.6].into()), - border_radius: 6, - }, - Primitive::Quad { - bounds: Rectangle { - x: bounds.x + 1.0, - y: bounds.y + 1.0, - width: bounds.width - 2.0, - height: bounds.height - 2.0, - }, - background: Background::Color( - if is_mouse_over { - [0.90, 0.90, 0.90] - } else { - [0.95, 0.95, 0.95] - } - .into(), - ), - border_radius: 5, - }, - ); + let checkbox = Primitive::Quad { + bounds, + background: Background::Color( + if is_mouse_over { + [0.90, 0.90, 0.90] + } else { + [0.95, 0.95, 0.95] + } + .into(), + ), + border_radius: 5, + border_width: 1, + border_color: Color::from_rgb(0.6, 0.6, 0.6), + }; ( Primitive::Group { @@ -56,9 +46,9 @@ impl checkbox::Renderer for Renderer { vertical_alignment: VerticalAlignment::Center, }; - vec![checkbox_border, checkbox_box, check, label] + vec![checkbox, check, label] } else { - vec![checkbox_border, checkbox_box, label] + vec![checkbox, label] }, }, if is_mouse_over { diff --git a/wgpu/src/renderer/widget/container.rs b/wgpu/src/renderer/widget/container.rs index 29c709f8..18908571 100644 --- a/wgpu/src/renderer/widget/container.rs +++ b/wgpu/src/renderer/widget/container.rs @@ -1,5 +1,5 @@ use crate::{container, defaults, Defaults, Primitive, Renderer}; -use iced_native::{Element, Layout, Point, Rectangle}; +use iced_native::{Color, Element, Layout, Point, Rectangle}; impl iced_native::container::Renderer for Renderer { type Style = Box; @@ -31,6 +31,8 @@ impl iced_native::container::Renderer for Renderer { bounds, background, border_radius: style.border_radius, + border_width: 0, + border_color: Color::TRANSPARENT, }; ( diff --git a/wgpu/src/renderer/widget/radio.rs b/wgpu/src/renderer/widget/radio.rs index 3c00a4c2..aa1dbadc 100644 --- a/wgpu/src/renderer/widget/radio.rs +++ b/wgpu/src/renderer/widget/radio.rs @@ -1,5 +1,5 @@ use crate::{Primitive, Renderer}; -use iced_native::{radio, Background, MouseCursor, Rectangle}; +use iced_native::{radio, Background, Color, MouseCursor, Rectangle}; const SIZE: f32 = 28.0; const DOT_SIZE: f32 = SIZE / 2.0; @@ -16,30 +16,20 @@ impl radio::Renderer for Renderer { is_mouse_over: bool, (label, _): Self::Output, ) -> Self::Output { - let (radio_border, radio_box) = ( - Primitive::Quad { - bounds, - background: Background::Color([0.6, 0.6, 0.6].into()), - border_radius: (SIZE / 2.0) as u16, - }, - Primitive::Quad { - bounds: Rectangle { - x: bounds.x + 1.0, - y: bounds.y + 1.0, - width: bounds.width - 2.0, - height: bounds.height - 2.0, - }, - background: Background::Color( - if is_mouse_over { - [0.90, 0.90, 0.90] - } else { - [0.95, 0.95, 0.95] - } - .into(), - ), - border_radius: (SIZE / 2.0 - 1.0) as u16, - }, - ); + let radio = Primitive::Quad { + bounds, + background: Background::Color( + if is_mouse_over { + [0.90, 0.90, 0.90] + } else { + [0.95, 0.95, 0.95] + } + .into(), + ), + border_radius: (SIZE / 2.0) as u16, + border_width: 1, + border_color: Color::from_rgb(0.6, 0.6, 0.6), + }; ( Primitive::Group { @@ -53,11 +43,13 @@ impl radio::Renderer for Renderer { }, background: Background::Color([0.3, 0.3, 0.3].into()), border_radius: (DOT_SIZE / 2.0) as u16, + border_width: 0, + border_color: Color::TRANSPARENT, }; - vec![radio_border, radio_box, radio_circle, label] + vec![radio, radio_circle, label] } else { - vec![radio_border, radio_box, label] + vec![radio, label] }, }, if is_mouse_over { diff --git a/wgpu/src/renderer/widget/scrollable.rs b/wgpu/src/renderer/widget/scrollable.rs index 6ef57185..42a4a743 100644 --- a/wgpu/src/renderer/widget/scrollable.rs +++ b/wgpu/src/renderer/widget/scrollable.rs @@ -1,5 +1,7 @@ use crate::{Primitive, Renderer}; -use iced_native::{scrollable, Background, MouseCursor, Rectangle, Vector}; +use iced_native::{ + scrollable, Background, Color, MouseCursor, Rectangle, Vector, +}; const SCROLLBAR_WIDTH: u16 = 10; const SCROLLBAR_MARGIN: u16 = 2; @@ -68,6 +70,8 @@ impl scrollable::Renderer for Renderer { [0.0, 0.0, 0.0, 0.7].into(), ), border_radius: 5, + border_width: 0, + border_color: Color::TRANSPARENT, }; if is_mouse_over_scrollbar || state.is_scroller_grabbed() { @@ -83,6 +87,8 @@ impl scrollable::Renderer for Renderer { [0.0, 0.0, 0.0, 0.3].into(), ), border_radius: 5, + border_width: 0, + border_color: Color::TRANSPARENT, }; Primitive::Group { diff --git a/wgpu/src/renderer/widget/slider.rs b/wgpu/src/renderer/widget/slider.rs index c73a4e56..386decb5 100644 --- a/wgpu/src/renderer/widget/slider.rs +++ b/wgpu/src/renderer/widget/slider.rs @@ -29,8 +29,10 @@ impl slider::Renderer for Renderer { width: bounds.width, height: 2.0, }, - background: Color::from_rgb(0.6, 0.6, 0.6).into(), + background: Background::Color([0.6, 0.6, 0.6, 0.5].into()), border_radius: 0, + border_width: 0, + border_color: Color::TRANSPARENT, }, Primitive::Quad { bounds: Rectangle { @@ -41,6 +43,8 @@ impl slider::Renderer for Renderer { }, background: Background::Color(Color::WHITE), border_radius: 0, + border_width: 0, + border_color: Color::TRANSPARENT, }, ); @@ -49,41 +53,31 @@ impl slider::Renderer for Renderer { let handle_offset = (bounds.width - HANDLE_WIDTH) * ((value - range_start) / (range_end - range_start).max(1.0)); - let (handle_border, handle) = ( - Primitive::Quad { - bounds: Rectangle { - x: bounds.x + handle_offset.round() - 1.0, - y: rail_y - HANDLE_HEIGHT / 2.0 - 1.0, - width: HANDLE_WIDTH + 2.0, - height: HANDLE_HEIGHT + 2.0, - }, - background: Color::from_rgb(0.6, 0.6, 0.6).into(), - border_radius: 5, + let handle = Primitive::Quad { + bounds: Rectangle { + x: bounds.x + handle_offset.round(), + y: rail_y - HANDLE_HEIGHT / 2.0, + width: HANDLE_WIDTH, + height: HANDLE_HEIGHT, }, - Primitive::Quad { - bounds: Rectangle { - x: bounds.x + handle_offset.round(), - y: rail_y - HANDLE_HEIGHT / 2.0, - width: HANDLE_WIDTH, - height: HANDLE_HEIGHT, - }, - background: Background::Color( - if is_dragging { - [0.85, 0.85, 0.85] - } else if is_mouse_over { - [0.90, 0.90, 0.90] - } else { - [0.95, 0.95, 0.95] - } - .into(), - ), - border_radius: 4, - }, - ); + background: Background::Color( + if is_dragging { + [0.85, 0.85, 0.85] + } else if is_mouse_over { + [0.90, 0.90, 0.90] + } else { + [0.95, 0.95, 0.95] + } + .into(), + ), + border_radius: 4, + border_width: 1, + border_color: Color::from_rgb(0.6, 0.6, 0.6), + }; ( Primitive::Group { - primitives: vec![rail_top, rail_bottom, handle_border, handle], + primitives: vec![rail_top, rail_bottom, handle], }, if is_dragging { MouseCursor::Grabbing diff --git a/wgpu/src/renderer/widget/text_input.rs b/wgpu/src/renderer/widget/text_input.rs index 929f94db..cf3a31ab 100644 --- a/wgpu/src/renderer/widget/text_input.rs +++ b/wgpu/src/renderer/widget/text_input.rs @@ -64,28 +64,17 @@ impl text_input::Renderer for Renderer { ) -> Self::Output { let is_mouse_over = bounds.contains(cursor_position); - let border = Primitive::Quad { - bounds, - background: Background::Color( - if is_mouse_over || state.is_focused() { - [0.5, 0.5, 0.5] - } else { - [0.7, 0.7, 0.7] - } - .into(), - ), - border_radius: 5, - }; - let input = Primitive::Quad { - bounds: Rectangle { - x: bounds.x + 1.0, - y: bounds.y + 1.0, - width: bounds.width - 2.0, - height: bounds.height - 2.0, - }, + bounds, background: Background::Color(Color::WHITE), - border_radius: 4, + border_radius: 5, + border_width: 1, + border_color: if is_mouse_over || state.is_focused() { + [0.5, 0.5, 0.5] + } else { + [0.7, 0.7, 0.7] + } + .into(), }; let text = value.to_string(); @@ -130,6 +119,8 @@ impl text_input::Renderer for Renderer { }, background: Background::Color(Color::BLACK), border_radius: 0, + border_width: 0, + border_color: Color::TRANSPARENT, }; ( @@ -150,7 +141,7 @@ impl text_input::Renderer for Renderer { ( Primitive::Group { - primitives: vec![border, input, contents], + primitives: vec![input, contents], }, if is_mouse_over { MouseCursor::Text diff --git a/wgpu/src/shader/quad.frag b/wgpu/src/shader/quad.frag index 2ee77e71..ad1af1ad 100644 --- a/wgpu/src/shader/quad.frag +++ b/wgpu/src/shader/quad.frag @@ -1,14 +1,17 @@ #version 450 layout(location = 0) in vec4 v_Color; -layout(location = 1) in vec2 v_Pos; -layout(location = 2) in vec2 v_Scale; -layout(location = 3) in float v_BorderRadius; +layout(location = 1) in vec4 v_BorderColor; +layout(location = 2) in vec2 v_Pos; +layout(location = 3) in vec2 v_Scale; +layout(location = 4) in float v_BorderRadius; +layout(location = 5) in float v_BorderWidth; layout(location = 0) out vec4 o_Color; -float rounded(in vec2 frag_coord, in vec2 position, in vec2 size, float radius, float s) +float distance(in vec2 frag_coord, in vec2 position, in vec2 size, float radius) { + // TODO: Try SDF approach: https://www.shadertoy.com/view/wd3XRN vec2 inner_size = size - vec2(radius, radius) * 2.0; vec2 top_left = position + vec2(radius, radius); vec2 bottom_right = top_left + inner_size; @@ -21,13 +24,43 @@ float rounded(in vec2 frag_coord, in vec2 position, in vec2 size, float radius, max(max(top_left_distance.y, bottom_right_distance.y), 0) ); - float d = sqrt(distance.x * distance.x + distance.y * distance.y); - - return 1.0 - smoothstep(radius - s, radius + s, d); + return sqrt(distance.x * distance.x + distance.y * distance.y); } void main() { - float radius_alpha = rounded(gl_FragCoord.xy, v_Pos, v_Scale, v_BorderRadius, 0.5); + vec4 mixed_color; - o_Color = vec4(v_Color.xyz, v_Color.w * radius_alpha); + // TODO: Remove branching (?) + if(v_BorderWidth > 0) { + float internal_border = max(v_BorderRadius - v_BorderWidth, 0); + + float internal_distance = distance( + gl_FragCoord.xy, + v_Pos + vec2(v_BorderWidth), + v_Scale - vec2(v_BorderWidth * 2.0), + internal_border + ); + + float border_mix = smoothstep( + max(internal_border - 0.5, 0.0), + internal_border + 0.5, + internal_distance + ); + + mixed_color = mix(v_Color, v_BorderColor, border_mix); + } else { + mixed_color = v_Color; + } + + float d = distance( + gl_FragCoord.xy, + v_Pos, + v_Scale, + v_BorderRadius + ); + + float radius_alpha = + 1.0 - smoothstep(max(v_BorderRadius - 0.5, 0), v_BorderRadius + 0.5, d); + + o_Color = vec4(mixed_color.xyz, mixed_color.w * radius_alpha); } diff --git a/wgpu/src/shader/quad.frag.spv b/wgpu/src/shader/quad.frag.spv index 17bd8f465ada98f5308097b3ce01c65532cdf70a..519f5f01679be972c5585ee081f5825c4586d435 100644 GIT binary patch literal 4212 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 literal 3044 zcmZQ(Qf6mhU}Rut;9#g`fB-=TCI&_Z1_o{hHZbk(6YQf`T#}+^Vrl?V!NgM|TPa6w{GA}HQK;gtdkQzU*G8b1S#pM}N;nUf#yoS&0l1db0-#FRn#?hGsp zAoqjf5)=<0J}B+TF@RDf0|ST;N=G0*D7}FApfm;IgHj=g4>BLb2ZaZS4>BLd7iM4r zr!z%xiemt?#Tb|w*cceVaVXBf!obeJ0Oo_tS72aa;9y_?i-E*Jd`>7Iq(_l~gMkaG z9;6P2L25u)n}G#vmN>{U3=9sU3@i+~P`f}vAbAj955!?$U;yz!=9(b!LGor$|HI_H z!SW6EAooT0@yta_8|2+;QY+M0J9&&2gL~}en9#`?g7OKNI%H^`B3+R z$KyeC6b09vb4nXFE%70`& zsN6^9gUWhjKB#Pm@j>>3%5@MQ6s{mzn1O)-H> z7#KimK;nH+F$o3+29P+Y>}iIINir}nfXoKTfx;2wFOV3>T#&ue3=9mQFaq&G_R2u* zf$?Rbe3-qUauuWoB;E+ML!N&*#md7yt z+6)W~AT=OykbY3yfy6-h0u)#J3=H6U9aLt6%m9TGs38Orhp91SU;x+e$ZCuj7#Kj} zJPhpM{A&y?S3%~3^n>JKa;8XfAa$Vn0A{v1)P7K%0JGnMfq?-e4pU(iF%J ckRFg4n7ttk3=E)l0!ZCI1||j&A5>NX04|Q-+yDRo diff --git a/wgpu/src/shader/quad.vert b/wgpu/src/shader/quad.vert index 539755cb..1d9a4fd2 100644 --- a/wgpu/src/shader/quad.vert +++ b/wgpu/src/shader/quad.vert @@ -4,7 +4,9 @@ layout(location = 0) in vec2 v_Pos; layout(location = 1) in vec2 i_Pos; layout(location = 2) in vec2 i_Scale; layout(location = 3) in vec4 i_Color; -layout(location = 4) in float i_BorderRadius; +layout(location = 4) in vec4 i_BorderColor; +layout(location = 5) in float i_BorderRadius; +layout(location = 6) in float i_BorderWidth; layout (set = 0, binding = 0) uniform Globals { mat4 u_Transform; @@ -12,9 +14,11 @@ layout (set = 0, binding = 0) uniform Globals { }; layout(location = 0) out vec4 o_Color; -layout(location = 1) out vec2 o_Pos; -layout(location = 2) out vec2 o_Scale; -layout(location = 3) out float o_BorderRadius; +layout(location = 1) out vec4 o_BorderColor; +layout(location = 2) out vec2 o_Pos; +layout(location = 3) out vec2 o_Scale; +layout(location = 4) out float o_BorderRadius; +layout(location = 5) out float o_BorderWidth; void main() { vec2 p_Pos = i_Pos * u_Scale; @@ -28,9 +32,11 @@ void main() { ); o_Color = i_Color; + o_BorderColor = i_BorderColor; o_Pos = p_Pos; o_Scale = p_Scale; o_BorderRadius = i_BorderRadius * u_Scale; + o_BorderWidth = i_BorderWidth * u_Scale; gl_Position = u_Transform * i_Transform * vec4(v_Pos, 0.0, 1.0); } diff --git a/wgpu/src/shader/quad.vert.spv b/wgpu/src/shader/quad.vert.spv index 9050adfb01dbe35088d3150834ade4555071ca2b..7059b51bc4575638f541d299aa07e0a12e4f6599 100644 GIT binary patch delta 1267 zcmX>jzDA0dnMs+Qfq{{Moq>a)d?K$Yqwqv$Mb!WX28KWe28Iv@28J*O28Kum28L(` z28IL%28Kii28K)q28M!(m3On*7(hz%8Q8$uGcm+jz((fB z2jmxn)vjPN@GcPDHC9|{`VqWy*iHzc&AP2x?!!uJ#GQg&=K^z6O z4Ou*$fq@}CCq5vxC@i(8B(;Kpfq{XIfsG-3@UGD-7-ybIFF%D}=svS);(f z!VnBKik*Rh0VEINgVF*_J%|rV7a%@JeFRiJ$l)OMAU??RF!?B`)7cmp>cIwr1VEty zvJj>L6dE86AU;SQ6dE9T83q=HG;q8zFlaI`Fvx-8kAZ=K7b*sl17VOuK)vxATf{`*$njz3^`CkKmi7_2oy-U3=nY`KaYWdL7stuVG;u? z14urffq?;}1|$wr0}81^P@sZC5>zrUFo4PkkQgW)0-+uRl?Na(P>csKuru(2(pU)t zL@`KGoq>Ttm4Sg_A_FTp>Ps0I7(kYR)PP(JO4DV~vI*p1kdHuokh;GNj0_eGj0^xF C?1Lfz delta 913 zcmZ1@bw-?*nMs+Qfq{{Moq>ZPZz8WLBmYEaMbSV828Lh;28J*O28IX*28IL%28Q&B zop-HS7(i0_@d5e83=9mc3@l(}`SHQYi8-kZtPE^mE&1_I`9&$IML~%vnWe=bb!-d~ zlP@xgOU8i=%83t1EecC5DoL$iU|?WiV_;*5n{3D=&KNh@lSx_@q=pHi&N(Nuz$LS| zBrz{Jm4S_cogr>=Ba<{Q$T=XLAp6rNuVgwd2y&Gi1IQx`4DKLTO`gasF9>ovNR)+v zfx&};l_75OM`mG9kok-Z3=G^*^0GQpjJnE|91qz+_9 z`et92*NpWF3@i)*P^Ih)3=Gy#KFCQR?JzzlJVAVr`cSBPHmG_K9~9Ow`EaPyVDcb7 z$TJ{k%P_Do#Das3fkBgjA&Ef_6n+d047^Z5kR%9$EQ*I(1addXAs{{|^gtGAGq5lS zF)%PBf`XEPfdQmG2^tQ3P=|4W;$d?nJ2Oi?$ZtUm3=EtM3=DP*%;1Co;@dK?Fo5Jj z7#J8NpmHF;g7_dgkRKwU>By0Rl|h7ofgy^4fkBXgfkBvofdQr_8YFzQumjEk->t2kpTdE30h_V