Bug 172113 - Line spacing calculated differently (or buggy) in LO compared to Microsoft Office
Summary: Line spacing calculated differently (or buggy) in LO compared to Microsoft Of...
Status: RESOLVED FIXED
Alias: None
Product: LibreOffice
Classification: Unclassified
Component: Writer (show other bugs)
Version:
(earliest affected)
Inherited From OOo
Hardware: All All
: medium normal
Assignee: Justin L
URL:
Whiteboard: target:27.2.0 inReleaseNotes:27.2
Keywords:
Depends on: 172169 172233
Blocks: Paragraph-Line-Spacing
  Show dependency treegraph
 
Reported: 2026-05-15 23:58 UTC by Justin L
Modified: 2026-07-01 03:27 UTC (History)
6 users (show)

See Also:
Crash report or crash signature:


Attachments
137335_linespacing.odt: various line spacing issues illustrated (26.77 KB, application/vnd.oasis.opendocument.text)
2026-05-15 23:58 UTC, Justin L
Details
137335_linespacing.mso2010.pdf: how it looks in MS Word 2010 (and 2024) (101.03 KB, application/pdf)
2026-05-16 12:29 UTC, Justin L
Details
172113_linespacingFirstLine.docx: LO doesn't use first line's height for line spacing calculation (5.15 KB, application/vnd.openxmlformats-officedocument.wordprocessingml.document)
2026-05-16 12:34 UTC, Justin L
Details
172113_linespacingFirstLine.mso2010.pdf: how it looks in MS Word 2010 (and 2024) (20.48 KB, application/pdf)
2026-05-16 12:35 UTC, Justin L
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Justin L 2026-05-15 23:58:25 UTC
Created attachment 207092 [details]
137335_linespacing.odt: various line spacing issues illustrated

Line spacing is an interesting beast.

The first problem is how to even define what ought to happen. Think about it. A paragraph can span multiple lines, and each line can contain several differently sized characters. So how do you define the size of the requested gap?

The answer is NOT simply based on the paragraph's default font/size. Both LO and MS Word calculate the maximum height of each line individually and thus determine a unique line spacing height for each line. So far so good.

So where do you put that line spacing gap? LO seems to put it above the line, while MS Word apparently puts it below the line. [Oh well - sigh]

So what elements determine the height of the line spacing? LO says pretty much everything (except for images and tabstops) does. MSO also excludes the size of spaces and tabstops (unless those are the only things on a non-last line) as well as excluding bullets/numbering. [Since 25.2 we handle DOCX spaces and tabstops OK, but we don't ignore numbering.]


And then there is the question of how to handle the spacing in between two paragraphs? I think the answer is easy for MS Word, since it puts the spacing below the line already. So of course it is just based on the line spacing of the last line of the first paragraph - the second paragraph is not involved at all.
For LO the answer is similar - in order to be somewhat interoperable with MSO. This works because LO does NOT normally apply a paragraph's defined line spacing above the first row, so when it follows another paragraph, it can simply again add the previous paragraph's final line spacing above the first row.

[Currently that is a bit buggy because LO does a simplistic re-calculation for  mnHeightOfLastLine instead of re-using the value it already calculated/applied.]


Please note that this explanation was just based on what I see happening as I use LibreOffice. It was not confirmed that this is how it actually happens at the code level.

Steps to reproduce:
-open 137335_linespacing.odt and save as DOCX
-compare how LO and MSO handle the different situations
Comment 1 Justin L 2026-05-16 12:29:01 UTC
Created attachment 207102 [details]
137335_linespacing.mso2010.pdf: how it looks in MS Word 2010 (and 2024)
Comment 2 Justin L 2026-05-16 12:34:58 UTC
Created attachment 207103 [details]
172113_linespacingFirstLine.docx: LO doesn't use first line's height for line spacing calculation

(In reply to Justin L from comment #0)
> So where do you put that line spacing gap? LO seems to put it above the
> line, while MS Word apparently puts it below the line.
This rather silly LO implementation results in a complete inability to be fully interoperable with MS Word. Plus it just looks worse, and ends up being overly complicated.
Comment 3 Justin L 2026-05-16 12:35:31 UTC
Created attachment 207104 [details]
172113_linespacingFirstLine.mso2010.pdf: how it looks in MS Word 2010 (and 2024)
Comment 4 Justin L 2026-05-19 12:43:01 UTC
(In reply to Justin L from comment #0)
> So what elements determine the height of the line spacing? LO says pretty
> much everything (except for images and tabstops) does.
This needs to be qualified - it is different for inside-the-paragraph gaps and between-paragraph gaps.

bug 172169: For inside-the-paragraph gaps, before 7.1 (almost) everything affected the line spacing height. Since 7.1, only plain text (SwTextPortion) determines line-spacing the gaps inside the paragraph. (Thus tabstops, fields, footnotes, hidden text currently are ignored.)

Of course, note that in LO the first line (of multi-line paragraphs) never affects anything - so bullets/numbering/dropCaps never came into play.

For between-paragraph gaps, pretty much everything  on the last line (including tabstops) (excluding images) affects the line-spacing height.
Comment 5 Justin L 2026-05-26 14:20:08 UTC
Not surprisingly, the ODT specification is rather silent on the specifics of this - especially up to version 1.3. Version 1.4 did add the following in relation to this topic of proportional line spacing:

-----
20.204 fo:line-height
a value of type percent: The font-size is multiplied with the percent value. In case the line contains content of descendants of the paragraph, for which a different font-size is specified, the maximum of the font-sizes is used. This calculated value is a minimum line-height. If content would vertically overflow the line area, e.g. an image with a larger specified height, the height of the line is increased till the content does not overflow. The vertical position of the baseline is implementation-dependent. In case a style:line- height-at-least 20.317 or a style:line-spacing 20.318 attribute occurs in addition in the same element, the attribute fo:line-height 20.204 has precedence.
-----

So it really doesn't give any real guidance here - everything is left up to the 'implementation' and there is no 'right way' to do things.

DOCX specification is not even that clear.
example: <w:spacing w:line="276" w:lineRule="auto" />  #115% since 240 is 100%
-----
17.3.1.33 spacing (Spacing Between Lines and Above/Below Paragraph)
... and that the spacing in each line should be automatically calculated based on a 1.15 times (276 divided by 240) the normal single spacing calculation.
-----

So DOCX only specifies how to read the proportional value, but gives no guidance as to what it means for the document layout itself.
Comment 6 Justin L 2026-05-29 18:14:34 UTC
(In reply to Justin L from comment #4)
> Since 7.1, only plain text (SwTextPortion)
> determines the line-spacing gaps inside the paragraph.
This also needs to be qualified.

In LO, even if a non-determining-portion (tabstop, bidi, rotated text, field) does not normally affect the line-spacing, it does if it is the very first portion in the line. So 7.1's change was not all-encompassing - although that ends up being a good thing for uniform paragraphs (of Bidi text for example).

Note that in LO it is not the 'height' of these things that matters, but their 'font size'. So, although rotated text or images might take up a lot of height, the line spacing gap will only be affected (via CalcAscent) if the font itself is different. But of course for most things the portion height and font height are equivalent.

[It is probably worth repeating that the observations in this comment exclude the very first line (which LO totally ignores for line spacing purposes) and it also excludes the gap after the last line (which LO determines using the height of basically everything).]
Comment 7 Justin L 2026-05-29 18:44:07 UTC
I have a nearly finished chain of WIP commits ready, starting at https://gerrit.libreoffice.org/c/core/+/205234.

I used https://gerrit.libreoffice.org/c/core/+/205316 to discover many things, so it has good debugging info in its earlier patchsets.


In addition to InTextGrp, it appears that MutliPortion generally should also be included, so I added Bidi and RotatedText. DoubleLineText also should be added, and so I guess that RubyPortions should as well.


One remaining thing that has proved tricky is when IsTextPortion HasOnlyBlanks. I probably need to extend the Portions class to hold a bHasOnlyBlanks flag.
Comment 8 Michael Stahl 2026-06-01 14:39:41 UTC
(In reply to Justin L from comment #5)
> Not surprisingly, the ODT specification is rather silent on the specifics of
> this - especially up to version 1.3. Version 1.4 did add the following in
> relation to this topic of proportional line spacing:

this was changed for issue https://issues.oasis-open.org/browse/OFFICE-3997 based on Regina's analysis, might want to compare if you've got the same understanding.
Comment 9 Justin L 2026-06-01 16:34:14 UTC
(In reply to Michael Stahl from comment #8)
It seems the analysis was done in 2018, so probably using LO 6.1. The result of the analysis was the changed ODF 1.3->1.4 wording documented in comment 5. Thanks for pointing out the URL that lead to that change, mstahl.

> (A) value type 'percent' with span-element
Sounds good. I think it says the same thing as my 'Both LO and MS Word calculate the maximum height of each line individually and thus determine a unique line spacing height for each line.'

> (B) case value type 'percent' with image as child-element
> Only LibreOffice applies the percentage value to the height of the image.
> I consider this as bug in LibreOffice.
Agree that this was a bug. I believe this was 'fixed' in LO 7.1 (comment 4).

> (C) case value type 'length'
Irrelevant for this discussion of "proportional".

> (D) distribution of additional leading
> As result the previous and the next line are at the same position
> in Word and LibreOffice...
See comment 4 about this. I consider LO's implementation to be buggy. My set of patches ought to make this statement become true.

My patchset should also match Word's 'place gap below' ("Word seems to calculate like this: Add the height which is calculated from the paragraph font-size to the top of the previous line, downwards").
Comment 10 Jonathan Clark 2026-06-25 14:45:39 UTC
I agree documents will look better with these changes, so I'm confirming this bug. We can always change the values of compatibility flags later on if needed.
Comment 11 Commit Notification 2026-06-26 23:29:57 UTC
Justin Luth committed a patch related to this issue.
It has been pushed to "master":

https://git.libreoffice.org/core/commit/d896865f48648d5f7c599d3654b487bae67f2d8d

tdf#172113 sw MaxAscentDescent: ignore PostItsPortion

It will be available in 27.2.0.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.
Comment 12 Commit Notification 2026-06-26 23:31:03 UTC
Justin Luth committed a patch related to this issue.
It has been pushed to "master":

https://git.libreoffice.org/core/commit/d4721108782cd3bb07c78b31db08ed78894d150b

tdf#172113 sw line spacing: introduce LINE_SPACING_AS_GAP_BELOW

It will be available in 27.2.0.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.
Comment 13 Commit Notification 2026-06-26 23:32:22 UTC
Justin Luth committed a patch related to this issue.
It has been pushed to "master":

https://git.libreoffice.org/core/commit/4031fa9b9aea40ca36b7fd100950f42d5f23f762

tdf#172113 sw ms import: consistent linespacing gap height

It will be available in 27.2.0.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.
Comment 14 Commit Notification 2026-06-26 23:32:24 UTC
Justin Luth committed a patch related to this issue.
It has been pushed to "master":

https://git.libreoffice.org/core/commit/10a3c6589990673c8d340dca7390450dfd7c5603

tdf#172113 sw line spacing: additional unit test / cleanup

It will be available in 27.2.0.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.
Comment 15 Justin L 2026-06-26 23:34:11 UTC
This is the (reverse) order of the patchset:
tdf#172113 sw line spacing: additional unit test / cleanup
tdf#172113 sw ms import: consistent linespacing gap height
tdf#172233 sw: apply line spacing gap after the line, not before
tdf#172169 sw ms import: 1st portion shouldn't define min linespace
tdf#172169 sw ms import: IsMultiPortion IsUsedToCalcLineSpacingHeight
tdf#172169 sw line spacing: InsertPortion max for LineSpacingBaseHeight
tdf#172169 sw line spacing: CalcLine max for LineSpacingBaseHeight
tdf#172169 sw ms import: line portion IsUsedToCalcLineSpacingHeight
tdf#172113 sw line spacing: introduce LINE_SPACING_AS_GAP_BELOW
tdf#172169 sw line spacing: SwFootnotePortion != IsTextFrame
tdf#172113 sw MaxAscentDescent: ignore PostItsPortion
Comment 16 Commit Notification 2026-07-01 03:26:56 UTC
Justin Luth committed a patch related to this issue.
It has been pushed to "master":

https://git.libreoffice.org/core/commit/20fa66f440a4ceb9d467a559e321dd6045646308

tdf#172113 sw line spacing: user can change LINE_SPACING_AS_GAP_BELOW

It will be available in 27.2.0.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.
Comment 17 Commit Notification 2026-07-01 03:26:59 UTC
Justin Luth committed a patch related to this issue.
It has been pushed to "master":

https://git.libreoffice.org/core/commit/4ea468fd3b37158d67238204412edbc76e3765fe

tdf#172113 sw line spacing: user can no longer set OLD_LINE_SPACING

It will be available in 27.2.0.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.