Bug 147989 - The size of a MediaBox of the PDF exported from an A5-paper Writer Document might be wrong (very slightly).
Summary: The size of a MediaBox of the PDF exported from an A5-paper Writer Document m...
Status: NEW
Alias: None
Product: LibreOffice
Classification: Unclassified
Component: Writer (show other bugs)
Version:
(earliest affected)
unspecified
Hardware: x86-64 (AMD64) Windows (All)
: medium normal
Assignee: Not Assigned
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: Page
  Show dependency treegraph
 
Reported: 2022-03-14 21:57 UTC by Lemures Lemniscati
Modified: 2022-12-27 05:42 UTC (History)
3 users (show)

See Also:
Crash report or crash signature:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Lemures Lemniscati 2022-03-14 21:57:42 UTC
Description:
Version: 7.3.1.3 (x64) / LibreOffice Community
Build ID: a69ca51ded25f3eefd52d7bf9a5fad8c90b87951
CPU threads: 8; OS: Windows 10.0 Build 22000; UI render: Skia/Vulkan; VCL: win
Locale: ja-JP (ja_JP); UI: en-US
Calc: threaded


1. Create Writer Document.
2. Select from the menu: Format -> Page Style.
3. Set 'A5' to Format in Page Format, and press OK. (Width = 14.80 cm, Height = 21.00 cm).
4. Select from the menu: File -> Export As -> Export As PDF..., and press Export.
5. Save as sample.pdf
6. Check the box size with pdfinfo (pdfinfo sample.pdf): we'll get
```
Page size:      419.556 x 595.304 pts
```

Weirdly, both of its width and its height are larger by .01 mm
(0.0283464 pts), although they should be 419.528 x 595.276 pts.


Steps to Reproduce:
1. Create Writer Document.
2. Select from the menu: Format -> Page Style.
3. Set 'A5' to Format in Page Format, and press OK. (Width = 14.80 cm, Height = 21.00 cm).
4. Select from the menu: File -> Export As -> Export As PDF..., and press Export.
5. Save as sample.pdf
6. Check the box size with pdfinfo (pdfinfo sample.pdf)


Actual Results:
```
Page size:      419.556 x 595.304 pts
```

Weirdly, both of its width and its height are larger by .01 mm
(0.0283464 pts), although they should be 419.528 x 595.276 pts.



Expected Results:
419.528 x 595.276 pts.



Reproducible: Always


User Profile Reset: No



Additional Info:
This might be related to https://bugs.documentfoundation.org/show_bug.cgi?id=103682#c9
Comment 1 Shinji Enoki 2022-03-15 12:49:27 UTC
I reproduced it. 
I don't know if this is a LibreOffice bug. 

Version: 7.3.1.3 / LibreOffice Community
Build ID: a69ca51ded25f3eefd52d7bf9a5fad8c90b87951
CPU threads: 8; OS: Linux 5.16; UI render: default; VCL: gtk3
Locale: ja-JP (ja_JP.UTF-8); UI: ja-JP
Calc: threaded

$ pdfinfo -v
pdfinfo version 20.09.0
Copyright 2005-2020 The Poppler Developers - http://poppler.freedesktop.org
Copyright 1996-2011 Glyph & Cog, LLC


$ pdfinfo pdf-size.pdf 
Creator:        Writer
Producer:       LibreOffice 7.3
CreationDate:   Tue Mar 15 21:08:56 2022 JST
Tagged:         no
UserProperties: no
Suspects:       no
Form:           none
JavaScript:     no
Pages:          1
Encrypted:      no
Page size:      419.556 x 595.304 pts
Page rot:       0
File size:      9992 bytes
Optimized:      no
PDF version:    1.6
Comment 2 Julien Nabet 2022-03-20 09:33:42 UTC
On pc Debian x86-64 with master sources updated yesterday, I noticed some stra

In PDFExport::ExportSelection (filter/source/pdf/pdfexport.cxx:246), I noticed this:
(gdb) p aPageSize
$19 = {Width = 14801, Height = 21001}

I would have expected:
$19 = {Width = 14800, Height = 21000}

I'm trying to dig in SwXTextDocument::getRenderer (sw/source/uibase/uno/unotxdoc.cxx:2673)
Comment 3 Julien Nabet 2022-03-20 09:33:59 UTC
... some strange values.
Comment 4 Julien Nabet 2022-03-20 10:18:22 UTC
Here's a code pointer:
#0  SwLayoutFrame::Lower() const (this=0x5a3a750) at sw/source/core/inc/layfrm.hxx:101
#1  0x00007fa9a333d5b4 in SwViewShell::GetPageSize(unsigned short, bool) const (this=0x5a36090, nPageNum=1, bSkipEmptyPages=true) at sw/source/core/view/viewsh.cxx:2686
#2  0x00007fa9a3ac7c89 in SwXTextDocument::getRenderer(int, com::sun::star::uno::Any const&, com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) (this=0x5909430, nRenderer=0, rSelection=
    uno::Any("com.sun.star.lang.XComponent": {<com::sun::star::uno::XInterface> = {_vptr$XInterface = 0x5909608}, <No data fields>}), rxOptions=uno::Sequence of length 8 = {...})
    at sw/source/uibase/uno/unotxdoc.cxx:2734
#3  0x00007fa9a3ac8d40 in non-virtual thunk to SwXTextDocument::getRenderer(int, com::sun::star::uno::Any const&, com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) ()
    at sw/source/uibase/uno/unotxdoc.cxx:2823
#4  0x00007fa96c6da28b in PDFExport::ExportSelection(vcl::PDFWriter&, com::sun::star::uno::Reference<com::sun::star::view::XRenderable> const&, com::sun::star::uno::Any const&, StringRangeEnumerator const&, com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>&, int) (this=0x7ffca9bd2a10, rPDFWriter=..., rRenderable=uno::Reference to (SwXTextDocument *) 0x59096e8, rSelection=
    uno::Any("com.sun.star.lang.XComponent": {<com::sun::star::uno::XInterface> = {_vptr$XInterface = 0x5909608}, <No data fields>}), rRangeEnum=..., rRenderOptions=uno::Sequence of length 8 = {...}, nPageCount=1) at filter/source/pdf/pdfexport.cxx:186
#5  0x00007fa96c6df97a in PDFExport::Export(rtl::OUString const&, com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&)
    (this=0x7ffca9bd2a10, rFile="file:///tmp/lu1ib4w.tmp/lu1ib5o.tmp", rFilterData=uno::Sequence of length 53 = {...}) at filter/source/pdf/pdfexport.cxx:987

(gdb) p *pTmpRoot->Lower()
$32 = {<SwFrameAreaDefinition> = {_vptr$SwFrameAreaDefinition = 0x7fa9a4761340 <vtable for SwPageFrame+16>, maFrameArea = SwRect = {point = Point = {x = 9755, y = 284}, size = Size = {width = 8391, 
        height = 11906}}, maFramePrintArea = SwRect = {point = Point = {x = 1134, y = 1134}, size = Size = {width = 6123, height = 9638}}, mbFrameAreaPositionValid = true, mbFrameAreaSizeValid = true, 
    mbFramePrintAreaValid = true, static snLastFrameId = 4, mnFrameId = 1}, <SwClient> = {<sw::WriterListener> = {_vptr$WriterListener = 0x7fa9a4761488 <vtable for SwPageFrame+344>, m_pLeft = 0x0, 
      m_pRight = 0x0}, m_pRegisteredIn = 0x5958d18}, <SfxBroadcaster> = {_vptr$SfxBroadcaster = 0x7fa9a47614d0 <vtable for SwPageFrame+416>, m_RemovedPositions = std::__debug::vector of length 0, capacity 0, 
    m_Listeners = std::__debug::vector of length 0, capacity 0}, static spCache = 0x5918d10, mpRoot = 0x5a3a750, mpUpper = 0x5a3a750, mpNext = 0x0, mpPrev = 0x0, m_pDrawObjs = std::unique_ptr<SwSortedObjs> = {
    get() = 0x0}, mnFrameType = SwFrameType::Page, mbInDtor = false, mbInvalidR2L = false, mbDerivedR2L = false, mbRightToLeft = false, mbInvalidVert = false, mbDerivedVert = false, mbVertical = false, 
  mbVertLR = false, mbVertLRBT = false, mbValidLineNum = false, mbFixSize = true, mbCompletePaint = true, mbRetouche = false, mbInfInvalid = false, mbInfBody = false, mbInfTab = false, mbInfFly = false, 
  mbInfFootnote = false, mbInfSct = false, mbColLocked = false, m_isInDestroy = false, mbForbidDelete = false}

and using https://www.translatorscafe.com/unit-converter/fr-FR/typography/4-1/millimeter-twip/
8391 gives 148.0079166667 which gives 148.01
11906 gives 210.0086111111 which gives 210.01

I think the root cause is the accumulation of roundings.
Comment 5 Lemures Lemniscati 2022-03-20 10:29:55 UTC
Sorry with the old version.

> I think the root cause is the accumulation of roundings.

I agree. Thank you.


----
This was another test.


Even when I did save it as a .odt file, the size was slightly wrong.

バージョン: 6.4.0.3 (x64)
Build ID: b0a288ab3d2d4774cb44b62f04d5d28733ac6df8
CPU threads: 8; OS:Windows 10.0 Build 22000; UI render: default; VCL: win; 
ロケール: ja-JP (ja_JP); UIの言語: ja-JP
Calc: threaded


----
1. Create Writer Document.
2. Select from the menu: Format -> Page Style.
3. Set 'A5' to Format in Page Format, and press OK. (Width = 14.80 cm, Height = 21.00 cm).
4. Select from the menu: File -> Save As
5. Save as sample-a5.odt
6. unzip -p sample-a5.odt styles.xml | sed -ze 's|^.*\(<style:page-layout-properties\)|\1|;s|\(</style:page-layout-properties>\).*$|\1|;'

I got:

<style:page-layout-properties fo:page-width="14.801cm" fo:page-height="21.001cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:footnote-max-height="0cm"><style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/></style:page-layout-properties>

The widht and height are
  fo:page-width="14.801cm"
  fo:page-height="21.001cm"
----


And even when creating a new document and save is as sample-a4.odt:

1. Create Writer Document.
2. Select from the menu: Format -> Page Style.
4. Select from the menu: File -> Save As
5. Save as sample-a4.odt
6. unzip -p sample-a4.odt styles.xml | sed -ze 's|^.*\(<style:page-layout-properties\)|\1|;s|\(</style:page-layout-properties>\).*$|\1|;'

I got

<style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:footnote-max-height="0cm"><style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/></style:page-layout-properties>

The widht and height are
  fo:page-width="21.001cm"
  fo:page-height="29.7cm"
----
Comment 6 Lemures Lemniscati 2022-03-20 10:51:20 UTC
> > I think the root cause is the accumulation of roundings.

> I agree. Thank you.

To use at most 2 digits after the decimal point when outputting a page size (width and height) in cm, could be a solution...
Comment 7 Julien Nabet 2022-03-20 10:53:42 UTC
I gave a try with https://gerrit.libreoffice.org/c/core/+/131875 but really not sure it's the right way.
Comment 8 Lemures Lemniscati 2022-03-20 11:05:14 UTC
> To use at most 2 digits after the decimal point when outputting a page size (width and height) in cm, could be a solution...

Sorry, this makes precision worse...

Please forget it.
Comment 9 Julien Nabet 2022-03-20 11:31:22 UTC
(In reply to Lemures Lemniscati from comment #8)
> ...
> Please forget it.

Before seeing your comment, I used this on my patch. I think the max precision to retrieve page size is 2 decimals after cm (or 1 after mm).
Eg "Legal" 21.59x35.56 cm seems the most precise.
Comment 10 Lemures Lemniscati 2022-03-20 11:41:24 UTC
Maybe a right solution for this is making the internal unit smaller.
The smaller the internal unit, the smaller the chances of errors.

As an estimation:

When the internal unit is 1/10 twips, rounding to 0.01 cm makes no error.
When the internal unit is 1/100 twips, rounding to 0.001 cm makes no error.
Comment 11 Lemures Lemniscati 2022-03-20 17:13:08 UTC
> When the internal unit is 1/10 twips, rounding to 0.01 cm makes no error.
> When the internal unit is 1/100 twips, rounding to 0.001 cm makes no error.

Sorry, I calculated them in mm instead of cm.
You are right, Julien.

When the internal unit is twip, rounding to 0.01 cm makes no error.
When the internal unit were 1/10 twip, rounding to 0.001 cm would make no error.
Comment 12 Lemures Lemniscati 2022-03-20 18:41:43 UTC
> I gave a try with https://gerrit.libreoffice.org/c/core/+/131875

Maybe this kind of conversion is required in other situations (calc, draw, etc.).

So, it would be useful to add a defition of convertTwipToMm10() to 
`include/tools/UnitConversion.hxx`:
----
template <typename N> constexpr auto convertTwipToMm10(N n)
{
    return o3tl::convert(n, o3tl::Length::twip, o3tl::Length::mm10);
}
----


And if the defintion is accepted, the new code in https://gerrit.libreoffice.org/c/core/+/131875 can be simply rewritten:
----
            // tdf#147989: workaround the accumulation of roundings
            aPageSize = awt::Size ( 10 * convertTwipToMm10( aTmpSize.Width() ),
                                    10 * convertTwipToMm10( aTmpSize.Height() ));
----
Comment 13 Julien Nabet 2022-03-20 19:20:16 UTC
Caolán: thought you might have some opinion about https://bugs.documentfoundation.org/show_bug.cgi?id=147989#c12  (related with https://gerrit.libreoffice.org/c/core/+/131875)
Comment 14 Caolán McNamara 2022-03-21 10:27:08 UTC
another thing we have is include/i18nutil/paper.hxx and "doSloppyFit" which snaps page dimensions to real paper sizes when they are close enough to be typically rounding errors away from their intended size
Comment 15 Julien Nabet 2022-03-21 15:04:01 UTC
(In reply to Caolán McNamara from comment #14)
> another thing we have is include/i18nutil/paper.hxx and "doSloppyFit" which
> snaps page dimensions to real paper sizes when they are close enough to be
> typically rounding errors away from their intended size

Indeed, I got:
git grep -n GetSvxPaper
cui/source/tabpages/page.cxx:481:    Paper ePaper = SvxPaperInfo::GetSvxPaper( aPaperSize, MapUnit::Map100thMM );
cui/source/tabpages/page.cxx:1000:    Paper ePaper = SvxPaperInfo::GetSvxPaper( aSize, eUnit );
editeng/source/items/paperinf.cxx:85:Paper SvxPaperInfo::GetSvxPaper( const Size &rSize, MapUnit eUnit )
include/editeng/paperinf.hxx:42:    static Paper    GetSvxPaper( const Size &rSize, MapUnit eUnit );
sc/source/ui/view/printfun.cxx:2635:    Paper ePaper = SvxPaperInfo::GetSvxPaper( aEnumSize, MapUnit::MapTwip );
sd/source/ui/sidebar/SlideBackground.cxx:920:                Paper ePaper = SvxPaperInfo::GetSvxPaper(aPaperSize, meUnit);
sw/source/ui/envelp/envfmt.cxx:136:        Paper ePaper = SvxPaperInfo::GetSvxPaper(
sw/source/ui/envelp/envfmt.cxx:394:    Paper ePaper = SvxPaperInfo::GetSvxPaper(
sw/source/uibase/sidebar/PageFormatPanel.cxx:175:                Paper ePaper = SvxPaperInfo::GetSvxPaper(aPaperSize, meUnit);

Now I don't know the best location where it should be called and not sure the location I changed (sw/source/uibase/uno/unotxdoc.cxx) is the best part.