Compare commits

...
4 changed files with 46 additions and 10 deletions
+2 -1
View File
File diff suppressed because one or more lines are too long
+26 -8
View File
@@ -101,6 +101,12 @@ impl RowInfo {
self.widths.iter().rfind(|(k, _)| *k == i).map(|(_, w)| *w)
}
/// How many per-cell overrides the row keeps, for tests.
#[cfg(test)]
pub(crate) fn overrides(&self) -> usize {
self.vmerge.len() + self.shading.len() + self.widths.len() + self.width_pcts.len() + self.valign.len() + self.merges.len()
}
/// The width percentage cell `i` ends up with, for tests.
#[cfg(test)]
pub(crate) fn width_pct_of(&self, i: u8) -> Option<f32> {
@@ -108,6 +114,15 @@ impl RowInfo {
}
}
/// Set cell `c`'s override to `v`, replacing an earlier one: one slot per cell, however often
/// a PAPX repeats the sprm, so a shared PAPX can't pile up copies on every paragraph mark.
fn set<T>(slots: &mut Vec<(u8, T)>, c: u8, v: T) {
match slots.iter_mut().find(|(k, _)| *k == c) {
Some(slot) => slot.1 = v,
None => slots.push((c, v)),
}
}
pub(crate) fn decode(papx: &[u8]) -> RowInfo {
let mut r = RowInfo::default();
let mut gap_half: Option<i16> = None;
@@ -144,8 +159,10 @@ pub(crate) fn decode(papx: &[u8]) -> RowInfo {
T_DXA_GAP_HALF => gap_half = s16(&prl),
T_TABLE_BORDERS_80 => r.borders = table_borders(prl.operand),
T_MERGE => {
// Rows apply only the first MAX_COLS merges.
if let [a, b, ..] = prl.operand
&& b > a
&& r.merges.len() < MAX_COLS
{
r.merges.push((*a, *b));
}
@@ -158,7 +175,8 @@ pub(crate) fn decode(papx: &[u8]) -> RowInfo {
1 => VMerge::Continue,
_ => VMerge::None,
};
if m != VMerge::None {
// The first override for a cell wins.
if m != VMerge::None && !r.vmerge.iter().any(|(k, _)| k == itc) {
r.vmerge.push((*itc, m));
}
}
@@ -168,7 +186,7 @@ pub(crate) fn decode(papx: &[u8]) -> RowInfo {
&& let [a, b, ..] = prl.operand.get(1..3).unwrap_or(&[])
{
for c in *a..(*b).min(MAX_COLS as u8) {
r.shading.push((c, Some(rgb)));
set(&mut r.shading, c, Some(rgb));
}
}
}
@@ -176,7 +194,7 @@ pub(crate) fn decode(papx: &[u8]) -> RowInfo {
let cells = prl.operand.get(1..).unwrap_or(&[]);
for (i, b) in cells.as_chunks::<2>().0.iter().take(MAX_COLS).enumerate() {
if let Some(rgb) = shd80_rgb(b) {
r.shading.push((i as u8, Some(rgb)));
set(&mut r.shading, i as u8, Some(rgb));
}
}
}
@@ -196,7 +214,7 @@ pub(crate) fn decode(papx: &[u8]) -> RowInfo {
if raw && b.get(8..10) == Some(&[0xFF, 0xFF]) {
continue;
}
r.shading.push(((first + i) as u8, shd_rgb(b)));
set(&mut r.shading, (first + i) as u8, shd_rgb(b));
}
}
T_CELL_WIDTH => {
@@ -207,12 +225,12 @@ pub(crate) fn decode(papx: &[u8]) -> RowInfo {
if *fts == 3 {
let w = (i16::from_le_bytes([*w0, *w1]) as f32 / 20.0).clamp(0.0, 1584.0);
for c in *a..(*b).min(MAX_COLS as u8) {
r.widths.push((c, w));
set(&mut r.widths, c, w);
}
} else if *fts == 2 {
let pct = (u16::from_le_bytes([*w0, *w1]) as f32 / 50.0).clamp(0.0, 100.0);
for c in *a..(*b).min(MAX_COLS as u8) {
r.width_pcts.push((c, pct));
set(&mut r.width_pcts, c, pct);
}
}
}
@@ -224,8 +242,8 @@ pub(crate) fn decode(papx: &[u8]) -> RowInfo {
2 => VAlign::Bottom,
_ => VAlign::Top,
};
for c in *a..*b {
r.valign.push((c, v));
for c in *a..(*b).min(MAX_COLS as u8) {
set(&mut r.valign, c, v);
}
}
}
+17
View File
@@ -2401,6 +2401,23 @@ fn second_table_gets_its_own_grid() {
assert_eq!(tables[1].props.indent, None, "indent reset");
}
#[test]
fn repeated_cell_sprms_keep_one_override_per_cell() {
// A PAPX repeating cell-range sprms (shared by every paragraph mark that names it) keeps one
// slot per cell, the last value winning, instead of a copy per repetition.
let mut sprms = Vec::new();
for w in 0..200u16 {
let [w0, w1] = (w * 20).to_le_bytes();
sprms.push(sprm_cb(0xD635, &[0, 63, 3, w0, w1]));
sprms.push(sprm_cb(0xD62C, &[0, 255, 1]));
sprms.push([0x24, 0x56, 0, 2].to_vec());
}
let row = crate::table::decode(&sprms.concat());
assert_eq!(row.width_of(0), Some(199.0), "the last width wins");
assert_eq!(row.width_of(62), Some(199.0));
assert!(row.overrides() <= 63 + 255 + 63, "{}", row.overrides());
}
#[test]
fn sprm_t_cell_width_twips_and_percentage() {
// [MS-DOC] §2.9.290 sprmTCellWidth (0xD635):
+1 -1
View File
File diff suppressed because one or more lines are too long