diff --git a/crates/model/src/resolve.rs b/crates/model/src/resolve.rs index 4457108b..8d87229f 100644 --- a/crates/model/src/resolve.rs +++ b/crates/model/src/resolve.rs @@ -100,11 +100,15 @@ pub fn parents<'a>(ctx: &Ctx<'a>, shape: &Shape) -> (Option<&'a Shape>, Option<& } } -/// The text style group (title / body / other) a shape draws from. Text in a table that isn't a -/// placeholder takes the master's other-text style, as in PowerPoint for Mac (a table cell is 14 pt -/// under an `otherStyle` of 14 pt and a `defaultTextStyle` of 26 pt, while a shape's or a text -/// box's text is 26 pt); other shapes take the presentation's default text style. +/// The text style group (title / body / other) a shape draws from. Text in a table takes the +/// master's other-text style, also when the table sits in a content placeholder, as in PowerPoint +/// for Mac (a table cell is 14 pt under an `otherStyle` of 14 pt, a `defaultTextStyle` of 26 pt and +/// a bulleted 36 pt `bodyStyle`, with or without ``, while a shape's or a text box's +/// text is 26 pt); other shapes take the presentation's default text style. pub fn master_list_style<'a>(ctx: &Ctx<'a>, shape: &Shape) -> &'a ListStyle { + if matches!(shape.kind, crate::ShapeKind::Table(_)) { + return &ctx.master.other_style; + } match shape.ph_type() { Some(PhType::Title | PhType::CtrTitle) => &ctx.master.title_style, Some( @@ -119,7 +123,6 @@ pub fn master_list_style<'a>(ctx: &Ctx<'a>, shape: &Shape) -> &'a ListStyle { | PhType::ClipArt, ) => &ctx.master.body_style, Some(_) => &ctx.master.other_style, - None if matches!(shape.kind, crate::ShapeKind::Table(_)) => &ctx.master.other_style, None => &ctx.pres.default_text_style, } } @@ -252,7 +255,9 @@ pub fn body(ctx: &Ctx, shape: &Shape) -> BodyProps { /// The merged level style (paragraph + run defaults) for paragraphs at `level` in `shape`. pub fn level_style(ctx: &Ctx, shape: &Shape, level: u8) -> LevelStyle { - let (lp, mp) = parents(ctx, shape); + // A table's text inherits nothing from a placeholder the table sits in: PowerPoint draws it in + // the other-text style even under list styles on the layout's and master's placeholders. + let (lp, mp) = if matches!(shape.kind, crate::ShapeKind::Table(_)) { (None, None) } else { parents(ctx, shape) }; let mut out = LevelStyle::default(); let add = |out: &mut LevelStyle, ls: Option<&LevelStyle>| { if let Some(l) = ls { diff --git a/crates/model/src/tests.rs b/crates/model/src/tests.rs index 05915a56..bc3817d9 100644 --- a/crates/model/src/tests.rs +++ b/crates/model/src/tests.rs @@ -273,12 +273,14 @@ fn ink_width_follows_pressure_and_keeps_the_old_placeholder() { #[test] fn table_text_takes_the_masters_other_style_and_shapes_the_default_text_style() { - // PowerPoint for Mac, with an otherStyle of 14 pt and a defaultTextStyle of 26 pt: a table - // cell's text is 14 pt, a shape's and a text box's 26 pt. + // PowerPoint for Mac, with an otherStyle of 14 pt, a defaultTextStyle of 26 pt and a 36 pt + // bodyStyle: a table cell's text is 14 pt, also in a table placed in a content placeholder; a + // shape's and a text box's is 26 pt. let mut p = Presentation::default(); let size = |pt: f64| crate::text::LevelStyle { run: RunProps { size: Some(pt), ..Default::default() }, ..Default::default() }; p.default_text_style.set(0, size(26.0)); std::sync::Arc::make_mut(&mut p.masters[0]).other_style.set(0, size(14.0)); + std::sync::Arc::make_mut(&mut p.masters[0]).body_style.set(0, size(36.0)); let s = p.slides[0].clone(); let ctx = Ctx::for_slide(&p, &s).unwrap(); let para = Paragraph::default(); @@ -287,6 +289,8 @@ fn table_text_takes_the_masters_other_style_and_shapes_the_default_text_style() assert_eq!(pt(&Shape::table_cell(body.clone())), Some(14.0), "a table cell"); let table = Shape { kind: ShapeKind::Table(Table::default()), ..Default::default() }; assert_eq!(pt(&table), Some(14.0), "the table itself (its formatting state)"); + let in_placeholder = Shape { ph: Some(Placeholder { kind: PhType::Obj, idx: 1, ..Default::default() }), ..table }; + assert_eq!(pt(&in_placeholder), Some(14.0), "a table in a content placeholder"); assert_eq!(pt(&Shape { text: Some(body.clone()), ..Default::default() }), Some(26.0), "a shape"); assert_eq!(pt(&Shape { text: Some(body), text_box: true, ..Default::default() }), Some(26.0), "a text box"); }