filter/source/pdf/pdfexport.cxx                    |   30 +
 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 ---------------------
 sw/qa/extras/htmlexport/data/embedded_formula.fodt |   30 +
 sw/qa/extras/htmlexport/htmlexport.cxx             |   66 ++--
 sw/source/filter/html/htmlplug.cxx                 |  184 +++++++-----
 sw/source/filter/html/wrthtml.cxx                  |    6 
 sw/source/filter/html/wrthtml.hxx                  |    3 
 11 files changed, 563 insertions(+), 442 deletions(-)

New commits:
commit cc539b1c2f3db9f868ad1c3b4292c8454ac5a79d
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Mon Oct 30 17:14:47 2023 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Tue Oct 31 12:00:47 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 7c74a27161ee..6b8de215d27c 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);
 }
 
@@ -2830,6 +2816,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 c4131e1af4f9..31722b3ed47f 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 9af110d9243309d6260699e51b046a281dc24fc4
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 Oct 30 23:34:46 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 338463f184f8..cc9e56983d7f 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())
@@ -950,7 +965,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),
@@ -961,6 +976,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 bda2daf7d955e540ee9dca379dbc4e5499d50840
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 Oct 30 23:33:17 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 2e6f3d2983ec6b44334acfc07c14286afe400269
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 Oct 30 23:10:42 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 c93aa5da1b1d..6bf52577f643 100644
--- a/starmath/source/document.cxx
+++ b/starmath/source/document.cxx
@@ -1486,9 +1486,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 3b50aa6b3d251c7ce63e550d1476879e1c2d1de3
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 Oct 30 22:49:15 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 4c65fec0b6fa..c93aa5da1b1d 100644
--- a/starmath/source/document.cxx
+++ b/starmath/source/document.cxx
@@ -1501,7 +1501,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 f96ba9e4e10a030b5e8abceafdc0a4c209534595
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 Oct 30 22:46:50 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 7d2847f9d8f6..4c65fec0b6fa 100644
--- a/starmath/source/document.cxx
+++ b/starmath/source/document.cxx
@@ -1498,11 +1498,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);
@@ -1522,14 +1520,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 c084cc8ec2a768b517a817276826849793932d37
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 Oct 30 22:44:36 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 eae45ed3630b..7d2847f9d8f6 100644
--- a/starmath/source/document.cxx
+++ b/starmath/source/document.cxx
@@ -1503,7 +1503,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 ac4995ced8e5bf0366ddffaff89cadf6e0284e36
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 Oct 30 22:42:31 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 a5d294f74fe8..eae45ed3630b 100644
--- a/starmath/source/document.cxx
+++ b/starmath/source/document.cxx
@@ -1504,7 +1504,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 7ce30a52ee7c68ee452eaa0d92b1b6cd2612b3ab
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 Oct 30 22:41:29 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 e7c5dee90c4d..a5d294f74fe8 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>
@@ -1224,4 +1225,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)
-        pViewSh = SfxViewShell::GetNext( *pViewSh, false /* search non-visible 
views as well*/, checkSfxViewShell<SmViewShell> );
-    SmViewShell *pView = dynamic_cast< SmViewShell *>( pViewSh );
-    SAL_WARN_IF( !pView, "starmath", "SmModel::render : no SmViewShell found" 
);
-
-    if (!pView)
-        return;
-
     SmPrinterAccess aPrinterAccess( *pDocSh );
 
     Size aPrtPaperSize;
@@ -1024,7 +1013,7 @@ void SAL_CALL SmModel::render(
         m_pPrintUIOptions.reset(new SmPrintUIOptions);
     m_pPrintUIOptions->processProperties( rxOptions );
 
-    pView->Impl_Print( *pOut, *m_pPrintUIOptions, OutputRect );
+    pDocSh->Impl_Print(*pOut, *m_pPrintUIOptions, OutputRect);
 
     // release SmPrintUIOptions when everything is done.
     // That way, when SmPrintUIOptions is needed again it will read the latest 
configuration settings in its c-tor.
diff --git a/starmath/source/view.cxx b/starmath/source/view.cxx
index bdc8b0729335..29db2fc3c45a 100644
--- a/starmath/source/view.cxx
+++ b/starmath/source/view.cxx
@@ -89,9 +89,6 @@
 #include <ElementsDockingWindow.hxx>
 #include <helpids.h>
 
-#define MINZOOM sal_uInt16(25)
-#define MAXZOOM sal_uInt16(800)
-
 // space around the edit window, in pixels
 // fdo#69111: Increased border on the top so that the window is
 // easier to tear off.
@@ -1192,320 +1189,6 @@ void SmViewShell::SetZoomFactor( const Fraction &rX, 
const Fraction &rY )
     SfxViewShell::SetZoomFactor( rX, rY );
 }
 
-Size SmViewShell::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;
-}
-
-Size SmViewShell::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;
-}
-
-void SmViewShell::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);
-}
-
-void SmViewShell::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 SmViewShell::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, GetDoc()->GetTitle(), 
aOutRect.GetWidth() - 200));
-
-        aFont.SetWeight(WEIGHT_NORMAL);
-        aFont.SetFontSize(aSize600);
-        rOutDev.SetFont(aFont);
-
-        Size aDescSize (GetTextSize(rOutDev, GetDoc()->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, GetDoc()->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, GetDoc()->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, GetDoc()->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, GetDoc()->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 (GetDoc()->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));
-    GetDoc()->DrawFormula(rOutDev, aPos);
-    rOutDev.SetClipRegion();
-
-    rOutDev.Pop();
-}
-
 SfxPrinter* SmViewShell::GetPrinter(bool bCreate)
 {
     SmDocShell* pDoc = GetDoc();
commit f64479dd729d83d3fa84fa1e97540f4ae0b37a2b
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sat Oct 28 18:06:34 2023 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Mon Oct 30 21:22:25 2023 +0300

    pPrinter may be nullptr
    
    E.g., calling storeToURL, generating a PDF, on an embedded formula.
    
    Change-Id: If74af90f9c3dfd54a328782ddecd0adf52b51a5a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158591
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/starmath/source/unomodel.cxx b/starmath/source/unomodel.cxx
index b7a92567fe25..89796c27e04f 100644
--- a/starmath/source/unomodel.cxx
+++ b/starmath/source/unomodel.cxx
@@ -910,8 +910,9 @@ uno::Sequence< beans::PropertyValue > SAL_CALL 
SmModel::getRenderer(
         throw RuntimeException();
 
     SmPrinterAccess aPrinterAccess( *pDocSh );
-    Printer *pPrinter = aPrinterAccess.GetPrinter();
-    Size    aPrtPaperSize ( pPrinter->GetPaperSize() );
+    Size aPrtPaperSize;
+    if (Printer *pPrinter = aPrinterAccess.GetPrinter())
+        aPrtPaperSize = pPrinter->GetPaperSize();
 
     // if paper size is 0 (usually if no 'real' printer is found),
     // guess the paper size
@@ -981,11 +982,16 @@ void SAL_CALL SmModel::render(
         return;
 
     SmPrinterAccess aPrinterAccess( *pDocSh );
-    Printer *pPrinter = aPrinterAccess.GetPrinter();
 
-    Size    aPrtPaperSize ( pPrinter->GetPaperSize() );
-    Size    aOutputSize   ( pPrinter->GetOutputSize() );
-    Point   aPrtPageOffset( pPrinter->GetPageOffset() );
+    Size aPrtPaperSize;
+    Size aOutputSize;
+    Point aPrtPageOffset;
+    if (Printer *pPrinter = aPrinterAccess.GetPrinter())
+    {
+        aPrtPaperSize = pPrinter->GetPaperSize();
+        aOutputSize = pPrinter->GetOutputSize();
+        aPrtPageOffset = pPrinter->GetPageOffset();
+    }
 
     // no real printer ??
     if (aPrtPaperSize.IsEmpty())

Reply via email to