mirror of
https://github.com/storytold/deckcraft.git
synced 2026-10-24 10:37:03 -06:00
This commit is contained in:
@@ -129,6 +129,7 @@ app's JSON control channel (`deckcraft --control PORT`).
|
||||
| Date | What landed |
|
||||
|---|---|
|
||||
| 2026-10-13 | Eyedropper: Shape Fill, Shape Outline, Font Color and every other colour menu end with an Eyedropper that takes the colour drawn at a point of the slide (hover shows it, a click applies it, Esc cancels); `slide.colorAt` gives the same from scripts and MCP (#367) |
|
||||
| 2026-10-13 | Slide show: Honeycomb's hexagons cover the whole slide again — the bottom quarter stayed black until the endpoint (#420) |
|
||||
| 2026-10-13 | Slide transitions like PowerPoint: every transition and option measured frame by frame against PowerPoint's video export and retuned (curves, directions, soft edges, 3-D perspective, contents moving over backgrounds); PowerPoint's own XML elements and defaults read and written (diagonal Wipe, Zoom, Shape In/Out, Glitter Hexagons, Shred In/Out, Page Curl Single); `deckcraft-cli render-transition` renders frames headless |
|
||||
| 2026-10-13 | Wild text cases measured against PowerPoint (102 synthetic slides): bidi by run language, East Asian vertical text upright, mongolianVert/wordArtVert/wordArtVertRtl, underline styles and strikethrough at the font's metrics, centre/right/decimal tabs, East Asian, Thai, Hindi, Arabic and Hebrew numbering, small caps, all-caps "ß", transparent text, soft hyphens, kinsoku, rtlCol and just/dist anchoring, emoji presentation, fallback faces that no longer move the baseline |
|
||||
| 2026-10-13 | Render matches PowerPoint more closely on wild shape, picture and table cases: even-odd custom paths, dashes and caps, arrowheads, radial and path gradients, tile rects, rotWithShape, gradient lines, shadows cast by what is drawn (group and perspective too), group fill, picture borders, tiles, reflection, recolour (biLevel, alphaInv, brightness/contrast), table borders and grid default, 20+ preset shapes by their ECMA formulas, default miter joins, and approximate 3-D bevels, cameras and face lighting |
|
||||
|
||||
@@ -789,3 +789,33 @@ fn show_follows_links() {
|
||||
assert_eq!(s.follow(&p, &Action::LastViewed, None), LinkJump::None);
|
||||
assert_eq!(s.slide, 3);
|
||||
}
|
||||
|
||||
/// #420: late in the Honeycomb every cell has settled, so the incoming hexagons must cover the
|
||||
/// whole slide — the old row count stopped at ~75% of a 16:9 slide and left the bottom black.
|
||||
#[test]
|
||||
fn honeycomb_cells_reach_the_bottom_before_the_slide_ends() {
|
||||
let sign = |a: [f64; 2], b: [f64; 2], c: [f64; 2]| (a[0] - c[0]) * (b[1] - c[1]) - (b[0] - c[0]) * (a[1] - c[1]);
|
||||
let inside = |p: [f64; 2], t: [[f64; 2]; 3]| {
|
||||
// The dark seams between cells are the effect: at t=0.99 they are ~0.012% of the width
|
||||
// open, so a 1% pad forgives them and still fails genuinely uncovered ground.
|
||||
let c = [(t[0][0] + t[1][0] + t[2][0]) / 3.0, (t[0][1] + t[1][1] + t[2][1]) / 3.0];
|
||||
let t = t.map(|v| [c[0] + (v[0] - c[0]) * 1.01, c[1] + (v[1] - c[1]) * 1.01]);
|
||||
let (d1, d2, d3) = (sign(p, t[0], t[1]), sign(p, t[1], t[2]), sign(p, t[2], t[0]));
|
||||
!((d1 < 0.0 || d2 < 0.0 || d3 < 0.0) && (d1 > 0.0 || d2 > 0.0 || d3 > 0.0))
|
||||
};
|
||||
for aspect in [16.0 / 9.0, 3.0 / 2.0, 4.0 / 3.0, 11.0 / 8.5, 1.0] {
|
||||
// t = 0.99: every cell is settled and the seams are nearly closed.
|
||||
let ls = transition_frame("honeycomb", "", 0.99, aspect);
|
||||
let tris: Vec<[[f64; 2]; 3]> =
|
||||
ls.iter().filter(|l| l.source == Source::New && l.alpha >= 1.0).map(|l| [l.quad[0], l.quad[1], l.quad[2]]).collect();
|
||||
assert!(!tris.is_empty());
|
||||
let mut sy = 0.0;
|
||||
while sy <= 1.0 {
|
||||
for sx in [0.0, 0.2, 0.4, 0.6, 0.8, 0.99, 1.0] {
|
||||
let p = [sx, sy];
|
||||
assert!(tris.iter().any(|t| inside(p, *t)), "honeycomb aspect {aspect} t=0.99: {sx},{sy} is uncovered (no settled cell reaches it)");
|
||||
}
|
||||
sy += 0.02;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -794,7 +794,11 @@ fn honeycomb(t: f64, a: f64) -> Vec<Layer> {
|
||||
let cols = 11usize;
|
||||
let w = 1.0 / cols as f64;
|
||||
let rh = w * a * 0.5;
|
||||
let rows = (1.0 / (rh * 1.5)).ceil() as usize + 2;
|
||||
// Rows sit 0.866*rh apart; a settled hex reaches only 0.577*rh from its centre at the side
|
||||
// vertices, and the flat bottom zone 0.289*rh. Count the rows whose FLAT zone still covers
|
||||
// the slide's bottom: counting the vertex reach instead left V-notches of black above the
|
||||
// bottom edge on about a third of the aspect ratios (#420).
|
||||
let rows = ((1.0 / (rh * 0.866) - 1.0 / 3.0).ceil().max(1.0)) as usize + 1;
|
||||
let mut v = vec![Layer::full(Black, 1.0)];
|
||||
let seam = ss(win(t, 0.0, 0.12)) * (1.0 - ss(win(t, 0.85, 1.0)));
|
||||
let hex = |cx: f64, cy: f64, s: f64| -> Vec<[f64; 2]> {
|
||||
|
||||
Reference in New Issue
Block a user