idml: explicit zero cell edge weights hide the default table border (#1623)

This commit is contained in:
MarekSpodBiedry
2026-10-23 17:35:51 +02:00
parent 2e36dcf909
commit 7b91a1eefc
2 changed files with 37 additions and 1 deletions
+8 -1
View File
@@ -2170,9 +2170,12 @@ impl<'r> Importer<'r> {
}
// Table-local options override the named table style. Cell styles are already
// materialized independently, so their edges retain their higher precedence.
let mut border_unset = style.border.is_none() && style.borders.iter().all(|b| b.is_empty());
let mut borders = std::array::from_fn::<_, 4, _>(|i| t.options.border_for(i).clone());
for (side, border) in ["TopBorder", "LeftBorder", "BottomBorder", "RightBorder"].iter().zip(&mut borders) {
self.cell_stroke_attrs(e, side).apply_to(border);
let attrs = self.cell_stroke_attrs(e, side);
border_unset &= attrs.is_empty();
attrs.apply_to(border);
}
t.options.border = borders[0].clone();
t.options.borders = borders.map(Some);
@@ -2243,6 +2246,10 @@ impl<'r> Importer<'r> {
cell.stroke_priorities[i] = priority;
// Preserve style-defined edges and #102's positive-priority local overrides.
cell.border_overrides[i] |= priority > 0;
// No table or table style border is given anywhere, so the built-in 1 pt default must not
// draw over an outer edge the cell explicitly hides (weight 0 or the None swatch), as InDesign draws nothing.
let hidden = attrs.weight == Some(0.0) || attrs.color.as_deref() == Some(swatch::NONE);
cell.border_overrides[i] |= border_unset && hidden;
}
if let Some(slot) = t.cell_mut(r, c) {
*slot = cell;
+29
View File
@@ -1100,6 +1100,35 @@ fn imports_and_round_trips_explicit_cell_border_overrides() {
assert_eq!(roundtrip.cell(0, 1).unwrap().border_overrides, [false; 4]);
}
#[test]
fn explicitly_hidden_cell_edges_hide_the_default_table_border() {
// No table border or table style is given, and every cell edge is explicitly hidden (issue #1623):
// the first cell by weight 0, the second by the None swatch.
let cell = |name: &str, attr: &str, value: &str| {
format!(
r#"<Cell Name="{name}" LeftEdge{attr}="{value}" RightEdge{attr}="{value}" TopEdge{attr}="{value}" BottomEdge{attr}="{value}">
<ParagraphStyleRange><CharacterStyleRange><Content>X</Content></CharacterStyleRange></ParagraphStyleRange></Cell>"#
)
};
let story = format!(
r#"<idPkg:Story xmlns:idPkg="http://ns.adobe.com/AdobeInDesign/idml/1.0/packaging">
<Story Self="s1"><ParagraphStyleRange><CharacterStyleRange>
<Table HeaderRowCount="0" FooterRowCount="0">
<Row Name="0" MinimumHeight="24"/>
<Column Name="0" SingleColumnWidth="60"/><Column Name="1" SingleColumnWidth="60"/>
{}{}
</Table></CharacterStyleRange></ParagraphStyleRange></Story></idPkg:Story>"#,
cell("0:0", "StrokeWeight", "0"),
cell("1:0", "StrokeColor", "Swatch/None")
);
let d = import_idml(&fixture_with_story(&story)).unwrap();
d.check().unwrap();
let table = d.stories.values().flat_map(|s| s.tables.values()).next().unwrap();
for c in 0..2 {
assert_eq!(table.cell(0, c).unwrap().border_overrides, [true; 4], "cell {c} suppresses the table border");
}
}
#[test]
fn round_trips_footnotes_and_options() {
let mut d = Document::new(&NewDocument::default());