include/editeng/unoprnms.hxx       |    1 
 include/svx/svdograf.hxx           |    2 
 include/svx/unoshprp.hxx           |    2 
 include/xmloff/shapeexport.hxx     |    6 ++
 svx/source/svdraw/svdograf.cxx     |   72 +++++++++++++++++++++++++++++++++
 svx/source/unodraw/unoprov.cxx     |    1 
 svx/source/unodraw/unoshap2.cxx    |    7 ++-
 xmloff/source/draw/shapeexport.cxx |   80 +++++++++++++++++++++++++++++++++++--
 8 files changed, 166 insertions(+), 5 deletions(-)

New commits:
commit d73d26e8d74988f5a4c2afcaae715dd50425100a
Author:     Caolán McNamara <[email protected]>
AuthorDate: Fri Sep 12 15:36:30 2025 +0100
Commit:     Miklos Vajna <[email protected]>
CommitDate: Wed Sep 17 09:44:05 2025 +0200

    optionally explode pdf into odf elements as fodg export time
    
    e.g. instdir/program/soffice --headless --convert-to \
    'fodg:OpenDocument Drawing Flat 
XML:{"DecomposePDF":{"type":"boolean","value":"true"}}' \
    sample.pdf
    
    Change-Id: I1e36b3d0c12e8716aada52e5d34526d06fe28cc5
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190967
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Miklos Vajna <[email protected]>

diff --git a/include/editeng/unoprnms.hxx b/include/editeng/unoprnms.hxx
index b42c03bca762..327a32dc47b6 100644
--- a/include/editeng/unoprnms.hxx
+++ b/include/editeng/unoprnms.hxx
@@ -178,6 +178,7 @@ inline constexpr OUString UNO_NAME_HYPERLINK = 
u"Hyperlink"_ustr;
 
 inline constexpr OUString UNO_NAME_GRAPHOBJ_FILLBITMAP = 
u"GraphicObjectFillBitmap"_ustr;
 inline constexpr OUString UNO_NAME_GRAPHOBJ_REPLACEMENT_GRAPHIC = 
u"ReplacementGraphic"_ustr;
+inline constexpr OUString UNO_NAME_GRAPHOBJ_REPLACEMENT_MODEL = 
u"ReplacementModel"_ustr;
 inline constexpr OUString UNO_NAME_GRAPHOBJ_GRAFSTREAMURL = 
u"GraphicStreamURL"_ustr;
 #define UNO_NAME_GRAPHOBJ_URLPKGPREFIX          "vnd.sun.star.Package:"
 inline constexpr OUString UNO_NAME_GRAPHOBJ_GRAPHIC = u"Graphic"_ustr;
diff --git a/include/svx/svdograf.hxx b/include/svx/svdograf.hxx
index fae28c0a72dc..9618b884bf18 100644
--- a/include/svx/svdograf.hxx
+++ b/include/svx/svdograf.hxx
@@ -124,6 +124,8 @@ public:
     void                    SetGraphicObject( const GraphicObject& rGrfObj );
     const GraphicObject&    GetGraphicObject(bool bForceSwapIn = false) const;
     SAL_DLLPRIVATE const GraphicObject*    GetReplacementGraphicObject() const;
+    // An exploded view of a pdf page as a draw document.
+    SAL_DLLPRIVATE css::uno::Reference<css::lang::XComponent> 
GetReplacementGraphicModel() const;
 
     SAL_DLLPRIVATE void                    NbcSetGraphic(const Graphic& rGrf);
     void                    SetGraphic(const Graphic& rGrf);
diff --git a/include/svx/unoshprp.hxx b/include/svx/unoshprp.hxx
index cbb2521684be..358576ac23ce 100644
--- a/include/svx/unoshprp.hxx
+++ b/include/svx/unoshprp.hxx
@@ -117,6 +117,7 @@
 
 /// reuse attr slots for GraphicObject which will never be used together with 
graphic object
 #define OWN_ATTR_REPLACEMENT_GRAPHIC            (OWN_ATTR_VALUE_START+14)
+#define OWN_ATTR_REPLACEMENT_MODEL              (OWN_ATTR_VALUE_START+15)
 
 #define OWN_ATTR_APPLET_DOCBASE                 (OWN_ATTR_VALUE_START+48)
 #define OWN_ATTR_APPLET_CODEBASE                (OWN_ATTR_VALUE_START+49)
@@ -471,6 +472,7 @@
     SPECIAL_GRAPHOBJ_PROPERTIES_DEFAULTS \
     { UNO_NAME_GRAPHIC_GRAPHICCROP,           SDRATTR_GRAFCROP            , 
::cppu::UnoType<css::text::GraphicCrop>::get(),        0,  0 }, \
     { UNO_NAME_GRAPHOBJ_REPLACEMENT_GRAPHIC,  OWN_ATTR_REPLACEMENT_GRAPHIC, 
cppu::UnoType<css::graphic::XGraphic>::get()  ,   0,     0}, \
+    { UNO_NAME_GRAPHOBJ_REPLACEMENT_MODEL  ,  OWN_ATTR_REPLACEMENT_MODEL,   
cppu::UnoType<css::lang::XComponent>::get()  ,    0,     0}, \
     { UNO_NAME_GRAPHOBJ_GRAFSTREAMURL,        OWN_ATTR_GRAFSTREAMURL      , 
::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 
}, \
     { UNO_NAME_GRAPHOBJ_FILLBITMAP,           OWN_ATTR_VALUE_FILLBITMAP   , 
cppu::UnoType<css::awt::XBitmap>::get()  ,    0,     0},    \
     { UNO_NAME_GRAPHOBJ_GRAPHIC,              OWN_ATTR_VALUE_GRAPHIC      , 
cppu::UnoType<css::graphic::XGraphic>::get()  ,   0,     0}, \
diff --git a/include/xmloff/shapeexport.hxx b/include/xmloff/shapeexport.hxx
index 0d0e4ce6521e..7cf99533cf7a 100644
--- a/include/xmloff/shapeexport.hxx
+++ b/include/xmloff/shapeexport.hxx
@@ -39,6 +39,7 @@ namespace com::sun::star::awt { struct Point; }
 namespace com::sun::star::beans { class XPropertySet; }
 namespace com::sun::star::drawing { class XShape; }
 namespace com::sun::star::drawing { class XShapes; }
+namespace com::sun::star::lang { class XComponent; }
 
 class XMLTableExport;
 namespace comphelper { class AttributeList; }
@@ -135,6 +136,7 @@ struct ImplXMLShapeExportInfo
     XmlShapeType    meShapeType;
 
     css::uno::Reference< css::drawing::XShape > xCustomShapeReplacement;
+    css::uno::Reference<css::lang::XComponent> xPDFModelReplacement;
 
     ImplXMLShapeExportInfo() : mnFamily( XmlStyleFamily::SD_GRAPHICS_ID ), 
meShapeType( XmlShapeType::NotYetSet ) {}
 };
@@ -289,6 +291,10 @@ public:
     css::uno::Reference < css::drawing::XShape > 
checkForCustomShapeReplacement(
         const css::uno::Reference < css::drawing::XShape >& );
 
+    /** replacing PDF with drawing objects */
+    css::uno::Reference<css::lang::XComponent> checkForPDFShapeReplacement(
+        const css::uno::Reference<css::drawing::XShape>& xShape);
+
     /** helper to export the style for graphic defaults */
     void ExportGraphicDefaults();
 
diff --git a/svx/source/svdraw/svdograf.cxx b/svx/source/svdraw/svdograf.cxx
index 3a11aa0a0d49..c766e7d4780d 100644
--- a/svx/source/svdraw/svdograf.cxx
+++ b/svx/source/svdraw/svdograf.cxx
@@ -29,11 +29,13 @@
 #include <vcl/svapp.hxx>
 
 #include <sfx2/linkmgr.hxx>
+#include <sfx2/viewsh.hxx>
 #include <svx/dialmgr.hxx>
 #include <svx/strings.hrc>
 #include <svx/svdhdl.hxx>
 #include <svx/svdmodel.hxx>
 #include <svx/svdpage.hxx>
+#include <svx/svdview.hxx>
 #include <svx/svdograf.hxx>
 #include <svx/svdogrp.hxx>
 #include <svx/xbtmpit.hxx>
@@ -54,6 +56,15 @@
 #include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx>
 #include <memory>
 
+#include <comphelper/processfactory.hxx>
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+#include <com/sun/star/frame/DispatchHelper.hpp>
+#include <com/sun/star/frame/XDesktop2.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <vcl/filter/PDFiumLibrary.hxx>
+#include <svdpdf.hxx>
+#include <svx/unoapi.hxx>
+
 using namespace ::com::sun::star;
 
 class SdrGraphicLink : public sfx2::SvBaseLink
@@ -349,6 +360,67 @@ const GraphicObject* 
SdrGrafObj::GetReplacementGraphicObject() const
     return mpReplacementGraphicObject.get();
 }
 
+css::uno::Reference<css::lang::XComponent> 
SdrGrafObj::GetReplacementGraphicModel() const
+{
+    if (!mpGraphicObject)
+        return nullptr;
+
+    const Graphic& rGraphic = mpGraphicObject->GetGraphic();
+    auto const & rVectorGraphicDataPtr = rGraphic.getVectorGraphicData();
+    if (!rVectorGraphicDataPtr)
+        return nullptr;
+
+    if (rVectorGraphicDataPtr->getType() != VectorGraphicDataType::Pdf)
+        return nullptr;
+
+    auto pPdfium = vcl::pdf::PDFiumLibrary::get();
+    if (!pPdfium)
+        return nullptr;
+
+    // Create an empty Draw component.
+    uno::Reference<uno::XComponentContext> xContext = 
::comphelper::getProcessComponentContext();
+    uno::Reference<frame::XDesktop2> xDesktop = 
css::frame::Desktop::create(xContext);
+    if (!xDesktop)
+        return nullptr;
+    uno::Reference<lang::XComponent> xComponent = 
xDesktop->loadComponentFromURL(u"private:factory/sdraw"_ustr, u"_default"_ustr, 
0, {});
+    uno::Reference<frame::XModel> xModel(xComponent, uno::UNO_QUERY);
+    if (!xModel)
+        return nullptr;
+    uno::Reference<frame::XController> 
xController(xModel->getCurrentController());
+    SfxViewShell* pViewShell = SfxViewShell::Get(xController);
+    if (!pViewShell)
+        return nullptr;
+    uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(xComponent, 
uno::UNO_QUERY);
+    if (!xDrawPagesSupplier)
+        return nullptr;
+    uno::Reference<drawing::XDrawPages> xDrawPages = 
xDrawPagesSupplier->getDrawPages();
+    if (!xDrawPages)
+        return nullptr;
+    uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPages->getByIndex(0), 
uno::UNO_QUERY);
+    SdrPage* pSdrPage = GetSdrPageFromXDrawPage(xDrawPage);
+    if (!pSdrPage)
+        return nullptr;
+
+    SdrModel& rSdrModel = pSdrPage->getSdrModelFromSdrPage();
+
+    tools::Rectangle aLogicRect = GetLogicRect();
+
+    ImpSdrPdfImport aFilter(rSdrModel, GetLayer(), aLogicRect, rGraphic);
+    if (rGraphic.getPageNumber() < aFilter.GetPageCount())
+    {
+        aFilter.DoImport(*pSdrPage, 0, rGraphic.getPageNumber(), nullptr);
+    }
+
+    if (SdrView* pView = pViewShell->GetDrawView())
+    {
+        // Group shapes together
+        pView->MarkAllObj();
+        pView->GroupMarked();
+    }
+
+    return xComponent;
+}
+
 void SdrGrafObj::NbcSetGraphic(const Graphic& rGraphic)
 {
     mpGraphicObject->SetGraphic(rGraphic);
diff --git a/svx/source/unodraw/unoprov.cxx b/svx/source/unodraw/unoprov.cxx
index e4de02447d68..ca67ef523415 100644
--- a/svx/source/unodraw/unoprov.cxx
+++ b/svx/source/unodraw/unoprov.cxx
@@ -763,6 +763,7 @@ static std::span<SfxItemPropertyMapEntry const> 
ImplGetSvxTableShapePropertyMap(
         { u"UseBandingRowStyle"_ustr,           
OWN_ATTR_TABLETEMPLATE_BANDINGROWS, cppu::UnoType<bool>::get(),0, 0},
         { u"UseBandingColumnStyle"_ustr,        
OWN_ATTR_TABLETEMPLATE_BANDINGCOLUMNS, cppu::UnoType<bool>::get(),0, 0},
         { u"ReplacementGraphic"_ustr,           OWN_ATTR_REPLACEMENT_GRAPHIC, 
cppu::UnoType<css::graphic::XGraphic>::get(), 
css::beans::PropertyAttribute::READONLY, 0},
+        { u"ReplacementModel"_ustr,             OWN_ATTR_REPLACEMENT_MODEL, 
cppu::UnoType<css::lang::XComponent>::get(), 
css::beans::PropertyAttribute::READONLY, 0},
     };
 
     return aTableShapePropertyMap_Impl;
diff --git a/svx/source/unodraw/unoshap2.cxx b/svx/source/unodraw/unoshap2.cxx
index d1a8c86d0f6c..f425c2fb76a6 100644
--- a/svx/source/unodraw/unoshap2.cxx
+++ b/svx/source/unodraw/unoshap2.cxx
@@ -65,7 +65,6 @@
 #include <cppuhelper/queryinterface.hxx>
 #include <tools/stream.hxx>
 
-
 #include <memory>
 
 using namespace ::cppu;
@@ -1452,6 +1451,12 @@ bool SvxGraphicObject::getPropertyValueImpl( const 
OUString& rName, const SfxIte
         break;
     }
 
+    case OWN_ATTR_REPLACEMENT_MODEL:
+    {
+        rValue <<= 
static_cast<SdrGrafObj*>(GetSdrObject())->GetReplacementGraphicModel();
+        break;
+    }
+
     case OWN_ATTR_GRAFSTREAMURL:
     {
         const OUString  aStreamURL( static_cast<SdrGrafObj*>( GetSdrObject() 
)->GetGrafStreamURL() );
diff --git a/xmloff/source/draw/shapeexport.cxx 
b/xmloff/source/draw/shapeexport.cxx
index 5eb127ac8a89..db0448342990 100644
--- a/xmloff/source/draw/shapeexport.cxx
+++ b/xmloff/source/draw/shapeexport.cxx
@@ -60,6 +60,7 @@
 #include <com/sun/star/drawing/ShadeMode.hpp>
 #include <com/sun/star/drawing/XControlShape.hpp>
 #include <com/sun/star/drawing/XCustomShapeEngine.hpp>
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
 #include <com/sun/star/drawing/XGluePointsSupplier.hpp>
 #include <com/sun/star/drawing/BarCode.hpp>
 #include <com/sun/star/drawing/BarCodeErrorCorrection.hpp>
@@ -81,6 +82,7 @@
 #include <com/sun/star/table/XColumnRowRange.hpp>
 #include <com/sun/star/text/WritingMode2.hpp>
 #include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/util/XCloseable.hpp>
 
 #include <comphelper/classids.hxx>
 #include <comphelper/processfactory.hxx>
@@ -217,6 +219,50 @@ XMLShapeExport::~XMLShapeExport()
 {
 }
 
+static css::uno::Reference<css::drawing::XShape> GetPDFShape(const 
uno::Reference<lang::XComponent>& xReplacementModel)
+{
+    uno::Reference<drawing::XDrawPagesSupplier> 
xDrawPagesSupplier(xReplacementModel, uno::UNO_QUERY);
+    if (!xDrawPagesSupplier)
+        return nullptr;
+    uno::Reference<drawing::XDrawPages> 
xDrawPages(xDrawPagesSupplier->getDrawPages());
+    if (!xDrawPages)
+        return nullptr;
+    uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPages->getByIndex(0), 
uno::UNO_QUERY);
+    if (!xDrawPage)
+        return nullptr;
+    return uno::Reference<drawing::XShape>(xDrawPage->getByIndex(0), 
uno::UNO_QUERY);
+}
+
+uno::Reference<lang::XComponent> 
XMLShapeExport::checkForPDFShapeReplacement(const 
uno::Reference<drawing::XShape>& xShape)
+{
+    if (!GetExport().decomposePDF())
+        return nullptr;
+
+    OUString aType( xShape->getShapeType() );
+    if (aType != "com.sun.star.drawing.GraphicObjectShape")
+        return nullptr;
+
+    const uno::Reference< beans::XPropertySet > xPropSet(xShape, 
uno::UNO_QUERY);
+    if(!xPropSet.is())
+        return nullptr;
+
+    uno::Reference<graphic::XGraphic> xGraphic;
+    xPropSet->getPropertyValue(u"Graphic"_ustr) >>= xGraphic;
+
+    OUString sOutMimeType;
+    GetExport().GetGraphicMimeTypeFromStream(xGraphic, sOutMimeType);
+
+    if (sOutMimeType != "application/pdf")
+        return nullptr;
+
+    // To export PDF as exploded drawing object replacements
+    uno::Reference<lang::XComponent> xReplacementModel;
+    xPropSet->getPropertyValue(u"ReplacementModel"_ustr) >>= xReplacementModel;
+    SAL_WARN_IF(!xReplacementModel.is(), "xmloff", "no xModel for pdf format");
+
+    return xReplacementModel;
+}
+
 // sj: replacing CustomShapes with standard objects that are also supported in 
OpenOffice.org format
 uno::Reference< drawing::XShape > 
XMLShapeExport::checkForCustomShapeReplacement( const uno::Reference< 
drawing::XShape >& xShape )
 {
@@ -284,9 +330,18 @@ void XMLShapeExport::collectShapeAutoStyles(const 
uno::Reference< drawing::XShap
 
     ImplXMLShapeExportInfo& aShapeInfo = aShapeInfoVector[nZIndex];
 
-    uno::Reference< drawing::XShape > xCustomShapeReplacement = 
checkForCustomShapeReplacement( xShape );
-    if ( xCustomShapeReplacement.is() )
-        aShapeInfo.xCustomShapeReplacement = 
std::move(xCustomShapeReplacement);
+    css::uno::Reference<css::lang::XComponent> xPDFModelReplacement = 
checkForPDFShapeReplacement(xShape);
+    if (xPDFModelReplacement)
+    {
+        aShapeInfo.xPDFModelReplacement = std::move(xPDFModelReplacement);
+        aShapeInfo.xCustomShapeReplacement = 
GetPDFShape(aShapeInfo.xPDFModelReplacement);
+    }
+    else
+    {
+        uno::Reference<drawing::XShape> xCustomShapeReplacement = 
checkForCustomShapeReplacement(xShape);
+        if ( xCustomShapeReplacement.is() )
+            aShapeInfo.xCustomShapeReplacement = 
std::move(xCustomShapeReplacement);
+    }
 
     // first compute the shapes type
     ImpCalcShapeType(xShape, aShapeInfo.meShapeType);
@@ -828,7 +883,24 @@ void XMLShapeExport::exportShape(const uno::Reference< 
drawing::XShape >& xShape
         case XmlShapeType::DrawGraphicObjectShape:
         case XmlShapeType::PresGraphicObjectShape:
         {
-            ImpExportGraphicObjectShape(xShape, aShapeInfo.meShapeType, 
nFeatures, pRefPoint );
+            if (aShapeInfo.xCustomShapeReplacement.is()) // exploded PDF
+            {
+                ImpExportGroupShape(aShapeInfo.xCustomShapeReplacement, 
nFeatures, pRefPoint);
+                uno::Reference<css::util::XCloseable> 
xClose(aShapeInfo.xPDFModelReplacement, uno::UNO_QUERY);
+                if (xClose.is())
+                {
+                    try
+                    {
+                        xClose->close(true);
+                    }
+                    catch (const uno::RuntimeException& e)
+                    {
+                        SAL_WARN("xmloff", "Couldn't close PDF replacement 
model: " << e.Message);
+                    }
+                }
+            }
+            else
+                ImpExportGraphicObjectShape(xShape, aShapeInfo.meShapeType, 
nFeatures, pRefPoint );
             break;
         }
 

Reply via email to