Repository.mk                                                         |    4 
 RepositoryExternal.mk                                                 |    6 
 config_host/config_features.h.in                                      |    5 
 configure.ac                                                          |   21 
 desktop/Library_sofficeapp.mk                                         |    3 
 desktop/source/deployment/registry/configuration/dp_configuration.cxx |   36 
 filter/source/pdf/pdfexport.cxx                                       |   30 
 include/comphelper/xmlencode.hxx                                      |   62 +
 include/sfx2/strings.hrc                                              |    7 
 include/svtools/HtmlWriter.hxx                                        |    3 
 include/svtools/htmlkywd.hxx                                          |    1 
 include/svtools/htmltokn.h                                            |    1 
 include/svtools/parhtml.hxx                                           |    5 
 include/svtools/sfxecode.hxx                                          |    4 
 include/vcl/pdfwriter.hxx                                             |    2 
 lingucomponent/Module_lingucomponent.mk                               |    2 
 sd/source/filter/html/htmlex.cxx                                      |    5 
 sfx2/source/doc/docmacromode.cxx                                      |   25 
 sfx2/source/view/viewfrm.cxx                                          |   40 
 starmath/inc/document.hxx                                             |    4 
 starmath/inc/view.hxx                                                 |   19 
 starmath/source/document.cxx                                          |  309 
++++++
 starmath/source/unomodel.cxx                                          |   37 
 starmath/source/view.cxx                                              |  317 
------
 svtools/inc/errtxt.hrc                                                |    3 
 svtools/qa/unit/testHtmlWriter.cxx                                    |    6 
 svtools/source/svhtml/HtmlWriter.cxx                                  |   25 
 svtools/source/svhtml/htmlkywd.cxx                                    |    1 
 svtools/source/svhtml/parhtml.cxx                                     |   59 -
 sw/qa/extras/htmlexport/data/NestingInA1.fodt                         |   47 
 sw/qa/extras/htmlexport/data/embedded_formula.fodt                    |   30 
 sw/qa/extras/htmlexport/data/frameWithText.fodt                       |   25 
 sw/qa/extras/htmlexport/data/image_anchored_to_paragraph_no_wrap.fodt |   20 
 sw/qa/extras/htmlexport/data/table_cell_padding.fodt                  |   34 
 sw/qa/extras/htmlexport/data/table_with_wide_horizontal_border.fodt   |   27 
 sw/qa/extras/htmlexport/data/tdf155871.fodt                           |   21 
 sw/qa/extras/htmlexport/data/test_no_space_preserve.fodt              |   25 
 sw/qa/extras/htmlexport/data/twoListsWithSameStyle.fodt               |   19 
 sw/qa/extras/htmlexport/htmlexport.cxx                                |  511 
+++++++++-
 sw/qa/extras/tiledrendering/data/multiline.odt                        |binary
 sw/qa/extras/tiledrendering/tiledrendering.cxx                        |   40 
 sw/source/core/doc/doclay.cxx                                         |   25 
 sw/source/filter/basflt/shellio.cxx                                   |   14 
 sw/source/filter/html/css1atr.cxx                                     |   23 
 sw/source/filter/html/css1kywd.cxx                                    |    2 
 sw/source/filter/html/css1kywd.hxx                                    |    2 
 sw/source/filter/html/htmlatr.cxx                                     |  150 ++
 sw/source/filter/html/htmlfldw.cxx                                    |    7 
 sw/source/filter/html/htmlflywriter.cxx                               |  179 
++-
 sw/source/filter/html/htmlforw.cxx                                    |   16 
 sw/source/filter/html/htmlftn.cxx                                     |    8 
 sw/source/filter/html/htmlnumwriter.cxx                               |   46 
 sw/source/filter/html/htmlplug.cxx                                    |  187 
++-
 sw/source/filter/html/htmltab.cxx                                     |   27 
 sw/source/filter/html/htmltabw.cxx                                    |   29 
 sw/source/filter/html/svxcss1.cxx                                     |   14 
 sw/source/filter/html/svxcss1.hxx                                     |    1 
 sw/source/filter/html/swhtml.cxx                                      |   11 
 sw/source/filter/html/wrthtml.cxx                                     |  161 
+--
 sw/source/filter/html/wrthtml.hxx                                     |   24 
 sw/source/ui/dialog/swdlgfact.cxx                                     |    4 
 sw/source/uibase/app/docsh.cxx                                        |   14 
 sw/source/uibase/dochdl/swdtflvr.cxx                                  |    2 
 sw/source/uibase/inc/translatehelper.hxx                              |    8 
 sw/source/uibase/shells/textsh1.cxx                                   |   14 
 sw/source/uibase/shells/translatehelper.cxx                           |    8 
 ucb/JunitTest_ucb_webdav_unoapi.mk                                    |   14 
 ucb/Module_ucb.mk                                                     |    1 
 ucb/qa/unoapi/ucb.sce                                                 |    2 
 ucb/qa/unoapi/ucb_webdav.sce                                          |   19 
 vcl/source/gdi/pdfwriter_impl.cxx                                     |   39 
 71 files changed, 2027 insertions(+), 865 deletions(-)

New commits:
commit aa7f38757c84c16ca1e96a46df803020a4bff541
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Mon Nov 27 16:01:11 2023 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Mon Dec 11 16:56:42 2023 +0300

    Don't emit 'br clear=...' for graphics wrap in ReqIF export
    
    Change-Id: I7684c78c9b98fe63c2281bf3b2a2186d125e0ba4
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159994
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git 
a/sw/qa/extras/htmlexport/data/image_anchored_to_paragraph_no_wrap.fodt 
b/sw/qa/extras/htmlexport/data/image_anchored_to_paragraph_no_wrap.fodt
new file mode 100644
index 000000000000..f1080724307e
--- /dev/null
+++ b/sw/qa/extras/htmlexport/data/image_anchored_to_paragraph_no_wrap.fodt
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office: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.text">
+ <office:automatic-styles>
+  <style:style style:name="fr1" style:family="graphic" 
style:parent-style-name="OLE">
+   <style:graphic-properties style:wrap="none"/>
+  </style:style>
+ </office:automatic-styles>
+ <office:body>
+  <office:text>
+   <text:p><draw:frame draw:style-name="fr1" draw:name="Image1" 
text:anchor-type="paragraph" svg:width="17cm" svg:height="13cm"><draw:image 
draw:mime-type="image/svg+xml">
+      
<office:binary-data>PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB4bWxucz0iaHR0
+       cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDIw
+       IDIwIiBzdHJva2U9ImJsYWNrIj4KPHBhdGggZD0iTTEsMUwxOSwxOSIvPgo8L3N2Zz4=
+      </office:binary-data>
+     </draw:image>
+    </draw:frame></text:p>
+  </office:text>
+ </office:body>
+</office:document>
\ No newline at end of file
diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx 
b/sw/qa/extras/htmlexport/htmlexport.cxx
index 721b72f31632..0e2396c39fd5 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -3005,6 +3005,24 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, 
testReqIF_ExportFormulasAsPDF)
                          xTypeDetection->queryTypeByDescriptor(descr, true));
 }
 
+CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqIF_NoBrClearForImageWrap)
+{
+    // Given a document with a paragraph-anchored image with "none" wrap:
+    createSwDoc("image_anchored_to_paragraph_no_wrap.fodt");
+    // When exporting to reqif:
+    ExportToReqif();
+    // Make sure that there's no 'br' elements in the 'object' (used to 
represent the wrapping
+    // in HTML export, using 'clear' attribute):
+    SvMemoryStream aStream;
+    WrapReqifFromTempFile(aStream);
+    xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream);
+    CPPUNIT_ASSERT(pXmlDoc);
+    assertXPath(pXmlDoc, 
"/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p/reqif-xhtml:object");
+    assertXPath(pXmlDoc,
+                
"/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p/reqif-xhtml:object/reqif-xhtml:br",
+                0);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/html/htmlflywriter.cxx 
b/sw/source/filter/html/htmlflywriter.cxx
index b58d3d9f6c44..624d992fb273 100644
--- a/sw/source/filter/html/htmlflywriter.cxx
+++ b/sw/source/filter/html/htmlflywriter.cxx
@@ -723,68 +723,71 @@ OString SwHTMLWriter::OutFrameFormatOptions( const 
SwFrameFormat &rFrameFormat,
         sOut.setLength(0);
     }
 
-    // Insert wrap for graphics that are anchored to a paragraph as
-    // <BR CLEAR=...> in the string
-    const SwFormatSurround* pSurround;
-    if( (nFrameOpts & HtmlFrmOpts::BrClear) &&
-        ((RndStdIds::FLY_AT_PARA == rFrameFormat.GetAnchor().GetAnchorId()) ||
-         (RndStdIds::FLY_AT_CHAR == rFrameFormat.GetAnchor().GetAnchorId())) &&
-        (pSurround = rItemSet.GetItemIfSet( RES_SURROUND )) )
-    {
-        sal_Int16 eHoriOri =    rFrameFormat.GetHoriOrient().GetHoriOrient();
-        pStr = nullptr;
-        css::text::WrapTextMode eSurround = pSurround->GetSurround();
-        bool bAnchorOnly = pSurround->IsAnchorOnly();
-        switch( eHoriOri )
+    if (!mbReqIF)
+    {
+        // Insert wrap for graphics that are anchored to a paragraph as
+        // <BR CLEAR=...> in the string
+        const SwFormatSurround* pSurround;
+        if( (nFrameOpts & HtmlFrmOpts::BrClear) &&
+            ((RndStdIds::FLY_AT_PARA == 
rFrameFormat.GetAnchor().GetAnchorId()) ||
+             (RndStdIds::FLY_AT_CHAR == 
rFrameFormat.GetAnchor().GetAnchorId())) &&
+            (pSurround = rItemSet.GetItemIfSet( RES_SURROUND )) )
         {
-        case text::HoriOrientation::RIGHT:
+            sal_Int16 eHoriOri =    
rFrameFormat.GetHoriOrient().GetHoriOrient();
+            pStr = nullptr;
+            css::text::WrapTextMode eSurround = pSurround->GetSurround();
+            bool bAnchorOnly = pSurround->IsAnchorOnly();
+            switch( eHoriOri )
             {
-                switch( eSurround )
+            case text::HoriOrientation::RIGHT:
                 {
-                case css::text::WrapTextMode_NONE:
-                case css::text::WrapTextMode_RIGHT:
-                    pStr = OOO_STRING_SVTOOLS_HTML_AL_right;
-                    break;
-                case css::text::WrapTextMode_LEFT:
-                case css::text::WrapTextMode_PARALLEL:
-                    if( bAnchorOnly )
-                        m_bClearRight = true;
-                    break;
-                default:
-                    ;
+                    switch( eSurround )
+                    {
+                    case css::text::WrapTextMode_NONE:
+                    case css::text::WrapTextMode_RIGHT:
+                        pStr = OOO_STRING_SVTOOLS_HTML_AL_right;
+                        break;
+                    case css::text::WrapTextMode_LEFT:
+                    case css::text::WrapTextMode_PARALLEL:
+                        if( bAnchorOnly )
+                            m_bClearRight = true;
+                        break;
+                    default:
+                        ;
+                    }
                 }
-            }
-            break;
+                break;
 
-        default:
-            // If a frame is centered, it gets left aligned. This
-            // should be taken into account here, too.
-            {
-                switch( eSurround )
+            default:
+                // If a frame is centered, it gets left aligned. This
+                // should be taken into account here, too.
                 {
-                case css::text::WrapTextMode_NONE:
-                case css::text::WrapTextMode_LEFT:
-                    pStr = OOO_STRING_SVTOOLS_HTML_AL_left;
-                    break;
-                case css::text::WrapTextMode_RIGHT:
-                case css::text::WrapTextMode_PARALLEL:
-                    if( bAnchorOnly )
-                        m_bClearLeft = true;
-                    break;
-                default:
-                    ;
+                    switch( eSurround )
+                    {
+                    case css::text::WrapTextMode_NONE:
+                    case css::text::WrapTextMode_LEFT:
+                        pStr = OOO_STRING_SVTOOLS_HTML_AL_left;
+                        break;
+                    case css::text::WrapTextMode_RIGHT:
+                    case css::text::WrapTextMode_PARALLEL:
+                        if( bAnchorOnly )
+                            m_bClearLeft = true;
+                        break;
+                    default:
+                        ;
+                    }
                 }
-            }
-            break;
+                break;
 
-        }
+            }
 
-        if( pStr )
-        {
-            sOut.append("<" OOO_STRING_SVTOOLS_HTML_linebreak
-                    " " OOO_STRING_SVTOOLS_HTML_O_clear
-                    "=\"" + OString::Concat(pStr) + "\">");
-            sRetEndTags = sOut.makeStringAndClear();
+            if( pStr )
+            {
+                sOut.append("<" OOO_STRING_SVTOOLS_HTML_linebreak
+                        " " OOO_STRING_SVTOOLS_HTML_O_clear
+                        "=\"" + OString::Concat(pStr) + "\">");
+                sRetEndTags = sOut.makeStringAndClear();
+            }
         }
     }
     return sRetEndTags;
@@ -1034,6 +1037,9 @@ void SwHTMLWriter::writeFrameFormatOptions(HtmlWriter& 
aHtml, const SwFrameForma
         }
     }
 
+    if (mbReqIF)
+        return;
+
     // Insert wrap for graphics that are anchored to a paragraph as
     // <BR CLEAR=...> in the string
 
commit 1ec4ac1f29a900ac2c9910eaee7633147665a210
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Fri Nov 24 18:16:11 2023 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Mon Dec 11 16:56:42 2023 +0300

    Fix HtmlWriter::characters
    
    This method may be called after an end(), and then it shouldn't try
    to close a tag again. Also in this case the characters shouldn't be
    considered in the next start()/characters()/end() run.
    
    Clarify the meaning of the previous mbElementOpen, by renaming it
    to mbOpeningTagOpen. The old mbCharactersWritten flag was redundant.
    
    Change-Id: Ie0ac6ddd88be774853a1fc152742b51793af798b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159932
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/include/svtools/HtmlWriter.hxx b/include/svtools/HtmlWriter.hxx
index 21ccad0cd96d..9fe66a7d9ad2 100644
--- a/include/svtools/HtmlWriter.hxx
+++ b/include/svtools/HtmlWriter.hxx
@@ -24,8 +24,7 @@ private:
 
     SvStream& mrStream;
 
-    bool mbElementOpen;
-    bool mbCharactersWritten;
+    bool mbOpeningTagOpen = false;
     bool mbPrettyPrint;
     /// XML namespace, in case of XHTML.
     OString maNamespace;
diff --git a/svtools/qa/unit/testHtmlWriter.cxx 
b/svtools/qa/unit/testHtmlWriter.cxx
index 702bf64464ab..e4d31a2da46e 100644
--- a/svtools/qa/unit/testHtmlWriter.cxx
+++ b/svtools/qa/unit/testHtmlWriter.cxx
@@ -175,10 +175,14 @@ CPPUNIT_TEST_FIXTURE(Test, testCharacters)
     aHtml.start("abc");
     aHtml.characters("hello");
     aHtml.end();
+    aHtml.characters(" "); // Should not try to close a not opened tag
+    aHtml.start("abc");
+    aHtml.characters("world"); // Should close opening tag
+    aHtml.end();
 
     OString aString = extractFromStream(aStream);
 
-    CPPUNIT_ASSERT_EQUAL(OString("<abc>hello</abc>"), aString);
+    CPPUNIT_ASSERT_EQUAL(OString("<abc>hello</abc> <abc>world</abc>"), 
aString);
 }
 
 CPPUNIT_TEST_FIXTURE(Test, testExactElementEnd)
diff --git a/svtools/source/svhtml/HtmlWriter.cxx 
b/svtools/source/svhtml/HtmlWriter.cxx
index 8f99e3b29110..bbb63ba98051 100644
--- a/svtools/source/svhtml/HtmlWriter.cxx
+++ b/svtools/source/svhtml/HtmlWriter.cxx
@@ -15,8 +15,6 @@
 
 HtmlWriter::HtmlWriter(SvStream& rStream, std::string_view rNamespace) :
     mrStream(rStream),
-    mbElementOpen(false),
-    mbCharactersWritten(false),
     mbPrettyPrint(true)
 {
     if (!rNamespace.empty())
@@ -36,7 +34,7 @@ void HtmlWriter::prettyPrint(bool b)
 
 void HtmlWriter::start(const OString& aElement)
 {
-    if (mbElementOpen)
+    if (mbOpeningTagOpen)
     {
         mrStream.WriteChar('>');
         if (mbPrettyPrint)
@@ -54,7 +52,7 @@ void HtmlWriter::start(const OString& aElement)
 
     mrStream.WriteChar('<');
     mrStream.WriteOString(Concat2View(maNamespace + aElement));
-    mbElementOpen = true;
+    mbOpeningTagOpen = true;
 }
 
 void HtmlWriter::single(const OString &aContent)
@@ -65,12 +63,12 @@ void HtmlWriter::single(const OString &aContent)
 
 void HtmlWriter::endAttribute()
 {
-    if (mbElementOpen)
+    if (mbOpeningTagOpen)
     {
         mrStream.WriteCharPtr("/>");
         if (mbPrettyPrint)
             mrStream.WriteCharPtr("\n");
-        mbElementOpen = false;
+        mbOpeningTagOpen = false;
     }
 }
 
@@ -92,11 +90,12 @@ bool HtmlWriter::end(const OString& aElement)
 
 void HtmlWriter::end()
 {
-    if (mbElementOpen && !mbCharactersWritten)
+    if (mbOpeningTagOpen)
     {
         mrStream.WriteCharPtr("/>");
         if (mbPrettyPrint)
             mrStream.WriteCharPtr("\n");
+        mbOpeningTagOpen = false;
     }
     else
     {
@@ -114,8 +113,6 @@ void HtmlWriter::end()
             mrStream.WriteCharPtr("\n");
     }
     maElementStack.pop_back();
-    mbElementOpen = false;
-    mbCharactersWritten = false;
 }
 
 void HtmlWriter::writeAttribute(SvStream& rStream, std::string_view 
aAttribute, sal_Int32 aValue)
@@ -134,7 +131,7 @@ void HtmlWriter::writeAttribute(SvStream& rStream, 
std::string_view aAttribute,
 
 void HtmlWriter::attribute(std::string_view aAttribute, std::string_view 
aValue)
 {
-    if (mbElementOpen && !aAttribute.empty() && !aValue.empty())
+    if (mbOpeningTagOpen && !aAttribute.empty() && !aValue.empty())
     {
         mrStream.WriteChar(' ');
         writeAttribute(mrStream, aAttribute, aValue);
@@ -158,7 +155,7 @@ void HtmlWriter::attribute(std::string_view aAttribute, 
std::u16string_view aVal
 
 void HtmlWriter::attribute(std::string_view aAttribute)
 {
-    if (mbElementOpen && !aAttribute.empty())
+    if (mbOpeningTagOpen && !aAttribute.empty())
     {
         mrStream.WriteChar(' ');
         mrStream.WriteOString(aAttribute);
@@ -167,10 +164,12 @@ void HtmlWriter::attribute(std::string_view aAttribute)
 
 void HtmlWriter::characters(std::string_view rChars)
 {
-    if (!mbCharactersWritten)
+    if (mbOpeningTagOpen)
+    {
         mrStream.WriteCharPtr(">");
+        mbOpeningTagOpen = false;
+    }
     mrStream.WriteOString(rChars);
-    mbCharactersWritten = true;
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 4eed22826b1e506aec3333c7eedd96153b9fe3dc
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Tue Nov 14 11:05:05 2023 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Mon Dec 11 16:56:42 2023 +0300

    Limit PreserveSpaces HTML/ReqIF export option to proper space characters
    
    We only need to care about SPACE, TAB, LF, and CR. We don't need to care
    about LF in some cases, because it gets converted to a <br/> element, and
    handled specially. And we don't need to care about other "whitespace"
    characters, like control characters and Unicode space.
    
    Our own object placeholder characters were treated as "space", which was
    wrong.
    
    One peculiarity needs to be noted. In ReqIF case, a SPACE before LF needs
    no 'xml:space="preserve"', but an LF before SPACE needs one, because it
    needs to disambiguate between a <br> followed by a significant space vs.
    a <br> followed by a pretty-printed newline.
    
    Change-Id: I74273592df05bb94d8e4ecaea2c069c0e086b7d8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159853
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/include/svtools/parhtml.hxx b/include/svtools/parhtml.hxx
index a6a15b93e3c1..1a17e98b2997 100644
--- a/include/svtools/parhtml.hxx
+++ b/include/svtools/parhtml.hxx
@@ -189,6 +189,7 @@ protected:
 
     void SetNamespace(std::u16string_view rNamespace);
 
+    bool GetPreserveSpaces() const { return m_bPreserveSpaces; }
     void SetPreserveSpaces(bool val) { m_bPreserveSpaces = val; }
 
 public:
diff --git a/sw/qa/extras/htmlexport/data/test_no_space_preserve.fodt 
b/sw/qa/extras/htmlexport/data/test_no_space_preserve.fodt
new file mode 100644
index 000000000000..e0d9a3506e9f
--- /dev/null
+++ b/sw/qa/extras/htmlexport/data/test_no_space_preserve.fodt
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office: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.text">
+ <office:body>
+  <office:text>
+   <text:p>No special spaces</text:p>
+   <text:p><text:s/>Leading space</text:p>
+   <text:p>Trailing space </text:p>
+   <text:p>Double <text:s/>space</text:p>
+   <text:p><text:line-break/>Leading/trailing breaks<text:line-break/></text:p>
+   <text:p><text:line-break/> Leading break + space</text:p>
+   <text:p>Trailing space + break <text:line-break/></text:p>
+   <text:p>Middle<text:line-break/>break</text:p>
+   <text:p>Middle space <text:line-break/>+ break</text:p>
+   <text:p>Middle break<text:line-break/> + space</text:p>
+   <text:p>Trailing space and SVG <draw:frame text:anchor-type="as-char" 
svg:width="5.59mm" svg:height="5.59mm" draw:z-index="0"><draw:image 
draw:mime-type="image/svg+xml">
+      
<office:binary-data>PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB4bWxucz0iaHR0
+       cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDIw
+       IDIwIiBzdHJva2U9ImJsYWNrIj4KPHBhdGggZD0iTTEsMUwxOSwxOSIvPgo8L3N2Zz4=
+      </office:binary-data>
+     </draw:image>
+    </draw:frame></text:p>
+  </office:text>
+ </office:body>
+</office:document>
\ No newline at end of file
diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx 
b/sw/qa/extras/htmlexport/htmlexport.cxx
index b77005aaf496..721b72f31632 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -2824,6 +2824,153 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, 
testReqIF_PreserveSpaces)
     CPPUNIT_ASSERT_EQUAL(paraText, getParagraph(1)->getString());
 }
 
+CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testHTML_NoPreserveSpaces)
+{
+    // Test cases where "PreserveSpaces" should not introduce respective markup
+
+    const auto assertXPath_NoWhiteSpaceInStyle
+        = [this](const xmlDocUniquePtr& pDoc, const OString& rXPath) {
+              xmlXPathObjectPtr pXmlObj = getXPathNode(pDoc, rXPath);
+              xmlNodeSetPtr pXmlNodes = pXmlObj->nodesetval;
+              CPPUNIT_ASSERT_EQUAL_MESSAGE(rXPath.getStr(), 1, 
xmlXPathNodeSetGetLength(pXmlNodes));
+              xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0];
+              if (xmlChar* prop = xmlGetProp(pXmlNode, BAD_CAST("style")))
+              {
+                  OUString style = OUString::fromUtf8(reinterpret_cast<const 
char*>(prop));
+                  CPPUNIT_ASSERT_MESSAGE(rXPath.getStr(), 
style.indexOf("white-space:") < 0);
+              }
+              xmlXPathFreeObject(pXmlObj);
+          };
+    const auto assertXPath_HasWhiteSpaceInStyle
+        = [this](const xmlDocUniquePtr& pDoc, const OString& rXPath) {
+              const OUString style = getXPath(pDoc, rXPath, "style");
+              CPPUNIT_ASSERT_MESSAGE(rXPath.getStr(), 
style.indexOf("white-space: pre-wrap") >= 0);
+          };
+
+    createSwDoc("test_no_space_preserve.fodt");
+
+    // Export to plain HTML, using PreserveSpaces:
+    uno::Reference<css::frame::XStorable> xStorable(mxComponent, 
uno::UNO_QUERY_THROW);
+    css::uno::Sequence<css::beans::PropertyValue> aStoreProperties = {
+        comphelper::makePropertyValue("FilterName", OUString("HTML 
(StarWriter)")),
+        comphelper::makePropertyValue("PreserveSpaces", true),
+    };
+    xStorable->storeToURL(maTempFile.GetURL(), aStoreProperties);
+
+    htmlDocUniquePtr pHtmlDoc = parseHtml(maTempFile);
+    CPPUNIT_ASSERT(pHtmlDoc);
+
+    // No whitespace preservation, where no leading / trailing / double 
whitespace
+    assertXPath_NoWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[1]");
+    // Whitespace preserved for a leading space
+    assertXPath_HasWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[2]");
+    // Whitespace preserved for a trailing space
+    assertXPath_HasWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[3]");
+    // Whitespace preserved for a double space
+    assertXPath_HasWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[4]");
+    // No whitespace preservation for leading / trailing breaks
+    assertXPath_NoWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[5]");
+    // Whitespace preserved for a leading break + space
+    assertXPath_HasWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[6]");
+    // Whitespace preserved for a trailing space + break
+    assertXPath_HasWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[7]");
+    // No whitespace preservation for a middle break
+    assertXPath_NoWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[8]");
+    // Whitespace preserved for a middle space + break
+    assertXPath_HasWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[9]");
+    // Whitespace preserved for a middle break + space
+    assertXPath_HasWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[10]");
+    // No whitespace preservation for a trailing space and SVG
+    assertXPath_NoWhiteSpaceInStyle(pHtmlDoc, "/html/body/p[11]");
+
+    // Test import
+
+    setImportFilterName("HTML (StarWriter)");
+    UnoApiTest::load(maTempFile.GetURL());
+
+    CPPUNIT_ASSERT_EQUAL(OUString("No special spaces"), 
getParagraph(1)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString(" Leading space"), 
getParagraph(2)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("Trailing space "), 
getParagraph(3)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("Double  space"), 
getParagraph(4)->getString());
+    // Trailing break is removed in SwHTMLParser::AppendTextNode, and replaced 
with para spacing
+    CPPUNIT_ASSERT_EQUAL(OUString("\nLeading/trailing breaks"), 
getParagraph(5)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("\n Leading break + space"), 
getParagraph(6)->getString());
+    // Trailing break is removed in SwHTMLParser::AppendTextNode, and replaced 
with para spacing
+    CPPUNIT_ASSERT_EQUAL(OUString("Trailing space + break "), 
getParagraph(7)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("Middle\nbreak"), 
getParagraph(8)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("Middle space \n+ break"), 
getParagraph(9)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("Middle break\n + space"), 
getParagraph(10)->getString());
+    // The SVG is replaced by a space in SwXParagraph::getString()
+    CPPUNIT_ASSERT_EQUAL(OUString("Trailing space and SVG  "), 
getParagraph(11)->getString());
+}
+
+CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqIF_NoPreserveSpaces)
+{
+    // Test cases where "PreserveSpaces" should not introduce respective markup
+
+    createSwDoc("test_no_space_preserve.fodt");
+
+    // Export to ReqIF, using PreserveSpaces:
+    uno::Reference<css::frame::XStorable> xStorable(mxComponent, 
uno::UNO_QUERY_THROW);
+    css::uno::Sequence<css::beans::PropertyValue> aStoreProperties = {
+        comphelper::makePropertyValue("FilterName", OUString("HTML 
(StarWriter)")),
+        comphelper::makePropertyValue("FilterOptions", 
OUString("xhtmlns=reqif-xhtml")),
+        comphelper::makePropertyValue("PreserveSpaces", true),
+    };
+    xStorable->storeToURL(maTempFile.GetURL(), aStoreProperties);
+
+    SvMemoryStream aStream;
+    WrapReqifFromTempFile(aStream);
+    xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream);
+
+    // No whitespace preservation, where no leading / trailing / double 
whitespace
+    assertXPathNoAttribute(pXmlDoc, 
"/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[1]", "space");
+    // Whitespace preserved for a leading space
+    assertXPath(pXmlDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[2]", 
"space",
+                u"preserve");
+    // Whitespace preserved for a trailing space
+    assertXPath(pXmlDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[3]", 
"space",
+                u"preserve");
+    // Whitespace preserved for a double space
+    assertXPath(pXmlDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[4]", 
"space",
+                u"preserve");
+    // No whitespace preservation for leading / trailing breaks
+    assertXPathNoAttribute(pXmlDoc, 
"/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[5]", "space");
+    // Whitespace preserved for a leading break + space
+    assertXPath(pXmlDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[6]", 
"space",
+                u"preserve");
+    // No whitespace preservation for a trailing space + break
+    assertXPathNoAttribute(pXmlDoc, 
"/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[7]", "space");
+    // No whitespace preservation for a middle break
+    assertXPathNoAttribute(pXmlDoc, 
"/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[8]", "space");
+    // No whitespace preservation for a middle space + break
+    assertXPathNoAttribute(pXmlDoc, 
"/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[9]", "space");
+    // Whitespace preserved for a middle break + space
+    assertXPath(pXmlDoc, 
"/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[10]", "space",
+                u"preserve");
+    // No whitespace preservation for a trailing space and SVG
+    assertXPathNoAttribute(pXmlDoc, 
"/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[11]", "space");
+
+    // Test import
+
+    setImportFilterOptions("xhtmlns=reqif-xhtml");
+    setImportFilterName("HTML (StarWriter)");
+    UnoApiTest::load(maTempFile.GetURL());
+
+    CPPUNIT_ASSERT_EQUAL(OUString("No special spaces"), 
getParagraph(1)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString(" Leading space"), 
getParagraph(2)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("Trailing space "), 
getParagraph(3)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("Double  space"), 
getParagraph(4)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("\nLeading/trailing breaks\n"), 
getParagraph(5)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("\n Leading break + space"), 
getParagraph(6)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("Trailing space + break \n"), 
getParagraph(7)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("Middle\nbreak"), 
getParagraph(8)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("Middle space \n+ break"), 
getParagraph(9)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("Middle break\n + space"), 
getParagraph(10)->getString());
+    // The SVG is replaced by a space in SwXParagraph::getString()
+    CPPUNIT_ASSERT_EQUAL(OUString("Trailing space and SVG  "), 
getParagraph(11)->getString());
+}
+
 CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqIF_ExportFormulasAsPDF)
 {
     // Given a document with a formula:
diff --git a/sw/source/filter/html/htmlatr.cxx 
b/sw/source/filter/html/htmlatr.cxx
index e0722596d368..a99140564301 100644
--- a/sw/source/filter/html/htmlatr.cxx
+++ b/sw/source/filter/html/htmlatr.cxx
@@ -769,7 +769,7 @@ static void OutHTML_SwFormat( Writer& rWrt, const SwFormat& 
rFormat,
     if( rInfo.bInNumberBulletList && bNumberedForListItem )
     {
         HtmlWriter html(rWrt.Strm(), rHWrt.maNamespace);
-        html.prettyPrint(rHWrt.m_bPrettyPrint);
+        html.prettyPrint(rHWrt.IsPrettyPrint());
         html.start(OOO_STRING_SVTOOLS_HTML_li);
         if (!bNumbered)
         {
@@ -1011,7 +1011,7 @@ static void OutHTML_SwFormatOff( Writer& rWrt, const 
SwHTMLTextCollOutputInfo& r
 
     if( rInfo.ShouldOutputToken() )
     {
-        if (rHWrt.m_bPrettyPrint && rHWrt.IsLFPossible())
+        if (rHWrt.IsPrettyPrint() && rHWrt.IsLFPossible())
             rHWrt.OutNewLine( true );
 
         // if necessary, for BLOCKQUOTE, ADDRESS and DD another paragraph token
@@ -2006,26 +2006,70 @@ void HTMLEndPosLst::OutEndAttrs( SwHTMLWriter& rHWrt, 
sal_Int32 nPos )
     }
 }
 
-static bool NeedPreserveWhitespace(std::u16string_view str)
+static constexpr bool IsLF(sal_Unicode ch) { return ch == '\n'; }
+
+static constexpr bool IsWhitespaceExcludingLF(sal_Unicode ch)
+{
+    return ch == ' ' || ch == '\t' || ch == '\r';
+}
+
+static constexpr bool IsWhitespaceIncludingLF(sal_Unicode ch)
+{
+    return IsWhitespaceExcludingLF(ch) || IsLF(ch);
+}
+
+static bool NeedPreserveWhitespace(std::u16string_view str, bool xml)
 {
     if (str.empty())
         return false;
     // leading / trailing spaces
-    if (o3tl::internal::implIsWhitespace(str.front())
-        || o3tl::internal::implIsWhitespace(str.back()))
+    // A leading / trailing \n would turn into a leading / trailing <br/>,
+    // and will not disappear, even without space preserving option
+    if (IsWhitespaceExcludingLF(str.front()) || 
IsWhitespaceExcludingLF(str.back()))
         return true;
-    bool bWasSpace = false;
-    for (auto ch : str)
+    for (size_t i = 0; i < str.size(); ++i)
     {
-        if (o3tl::internal::implIsWhitespace(ch))
+        if (xml)
         {
-            if (bWasSpace)
-                return true; // Second whitespace in a row
-            else
-                bWasSpace = true;
+            // No need to consider \n, which convert to <br/>, when it's after 
a space
+            // (but handle it *before* a space)
+            if (IsWhitespaceIncludingLF(str[i]))
+            {
+                do
+                {
+                    ++i;
+                    if (i == str.size())
+                        return false;
+                } while (IsLF(str[i]));
+                if (IsWhitespaceExcludingLF(str[i]))
+                    return true; // Second whitespace in a row
+            }
+        }
+        else // html
+        {
+            // Only consider \n, when an adjacent space is not \n - which 
would be eaten
+            // without a space preserving option
+            if (IsWhitespaceExcludingLF(str[i]))
+            {
+                ++i;
+                if (i == str.size())
+                    return false;
+                if (IsWhitespaceIncludingLF(str[i]))
+                    return true; // Any whitespace after a non-LF whitespace
+            }
+            else if (IsLF(str[i]))
+            {
+                do
+                {
+                    ++i;
+                    if (i == str.size())
+                        return false;
+                }
+                while (IsLF(str[i]));
+                if (IsWhitespaceExcludingLF(str[i]))
+                    return true; // A non-LF whitespace after a LF
+            }
         }
-        else
-            bWasSpace = false;
     }
     return false;
 }
@@ -2062,7 +2106,7 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const 
SwContentNode& rNode )
         rHTMLWrt.SetLFPossible(true);
 
         HtmlWriter aHtml(rWrt.Strm(), rHTMLWrt.maNamespace);
-        aHtml.prettyPrint(rHTMLWrt.m_bPrettyPrint);
+        aHtml.prettyPrint(rHTMLWrt.IsPrettyPrint());
         aHtml.start(OOO_STRING_SVTOOLS_HTML_horzrule);
 
         const SfxItemSet* pItemSet = pNd->GetpSwAttrSet();
@@ -2240,7 +2284,7 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const 
SwContentNode& rNode )
     bool bOldLFPossible = rHTMLWrt.IsLFPossible();
     bool bOldSpacePreserve = rHTMLWrt.IsSpacePreserve();
     if (rHTMLWrt.IsPreserveSpacesOnWritePrefSet())
-        rHTMLWrt.SetSpacePreserve(NeedPreserveWhitespace(rStr));
+        rHTMLWrt.SetSpacePreserve(NeedPreserveWhitespace(rStr, 
rHTMLWrt.mbReqIF));
     OutHTML_SwFormat( rWrt, rFormat, pNd->GetpSwAttrSet(), aFormatInfo );
 
     // If we didn't open a new line before the paragraph tag, we do that now
@@ -2255,7 +2299,7 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const 
SwContentNode& rNode )
     // now it's a good opportunity again for an LF - if it is still allowed
     // FIXME: for LOK case we set rHTMLWrt.m_nWishLineLen as -1, for now keep 
old flow
     // when LOK side will be fixed - don't insert new line at the beginning
-    if( rHTMLWrt.IsLFPossible() && rHTMLWrt.m_bPrettyPrint && 
rHTMLWrt.m_nWishLineLen >= 0 &&
+    if( rHTMLWrt.IsLFPossible() && rHTMLWrt.IsPrettyPrint() && 
rHTMLWrt.m_nWishLineLen >= 0 &&
         rHTMLWrt.GetLineLen() >= rHTMLWrt.m_nWishLineLen )
     {
         rHTMLWrt.OutNewLine();
@@ -2494,7 +2538,7 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const 
SwContentNode& rNode )
                         nWordLen = nEnd;
                     nWordLen -= nStrPos;
 
-                    if( rHTMLWrt.m_bPrettyPrint && rHTMLWrt.m_nWishLineLen >= 
0 &&
+                    if( rHTMLWrt.IsPrettyPrint() && rHTMLWrt.m_nWishLineLen >= 
0 &&
                         (nLineLen >= rHTMLWrt.m_nWishLineLen ||
                         (nLineLen+nWordLen) >= rHTMLWrt.m_nWishLineLen ) )
                     {
@@ -2510,7 +2554,7 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const 
SwContentNode& rNode )
                     {
                         HTMLOutFuncs::FlushToAscii( rWrt.Strm() );
                         HtmlWriter aHtml(rWrt.Strm(), rHTMLWrt.maNamespace);
-                        aHtml.prettyPrint(rHTMLWrt.m_bPrettyPrint);
+                        aHtml.prettyPrint(rHTMLWrt.IsPrettyPrint());
                         aHtml.single(OOO_STRING_SVTOOLS_HTML_linebreak);
                     }
                     else if (c == CH_TXT_ATR_FORMELEMENT)
@@ -2589,7 +2633,7 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const 
SwContentNode& rNode )
         else
         {
             HtmlWriter aHtml(rHTMLWrt.Strm(), rHTMLWrt.maNamespace);
-            aHtml.prettyPrint(rHTMLWrt.m_bPrettyPrint);
+            aHtml.prettyPrint(rHTMLWrt.IsPrettyPrint());
             aHtml.single(OOO_STRING_SVTOOLS_HTML_linebreak);
             const SvxULSpaceItem& rULSpace = 
pNd->GetSwAttrSet().Get(RES_UL_SPACE);
             if (rULSpace.GetLower() > 0 && !bEndOfCell)
@@ -2616,7 +2660,7 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const 
SwContentNode& rNode )
         }
 
         HtmlWriter aHtml(rHTMLWrt.Strm(), rHTMLWrt.maNamespace);
-        aHtml.prettyPrint(rHTMLWrt.m_bPrettyPrint);
+        aHtml.prettyPrint(rHTMLWrt.IsPrettyPrint());
         aHtml.start(OOO_STRING_SVTOOLS_HTML_linebreak);
         aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_clear, pString);
         aHtml.end();
diff --git a/sw/source/filter/html/swhtml.cxx b/sw/source/filter/html/swhtml.cxx
index 14adde2590ae..40f5e1526464 100644
--- a/sw/source/filter/html/swhtml.cxx
+++ b/sw/source/filter/html/swhtml.cxx
@@ -1524,7 +1524,7 @@ void SwHTMLParser::NextToken( HtmlTokenId nToken )
     case HtmlTokenId::TEXTTOKEN:
     case HtmlTokenId::CDATA:
         // insert string without spanning attributes at the end.
-        if( !aToken.isEmpty() && ' '==aToken[0] && !IsReadPRE() )
+        if (!aToken.isEmpty() && ' ' == aToken[0] && !IsReadPRE() && 
!GetPreserveSpaces())
         {
             sal_Int32 nPos = m_pPam->GetPoint()->GetContentIndex();
             const SwTextNode* pTextNode = nPos ? 
m_pPam->GetPoint()->GetNode().GetTextNode() : nullptr;
diff --git a/sw/source/filter/html/wrthtml.cxx 
b/sw/source/filter/html/wrthtml.cxx
index 1826cee5bd14..be83b5331266 100644
--- a/sw/source/filter/html/wrthtml.cxx
+++ b/sw/source/filter/html/wrthtml.cxx
@@ -153,7 +153,6 @@ SwHTMLWriter::SwHTMLWriter( const OUString& rBaseURL, 
std::u16string_view rFilte
     , mbEmbedImages(false)
     , m_bCfgPrintLayout( false )
     , m_bParaDotLeaders( false )
-    , m_bPrettyPrint( true )
 {
     SetBaseURL(rBaseURL);
 
diff --git a/sw/source/filter/html/wrthtml.hxx 
b/sw/source/filter/html/wrthtml.hxx
index b6cb0b6bd830..423fd265063e 100644
--- a/sw/source/filter/html/wrthtml.hxx
+++ b/sw/source/filter/html/wrthtml.hxx
@@ -278,6 +278,7 @@ class SW_DLLPUBLIC SwHTMLWriter : public Writer
 
     FieldUnit m_eCSS1Unit;
 
+    bool m_bPrettyPrint = true; // Allows to add new lines to make it more 
readable
     bool m_bLFPossible = false; // a line break can be inserted
     bool m_bSpacePreserve = false; // Using xml::space="preserve", or 
"white-space: pre-wrap" style
     bool m_bPreserveSpacesOnWrite = false; // If export should use 
m_bSpacePreserve
@@ -419,7 +420,6 @@ public:
 #define sCSS2_P_CLASS_leaders "leaders"
     bool m_bCfgPrintLayout : 1;       // PrintLayout option for TOC dot leaders
     bool m_bParaDotLeaders : 1;       // for TOC dot leaders
-    bool m_bPrettyPrint : 1;          // Allows to add new lines to make it 
more readable
     // 26
 
     /// Tracks which text portion attributes are currently open: a which id -> 
open count map.
@@ -624,6 +624,7 @@ public:
     /// Determines the prefix string needed to respect the requested namespace 
alias.
     OString GetNamespace() const;
 
+    bool IsPrettyPrint() const { return !m_bSpacePreserve && m_bPrettyPrint; }
     bool IsLFPossible() const { return !m_bSpacePreserve && m_bLFPossible; }
     void SetLFPossible(bool val) { m_bLFPossible = val; }
     bool IsSpacePreserve() const { return m_bSpacePreserve; }
commit 7d87df1049103066496f7ce24051f8343e9f06a2
Author:     Szymon Kłos <szymon.k...@collabora.com>
AuthorDate: Fri Nov 19 12:38:18 2021 +0100
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Mon Dec 11 16:56:42 2023 +0300

    lok: don't pretty print html for online
    
    followup for "lok: don't limit line length in HTMLWriter"
    
    Pretty printing makes html more readable for human but introduces
    lots of new line marks which are later interpreted in the client
    as a valid new lines in the document content.
    
    This was causing multiplying the line breaks when inserting hyperlinks
    where we read current selection's content and then we pass it back
    to the core as link's content (with added new lines).
    
    This change needs cypress change to not contain "\n" at the beginning
    of some content read from the document.
    
    This also afects copying from the online document to clipboard.
    
    Change-Id: I2b17d62398d947fcf1d3fb1ed6005c3063d114f2
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136893
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Henry Castro <hcas...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141479
    Tested-by: Jenkins
    Reviewed-by: Szymon Kłos <szymon.k...@collabora.com>

diff --git a/sw/qa/extras/tiledrendering/data/multiline.odt 
b/sw/qa/extras/tiledrendering/data/multiline.odt
new file mode 100644
index 000000000000..4c60b58decb2
Binary files /dev/null and b/sw/qa/extras/tiledrendering/data/multiline.odt 
differ
diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx 
b/sw/qa/extras/tiledrendering/tiledrendering.cxx
index fa37a2e70f82..578a120465f4 100644
--- a/sw/qa/extras/tiledrendering/tiledrendering.cxx
+++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx
@@ -424,6 +424,46 @@ CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, 
testGetTextSelectionLineLimit)
     CPPUNIT_ASSERT(sHtmlText.match(sExpectedHtml, nStart));
 }
 
+CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testGetTextSelectionMultiLine)
+{
+    // Test will check if correct number of new line marks / paragraphs is 
generated
+    static OStringLiteral sOriginalText(u8"Heading\n\
+Let's have text; we need to be able to select the text inside the shape, but 
also the various individual ones too:\n\
+\n\
+\n\
+\n\
+\n\
+\n\
+And this is all for Writer shape objects\n\
+Heading on second page");
+
+    static OStringLiteral sExpectedHtml(u8"Heading</h2>\n\
+<p>Let's have text; we need to be able to select the text inside the shape, 
but also the various individual ones too:</p>\n\
+<p><br/><br/></p>\n\
+<p><br/><br/></p>\n\
+<p><br/><br/></p>\n\
+<p><br/><br/></p>\n\
+<p><br/><br/></p>\n\
+<h1 class=\"western\">And this is all for Writer shape objects</h1>\n\
+<h2 class=\"western\">Heading on second page</h2>");
+
+    SwXTextDocument* pXTextDocument = createDoc("multiline.odt");
+
+    SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell();
+    // Create a selection.
+    pWrtShell->SelAll();
+
+    OString sPlainText = 
apitest::helper::transferable::getTextSelection(pXTextDocument->getSelection(), 
"text/plain;charset=utf-8");
+
+    CPPUNIT_ASSERT_EQUAL(OString(sOriginalText), sPlainText.trim());
+
+    OString sHtmlText = 
apitest::helper::transferable::getTextSelection(pXTextDocument->getSelection(), 
"text/html");
+
+    int nStart = sHtmlText.indexOf(u8"Heading");
+
+    CPPUNIT_ASSERT(sHtmlText.match(sExpectedHtml, nStart));
+}
+
 CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testSetGraphicSelection)
 {
     SwXTextDocument* pXTextDocument = createDoc("shape.fodt");
diff --git a/sw/source/filter/html/htmlatr.cxx 
b/sw/source/filter/html/htmlatr.cxx
index 114d6de16b3a..e0722596d368 100644
--- a/sw/source/filter/html/htmlatr.cxx
+++ b/sw/source/filter/html/htmlatr.cxx
@@ -769,6 +769,7 @@ static void OutHTML_SwFormat( Writer& rWrt, const SwFormat& 
rFormat,
     if( rInfo.bInNumberBulletList && bNumberedForListItem )
     {
         HtmlWriter html(rWrt.Strm(), rHWrt.maNamespace);
+        html.prettyPrint(rHWrt.m_bPrettyPrint);
         html.start(OOO_STRING_SVTOOLS_HTML_li);
         if (!bNumbered)
         {
@@ -1010,7 +1011,7 @@ static void OutHTML_SwFormatOff( Writer& rWrt, const 
SwHTMLTextCollOutputInfo& r
 
     if( rInfo.ShouldOutputToken() )
     {
-        if (rHWrt.IsLFPossible())
+        if (rHWrt.m_bPrettyPrint && rHWrt.IsLFPossible())
             rHWrt.OutNewLine( true );
 
         // if necessary, for BLOCKQUOTE, ADDRESS and DD another paragraph token
@@ -2061,6 +2062,7 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const 
SwContentNode& rNode )
         rHTMLWrt.SetLFPossible(true);
 
         HtmlWriter aHtml(rWrt.Strm(), rHTMLWrt.maNamespace);
+        aHtml.prettyPrint(rHTMLWrt.m_bPrettyPrint);
         aHtml.start(OOO_STRING_SVTOOLS_HTML_horzrule);
 
         const SfxItemSet* pItemSet = pNd->GetpSwAttrSet();
@@ -2253,8 +2255,8 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const 
SwContentNode& rNode )
     // now it's a good opportunity again for an LF - if it is still allowed
     // FIXME: for LOK case we set rHTMLWrt.m_nWishLineLen as -1, for now keep 
old flow
     // when LOK side will be fixed - don't insert new line at the beginning
-    if( rHTMLWrt.IsLFPossible() &&
-        rHTMLWrt.GetLineLen() >= (rHTMLWrt.m_nWishLineLen >= 0 ? 
rHTMLWrt.m_nWishLineLen : 70 ) )
+    if( rHTMLWrt.IsLFPossible() && rHTMLWrt.m_bPrettyPrint && 
rHTMLWrt.m_nWishLineLen >= 0 &&
+        rHTMLWrt.GetLineLen() >= rHTMLWrt.m_nWishLineLen )
     {
         rHTMLWrt.OutNewLine();
     }
@@ -2492,7 +2494,7 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const 
SwContentNode& rNode )
                         nWordLen = nEnd;
                     nWordLen -= nStrPos;
 
-                    if( rHTMLWrt.m_nWishLineLen >= 0 &&
+                    if( rHTMLWrt.m_bPrettyPrint && rHTMLWrt.m_nWishLineLen >= 
0 &&
                         (nLineLen >= rHTMLWrt.m_nWishLineLen ||
                         (nLineLen+nWordLen) >= rHTMLWrt.m_nWishLineLen ) )
                     {
@@ -2508,6 +2510,7 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const 
SwContentNode& rNode )
                     {
                         HTMLOutFuncs::FlushToAscii( rWrt.Strm() );
                         HtmlWriter aHtml(rWrt.Strm(), rHTMLWrt.maNamespace);
+                        aHtml.prettyPrint(rHTMLWrt.m_bPrettyPrint);
                         aHtml.single(OOO_STRING_SVTOOLS_HTML_linebreak);
                     }
                     else if (c == CH_TXT_ATR_FORMELEMENT)
@@ -2586,6 +2589,7 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const 
SwContentNode& rNode )
         else
         {
             HtmlWriter aHtml(rHTMLWrt.Strm(), rHTMLWrt.maNamespace);
+            aHtml.prettyPrint(rHTMLWrt.m_bPrettyPrint);
             aHtml.single(OOO_STRING_SVTOOLS_HTML_linebreak);
             const SvxULSpaceItem& rULSpace = 
pNd->GetSwAttrSet().Get(RES_UL_SPACE);
             if (rULSpace.GetLower() > 0 && !bEndOfCell)
@@ -2612,6 +2616,7 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const 
SwContentNode& rNode )
         }
 
         HtmlWriter aHtml(rHTMLWrt.Strm(), rHTMLWrt.maNamespace);
+        aHtml.prettyPrint(rHTMLWrt.m_bPrettyPrint);
         aHtml.start(OOO_STRING_SVTOOLS_HTML_linebreak);
         aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_clear, pString);
         aHtml.end();
diff --git a/sw/source/filter/html/wrthtml.cxx 
b/sw/source/filter/html/wrthtml.cxx
index 48c6f8718665..1826cee5bd14 100644
--- a/sw/source/filter/html/wrthtml.cxx
+++ b/sw/source/filter/html/wrthtml.cxx
@@ -153,6 +153,7 @@ SwHTMLWriter::SwHTMLWriter( const OUString& rBaseURL, 
std::u16string_view rFilte
     , mbEmbedImages(false)
     , m_bCfgPrintLayout( false )
     , m_bParaDotLeaders( false )
+    , m_bPrettyPrint( true )
 {
     SetBaseURL(rBaseURL);
 
@@ -227,6 +228,12 @@ void SwHTMLWriter::SetupFilterOptions(std::u16string_view 
rFilterOptions)
         aStoreMap["NoLineLimit"] <<= true;
     }
 
+    // this option can be "on" together with any of above
+    if (rFilterOptions.find(u"NoPrettyPrint") != std::u16string_view::npos)
+    {
+        aStoreMap["NoPrettyPrint"] <<= true;
+    }
+
     const uno::Sequence<OUString> aOptionSeq
         = comphelper::string::convertCommaSeparated(rFilterOptions);
     static const OUStringLiteral aXhtmlNsKey(u"xhtmlns=");
@@ -291,6 +298,14 @@ void SwHTMLWriter::SetupFilterFromPropertyValues(
         mbSkipHeaderFooter = bVal;
     }
 
+    // this option can be "on" together with any of above
+    it = aStoreMap.find("NoPrettyPrint");
+    if (it != aStoreMap.end())
+    {
+        m_nWishLineLen = -1;
+        m_bPrettyPrint = false;
+    }
+
     it = aStoreMap.find("EmbedImages");
     if (it != aStoreMap.end())
     {
diff --git a/sw/source/filter/html/wrthtml.hxx 
b/sw/source/filter/html/wrthtml.hxx
index 721c901d379b..b6cb0b6bd830 100644
--- a/sw/source/filter/html/wrthtml.hxx
+++ b/sw/source/filter/html/wrthtml.hxx
@@ -419,7 +419,8 @@ public:
 #define sCSS2_P_CLASS_leaders "leaders"
     bool m_bCfgPrintLayout : 1;       // PrintLayout option for TOC dot leaders
     bool m_bParaDotLeaders : 1;       // for TOC dot leaders
-    // 25
+    bool m_bPrettyPrint : 1;          // Allows to add new lines to make it 
more readable
+    // 26
 
     /// Tracks which text portion attributes are currently open: a which id -> 
open count map.
     std::map<sal_uInt16, int> maStartedAttributes;
diff --git a/sw/source/uibase/dochdl/swdtflvr.cxx 
b/sw/source/uibase/dochdl/swdtflvr.cxx
index 3d8fe6b821f6..6c747df13c3f 100644
--- a/sw/source/uibase/dochdl/swdtflvr.cxx
+++ b/sw/source/uibase/dochdl/swdtflvr.cxx
@@ -782,7 +782,7 @@ bool SwTransferable::WriteObject( 
tools::SvRef<SotTempStream>& xStream,
     case SWTRANSFER_OBJECTTYPE_HTML:
     {
         // LOK is interested in getting images embedded for copy/paste support.
-        GetHTMLWriter( comphelper::LibreOfficeKit::isActive() ? 
OUString("EmbedImages;NoLineLimit") : OUString(), OUString(), xWrt );
+        GetHTMLWriter( comphelper::LibreOfficeKit::isActive() ? 
OUString("EmbedImages;NoPrettyPrint") : OUString(), OUString(), xWrt );
         break;
     }
 
commit 8a03d9a35ab5ae8d34151a57fc2eca2a7d9a082a
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Mon Nov 13 07:22:09 2023 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Mon Dec 11 16:56:42 2023 +0300

    --disable-curl builds: split WebDAV-related JunitTests to fix checks
    
    Change-Id: I0a46dc226e141eb585817fff4871f8d1681a3f3b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159352
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/ucb/JunitTest_ucb_webdav_unoapi.mk 
b/ucb/JunitTest_ucb_webdav_unoapi.mk
new file mode 100644
index 000000000000..2675922a3cea
--- /dev/null
+++ b/ucb/JunitTest_ucb_webdav_unoapi.mk
@@ -0,0 +1,14 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_JunitTest_JunitTest,ucb_webdav_unoapi))
+
+$(eval $(call gb_JunitTest_set_unoapi_test_defaults,ucb_webdav_unoapi))
+
+# vim: set noet sw=4 ts=4:
diff --git a/ucb/Module_ucb.mk b/ucb/Module_ucb.mk
index 7bbcc925e28d..023863ba936a 100644
--- a/ucb/Module_ucb.mk
+++ b/ucb/Module_ucb.mk
@@ -42,6 +42,7 @@ endif
 $(eval $(call gb_Module_add_subsequentcheck_targets,ucb,\
        JunitTest_ucb_complex \
        JunitTest_ucb_unoapi \
+       $(if $(WITH_WEBDAV),JunitTest_ucb_webdav_unoapi) \
 ))
 
 # vim: set noet sw=4 ts=4:
diff --git a/ucb/qa/unoapi/ucb.sce b/ucb/qa/unoapi/ucb.sce
index 0c798cfdedab..00aa7de2a8b7 100644
--- a/ucb/qa/unoapi/ucb.sce
+++ b/ucb/qa/unoapi/ucb.sce
@@ -18,9 +18,7 @@
 -o ucb.UcbContentProviderProxyFactory
 -o ucb.UcbPropertiesManager
 -o ucb.UcbStore
--o ucb.UniversalContentBroker
 -o ucpchelp.CHelpContentProvider
--o ucpdav.WebDAVContentProvider
 -o ucpfile.FileProvider
 -o ucpftp.FTPContentProvider
 -o ucphier.HierarchyContentProvider
diff --git a/ucb/qa/unoapi/ucb_webdav.sce b/ucb/qa/unoapi/ucb_webdav.sce
new file mode 100644
index 000000000000..4ce463cc0bec
--- /dev/null
+++ b/ucb/qa/unoapi/ucb_webdav.sce
@@ -0,0 +1,19 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements. See the NOTICE file distributed
+#   with this work for additional information regarding copyright
+#   ownership. The ASF licenses this file to you under the Apache
+#   License, Version 2.0 (the "License"); you may not use this file
+#   except in compliance with the License. You may obtain a copy of
+#   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+-o ucb.UniversalContentBroker
+-o ucpdav.WebDAVContentProvider
commit dd85decbd40b18c009f67dba3956b0bc03a61946
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Fri Nov 10 21:10:11 2023 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Mon Dec 11 16:56:42 2023 +0300

    Fix packaging with --enable-mpl-subset
    
    Change-Id: I1cae9e9a9837df968663b6f46bd1e0d369377126
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159308
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/RepositoryExternal.mk b/RepositoryExternal.mk
index 9abad8667cfb..0a8d63493463 100644
--- a/RepositoryExternal.mk
+++ b/RepositoryExternal.mk
@@ -3044,9 +3044,10 @@ endef
 else # !SYSTEM_POSTGRESQL
 
 ifeq ($(OS),WNT)
+$(if $(MPL_SUBSET),,\
 $(eval $(call gb_Helper_register_packages_for_install,postgresqlsdbc,\
        postgresql \
-))
+)))
 endif # WNT
 
 define gb_LinkTarget__use_postgresql
commit 2f45c92aa8cb58bb42c9c9ce8c603f1727a19443
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Fri Nov 10 21:09:11 2023 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Mon Dec 11 16:56:42 2023 +0300

    Fix packaging with --disable-curl
    
    Change-Id: I9c3c1f1953c4d59c5a2d4c6017e73768d93a7bc7
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159307
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/Repository.mk b/Repository.mk
index 56d8b2d28b84..2375470218a9 100644
--- a/Repository.mk
+++ b/Repository.mk
@@ -368,7 +368,7 @@ endif
 
 $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,ooo, \
     avmedia \
-       LanguageTool \
+       $(if $(ENABLE_CURL),LanguageTool) \
     $(call gb_Helper_optional,AVMEDIA, \
        $(if $(filter MACOSX,$(OS)),\
                avmediaMacAVF \
@@ -671,7 +671,7 @@ $(eval $(call 
gb_Helper_register_libraries_for_install,PLAINLIBS_OOO,ooo, \
        ucbhelper \
        $(if $(WITH_WEBDAV),ucpdav1) \
        ucpfile1 \
-       ucpftp1 \
+       $(if $(ENABLE_CURL),ucpftp1) \
     $(call gb_Helper_optional,XMLHELP,ucpchelp1) \
        ucphier1 \
        ucppkg1 \
diff --git a/RepositoryExternal.mk b/RepositoryExternal.mk
index 92ea4ba17670..9abad8667cfb 100644
--- a/RepositoryExternal.mk
+++ b/RepositoryExternal.mk
@@ -2724,9 +2724,10 @@ endef
 
 else # !SYSTEM_CURL
 
+$(if $(ENABLE_CURL),\
 $(eval $(call gb_Helper_register_packages_for_install,ooo,\
        curl \
-))
+)))
 
 define gb_LinkTarget__use_curl
 $(call gb_LinkTarget_use_package,$(1),curl)
commit aa034136dd86024ec6df63594d1323ea96652e6d
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Mon Oct 30 17:14:47 2023 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Mon Dec 11 16:56:41 2023 +0300

    ReqIF: introduce ExportFormulasAsPDF HTML export filter option
    
    Change-Id: Id400bd5571d0a192d854620abe83d862e0512434
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158663
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/sw/qa/extras/htmlexport/data/embedded_formula.fodt 
b/sw/qa/extras/htmlexport/data/embedded_formula.fodt
new file mode 100644
index 000000000000..46e5391223c0
--- /dev/null
+++ b/sw/qa/extras/htmlexport/data/embedded_formula.fodt
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office: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.text">
+ <office:body>
+  <office:text>
+   <text:p>Formula:</text:p>
+   <text:p><draw:frame draw:name="Formula1" text:anchor-type="as-char" 
svg:width="1.549cm" svg:height="0.531cm"><draw:object>
+      <math xmlns="http://www.w3.org/1998/Math/MathML"; display="block">
+       <semantics>
+        <mrow>
+         <msup>
+          <mi mathvariant="normal">e</mi>
+          <mrow>
+           <mi>i</mi>
+           <mi>π</mi>
+          </mrow>
+         </msup>
+         <mo stretchy="false">+</mo>
+         <mn>1</mn>
+         <mo stretchy="false">=</mo>
+         <mn>0</mn>
+        </mrow>
+        <annotation encoding="StarMath 5.0">{ func e ^ { i %pi } + 1 } = 
0</annotation>
+       </semantics>
+      </math>
+     </draw:object>
+    </draw:frame></text:p>
+  </office:text>
+ </office:body>
+</office:document>
\ No newline at end of file
diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx 
b/sw/qa/extras/htmlexport/htmlexport.cxx
index f7ff19ce533b..b77005aaf496 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -13,6 +13,7 @@
 #include <string_view>
 
 #include <com/sun/star/document/XEmbeddedObjectSupplier2.hpp>
+#include <com/sun/star/document/XTypeDetection.hpp>
 #include <com/sun/star/embed/ElementModes.hpp>
 #include <com/sun/star/io/XActiveDataStreamer.hpp>
 #include <com/sun/star/io/XSeekable.hpp>
@@ -265,9 +266,10 @@ public:
     {
     }
 
+    OUString GetObjectPath(const OUString& ext);
     /// Get the .ole path, assuming maTempFile is an XHTML export result.
-    OUString GetOlePath();
-    OUString GetPngPath();
+    OUString GetOlePath() { return GetObjectPath(".ole"); }
+    OUString GetPngPath() { return GetObjectPath(".png"); }
     /// Parse the ole1 data out of an RTF fragment URL.
     void ParseOle1FromRtfUrl(const OUString& rRtfUrl, SvMemoryStream& rOle1);
     /// Export using the C++ HTML export filter, with xhtmlns=reqif-xhtml.
@@ -276,35 +278,19 @@ public:
     void ImportFromReqif(const OUString& rUrl);
 };
 
-OUString SwHtmlDomExportTest::GetOlePath()
+OUString SwHtmlDomExportTest::GetObjectPath(const OUString& ext)
 {
+    assert(ext.startsWith("."));
     SvMemoryStream aStream;
     WrapReqifFromTempFile(aStream);
     xmlDocUniquePtr pDoc = parseXmlStream(&aStream);
     CPPUNIT_ASSERT(pDoc);
     OUString aOlePath = getXPath(
         pDoc, 
"/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p/reqif-xhtml:object", "data");
-    OUString aOleSuffix(".ole");
-    CPPUNIT_ASSERT(aOlePath.endsWith(aOleSuffix));
+    CPPUNIT_ASSERT(aOlePath.endsWith(ext));
     INetURLObject aUrl(maTempFile.GetURL());
-    aUrl.setBase(aOlePath.subView(0, aOlePath.getLength() - 
aOleSuffix.getLength()));
-    aUrl.setExtension(u"ole");
-    return aUrl.GetMainURL(INetURLObject::DecodeMechanism::NONE);
-}
-
-OUString SwHtmlDomExportTest::GetPngPath()
-{
-    SvMemoryStream aStream;
-    WrapReqifFromTempFile(aStream);
-    xmlDocUniquePtr pDoc = parseXmlStream(&aStream);
-    CPPUNIT_ASSERT(pDoc);
-    OUString aPngPath = getXPath(
-        pDoc, 
"/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p/reqif-xhtml:object", "data");
-    OUString aPngSuffix(".png");
-    CPPUNIT_ASSERT(aPngPath.endsWith(aPngSuffix));
-    INetURLObject aUrl(maTempFile.GetURL());
-    aUrl.setBase(aPngPath.subView(0, aPngPath.getLength() - 
aPngSuffix.getLength()));
-    aUrl.setExtension(u"png");
+    aUrl.setBase(aOlePath.subView(0, aOlePath.getLength() - ext.getLength()));
+    aUrl.setExtension(ext.subView(1));
     return aUrl.GetMainURL(INetURLObject::DecodeMechanism::NONE);
 }
 
@@ -2838,6 +2824,40 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, 
testReqIF_PreserveSpaces)
     CPPUNIT_ASSERT_EQUAL(paraText, getParagraph(1)->getString());
 }
 
+CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqIF_ExportFormulasAsPDF)
+{
+    // Given a document with a formula:
+    createSwDoc("embedded_formula.fodt");
+
+    // When exporting to reqif with ExportFormulasAsPDF=true:
+    uno::Reference<frame::XStorable> xStorable(mxComponent, 
uno::UNO_QUERY_THROW);
+    uno::Sequence<beans::PropertyValue> aStoreProperties = {
+        comphelper::makePropertyValue("FilterName", OUString("HTML 
(StarWriter)")),
+        comphelper::makePropertyValue("FilterOptions", 
OUString("xhtmlns=reqif-xhtml")),
+        comphelper::makePropertyValue("ExportFormulasAsPDF", true),
+    };
+    xStorable->storeToURL(maTempFile.GetURL(), aStoreProperties);
+
+    // Make sure that the formula is exported as PDF:
+    SvMemoryStream aStream;
+    WrapReqifFromTempFile(aStream);
+    xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream);
+    assertXPath(pXmlDoc, 
"/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p[2]/reqif-xhtml:object",
+                "type", "application/pdf");
+
+    css::uno::Sequence<css::beans::PropertyValue> descr{
+        comphelper::makePropertyValue("URL", GetObjectPath(".pdf")),
+    };
+
+    uno::Reference<lang::XMultiServiceFactory> xFactory(
+        comphelper::getProcessComponentContext()->getServiceManager(), 
uno::UNO_QUERY_THROW);
+    uno::Reference<document::XTypeDetection> xTypeDetection(
+        xFactory->createInstance("com.sun.star.document.TypeDetection"), 
uno::UNO_QUERY_THROW);
+
+    CPPUNIT_ASSERT_EQUAL(OUString("pdf_Portable_Document_Format"),
+                         xTypeDetection->queryTypeByDescriptor(descr, true));
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/html/htmlplug.cxx 
b/sw/source/filter/html/htmlplug.cxx
index c606ae326fe4..af25c54528e8 100644
--- a/sw/source/filter/html/htmlplug.cxx
+++ b/sw/source/filter/html/htmlplug.cxx
@@ -1483,6 +1483,119 @@ Writer& OutHTML_FrameFormatOLENode( Writer& rWrt, const 
SwFrameFormat& rFrameFor
     return rWrt;
 }
 
+static void OutHTMLGraphic(SwHTMLWriter& rWrt, const SwFrameFormat& 
rFrameFormat, SwOLENode* pOLENd,
+                           const Graphic& rGraphic, bool bObjectOpened, bool 
bInCntnr)
+{
+    OUString aGraphicURL;
+    OUString aMimeType;
+    if (!rWrt.mbEmbedImages)
+    {
+        const OUString* pTempFileName = rWrt.GetOrigFileName();
+        if (pTempFileName)
+            aGraphicURL = *pTempFileName;
+
+        OUString aFilterName("JPG");
+        XOutFlags nFlags = XOutFlags::UseGifIfPossible | 
XOutFlags::UseNativeIfPossible;
+
+        if (bObjectOpened)
+        {
+            aFilterName = "PNG";
+            nFlags = XOutFlags::NONE;
+            aMimeType = "image/png";
+
+            if (rGraphic.GetType() == GraphicType::NONE)
+            {
+                // The OLE Object has no replacement image, write a stub.
+                aGraphicURL = lcl_CalculateFileName(rWrt.GetOrigFileName(), 
rGraphic, u"png");
+                osl::File aFile(aGraphicURL);
+                aFile.open(osl_File_OpenFlag_Create);
+                aFile.close();
+            }
+        }
+
+        ErrCode nErr = XOutBitmap::WriteGraphic(rGraphic, aGraphicURL, 
aFilterName, nFlags);
+        if (nErr) // error, don't write anything
+        {
+            rWrt.m_nWarn = WARN_SWG_POOR_LOAD;
+            if (bObjectOpened) // Still at least close the tag.
+                rWrt.Strm().WriteOString(
+                    Concat2View("</" + rWrt.GetNamespace() + 
OOO_STRING_SVTOOLS_HTML_object ">"));
+            return;
+        }
+        aGraphicURL = 
URIHelper::SmartRel2Abs(INetURLObject(rWrt.GetBaseURL()), aGraphicURL,
+                                              URIHelper::GetMaybeFileHdl());
+    }
+    HtmlFrmOpts nFlags = bInCntnr ? HtmlFrmOpts::GenImgAllMask : 
HtmlFrmOpts::GenImgMask;
+    if (bObjectOpened)
+        nFlags |= HtmlFrmOpts::Replacement;
+    HtmlWriter aHtml(rWrt.Strm(), rWrt.maNamespace);
+    OutHTML_ImageStart(aHtml, rWrt, rFrameFormat, aGraphicURL, rGraphic, 
pOLENd->GetTitle(),
+                       pOLENd->GetTwipSize(), nFlags, "ole", nullptr, 
aMimeType);
+    OutHTML_ImageEnd(aHtml, rWrt);
+}
+
+static void OutHTMLStartObject(SwHTMLWriter& rWrt, const OUString& rFileName, 
const OUString& rFileType)
+{
+    OUString aFileName = 
URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(), rFileName);
+
+    if (rWrt.IsLFPossible())
+        rWrt.OutNewLine();
+    rWrt.Strm().WriteOString(
+        Concat2View("<" + rWrt.GetNamespace() + 
OOO_STRING_SVTOOLS_HTML_object));
+    rWrt.Strm().WriteOString(Concat2View(" data=\"" + aFileName.toUtf8() + 
"\""));
+    if (!rFileType.isEmpty())
+        rWrt.Strm().WriteOString(Concat2View(" type=\"" + rFileType.toUtf8() + 
"\""));
+    rWrt.Strm().WriteOString(">");
+    rWrt.SetLFPossible(true);
+}
+
+static void OutHTMLEndObject(SwHTMLWriter& rWrt)
+{
+    rWrt.Strm().WriteOString(
+        Concat2View("</" + rWrt.GetNamespace() + 
OOO_STRING_SVTOOLS_HTML_object ">"));
+}
+
+static bool TrySaveFormulaAsPDF(SwHTMLWriter& rWrt, const SwFrameFormat& 
rFrameFormat,
+                                SwOLENode* pOLENd, bool 
bWriteReplacementGraphic, bool bInCntnr)
+{
+    if (!rWrt.mbReqIF)
+        return false;
+    if (!rWrt.m_bExportFormulasAsPDF)
+        return false;
+
+    auto xTextContent = SwXTextEmbeddedObject::CreateXTextEmbeddedObject(
+        *rWrt.m_pDoc, const_cast<SwFrameFormat*>(&rFrameFormat));
+    uno::Reference<frame::XStorable> 
xStorable(xTextContent->getEmbeddedObject(), uno::UNO_QUERY);
+    uno::Reference<lang::XServiceInfo> xServiceInfo(xStorable, uno::UNO_QUERY);
+    if (!xServiceInfo)
+        return false;
+    if 
(!xServiceInfo->supportsService("com.sun.star.formula.FormulaProperties"))
+        return false;
+
+    Graphic aGraphic(xTextContent->getReplacementGraphic());
+    OUString aFileName = lcl_CalculateFileName(rWrt.GetOrigFileName(), 
aGraphic, u"pdf");
+
+    utl::MediaDescriptor aDescr;
+    aDescr["FilterName"] <<= OUString("math_pdf_Export");
+    // Properties from starmath/inc/unomodel.hxx
+    aDescr["FilterData"] <<= comphelper::InitPropertySequence({
+        { u"TitleRow", css::uno::Any(false) },
+        { u"FormulaText", css::uno::Any(false) },
+        { u"Border", css::uno::Any(false) },
+        { u"PrintFormat", css::uno::Any(sal_Int32(1)) }, // PRINT_SIZE_SCALED
+    });
+    xStorable->storeToURL(aFileName, aDescr.getAsConstPropertyValueList());
+
+    OutHTMLStartObject(rWrt, aFileName, "application/pdf");
+
+    if (bWriteReplacementGraphic)
+        OutHTMLGraphic(rWrt, rFrameFormat, pOLENd, aGraphic, true, bInCntnr);
+
+    OutHTMLEndObject(rWrt);
+
+    return true;
+}
+
 Writer& OutHTML_FrameFormatOLENodeGrf( Writer& rWrt, const SwFrameFormat& 
rFrameFormat,
                                   bool bInCntnr, bool bWriteReplacementGraphic 
)
 {
@@ -1543,6 +1656,9 @@ Writer& OutHTML_FrameFormatOLENodeGrf( Writer& rWrt, 
const SwFrameFormat& rFrame
         return rWrt;
     }
 
+    if (TrySaveFormulaAsPDF(rHTMLWrt, rFrameFormat, pOLENd, 
bWriteReplacementGraphic, bInCntnr))
+        return rWrt;
+
     if ( !pOLENd->GetGraphic() )
     {
         SAL_WARN("sw.html", "Unexpected missing OLE fallback graphic");
@@ -1640,80 +1756,18 @@ Writer& OutHTML_FrameFormatOLENodeGrf( Writer& rWrt, 
const SwFrameFormat& rFrame
                 aFileType = aRTFType;
             }
         }
-        aFileName = URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(), 
aFileName);
 
         // Refer to this data.
-        if (rHTMLWrt.IsLFPossible())
-            rHTMLWrt.OutNewLine();
-        rWrt.Strm().WriteOString(Concat2View("<" + rHTMLWrt.GetNamespace() + 
OOO_STRING_SVTOOLS_HTML_object));
-        rWrt.Strm().WriteOString(Concat2View(" data=\"" + aFileName.toUtf8() + 
"\""));
-        if (!aFileType.isEmpty())
-            rWrt.Strm().WriteOString(Concat2View(" type=\"" + 
aFileType.toUtf8() + "\""));
-        rWrt.Strm().WriteOString(">");
+        OutHTMLStartObject(rHTMLWrt, aFileName, aFileType);
         bObjectOpened = true;
-        rHTMLWrt.SetLFPossible(true);
     }
 
     if (!bObjectOpened || bWriteReplacementGraphic)
-    {
-        OUString aGraphicURL;
-        OUString aMimeType;
-        if(!rHTMLWrt.mbEmbedImages)
-        {
-            const OUString* pTempFileName = rHTMLWrt.GetOrigFileName();
-            if(pTempFileName)
-                aGraphicURL = *pTempFileName;
-
-            OUString aFilterName("JPG");
-            XOutFlags nFlags = XOutFlags::UseGifIfPossible | 
XOutFlags::UseNativeIfPossible;
-
-            if (bObjectOpened)
-            {
-                aFilterName = "PNG";
-                nFlags = XOutFlags::NONE;
-                aMimeType = "image/png";
-
-                if (aGraphic.GetType() == GraphicType::NONE)
-                {
-                    // The OLE Object has no replacement image, write a stub.
-                    aGraphicURL = 
lcl_CalculateFileName(rHTMLWrt.GetOrigFileName(), aGraphic, u"png");
-                    osl::File aFile(aGraphicURL);
-                    aFile.open(osl_File_OpenFlag_Create);
-                    aFile.close();
-                }
-            }
-
-            ErrCode nErr = XOutBitmap::WriteGraphic( aGraphic, aGraphicURL,
-                                        aFilterName,
-                                        nFlags );
-            if( nErr )              // error, don't write anything
-            {
-                rHTMLWrt.m_nWarn = WARN_SWG_POOR_LOAD;
-                if (bObjectOpened) // Still at least close the tag.
-                    rWrt.Strm().WriteOString(Concat2View("</" + 
rHTMLWrt.GetNamespace()
-                        + OOO_STRING_SVTOOLS_HTML_object ">"));
-                return rWrt;
-            }
-            aGraphicURL = URIHelper::SmartRel2Abs(
-                INetURLObject(rWrt.GetBaseURL()), aGraphicURL,
-                URIHelper::GetMaybeFileHdl() );
-
-        }
-        HtmlFrmOpts nFlags = bInCntnr ? HtmlFrmOpts::GenImgAllMask
-            : HtmlFrmOpts::GenImgMask;
-        if (bObjectOpened)
-            nFlags |= HtmlFrmOpts::Replacement;
-        HtmlWriter aHtml(rWrt.Strm(), rHTMLWrt.maNamespace);
-        OutHTML_ImageStart( aHtml, rWrt, rFrameFormat, aGraphicURL, aGraphic,
-                pOLENd->GetTitle(), pOLENd->GetTwipSize(),
-                nFlags, "ole", nullptr, aMimeType );
-        OutHTML_ImageEnd(aHtml, rWrt);
-    }
+        OutHTMLGraphic(rHTMLWrt, rFrameFormat, pOLENd, aGraphic, 
bObjectOpened, bInCntnr);
 
     if (bObjectOpened)
         // Close native data.
-        rWrt.Strm().WriteOString(Concat2View("</" + rHTMLWrt.GetNamespace() + 
OOO_STRING_SVTOOLS_HTML_object
-                                 ">"));
+        OutHTMLEndObject(rHTMLWrt);
 
     return rWrt;
 }
diff --git a/sw/source/filter/html/wrthtml.cxx 
b/sw/source/filter/html/wrthtml.cxx
index 03879eb42ff0..48c6f8718665 100644
--- a/sw/source/filter/html/wrthtml.cxx
+++ b/sw/source/filter/html/wrthtml.cxx
@@ -261,6 +261,12 @@ void SwHTMLWriter::SetupFilterFromPropertyValues(
         it->second >>= m_bExportImagesAsOLE;
     }
 
+    it = aStoreMap.find("ExportFormulasAsPDF");
+    if (it != aStoreMap.end())
+    {
+        it->second >>= m_bExportFormulasAsPDF;
+    }
+
     it = aStoreMap.find("ShapeDPI");
     if (it != aStoreMap.end())
     {
diff --git a/sw/source/filter/html/wrthtml.hxx 
b/sw/source/filter/html/wrthtml.hxx
index f8f5a111e6eb..721c901d379b 100644
--- a/sw/source/filter/html/wrthtml.hxx
+++ b/sw/source/filter/html/wrthtml.hxx
@@ -429,6 +429,9 @@ public:
     /// ReqIF mode: export images as OLE objects.
     bool m_bExportImagesAsOLE = false;
 
+    /// ReqIF mode: export formulas as PDFs.
+    bool m_bExportFormulasAsPDF = false;
+
     /// DPI used when exporting a vector shape as a bitmap.
     std::optional<sal_Int32> m_nShapeDPI;
 
commit 3fd1b0455475ca1f35eabe3dedc3db3301d67404
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Mon Oct 30 08:41:54 2023 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Mon Dec 11 16:56:41 2023 +0300

    Allow passing Math-specific options to PDF export
    
    The options present in the Math' Print dialog:
    * Contents:
      - Title;
      - Formula text;
      - Borders;
    * Size:
      - Original size;
      - Fit to page;
      - Scaling N%
    
    were previously not handled in math_pdf_Export. This change makes
    them handled, similar to handling of other modules' options.
    
    The final handling of them happens in SmDocShell::Impl_Print.
    
      TitleRow (boolean; default = true)
      FormulaText (boolean; default = true)
      Border (boolean; default = true)
      PrintFormat (long: 0 - original size; 1 - fit to page; 2 - scaling to 
PrintScale; default = 0)
      PrintScale (unsigned short; default = 100)
    
    They are also available in command line, as implemented in commit
    0c3b8792b712e939d2ad524d554f96616b4844be (PDF export: allow setting
    filter data keys from the cmdline, 2022-01-24), using JSON syntax.
    
    TODO: make these options available in Math' PDF export dialog.
    Change-Id: I4fcc609e943823a5325a4840988a96c9d5ab3223
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158637
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/filter/source/pdf/pdfexport.cxx b/filter/source/pdf/pdfexport.cxx
index b886aa5d0f43..768ff382a111 100644
--- a/filter/source/pdf/pdfexport.cxx
+++ b/filter/source/pdf/pdfexport.cxx
@@ -451,7 +451,11 @@ bool PDFExport::Export( const OUString& rFile, const 
Sequence< PropertyValue >&
             OUString aOpenPassword, aPermissionPassword;
             Reference< beans::XMaterialHolder > xEnc;
             Sequence< beans::NamedValue > aPreparedPermissionPassword;
-
+            std::optional<PropertyValue> oMathTitleRow;
+            std::optional<PropertyValue> oMathFormulaText;
+            std::optional<PropertyValue> oMathBorder;
+            std::optional<PropertyValue> oMathPrintFormat;
+            std::optional<PropertyValue> oMathPrintScale;
 
             // getting the string for the creator
             OUString aCreator;
@@ -659,6 +663,17 @@ bool PDFExport::Export( const OUString& rFile, const 
Sequence< PropertyValue >&
                 // Redaction & bitmap related stuff
                 else if ( rProp.Name == "IsRedactMode" )
                     rProp.Value >>= mbIsRedactMode;
+                // Math-specific render options
+                else if (rProp.Name == "TitleRow")
+                    oMathTitleRow = rProp;
+                else if (rProp.Name == "FormulaText")
+                    oMathFormulaText = rProp;
+                else if (rProp.Name == "Border")
+                    oMathBorder = rProp;
+                else if (rProp.Name == "PrintFormat")
+                    oMathPrintFormat = rProp;
+                else if (rProp.Name == "PrintScale")
+                    oMathPrintScale = rProp;
             }
 
             if (!maSignCertificate.is() && 
!aSignCertificateSubjectName.isEmpty())
@@ -958,7 +973,7 @@ bool PDFExport::Export( const OUString& rFile, const 
Sequence< PropertyValue >&
                 aPDFExtOutDevData.SetIsReduceImageResolution( 
mbReduceImageResolution );
                 aPDFExtOutDevData.SetIsExportNamedDestinations( 
mbExportBmkToDest );
 
-                Sequence< PropertyValue > aRenderOptions{
+                std::vector<PropertyValue> aRenderOptionsVector{
                     comphelper::makePropertyValue("RenderDevice", 
uno::Reference<awt::XDevice>(xDevice)),
                     comphelper::makePropertyValue("ExportNotesPages", false),
                     comphelper::makePropertyValue("IsFirstPage", true),
@@ -969,6 +984,17 @@ bool PDFExport::Export( const OUString& rFile, const 
Sequence< PropertyValue >&
                     comphelper::makePropertyValue("SinglePageSheets", 
mbSinglePageSheets),
                     comphelper::makePropertyValue("ExportNotesInMargin", 
mbExportNotesInMargin)
                 };
+                if (oMathTitleRow)
+                    aRenderOptionsVector.push_back(*oMathTitleRow);
+                if (oMathFormulaText)
+                    aRenderOptionsVector.push_back(*oMathFormulaText);
+                if (oMathBorder)
+                    aRenderOptionsVector.push_back(*oMathBorder);
+                if (oMathPrintFormat)
+                    aRenderOptionsVector.push_back(*oMathPrintFormat);
+                if (oMathPrintScale)
+                    aRenderOptionsVector.push_back(*oMathPrintScale);
+                Sequence aRenderOptions = 
comphelper::containerToSequence(aRenderOptionsVector);
                 Any& rExportNotesValue = aRenderOptions.getArray()[ 1 ].Value;
 
                 if( !aPageRange.isEmpty() || !aSelection.hasValue() )
commit 0bc1e8700fb014817498c7d5fe31857dce23a684
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sun Oct 29 16:36:43 2023 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Mon Dec 11 16:56:41 2023 +0300

    tdf#157965: UNO methods are expected to return sizes in mm/100
    
    Commit 9e92a17cb6e03beedeeca40bfc8524c2623d31eb made sm to always
    use twips; before, it used mm/100 except in LOK. That change broke
    the size values returned from XRenderable::getRenderer: instead of
    mm/100, the resulting values were in twips, but handled as mm/100.
    
    Set the printer's map mode to use mm/100s explicitly. Also use
    mm/100s in the call to SvxPaperInfo::GetDefaultPaperSize.
    
    Change-Id: Id7cf40d4bc19c92dc54ca03d81f25ba1f6bf25b9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158622
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/starmath/source/unomodel.cxx b/starmath/source/unomodel.cxx
index f31d01debcc1..582d8f358760 100644
--- a/starmath/source/unomodel.cxx
+++ b/starmath/source/unomodel.cxx
@@ -912,12 +912,16 @@ uno::Sequence< beans::PropertyValue > SAL_CALL 
SmModel::getRenderer(
     SmPrinterAccess aPrinterAccess( *pDocSh );
     Size aPrtPaperSize;
     if (Printer *pPrinter = aPrinterAccess.GetPrinter())
+    {
+        // tdf#157965: UNO methods are expected to return sizes in mm/100
+        pPrinter->SetMapMode(MapMode(MapUnit::Map100thMM)); // reset in 
SmPrinterAccess dtor
         aPrtPaperSize = pPrinter->GetPaperSize();
+    }
 
     // if paper size is 0 (usually if no 'real' printer is found),
     // guess the paper size
     if (aPrtPaperSize.IsEmpty())
-        aPrtPaperSize = SvxPaperInfo::GetDefaultPaperSize(SmMapUnit());
+        aPrtPaperSize = SvxPaperInfo::GetDefaultPaperSize(MapUnit::Map100thMM);
     awt::Size   aPageSize( aPrtPaperSize.Width(), aPrtPaperSize.Height() );
 
     uno::Sequence< beans::PropertyValue > aRenderer(1);
commit 1dbb9ebe761fd760bcc9e472abc6a857ecad3487
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sun Oct 29 14:48:48 2023 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Mon Dec 11 16:56:41 2023 +0300

    Drop pointless print format limitation of PDF export
    
    PRINT_SIZE_NORMAL is the default, so will be used anyway, when export
    doesn't provide an explicit value. Preventing an explicitly provided
    value is wrong.
    
    Change-Id: I4781f429741f3882cc9c716839763ccddfc07652
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158619
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/starmath/source/document.cxx b/starmath/source/document.cxx
index 60d63821e5ef..4e01ea30ded6 100644
--- a/starmath/source/document.cxx
+++ b/starmath/source/document.cxx
@@ -1484,9 +1484,6 @@ void SmDocShell::Impl_Print(OutputDevice& rOutDev, const 
SmPrintUIOptions& rPrin
     Size aSize(GetSize());
 
     MapMode OutputMapMode;
-    // PDF export should always use PRINT_SIZE_NORMAL ...
-    if (!rPrintUIOptions.getBoolValue("IsPrinter"))
-        ePrintSize = PRINT_SIZE_NORMAL;
     switch (ePrintSize)
     {
         case PRINT_SIZE_NORMAL:
commit a39371f43ba395778067edd6e2b1e76685d2687c
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sun Oct 29 14:45:01 2023 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Mon Dec 11 16:56:41 2023 +0300

    Only decrase zoom on fit-to-page printout when printing frame
    
    Change-Id: I51466924823bc574acfed6cff9fbd1bc4c77931b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158618
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/starmath/source/document.cxx b/starmath/source/document.cxx
index 8c84c0ffab82..60d63821e5ef 100644
--- a/starmath/source/document.cxx
+++ b/starmath/source/document.cxx
@@ -1499,7 +1499,7 @@ void SmDocShell::Impl_Print(OutputDevice& rOutDev, const 
SmPrintUIOptions& rPrin
                 sal_uInt16 nZ
                     = std::min(o3tl::convert(aOutRect.GetWidth(), 100, 
aSize.Width()),
                                o3tl::convert(aOutRect.GetHeight(), 100, 
aSize.Height()));
-                if (nZ > MINZOOM)
+                if (bIsPrintFrame && nZ > MINZOOM)
                     nZ -= 10;
                 Fraction aFraction(std::clamp(nZ, MINZOOM, MAXZOOM), 100);
 
commit 7ffeb38cfc98af7aeb3e1a25c2d3e023d62c32d3
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sun Oct 29 14:59:47 2023 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Mon Dec 11 16:56:41 2023 +0300

    Drop some intermediate conversions to pixel
    
    Should improve independence of results from resolution. Some output
    devices are not even pixel-based (e.g., PDF output).
    
    Change-Id: Id4359bfa0d7ba76ac4e4694c3ae4f042a780cd53
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158620
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/starmath/source/document.cxx b/starmath/source/document.cxx
index fa60a53ad85e..8c84c0ffab82 100644
--- a/starmath/source/document.cxx
+++ b/starmath/source/document.cxx
@@ -1496,11 +1496,9 @@ void SmDocShell::Impl_Print(OutputDevice& rOutDev, const 
SmPrintUIOptions& rPrin
         case PRINT_SIZE_SCALED:
             if (!aSize.IsEmpty())
             {
-                Size OutputSize(rOutDev.LogicToPixel(aOutRect.GetSize(), 
MapMode(SmMapUnit())));
-                Size GraphicSize(rOutDev.LogicToPixel(aSize, 
MapMode(SmMapUnit())));
                 sal_uInt16 nZ
-                    = std::min(o3tl::convert(OutputSize.Width(), 100, 
GraphicSize.Width()),
-                               o3tl::convert(OutputSize.Height(), 100, 
GraphicSize.Height()));
+                    = std::min(o3tl::convert(aOutRect.GetWidth(), 100, 
aSize.Width()),
+                               o3tl::convert(aOutRect.GetHeight(), 100, 
aSize.Height()));
                 if (nZ > MINZOOM)
                     nZ -= 10;
                 Fraction aFraction(std::clamp(nZ, MINZOOM, MAXZOOM), 100);
@@ -1520,14 +1518,13 @@ void SmDocShell::Impl_Print(OutputDevice& rOutDev, 
const SmPrintUIOptions& rPrin
         }
     }
 
-    aSize = rOutDev.PixelToLogic(rOutDev.LogicToPixel(aSize, OutputMapMode), 
MapMode(SmMapUnit()));
+    aSize = OutputDevice::LogicToLogic(aSize, OutputMapMode, 
MapMode(SmMapUnit()));
 
     Point aPos(aOutRect.Left() + (aOutRect.GetWidth() - aSize.Width()) / 2,
                aOutRect.Top() + (aOutRect.GetHeight() - aSize.Height()) / 2);
 
-    aPos = rOutDev.PixelToLogic(rOutDev.LogicToPixel(aPos, 
MapMode(SmMapUnit())), OutputMapMode);
-    aOutRect
-        = rOutDev.PixelToLogic(rOutDev.LogicToPixel(aOutRect, 
MapMode(SmMapUnit())), OutputMapMode);
+    aPos = OutputDevice::LogicToLogic(aPos, MapMode(SmMapUnit()), 
OutputMapMode);
+    aOutRect = OutputDevice::LogicToLogic(aOutRect, MapMode(SmMapUnit()), 
OutputMapMode);
 
     rOutDev.SetMapMode(OutputMapMode);
     rOutDev.SetClipRegion(vcl::Region(aOutRect));
commit 77887e1662f6da9c62b7c464b4f5d42929cda4a2
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sun Oct 29 16:45:53 2023 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Mon Dec 11 16:56:41 2023 +0300

    Subtraction could wrap
    
    Change-Id: Ifc248835a70ee593e47d50bb0e1bf9165eb06391
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158623
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/starmath/inc/view.hxx b/starmath/inc/view.hxx
index b55edc1715c5..9a98d6d17476 100644
--- a/starmath/inc/view.hxx
+++ b/starmath/inc/view.hxx
@@ -37,8 +37,8 @@ class SmPrintUIOptions;
 class SmGraphicAccessible;
 class SmGraphicWidget;
 
-#define MINZOOM sal_uInt16(25)
-#define MAXZOOM sal_uInt16(800)
+constexpr sal_uInt16 MINZOOM = 25;
+constexpr sal_uInt16 MAXZOOM = 800;
 
 class SmGraphicWindow final : public InterimItemWindow
 {
diff --git a/starmath/source/document.cxx b/starmath/source/document.cxx
index 3c7ac048b3eb..fa60a53ad85e 100644
--- a/starmath/source/document.cxx
+++ b/starmath/source/document.cxx
@@ -1501,7 +1501,8 @@ void SmDocShell::Impl_Print(OutputDevice& rOutDev, const 
SmPrintUIOptions& rPrin
                 sal_uInt16 nZ
                     = std::min(o3tl::convert(OutputSize.Width(), 100, 
GraphicSize.Width()),
                                o3tl::convert(OutputSize.Height(), 100, 
GraphicSize.Height()));
-                nZ -= 10;
+                if (nZ > MINZOOM)
+                    nZ -= 10;
                 Fraction aFraction(std::clamp(nZ, MINZOOM, MAXZOOM), 100);
 
                 OutputMapMode = MapMode(SmMapUnit(), Point(), aFraction, 
aFraction);
commit e180042ec08f52f1e84d072b99f2ae3bb5079db4
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sun Oct 29 14:57:03 2023 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Mon Dec 11 16:56:41 2023 +0300

    tdf#157966: fix "Fit to page" printing option
    
    Regression after commit bf4bbc3c2174b21577b8878bc3197923ba44a029
    (replace std::max(std::min()) with std::clamp, 2020-11-16).
    
    Change-Id: Iada43ba352cbfb5ea597c72c871b47beb2d766c9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158617
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/starmath/source/document.cxx b/starmath/source/document.cxx
index 7d59f68f691d..3c7ac048b3eb 100644
--- a/starmath/source/document.cxx
+++ b/starmath/source/document.cxx
@@ -1502,7 +1502,7 @@ void SmDocShell::Impl_Print(OutputDevice& rOutDev, const 
SmPrintUIOptions& rPrin
                     = std::min(o3tl::convert(OutputSize.Width(), 100, 
GraphicSize.Width()),
                                o3tl::convert(OutputSize.Height(), 100, 
GraphicSize.Height()));
                 nZ -= 10;
-                Fraction aFraction(std::clamp(nZ, MINZOOM, sal_uInt16(100)), 
1);
+                Fraction aFraction(std::clamp(nZ, MINZOOM, MAXZOOM), 100);
 
                 OutputMapMode = MapMode(SmMapUnit(), Point(), aFraction, 
aFraction);
             }
commit f1963e88d787b4f762b5c4a40ccc3b3da7703a75
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sat Oct 28 20:23:00 2023 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Mon Dec 11 16:56:41 2023 +0300

    Move Impl_Print from SmViewShell to SmDocShell
    
    All functionality is in the latter, anyway. This move allows
    to exclude dependency on existing views from SmModel::render.
    
    Change-Id: I3dff855b7f25089439c8afc57904a25a48fd127b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158594
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/starmath/inc/document.hxx b/starmath/inc/document.hxx
index 214d9a9ce558..6ad7161ec96d 100644
--- a/starmath/inc/document.hxx
+++ b/starmath/inc/document.hxx
@@ -61,6 +61,7 @@ inline constexpr OUStringLiteral MATHML_XML = u"MathML XML 
(Math)";
 class SmDocShell;
 class EditEngine;
 class SmEditEngine;
+class SmPrintUIOptions;
 
 class SmPrinterAccess
 {
@@ -221,6 +222,9 @@ public:
         mathml::SmMlIteratorFree(m_pMlElementTree);
         m_pMlElementTree = pMlElementTree;
     }
+
+    void Impl_Print(OutputDevice& rOutDev, const SmPrintUIOptions& 
rPrintUIOptions,
+                    tools::Rectangle aOutRect);
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/starmath/inc/view.hxx b/starmath/inc/view.hxx
index 41e28a44c3df..b55edc1715c5 100644
--- a/starmath/inc/view.hxx
+++ b/starmath/inc/view.hxx
@@ -37,6 +37,9 @@ class SmPrintUIOptions;
 class SmGraphicAccessible;
 class SmGraphicWidget;
 
+#define MINZOOM sal_uInt16(25)
+#define MAXZOOM sal_uInt16(800)
+
 class SmGraphicWindow final : public InterimItemWindow
 {
 private:
@@ -258,19 +261,6 @@ class SmViewShell final : public SfxViewShell
     DECL_LINK( DialogClosedHdl, sfx2::FileDialogHelper*, void );
     virtual void            Notify( SfxBroadcaster& rBC, const SfxHint& rHint 
) override;
 
-    static Size GetTextLineSize(OutputDevice const & rDevice,
-                         const OUString& rLine);
-    static Size GetTextSize(OutputDevice const & rDevice,
-                     std::u16string_view rText,
-                     tools::Long          MaxWidth);
-    static void DrawTextLine(OutputDevice& rDevice,
-                      const Point&  rPosition,
-                      const OUString& rLine);
-    static void DrawText(OutputDevice& rDevice,
-                  const Point&  rPosition,
-                  std::u16string_view rText,
-                  sal_uInt16        MaxWidth);
-
     virtual SfxPrinter *GetPrinter(bool bCreate = false) override;
     virtual sal_uInt16 SetPrinter(SfxPrinter *pNewPrinter,
                               SfxPrinterChangeFlags nDiffFlags = 
SFX_PRINTER_ALL) override;
@@ -334,9 +324,6 @@ public:
     void Execute( SfxRequest& rReq );
     void GetState(SfxItemSet &);
 
-    void Impl_Print( OutputDevice &rOutDev, const SmPrintUIOptions 
&rPrintUIOptions,
-            tools::Rectangle aOutRect );
-
     /** Set bInsertIntoEditWindow so we know where to insert
      *
      * This method is called whenever SmGraphicWidget or SmEditWindow gets 
focus,
diff --git a/starmath/source/document.cxx b/starmath/source/document.cxx
index 0593d26c268c..7d59f68f691d 100644
--- a/starmath/source/document.cxx
+++ b/starmath/source/document.cxx
@@ -24,6 +24,7 @@
 
 #include <comphelper/fileformat.h>
 #include <comphelper/accessibletexthelper.hxx>
+#include <comphelper/string.hxx>
 #include <rtl/ustrbuf.hxx>
 #include <rtl/ustring.hxx>
 #include <sal/log.hxx>
@@ -1222,4 +1223,317 @@ bool SmDocShell::WriteAsMathType3( SfxMedium& rMedium )
     return aEquation.ConvertFromStarMath( rMedium );
 }
 
+static Size GetTextLineSize(OutputDevice const& rDevice, const OUString& rLine)
+{
+    Size aSize(rDevice.GetTextWidth(rLine), rDevice.GetTextHeight());
+    const tools::Long nTabPos = rLine.isEmpty() ? 0 : 
rDevice.approximate_digit_width() * 8;
+
+    if (nTabPos)
+    {
+        aSize.setWidth(0);
+        sal_Int32 nPos = 0;
+        do
+        {
+            if (nPos > 0)
+                aSize.setWidth(((aSize.Width() / nTabPos) + 1) * nTabPos);
+
+            const OUString aText = rLine.getToken(0, '\t', nPos);
+            aSize.AdjustWidth(rDevice.GetTextWidth(aText));
+        } while (nPos >= 0);
+    }
+
+    return aSize;
+}
+
+static Size GetTextSize(OutputDevice const& rDevice, std::u16string_view rText,
+                        tools::Long MaxWidth)
+{
+    Size aSize;
+    Size aTextSize;
+    if (rText.empty())
+        return aTextSize;
+
+    sal_Int32 nPos = 0;
+    do
+    {
+        OUString aLine(o3tl::getToken(rText, 0, '\n', nPos));
+        aLine = aLine.replaceAll("\r", "");
+
+        aSize = GetTextLineSize(rDevice, aLine);
+
+        if (aSize.Width() > MaxWidth)
+        {
+            do
+            {
+                OUString aText;
+                sal_Int32 m = aLine.getLength();
+                sal_Int32 nLen = m;
+
+                for (sal_Int32 n = 0; n < nLen; n++)
+                {
+                    sal_Unicode cLineChar = aLine[n];
+                    if ((cLineChar == ' ') || (cLineChar == '\t'))
+                    {
+                        aText = aLine.copy(0, n);
+                        if (GetTextLineSize(rDevice, aText).Width() < MaxWidth)
+                            m = n;
+                        else
+                            break;
+                    }
+                }
+
+                aText = aLine.copy(0, m);
+                aLine = aLine.replaceAt(0, m, u"");
+                aSize = GetTextLineSize(rDevice, aText);
+                aTextSize.AdjustHeight(aSize.Height());
+                aTextSize.setWidth(std::clamp(aSize.Width(), 
aTextSize.Width(), MaxWidth));
+
+                aLine = comphelper::string::stripStart(aLine, ' ');
+                aLine = comphelper::string::stripStart(aLine, '\t');
+                aLine = comphelper::string::stripStart(aLine, ' ');
+            } while (!aLine.isEmpty());
+        }
+        else
+        {
+            aTextSize.AdjustHeight(aSize.Height());
+            aTextSize.setWidth(std::max(aTextSize.Width(), aSize.Width()));
+        }
+    } while (nPos >= 0);
+
+    return aTextSize;
+}
+
+static void DrawTextLine(OutputDevice& rDevice, const Point& rPosition, const 
OUString& rLine)
+{
+    Point aPoint(rPosition);
+    const tools::Long nTabPos = rLine.isEmpty() ? 0 : 
rDevice.approximate_digit_width() * 8;
+
+    if (nTabPos)
+    {
+        sal_Int32 nPos = 0;
+        do
+        {
+            if (nPos > 0)
+                aPoint.setX(((aPoint.X() / nTabPos) + 1) * nTabPos);
+
+            OUString aText = rLine.getToken(0, '\t', nPos);
+            rDevice.DrawText(aPoint, aText);
+            aPoint.AdjustX(rDevice.GetTextWidth(aText));
+        } while (nPos >= 0);
+    }
+    else
+        rDevice.DrawText(aPoint, rLine);
+}
+
+static void DrawText(OutputDevice& rDevice, const Point& rPosition, 
std::u16string_view rText,
+                     sal_uInt16 MaxWidth)
+{
+    if (rText.empty())
+        return;
+
+    Point aPoint(rPosition);
+    Size aSize;
+
+    sal_Int32 nPos = 0;
+    do
+    {
+        OUString aLine(o3tl::getToken(rText, 0, '\n', nPos));
+        aLine = aLine.replaceAll("\r", "");
+        aSize = GetTextLineSize(rDevice, aLine);
+        if (aSize.Width() > MaxWidth)
+        {
+            do
+            {
+                OUString aText;
+                sal_Int32 m = aLine.getLength();
+                sal_Int32 nLen = m;
+
+                for (sal_Int32 n = 0; n < nLen; n++)
+                {
+                    sal_Unicode cLineChar = aLine[n];
+                    if ((cLineChar == ' ') || (cLineChar == '\t'))
+                    {
+                        aText = aLine.copy(0, n);
+                        if (GetTextLineSize(rDevice, aText).Width() < MaxWidth)
+                            m = n;
+                        else
+                            break;
+                    }
+                }
+                aText = aLine.copy(0, m);
+                aLine = aLine.replaceAt(0, m, u"");
+
+                DrawTextLine(rDevice, aPoint, aText);
+                aPoint.AdjustY(aSize.Height());
+
+                aLine = comphelper::string::stripStart(aLine, ' ');
+                aLine = comphelper::string::stripStart(aLine, '\t');
+                aLine = comphelper::string::stripStart(aLine, ' ');
+            } while (GetTextLineSize(rDevice, aLine).Width() > MaxWidth);
+
+            // print the remaining text
+            if (!aLine.isEmpty())
+            {
+                DrawTextLine(rDevice, aPoint, aLine);
+                aPoint.AdjustY(aSize.Height());
+            }
+        }
+        else
+        {
+            DrawTextLine(rDevice, aPoint, aLine);
+            aPoint.AdjustY(aSize.Height());
+        }
+    } while (nPos >= 0);
+}
+
+void SmDocShell::Impl_Print(OutputDevice& rOutDev, const SmPrintUIOptions& 
rPrintUIOptions,
+                tools::Rectangle aOutRect)
+{
+    const bool bIsPrintTitle = 
rPrintUIOptions.getBoolValue(PRTUIOPT_TITLE_ROW, true);
+    const bool bIsPrintFrame = rPrintUIOptions.getBoolValue(PRTUIOPT_BORDER, 
true);
+    const bool bIsPrintFormulaText = 
rPrintUIOptions.getBoolValue(PRTUIOPT_FORMULA_TEXT, true);
+    SmPrintSize ePrintSize(static_cast<SmPrintSize>(
+        rPrintUIOptions.getIntValue(PRTUIOPT_PRINT_FORMAT, 
PRINT_SIZE_NORMAL)));
+    const sal_uInt16 nZoomFactor
+        = 
static_cast<sal_uInt16>(rPrintUIOptions.getIntValue(PRTUIOPT_PRINT_SCALE, 100));
+
+    rOutDev.Push();
+    rOutDev.SetLineColor(COL_BLACK);
+
+    // output text on top
+    if (bIsPrintTitle)
+    {
+        Size aSize600(0, 600);
+        Size aSize650(0, 650);
+        vcl::Font aFont(FAMILY_DONTKNOW, aSize600);
+
+        aFont.SetAlignment(ALIGN_TOP);
+        aFont.SetWeight(WEIGHT_BOLD);
+        aFont.SetFontSize(aSize650);
+        aFont.SetColor(COL_BLACK);
+        rOutDev.SetFont(aFont);
+
+        Size aTitleSize(GetTextSize(rOutDev, GetTitle(), aOutRect.GetWidth() - 
200));
+
+        aFont.SetWeight(WEIGHT_NORMAL);
+        aFont.SetFontSize(aSize600);
+        rOutDev.SetFont(aFont);
+
+        Size aDescSize(GetTextSize(rOutDev, GetComment(), aOutRect.GetWidth() 
- 200));
+
+        if (bIsPrintFrame)
+            rOutDev.DrawRect(tools::Rectangle(
+                aOutRect.TopLeft(), Size(aOutRect.GetWidth(), 100 + 
aTitleSize.Height() + 200
+                                                                  + 
aDescSize.Height() + 100)));
+        aOutRect.AdjustTop(200);
+
+        // output title
+        aFont.SetWeight(WEIGHT_BOLD);
+        aFont.SetFontSize(aSize650);
+        rOutDev.SetFont(aFont);
+        Point aPoint(aOutRect.Left() + (aOutRect.GetWidth() - 
aTitleSize.Width()) / 2,
+                     aOutRect.Top());
+        DrawText(rOutDev, aPoint, GetTitle(),
+                 sal::static_int_cast<sal_uInt16>(aOutRect.GetWidth() - 200));
+        aOutRect.AdjustTop(aTitleSize.Height() + 200);
+
+        // output description
+        aFont.SetWeight(WEIGHT_NORMAL);
+        aFont.SetFontSize(aSize600);
+        rOutDev.SetFont(aFont);
+        aPoint.setX(aOutRect.Left() + (aOutRect.GetWidth() - 
aDescSize.Width()) / 2);
+        aPoint.setY(aOutRect.Top());
+        DrawText(rOutDev, aPoint, GetComment(),
+                 sal::static_int_cast<sal_uInt16>(aOutRect.GetWidth() - 200));
+        aOutRect.AdjustTop(aDescSize.Height() + 300);
+    }
+
+    // output text on bottom
+    if (bIsPrintFormulaText)
+    {
+        vcl::Font aFont(FAMILY_DONTKNOW, Size(0, 600));
+        aFont.SetAlignment(ALIGN_TOP);
+        aFont.SetColor(COL_BLACK);
+
+        // get size
+        rOutDev.SetFont(aFont);
+
+        Size aSize(GetTextSize(rOutDev, GetText(), aOutRect.GetWidth() - 200));
+
+        aOutRect.AdjustBottom(-(aSize.Height() + 600));
+
+        if (bIsPrintFrame)
+            rOutDev.DrawRect(tools::Rectangle(
+                aOutRect.BottomLeft(), Size(aOutRect.GetWidth(), 200 + 
aSize.Height() + 200)));
+
+        Point aPoint(aOutRect.Left() + (aOutRect.GetWidth() - aSize.Width()) / 
2,
+                     aOutRect.Bottom() + 300);
+        DrawText(rOutDev, aPoint, GetText(),
+                 sal::static_int_cast<sal_uInt16>(aOutRect.GetWidth() - 200));
+        aOutRect.AdjustBottom(-200);
+    }
+
+    if (bIsPrintFrame)
+        rOutDev.DrawRect(aOutRect);
+
+    aOutRect.AdjustTop(100);
+    aOutRect.AdjustLeft(100);
+    aOutRect.AdjustBottom(-100);
+    aOutRect.AdjustRight(-100);
+
+    Size aSize(GetSize());
+
+    MapMode OutputMapMode;
+    // PDF export should always use PRINT_SIZE_NORMAL ...
+    if (!rPrintUIOptions.getBoolValue("IsPrinter"))
+        ePrintSize = PRINT_SIZE_NORMAL;
+    switch (ePrintSize)
+    {
+        case PRINT_SIZE_NORMAL:
+            OutputMapMode = MapMode(SmMapUnit());
+            break;
+
+        case PRINT_SIZE_SCALED:
+            if (!aSize.IsEmpty())
+            {
+                Size OutputSize(rOutDev.LogicToPixel(aOutRect.GetSize(), 
MapMode(SmMapUnit())));
+                Size GraphicSize(rOutDev.LogicToPixel(aSize, 
MapMode(SmMapUnit())));
+                sal_uInt16 nZ
+                    = std::min(o3tl::convert(OutputSize.Width(), 100, 
GraphicSize.Width()),
+                               o3tl::convert(OutputSize.Height(), 100, 
GraphicSize.Height()));
+                nZ -= 10;
+                Fraction aFraction(std::clamp(nZ, MINZOOM, sal_uInt16(100)), 
1);
+
+                OutputMapMode = MapMode(SmMapUnit(), Point(), aFraction, 
aFraction);
+            }
+            else
+                OutputMapMode = MapMode(SmMapUnit());
+            break;
+
+        case PRINT_SIZE_ZOOMED:
+        {
+            Fraction aFraction(nZoomFactor, 100);
+
+            OutputMapMode = MapMode(SmMapUnit(), Point(), aFraction, 
aFraction);
+            break;
+        }
+    }
+
+    aSize = rOutDev.PixelToLogic(rOutDev.LogicToPixel(aSize, OutputMapMode), 
MapMode(SmMapUnit()));
+
+    Point aPos(aOutRect.Left() + (aOutRect.GetWidth() - aSize.Width()) / 2,
+               aOutRect.Top() + (aOutRect.GetHeight() - aSize.Height()) / 2);
+
+    aPos = rOutDev.PixelToLogic(rOutDev.LogicToPixel(aPos, 
MapMode(SmMapUnit())), OutputMapMode);
+    aOutRect
+        = rOutDev.PixelToLogic(rOutDev.LogicToPixel(aOutRect, 
MapMode(SmMapUnit())), OutputMapMode);
+
+    rOutDev.SetMapMode(OutputMapMode);
+    rOutDev.SetClipRegion(vcl::Region(aOutRect));
+    DrawFormula(rOutDev, aPos);
+    rOutDev.SetClipRegion();
+
+    rOutDev.Pop();
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/starmath/source/unomodel.cxx b/starmath/source/unomodel.cxx
index 89796c27e04f..f31d01debcc1 100644
--- a/starmath/source/unomodel.cxx
+++ b/starmath/source/unomodel.cxx
@@ -970,17 +970,6 @@ void SAL_CALL SmModel::render(
     if (xModel != pDocSh->GetModel())
         return;
 
-    //!! when called via API we may not have an active view
-    //!! thus we go and look for a view that can be used.
-    SfxViewShell* pViewSh = SfxViewShell::GetFirst( false /* search 
non-visible views as well*/, checkSfxViewShell<SmViewShell> );
-    while (pViewSh && pViewSh->GetObjectShell() != pDocSh)

... etc. - the rest is truncated

Reply via email to