Implement stable serialization and restoration for dock layouts, including auto-hidden and floating panels
- Add `persistence.rs` for stable serialization of dock layouts without runtime identifiers. - Introduce `preview.rs` for geometry handling of dock drop previews. - Create `sizing.rs` to manage content-aware sizing policies and constraint solving for dock panels. - Implement `welcome.rs` to provide a welcome surface when no documents are open, featuring New and Open actions.
This commit is contained in:
+40
-16
@@ -35,17 +35,23 @@ pub fn create_ellipse_mask(w: u32, h: u32, cx: u32, cy: u32, rx: u32, ry: u32) -
|
||||
|
||||
/// Grow a mask by `px` pixels (4-connected dilation).
|
||||
pub fn grow_mask(mask: &mut [u8], w: u32, h: u32, px: u32) {
|
||||
if px == 0 { return; }
|
||||
if px == 0 {
|
||||
return;
|
||||
}
|
||||
let mut temp = mask.to_vec();
|
||||
for _ in 0..px {
|
||||
let old = temp.clone();
|
||||
for y in 0..h {
|
||||
for x in 0..w {
|
||||
let i = (y * w + x) as usize;
|
||||
if old[i] > 0 { continue; }
|
||||
if old[i] > 0 {
|
||||
continue;
|
||||
}
|
||||
let neighbors = [
|
||||
(x.wrapping_sub(1), y), (x + 1, y),
|
||||
(x, y.wrapping_sub(1)), (x, y + 1),
|
||||
(x.wrapping_sub(1), y),
|
||||
(x + 1, y),
|
||||
(x, y.wrapping_sub(1)),
|
||||
(x, y + 1),
|
||||
];
|
||||
for (nx, ny) in neighbors {
|
||||
if nx < w && ny < h {
|
||||
@@ -64,17 +70,23 @@ pub fn grow_mask(mask: &mut [u8], w: u32, h: u32, px: u32) {
|
||||
|
||||
/// Shrink a mask by `px` pixels (4-connected erosion).
|
||||
pub fn shrink_mask(mask: &mut [u8], w: u32, h: u32, px: u32) {
|
||||
if px == 0 { return; }
|
||||
if px == 0 {
|
||||
return;
|
||||
}
|
||||
let mut temp = mask.to_vec();
|
||||
for _ in 0..px {
|
||||
let old = temp.clone();
|
||||
for y in 0..h {
|
||||
for x in 0..w {
|
||||
let i = (y * w + x) as usize;
|
||||
if old[i] == 0 { continue; }
|
||||
if old[i] == 0 {
|
||||
continue;
|
||||
}
|
||||
let neighbors = [
|
||||
(x.wrapping_sub(1), y), (x + 1, y),
|
||||
(x, y.wrapping_sub(1)), (x, y + 1),
|
||||
(x.wrapping_sub(1), y),
|
||||
(x + 1, y),
|
||||
(x, y.wrapping_sub(1)),
|
||||
(x, y + 1),
|
||||
];
|
||||
let mut has_zero = false;
|
||||
for (nx, ny) in neighbors {
|
||||
@@ -96,7 +108,9 @@ pub fn shrink_mask(mask: &mut [u8], w: u32, h: u32, px: u32) {
|
||||
/// a smooth falloff. This properly creates soft transitions at the border
|
||||
/// by including previously-unselected pixels within the feather radius.
|
||||
pub fn feather_mask(mask: &mut [u8], w: u32, h: u32, radius: f32) {
|
||||
if radius <= 0.0 { return; }
|
||||
if radius <= 0.0 {
|
||||
return;
|
||||
}
|
||||
let r = radius.ceil() as i32;
|
||||
let r_sq = (radius * radius) as f32;
|
||||
let size = (w * h) as usize;
|
||||
@@ -114,7 +128,9 @@ pub fn feather_mask(mask: &mut [u8], w: u32, h: u32, radius: f32) {
|
||||
// Check if any selected pixel is within radius
|
||||
'outer: for dy in -r..=r {
|
||||
for dx in -r..=r {
|
||||
if (dx * dx + dy * dy) as f32 > r_sq { continue; }
|
||||
if (dx * dx + dy * dy) as f32 > r_sq {
|
||||
continue;
|
||||
}
|
||||
let nx = (x as i32 + dx).clamp(0, w as i32 - 1) as u32;
|
||||
let ny = (y as i32 + dy).clamp(0, h as i32 - 1) as u32;
|
||||
if mask[(ny * w + nx) as usize] > 0 {
|
||||
@@ -294,7 +310,9 @@ pub fn lasso_fill_mask(mask: &mut [u8], w: u32, h: u32, points: &[(u32, u32)]) {
|
||||
/// - `w`, `h`: Canvas dimensions.
|
||||
/// - `thickness`: Border thickness in pixels.
|
||||
pub fn border_mask(mask: &mut [u8], w: u32, h: u32, thickness: u32) {
|
||||
if thickness == 0 { return; }
|
||||
if thickness == 0 {
|
||||
return;
|
||||
}
|
||||
let original = mask.to_vec();
|
||||
|
||||
// First, create the outer border by eroding
|
||||
@@ -304,10 +322,14 @@ pub fn border_mask(mask: &mut [u8], w: u32, h: u32, thickness: u32) {
|
||||
for y in 0..h {
|
||||
for x in 0..w {
|
||||
let i = (y * w + x) as usize;
|
||||
if old[i] == 0 { continue; }
|
||||
if old[i] == 0 {
|
||||
continue;
|
||||
}
|
||||
let neighbors = [
|
||||
(x.wrapping_sub(1), y), (x + 1, y),
|
||||
(x, y.wrapping_sub(1)), (x, y + 1),
|
||||
(x.wrapping_sub(1), y),
|
||||
(x + 1, y),
|
||||
(x, y.wrapping_sub(1)),
|
||||
(x, y + 1),
|
||||
];
|
||||
let mut has_zero = false;
|
||||
for (nx, ny) in neighbors {
|
||||
@@ -343,7 +365,9 @@ pub fn border_mask(mask: &mut [u8], w: u32, h: u32, thickness: u32) {
|
||||
/// - `w`, `h`: Canvas dimensions.
|
||||
/// - `radius`: Blur radius in pixels.
|
||||
pub fn smooth_mask(mask: &mut [u8], w: u32, h: u32, radius: u32) {
|
||||
if radius == 0 { return; }
|
||||
if radius == 0 {
|
||||
return;
|
||||
}
|
||||
let r = radius as i32;
|
||||
let size = (w * h) as usize;
|
||||
let mut result = vec![0u8; size];
|
||||
@@ -365,4 +389,4 @@ pub fn smooth_mask(mask: &mut [u8], w: u32, h: u32, radius: u32) {
|
||||
}
|
||||
|
||||
mask.copy_from_slice(&result);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user