bin/find-can-be-private-symbols.functions.results          |    5 
 configure.ac                                               |    4 
 cui/source/tabpages/paragrph.cxx                           |   10 
 cui/uiconfig/ui/optviewpage.ui                             |    3 
 dbaccess/source/ui/relationdesign/RTableConnectionData.cxx |    5 
 dbaccess/source/ui/relationdesign/RelationTableView.cxx    |   10 
 download.lst                                               |    8 
 drawinglayer/source/primitive2d/textlayoutdevice.cxx       |   67 
 drawinglayer/source/processor2d/vclprocessor2d.cxx         |   28 
 editeng/source/editeng/impedit3.cxx                        |    2 
 extras/source/tipoftheday/formdocuments.svg                |    2 
 include/drawinglayer/primitive2d/textlayoutdevice.hxx      |    2 
 include/formula/tokenarray.hxx                             |    2 
 include/svl/numformat.hxx                                  |   31 
 include/svl/zformat.hxx                                    |   12 
 include/vcl/outdev.hxx                                     |    7 
 include/vcl/vcllayout.hxx                                  |    5 
 odk/docs/install.html                                      |    2 
 readlicense_oo/license/CREDITS.fodt                        | 3327 ++++++-------
 sc/Module_sc.mk                                            |    7 
 sc/inc/interpretercontext.hxx                              |    4 
 sc/qa/uitest/pasteSpecial/tdf160765.py                     |  109 
 sc/qa/unit/data/ods/tdf160329_sortWithHiddenRows.ods       |binary
 sc/qa/unit/scshapetest.cxx                                 |   37 
 sc/source/core/data/queryevaluator.cxx                     |    2 
 sc/source/core/data/table3.cxx                             |   78 
 sc/source/core/tool/interpr4.cxx                           |   49 
 sc/source/ui/miscdlgs/inscodlg.cxx                         |    4 
 sc/source/ui/navipi/content.cxx                            |    2 
 sc/source/ui/view/viewfun3.cxx                             |    3 
 sc/uiconfig/scalc/ui/conditionalentry.ui                   |  343 -
 sd/qa/unit/data/odg/adjust-to-contour.fodg                 |   52 
 sd/qa/unit/layout-tests.cxx                                |   48 
 sfx2/source/doc/objstor.cxx                                |    6 
 svgio/inc/svgcharacternode.hxx                             |    8 
 svgio/inc/svgstyleattributes.hxx                           |    8 
 svgio/qa/cppunit/SvgImportTest.cxx                         |  150 
 svgio/qa/cppunit/data/contextStroke.svg                    |   14 
 svgio/qa/cppunit/data/tdf160773.svg                        |    5 
 svgio/source/svgreader/svgcharacternode.cxx                |  115 
 svgio/source/svgreader/svgdocumenthandler.cxx              |   83 
 svgio/source/svgreader/svgmarkernode.cxx                   |    2 
 svgio/source/svgreader/svgstyleattributes.cxx              |   38 
 svl/source/items/itemset.cxx                               |   18 
 svl/source/numbers/zforlist.cxx                            |   15 
 svl/source/numbers/zformat.cxx                             |   12 
 svx/source/dialog/svxruler.cxx                             |    2 
 sw/qa/core/text/data/Broken indent demo.odt                |binary
 sw/qa/core/text/data/tdf156146.fodt                        |  281 +
 sw/qa/core/text/text.cxx                                   |   62 
 sw/qa/extras/odfexport/odfexport2.cxx                      |    6 
 sw/qa/extras/uiwriter/data/table-in-table.fodt             |   29 
 sw/qa/extras/uiwriter/uiwriter9.cxx                        |   14 
 sw/qa/uitest/writer_tests2/formatParagraph.py              |    2 
 sw/source/core/crsr/crsrsh.cxx                             |   12 
 sw/source/core/text/inftxt.hxx                             |    6 
 sw/source/core/text/itratr.hxx                             |    2 
 sw/source/core/text/itrtxt.hxx                             |    2 
 sw/source/filter/html/htmlctxt.cxx                         |    3 
 sysui/desktop/menus/calc.desktop                           |    2 
 sysui/desktop/menus/draw.desktop                           |    2 
 sysui/desktop/menus/impress.desktop                        |    2 
 sysui/desktop/menus/math.desktop                           |    2 
 sysui/desktop/menus/writer.desktop                         |    2 
 vcl/inc/qt5/QtTransferable.hxx                             |   31 
 vcl/qa/cppunit/graphicfilter/filters-webp-test.cxx         |   12 
 vcl/qa/cppunit/pdfexport/pdfexport2.cxx                    |    6 
 vcl/qt5/QtClipboard.cxx                                    |    2 
 vcl/qt5/QtTransferable.cxx                                 |   81 
 vcl/skia/gdiimpl.cxx                                       |    2 
 vcl/source/app/svapp.cxx                                   |    1 
 vcl/source/bitmap/BitmapEx.cxx                             |   11 
 vcl/source/filter/webp/reader.cxx                          |    4 
 vcl/source/gdi/pdfwriter_impl.cxx                          |   14 
 vcl/source/gdi/sallayout.cxx                               |   33 
 vcl/source/outdev/map.cxx                                  |    8 
 vcl/source/outdev/text.cxx                                 |   38 
 vcl/win/gdi/DWriteTextRenderer.cxx                         |   11 
 xmloff/source/text/XMLTextListBlockContext.hxx             |    1 
 xmloff/source/text/txtimp.cxx                              |   64 
 80 files changed, 3249 insertions(+), 2245 deletions(-)

New commits:
commit 470f00694ac42fd07a55d6fbea5a56a28791fcc0
Author:     Aron Budea <aron.bu...@collabora.com>
AuthorDate: Wed May 8 13:23:00 2024 +0200
Commit:     Aron Budea <aron.bu...@collabora.com>
CommitDate: Wed May 8 13:23:00 2024 +0200

    Bump version to 24.04.2.1
    
    Change-Id: I27a048323e6f65273688955bdac97dd4f312d88f

diff --git a/configure.ac b/configure.ac
index 745788dc5525..f788bb346a2b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -9,7 +9,7 @@ dnl in order to create a configure script.
 # several non-alphanumeric characters, those are split off and used only for 
the
 # ABOUTBOXPRODUCTVERSIONSUFFIX in openoffice.lst. Why that is necessary, no 
idea.
 
-AC_INIT([Collabora Office],[24.04.1.4],[],[],[https://collaboraoffice.com/])
+AC_INIT([Collabora Office],[24.04.2.1],[],[],[https://collaboraoffice.com/])
 
 dnl libnumbertext needs autoconf 2.68, but that can pick up autoconf268 just 
fine if it is installed
 dnl whereas aclocal (as run by autogen.sh) insists on using autoconf and fails 
hard
commit 56097e5efdb85b3846a0c2536d3e45c0ab566b87
Author:     Xisco Fauli <xiscofa...@libreoffice.org>
AuthorDate: Thu Apr 25 15:52:29 2024 +0200
Commit:     Aron Budea <aron.bu...@collabora.com>
CommitDate: Wed May 8 08:13:58 2024 +0200

    svx: Avoid divide by 0
    
    See 
https://crashreport.libreoffice.org/stats/signature/SvxRuler::UpdateTabs()
    
    Change-Id: Ie08c54d1a1b40bcc42da9f81c893f496fff433a8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166626
    Tested-by: Jenkins
    Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    (cherry picked from commit 90548039f09d4bc773bf6879a62d544adfa175db)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166674
    Reviewed-by: Aron Budea <aron.bu...@collabora.com>
    (cherry picked from commit 35c0afcf0a0428670e3e1998f222440b504ae0c8)

diff --git a/svx/source/dialog/svxruler.cxx b/svx/source/dialog/svxruler.cxx
index 6323583fd271..17c4edaa930d 100644
--- a/svx/source/dialog/svxruler.cxx
+++ b/svx/source/dialog/svxruler.cxx
@@ -1033,7 +1033,7 @@ void SvxRuler::UpdateTabs()
             lCurrentDefTabDist = mxTabStopItem->GetDefaultDistance();
         tools::Long nDefTabDist = ConvertHPosPixel(lCurrentDefTabDist);
 
-        const sal_uInt16 nDefTabBuf = lPosPixel > lRightIndent || lLastTab > 
lRightIndent
+        const sal_uInt16 nDefTabBuf = lPosPixel > lRightIndent || lLastTab > 
lRightIndent || nDefTabDist == 0
                     ? 0
                     : static_cast<sal_uInt16>( (lRightIndent - lPosPixel) / 
nDefTabDist );
 
commit 1c06adec8df9c6add4681d8c2554cde765e91144
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Sun May 5 20:54:59 2024 +0100
Commit:     Aron Budea <aron.bu...@collabora.com>
CommitDate: Wed May 8 08:13:48 2024 +0200

    wrong ScContentTree::SelectEntryByName early return condition
    
    Change-Id: I974f5aea545a80b0e48b50e2a2eae0729ff59691
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167174
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Tested-by: Jenkins
    (cherry picked from commit 18b70ec7d9c4a0288f206cb64708f87a83789c00)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167085
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>
    (cherry picked from commit fb7e3ebf22a120fa0055d556616aeb69abe49bec)

diff --git a/sc/source/ui/navipi/content.cxx b/sc/source/ui/navipi/content.cxx
index d16f61411016..5694fe40fe84 100644
--- a/sc/source/ui/navipi/content.cxx
+++ b/sc/source/ui/navipi/content.cxx
@@ -1451,7 +1451,7 @@ void ScContentTree::SelectEntryByName(const ScContentId 
nRoot, std::u16string_vi
 {
     weld::TreeIter* pParent = m_aRootNodes[nRoot].get();
 
-    if (pParent || !m_xTreeView->iter_has_child(*pParent))
+    if (!pParent || !m_xTreeView->iter_has_child(*pParent))
         return;
 
     std::unique_ptr<weld::TreeIter> 
xEntry(m_xTreeView->make_iterator(pParent));
commit 428767c907b476ffcd5573abbdef58a08289729f
Author:     Xisco Fauli <xiscofa...@libreoffice.org>
AuthorDate: Tue Apr 23 11:54:47 2024 +0200
Commit:     Aron Budea <aron.bu...@collabora.com>
CommitDate: Wed May 8 08:13:40 2024 +0200

    tdf#159661, tdf#160773: svgio: Add unittest
    
    Change-Id: I2d0b96f13e02ac81b97ea347889c76770c22a989
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166509
    Tested-by: Jenkins
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167053
    (cherry picked from commit b2dc48571714a84b1eeff127e86c07b29b579e43)

diff --git a/svgio/qa/cppunit/SvgImportTest.cxx 
b/svgio/qa/cppunit/SvgImportTest.cxx
index dc900b1eee1e..48b8d89bfeee 100644
--- a/svgio/qa/cppunit/SvgImportTest.cxx
+++ b/svgio/qa/cppunit/SvgImportTest.cxx
@@ -1976,6 +1976,22 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf156837)
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"text"_ostr, "3");
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testTdf160773)
+{
+    xmlDocUniquePtr pDocument = 
dumpAndParseSvg(u"/svgio/qa/cppunit/data/tdf160773.svg");
+
+    // tdf#160773 Check there is a rectangle
+    assertXPath(pDocument, 
"/primitive2D/transform/mask/transform/polypolygoncolor"_ostr, "color"_ostr, 
"#ff0000");
+
+    // tdf#159661 Check there is text in the right position
+    assertXPath(pDocument, 
"/primitive2D/transform/mask/transform/textsimpleportion"_ostr, 1);
+    assertXPath(pDocument, 
"/primitive2D/transform/mask/transform/textsimpleportion"_ostr, "x"_ostr, "0");
+    assertXPath(pDocument, 
"/primitive2D/transform/mask/transform/textsimpleportion"_ostr, "y"_ostr, "0");
+    assertXPath(pDocument, 
"/primitive2D/transform/mask/transform/textsimpleportion"_ostr, "height"_ostr, 
"0");
+    assertXPath(pDocument, 
"/primitive2D/transform/mask/transform/textsimpleportion"_ostr, "width"_ostr, 
"0");
+    assertXPath(pDocument, 
"/primitive2D/transform/mask/transform/textsimpleportion"_ostr, "text"_ostr, 
"Red");
+}
+
 CPPUNIT_TEST_FIXTURE(Test, testTdf156271)
 {
     Primitive2DSequence aSequence = 
parseSvg(u"/svgio/qa/cppunit/data/tdf156271.svg");
diff --git a/svgio/qa/cppunit/data/tdf160773.svg 
b/svgio/qa/cppunit/data/tdf160773.svg
new file mode 100644
index 000000000000..812c0824862c
--- /dev/null
+++ b/svgio/qa/cppunit/data/tdf160773.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" ?>
+<svg width="600px" height="600px" viewBox="0 0 1 1" 
xmlns="http://www.w3.org/2000/svg";>
+       <text x="0" y="0.5" font-size="0.2px" dominant-baseline="middle" 
>Red</text>
+       <rect x="0.05" y="0.05" fill="#f00" width="0.36" height="0.242" />
+</svg>
commit 5140abd2c94b96f2a32f0f7416ae79239a2af187
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Fri May 3 14:14:26 2024 +0500
Commit:     Aron Budea <aron.bu...@collabora.com>
CommitDate: Wed May 8 08:13:32 2024 +0200

    tdf#152906: use correct Y offset
    
    GetEditCursor now returns the position relative to the line, not
    to the whole text. In ImpEditEngine::CreateLines, its use wasn't
    fixed, and so the Y position of all lines in the calculation was
    the same, thus adjusting to the same contour's horizontal stripe.
    
    Change-Id: I16362bab47f3064281eefb45a12834d836a8ada3
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167042
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167188
    (cherry picked from commit 9f5664f4d34e8f04cc18dc252cad4b3b853db882)

diff --git a/editeng/source/editeng/impedit3.cxx 
b/editeng/source/editeng/impedit3.cxx
index 464e9ed07550..32875bd76f0b 100644
--- a/editeng/source/editeng/impedit3.cxx
+++ b/editeng/source/editeng/impedit3.cxx
@@ -929,7 +929,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, 
sal_uInt32 nStartPosY )
         {
             GetTextRanger()->SetVertical( IsEffectivelyVertical() );
 
-            tools::Long nTextY = nStartPosY + GetEditCursor( pParaPortion, 
pLine, pLine->GetStart(), GetCursorFlags::NONE ).Top();
+            tools::Long nTextY = nCurrentPosY + GetEditCursor( pParaPortion, 
pLine, pLine->GetStart(), GetCursorFlags::NONE ).Top();
             if ( !bSameLineAgain )
             {
                 SeekCursor( pNode, nTmpPos+1, aTmpFont );
diff --git a/sd/qa/unit/data/odg/adjust-to-contour.fodg 
b/sd/qa/unit/data/odg/adjust-to-contour.fodg
new file mode 100644
index 000000000000..a5ec6fed74fc
--- /dev/null
+++ b/sd/qa/unit/data/odg/adjust-to-contour.fodg
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" 
xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
office:version="1.3" 
office:mimetype="application/vnd.oasis.opendocument.graphics">
+ <office:font-face-decls>
+  <style:font-face style:name="Liberation Sans" 
svg:font-family="&apos;Liberation Sans&apos;" style:font-family-generic="roman" 
style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+  <style:default-style style:family="graphic">
+   <style:graphic-properties svg:stroke-color="#3465a4" 
draw:fill-color="#729fcf"/>
+   <style:paragraph-properties style:text-autospace="ideograph-alpha" 
style:punctuation-wrap="simple" style:line-break="strict" 
style:writing-mode="lr-tb" style:font-independent-line-spacing="false">
+    <style:tab-stops/>
+   </style:paragraph-properties>
+  </style:default-style>
+  <style:style style:name="standard" style:family="graphic">
+   <style:graphic-properties draw:stroke="solid" svg:stroke-width="0cm" 
draw:marker-start-width="0.2cm" draw:marker-start-center="false" 
draw:marker-end-width="0.2cm" draw:marker-end-center="false" draw:fill="solid" 
draw:textarea-horizontal-align="justify" fo:padding-top="0" 
fo:padding-bottom="0" fo:padding-left="0" fo:padding-right="0" 
fo:wrap-option="wrap" draw:shadow="hidden" draw:shadow-offset-x="0.2cm" 
draw:shadow-offset-y="0.2cm" draw:shadow-color="#808080"/>
+   <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" 
fo:margin-top="0cm" fo:margin-bottom="0cm" fo:line-height="100%" 
fo:text-indent="0cm"/>
+   <style:text-properties fo:font-variant="normal" fo:text-transform="none" 
style:use-window-font-color="true" style:text-outline="false" 
style:text-line-through-style="none" style:text-line-through-type="none" 
style:font-name="Liberation Sans" fo:font-size="18pt" fo:font-style="normal" 
fo:text-shadow="none" style:text-underline-style="none" fo:font-weight="normal" 
style:letter-kerning="true" style:text-emphasize="none" 
style:font-relief="none" style:text-overline-style="none" 
style:text-overline-color="font-color"/>
+  </style:style>
+ </office:styles>
+ <office:automatic-styles>
+  <style:page-layout style:name="PM0">
+   <style:page-layout-properties fo:margin-top="0" fo:margin-bottom="0" 
fo:margin-left="0" fo:margin-right="0" fo:page-width="21cm" 
fo:page-height="29.7cm" style:print-orientation="portrait"/>
+  </style:page-layout>
+  <style:style style:name="dp1" style:family="drawing-page"/>
+  <style:style style:name="gr1" style:family="graphic" 
style:parent-style-name="standard">
+   <style:graphic-properties draw:textarea-vertical-align="middle" 
draw:fit-to-contour="true"/>
+  </style:style>
+  <style:style style:name="P1" style:family="paragraph">
+   <style:paragraph-properties fo:text-align="center"/>
+   <style:text-properties fo:language="zxx" fo:country="none"/>
+  </style:style>
+ </office:automatic-styles>
+ <office:master-styles>
+  <draw:layer-set>
+   <draw:layer draw:name="layout"/>
+   <draw:layer draw:name="background"/>
+   <draw:layer draw:name="backgroundobjects"/>
+   <draw:layer draw:name="controls"/>
+   <draw:layer draw:name="measurelines"/>
+  </draw:layer-set>
+  <style:master-page style:name="Default" style:page-layout-name="PM0" 
draw:style-name="dp1"/>
+ </office:master-styles>
+ <office:body>
+  <office:drawing>
+   <draw:page draw:name="page1" draw:style-name="dp1" 
draw:master-page-name="Default">
+    <draw:ellipse draw:style-name="gr1" draw:layer="layout" svg:width="13cm" 
svg:height="13cm" svg:x="4cm" svg:y="8cm">
+     <text:p text:style-name="P1">Lorem ipsum dolor sit amet, consectetur 
adipiscing elit. Vestibulum consequat mi quis pretium semper. Proin luctus orci 
ac neque venenatis, quis commodo dolor posuere. Curabitur dignissim sapien quis 
cursus egestas. Donec blandit auctor arcu, nec pellentesque eros molestie eget. 
In consectetur aliquam hendrerit. Sed cursus mauris vitae ligula pellentesque, 
non pellentesque urna aliquet. Fusce placerat mauris enim, nec rutrum purus 
semper vel. Praesent tincidunt neque eu pellentesque pharetra. Fusce 
pellentesque est orci.</text:p>
+    </draw:ellipse>
+   </draw:page>
+  </office:drawing>
+ </office:body>
+</office:document>
\ No newline at end of file
diff --git a/sd/qa/unit/layout-tests.cxx b/sd/qa/unit/layout-tests.cxx
index a93584b62f67..9be1ce154bc6 100644
--- a/sd/qa/unit/layout-tests.cxx
+++ b/sd/qa/unit/layout-tests.cxx
@@ -380,6 +380,54 @@ CPPUNIT_TEST_FIXTURE(SdLayoutTest, testTdf112594)
                        u"11\u202f\u1824"_ustr);
 }
 
+CPPUNIT_TEST_FIXTURE(SdLayoutTest, testTdf152906_AdjustToContour)
+{
+    // Test that the text adjusts to contour properly
+
+    constexpr OUString sText
+        = u"Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
Vestibulum consequat mi quis "
+          "pretium semper. Proin luctus orci ac neque venenatis, quis commodo 
dolor posuere. "
+          "Curabitur dignissim sapien quis cursus egestas. Donec blandit 
auctor arcu, nec "
+          "pellentesque eros molestie eget. In consectetur aliquam hendrerit. 
Sed cursus mauris "
+          "vitae ligula pellentesque, non pellentesque urna aliquet. Fusce 
placerat mauris enim, "
+          "nec rutrum purus semper vel. Praesent tincidunt neque eu 
pellentesque pharetra. Fusce "
+          "pellentesque est orci."_ustr;
+
+    // index, length, x, y
+    const std::tuple<int, int, int, int> strings[] = {
+        { 0, 6, 9600, 8647 }, //                        Lorem
+        { 6, 22, 7572, 9358 }, //               ipsum dolor sit amet,
+        { 28, 29, 6776, 10069 }, //         consectetur adipiscing elit.
+        { 57, 29, 6300, 10780 }, //         Vestibulum consequat mi quis
+        { 86, 37, 5453, 11491 }, //     pretium semper. Proin luctus orci ac
+        { 123, 36, 5136, 12202 }, //     neque venenatis, quis commodo dolor
+        { 159, 41, 4765, 12913 }, //  posuere. Curabitur dignissim sapien quis
+        { 200, 43, 4482, 13624 }, // cursus egestas. Donec blandit auctor arcu,
+        { 243, 40, 4977, 14335 }, //   nec pellentesque eros molestie eget. In
+        { 283, 42, 4554, 15046 }, //  consectetur aliquam hendrerit. Sed cursus
+        { 325, 38, 5364, 15757 }, //    mauris vitae ligula pellentesque, non
+        { 363, 42, 4693, 16468 }, //  pellentesque urna aliquet. Fusce placerat
+        { 405, 37, 5049, 17179 }, //    mauris enim, nec rutrum purus semper
+        { 442, 33, 5963, 17890 }, //      vel. Praesent tincidunt neque eu
+        { 475, 29, 6389, 18601 }, //        pellentesque pharetra. Fusce
+        { 504, 22, 7500, 19312 }, //           pellentesque est orci.
+    };
+
+    xmlDocUniquePtr pXmlDoc = load("odg/adjust-to-contour.fodg");
+
+    assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/textarray"_ostr, 
std::size(strings));
+    for (size_t i = 0; i < std::size(strings); ++i)
+    {
+        const auto & [ index, length, x, y ] = strings[i];
+        OString sXPath = "/metafile/push[1]/push[1]/textarray[" + 
OString::number(i + 1) + "]";
+        assertXPathContent(pXmlDoc, sXPath + "/text", sText);
+        assertXPath(pXmlDoc, sXPath, "index"_ostr, OUString::number(index));
+        assertXPath(pXmlDoc, sXPath, "length"_ostr, OUString::number(length));
+        assertXPath(pXmlDoc, sXPath, "x"_ostr, OUString::number(x));
+        assertXPath(pXmlDoc, sXPath, "y"_ostr, OUString::number(y));
+    }
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit dcd9cf8d045a43f187067c5d709505b1ec382f9c
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Sat Apr 13 20:42:16 2024 +0100
Commit:     Aron Budea <aron.bu...@collabora.com>
CommitDate: Wed May 8 08:13:23 2024 +0200

    Related: tdf#160056 1 entry is more common than no entries
    
    Change-Id: I78fe8969120f894cf5c0a71fb61611af2d203d18
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166065
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    (cherry picked from commit 7f2283c2986ff94766cc1d2c076fb34a2c88a31a)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166302
    Reviewed-by: Eike Rathke <er...@redhat.com>
    (cherry picked from commit 46bd13a55492adef4bf95133d7123494a62f549a)

diff --git a/svl/source/items/itemset.cxx b/svl/source/items/itemset.cxx
index 66780cb581cb..fd9cbb1dddee 100644
--- a/svl/source/items/itemset.cxx
+++ b/svl/source/items/itemset.cxx
@@ -1891,11 +1891,8 @@ static void isMiss()
 
 sal_uInt16 WhichRangesContainer::getOffsetFromWhich(sal_uInt16 nWhich) const
 {
-    if (empty())
-        return INVALID_WHICHPAIR_OFFSET;
-
     // special case for single entry - happens often e.g. UI stuff
-    if (1 == m_size)
+    if (m_size == 1)
     {
         if( m_pairs->first <= nWhich && nWhich <= m_pairs->second )
             return nWhich - m_pairs->first;
@@ -1904,6 +1901,9 @@ sal_uInt16 
WhichRangesContainer::getOffsetFromWhich(sal_uInt16 nWhich) const
         return INVALID_WHICHPAIR_OFFSET;
     }
 
+    if (m_size == 0)
+        return INVALID_WHICHPAIR_OFFSET;
+
     // check if nWhich is inside last successfully used WhichPair
     if (INVALID_WHICHPAIR_OFFSET != m_aLastWhichPairOffset
         && m_aLastWhichPairFirst <= nWhich
@@ -1949,12 +1949,8 @@ sal_uInt16 
WhichRangesContainer::getOffsetFromWhich(sal_uInt16 nWhich) const
 
 sal_uInt16 WhichRangesContainer::getWhichFromOffset(sal_uInt16 nOffset) const
 {
-    // check for empty, if yes, return null which is an invalid WhichID
-    if (empty())
-        return 0;
-
     // special case for single entry - happens often e.g. UI stuff
-    if (1 == m_size)
+    if (m_size == 1)
     {
         if (nOffset <= m_pairs->second - m_pairs->first)
             return m_pairs->first + nOffset;
@@ -1963,6 +1959,10 @@ sal_uInt16 
WhichRangesContainer::getWhichFromOffset(sal_uInt16 nOffset) const
         return 0;
     }
 
+    // check for empty, if yes, return null which is an invalid WhichID
+    if (m_size == 0)
+        return 0;
+
     // check if nWhich is inside last successfully used WhichPair
     if (INVALID_WHICHPAIR_OFFSET != m_aLastWhichPairOffset)
     {
commit 14620a5113c817f9888a18e08d4bd7919cf80a75
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Fri Apr 12 12:24:06 2024 +0100
Commit:     Aron Budea <aron.bu...@collabora.com>
CommitDate: Wed May 8 08:13:15 2024 +0200

    Related: tdf#160056 don't call GetParamCount twice
    
    GetParamCount: 290ms -> 175ms
    Change-Id: Ic3a26b1e8035744dcab2da69a8ebd3b29dd2160a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166031
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    (cherry picked from commit 030b655963c182693c7b657dc6aa4d2fe85c17c6)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166301
    Reviewed-by: Eike Rathke <er...@redhat.com>
    (cherry picked from commit 34126d6fceb054b7ba05ceeae76e32c89fac580f)

diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 597f13c691f2..b3a2f8786f22 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -4048,8 +4048,9 @@ StackVar ScInterpreter::Interpret()
                 (*aTokenMatrixMapIter).second->GetType() != svJumpMatrix)
         {
             // Path already calculated, reuse result.
-            if (sp >= pCur->GetParamCount())
-                nStackBase = sp - pCur->GetParamCount();
+            const sal_uInt8 nParamCount = pCur->GetParamCount();
+            if (sp >= nParamCount)
+                nStackBase = sp - nParamCount;
             else
             {
                 SAL_WARN("sc.core", "Stack anomaly with calculated path at "
@@ -4057,7 +4058,7 @@ StackVar ScInterpreter::Interpret()
                         << "  " << aPos.Format(
                             ScRefFlags::VALID | ScRefFlags::FORCE_DOC | 
ScRefFlags::TAB_3D, &mrDoc)
                         << "  eOp: " << static_cast<int>(eOp)
-                        << "  params: " << 
static_cast<int>(pCur->GetParamCount())
+                        << "  params: " << static_cast<int>(nParamCount)
                         << "  nStackBase: " << nStackBase << "  sp: " << sp);
                 nStackBase = sp;
                 assert(!"underflow");
@@ -4086,18 +4087,22 @@ StackVar ScInterpreter::Interpret()
                     eOp = ocNone;       // JumpMatrix created
                     nStackBase = sp;
                 }
-                else if (sp >= pCur->GetParamCount())
-                    nStackBase = sp - pCur->GetParamCount();
                 else
                 {
-                    SAL_WARN("sc.core", "Stack anomaly at " << aPos.Tab() << 
"," << aPos.Col() << "," << aPos.Row()
-                            << "  " << aPos.Format(
-                                ScRefFlags::VALID | ScRefFlags::FORCE_DOC | 
ScRefFlags::TAB_3D, &mrDoc)
-                            << "  eOp: " << static_cast<int>(eOp)
-                            << "  params: " << 
static_cast<int>(pCur->GetParamCount())
-                            << "  nStackBase: " << nStackBase << "  sp: " << 
sp);
-                    nStackBase = sp;
-                    assert(!"underflow");
+                    const sal_uInt8 nParamCount = pCur->GetParamCount();
+                    if (sp >= nParamCount)
+                        nStackBase = sp - nParamCount;
+                    else
+                    {
+                        SAL_WARN("sc.core", "Stack anomaly at " << aPos.Tab() 
<< "," << aPos.Col() << "," << aPos.Row()
+                                << "  " << aPos.Format(
+                                    ScRefFlags::VALID | ScRefFlags::FORCE_DOC 
| ScRefFlags::TAB_3D, &mrDoc)
+                                << "  eOp: " << static_cast<int>(eOp)
+                                << "  params: " << 
static_cast<int>(nParamCount)
+                                << "  nStackBase: " << nStackBase << "  sp: " 
<< sp);
+                        nStackBase = sp;
+                        assert(!"underflow");
+                    }
                 }
             }
 
commit 53cb51744a428c070db266056e56fa52365785f8
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Sat Apr 13 16:35:28 2024 +0100
Commit:     Aron Budea <aron.bu...@collabora.com>
CommitDate: Wed May 8 08:13:07 2024 +0200

    Related: tdf#160056 don't set nVal twice
    
    Change-Id: I0da3e0c7f18271f6104d52b50d65e96564650b8b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166054
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    (cherry picked from commit 63b237e1e8147f54e6d4db4671f612a656200e2f)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166300
    Reviewed-by: Eike Rathke <er...@redhat.com>
    (cherry picked from commit 9757290668b50827ab22597a73a4850ebf3f6521)

diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 8764a7674a85..597f13c691f2 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -2099,7 +2099,7 @@ double ScInterpreter::GetDoubleFromMatrix(const 
ScMatrixRef& pMat)
 
 double ScInterpreter::GetDouble()
 {
-    double nVal(0.0);
+    double nVal;
     switch( GetRawStackType() )
     {
         case svDouble:
@@ -2134,13 +2134,16 @@ double ScInterpreter::GetDouble()
         {
             ScExternalRefCache::TokenRef pToken;
             PopExternalSingleRef(pToken);
-            if (nGlobalError == FormulaError::NONE)
+            if (nGlobalError != FormulaError::NONE)
             {
-                if (pToken->GetType() == svDouble || pToken->GetType() == 
svEmptyCell)
-                    nVal = pToken->GetDouble();
-                else
-                    nVal = ConvertStringToValue( 
pToken->GetString().getString());
+                nVal = 0.0;
+                break;
             }
+
+            if (pToken->GetType() == svDouble || pToken->GetType() == 
svEmptyCell)
+                nVal = pToken->GetDouble();
+            else
+                nVal = ConvertStringToValue( pToken->GetString().getString());
         }
         break;
         case svExternalDoubleRef:
@@ -2148,7 +2151,10 @@ double ScInterpreter::GetDouble()
             ScMatrixRef pMat;
             PopExternalDoubleRef(pMat);
             if (nGlobalError != FormulaError::NONE)
+            {
+                nVal = 0.0;
                 break;
+            }
 
             nVal = GetDoubleFromMatrix(pMat);
         }
commit da60a27ac06ddc1c51a5eec5e8bc5c4f6e3b6f80
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Sat Apr 13 10:56:37 2024 +0100
Commit:     Aron Budea <aron.bu...@collabora.com>
CommitDate: Wed May 8 08:12:59 2024 +0200

    Related: tdf#160056 all maTokens are FormulaTypedDoubleToken*
    
    Change-Id: I6eacaf58c25ef9c5cb930a79177471c79a6a26c0
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166047
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    (cherry picked from commit adbbe732e7ed7f3a749e04f1d9023989c972ec22)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166299
    Reviewed-by: Eike Rathke <er...@redhat.com>
    (cherry picked from commit bc7198d47b4d1aef7a346c3f939122c9c764eeda)

diff --git a/sc/inc/interpretercontext.hxx b/sc/inc/interpretercontext.hxx
index 5b3a85ab24d9..c43e9c0b6892 100644
--- a/sc/inc/interpretercontext.hxx
+++ b/sc/inc/interpretercontext.hxx
@@ -19,7 +19,7 @@
 
 namespace formula
 {
-class FormulaToken;
+class FormulaTypedDoubleToken;
 }
 
 #define TOKEN_CACHE_SIZE 8
@@ -44,7 +44,7 @@ struct ScInterpreterContext
 {
     const ScDocument* mpDoc;
     size_t mnTokenCachePos;
-    std::vector<formula::FormulaToken*> maTokens;
+    std::vector<formula::FormulaTypedDoubleToken*> maTokens;
     std::vector<DelayedSetNumberFormat> maDelayedSetNumberFormat;
     std::unique_ptr<ScLookupCacheMap> mxScLookupCache; // cache for lookups 
like VLOOKUP and MATCH
     // Allocation cache for "aConditions" array in 
ScInterpreter::IterateParameterIfs()
commit ad9e4e1869c109fb7821fb9a7ec1eb957891c8bd
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Tue Mar 12 20:38:35 2024 +0000
Commit:     Aron Budea <aron.bu...@collabora.com>
CommitDate: Wed May 8 08:12:51 2024 +0200

    Related: tdf#160056 various functions and objects that can be const
    
    this formatter can be const
    
    Change-Id: I2cd83140585e0b7027bb1c165a8d59e51cbbaad0
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164728
    Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    
    SvNumberformat::ImpGetFractionOfSecondString can be const
    
    Change-Id: If7a31f8b3667d9a6b8719553567211071bd2d631
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164774
    Tested-by: Jenkins
    Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    
    ImpIsEntry can be const
    
    Change-Id: Id229344a68925a1bde84f2b4aad46cfc5f01b797
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164769
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    
    SvNumberformat::ImpGetLogicalOutput can be const
    
    Change-Id: I847e5de84f0636b5a169f383e319a6b8707cc31f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164773
    Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    
    SvNumberFormatter::GetUserDefColor can be const
    
    Change-Id: If499e28e5ac69018b35b475a73ecb2dc4b78dad6
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164786
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    
    These methods can be const too
    
    Change-Id: Iaef46216dac6584f57b7933d658384f54d0a4544
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164772
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166125
    Reviewed-by: Eike Rathke <er...@redhat.com>
    (cherry picked from commit e3e9d51c2d4bed475f9848c62c7b0e5c72d5e125)

diff --git a/include/svl/numformat.hxx b/include/svl/numformat.hxx
index bf31ff22b605..2ebed94959cc 100644
--- a/include/svl/numformat.hxx
+++ b/include/svl/numformat.hxx
@@ -62,7 +62,7 @@ public:
     /// Set CallBack to ColorTable
     void SetColorLink(const Link<sal_uInt16, Color*>& rColorTableCallBack);
     /// Do the CallBack to ColorTable
-    Color* GetUserDefColor(sal_uInt16 nIndex);
+    Color* GetUserDefColor(sal_uInt16 nIndex) const;
 
     /// Change language/country, also input and format scanner
     void ChangeIntl(LanguageType eLnge);
@@ -627,7 +627,7 @@ private:
     // Test whether format code already exists, then return index key,
     // otherwise NUMBERFORMAT_ENTRY_NOT_FOUND
     SVL_DLLPRIVATE sal_uInt32 ImpIsEntry(std::u16string_view rString, 
sal_uInt32 CLOffset,
-                                         LanguageType eLnge);
+                                         LanguageType eLnge) const;
 
     // Create builtin formats for language/country if necessary, return 
CLOffset
     SVL_DLLPRIVATE sal_uInt32 ImpGenerateCL(LanguageType eLnge);
diff --git a/include/svl/zformat.hxx b/include/svl/zformat.hxx
index 1fa52c3384a2..b4d7ddb0ac29 100644
--- a/include/svl/zformat.hxx
+++ b/include/svl/zformat.hxx
@@ -638,7 +638,7 @@ private:
                                  sal_uInt16 j,
                                  sal_uInt16 nIx,
                                  sal_Int32 nDigCnt,
-                                 bool bAddDecSep = true );
+                                 bool bAddDecSep = true ) const;
 
     // Helper function to fill in the group (AKA thousand) separators
     // or to skip additional digits
@@ -647,14 +647,14 @@ private:
                                       sal_Int32& k,
                                       sal_uInt16 nIx,
                                       sal_Int32 & nDigitCount,
-                                      utl::DigitGroupingIterator & );
+                                      utl::DigitGroupingIterator & ) const;
 
     SVL_DLLPRIVATE bool ImpDecimalFill( OUStringBuffer& sStr,
                                  double& rNumber,
                                  sal_Int32 nDecPos,
                                  sal_uInt16 j,
                                  sal_uInt16 nIx,
-                                 bool bInteger );
+                                 bool bInteger ) const;
 
     /** Calculate each element of fraction:
      * integer part, numerator part, denominator part
@@ -701,11 +701,11 @@ private:
 
     SVL_DLLPRIVATE bool ImpGetLogicalOutput( double fNumber,
                                              sal_uInt16 nIx,
-                                             OUStringBuffer& OutString );
+                                             OUStringBuffer& OutString ) const;
 
     SVL_DLLPRIVATE bool ImpGetNumberOutput( double fNumber,
                                             sal_uInt16 nIx,
-                                            OUStringBuffer& OutString );
+                                            OUStringBuffer& OutString ) const;
 
     SVL_DLLPRIVATE void ImpCopyNumberformat( const SvNumberformat& rFormat );
 
@@ -731,7 +731,7 @@ private:
     // nFractionDecimals, unless nMinimumInputLineDecimals>0 is given for input
     // line string where extra trailing "0" are discarded.
     SVL_DLLPRIVATE sal_uInt16 ImpGetFractionOfSecondString( OUStringBuffer& 
rBuf, double fFractionOfSecond,
-            int nFractionDecimals, bool bAddOneRoundingDecimal, sal_uInt16 
nIx, sal_uInt16 nMinimumInputLineDecimals );
+            int nFractionDecimals, bool bAddOneRoundingDecimal, sal_uInt16 
nIx, sal_uInt16 nMinimumInputLineDecimals ) const;
 
     // transliterate according to NativeNumber
     SVL_DLLPRIVATE OUString impTransliterateImpl(const OUString& rStr, const 
SvNumberNatNum& rNum) const;
diff --git a/sc/source/core/data/queryevaluator.cxx 
b/sc/source/core/data/queryevaluator.cxx
index a8a08d9edfd9..174e1e0989c7 100644
--- a/sc/source/core/data/queryevaluator.cxx
+++ b/sc/source/core/data/queryevaluator.cxx
@@ -244,7 +244,7 @@ std::pair<bool, bool> 
ScQueryEvaluator::compareByValue(const ScRefCellValue& rCe
             nNumFmt = getNumFmt(nCol, nRow);
         if (nNumFmt)
         {
-            SvNumberFormatter* pFormatter
+            const SvNumberFormatter* pFormatter
                 = mpContext ? mpContext->GetFormatTable() : 
mrDoc.GetFormatTable();
             const SvNumberformat* pEntry = pFormatter->GetEntry(nNumFmt);
             if (pEntry)
diff --git a/svl/source/numbers/zforlist.cxx b/svl/source/numbers/zforlist.cxx
index c96653460d95..a75c932a2c1c 100644
--- a/svl/source/numbers/zforlist.cxx
+++ b/svl/source/numbers/zforlist.cxx
@@ -376,7 +376,7 @@ void SvNumberFormatter::SetColorLink( const 
Link<sal_uInt16,Color*>& rColorTable
     aColorLink = rColorTableCallBack;
 }
 
-Color* SvNumberFormatter::GetUserDefColor(sal_uInt16 nIndex)
+Color* SvNumberFormatter::GetUserDefColor(sal_uInt16 nIndex) const
 {
     ::osl::MutexGuard aGuard( GetInstanceMutex() );
     if( aColorLink.IsSet() )
@@ -998,7 +998,7 @@ sal_uInt32 SvNumberFormatter::ImpGetCLOffset(LanguageType 
eLnge) const
 
 sal_uInt32 SvNumberFormatter::ImpIsEntry(std::u16string_view rString,
                                          sal_uInt32 nCLOffset,
-                                         LanguageType eLnge)
+                                         LanguageType eLnge) const
 {
     sal_uInt32 res = NUMBERFORMAT_ENTRY_NOT_FOUND;
     auto it = aFTable.find( nCLOffset);
@@ -1017,7 +1017,6 @@ sal_uInt32 
SvNumberFormatter::ImpIsEntry(std::u16string_view rString,
     return res;
 }
 
-
 SvNumberFormatTable& SvNumberFormatter::GetFirstEntryTable(
                                                       SvNumFormatType& eType,
                                                       sal_uInt32& FIndex,
diff --git a/svl/source/numbers/zformat.cxx b/svl/source/numbers/zformat.cxx
index 313a59827947..b2d38f29cde7 100644
--- a/svl/source/numbers/zformat.cxx
+++ b/svl/source/numbers/zformat.cxx
@@ -3052,7 +3052,7 @@ bool SvNumberformat::ImpGetFractionOutput(double fNumber,
 }
 
 sal_uInt16 SvNumberformat::ImpGetFractionOfSecondString( OUStringBuffer& rBuf, 
double fFractionOfSecond,
-        int nFractionDecimals, bool bAddOneRoundingDecimal, sal_uInt16 nIx, 
sal_uInt16 nMinimumInputLineDecimals )
+        int nFractionDecimals, bool bAddOneRoundingDecimal, sal_uInt16 nIx, 
sal_uInt16 nMinimumInputLineDecimals ) const
 {
     if (!nFractionDecimals)
         return 0;
@@ -4327,7 +4327,7 @@ bool SvNumberformat::ImpGetDateTimeOutput(double fNumber,
 
 bool SvNumberformat::ImpGetLogicalOutput(double fNumber,
                                          sal_uInt16 nIx,
-                                         OUStringBuffer& sStr)
+                                         OUStringBuffer& sStr) const
 {
     bool bRes = false;
     const ImpSvNumberformatInfo& rInfo = NumFor[nIx].Info();
@@ -4350,7 +4350,7 @@ bool SvNumberformat::ImpGetLogicalOutput(double fNumber,
 
 bool SvNumberformat::ImpGetNumberOutput(double fNumber,
                                         sal_uInt16 nIx,
-                                        OUStringBuffer& sStr)
+                                        OUStringBuffer& sStr) const
 {
     bool bRes = false;
     bool bSign;
@@ -4470,7 +4470,7 @@ bool SvNumberformat::ImpDecimalFill( OUStringBuffer& 
sStr,  // number string
                                    sal_Int32 nDecPos,     // decimals start
                                    sal_uInt16 j,          // symbol index 
within format code
                                    sal_uInt16 nIx,        // subformat index
-                                   bool bInteger)         // is integer
+                                   bool bInteger) const   // is integer
 {
     bool bRes = false;
     bool bFilled = false;               // Was filled?
@@ -4592,7 +4592,7 @@ bool SvNumberformat::ImpNumberFillWithThousands( 
OUStringBuffer& sBuff,  // numb
                                                  sal_uInt16 j,          // 
symbol index within format code
                                                  sal_uInt16 nIx,        // 
subformat index
                                                  sal_Int32 nDigCnt,     // 
count of integer digits in format
-                                                 bool bAddDecSep)       // add 
decimal separator if necessary
+                                                 bool bAddDecSep) const // add 
decimal separator if necessary
 {
     bool bRes = false;
     sal_Int32 nLeadingStringChars = 0; // inserted StringChars before number
@@ -4752,7 +4752,7 @@ void SvNumberformat::ImpDigitFill(OUStringBuffer& sStr,   
  // number string
                                   sal_Int32 & k,            // position within 
string
                                   sal_uInt16 nIx,           // subformat index
                                   sal_Int32 & nDigitCount,  // count of 
integer digits from the right so far
-                                  utl::DigitGroupingIterator & rGrouping )  // 
current grouping
+                                  utl::DigitGroupingIterator & rGrouping ) 
const // current grouping
 {
     if (NumFor[nIx].Info().bThousand) // Only if grouping fill in separators
     {
commit bb87f26fc0fcf2d15d180eb7bcd787c8c54e6023
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Sun May 5 16:39:36 2024 +0100
Commit:     Aron Budea <aron.bu...@collabora.com>
CommitDate: Wed May 8 08:12:43 2024 +0200

    cid#1596833 Uninitialized pointer field
    
    Change-Id: I1f05ef494e7e28bd105b7658072c33b2d274a803
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167159
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Tested-by: Jenkins
    (cherry picked from commit 66916b20818e4fc4a25d711b3860b4096e575a5c)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167080
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>
    (cherry picked from commit a7587def8792dc811d9aa66a462d752130f575d5)

diff --git a/svgio/source/svgreader/svgstyleattributes.cxx 
b/svgio/source/svgreader/svgstyleattributes.cxx
index 81ef74d62f63..eee09889c226 100644
--- a/svgio/source/svgreader/svgstyleattributes.cxx
+++ b/svgio/source/svgreader/svgstyleattributes.cxx
@@ -1294,7 +1294,8 @@ namespace svgio::svgreader
             maDominantBaseline(DominantBaseline::Auto),
             maResolvingParent(33, 0),
             mbStrokeDasharraySet(false),
-            mbContextStroke(false)
+            mbContextStroke(false),
+            maContextStroke(nullptr)
         {
         }
 
commit aabb4ddb320dc96a4f6d1c4ef64ace722ccc2d60
Author:     Pierre <prrv...@gmail.com>
AuthorDate: Sat Apr 13 19:19:50 2024 +0200
Commit:     Aron Budea <aron.bu...@collabora.com>
CommitDate: Wed May 8 08:12:30 2024 +0200

    tdf#160375 Base displays and gives the full name of the table
    
    Change-Id: Icc8c6d85cc5a88461b7bd02487513e0e864bacef
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166093
    Reviewed-by: Pierre Vacher <prrv...@gmail.com>
    Tested-by: Jenkins
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>
    (cherry picked from commit eb045cc529f0e7b17e7e3bc913f2ab1748247966)

diff --git a/dbaccess/source/ui/relationdesign/RTableConnectionData.cxx 
b/dbaccess/source/ui/relationdesign/RTableConnectionData.cxx
index 2fb7c0b8213c..9651a89c9f09 100644
--- a/dbaccess/source/ui/relationdesign/RTableConnectionData.cxx
+++ b/dbaccess/source/ui/relationdesign/RTableConnectionData.cxx
@@ -256,7 +256,8 @@ bool ORelationTableConnectionData::Update()
 
         xKey->setPropertyValue(PROPERTY_NAME,Any(sKeyName));
         xKey->setPropertyValue(PROPERTY_TYPE,Any(KeyType::FOREIGN));
-        
xKey->setPropertyValue(PROPERTY_REFERENCEDTABLE,Any(getReferencedTable()->GetTableName()));
+        // get the full name of the tables to ensure uniqueness across 
catalogs and schema
+        
xKey->setPropertyValue(PROPERTY_REFERENCEDTABLE,Any(getReferencedTable()->GetComposedName()));
         xKey->setPropertyValue(PROPERTY_UPDATERULE, Any(GetUpdateRules()));
         xKey->setPropertyValue(PROPERTY_DELETERULE, Any(GetDeleteRules()));
     }
@@ -301,7 +302,7 @@ bool ORelationTableConnectionData::Update()
         {
             OUString sReferencedTable;
             xKey->getPropertyValue(PROPERTY_REFERENCEDTABLE) >>= 
sReferencedTable;
-            if ( sReferencedTable == getReferencedTable()->GetTableName() )
+            if ( sReferencedTable == getReferencedTable()->GetComposedName() )
             {
                 xColSup.set(xKey,UNO_QUERY_THROW);
                 try
diff --git a/dbaccess/source/ui/relationdesign/RelationTableView.cxx 
b/dbaccess/source/ui/relationdesign/RelationTableView.cxx
index 6c96d3952047..da82719b7a23 100644
--- a/dbaccess/source/ui/relationdesign/RelationTableView.cxx
+++ b/dbaccess/source/ui/relationdesign/RelationTableView.cxx
@@ -108,7 +108,8 @@ void ORelationTableView::ReSync()
             // it should be cleaned up, including its data in the document
             pTabWin->clearListBox();
             pTabWin.disposeAndClear();
-            arrInvalidTables.push_back(pData->GetTableName());
+            // get the full name of the tables to ensure uniqueness across 
catalogs and schema
+            arrInvalidTables.push_back(pData->GetComposedName());
 
             std::erase(rTabWinDataList, *aIter);
             continue;
@@ -132,9 +133,9 @@ void ORelationTableView::ReSync()
         if ( !arrInvalidTables.empty() )
         {
             // do the tables to the  connection exist?
-            OUString strTabExistenceTest = 
pTabConnData->getReferencingTable()->GetTableName();
+            OUString strTabExistenceTest = 
pTabConnData->getReferencingTable()->GetComposedName();
             bool bInvalid = 
std::find(arrInvalidTables.begin(),arrInvalidTables.end(),strTabExistenceTest) 
!= arrInvalidTables.end();
-            strTabExistenceTest = 
pTabConnData->getReferencedTable()->GetTableName();
+            strTabExistenceTest = 
pTabConnData->getReferencedTable()->GetComposedName();
             bInvalid = bInvalid || 
std::find(arrInvalidTables.begin(),arrInvalidTables.end(),strTabExistenceTest) 
!= arrInvalidTables.end();
 
             if (bInvalid)
@@ -290,7 +291,8 @@ void ORelationTableView::AddTabWin(const OUString& 
_rComposedName, const OUStrin
     }
 
     // enter the new data structure into DocShell
-    TTableWindowData::value_type pNewTabWinData(createTableWindowData( 
_rComposedName, rWinName,rWinName ));
+    // show the table's full name as window name to ensure uniqueness across 
catalogs and schema
+    TTableWindowData::value_type pNewTabWinData(createTableWindowData( 
_rComposedName, rWinName, _rComposedName ));
     pNewTabWinData->ShowAll(false);
 
     // link new window into the window list
commit 2e603b2bb0193c7b8918954584f0f0e059f28f28
Author:     Julien Nabet <serval2...@yahoo.fr>
AuthorDate: Sat May 4 10:18:15 2024 +0200
Commit:     Aron Budea <aron.bu...@collabora.com>
CommitDate: Wed May 8 08:12:20 2024 +0200

    tdf#160924: SDK: typo SDK_HOME instead of OO_SDK_HOME for linux
    
    Change-Id: I8ec2bc31b19cc6b724a6f7ea3238dda8cf60d4b7
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167111
    Tested-by: Jenkins
    Reviewed-by: Julien Nabet <serval2...@yahoo.fr>
    (cherry picked from commit 6aa2e8fe2b0b59e2fe20191decb9bd6202dabcc9)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167073
    Reviewed-by: Adolfo Jayme Barrientos <fit...@ubuntu.com>
    Reviewed-by: Ilmari Lauhakangas <ilmari.lauhakan...@libreoffice.org>
    (cherry picked from commit ee9f7d31348e917eb8ba5b007a6679e01ecdb37f)

diff --git a/odk/docs/install.html b/odk/docs/install.html
index aaafae6ce9c3..42e3b13cfb2f 100644
--- a/odk/docs/install.html
+++ b/odk/docs/install.html
@@ -459,7 +459,7 @@
                               <tr valign="top">
                                 <td class="cell20">LD_LIBRARY_PATH</td>
                                 <td class="cell80">=<i>$OO_SDK_URE_LIB_DIR:
-                                    $SDK_HOME/linux/lib:
+                                    $OO_SDK_HOME/linux/lib:
                                     $LD_LIBRARY_PATH</i><br/>
                                   <p>The LD_LIBRARY_PATH will be set or will be
                                     extended by the office/URE library path, 
the
commit 816d9fa689525666f49cb1b3b2407d44e3c4b2b5
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Tue Apr 23 05:25:34 2024 +0500
Commit:     Aron Budea <aron.bu...@collabora.com>
CommitDate: Wed May 8 08:12:11 2024 +0200

    Fix a thinko in 8a97f1ba8d9ccb65b2c89106de20666311d90c30
    
    Change-Id: I07bb67e9384470269d1fd3df087acee377cce729
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166490
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167052
    (cherry picked from commit d1c31e3857b7f0c6b3fb72da0c967bfa2bdef015)

diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx 
b/drawinglayer/source/primitive2d/textlayoutdevice.cxx
index 3e5708a99de6..9de634076960 100644
--- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx
+++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx
@@ -188,7 +188,7 @@ void TextLayouterDevice::setFontAttribute(const 
attribute::FontAttribute& rFontA
     }
     else
     {
-        mnFontScalingFixX = mnFontScalingFixY = 0;
+        mnFontScalingFixX = mnFontScalingFixY = 1.0;
     }
 }
 
commit 8b98e21b1a061b3e47f5f5d51f743f7f2201ae4b
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Mon Apr 22 14:45:37 2024 +0500
Commit:     Aron Budea <aron.bu...@collabora.com>
CommitDate: Wed May 8 08:12:01 2024 +0200

    tdf#160773: handle 0-size font height
    
    Regression from commit cc3663bbaed4f65d64154e5f9abb51a5f622f710
    (tdf#160702: improve text positioning, 2024-04-20), where I didn't
    know yet that this was possible :-)
    
    Change-Id: I1316db48b8acbacd077eeb4a8989c3dbf7e4a7b5
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166425
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167051
    (cherry picked from commit 14c7b4249e822c218f912fcd3707226081363f7a)

diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx 
b/drawinglayer/source/primitive2d/textlayoutdevice.cxx
index afc0663aa4b0..3e5708a99de6 100644
--- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx
+++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx
@@ -179,8 +179,17 @@ void TextLayouterDevice::setFontAttribute(const 
attribute::FontAttribute& rFontA
         = getVclFontFromFontAttribute(rFontAttribute, fFontScaleX, 
fFontScaleY, 0.0, rLocale);
     setFont(aFont);
     Size aFontSize = aFont.GetFontSize();
-    mnFontScalingFixY = fFontScaleY / aFontSize.Height();
-    mnFontScalingFixX = fFontScaleX / (aFontSize.Width() ? aFontSize.Width() : 
aFontSize.Height());
+    if (aFontSize.Height())
+    {
+        mnFontScalingFixY = fFontScaleY / aFontSize.Height();
+        // aFontSize.Width() is 0 for uninformly scaled fonts: see 
getVclFontFromFontAttribute
+        mnFontScalingFixX
+            = fFontScaleX / (aFontSize.Width() ? aFontSize.Width() : 
aFontSize.Height());
+    }
+    else
+    {
+        mnFontScalingFixX = mnFontScalingFixY = 0;
+    }
 }
 
 double TextLayouterDevice::getOverlineOffset() const
commit 8173935b8491ff24831e849dbf6a7d872e680ddd
Author:     Xisco Fauli <xiscofa...@libreoffice.org>
AuthorDate: Thu May 2 22:16:36 2024 +0200
Commit:     Aron Budea <aron.bu...@collabora.com>
CommitDate: Wed May 8 08:11:53 2024 +0200

    tdf#155651: Add support for "context-stroke"
    
    Change-Id: Ib4f4a7b644d0d6c6b36e31b80fd7adc18999110d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166908
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Tested-by: Jenkins
    (cherry picked from commit f4a868ce3b7e5fe6e708f2c795402d646e0746d5)

diff --git a/svgio/inc/svgstyleattributes.hxx b/svgio/inc/svgstyleattributes.hxx
index c5c095462f3d..61a3816e82cb 100644
--- a/svgio/inc/svgstyleattributes.hxx
+++ b/svgio/inc/svgstyleattributes.hxx
@@ -247,10 +247,15 @@ namespace svgio::svgreader
             // #121221# Defines if evtl. an empty array *is* set
             bool                        mbStrokeDasharraySet : 1;
 
+            // tdf#155651 Defines if 'context-stroke' is used in stroke
+            bool                        mbContextStroke : 1;
+
             // tdf#94765 Check id references in gradient/pattern getters
             OUString                    maNodeFillURL;
             OUString                    maNodeStrokeURL;
 
+            const basegfx::BColor*  maContextStroke;
+
             /// internal helpers
             void add_fillGradient(
                 const basegfx::B2DPolyPolygon& rPath,
@@ -327,6 +332,9 @@ namespace svgio::svgreader
             /// stroke content
             const basegfx::BColor* getStroke() const;
 
+            /// context stroke content
+            const basegfx::BColor* getContextStroke() const;
+
             /// stop color content
             const basegfx::BColor& getStopColor() const;
 
diff --git a/svgio/qa/cppunit/SvgImportTest.cxx 
b/svgio/qa/cppunit/SvgImportTest.cxx
index 69c6a10d23f4..dc900b1eee1e 100644
--- a/svgio/qa/cppunit/SvgImportTest.cxx
+++ b/svgio/qa/cppunit/SvgImportTest.cxx
@@ -685,6 +685,17 @@ CPPUNIT_TEST_FIXTURE(Test, testMarkerOrient)
     assertXPath(pDocument, "/primitive2D/transform/transform[2]"_ostr, 
"xy33"_ostr, "1");
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testContextStroke)
+{
+    xmlDocUniquePtr pDocument = 
dumpAndParseSvg(u"/svgio/qa/cppunit/data/contextStroke.svg");
+
+    assertXPath(pDocument, 
"/primitive2D/transform/polypolygonstroke/line"_ostr, "color"_ostr, "#ff0000");
+    assertXPath(pDocument, 
"/primitive2D/transform/transform[1]/polypolygonstroke/line"_ostr, 
"color"_ostr, "#ff0000");
+    assertXPath(pDocument, 
"/primitive2D/transform/transform[2]/polypolygonstroke/line"_ostr, 
"color"_ostr, "#ff0000");
+    assertXPath(pDocument, 
"/primitive2D/transform/transform[3]/polypolygonstroke/line"_ostr, 
"color"_ostr, "#ff0000");
+    assertXPath(pDocument, 
"/primitive2D/transform/transform[4]/polypolygonstroke/line"_ostr, 
"color"_ostr, "#ff0000");
+}
+
 CPPUNIT_TEST_FIXTURE(Test, testMarkerInPresentation)
 {
     Primitive2DSequence aSequence = 
parseSvg(u"/svgio/qa/cppunit/data/markerInPresentation.svg");
diff --git a/svgio/qa/cppunit/data/contextStroke.svg 
b/svgio/qa/cppunit/data/contextStroke.svg
new file mode 100644
index 000000000000..5a9b27d69c84
--- /dev/null
+++ b/svgio/qa/cppunit/data/contextStroke.svg
@@ -0,0 +1,14 @@
+<svg xmlns="http://www.w3.org/2000/svg"; viewBox="0 0 100 100">
+  <style>
+    path {
+      fill: none;
+      stroke-width: 4px;
+      marker: url(#diamond);
+    }
+  </style>
+  <path d="M 10,50 v -20 h 40 v -20" stroke="red"/>
+
+  <marker id="diamond" markerWidth="12" markerHeight="12" refX="6" refY="6" 
markerUnits="userSpaceOnUse">
+    <circle cx="6" cy="6" r="3" fill="white" stroke="context-stroke" 
stroke-width="2"/>
+  </marker>
+</svg>
diff --git a/svgio/source/svgreader/svgmarkernode.cxx 
b/svgio/source/svgreader/svgmarkernode.cxx
index 083471b49c6b..2279920634a6 100644
--- a/svgio/source/svgreader/svgmarkernode.cxx
+++ b/svgio/source/svgreader/svgmarkernode.cxx
@@ -174,7 +174,7 @@ namespace svgio::svgreader
 
         const drawinglayer::primitive2d::Primitive2DContainer& 
SvgMarkerNode::getMarkerPrimitives() const
         {
-            if(aPrimitives.empty() && Display::None != getDisplay())
+            if(Display::None != getDisplay())
             {
                 decomposeSvgNode(const_cast< SvgMarkerNode* 
>(this)->aPrimitives, true);
             }
diff --git a/svgio/source/svgreader/svgstyleattributes.cxx 
b/svgio/source/svgreader/svgstyleattributes.cxx
index 50f72199e40b..81ef74d62f63 100644
--- a/svgio/source/svgreader/svgstyleattributes.cxx
+++ b/svgio/source/svgreader/svgstyleattributes.cxx
@@ -817,6 +817,11 @@ namespace svgio::svgreader
             rMarkerTransform.identity();
             rClipRange.reset();
 
+            // Set the current stroke to the marker before calling 
getMarkerPrimitives,
+            // which calls decomposeSvgNode to decompose the children of the 
marker.
+            // If any of the children uses 'stroke="context-stroke"', then it 
will use it
+            
const_cast<SvgStyleAttributes*>(rMarker.getSvgStyleAttributes())->maContextStroke
 = getStroke();
+
             // get marker primitive representation
             rMarkerPrimitives = rMarker.getMarkerPrimitives();
 
@@ -1287,8 +1292,9 @@ namespace svgio::svgreader
             maBaselineShift(BaselineShift::Baseline),
             maBaselineShiftNumber(0),
             maDominantBaseline(DominantBaseline::Auto),
-            maResolvingParent(32, 0),
-            mbStrokeDasharraySet(false)
+            maResolvingParent(33, 0),
+            mbStrokeDasharraySet(false),
+            mbContextStroke(false)
         {
         }
 
@@ -1353,7 +1359,11 @@ namespace svgio::svgreader
                     OUString aURL;
                     SvgNumber aOpacity;
 
-                    if(readSvgPaint(aContent, aSvgPaint, aURL, aOpacity))
+                    if(o3tl::equalsIgnoreAsciiCase(o3tl::trim(aContent), 
u"context-stroke"))
+                    {
+                        mbContextStroke = true;
+                    }
+                    else if(readSvgPaint(aContent, aSvgPaint, aURL, aOpacity))
                     {
                         maStroke = aSvgPaint;
                         if(aOpacity.isSet())
@@ -1996,6 +2006,23 @@ namespace svgio::svgreader
             }
         }
 
+        const basegfx::BColor* SvgStyleAttributes::getContextStroke() const
+        {
+            if (SVGToken::Marker == mrOwner.getType())
+                return maContextStroke;
+
+            const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
+            if (pSvgStyleAttributes && maResolvingParent[32] < 
nStyleDepthLimit)
+            {
+                ++maResolvingParent[32];
+                auto ret = pSvgStyleAttributes->getContextStroke();
+                --maResolvingParent[32];
+                return ret;
+            }
+
+            return nullptr;
+        }
+
         bool SvgStyleAttributes::isClipPathContent() const
         {
             if (SVGToken::ClipPathNode == mrOwner.getType())
@@ -2109,6 +2136,10 @@ namespace svgio::svgreader
                     return &maStroke.getBColor();
                 }
             }
+            else if (mbContextStroke)
+            {
+                return getContextStroke();
+            }
             else if (maNodeStrokeURL.isEmpty())
             {
                 const SvgStyleAttributes* pSvgStyleAttributes = 
getParentStyle();
commit acf30a32c7671278a2b6d3d20ac81726e56df254
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Thu Apr 18 13:23:43 2024 +0500
Commit:     Aron Budea <aron.bu...@collabora.com>
CommitDate: Wed May 8 08:11:45 2024 +0200

    tdf#157103: fix SVG whitespace handling
    
    Previous code tried to hack some tricks to restore whitespaces after
    trimming them according to the xml:space attribute value. But it was
    wrong in multiple ways.
    
    1. The collapsed space must stay in the block where its start was.
       When a block ended with a space, then trimming the space from it,
       and adding to a next block, can change the size of the space.
    2. The shift of a line (e.g., specifying x and y values) doesn't end
       the logical line. A space before such a shift must be kept by the
       same rules, as if there weren't a shift.
    3. A block with xml:space="preserve" is treated as if it consists of
       all non-whitespace characters, even if its leading or trailing
       characters are spaces. I.e., a trailing space in a block before,
       or a leading space in a block after, should be collapsed into a
       single space, not removed - even when the space-preserving block
       itself is made invisible.
    
    Change-Id: Ic778d1e9d6b9d0c342ea74ad78d44bb47bc8d708
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166239
    Tested-by: Mike Kaganski <mike.kagan...@collabora.com>
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167050
    Tested-by: Jenkins
    (cherry picked from commit 44b6b90080e7585e46250fb4076b210619e10bb3)

diff --git a/svgio/inc/svgcharacternode.hxx b/svgio/inc/svgcharacternode.hxx
index d81066af47a6..20c60d787cb5 100644
--- a/svgio/inc/svgcharacternode.hxx
+++ b/svgio/inc/svgcharacternode.hxx
@@ -38,11 +38,10 @@ namespace svgio::svgreader
             /// the string data
             OUString           maText;
 
-            // keep a copy of string data before space handling
-            OUString           maTextBeforeSpaceHandling;
-
             SvgTspanNode*        mpParentLine;
 
+            bool mbHadTrailingSpace = false;
+
             /// local helpers
             rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> 
createSimpleTextPrimitive(
                 SvgTextPosition& rSvgTextPosition,
@@ -65,8 +64,7 @@ namespace svgio::svgreader
             virtual const SvgStyleAttributes* getSvgStyleAttributes() const 
override;
 
             void 
decomposeText(drawinglayer::primitive2d::Primitive2DContainer& rTarget, 
SvgTextPosition& rSvgTextPosition) const;
-            void whiteSpaceHandling();
-            SvgCharacterNode* addGap(SvgCharacterNode* pPreviousCharacterNode);
+            SvgCharacterNode* whiteSpaceHandling(SvgCharacterNode* 
pPreviousCharacterNode);
             void concatenate(std::u16string_view rText);
 
             /// Text content
diff --git a/svgio/qa/cppunit/SvgImportTest.cxx 
b/svgio/qa/cppunit/SvgImportTest.cxx
index f6fb93634b8c..69c6a10d23f4 100644
--- a/svgio/qa/cppunit/SvgImportTest.cxx
+++ b/svgio/qa/cppunit/SvgImportTest.cxx
@@ -871,7 +871,7 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf85770)
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, 
"height"_ostr, "11");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, 
"familyname"_ostr, "Times New Roman");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"fontcolor"_ostr, "#000000");
-    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"text"_ostr, "Start");
+    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"text"_ostr, "Start ");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"height"_ostr, "11");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"familyname"_ostr, "Times New Roman");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]"_ostr, 
"fontcolor"_ostr, "#000000");
@@ -916,17 +916,17 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf93583)
     CPPUNIT_ASSERT (pDocument);
 
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, 
"text"_ostr, "This is the");
-    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, 
"x"_ostr, "62");
+    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, 
"x"_ostr, "58");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, 
"y"_ostr, "303");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, 
"width"_ostr, "16");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, 
"height"_ostr, "16");
-    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"text"_ostr, " first");
-    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"x"_ostr, "128");
+    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"text"_ostr, " first ");
+    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"x"_ostr, "124");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"y"_ostr, "303");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"width"_ostr, "32");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"height"_ostr, "32");
-    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]"_ostr, 
"text"_ostr, " line");
-    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]"_ostr, 
"x"_ostr, "188");
+    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]"_ostr, 
"text"_ostr, "line");
+    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]"_ostr, 
"x"_ostr, "192");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]"_ostr, 
"y"_ostr, "303");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]"_ostr, 
"width"_ostr, "16");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]"_ostr, 
"height"_ostr, "16");
@@ -942,28 +942,28 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf156616)
 
     CPPUNIT_ASSERT (pDocument);
 
-    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, 
"text"_ostr, "First");
+    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, 
"text"_ostr, "First ");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, 
"x"_ostr, "114");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, 
"y"_ostr, "103");
-    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"text"_ostr, " line");
-    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"x"_ostr, "143");
+    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"text"_ostr, "line ");
+    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"x"_ostr, "147");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"y"_ostr, "103");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]"_ostr, 
"text"_ostr, "Second line");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]"_ostr, 
"x"_ostr, "114");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]"_ostr, 
"y"_ostr, "122");
-    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[4]"_ostr, 
"text"_ostr, "First");
-    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[4]"_ostr, 
"x"_ostr, "86");
+    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[4]"_ostr, 
"text"_ostr, "First ");
+    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[4]"_ostr, 
"x"_ostr, "84");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[4]"_ostr, 
"y"_ostr, "153");
-    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[5]"_ostr, 
"text"_ostr, " line");
-    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[5]"_ostr, 
"x"_ostr, "115");
+    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[5]"_ostr, 
"text"_ostr, "line ");
+    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[5]"_ostr, 
"x"_ostr, "117");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[5]"_ostr, 
"y"_ostr, "153");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[6]"_ostr, 
"text"_ostr, "Second line");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[6]"_ostr, 
"x"_ostr, "77");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[6]"_ostr, 
"y"_ostr, "172");
-    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[7]"_ostr, 
"text"_ostr, "First");
-    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[7]"_ostr, 
"x"_ostr, "59");
+    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[7]"_ostr, 
"text"_ostr, "First ");
+    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[7]"_ostr, 
"x"_ostr, "55");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[7]"_ostr, 
"y"_ostr, "203");
-    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[8]"_ostr, 
"text"_ostr, " line");
+    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[8]"_ostr, 
"text"_ostr, "line ");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[8]"_ostr, 
"x"_ostr, "88");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[8]"_ostr, 
"y"_ostr, "203");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[9]"_ostr, 
"text"_ostr, "Second line");
@@ -1408,12 +1408,12 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf156251)
     // Without the fix in place, this test would have failed with
     // - Expected: 'You are '
     // - Actual  : 'You are'
-    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, 
"text"_ostr, "You are");
-    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"text"_ostr, " not");
+    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, 
"text"_ostr, "You are ");
+    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"text"_ostr, "not");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]"_ostr, 
"text"_ostr, " a banana!");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[4]"_ostr, 
"text"_ostr, "You are");
-    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[5]"_ostr, 
"text"_ostr, " not");
-    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[6]"_ostr, 
"text"_ostr, " a banana!");
+    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[5]"_ostr, 
"text"_ostr, " not ");
+    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[6]"_ostr, 
"text"_ostr, "a banana!");
 }
 
 CPPUNIT_TEST_FIXTURE(Test, testMaskText)
@@ -1954,15 +1954,15 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf156837)
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, 
"x"_ostr, "114");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, 
"y"_ostr, "103");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, 
"height"_ostr, "16");
-    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, 
"text"_ostr, "x");
-    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"x"_ostr, "122");
+    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, 
"text"_ostr, "x ");
+    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"x"_ostr, "126");
 
     // Without the fix in place, this test would have failed with
     // - Expected: 94
     // - Actual  : 103
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"y"_ostr, "94");
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"height"_ostr, "10");
-    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"text"_ostr, " 3");
+    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"text"_ostr, "3");
 }
 
 CPPUNIT_TEST_FIXTURE(Test, testTdf156271)
diff --git a/svgio/source/svgreader/svgcharacternode.cxx 
b/svgio/source/svgreader/svgcharacternode.cxx
index 7fdac9e92bc5..0aea1976c10f 100644
--- a/svgio/source/svgreader/svgcharacternode.cxx
+++ b/svgio/source/svgreader/svgcharacternode.cxx
@@ -486,53 +486,80 @@ namespace svgio::svgreader
             }
         }
 
-        void SvgCharacterNode::whiteSpaceHandling()
+        SvgCharacterNode*
+        SvgCharacterNode::whiteSpaceHandling(SvgCharacterNode* 
pPreviousCharacterNode)
         {
             bool bIsDefault(XmlSpace::Default == getXmlSpace());
             // if xml:space="default" then remove all newline characters, 
otherwise convert them to space
             // convert tab to space too
-            maText = maTextBeforeSpaceHandling = maText.replaceAll(u"
", bIsDefault ? u"" : u" ").replaceAll(u"       ", u" ");
+            maText = maText.replaceAll(u"
", bIsDefault ? u"" : u" ").replaceAll(u"       ", u" ");
 
-            if(bIsDefault)
+            if (!bIsDefault)
             {
-                // strip of all leading and trailing spaces
-                // and consolidate contiguous space
-                maText = consolidateContiguousSpace(maText.trim());
-            }
-        }
+                if (maText.isEmpty())
+                {
+                    // Ignore this empty node for the purpose of whitespace 
handling
+                    return pPreviousCharacterNode;
+                }
 
-        SvgCharacterNode* SvgCharacterNode::addGap(SvgCharacterNode* 
pPreviousCharacterNode)
-        {
-            // maText may have lost all text. If that's the case, ignore as 
invalid character node
-            // Also ignore if maTextBeforeSpaceHandling just have spaces
-            if(!maText.isEmpty() && 
!o3tl::trim(maTextBeforeSpaceHandling).empty())
-            {
-                if(pPreviousCharacterNode)
+                if (pPreviousCharacterNode && 
pPreviousCharacterNode->mbHadTrailingSpace)
                 {
-                    bool bAddGap(true);
+                    // pPreviousCharacterNode->mbHadTrailingSpace implies its 
xml:space="default".
+                    // Even if this xml:space="preserve" node is 
whitespace-only, the trailing space
+                    // of the previous node is significant - restore it
+                    pPreviousCharacterNode->maText += " ";
+                }
+
+                return this;
+            }
 
-                    // Do not add a gap if last node doesn't end with a space 
and
-                    // current note doesn't start with a space
-                    const sal_uInt32 
nLastLength(pPreviousCharacterNode->maTextBeforeSpaceHandling.getLength());
-                    
if(pPreviousCharacterNode->maTextBeforeSpaceHandling[nLastLength - 1] != ' ' && 
maTextBeforeSpaceHandling[0] != ' ')
-                        bAddGap = false;
+            bool bHadLeadingSpace = maText.startsWith(" ");
+            mbHadTrailingSpace = maText.endsWith(" "); // Only set for 
xml:space="default"
 
-                    // Do not add a gap if this node and last node are in 
different lines
-                    if(pPreviousCharacterNode->mpParentLine != mpParentLine)
-                        bAddGap = false;
+            // strip of all leading and trailing spaces
+            // and consolidate contiguous space
+            maText = consolidateContiguousSpace(maText.trim());
 
-                    // add in-between whitespace (single space) to the 
beginning of the current character node
-                    if(bAddGap)
+            if (pPreviousCharacterNode)
+            {
+                if (pPreviousCharacterNode->mbHadTrailingSpace)
+                {
+                    // pPreviousCharacterNode->mbHadTrailingSpace implies its 
xml:space="default".
+                    // The previous node already has a pending trailing space.
+                    if (maText.isEmpty())
                     {
-                        maText = " " + maText;
+                        // Leading spaces in this empty node are insignificant.
+                        // Ignore this empty node for the purpose of 
whitespace handling
+                        return pPreviousCharacterNode;
                     }
+                    // The previous node's trailing space is significant - 
restore it. Note that
+                    // it is incorrect to insert a space in this node instead: 
the spaces in
+                    // different nodes may have different size
+                    pPreviousCharacterNode->maText += " ";
+                    return this;
                 }
 
-                // this becomes the previous character node
-                return this;
+                if (bHadLeadingSpace)
+                {
+                    // This possibly whitespace-only xml:space="default" node 
goes after another
+                    // node either having xml:space="default", but without a 
trailing space; or
+                    // having xml:space="preserve" (in that case, it's 
irrelevant if that node had
+                    // any trailing spaces).
+                    if (!maText.isEmpty())
+                    {
+                        // The leading whitespace in this node is significant 
- restore it
+                        maText = " " + maText;
+                    }
+                    // The trailing whitespace in this node may or may not be
+                    // significant (it will be significant, if there will be 
more nodes). Keep it as
+                    // it is (even empty), but return this, to participate in 
whitespace handling
+                    return this;
+                }
             }
 
-            return pPreviousCharacterNode;
+            // No previous node, or no leading/trailing space on the previous 
node's boundary: if
+            // this is whitespace-only, its whitespace is never significant
+            return maText.isEmpty() ? pPreviousCharacterNode : this;
         }
 
         void SvgCharacterNode::concatenate(std::u16string_view rText)
diff --git a/svgio/source/svgreader/svgdocumenthandler.cxx 
b/svgio/source/svgreader/svgdocumenthandler.cxx
index 8d2cc8849c55..5e6e0d404843 100644
--- a/svgio/source/svgreader/svgdocumenthandler.cxx
+++ b/svgio/source/svgreader/svgdocumenthandler.cxx
@@ -66,7 +66,46 @@ namespace svgio::svgreader
 
 namespace
 {
-    svgio::svgreader::SvgCharacterNode* 
whiteSpaceHandling(svgio::svgreader::SvgNode const * pNode, 
svgio::svgreader::SvgTspanNode* pParentLine, 
svgio::svgreader::SvgCharacterNode* pLast)
+using CharacterNodeHandlerFunc
+    = svgio::svgreader::SvgCharacterNode*(svgio::svgreader::SvgCharacterNode* 
pCharNode,
+                                          svgio::svgreader::SvgTspanNode* 
pParentLine,
+                                          svgio::svgreader::SvgCharacterNode* 
pLast);
+    // clean whitespace in text span
+    svgio::svgreader::SvgCharacterNode* 
whiteSpaceHandling(svgio::svgreader::SvgCharacterNode* pCharNode,
+                                                           
svgio::svgreader::SvgTspanNode* pParentLine,
+                                                           
svgio::svgreader::SvgCharacterNode* pLast)
+    {
+        pCharNode->setParentLine(pParentLine);
+        return pCharNode->whiteSpaceHandling(pLast);
+    }
+
+    // set correct widths of text lines
+    svgio::svgreader::SvgCharacterNode* 
calcTextLineWidths(svgio::svgreader::SvgCharacterNode* pCharNode,
+                                                           
svgio::svgreader::SvgTspanNode* pParentLine,
+                                                           
svgio::svgreader::SvgCharacterNode* /*pLast*/)
+    {
+        if (const SvgStyleAttributes* pSvgStyleAttributes = 
pCharNode->getSvgStyleAttributes())
+        {
+            const drawinglayer::attribute::FontAttribute aFontAttribute(
+                
svgio::svgreader::SvgCharacterNode::getFontAttribute(*pSvgStyleAttributes));
+
+            double 
fFontWidth(pSvgStyleAttributes->getFontSizeNumber().solve(*pCharNode));
+            double fFontHeight(fFontWidth);
+
+            css::lang::Locale aLocale;
+            drawinglayer::primitive2d::TextLayouterDevice aTextLayouterDevice;
+            aTextLayouterDevice.setFontAttribute(aFontAttribute, fFontWidth, 
fFontHeight, aLocale);
+            double fTextWidth = 
aTextLayouterDevice.getTextWidth(pCharNode->getText(), 0.0,
+                                                                 
pCharNode->getText().getLength());
+            pParentLine->concatenateTextLineWidth(fTextWidth);
+        }
+        return nullptr; // no pLast handling
+    }
+
+    svgio::svgreader::SvgCharacterNode* 
walkRecursive(svgio::svgreader::SvgNode const* pNode,
+                                                      
svgio::svgreader::SvgTspanNode* pParentLine,
+                                                      
svgio::svgreader::SvgCharacterNode* pLast,
+                                                      
CharacterNodeHandlerFunc* pHandlerFunc)
     {
         if(pNode)
         {
@@ -83,34 +122,9 @@ namespace
                     {
                         case SVGToken::Character:
                         {
-                            // clean whitespace in text span
                             svgio::svgreader::SvgCharacterNode* pCharNode = 
static_cast< svgio::svgreader::SvgCharacterNode* >(pCandidate);
 
-                            pCharNode->setParentLine(pParentLine);
-
-                            pCharNode->whiteSpaceHandling();
-                            pLast = pCharNode->addGap(pLast);
-
-                            double fTextWidth(0.0);
-
-                            const SvgStyleAttributes* pSvgStyleAttributes = 
pCharNode->getSvgStyleAttributes();
-
-                            if(pSvgStyleAttributes)
-                            {
-                                const drawinglayer::attribute::FontAttribute 
aFontAttribute(
-                                        
svgio::svgreader::SvgCharacterNode::getFontAttribute(*pSvgStyleAttributes));
-
-                                double 
fFontWidth(pSvgStyleAttributes->getFontSizeNumber().solve(*pCharNode));
-                                double fFontHeight(fFontWidth);
-
-                                css::lang::Locale aLocale;
-
-                                drawinglayer::primitive2d::TextLayouterDevice 
aTextLayouterDevice;
-                                
aTextLayouterDevice.setFontAttribute(aFontAttribute, fFontWidth, fFontHeight, 
aLocale);
-                                fTextWidth = 
aTextLayouterDevice.getTextWidth(pCharNode->getText(), 0.0, 
pCharNode->getText().getLength());
-                            }
-
-                            pParentLine->concatenateTextLineWidth(fTextWidth);
+                            pLast = pHandlerFunc(pCharNode, pParentLine, 
pLast);
                             break;
                         }
                         case SVGToken::Tspan:
@@ -121,15 +135,15 @@ namespace
                             if(!pTspanNode->getX().empty() || 
!pTspanNode->getY().empty())
                                 pParentLine = pTspanNode;
 
-                            // recursively clean whitespaces in subhierarchy
-                            pLast = whiteSpaceHandling(pCandidate, 
pParentLine, pLast);
+                            // recursively handle subhierarchy
+                            pLast = walkRecursive(pCandidate, pParentLine, 
pLast, pHandlerFunc);
                             break;
                         }
                         case SVGToken::TextPath:
                         case SVGToken::Tref:
                         {
-                            // recursively clean whitespaces in subhierarchy
-                            pLast = whiteSpaceHandling(pCandidate, 
pParentLine, pLast);
+                            // recursively handle subhierarchy
+                            pLast = walkRecursive(pCandidate, pParentLine, 
pLast, pHandlerFunc);
                             break;
                         }
                         default:
@@ -516,7 +530,12 @@ namespace
             if(pTextNode)
             {
                 // cleanup read strings
-                whiteSpaceHandling(pTextNode, static_cast< 
SvgTspanNode*>(pTextNode), nullptr);
+                // First pass: handle whitespace. This works in a way that 
handling a following
+                // node may append a space to a previous node; so correct line 
width calculation
+                // may only happen after this pass finishes
+                walkRecursive(pTextNode, 
static_cast<SvgTspanNode*>(pTextNode), nullptr, whiteSpaceHandling);
+                // Second pass: calculate line widths
+                walkRecursive(pTextNode, 
static_cast<SvgTspanNode*>(pTextNode), nullptr, calcTextLineWidths);
             }
         }
 
commit 063a24044ee3e6b225147f619d1f77b8270499fa
Author:     Julien Nabet <serval2...@yahoo.fr>
AuthorDate: Fri May 3 08:04:53 2024 +0200
Commit:     Aron Budea <aron.bu...@collabora.com>
CommitDate: Wed May 8 08:11:36 2024 +0200

    tdf#160916: typo "Checbox"
    
    Change-Id: Ia06bc947cd1788850251b1386977ef0229dddd8a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167030
    Reviewed-by: Julien Nabet <serval2...@yahoo.fr>
    Tested-by: Jenkins
    (cherry picked from commit 68008d9f0176c43ecc768af8e3539227640d1519)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166905
    Reviewed-by: Adolfo Jayme Barrientos <fit...@ubuntu.com>
    Reviewed-by: Heiko Tietze <heiko.tie...@documentfoundation.org>
    Tested-by: Julien Nabet <serval2...@yahoo.fr>
    (cherry picked from commit f1b1e61ef56b85fd56f39854d2edb52f3c2d8b82)

diff --git a/extras/source/tipoftheday/formdocuments.svg 
b/extras/source/tipoftheday/formdocuments.svg
index b6ad08cab3d7..a3d752292fa5 100644
--- a/extras/source/tipoftheday/formdocuments.svg
+++ b/extras/source/tipoftheday/formdocuments.svg
@@ -1 +1 @@
-<svg height="150" viewBox="0 0 39.687499 39.6875" width="150" 
xmlns="http://www.w3.org/2000/svg"; 
xmlns:xlink="http://www.w3.org/1999/xlink";><filter id="a" 
color-interpolation-filters="sRGB" height="1.13824" width="1.136293" 
x="-.068146" y="-.06912"><feGaussianBlur stdDeviation="1.0668"/></filter><g 
stroke-width=".264583"><path d="m1.3229163 1.852083 
37.5708337-.0000022v37.0416692l-37.5708337.000002z" fill="#48484a" 
filter="url(#a)" opacity=".557352" stroke-opacity=".501961"/><path 
d="m1.5875003 2.116667h37.0416677v35.983334h-37.0416677z" fill="#f2f2f7" 
stroke-opacity=".501961"/><text stroke-linecap="round" stroke-linejoin="round" 
x="34.924999" y="2.645833"><tspan stroke-width=".264583" x="34.924999" 
y="2.645833"/></text><path d="m1.5875 
2.1166666h37.041668v8.9958334h-37.041668z" fill="#d1d1d6" 
stroke-linecap="round" stroke-linejoin="round"/><text fill="#48484a" 
font-family="Inter" font-size="3.52778" stroke-linecap="round" 
stroke-linejoin="round" x="13.448908" y="7.878621"><tspan fi
 ll="#48484a" font-family="Inter" font-size="3.52778" font-weight="bold" 
stroke-width=".264583" x="13.448908" y="7.878621">PDF Form</tspan></text><g 
transform="translate(.071347 16.933337)"><path d="m6.543236 5.0270833c-.2931584 
0-.5291667.2360083-.5291667.5291666v2.9104167c0 
.2931583.2360083.5291667.5291667.5291667h2.9104166c.2931583 0 
.5291667-.2360084.5291667-.5291667v-2.9104167c0-.2931583-.2360084-.5291666-.5291667-.5291666zm.1322916.2645833h2.6458333c.2198688
 0 .396875.1770063.396875.396875v2.6458333c0 
.2198688-.1770062.396875-.396875.396875h-2.6458333c-.2198687 
0-.396875-.1770062-.396875-.396875v-2.6458333c0-.2198687.1770063-.396875.396875-.396875z"
 fill="#44b1e9"/><path d="m6.6755276 5.2916666h2.6458333c.2198688 0 
.396875.1770063.396875.396875v2.6458333c0 
.2198688-.1770062.396875-.396875.396875h-2.6458333c-.2198687 
0-.396875-.1770062-.396875-.396875v-2.6458333c0-.2198687.1770063-.396875.396875-.396875z"
 fill="#93cee9"/><path d="m6.543236 6.8791666v.396875l1.0583333 1.0583333 1
 .8520833-1.8520833v-.396875h-.4578194l-1.3942639 1.3229167-.5291667-.5291667z" 
fill="#232629"/></g><g transform="translate(6.085417 28.839591)"><path 
d="m1.984375 0a1.984375 1.984375 0 0 0 -1.984375 1.984375 1.984375 1.984375 0 0 
0 1.984375 1.984375 1.984375 1.984375 0 0 0 1.984375-1.984375 1.984375 1.984375 
0 0 0 -1.984375-1.984375zm0 .26458333a1.7197916 1.7197916 0 0 1 1.7197916 
1.71979167 1.7197916 1.7197916 0 0 1 -1.7197916 1.7197916 1.7197916 1.7197916 0 
0 1 -1.71979167-1.7197916 1.7197916 1.7197916 0 0 1 1.71979167-1.71979167z" 
fill="#44b1e9"/><path d="m3.7041666 1.984375a1.7197916 1.7197916 0 0 1 
-1.7197916 1.7197916 1.7197916 1.7197916 0 0 1 -1.71979167-1.7197916 1.7197916 
1.7197916 0 0 1 1.71979167-1.71979167 1.7197916 1.7197916 0 0 1 1.7197916 
1.71979167z" fill="#93cee9"/><path d="m2.778125 1.984375a.79374999.79374999 0 0 
1 -.79375.79375.79374999.79374999 0 0 1 -.79375-.79375.79374999.79374999 0 0 1 
.79375-.79375.79374999.79374999 0 0 1 .79375.79375z" fill="#232629"/></g><
 g fill="#48484a"><text font-family="Inter" font-size="3.175" 
stroke-linecap="round" stroke-linejoin="round" x="13.448908" 
y="25.225746"><tspan fill="#48484a" font-family="Inter" font-size="3.175" 
stroke-width=".264583" x="13.448908" y="25.225746">Checbox</tspan></text><text 
font-family="Inter" font-size="3.175" stroke-linecap="round" 
stroke-linejoin="round" x="13.448908" y="31.994297"><tspan fill="#48484a" 
font-family="Inter" font-size="3.175" stroke-width=".264583" x="13.448908" 
y="31.994297">Radio Button</tspan></text><text font-family="Inter" 
font-size="3.175" stroke-linecap="round" stroke-linejoin="round" x="13.448908" 
y="18.346573"><tspan fill="#48484a" font-family="Inter" font-size="3.175" 
stroke-width=".264583" x="13.448908" y="18.346573">Text 
Box</tspan></text></g><path d="m7.7333779 14.948958-1.0231933 
2.901115-.037724.122473-.4547527 
1.209745h.511597l.5017781-1.342037h1.677417l.5017781 
1.342037h.5115967l-.4547526-1.209745-.0377238-.122473-1.0231934-2.901115h-.0661459-.5405
 353zm.3410644.586011.6728273 1.918229h-1.3549561z" fill="#232629"/></g><g 
transform="translate(.529167)"><path d="m5.0270833 
3.7041667v5.8208332h4.7624999v-3.96875l-1.8520833-1.8520832zm.2645833.2645833h2.38125v1.8520833h1.8520833v3.4395833h-4.2333333z"
 fill="#48484a" stroke-width=".264583"/><path d="m5.8208333 
8.4666666c1.3829607-1.1563781 1.2720396-2.0342018 1.2271086-2.92433-.198148 
1.4292522.5394675 1.9405571 1.6971971 
2.0397454-.8730557-.2752884-1.7982518-.2583058-2.9243057.8845846z" fill="none" 
stroke="#ed3d3b" stroke-linecap="round" stroke-linejoin="round" 
stroke-width=".250965"/></g></svg>
\ No newline at end of file
+<svg height="150" viewBox="0 0 39.687499 39.6875" width="150" 
xmlns="http://www.w3.org/2000/svg"; 
xmlns:xlink="http://www.w3.org/1999/xlink";><filter id="a" 
color-interpolation-filters="sRGB" height="1.13824" width="1.136293" 
x="-.068146" y="-.06912"><feGaussianBlur stdDeviation="1.0668"/></filter><g 
stroke-width=".264583"><path d="m1.3229163 1.852083 
37.5708337-.0000022v37.0416692l-37.5708337.000002z" fill="#48484a" 
filter="url(#a)" opacity=".557352" stroke-opacity=".501961"/><path 
d="m1.5875003 2.116667h37.0416677v35.983334h-37.0416677z" fill="#f2f2f7" 
stroke-opacity=".501961"/><text stroke-linecap="round" stroke-linejoin="round" 
x="34.924999" y="2.645833"><tspan stroke-width=".264583" x="34.924999" 
y="2.645833"/></text><path d="m1.5875 
2.1166666h37.041668v8.9958334h-37.041668z" fill="#d1d1d6" 
stroke-linecap="round" stroke-linejoin="round"/><text fill="#48484a" 
font-family="Inter" font-size="3.52778" stroke-linecap="round" 
stroke-linejoin="round" x="13.448908" y="7.878621"><tspan fi
 ll="#48484a" font-family="Inter" font-size="3.52778" font-weight="bold" 
stroke-width=".264583" x="13.448908" y="7.878621">PDF Form</tspan></text><g 
transform="translate(.071347 16.933337)"><path d="m6.543236 5.0270833c-.2931584 
0-.5291667.2360083-.5291667.5291666v2.9104167c0 
.2931583.2360083.5291667.5291667.5291667h2.9104166c.2931583 0 
.5291667-.2360084.5291667-.5291667v-2.9104167c0-.2931583-.2360084-.5291666-.5291667-.5291666zm.1322916.2645833h2.6458333c.2198688
 0 .396875.1770063.396875.396875v2.6458333c0 
.2198688-.1770062.396875-.396875.396875h-2.6458333c-.2198687 
0-.396875-.1770062-.396875-.396875v-2.6458333c0-.2198687.1770063-.396875.396875-.396875z"
 fill="#44b1e9"/><path d="m6.6755276 5.2916666h2.6458333c.2198688 0 
.396875.1770063.396875.396875v2.6458333c0 
.2198688-.1770062.396875-.396875.396875h-2.6458333c-.2198687 
0-.396875-.1770062-.396875-.396875v-2.6458333c0-.2198687.1770063-.396875.396875-.396875z"
 fill="#93cee9"/><path d="m6.543236 6.8791666v.396875l1.0583333 1.0583333 1
 .8520833-1.8520833v-.396875h-.4578194l-1.3942639 1.3229167-.5291667-.5291667z" 
fill="#232629"/></g><g transform="translate(6.085417 28.839591)"><path 
d="m1.984375 0a1.984375 1.984375 0 0 0 -1.984375 1.984375 1.984375 1.984375 0 0 
0 1.984375 1.984375 1.984375 1.984375 0 0 0 1.984375-1.984375 1.984375 1.984375 
0 0 0 -1.984375-1.984375zm0 .26458333a1.7197916 1.7197916 0 0 1 1.7197916 
1.71979167 1.7197916 1.7197916 0 0 1 -1.7197916 1.7197916 1.7197916 1.7197916 0 
0 1 -1.71979167-1.7197916 1.7197916 1.7197916 0 0 1 1.71979167-1.71979167z" 
fill="#44b1e9"/><path d="m3.7041666 1.984375a1.7197916 1.7197916 0 0 1 
-1.7197916 1.7197916 1.7197916 1.7197916 0 0 1 -1.71979167-1.7197916 1.7197916 
1.7197916 0 0 1 1.71979167-1.71979167 1.7197916 1.7197916 0 0 1 1.7197916 
1.71979167z" fill="#93cee9"/><path d="m2.778125 1.984375a.79374999.79374999 0 0 
1 -.79375.79375.79374999.79374999 0 0 1 -.79375-.79375.79374999.79374999 0 0 1 
.79375-.79375.79374999.79374999 0 0 1 .79375.79375z" fill="#232629"/></g><
 g fill="#48484a"><text font-family="Inter" font-size="3.175" 
stroke-linecap="round" stroke-linejoin="round" x="13.448908" 
y="25.225746"><tspan fill="#48484a" font-family="Inter" font-size="3.175" 
stroke-width=".264583" x="13.448908" y="25.225746">Checkbox</tspan></text><text 
font-family="Inter" font-size="3.175" stroke-linecap="round" 
stroke-linejoin="round" x="13.448908" y="31.994297"><tspan fill="#48484a" 
font-family="Inter" font-size="3.175" stroke-width=".264583" x="13.448908" 
y="31.994297">Radio Button</tspan></text><text font-family="Inter" 
font-size="3.175" stroke-linecap="round" stroke-linejoin="round" x="13.448908" 
y="18.346573"><tspan fill="#48484a" font-family="Inter" font-size="3.175" 
stroke-width=".264583" x="13.448908" y="18.346573">Text 
Box</tspan></text></g><path d="m7.7333779 14.948958-1.0231933 
2.901115-.037724.122473-.4547527 
1.209745h.511597l.5017781-1.342037h1.677417l.5017781 
1.342037h.5115967l-.4547526-1.209745-.0377238-.122473-1.0231934-2.901115h-.0661459-.540
 5353zm.3410644.586011.6728273 1.918229h-1.3549561z" fill="#232629"/></g><g 
transform="translate(.529167)"><path d="m5.0270833 
3.7041667v5.8208332h4.7624999v-3.96875l-1.8520833-1.8520832zm.2645833.2645833h2.38125v1.8520833h1.8520833v3.4395833h-4.2333333z"
 fill="#48484a" stroke-width=".264583"/><path d="m5.8208333 
8.4666666c1.3829607-1.1563781 1.2720396-2.0342018 1.2271086-2.92433-.198148 
1.4292522.5394675 1.9405571 1.6971971 
2.0397454-.8730557-.2752884-1.7982518-.2583058-2.9243057.8845846z" fill="none" 
stroke="#ed3d3b" stroke-linecap="round" stroke-linejoin="round" 
stroke-width=".250965"/></g></svg>
commit 0100a9bc2c517acb7204b09714777339798f18db
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Tue Apr 16 10:48:06 2024 +0500
Commit:     Aron Budea <aron.bu...@collabora.com>
CommitDate: Wed May 8 08:11:28 2024 +0200

    tdf#160702: improve text positioning
    
    Opening an SVG with text in different elements (e.g., tspans) in the
    same text element performs calculations to position the parts properly
    (i.e., the next part will start where the previous part ended, unless
    the position in overridden explicitly). These calculations require to
    know the text widths. The first problem leas here: the text width was
    calculated for a typically small text size (numerically equal to the
    pixel size defined in the SVG), but these calculations aren't truly
    linear, because font rendering may change depending on font height.
    Additionally, the rounding gives much higher error in smaller sizes
    than in larger. There was already a workaround for a similar problem
    in ViewRedirector::createRedirectedPrimitive2DSequence, where a large
    font (with 100 times greater height) was used to increase correctness.
    This was also used here, with the same large height (50000) used as a
    reference.
    
    Then, at the time of wrawing the text at different zoom levels, the
    code in VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D
    creates a font of a calculated size, and uses it to output the text.
    But the font is always created with an integral height, which means,
    that for a wanted height of 2.5 (in a zoomed out view), the really
    used height will be 3, which is 20% larger; or for wanted height of
    2.4, the actual height will be 2 (20% smaller). This resulted in odd
    jumps of the text widths, when the text may overlap the following
    part, or conversely, create a big gap before the next gap. To try to
    mitigate that, the function now takes the difference between the
    wanted and the actual font size into account, and adjusts the MapMode
    accordingly. This doesn't fix the jumping completely (e.g., because
    of the mentioned special handling of small font sizes in the fonts
    thenselves, like hinting), but still makes the calculations much more
    stable, decreasing the amount of jumping. Similar changes are made in
    TextLayouterDevice.
    
    Use of the functions that return text size as a double, not rounded
    value, should additionally help improving stability.
    
    Change-Id: I455845d8ca43ee9c06a0fc980947f35d8a25797a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166238
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166468
    (cherry picked from commit 5a25899a9c5c0c4e6fb92ca355ea1e24cec3a747)

diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx 
b/drawinglayer/source/primitive2d/textlayoutdevice.cxx
index 5145d84ed2b6..afc0663aa4b0 100644
--- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx
+++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx
@@ -22,6 +22,8 @@
 #include <algorithm>
 
 #include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
 #include <drawinglayer/attribute/fontattribute.hxx>
 #include <drawinglayer/primitive2d/textlayoutdevice.hxx>
 #include <comphelper/processfactory.hxx>
@@ -162,56 +164,69 @@ TextLayouterDevice::TextLayouterDevice()
 
 TextLayouterDevice::~TextLayouterDevice() COVERITY_NOEXCEPT_FALSE { 
releaseGlobalVirtualDevice(); }
 
-void TextLayouterDevice::setFont(const vcl::Font& rFont) { 
mrDevice.SetFont(rFont); }
+void TextLayouterDevice::setFont(const vcl::Font& rFont)
+{
+    mrDevice.SetFont(rFont);
+    mnFontScalingFixX = 1.0;
+    mnFontScalingFixY = 1.0;
+}
 
 void TextLayouterDevice::setFontAttribute(const attribute::FontAttribute& 
rFontAttribute,
                                           double fFontScaleX, double 
fFontScaleY,
                                           const css::lang::Locale& rLocale)
 {
-    setFont(getVclFontFromFontAttribute(rFontAttribute, fFontScaleX, 
fFontScaleY, 0.0, rLocale));
+    vcl::Font aFont
+        = getVclFontFromFontAttribute(rFontAttribute, fFontScaleX, 
fFontScaleY, 0.0, rLocale);
+    setFont(aFont);
+    Size aFontSize = aFont.GetFontSize();
+    mnFontScalingFixY = fFontScaleY / aFontSize.Height();
+    mnFontScalingFixX = fFontScaleX / (aFontSize.Width() ? aFontSize.Width() : 
aFontSize.Height());
 }
 
 double TextLayouterDevice::getOverlineOffset() const
 {
     const ::FontMetric& rMetric = mrDevice.GetFontMetric();
     double fRet = (rMetric.GetInternalLeading() / 2.0) - rMetric.GetAscent();
-    return fRet;
+    return fRet * mnFontScalingFixY;
 }
 
 double TextLayouterDevice::getUnderlineOffset() const
 {
     const ::FontMetric& rMetric = mrDevice.GetFontMetric();
     double fRet = rMetric.GetDescent() / 2.0;
-    return fRet;
+    return fRet * mnFontScalingFixY;
 }
 
 double TextLayouterDevice::getStrikeoutOffset() const
 {
     const ::FontMetric& rMetric = mrDevice.GetFontMetric();
     double fRet = (rMetric.GetAscent() - rMetric.GetInternalLeading()) / 3.0;
-    return fRet;
+    return fRet * mnFontScalingFixY;
 }
 
 double TextLayouterDevice::getOverlineHeight() const
 {
     const ::FontMetric& rMetric = mrDevice.GetFontMetric();
     double fRet = rMetric.GetInternalLeading() / 2.5;
-    return fRet;
+    return fRet * mnFontScalingFixY;
 }
 
 double TextLayouterDevice::getUnderlineHeight() const
 {
     const ::FontMetric& rMetric = mrDevice.GetFontMetric();
     double fRet = rMetric.GetDescent() / 4.0;
-    return fRet;
+    return fRet * mnFontScalingFixY;
 }
 
-double TextLayouterDevice::getTextHeight() const { return 
mrDevice.GetTextHeight(); }
+double TextLayouterDevice::getTextHeight() const
+{
+    return mrDevice.GetTextHeight() * mnFontScalingFixY;
+}
 
 double TextLayouterDevice::getTextWidth(const OUString& rText, sal_uInt32 
nIndex,
                                         sal_uInt32 nLength) const
 {
-    return mrDevice.GetTextWidth(rText, nIndex, nLength);
+    return mrDevice.GetTextWidth(rText, nIndex, nLength) * mnFontScalingFixX;
 }
 
 void TextLayouterDevice::getTextOutlines(basegfx::B2DPolyPolygonVector& 
rB2DPolyPolyVector,
@@ -245,6 +260,13 @@ void 
TextLayouterDevice::getTextOutlines(basegfx::B2DPolyPolygonVector& rB2DPoly
     {
         mrDevice.GetTextOutlines(rB2DPolyPolyVector, rText, nIndex, nIndex, 
nLength);
     }
+    if (!rtl_math_approxEqual(mnFontScalingFixY, 1.0)
+        || !rtl_math_approxEqual(mnFontScalingFixX, 1.0))
+    {
+        auto scale = 
basegfx::utils::createScaleB2DHomMatrix(mnFontScalingFixX, mnFontScalingFixY);
+        for (auto& poly : rB2DPolyPolyVector)
+            poly.transform(scale);
+    }
 }
 
 basegfx::B2DRange TextLayouterDevice::getTextBoundRect(const OUString& rText, 
sal_uInt32 nIndex,
@@ -262,6 +284,12 @@ basegfx::B2DRange 
TextLayouterDevice::getTextBoundRect(const OUString& rText, sa
     {
         basegfx::B2DRange aRect;
         mrDevice.GetTextBoundRect(aRect, rText, nIndex, nIndex, nLength);
+        if (!rtl_math_approxEqual(mnFontScalingFixY, 1.0)
+            || !rtl_math_approxEqual(mnFontScalingFixX, 1.0))
+        {
+            aRect.transform(
+                basegfx::utils::createScaleB2DHomMatrix(mnFontScalingFixX, 
mnFontScalingFixY));
+        }
         return aRect;
     }
 
@@ -271,13 +299,13 @@ basegfx::B2DRange 
TextLayouterDevice::getTextBoundRect(const OUString& rText, sa
 double TextLayouterDevice::getFontAscent() const
 {
     const ::FontMetric& rMetric = mrDevice.GetFontMetric();
-    return rMetric.GetAscent();
-e 
... etc. - the rest is truncated

Reply via email to