mirror of
https://github.com/storytold/photocraft.git
synced 2026-11-11 04:40:31 +00:00
This commit is contained in:
commit
38f684e4e4
2 files changed
+56
-2
No files matched your search
@@ -70,13 +70,17 @@ impl CutParts {
|
||||
let w = b.width() as usize;
|
||||
for (i, (p, r)) in pp.chunks_exact_mut(n).zip(rp.chunks_exact_mut(n)).enumerate() {
|
||||
let k = sel.sample_channel(b.x0 + (i % w) as i32, b.y0 + (i / w) as i32, 0);
|
||||
// The selection lifts its share of a pixel's coverage, up to all of it, and the
|
||||
// rest stays (Photoshop): a layer's own transparency, loaded as the selection,
|
||||
// lifts it whole and leaves no ghost behind (#7655). An opaque pixel splits as k
|
||||
// and 1 − k, as a product would.
|
||||
if k <= 0.0 {
|
||||
p.fill(0.0);
|
||||
} else {
|
||||
p[a] *= k;
|
||||
p[a] = p[a].min(k);
|
||||
}
|
||||
if !copy && !fill {
|
||||
r[a] *= 1.0 - k;
|
||||
r[a] = (r[a] - k).max(0.0);
|
||||
}
|
||||
}
|
||||
if !mask {
|
||||
|
||||
@@ -226,3 +226,53 @@ fn cutting_an_untouched_part_of_the_mask_moves_it_and_leaves_the_background_colo
|
||||
assert!((mask_at(&s, 12, 12) - 0.5).abs() < 0.01, "the hole takes the background colour");
|
||||
assert_eq!(mask_at(&s, 40, 12), 0.0);
|
||||
}
|
||||
|
||||
/// #7655: a selection loaded from the layer's own transparency lifts its half-transparent pixels
|
||||
/// whole, leaving nothing behind (Photoshop); a half selection of an opaque pixel still splits it.
|
||||
#[test]
|
||||
fn a_layers_own_transparency_floats_its_soft_pixels_whole() {
|
||||
let mut s = Session::new();
|
||||
s.execute("file.new", json!({"width": 80, "height": 60, "background": "transparent"})).unwrap();
|
||||
let id = s.active().unwrap().active_layer.unwrap();
|
||||
s.edit("paint", |doc, _| {
|
||||
let surf = doc.layer_mut(id).unwrap().surface_mut().unwrap();
|
||||
surf.fill_rect(Rect::new(10, 10, 20, 30), &[1.0, 0.0, 0.0, 0.5]);
|
||||
surf.fill_rect(Rect::new(20, 10, 30, 30), &[1.0, 0.0, 0.0, 1.0]);
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
s.execute("select.loadSelection", json!({"channel": "transparency"})).unwrap();
|
||||
s.execute("select.float", json!({"dx": 0, "dy": 25})).unwrap();
|
||||
s.execute("select.drop", json!({})).unwrap();
|
||||
let d = &s.active().unwrap().doc;
|
||||
assert_eq!(alpha(d, id, 15, 20), 0.0, "no ghost where the soft pixels were");
|
||||
assert!((alpha(d, id, 15, 45) - 0.5).abs() < 0.01, "they moved whole: {}", alpha(d, id, 15, 45));
|
||||
assert_eq!((alpha(d, id, 25, 20), alpha(d, id, 25, 45)), (0.0, 1.0));
|
||||
|
||||
// A copy (⌥) of them is as solid as they are, as Photoshop's Layer via Copy of the same
|
||||
// selection is, and leaves them where they were.
|
||||
s.undo();
|
||||
s.execute("select.loadSelection", json!({"channel": "transparency"})).unwrap();
|
||||
s.execute("select.float", json!({"dx": 0, "dy": 25, "copy": true})).unwrap();
|
||||
s.execute("select.drop", json!({})).unwrap();
|
||||
let d = &s.active().unwrap().doc;
|
||||
assert!((alpha(d, id, 15, 20) - 0.5).abs() < 0.01 && (alpha(d, id, 15, 45) - 0.5).abs() < 0.01, "{} {}", alpha(d, id, 15, 20), alpha(d, id, 15, 45));
|
||||
|
||||
// A half selection of an opaque pixel splits it half and half, as before.
|
||||
let (mut s, id) = session();
|
||||
s.execute("select.all", json!({})).unwrap();
|
||||
s.edit("half", |doc, _| {
|
||||
let sel = doc.selection.as_mut().unwrap();
|
||||
sel.fill_rect(doc_rect(80, 60), &[0.5]);
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
s.execute("select.float", json!({"dx": 40, "dy": 0})).unwrap();
|
||||
s.execute("select.drop", json!({})).unwrap();
|
||||
let d = &s.active().unwrap().doc;
|
||||
assert!((alpha(d, id, 15, 15) - 0.5).abs() < 0.01 && (alpha(d, id, 55, 15) - 0.5).abs() < 0.01);
|
||||
}
|
||||
|
||||
fn doc_rect(w: i32, h: i32) -> Rect {
|
||||
Rect::new(0, 0, w, h)
|
||||
}
|
||||
Reference in new issue
Block a user