fix: optimize performance by wrapping trace logs, adding captured drag event subscriptions, and adding regression tests for adjustment compositing.

This commit is contained in:
Your Name
2026-07-24 02:04:35 +03:00
parent f2cca7e6a1
commit fba10b753c
9 changed files with 364 additions and 50 deletions
+40 -14
View File
@@ -384,6 +384,16 @@ pub fn composite_tiled_into(
}
}
/// Applies one adjustment-layer pixel to the current composite row.
///
/// **Purpose:** Evaluates curves, gradient-map, or hue/saturation data while
/// respecting masks, opacity, and blend mode. **Logic & Workflow:** Transparent
/// or masked-out destinations exit early; Normal blend bypasses the generic
/// blend dispatcher, and fully opaque adjustment pixels are assigned directly.
/// **Arguments:** `row` is the destination row, `x`/`gy` are canvas coordinates,
/// `layer` owns adjustment and mask data, and `blend`/`opacity` control mixing.
/// **Returns:** Nothing. **Side Effects / Dependencies:** Mutates only the RGB
/// channels of one destination pixel and uses `hcie-blend` for non-Normal modes.
#[inline]
fn blend_adjustment_pixel(
row: &mut [u8],
@@ -435,20 +445,36 @@ fn blend_adjustment_pixel(
};
let eff_opacity = opacity * (mask_val as f32 / 255.0);
let blended_opaque = blend_pixels(
[dst[0], dst[1], dst[2], 255],
[adj_rgb[0], adj_rgb[1], adj_rgb[2], 255],
blend,
1.0,
);
row[out_idx] = ((1.0 - eff_opacity) * dst[0] as f32 + eff_opacity * blended_opaque[0] as f32)
.round() as u8;
row[out_idx + 1] = ((1.0 - eff_opacity) * dst[1] as f32
+ eff_opacity * blended_opaque[1] as f32)
.round() as u8;
row[out_idx + 2] = ((1.0 - eff_opacity) * dst[2] as f32
+ eff_opacity * blended_opaque[2] as f32)
.round() as u8;
if eff_opacity <= 0.0 {
return;
}
let blended_rgb = if blend == hcie_blend::BlendMode::Normal {
adj_rgb
} else {
let blended = blend_pixels(
[dst[0], dst[1], dst[2], 255],
[adj_rgb[0], adj_rgb[1], adj_rgb[2], 255],
blend,
1.0,
);
[blended[0], blended[1], blended[2]]
};
if eff_opacity >= 1.0 {
row[out_idx] = blended_rgb[0];
row[out_idx + 1] = blended_rgb[1];
row[out_idx + 2] = blended_rgb[2];
return;
}
let inverse_opacity = 1.0 - eff_opacity;
row[out_idx] =
(inverse_opacity * dst[0] as f32 + eff_opacity * blended_rgb[0] as f32).round() as u8;
row[out_idx + 1] =
(inverse_opacity * dst[1] as f32 + eff_opacity * blended_rgb[1] as f32).round() as u8;
row[out_idx + 2] =
(inverse_opacity * dst[2] as f32 + eff_opacity * blended_rgb[2] as f32).round() as u8;
}
#[inline]
@@ -0,0 +1,64 @@
//! Regression coverage for optimized Normal-blend adjustment compositing.
//!
//! **Purpose:** Verifies that bypassing the generic blend dispatcher preserves
//! exact RGB output for opaque and partially opaque adjustments.
//! **Logic & Workflow:** Builds a one-pixel base and Curves layer, composites
//! through the public tiled path, and compares deterministic channel values.
//! **Side Effects / Dependencies:** Allocates only one-pixel protocol layers.
use hcie_blend::Adjustment;
use hcie_composite::tiled::composite_tiled;
use hcie_protocol::Layer;
use hcie_tile::TiledLayer;
/// Builds a Curves adjustment whose lookup tables map selected input channels.
///
/// **Arguments:** `opacity` controls the layer-level adjustment mix.
/// **Returns:** A one-pixel adjustment layer. **Side Effects / Dependencies:** None.
fn curves_layer(opacity: f32) -> Layer {
let mut lut_r: Vec<u8> = (0..=255).map(|value| value as u8).collect();
let mut lut_g = lut_r.clone();
let mut lut_b = lut_r.clone();
lut_r[10] = 100;
lut_g[20] = 110;
lut_b[30] = 120;
let mut layer = Layer::new_transparent("Curves", 1, 1);
layer.adjustment = Some(Adjustment::Curves {
lut_r,
lut_g,
lut_b,
});
layer.opacity = opacity;
layer
}
/// Confirms a fully opaque Normal adjustment assigns the LUT result exactly.
#[test]
fn opaque_normal_adjustment_matches_lookup_result() {
let base = Layer::from_rgba("Base", 1, 1, vec![10, 20, 30, 255]);
let adjustment = curves_layer(1.0);
let tiles = vec![
Some(TiledLayer::from_dense(&base.pixels, 1, 1)),
Some(TiledLayer::from_dense(&adjustment.pixels, 1, 1)),
];
let output = composite_tiled(&[base, adjustment], &tiles, 1, 1);
assert_eq!(output, vec![100, 110, 120, 255]);
}
/// Confirms partial opacity retains the previous rounded interpolation behavior.
#[test]
fn partial_normal_adjustment_preserves_rounded_interpolation() {
let base = Layer::from_rgba("Base", 1, 1, vec![10, 20, 30, 255]);
let adjustment = curves_layer(0.5);
let tiles = vec![
Some(TiledLayer::from_dense(&base.pixels, 1, 1)),
Some(TiledLayer::from_dense(&adjustment.pixels, 1, 1)),
];
let output = composite_tiled(&[base, adjustment], &tiles, 1, 1);
assert_eq!(output, vec![55, 65, 75, 255]);
}