G11: Asset Export seam regression and supersampled thumbs

assets.export of abutting fills must leave no ghost edge (#983 / #1037); panel thumbnails use the same Art Optimized supersample. Progress docs mark the gap closed.
This commit is contained in:
Fabio William Conceição
2026-10-16 04:45:01 +07:00
committed by bflatastic
parent 74573d6bad
commit ed6d474042
5 changed files with 38 additions and 7 deletions
+27 -1
View File
@@ -1,6 +1,7 @@
//! Asset Export: collecting art as assets (single and multiple), assets following their art
//! (moves, deletions), names, undo, the native round trip, the shared export settings and
//! exporting assets alone, cropped to their art.
//! exporting assets alone, cropped to their art. Art Optimized PNG exports are supersampled
//! so abutting shapes leave no ghost seam (#983 / #1037).
use serde_json::{Value, json};
use vectorcraft_color::{Color, Paint};
@@ -284,6 +285,31 @@ fn assets_export_into_a_folder() {
let _ = std::fs::remove_dir_all(&dir);
}
/// #983: Asset Export Art Optimized PNG supersamples, so two abutting fills leave no white seam
/// on the shared edge (same idea as `supersampled_art_leaves_no_seam_between_shapes_that_meet`).
#[test]
fn assets_export_leaves_no_seam_between_abutting_shapes() {
let mut s = session();
s.paint.fill = Paint::solid(Color::rgb(1.0, 0.0, 0.0));
// Share the edge at x = 30; the crop is (10, 10)–(50, 30).
let (a, b) = (rect(&mut s, 10.0, 10.0, 20.0, 20.0), rect(&mut s, 30.0, 10.0, 20.0, 20.0));
run(&mut s, "assets.add", json!({"ids": [a, b], "multiple": false}));
let out = files(&run(
&mut s,
"assets.export",
json!({
"formats": [{"format": "png", "scale": "1x", "background": "white"}],
"antiAlias": "art",
}),
));
assert_eq!(out[0].0, "Asset-1.png");
let img = image::load_from_memory(&out[0].1).unwrap().to_rgba8();
assert_eq!(img.dimensions(), (40, 20));
// Column 20 is the shared edge in crop space; green must stay red (no white bleed).
let palest_g = (2..18).map(|y| img.get_pixel(20, y).0[1].max(img.get_pixel(19, y).0[1])).max().unwrap();
assert_eq!(palest_g, 0, "supersampled Asset Export: no seam on the shared edge (G={palest_g})");
}
#[test]
fn collecting_explicit_assets_rejects_invalid_ids_without_adding_anything() {
let mut s = session();
+5 -2
View File
@@ -67,11 +67,14 @@ pub(crate) fn paint_thumb(ui: &Ui, st: &DocState, a: &ExportAsset, r: Rect) {
let key = (nodes, px);
let tex = CACHE.with(|c| c.borrow().get(&key).cloned()).or_else(|| {
let art: Vec<&Node> = ids().iter().filter_map(|id| st.doc.node(*id)).collect();
// Same Art Optimized supersample as assets.export (#983): abutting fills leave no seam in
// the tile (Layers row thumbs stay cheap without it).
let opts = vectorcraft_render::RenderOptions { image_mips: true, precise: true, supersample: true, ..Default::default() };
let img = RENDERER.with(|rr| match art.as_slice() {
[one] => rr.borrow_mut().render_node_thumbnail_with(&st.doc, one, px, None, &super::layers::thumb_options()),
[one] => rr.borrow_mut().render_node_thumbnail_with(&st.doc, one, px, None, &opts),
many => {
let group = Node::group(NodeId(0), many.iter().map(|n| Arc::new((*n).clone())).collect());
rr.borrow_mut().render_node_thumbnail_with(&st.doc, &group, px, None, &super::layers::thumb_options())
rr.borrow_mut().render_node_thumbnail_with(&st.doc, &group, px, None, &opts)
}
})?;
let color = egui::ColorImage::from_rgba_premultiplied([img.width as usize, img.height as usize], &img.pixels);
+1
View File
@@ -137,6 +137,7 @@ from G14 and the budget run of G15: **~170–270 h** one agent, ~50–80 h wall
## G11 Correctness bugs in core tools
- **Done:** Asset Export / raster Art Optimized edges supersample so shapes that meet edge to edge leave no ghost seam (#983, #1037; `assets.export` abutting-rects regression; Asset Export panel thumbs use the same supersample).
- **Done (2026-10-14):** Align and Distribute act on the anchor points selected with Direct Selection: the points of one path align to each other, not to the artboard, and Distribute spaces them (#1641, fixes #1636; aligning to a key anchor is still missing). Delete removes every selected anchor of a closed path (it used to remove the wrong ones), removes objects selected whole along with the selected anchors of others, and keeps the remainder selected so a second Delete removes it (#1674). In isolation mode Direct Selection and Group Selection pick only inside the isolated object (#1666). Escape cancels a Direct Selection drag (#1803, #1743). Escape while typing ends the edit, keeps the type selected and switches to the Selection tool (#1802, #1686, #1656). A filled Pencil path keeps a stroke of None (#1804, part of #1679). In the Pathfinder panel a group selected alone counts its nested shapes, so an expanded stroked object keeps the Shape Modes enabled (#1642, #1635). Object › Expand turns radial, grid and mirror repeats into groups of their instances (#1765, #1756). Select › Same matches type on its characters' fill and stroke (#1746, #1737). Roughen with Smooth keeps turn-backs smooth instead of making cusps that draw as spikes (#1646, #1643). Scribble draws one zig-zag per region, with no lines across holes and notches; convex shapes are unchanged (#1651, #1648).
- **Done:** Divide splits filled paths along open cutting lines and curves (#1307), preserving the frontmost filled appearance, implicit filled closure, holes, unrelated objects and one Undo/Redo; the existing bounded-map fallback remains.
+2 -2
View File
@@ -22,7 +22,7 @@ Checked 2026-10-10 from the code, tests and open issues; no workflow fails, so V
| Draw and edit paths precisely: Pen, Curvature, Direct Selection on anchors and handles, smart guides and snapping, Pathfinder | yes | `crates/tools/src/pen.rs`, `direct.rs`, `guides.rs` and their tests; 10 exact Pathfinder booleans; [ui-parity.md](ui-parity.md). Shape Builder misses regions in some files (#937), Pathfinder covers the same results | 0 |
| Paint and style: fills and strokes, global and spot swatches, gradients, Appearance, transparency, graphic styles | yes | M3 done (92 tasks); area scores 92–97% in [target-app-parity.md](target-app-parity.md#feature-areas) | 0 |
| Set type: point and area type, Character and Paragraph styles, threading, outlines | yes | type core 80%; styles, threading, Create Outlines and font matching tested ([type-parity.md](type-parity.md)); hyphenation and justification options missing (not blocking) | 0 |
| Organise layers and artboards and export assets (Export for Screens, SVG, PNG, PDF per artboard) | yes | Layers panel rework, Artboards panel and tool, Export for Screens and Asset Export done; ghost borders in some Asset Export output (#983) | 0 |
| Organise layers and artboards and export assets (Export for Screens, SVG, PNG, PDF per artboard) | yes | Layers panel rework, Artboards panel and tool, Export for Screens and Asset Export done; Art Optimized supersample closes ghost borders (#983 / #1037) | 0 |
| Print production: CMYK and spot colour, bleed and marks, PDF/X out, separations preview | yes | PDF/X-1a/3/4, presets, marks and bleed, ICC output intent, Separations Preview, Print with PostScript output | 0 |
| Exchange files with Illustrator users: open their `.ai`/EPS/PDF, hand back a file they can open | partial (doesn't block alpha) | `.ai`, EPS and PDF open as editable art, but real files can get the wrong layer structure (#951) and lose guides (#779); Save As `.ai` is PDF-compatible, which Illustrator opens without its own editing data (#868), or legacy version 7, which keeps layers, groups and type as text, one artboard per file, and waits for users' testing. This is the beta main-format gap ([gaps.md](gaps.md) G9) | 10–20 (for beta) |
@@ -32,7 +32,7 @@ Checked 2026-10-10 from the code, tests and open issues; no workflow fails, so V
Selection, smart guides and snapping first. 60–90 h, parallel by tool.
2. **`.ai` files from real users** (G9): layer structure (#951), guides (#779). 10–20 h.
3. **Launch and stability** (G10): the Windows and Linux start-up reports. 20–35 h.
4. **Core-tool bugs** (G11): Shape Builder regions (#937), Asset Export borders (#983). 8–15 h.
4. **Core-tool bugs** (G11): Shape Builder regions (#937). Asset Export ghost borders closed (#983 / #1037). 8–15 h.
5. **Raster effects** (G2) continue alongside: Artistic (Film Grain done; 14 left), Sketch, then the Effect Gallery. 23–39 h.
## Next
File diff suppressed because one or more lines are too long