Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,11 @@ word start the next line. A line left holding only tabs keeps their runs'
height. Centred, right and decimal stops keep their field on the line.
A negative left or right indent widens a body paragraph's lines into the
margin, as Word does; table cells still clamp it to zero until they clip their
content at the cell edge (#2261).
content at the cell edge (#2261). A body list item's marker likewise starts at
its signed left indent minus its hanging span, and its lines at the signed left
indent, even left of the margin. While a paragraph style's `w:ind` still
stands in for a direct `w:numPr` level's (#2383), such an item keeps its marker
at the margin.

DOCX section body text supports top, centered and bottom page alignment,
including paragraph after-spacing and page breaks. Continuous sections use their
Expand Down
Binary file modified assets/bugfixes/issue-2233/after.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/bugfixes/issue-2233/before.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/bugfixes/issue-2233/gt.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 15 additions & 15 deletions assets/bugfixes/issue-2233/layout-audit.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,31 @@
"pages": [
{
"lines": {
"gt": 3,
"out": 3,
"matched": 3,
"gt": 1,
"out": 1,
"matched": 1,
"missing": 0,
"extra": 0,
"deviant": 0,
"deviant": 1,
"missing_text": [],
"extra_text": []
},
"baseline": {
"mean_abs_dy": 0.04504733333331975,
"worst_dy": 0.08896000000002857,
"worst_dy_signed": 0.08896000000002857,
"worst_line": "Aboutprovidinginformation"
"mean_abs_dy": 0.2096899999999664,
"worst_dy": 0.2096899999999664,
"worst_dy_signed": -0.2096899999999664,
"worst_line": "1.Testmarker"
},
"dx0": {
"mean_abs": 0.07666666666666326,
"worst": 0.10499999999998977
"mean_abs": 0.025000000000005684,
"worst": -0.025000000000005684
},
"width": {
"mean_abs_pct": 0.15638470487368875,
"worst_pct": 0.31213315474126385
"mean_abs_pct": 1.2162516818425884,
"worst_pct": 1.2162516818425884
},
"instances": {
"compared": 3,
"compared": 1,
"large_shift_threshold": 5.0,
"large_shift_count": 0,
"large_shifts": [],
Expand All @@ -47,8 +47,8 @@
"mismatches": []
},
"pitch": {
"pairs": 2,
"worst_delta": 0.12546999999999287
"pairs": 0,
"worst_delta": 0.0
},
"wraps": {
"count": 0,
Expand Down
198 changes: 35 additions & 163 deletions assets/bugfixes/issue-2233/render-clusters-page-1.json
Original file line number Diff line number Diff line change
@@ -1,195 +1,67 @@
{
"clusters": [
{
"area_pt2": 30.4128,
"bbox_pt": {
"height": 9.6,
"width": 8.64,
"x": 85.44,
"y": 60.0
},
"disposition": {
"class": "glyph-edge-rasterization",
"kind": "accepted-rendering",
"note": "Inspected in the 150 DPI diff and 600 DPI GT/after crops: 'Recipient' (R, e, c, i) differs only in glyph outlines at the same positions, Word's embedded Times New Roman against this host's metric-compatible Liberation Serif; its start is 0.10pt and its baseline 0.01pt from Word's."
},
"id": "p1-5dc5304100ba",
"region": "top-left"
},
{
"area_pt2": 30.4128,
"area_pt2": 96.768,
"bbox_pt": {
"height": 7.2,
"width": 5.76,
"x": 95.04,
"y": 62.88
"width": 19.2,
"x": 107.04,
"y": 78.24
},
"disposition": {
"class": "glyph-edge-rasterization",
"kind": "accepted-rendering",
"note": "Inspected in the 150 DPI diff and 600 DPI GT/after crops: 'Recipient' (R, e, c, i) differs only in glyph outlines at the same positions, Word's embedded Times New Roman against this host's metric-compatible Liberation Serif; its start is 0.10pt and its baseline 0.01pt from Word's."
"issue": "#1874",
"kind": "issue",
"note": "\"est marker\" sits 1.05-1.07pt right of Word: Word kerns the T-e pair (e at 88.03pt against our 89.10pt) in this package without a styles part, while the run states no w:kern. The 150 DPI crop shows the same glyphs, outlines and weight, offset by one pair kern; \"T\" matches at 80.55pt against 80.525pt. Sub-material, recorded under #1874."
},
"id": "p1-132d48374563",
"id": "p1-bab31bb1f25c",
"region": "top-left"
},
{
"area_pt2": 28.8,
"area_pt2": 90.5472,
"bbox_pt": {
"height": 9.6,
"width": 6.72,
"x": 136.8,
"y": 155.52
"height": 9.12,
"width": 16.32,
"x": 88.32,
"y": 76.32
},
"disposition": {
"class": "glyph-edge-rasterization",
"kind": "accepted-rendering",
"note": "Inspected in the 150 DPI diff and 600 DPI GT/after crops: 'Dear recipient' (D, e, a, r, i, p) differs only in glyph outlines at the same positions, Times New Roman drawn as the metric-compatible Liberation Serif; its start is 0.03pt and its baseline 0.04pt from Word's, unchanged by this fix."
"issue": "#1874",
"kind": "issue",
"note": "\"est marker\" sits 1.05-1.07pt right of Word: Word kerns the T-e pair (e at 88.03pt against our 89.10pt) in this package without a styles part, while the run states no w:kern. The 150 DPI crop shows the same glyphs, outlines and weight, offset by one pair kern; \"T\" matches at 80.55pt against 80.525pt. Sub-material, recorded under #1874."
},
"id": "p1-0762ad287736",
"id": "p1-fdf16f925882",
"region": "top-left"
},
{
"area_pt2": 28.3392,
"area_pt2": 55.5264,
"bbox_pt": {
"height": 7.2,
"width": 4.8,
"x": 101.76,
"y": 155.52
"width": 11.52,
"x": 136.32,
"y": 78.24
},
"disposition": {
"class": "glyph-edge-rasterization",
"kind": "accepted-rendering",
"note": "Inspected in the 150 DPI diff and 600 DPI GT/after crops: 'Dear recipient' (D, e, a, r, i, p) differs only in glyph outlines at the same positions, Times New Roman drawn as the metric-compatible Liberation Serif; its start is 0.03pt and its baseline 0.04pt from Word's, unchanged by this fix."
"issue": "#1874",
"kind": "issue",
"note": "\"est marker\" sits 1.05-1.07pt right of Word: Word kerns the T-e pair (e at 88.03pt against our 89.10pt) in this package without a styles part, while the run states no w:kern. The 150 DPI crop shows the same glyphs, outlines and weight, offset by one pair kern; \"T\" matches at 80.55pt against 80.525pt. Sub-material, recorded under #1874."
},
"id": "p1-be741a945e83",
"id": "p1-56013fea6996",
"region": "top-left"
},
{
"area_pt2": 27.8784,
"bbox_pt": {
"height": 7.2,
"width": 6.24,
"x": 227.04,
"y": 78.72
},
"disposition": {
"class": "glyph-edge-rasterization",
"kind": "accepted-rendering",
"note": "Inspected in the 150 DPI diff and 600 DPI GT/after crops: 'About providing information', the paragraph this fix moves 71pt left, now covers Word's glyphs (A, b, o, u, p, r, n, g, a, t) with outline-only differences, Times New Roman drawn as the metric-compatible Liberation Serif; its start is 0.10pt and its baseline 0.09pt from Word's."
},
"id": "p1-1031b376123d",
"region": "top"
},
{
"area_pt2": 24.8832,
"area_pt2": 54.3744,
"bbox_pt": {
"height": 10.08,
"width": 6.72,
"x": 130.08,
"y": 78.72
},
"disposition": {
"class": "glyph-edge-rasterization",
"kind": "accepted-rendering",
"note": "Inspected in the 150 DPI diff and 600 DPI GT/after crops: 'About providing information', the paragraph this fix moves 71pt left, now covers Word's glyphs (A, b, o, u, p, r, n, g, a, t) with outline-only differences, Times New Roman drawn as the metric-compatible Liberation Serif; its start is 0.10pt and its baseline 0.09pt from Word's."
},
"id": "p1-413d1972e343",
"region": "top-left"
},
{
"area_pt2": 23.5008,
"bbox_pt": {
"height": 7.2,
"width": 5.76,
"x": 101.28,
"y": 62.88
},
"disposition": {
"class": "glyph-edge-rasterization",
"kind": "accepted-rendering",
"note": "Inspected in the 150 DPI diff and 600 DPI GT/after crops: 'Recipient' (R, e, c, i) differs only in glyph outlines at the same positions, Word's embedded Times New Roman against this host's metric-compatible Liberation Serif; its start is 0.10pt and its baseline 0.01pt from Word's."
},
"id": "p1-a08c2c33abd1",
"region": "top-left"
},
{
"area_pt2": 23.5008,
"bbox_pt": {
"height": 7.68,
"width": 6.24,
"x": 94.08,
"y": 75.84
},
"disposition": {
"class": "glyph-edge-rasterization",
"kind": "accepted-rendering",
"note": "Inspected in the 150 DPI diff and 600 DPI GT/after crops: 'About providing information', the paragraph this fix moves 71pt left, now covers Word's glyphs (A, b, o, u, p, r, n, g, a, t) with outline-only differences, Times New Roman drawn as the metric-compatible Liberation Serif; its start is 0.10pt and its baseline 0.09pt from Word's."
},
"id": "p1-5c2de5b5fd65",
"region": "top-left"
},
{
"area_pt2": 23.5008,
"bbox_pt": {
"height": 7.2,
"width": 6.24,
"x": 109.44,
"y": 78.72
},
"disposition": {
"class": "glyph-edge-rasterization",
"kind": "accepted-rendering",
"note": "Inspected in the 150 DPI diff and 600 DPI GT/after crops: 'About providing information', the paragraph this fix moves 71pt left, now covers Word's glyphs (A, b, o, u, p, r, n, g, a, t) with outline-only differences, Times New Roman drawn as the metric-compatible Liberation Serif; its start is 0.10pt and its baseline 0.09pt from Word's."
},
"id": "p1-5e660269328d",
"region": "top-left"
},
{
"area_pt2": 20.736,
"bbox_pt": {
"height": 10.56,
"width": 4.8,
"x": 104.16,
"y": 75.36
},
"disposition": {
"class": "glyph-edge-rasterization",
"kind": "accepted-rendering",
"note": "Inspected in the 150 DPI diff and 600 DPI GT/after crops: 'About providing information', the paragraph this fix moves 71pt left, now covers Word's glyphs (A, b, o, u, p, r, n, g, a, t) with outline-only differences, Times New Roman drawn as the metric-compatible Liberation Serif; its start is 0.10pt and its baseline 0.09pt from Word's."
},
"id": "p1-b18b0ac62282",
"region": "top-left"
},
{
"area_pt2": 20.5056,
"bbox_pt": {
"height": 8.64,
"width": 6.24,
"x": 178.56,
"y": 79.68
},
"disposition": {
"class": "glyph-edge-rasterization",
"kind": "accepted-rendering",
"note": "Inspected in the 150 DPI diff and 600 DPI GT/after crops: 'About providing information', the paragraph this fix moves 71pt left, now covers Word's glyphs (A, b, o, u, p, r, n, g, a, t) with outline-only differences, Times New Roman drawn as the metric-compatible Liberation Serif; its start is 0.10pt and its baseline 0.09pt from Word's."
},
"id": "p1-6aeadbc09d9c",
"region": "top-left"
},
{
"area_pt2": 20.2752,
"bbox_pt": {
"height": 6.24,
"width": 6.24,
"x": 95.04,
"y": 155.52
"width": 10.08,
"x": 126.72,
"y": 74.88
},
"disposition": {
"class": "glyph-edge-rasterization",
"kind": "accepted-rendering",
"note": "Inspected in the 150 DPI diff and 600 DPI GT/after crops: 'Dear recipient' (D, e, a, r, i, p) differs only in glyph outlines at the same positions, Times New Roman drawn as the metric-compatible Liberation Serif; its start is 0.03pt and its baseline 0.04pt from Word's, unchanged by this fix."
"issue": "#1874",
"kind": "issue",
"note": "\"est marker\" sits 1.05-1.07pt right of Word: Word kerns the T-e pair (e at 88.03pt against our 89.10pt) in this package without a styles part, while the run states no w:kern. The 150 DPI crop shows the same glyphs, outlines and weight, offset by one pair kern; \"T\" matches at 80.55pt against 80.525pt. Sub-material, recorded under #1874."
},
"id": "p1-4b56a2ad43f4",
"id": "p1-cdf915b18a72",
"region": "top-left"
}
],
Expand All @@ -204,9 +76,9 @@
"schema_version": 1,
"strict": true,
"summary": {
"dispositioned": 12,
"dispositioned": 4,
"duplicate": 0,
"total": 12,
"total": 4,
"undispositioned": 0,
"unknown": 0
},
Expand Down
Binary file added assets/bugfixes/issue-2383/compare.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/bugfixes/issue-2384/compare.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/bugfixes/issue-2385/compare.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/bugfixes/issue-2386/compare.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 27 additions & 4 deletions crates/office2pdf/src/parser/docx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ use self::contexts::{
toc_caption_identifier, toc_heading_depth,
};
use self::lists::{
NumberingMap, TaggedElement, build_numbering_map, extract_num_info, group_into_lists,
NumberingMap, StyleSuppliedIndents, TaggedElement, build_numbering_map, extract_num_info,
group_into_lists,
};
use self::media::{
DrawingTextBoxPlacement, extract_drawing_image, extract_drawing_text_box_blocks,
Expand All @@ -59,8 +60,8 @@ use self::styles::{
use self::tables::{convert_table, convert_table_in_text_box};
use self::text::{
ThemeFonts, WORD_UNSTATED_FONT_SIZE_PT, extract_doc_default_paragraph_style,
extract_doc_default_text_style_with_theme, extract_paragraph_style, extract_run_style,
extract_run_style_id, extract_run_text, extract_run_text_marking_clears,
extract_doc_default_text_style_with_theme, extract_indent, extract_paragraph_style,
extract_run_style, extract_run_style_id, extract_run_text, extract_run_text_marking_clears,
extract_tab_stop_overrides, insert_east_asian_auto_space, is_column_break, is_page_break,
pair_kerning_from_half_points, parse_hex_color, parse_theme_fonts, resolve_hyperlink_url,
resolve_latin_theme_font_family, resolve_theme_font_family, take_clearing_break_markers,
Expand Down Expand Up @@ -1061,6 +1062,25 @@ fn convert_sdt_children(
result
}

/// Which indents a paragraph with a direct `w:numPr` takes from its style
/// chain because its own `w:ind` does not state them. None when the numbering
/// comes from the style.
fn style_supplied_indents(para: &docx_rs::Paragraph, style_map: &StyleMap) -> StyleSuppliedIndents {
if !para.has_numbering {
return StyleSuppliedIndents::default();
}
let (left, _, first_line) = extract_indent(&para.property.indent);
let style: Option<&ParagraphStyle> = get_paragraph_style_id(&para.property)
.and_then(|id| style_map.get(id))
.or_else(|| style_map.get(DOC_DEFAULT_STYLE_ID))
.map(|resolved| &resolved.paragraph);
StyleSuppliedIndents {
left: left.is_none() && style.is_some_and(|style| style.indent_left.is_some()),
first_line: first_line.is_none()
&& style.is_some_and(|style| style.indent_first_line.is_some()),
}
}

fn convert_body_table_block(
source_table: &docx_rs::Table,
images: &ImageMap,
Expand All @@ -1085,7 +1105,10 @@ fn convert_paragraph_element(
ctx: &DocxConversionContext,
styles: &docx_rs::Styles,
) -> Vec<TaggedElement> {
let num_info = extract_num_info(para, styles);
let num_info = extract_num_info(para, styles).map(|mut info| {
info.style_supplied_indents = style_supplied_indents(para, style_map);
info
});

// Build the paragraph IR
let mut blocks = Vec::new();
Expand Down
Loading
Loading