mirror of
https://github.com/storytold/deckcraft.git
synced 2026-10-24 10:37:03 -06:00
Open: also cap effect sizes in inherited text styles and theme effects
Review follow-up. A huge glow or shadow could still arrive through what text and shapes inherit: the deck's default text style, a master's title, body and other styles, a text box's or table cell's own list style, and the theme's effect styles that shape styles point at. sane_numbers caps those too; the test plants 10^18 pt glows in each and checks they come back capped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
daae74b57e
commit
8ee5094c60
@@ -3660,6 +3660,25 @@ fn opening_a_file_caps_absurd_effect_sizes() {
|
||||
r.props.glow = glow.clone();
|
||||
}
|
||||
}
|
||||
// Inherited styles too: the deck default, a master's body style, a text box's own list
|
||||
// style, and the theme's effect styles that shape styles point at.
|
||||
let level = deckcraft_model::text::LevelStyle {
|
||||
run: deckcraft_model::text::RunProps {
|
||||
glow: Some(Glow { color: deckcraft_model::style::ColorRef::rgb(deckcraft_color::Rgba::BLACK), radius: huge }),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
doc.default_text_style.set(0, level.clone());
|
||||
let m = std::sync::Arc::make_mut(&mut doc.masters[0]);
|
||||
m.body_style.set(0, level.clone());
|
||||
if let Some(fx) = m.theme.format.effects.first_mut() {
|
||||
fx.glow = Some(Glow { color: deckcraft_model::style::ColorRef::rgb(deckcraft_color::Rgba::BLACK), radius: huge });
|
||||
}
|
||||
let list = crate::shapes_mut(doc, sel).unwrap();
|
||||
if let Some(t) = list.iter_mut().find_map(|sh| sh.text.as_mut()) {
|
||||
t.list_style.set(0, level);
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
@@ -3689,6 +3708,16 @@ fn opening_a_file_caps_absurd_effect_sizes() {
|
||||
glows.extend(cells.flat_map(|p| p.runs.iter()).filter_map(|r| r.props.glow.as_ref().map(|g| g.radius)));
|
||||
}
|
||||
});
|
||||
let inherited = |ls: &deckcraft_model::text::ListStyle| {
|
||||
ls.levels.iter().flatten().filter_map(|l| l.run.glow.as_ref().map(|g| g.radius)).collect::<Vec<_>>()
|
||||
};
|
||||
glows.extend(inherited(&st.doc.default_text_style));
|
||||
let m = &st.doc.masters[0];
|
||||
for ls in [&m.title_style, &m.body_style, &m.other_style] {
|
||||
glows.extend(inherited(ls));
|
||||
}
|
||||
glows.extend(m.theme.format.effects.iter().filter_map(|e| e.glow.as_ref().map(|g| g.radius)));
|
||||
deckcraft_model::walk(&slide.shapes, &mut |sh, _| glows.extend(sh.text.iter().flat_map(|t| inherited(&t.list_style))));
|
||||
assert!(!glows.is_empty(), "{format}: the glows were kept");
|
||||
assert!(glows.iter().all(|g| (0.0..=150.0).contains(g)), "{format}: {glows:?}");
|
||||
// Capped, the slide renders (checked last: uncapped, this is what ran out of memory).
|
||||
|
||||
@@ -392,6 +392,13 @@ fn sane_reflection(r: &mut deckcraft_model::style::Reflection) {
|
||||
r.dist = effect_size(r.dist, MAX_REFLECTION);
|
||||
}
|
||||
|
||||
/// Run properties a list style hands down to the text that inherits it.
|
||||
fn sane_list_style(ls: &mut deckcraft_model::text::ListStyle) {
|
||||
for level in ls.levels.iter_mut().flatten() {
|
||||
sane_run(&mut level.run);
|
||||
}
|
||||
}
|
||||
|
||||
fn sane_effects(e: &mut deckcraft_model::Effects) {
|
||||
for s in e.outer_shadow.iter_mut().chain(e.inner_shadow.iter_mut()) {
|
||||
sane_shadow(s);
|
||||
@@ -420,6 +427,7 @@ fn sane_shapes(shapes: &mut [deckcraft_model::Shape], depth: usize) {
|
||||
sane_effects(e);
|
||||
}
|
||||
if let Some(t) = sh.text.as_mut() {
|
||||
sane_list_style(&mut t.list_style);
|
||||
for para in &mut t.paragraphs {
|
||||
sane_run(&mut para.end_props);
|
||||
for r in &mut para.runs {
|
||||
@@ -438,6 +446,9 @@ fn sane_shapes(shapes: &mut [deckcraft_model::Shape], depth: usize) {
|
||||
sane_shapes(children, depth + 1);
|
||||
}
|
||||
deckcraft_model::ShapeKind::Table(t) => {
|
||||
for cell in t.rows.iter_mut().flat_map(|r| r.cells.iter_mut()) {
|
||||
sane_list_style(&mut cell.text.list_style);
|
||||
}
|
||||
for para in t.rows.iter_mut().flat_map(|r| r.cells.iter_mut()).flat_map(|c| c.text.paragraphs.iter_mut()) {
|
||||
sane_run(&mut para.end_props);
|
||||
for r in &mut para.runs {
|
||||
@@ -459,12 +470,21 @@ pub fn sane_numbers(p: &mut Presentation) {
|
||||
*slide = Arc::new(fixed);
|
||||
}
|
||||
}
|
||||
// What text and shapes inherit: the deck's default text style, each master's title, body and
|
||||
// other styles, and the theme's effect styles that shape styles point at.
|
||||
sane_list_style(&mut p.default_text_style);
|
||||
for m in p.masters.iter_mut().chain(p.notes_master.iter_mut()).chain(p.handout_master.iter_mut()) {
|
||||
let mut fixed = (**m).clone();
|
||||
sane_shapes(&mut fixed.shapes, 0);
|
||||
for l in &mut fixed.layouts {
|
||||
sane_shapes(&mut l.shapes, 0);
|
||||
}
|
||||
for ls in [&mut fixed.title_style, &mut fixed.body_style, &mut fixed.other_style] {
|
||||
sane_list_style(ls);
|
||||
}
|
||||
for e in &mut fixed.theme.format.effects {
|
||||
sane_effects(e);
|
||||
}
|
||||
if fixed != **m {
|
||||
*m = Arc::new(fixed);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user