mirror of
https://github.com/storytold/deckcraft.git
synced 2026-11-13 13:43:50 +00:00
Charts: a legend entry's paragraph text wins over its list style
Review fixes: an entry's size, weight and colour are read from its paragraph (a:p) first and from a:lstStyle only where the paragraph sets none, as DrawingML inherits them; the writer keeps sizes to the reader's 1-400 pt, so a size reads back as written; and the legend draws an entry at its own size up to 400 pt rather than up to 8 times the legend's.
This commit is contained in:
1 parent
b5b77eb27e
commit
0e0d7f8cb2
3 files changed
+26
-5
No files matched your search
@@ -197,12 +197,15 @@ fn chart_within(root: &El, mut budget: usize) -> Option<Chart> {
|
||||
.flat_map(|l| l.children_named("legendEntry"))
|
||||
.take(MAX_LEGEND_ENTRIES)
|
||||
.filter_map(|e| {
|
||||
// The paragraph's own run properties first, then the list style's defaults
|
||||
// (`a:lstStyle` comes before `a:p`, and is the less specific of the two).
|
||||
let tx = e.child("txPr");
|
||||
let para = tx.and_then(|t| t.child("p"));
|
||||
let entry = deckcraft_model::chart::LegendEntry {
|
||||
idx: e.child("idx").and_then(|i| i.u32("val"))?,
|
||||
size: text_size(tx),
|
||||
bold: text_bold(tx),
|
||||
color: text_color(tx),
|
||||
size: text_size(para).or_else(|| text_size(tx)),
|
||||
bold: text_bold(para).or_else(|| text_bold(tx)),
|
||||
color: text_color(para).or_else(|| text_color(tx)),
|
||||
};
|
||||
(entry.size.is_some() || entry.bold.is_some() || entry.color.is_some()).then_some(entry)
|
||||
})
|
||||
|
||||
@@ -109,7 +109,8 @@ fn legend_entry(w: &mut W, e: &deckcraft_model::chart::LegendEntry) {
|
||||
w.open0("a:pPr");
|
||||
let mut a = A::new();
|
||||
if let Some(sz) = e.size.filter(|v| v.is_finite() && *v > 0.0) {
|
||||
a = a.a("sz", ((sz * 100.0).round().clamp(100.0, 400_000.0) as u32).to_string());
|
||||
// 1 to 400 pt, as the reader takes it, so a size reads back as written.
|
||||
a = a.a("sz", ((sz * 100.0).round().clamp(100.0, 40_000.0) as u32).to_string());
|
||||
}
|
||||
if let Some(b) = e.bold {
|
||||
a = a.a("b", if b { "1" } else { "0" });
|
||||
@@ -1243,6 +1244,23 @@ mod tests {
|
||||
// None: nothing written.
|
||||
e.legend_entries.clear();
|
||||
assert!(!String::from_utf8(super::chart_xml(&e).0).unwrap().contains("legendEntry"));
|
||||
// The paragraph's own properties win over the list style's, which come first in the XML.
|
||||
let listed = xml.replacen(
|
||||
r#"<c:legendEntry><c:idx val="0"/><c:txPr><a:bodyPr/><a:lstStyle/>"#,
|
||||
r#"<c:legendEntry><c:idx val="0"/><c:txPr><a:bodyPr/><a:lstStyle><a:lvl1pPr><a:defRPr sz="1200" b="0"><a:solidFill><a:srgbClr val="0000FF"/></a:solidFill></a:defRPr></a:lvl1pPr></a:lstStyle>"#,
|
||||
1,
|
||||
);
|
||||
assert_ne!(listed, xml, "the list style was put in");
|
||||
let c = crate::read::chart::read_chart_xml(listed.as_bytes()).unwrap();
|
||||
assert_eq!(c.legend_entries[0], want(0, (0xC0, 0, 0)), "the paragraph's 20 pt, bold, C00000");
|
||||
// A size reads back as it was written, within the reader's 1-400 pt.
|
||||
for (size, back) in [(20.5, 20.5), (400.0, 400.0), (500.0, 400.0)] {
|
||||
let mut e = c.clone();
|
||||
e.raw = None;
|
||||
e.legend_entries = vec![deckcraft_model::chart::LegendEntry { idx: 0, size: Some(size), bold: None, color: None }];
|
||||
let back_size = crate::read::chart::read_chart_xml(&super::chart_xml(&e).0).unwrap().legend_entries[0].size;
|
||||
assert_eq!(back_size, Some(back), "{size} pt");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -542,7 +542,7 @@ fn draw_legend(ctx: &mut RenderContext, draw: &LegendDraw<'_, '_>, mut area: Rec
|
||||
let styles: Vec<(f64, bool, Rgba)> = (0..legend_items.len())
|
||||
.map(|i| {
|
||||
let e = own(i);
|
||||
let size = e.and_then(|e| e.size).filter(|v| v.is_finite() && *v > 0.0).map_or(base, |v| v.min(base * 8.0));
|
||||
let size = e.and_then(|e| e.size).filter(|v| v.is_finite() && *v > 0.0).map_or(base, |v| v.min(400.0));
|
||||
let col = e.and_then(|e| e.color.as_ref()).map_or(text_col, |cr| rctx.color(cr, None));
|
||||
(size, e.and_then(|e| e.bold).unwrap_or(false), col)
|
||||
})
|
||||
|
||||
Reference in new issue
Block a user