summaryrefslogtreecommitdiff
path: root/filter/source/svg/svgexport.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'filter/source/svg/svgexport.cxx')
-rw-r--r--filter/source/svg/svgexport.cxx802
1 files changed, 601 insertions, 201 deletions
diff --git a/filter/source/svg/svgexport.cxx b/filter/source/svg/svgexport.cxx
index eb5da674e6c3..c6325f282a2e 100644
--- a/filter/source/svg/svgexport.cxx
+++ b/filter/source/svg/svgexport.cxx
@@ -17,6 +17,7 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
+#include <strings.hrc>
#include "svgwriter.hxx"
#include "svgfontexport.hxx"
#include "svgfilter.hxx"
@@ -43,14 +44,17 @@
#include <editeng/outliner.hxx>
#include <editeng/flditem.hxx>
#include <comphelper/processfactory.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/scopeguard.hxx>
#include <comphelper/sequenceashashmap.hxx>
#include <i18nlangtag/lang.h>
-#include <svl/zforlist.hxx>
+#include <svl/numformat.hxx>
#include <tools/debug.hxx>
#include <tools/urlobj.hxx>
#include <unotools/streamwrap.hxx>
#include <unotools/tempfile.hxx>
#include <unotools/ucbstreamhelper.hxx>
+#include <vcl/filter/SvmReader.hxx>
#include <xmloff/unointerfacetouniqueidentifiermapper.hxx>
#include <xmloff/namespacemap.hxx>
#include <xmloff/xmlnamespace.hxx>
@@ -60,7 +64,9 @@
#include <svx/svdmodel.hxx>
#include <svx/svdxcgv.hxx>
#include <sal/log.hxx>
-#include <tools/diagnose_ex.h>
+#include <comphelper/diagnose_ex.hxx>
+#include <tools/zcodec.hxx>
+#include <rtl/crc.h>
#include <memory>
#include <string_view>
@@ -68,39 +74,41 @@
using namespace css::animations;
using namespace css::presentation;
using namespace ::com::sun::star::graphic;
-using namespace ::com::sun::star::geometry;
+using namespace ::com::sun::star::style;
using namespace ::com::sun::star;
using namespace ::xmloff::token;
// - ooo elements and attributes -
-#define NSPREFIX "ooo:"
+#define NSPREFIX u"ooo:"
-#define SVG_PROP_TINYPROFILE "TinyMode"
-#define SVG_PROP_DTDSTRING "DTDString"
-#define SVG_PROP_EMBEDFONTS "EmbedFonts"
-#define SVG_PROP_NATIVEDECORATION "UseNativeTextDecoration"
-#define SVG_PROP_OPACITY "Opacity"
-#define SVG_PROP_POSITIONED_CHARACTERS "UsePositionedCharacters"
+constexpr OUStringLiteral SVG_PROP_TINYPROFILE = u"TinyMode";
+constexpr OUStringLiteral SVG_PROP_DTDSTRING = u"DTDString";
+constexpr OUStringLiteral SVG_PROP_EMBEDFONTS = u"EmbedFonts";
+constexpr OUStringLiteral SVG_PROP_NATIVEDECORATION = u"UseNativeTextDecoration";
+constexpr OUStringLiteral SVG_PROP_OPACITY = u"Opacity";
+constexpr OUStringLiteral SVG_PROP_POSITIONED_CHARACTERS = u"UsePositionedCharacters";
// ooo xml elements
-constexpr OUStringLiteral aOOOElemTextField = u"" NSPREFIX "text_field";
+constexpr OUString aOOOElemTextField = NSPREFIX "text_field"_ustr;
// ooo xml attributes for meta_slide
-const char aOOOAttrSlide[] = NSPREFIX "slide";
-const char aOOOAttrMaster[] = NSPREFIX "master";
-const char aOOOAttrBackgroundVisibility[] = NSPREFIX "background-visibility";
-const char aOOOAttrMasterObjectsVisibility[] = NSPREFIX "master-objects-visibility";
-const char aOOOAttrSlideDuration[] = NSPREFIX "slide-duration";
-const OUString aOOOAttrDateTimeField = NSPREFIX "date-time-field";
-constexpr OUStringLiteral aOOOAttrFooterField = u"" NSPREFIX "footer-field";
-const char aOOOAttrHasTransition[] = NSPREFIX "has-transition";
+constexpr OUString aOOOAttrSlide = NSPREFIX "slide"_ustr;
+constexpr OUString aOOOAttrMaster = NSPREFIX "master"_ustr;
+constexpr OUStringLiteral aOOOAttrHasCustomBackground = NSPREFIX "has-custom-background";
+constexpr OUStringLiteral aOOOAttrDisplayName = NSPREFIX "display-name";
+constexpr OUString aOOOAttrBackgroundVisibility = NSPREFIX "background-visibility"_ustr;
+constexpr OUString aOOOAttrMasterObjectsVisibility = NSPREFIX "master-objects-visibility"_ustr;
+constexpr OUStringLiteral aOOOAttrSlideDuration = NSPREFIX "slide-duration";
+constexpr OUString aOOOAttrDateTimeField = NSPREFIX "date-time-field"_ustr;
+constexpr OUString aOOOAttrFooterField = NSPREFIX "footer-field"_ustr;
+constexpr OUString aOOOAttrHasTransition = NSPREFIX "has-transition"_ustr;
// ooo xml attributes for pages and shapes
-const char aOOOAttrName[] = NSPREFIX "name";
+constexpr OUString aOOOAttrName = NSPREFIX "name"_ustr;
-constexpr OUStringLiteral constSvgNamespace = u"http://www.w3.org/2000/svg";
+constexpr OUString constSvgNamespace = u"http://www.w3.org/2000/svg"_ustr;
/** Text Field Class Hierarchy
@@ -203,7 +211,7 @@ public:
}
virtual void growCharSet( SVGFilter::UCharSetMapMap & aTextFieldCharSets ) const override
{
- static const OUString sFieldId = aOOOAttrFooterField;
+ static constexpr OUString sFieldId = aOOOAttrFooterField;
implGrowCharSet( aTextFieldCharSets, text, sFieldId );
}
};
@@ -300,7 +308,7 @@ public:
OUString sDateTimeFormat = sDateFormat + " " + sTimeFormat;
- pSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "date-time-format", sDateTimeFormat );
+ pSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "date-time-format"_ustr, sDateTimeFormat );
SvXMLElementExport aExp( *pSVGExport, XML_NAMESPACE_NONE, "g", true, true );
}
virtual void growCharSet( SVGFilter::UCharSetMapMap & aTextFieldCharSets ) const override
@@ -368,6 +376,11 @@ SVGExport::SVGExport(
// add namespaces
GetNamespaceMap_().Add(
+ GetXMLToken(XML_NP_SVG),
+ GetXMLToken(XML_N_SVG_COMPAT),
+ XML_NAMESPACE_SVG);
+
+ GetNamespaceMap_().Add(
GetXMLToken(XML_NP_PRESENTATION),
GetXMLToken(XML_N_PRESENTATION),
XML_NAMESPACE_PRESENTATION);
@@ -423,6 +436,12 @@ namespace
BitmapChecksum GetBitmapChecksum( const MetaAction* pAction )
{
+ if( !pAction )
+ {
+ OSL_FAIL( "GetBitmapChecksum: passed MetaAction pointer is null." );
+ return 0;
+ }
+
BitmapChecksum nChecksum = 0;
const MetaActionType nType = pAction->GetType();
@@ -431,19 +450,16 @@ BitmapChecksum GetBitmapChecksum( const MetaAction* pAction )
case MetaActionType::BMPSCALE:
{
const MetaBmpScaleAction* pA = static_cast<const MetaBmpScaleAction*>(pAction);
- if( pA )
- nChecksum = pA->GetBitmap().GetChecksum();
- else
- OSL_FAIL( "GetBitmapChecksum: MetaBmpScaleAction pointer is null." );
+ // The conversion to BitmapEx is needed since a Bitmap object is
+ // converted to BitmapEx before passing it to SVGActionWriter::ImplWriteBmp
+ // where the checksum is checked for matching.
+ nChecksum = BitmapEx( pA->GetBitmap() ).GetChecksum();
}
break;
case MetaActionType::BMPEXSCALE:
{
const MetaBmpExScaleAction* pA = static_cast<const MetaBmpExScaleAction*>(pAction);
- if( pA )
- nChecksum = pA->GetBitmapEx().GetChecksum();
- else
- OSL_FAIL( "GetBitmapChecksum: MetaBmpExScaleAction pointer is null." );
+ nChecksum = pA->GetBitmapEx().GetChecksum();
}
break;
default: break;
@@ -451,37 +467,131 @@ BitmapChecksum GetBitmapChecksum( const MetaAction* pAction )
return nChecksum;
}
-} // end anonymous namespace
+MetaAction* CreateMetaBitmapAction( const MetaAction* pAction, const Point& rPt, const Size& rSz )
+{
+ if( !pAction )
+ {
+ OSL_FAIL( "CreateMetaBitmapAction: passed MetaAction pointer is null." );
+ return nullptr;
+ }
+ MetaAction* pResAction = nullptr;
+ const MetaActionType nType = pAction->GetType();
+ switch( nType )
+ {
+ case MetaActionType::BMPSCALE:
+ {
+ const MetaBmpScaleAction* pA = static_cast<const MetaBmpScaleAction*>(pAction);
+ pResAction = new MetaBmpScaleAction( rPt, rSz, pA->GetBitmap() );
+ }
+ break;
+ case MetaActionType::BMPEXSCALE:
+ {
+ const MetaBmpExScaleAction* pA = static_cast<const MetaBmpExScaleAction*>(pAction);
+ pResAction = new MetaBmpExScaleAction( rPt, rSz, pA->GetBitmapEx() );
+ }
+ break;
+ default: break;
+ }
+ return pResAction;
+}
-static void MetaBitmapActionGetPoint( const MetaAction* pAction, Point& rPt )
+void MetaBitmapActionGetPoint( const MetaAction* pAction, Point& rPt )
{
+ if( !pAction )
+ {
+ OSL_FAIL( "MetaBitmapActionGetPoint: passed MetaAction pointer is null." );
+ return;
+ }
const MetaActionType nType = pAction->GetType();
switch( nType )
{
case MetaActionType::BMPSCALE:
{
const MetaBmpScaleAction* pA = static_cast<const MetaBmpScaleAction*>(pAction);
- if( pA )
- rPt = pA->GetPoint();
- else
- OSL_FAIL( "MetaBitmapActionGetPoint: MetaBmpScaleAction pointer is null." );
+ rPt = pA->GetPoint();
}
break;
case MetaActionType::BMPEXSCALE:
{
const MetaBmpExScaleAction* pA = static_cast<const MetaBmpExScaleAction*>(pAction);
- if( pA )
- rPt = pA->GetPoint();
- else
- OSL_FAIL( "MetaBitmapActionGetPoint: MetaBmpExScaleAction pointer is null." );
+ rPt = pA->GetPoint();
+ }
+ break;
+ default: break;
+ }
+}
+
+void MetaBitmapActionGetSize( const MetaAction* pAction, Size& rSz )
+{
+ if( !pAction )
+ {
+ OSL_FAIL( "MetaBitmapActionGetSize: passed MetaAction pointer is null." );
+ return;
+ }
+ const MetaActionType nType = pAction->GetType();
+ switch( nType )
+ {
+ case MetaActionType::BMPSCALE:
+ {
+ const MetaBmpScaleAction* pA = static_cast<const MetaBmpScaleAction*>(pAction);
+ rSz = pA->GetSize();
+ }
+ break;
+ case MetaActionType::BMPEXSCALE:
+ {
+ const MetaBmpExScaleAction* pA = static_cast<const MetaBmpExScaleAction*>(pAction);
+ rSz = pA->GetSize();
+ }
+ break;
+ default: break;
+ }
+}
+
+void MetaBitmapActionGetOrigSize( const MetaAction* pAction, Size& rSz )
+{
+ if( !pAction )
+ {
+ OSL_FAIL( "MetaBitmapActionGetOrigSize: passed MetaAction pointer is null." );
+ return;
+ }
+
+ const MetaActionType nType = pAction->GetType();
+ MapMode aSourceMode( MapUnit::MapPixel );
+ MapMode aTargetMode( MapUnit::Map100thMM );
+
+ switch( nType )
+ {
+ case MetaActionType::BMPSCALE:
+ {
+ const MetaBmpScaleAction* pA = static_cast<const MetaBmpScaleAction*>(pAction);
+ const Bitmap& rBitmap = pA->GetBitmap();
+ rSz = rBitmap.GetSizePixel();
+ }
+ break;
+ case MetaActionType::BMPEXSCALE:
+ {
+ const MetaBmpExScaleAction* pA = static_cast<const MetaBmpExScaleAction*>(pAction);
+ const BitmapEx& rBitmap = pA->GetBitmapEx();
+ rSz = rBitmap.GetSizePixel();
}
break;
default: break;
}
+ rSz = OutputDevice::LogicToLogic( rSz, aSourceMode, aTargetMode );
+}
+OUString getPatternIdForTiledBackground( std::u16string_view sSlideId, BitmapChecksum nChecksum )
+{
+ return OUString::Concat("bg-pattern.") + sSlideId + "." + OUString::number( nChecksum );
}
+OUString getIdForTiledBackground( std::u16string_view sSlideId, BitmapChecksum nChecksum )
+{
+ return OUString::Concat("bg-") + sSlideId + "." + OUString::number( nChecksum );
+}
+
+} // end anonymous namespace
size_t HashBitmap::operator()( const ObjectRepresentation& rObjRep ) const
{
@@ -544,6 +654,8 @@ bool SVGFilter::implExport( const Sequence< PropertyValue >& rDescriptor )
{
pValue[ i ].Value >>= maFilterData;
}
+ else if (pValue[i].Name == "StatusIndicator")
+ pValue[i].Value >>= mxStatusIndicator;
}
if(mbWriterFilter || mbCalcFilter)
@@ -556,12 +668,16 @@ bool SVGFilter::implExportImpressOrDraw( const Reference< XOutputStream >& rxOSt
{
Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() ) ;
bool bRet = false;
+ // Instead of writing to rxOStm directly, we write here in case we need
+ // to compress the output later
+ SvMemoryStream aTempStm;
if( rxOStm.is() )
{
- if( !mSelectedPages.empty() && !mMasterPageTargets.empty() )
+ if (!mSelectedPages.empty())
{
- Reference< XDocumentHandler > xDocHandler = implCreateExportDocumentHandler( rxOStm );
+ ::rtl::Reference< ::utl::OStreamWrapper > aTempStmWrapper = new ::utl::OStreamWrapper( aTempStm );
+ Reference< XDocumentHandler > xDocHandler = implCreateExportDocumentHandler( aTempStmWrapper );
if( xDocHandler.is() )
{
@@ -571,10 +687,6 @@ bool SVGFilter::implExportImpressOrDraw( const Reference< XOutputStream >& rxOSt
// mpSVGExport = new SVGExport( xDocHandler );
mpSVGExport = new SVGExport( xContext, xDocHandler, maFilterData );
- // xKeepAlive is set up only to manage the life-time of the object pointed by mpSVGExport,
- // and in order to prevent that it is destroyed when passed to AnimationExporter.
- Reference< XInterface > xKeepAlive = static_cast< css::document::XFilter* >( mpSVGExport );
-
// create an id for each draw page
for( const auto& rPage : mSelectedPages )
implRegisterInterface( rPage );
@@ -591,7 +703,7 @@ bool SVGFilter::implExportImpressOrDraw( const Reference< XOutputStream >& rxOSt
if( mxDefaultPage.is() )
{
- SvxDrawPage* pSvxDrawPage = comphelper::getUnoTunnelImplementation<SvxDrawPage>( mxDefaultPage );
+ SvxDrawPage* pSvxDrawPage = comphelper::getFromUnoTunnel<SvxDrawPage>( mxDefaultPage );
if( pSvxDrawPage )
{
@@ -640,6 +752,38 @@ bool SVGFilter::implExportImpressOrDraw( const Reference< XOutputStream >& rxOSt
}
}
}
+ if ( bRet )
+ {
+ const sal_Int8* aDataPtr = static_cast< const sal_Int8* >( aTempStm.GetData() );
+ sal_uInt32 aDataSize = aTempStm.GetSize();
+ SvMemoryStream aCompressedStm;
+ if ( mbShouldCompress )
+ {
+ sal_uInt32 nUncompressedCRC32
+ = rtl_crc32( 0, aTempStm.GetData(), aTempStm.GetSize() );
+ ZCodec aCodec;
+ aTempStm.Seek( 0 );
+ aCodec.BeginCompression( ZCODEC_DEFAULT_COMPRESSION, /*gzLib*/true );
+ // the inner modify time/filename doesn't really matter in this context because
+ // compressed graphic formats are meant to be opened as is - not to be extracted
+ aCodec.SetCompressionMetadata( "inner"_ostr, 0, nUncompressedCRC32 );
+ aCodec.Compress( aTempStm, aCompressedStm );
+ sal_uInt32 nTotalIn = static_cast< sal_uInt32 >( aCodec.EndCompression() );
+ if ( aCompressedStm.GetError() || nTotalIn != aDataSize )
+ {
+ bRet = false;
+ return bRet;
+ }
+ else
+ {
+ aDataPtr = static_cast< const sal_Int8* >( aCompressedStm.GetData() );
+ aDataSize = aCompressedStm.GetSize();
+ }
+ }
+
+ Sequence< sal_Int8 > aTempSeq( aDataPtr, aDataSize );
+ rxOStm->writeBytes( aTempSeq );
+ }
return bRet;
}
@@ -660,10 +804,6 @@ bool SVGFilter::implExportWriterOrCalc( const Reference< XOutputStream >& rxOStm
// mpSVGExport = new SVGExport( xDocHandler );
mpSVGExport = new SVGExport( xContext, xDocHandler, maFilterData );
- // xKeepAlive is set up only to manage the life-time of the object pointed by mpSVGExport,
- // and in order to prevent that it is destroyed when passed to AnimationExporter.
- Reference< XInterface > xKeepAlive = static_cast< css::document::XFilter* >( mpSVGExport );
-
try
{
mxDefaultPage = mSelectedPages[0];
@@ -693,42 +833,54 @@ bool SVGFilter::implExportWriterTextGraphic( const Reference< view::XSelectionSu
Any selection = xSelectionSupplier->getSelection();
uno::Reference<lang::XServiceInfo> xSelection;
selection >>= xSelection;
- if (xSelection.is() && xSelection->supportsService("com.sun.star.text.TextGraphicObject"))
- {
- uno::Reference<beans::XPropertySet> xPropertySet(xSelection, uno::UNO_QUERY);
+ if (!xSelection || !xSelection->supportsService("com.sun.star.text.TextGraphicObject"))
+ return true;
- uno::Reference<graphic::XGraphic> xOriginalGraphic;
- xPropertySet->getPropertyValue("Graphic") >>= xOriginalGraphic;
- const Graphic aOriginalGraphic(xOriginalGraphic);
+ uno::Reference<beans::XPropertySet> xPropertySet(xSelection, uno::UNO_QUERY);
- uno::Reference<graphic::XGraphic> xTransformedGraphic;
- xPropertySet->getPropertyValue("TransformedGraphic") >>= xTransformedGraphic;
+ uno::Reference<graphic::XGraphic> xOriginalGraphic;
+ xPropertySet->getPropertyValue("Graphic") >>= xOriginalGraphic;
+ const Graphic aOriginalGraphic(xOriginalGraphic);
- if (!xTransformedGraphic.is())
- return false;
- const Graphic aTransformedGraphic(xTransformedGraphic);
- bool bSameGraphic = aTransformedGraphic == aOriginalGraphic ||
- aOriginalGraphic.GetChecksum() == aTransformedGraphic.GetChecksum();
- const Graphic aGraphic = bSameGraphic ? aOriginalGraphic : aTransformedGraphic;
- uno::Reference<graphic::XGraphic> xGraphic = bSameGraphic ? xOriginalGraphic : xTransformedGraphic;
+ uno::Reference<graphic::XGraphic> xTransformedGraphic;
+ xPropertySet->getPropertyValue(
+ mbIsPreview ? OUString("GraphicPreview") : OUString("TransformedGraphic"))
+ >>= xTransformedGraphic;
- // Calculate size from Graphic
- Point aPos( OutputDevice::LogicToLogic(aGraphic.GetPrefMapMode().GetOrigin(), aGraphic.GetPrefMapMode(), MapMode(MapUnit::Map100thMM)) );
- Size aSize( OutputDevice::LogicToLogic(aGraphic.GetPrefSize(), aGraphic.GetPrefMapMode(), MapMode(MapUnit::Map100thMM)) );
+ if (!xTransformedGraphic.is())
+ return false;
+ const Graphic aTransformedGraphic(xTransformedGraphic);
+ bool bSameGraphic = aTransformedGraphic == aOriginalGraphic ||
+ aOriginalGraphic.GetChecksum() == aTransformedGraphic.GetChecksum();
+ const Graphic aGraphic = bSameGraphic ? aOriginalGraphic : aTransformedGraphic;
+ uno::Reference<graphic::XGraphic> xGraphic = bSameGraphic ? xOriginalGraphic : xTransformedGraphic;
+
+ // Calculate size from Graphic
+ Point aPos( OutputDevice::LogicToLogic(aGraphic.GetPrefMapMode().GetOrigin(), aGraphic.GetPrefMapMode(), MapMode(MapUnit::Map100thMM)) );
+ Size aSize( OutputDevice::LogicToLogic(aGraphic.GetPrefSize(), aGraphic.GetPrefMapMode(), MapMode(MapUnit::Map100thMM)) );
+
+ assert(mSelectedPages.size() == 1);
+ SvxDrawPage* pSvxDrawPage(comphelper::getFromUnoTunnel<SvxDrawPage>(mSelectedPages[0]));
+ if(pSvxDrawPage == nullptr || pSvxDrawPage->GetSdrPage() == nullptr)
+ return false;
- assert(mSelectedPages.size() == 1);
- SvxDrawPage* pSvxDrawPage(comphelper::getUnoTunnelImplementation<SvxDrawPage>(mSelectedPages[0]));
- if(pSvxDrawPage == nullptr || pSvxDrawPage->GetSdrPage() == nullptr)
- return false;
+ SdrModel& rModel = pSvxDrawPage->GetSdrPage()->getSdrModelFromSdrPage();
+ const bool bUndoEnable = rModel.IsUndoEnabled();
+ if (bUndoEnable)
+ rModel.EnableUndo(false);
+ comphelper::ScopeGuard guard([bUndoEnable, &rModel]() {
+ // restore when leaving
+ if (bUndoEnable)
+ rModel.EnableUndo(false);
+ });
- SdrGrafObj* pGraphicObj = new SdrGrafObj(pSvxDrawPage->GetSdrPage()->getSdrModelFromSdrPage(), aGraphic, tools::Rectangle( aPos, aSize ));
- uno::Reference< drawing::XShape > xShape = GetXShapeForSdrObject(pGraphicObj);
- uno::Reference< XPropertySet > xShapePropSet(xShape, uno::UNO_QUERY);
- xShapePropSet->setPropertyValue("Graphic", uno::Any(xGraphic));
+ rtl::Reference<SdrGrafObj> pGraphicObj = new SdrGrafObj(rModel, aGraphic, tools::Rectangle( aPos, aSize ));
+ uno::Reference< drawing::XShape > xShape = GetXShapeForSdrObject(pGraphicObj.get());
+ uno::Reference< XPropertySet > xShapePropSet(xShape, uno::UNO_QUERY);
+ xShapePropSet->setPropertyValue("Graphic", uno::Any(xGraphic));
- maShapeSelection = drawing::ShapeCollection::create(comphelper::getProcessComponentContext());
- maShapeSelection->add(xShape);
- }
+ maShapeSelection = drawing::ShapeCollection::create(comphelper::getProcessComponentContext());
+ maShapeSelection->add(xShape);
return true;
}
@@ -797,10 +949,14 @@ bool SVGFilter::implExportDocument()
// #i124608#
mbExportShapeSelection = mbSinglePage && maShapeSelection.is() && maShapeSelection->getCount();
- if(xDefaultPagePropertySet.is())
+ if (xDefaultPagePropertySet.is())
{
- xDefaultPagePropertySet->getPropertyValue( "Width" ) >>= nDocWidth;
- xDefaultPagePropertySet->getPropertyValue( "Height" ) >>= nDocHeight;
+ sal_Int32 nWidth = 0;
+ sal_Int32 nHeight = 0;
+ if (xDefaultPagePropertySet->getPropertyValue("Width") >>= nWidth)
+ nDocWidth = nWidth;
+ if (xDefaultPagePropertySet->getPropertyValue("Height") >>= nHeight)
+ nDocHeight = nHeight;
}
if(mbExportShapeSelection)
@@ -862,7 +1018,7 @@ bool SVGFilter::implExportDocument()
aObjects[ nPos++ ] = elem.second;
}
- mpSVGFontExport = new SVGFontExport( *mpSVGExport, aObjects );
+ mpSVGFontExport = new SVGFontExport( *mpSVGExport, std::move(aObjects) );
mpSVGWriter = new SVGActionWriter( *mpSVGExport, *mpSVGFontExport );
if( mpSVGExport->IsEmbedFonts() )
@@ -874,10 +1030,15 @@ bool SVGFilter::implExportDocument()
implExportTextShapeIndex();
implEmbedBulletGlyphs();
implExportTextEmbeddedBitmaps();
+ implExportBackgroundBitmaps();
+ mpSVGWriter->SetEmbeddedBitmapRefs( &maBitmapActionMap );
+ implExportTiledBackground();
}
+ if( mbIsPreview )
+ mpSVGWriter->SetPreviewMode();
// #i124608# export a given object selection, so no MasterPage export at all
- if (!mbExportShapeSelection)
+ if (!mbExportShapeSelection && !mMasterPageTargets.empty())
implExportMasterPages( mMasterPageTargets, 0, mMasterPageTargets.size() - 1 );
implExportDrawPages( mSelectedPages, 0, nLastPage );
@@ -947,6 +1108,7 @@ void SVGFilter::implExportDocumentHeaderImpressOrDraw(sal_Int32 nDocX, sal_Int32
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xmlns:presentation", "http://sun.com/xmlns/staroffice/presentation" );
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xmlns:smil", "http://www.w3.org/2001/SMIL20/" );
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xmlns:anim", "urn:oasis:names:tc:opendocument:xmlns:animation:1.0" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xmlns:svg", "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" );
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xml:space", "preserve" );
mpSVGDoc = new SvXMLElementExport( *mpSVGExport, XML_NAMESPACE_NONE, "svg", true, true );
@@ -1058,20 +1220,20 @@ void SVGFilter::implGenerateMetaData()
// we wrap all meta presentation info into a svg:defs element
SvXMLElementExport aDefsElem( *mpSVGExport, XML_NAMESPACE_NONE, "defs", true, true );
- mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", NSPREFIX "meta_slides" );
- mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "number-of-slides", OUString::number( nCount ) );
- mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "start-slide-number", OUString::number( mnVisiblePage ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", NSPREFIX "meta_slides"_ustr );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "number-of-slides"_ustr, OUString::number( nCount ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "start-slide-number"_ustr, OUString::number( mnVisiblePage ) );
if( mpSVGExport->IsUsePositionedCharacters() )
{
- mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "use-positioned-chars", "true" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "use-positioned-chars"_ustr, "true" );
}
// Add a (global) Page Numbering Type attribute for the document
// NOTE: at present pSdrModel->GetPageNumType() returns always css::style::NumberingType::ARABIC
// so the following code fragment is pretty useless
sal_Int32 nPageNumberingType = css::style::NumberingType::ARABIC;
- SvxDrawPage* pSvxDrawPage = comphelper::getUnoTunnelImplementation<SvxDrawPage>( mSelectedPages[0] );
+ SvxDrawPage* pSvxDrawPage = comphelper::getFromUnoTunnel<SvxDrawPage>( mSelectedPages[0] );
if( pSvxDrawPage )
{
SdrPage* pSdrPage = pSvxDrawPage->GetSdrPage();
@@ -1105,20 +1267,20 @@ void SVGFilter::implGenerateMetaData()
break;
}
if( !sNumberingType.isEmpty() )
- mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "page-numbering-type", sNumberingType );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "page-numbering-type"_ustr, sNumberingType );
}
{
SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
- const OUString aId( NSPREFIX "meta_slide" );
+ const OUString aId( NSPREFIX "meta_slide"_ustr );
const OUString aElemTextFieldId( aOOOElemTextField );
std::vector< std::unique_ptr<TextField> > aFieldSet;
// dummy slide - used as leaving slide for transition on the first slide
if( mbPresentation )
{
- mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", NSPREFIX "meta_dummy_slide" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", NSPREFIX "meta_dummy_slide"_ustr );
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrSlide, "dummy-slide" );
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrMaster, "dummy-master-page" );
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrBackgroundVisibility, "hidden" );
@@ -1131,6 +1293,8 @@ void SVGFilter::implGenerateMetaData()
{
const Reference< css::drawing::XDrawPage > & xDrawPage = mSelectedPages[i];
Reference< css::drawing::XMasterPageTarget > xMasterPageTarget( xDrawPage, UNO_QUERY );
+ if (!xMasterPageTarget.is())
+ continue;
Reference< css::drawing::XDrawPage > xMasterPage = xMasterPageTarget->getMasterPage();
OUString aSlideId(aId + "_" + OUString::number( i ));
@@ -1145,6 +1309,12 @@ void SVGFilter::implGenerateMetaData()
if( xPropSet.is() )
{
+ OUString sDisplayName;
+ if (xPropSet->getPropertyValue("LinkDisplayName") >>= sDisplayName)
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrDisplayName, sDisplayName);
+ }
+
bool bBackgroundVisibility = true; // default: visible
bool bBackgroundObjectsVisibility = true; // default: visible
@@ -1152,12 +1322,24 @@ void SVGFilter::implGenerateMetaData()
VariableDateTimeField aVariableDateTimeField;
FooterField aFooterField;
+ // check if the slide has a custom background which overlaps the master page background
+ Reference< XPropertySet > xBackground;
+ xPropSet->getPropertyValue( "Background" ) >>= xBackground;
+ if( xBackground.is() )
+ {
+ drawing::FillStyle aFillStyle;
+ bool assigned = ( xBackground->getPropertyValue( "FillStyle" ) >>= aFillStyle );
+ // has a custom background ?
+ if( assigned && aFillStyle != drawing::FillStyle_NONE )
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrHasCustomBackground, "true" );
+ }
+
xPropSet->getPropertyValue( "IsBackgroundVisible" ) >>= bBackgroundVisibility;
// in case the attribute is set to its default value it is not appended to the meta-slide element
if( !bBackgroundVisibility ) // visibility default value: 'visible'
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrBackgroundVisibility, "hidden" );
- // Page Number, Date/Time, Footer and Header Fields are regarded as background objects.
+ // Page Number, DateTime, Footer and Header Fields are regarded as background objects.
// So bBackgroundObjectsVisibility overrides visibility of master page text fields.
xPropSet->getPropertyValue( "IsBackgroundObjectsVisible" ) >>= bBackgroundObjectsVisibility;
if( bBackgroundObjectsVisibility ) // visibility default value: 'visible'
@@ -1171,50 +1353,44 @@ void SVGFilter::implGenerateMetaData()
bPageNumberVisibility = bPageNumberVisibility && ( nPageNumberingType != css::style::NumberingType::NUMBER_NONE );
if( bPageNumberVisibility ) // visibility default value: 'hidden'
{
- mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "page-number-visibility", "visible" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "page-number-visibility"_ustr, "visible" );
}
- // Date/Time Field
- xPropSet->getPropertyValue( "IsDateTimeVisible" ) >>= bDateTimeVisibility;
- if( bDateTimeVisibility ) // visibility default value: 'visible'
+ // DateTime Field
+ bool bDateTimeFixed = true; // default: fixed
+ xPropSet->getPropertyValue( "IsDateTimeFixed" ) >>= bDateTimeFixed;
+ if( bDateTimeFixed ) // we are interested only in the field text not in the date/time format
{
- bool bDateTimeFixed = true; // default: fixed
- xPropSet->getPropertyValue( "IsDateTimeFixed" ) >>= bDateTimeFixed;
- if( bDateTimeFixed ) // we are interested only in the field text not in the date/time format
+ xPropSet->getPropertyValue( "DateTimeText" ) >>= aFixedDateTimeField.text;
+ if( !aFixedDateTimeField.text.isEmpty() )
{
- xPropSet->getPropertyValue( "DateTimeText" ) >>= aFixedDateTimeField.text;
- if( !aFixedDateTimeField.text.isEmpty() )
- {
- OUString sFieldId = implGenerateFieldId( aFieldSet, aFixedDateTimeField, aElemTextFieldId, xMasterPage );
- mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrDateTimeField, sFieldId );
- }
- }
- else // the inverse applies: we are interested only in the date/time format not in the field text
- {
- xPropSet->getPropertyValue( "DateTimeFormat" ) >>= aVariableDateTimeField.format;
- OUString sFieldId = implGenerateFieldId( aFieldSet, aVariableDateTimeField, aElemTextFieldId, xMasterPage );
+ OUString sFieldId = implGenerateFieldId( aFieldSet, aFixedDateTimeField, aElemTextFieldId, xMasterPage );
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrDateTimeField, sFieldId );
}
}
- else
+ else // the inverse applies: we are interested only in the date/time format not in the field text
{
- mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "date-time-visibility", "hidden" );
+ xPropSet->getPropertyValue( "DateTimeFormat" ) >>= aVariableDateTimeField.format;
+ OUString sFieldId = implGenerateFieldId( aFieldSet, aVariableDateTimeField, aElemTextFieldId, xMasterPage );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrDateTimeField, sFieldId );
+ }
+ xPropSet->getPropertyValue( "IsDateTimeVisible" ) >>= bDateTimeVisibility;
+ if( !bDateTimeVisibility ) // visibility default value: 'visible'
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "date-time-visibility"_ustr, "hidden" );
}
// Footer Field
- xPropSet->getPropertyValue( "IsFooterVisible" ) >>= bFooterVisibility;
- if( bFooterVisibility ) // visibility default value: 'visible'
+ xPropSet->getPropertyValue( "FooterText" ) >>= aFooterField.text;
+ if( !aFooterField.text.isEmpty() )
{
- xPropSet->getPropertyValue( "FooterText" ) >>= aFooterField.text;
- if( !aFooterField.text.isEmpty() )
- {
- OUString sFieldId = implGenerateFieldId( aFieldSet, aFooterField, aElemTextFieldId, xMasterPage );
- mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrFooterField, sFieldId );
- }
+ OUString sFieldId = implGenerateFieldId( aFieldSet, aFooterField, aElemTextFieldId, xMasterPage );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrFooterField, sFieldId );
}
- else
+ xPropSet->getPropertyValue( "IsFooterVisible" ) >>= bFooterVisibility;
+ if( !bFooterVisibility ) // visibility default value: 'visible'
{
- mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "footer-visibility", "hidden" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "footer-visibility"_ustr, "hidden" );
}
}
else
@@ -1260,9 +1436,9 @@ void SVGFilter::implGenerateMetaData()
{
for( sal_Int32 i = 0, nSize = aFieldSet.size(); i < nSize; ++i )
{
- OUString sElemId = OUStringLiteral(aOOOElemTextField) + "_" + OUString::number( i );
+ OUString sElemId = OUString::Concat(aOOOElemTextField) + "_" + OUString::number( i );
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sElemId );
- aFieldSet[i]->elementExport( mpSVGExport );
+ aFieldSet[i]->elementExport( mpSVGExport.get() );
}
if( mpSVGExport->IsEmbedFonts() && mpSVGExport->IsUsePositionedCharacters() )
{
@@ -1350,7 +1526,7 @@ void SVGFilter::implExportTextShapeIndex()
for( sal_Int32 i = 0; i < nCount; ++i )
{
const Reference< css::drawing::XDrawPage > & xDrawPage = mSelectedPages[i];
- if( mTextShapeIdListMap.find( xDrawPage ) != mTextShapeIdListMap.end() )
+ if( mTextShapeIdListMap.contains(xDrawPage) )
{
OUString sTextShapeIdList = mTextShapeIdListMap[xDrawPage].trim();
@@ -1358,7 +1534,7 @@ void SVGFilter::implExportTextShapeIndex()
if( !rPageId.isEmpty() && !sTextShapeIdList.isEmpty() )
{
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrSlide, rPageId );
- mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "id-list", sTextShapeIdList );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "id-list"_ustr, sTextShapeIdList );
SvXMLElementExport aGElem( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
}
}
@@ -1408,8 +1584,105 @@ void SVGFilter::implEmbedBulletGlyph( sal_Unicode cBullet, const OUString & sPat
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "d", sPathData );
SvXMLElementExport aPathElem( *mpSVGExport, XML_NAMESPACE_NONE, "path", true, true );
+ mpSVGExport->SetEmbeddedBulletGlyph(cBullet);
+}
+
+void SVGFilter::implExportBackgroundBitmaps()
+{
+ if (maBitmapActionMap.empty())
+ return;
+
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "BackgroundBitmaps" );
+ SvXMLElementExport aDefsContainerElem( *mpSVGExport, XML_NAMESPACE_NONE, "defs", true, true );
+
+ OUString sId;
+ for( const auto& rItem : maBitmapActionMap )
+ {
+ BitmapChecksum nChecksum = rItem.first;
+ const GDIMetaFile& aEmbeddedBitmapMtf = *(rItem.second);
+ MetaAction* pBitmapAction = aEmbeddedBitmapMtf.GetAction( 0 );
+ if( pBitmapAction )
+ {
+ sId = "bitmap(" + OUString::number( nChecksum ) + ")";
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sId );
+
+ const Point aPos; // (0, 0)
+ const Size aSize = aEmbeddedBitmapMtf.GetPrefSize();
+ mpSVGWriter->WriteMetaFile( aPos, aSize, aEmbeddedBitmapMtf, 0xffffffff );
+ }
+ }
}
+void SVGFilter::implExportTiledBackground()
+{
+ if( maPatterProps.empty() )
+ return;
+
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "BackgroundPatterns" );
+ SvXMLElementExport aDefsContainerElem( *mpSVGExport, XML_NAMESPACE_NONE, "defs", true, true );
+
+ for( const auto& [ rSlideId, rData ] : maPatterProps )
+ {
+ auto aBitmapActionIt = maBitmapActionMap.find( rData.aBitmapChecksum );
+ if( aBitmapActionIt != maBitmapActionMap.end() )
+ {
+ // pattern element attributes
+ const OUString sPatternId = getPatternIdForTiledBackground( rSlideId, rData.aBitmapChecksum );
+ // <pattern> <use>
+ {
+ // pattern element attributes
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sPatternId );
+
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "x", OUString::number( rData.aPos.X() ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "y", OUString::number( rData.aPos.Y() ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "width", OUString::number( rData.aSize.Width() ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "height", OUString::number( rData.aSize.Height() ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "patternUnits", "userSpaceOnUse" );
+
+ SvXMLElementExport aPatternElem( *mpSVGExport, XML_NAMESPACE_NONE, "pattern", true, true );
+
+ // use element attributes
+ const Size& aOrigSize = aBitmapActionIt->second->GetPrefSize();
+ OUString sTransform;
+ Fraction aFractionX( rData.aSize.Width(), aOrigSize.Width() );
+ Fraction aFractionY( rData.aSize.Height(), aOrigSize.Height() );
+ double scaleX = rtl_math_round( double(aFractionX), 3, rtl_math_RoundingMode::rtl_math_RoundingMode_Corrected );
+ double scaleY = rtl_math_round( double(aFractionY), 3, rtl_math_RoundingMode::rtl_math_RoundingMode_Corrected );
+ if( !rtl_math_approxEqual( scaleX, 1.0 ) || !rtl_math_approxEqual( scaleY, 1.0 ) )
+ sTransform += " scale(" + OUString::number( double(aFractionX) ) + ", " + OUString::number( double(aFractionY) ) + ")";
+
+ if( !sTransform.isEmpty() )
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "transform", sTransform );
+
+ // referenced bitmap
+ OUString sRefId = "#bitmap(" + OUString::number( rData.aBitmapChecksum ) + ")";
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xlink:href", sRefId );
+
+ SvXMLElementExport aUseElem( *mpSVGExport, XML_NAMESPACE_NONE, "use", true, true );
+ } // </use> </pattern>
+
+ // <g> <rect>
+ {
+ // group
+ const OUString sBgId = getIdForTiledBackground( rSlideId, rData.aBitmapChecksum );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sBgId );
+
+ SvXMLElementExport aGroupElem( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+
+ // rectangle
+ const OUString sUrl = "url(#" + sPatternId + ")";
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "x", "0" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "y", "0" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "width", OUString::number( rData.aSlideSize.Width() ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "height", OUString::number( rData.aSlideSize.Height() ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "stroke", "none" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "fill", sUrl );
+
+ SvXMLElementExport aRectElem( *mpSVGExport, XML_NAMESPACE_NONE, "rect", true, true );
+ } // </g> </rect>
+ }
+ }
+}
/** SVGFilter::implExportTextEmbeddedBitmaps
We export bitmaps embedded into text shapes, such as those used by list
@@ -1549,7 +1822,7 @@ void SVGFilter::implGetPagePropSet( const Reference< css::drawing::XDrawPage > &
if( mVisiblePagePropSet.bIsPageNumberFieldVisible )
{
- SvxDrawPage* pSvxDrawPage = comphelper::getUnoTunnelImplementation<SvxDrawPage>( rxPage );
+ SvxDrawPage* pSvxDrawPage = comphelper::getFromUnoTunnel<SvxDrawPage>( rxPage );
if( pSvxDrawPage )
{
SdrPage* pSdrPage = pSvxDrawPage->GetSdrPage();
@@ -1636,25 +1909,21 @@ void SVGFilter::implExportDrawPages( const std::vector< Reference< css::drawing:
}
}
- if(!mbExportShapeSelection)
+ if (!mbExportShapeSelection)
{
// We wrap all slide in a group element with class name "SlideGroup".
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "SlideGroup" );
SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+ if (mxStatusIndicator)
+ mxStatusIndicator->start(FilterResId(STR_FILTER_DOC_SAVING), nLastPage - nFirstPage + 1);
+
for( sal_Int32 i = nFirstPage; i <= nLastPage; ++i )
{
- Reference< css::drawing::XShapes > xShapes;
+ if (mxStatusIndicator.is())
+ mxStatusIndicator->setValue(i - nFirstPage);
- if (mbExportShapeSelection)
- {
- // #i124608# export a given object selection
- xShapes = maShapeSelection;
- }
- else
- {
- xShapes = rxPages[i];
- }
+ Reference<css::drawing::XShapes> xShapes = rxPages[i];
if( xShapes.is() )
{
@@ -1697,6 +1966,9 @@ void SVGFilter::implExportDrawPages( const std::vector< Reference< css::drawing:
} // append the </g> closing tag related to inserted elements
} // append the </g> closing tag related to the svg element handling the slide visibility
}
+
+ if (mxStatusIndicator)
+ mxStatusIndicator->end();
}
else
{
@@ -1746,34 +2018,47 @@ bool SVGFilter::implExportPage( std::u16string_view sPageId,
const GDIMetaFile& rMtf = (*mpObjects)[ rxPage ].GetRepresentation();
if( rMtf.GetActionSize() )
{
- // background id = "bg-" + page id
- OUString sBackgroundId = OUString::Concat("bg-") + sPageId;
- mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sBackgroundId );
-
- // At present (LibreOffice 3.4.0) the 'IsBackgroundVisible' property is not handled
- // by Impress; anyway we handle this property as referring only to the visibility
- // of the master page background. So if a slide has its own background object,
- // the visibility of such a background object is always inherited from the visibility
- // of the parent slide regardless of the value of the 'IsBackgroundVisible' property.
- // This means that we need to set up the visibility attribute only for the background
- // element of a master page.
- if( !mbPresentation && bMaster )
+ // If this is not a master page wrap the slide custom background
+ // by a <defs> element.
+ // Slide custom background, if any, is referenced at a different position
+ // in order to not overlap background objects.
+ std::unique_ptr<SvXMLElementExport> xDefsExp;
+ if (!bMaster) // insert the <defs> open tag related to the slide background
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "SlideBackground" );
+ xDefsExp.reset( new SvXMLElementExport( *mpSVGExport, XML_NAMESPACE_NONE, "defs", true, true ) );
+ }
{
- if( !mVisiblePagePropSet.bIsBackgroundVisible )
+ // background id = "bg-" + page id
+ OUString sBackgroundId = OUString::Concat("bg-") + sPageId;
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sBackgroundId );
+
+ // At present (LibreOffice 3.4.0) the 'IsBackgroundVisible' property is not handled
+ // by Impress; anyway we handle this property as referring only to the visibility
+ // of the master page background. So if a slide has its own background object,
+ // the visibility of such a background object is always inherited from the visibility
+ // of the parent slide regardless of the value of the 'IsBackgroundVisible' property.
+ // This means that we need to set up the visibility attribute only for the background
+ // element of a master page.
+ if( !mbPresentation && bMaster )
{
- mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "visibility", "hidden" );
+ if( !mVisiblePagePropSet.bIsBackgroundVisible )
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "visibility", "hidden" );
+ }
}
- }
- mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "Background" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "Background" );
- // insert the <g> open tag related to the Background
- SvXMLElementExport aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+ // insert the <g> open tag related to the Background
+ SvXMLElementExport aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+
+ // append all elements that make up the Background
+ const Point aNullPt;
+ mpSVGWriter->WriteMetaFile( aNullPt, rMtf.GetPrefSize(), rMtf, SVGWRITER_WRITE_FILL );
+ } // insert the </g> closing tag related to the Background
- // append all elements that make up the Background
- const Point aNullPt;
- mpSVGWriter->WriteMetaFile( aNullPt, rMtf.GetPrefSize(), rMtf, SVGWRITER_WRITE_FILL );
- } // insert the </g> closing tag related to the Background
+ } // insert the </defs> closing tag related to the slide background
}
// In case we are dealing with a master page we need to group all its shapes
@@ -1881,20 +2166,25 @@ bool SVGFilter::implExportShape( const Reference< css::drawing::XShape >& rxShap
if( rMtf.GetActionSize() )
{ // for text field shapes we set up text-adjust attributes
// and set visibility to hidden
- const OUString* pElementId = nullptr;
+ OUString aElementId;
+
if( mbPresentation )
{
- bool bIsPageNumber = ( aShapeClass == "Slide_Number" );
+ bool bIsPageNumber = ( aShapeClass == "PageNumber" );
bool bIsFooter = ( aShapeClass == "Footer" );
- bool bIsDateTime = ( aShapeClass == "Date/Time" );
- if( bIsPageNumber || bIsDateTime || bIsFooter )
+ bool bIsDateTime = ( aShapeClass == "DateTime" );
+ bool bTextField = bIsPageNumber || bIsFooter || bIsDateTime;
+ if( bTextField )
{
// to notify to the SVGActionWriter::ImplWriteActions method
// that we are dealing with a placeholder shape
- pElementId = &sPlaceholderTag;
+ aElementId = sPlaceholderTag;
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "visibility", "hidden" );
+ }
+ if( bTextField || ( aShapeClass == "TextShape" ) )
+ {
sal_uInt16 nTextAdjust = sal_uInt16(ParagraphAdjust_LEFT);
OUString sTextAdjust;
xShapePropSet->getPropertyValue( "ParaAdjust" ) >>= nTextAdjust;
@@ -1913,7 +2203,7 @@ bool SVGFilter::implExportShape( const Reference< css::drawing::XShape >& rxShap
default:
break;
}
- mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "text-adjust", sTextAdjust );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "text-adjust"_ustr, sTextAdjust );
}
}
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", aShapeClass );
@@ -1982,7 +2272,7 @@ bool SVGFilter::implExportShape( const Reference< css::drawing::XShape >& rxShap
SvXMLElementExport alinkA( *mpSVGExport, XML_NAMESPACE_NONE, "a", true, true );
mpSVGWriter->WriteMetaFile( aTopLeft, aSize, rMtf,
0xffffffff,
- pElementId,
+ aElementId,
&rxShape,
pEmbeddedBitmapsMtf );
}
@@ -1991,7 +2281,7 @@ bool SVGFilter::implExportShape( const Reference< css::drawing::XShape >& rxShap
{
mpSVGWriter->WriteMetaFile( aTopLeft, aSize, rMtf,
0xffffffff,
- pElementId,
+ aElementId,
&rxShape,
pEmbeddedBitmapsMtf );
}
@@ -2046,21 +2336,19 @@ bool SVGFilter::implCreateObjects()
// implementation status:
// - hatch stroke color is set to 'none' so the hatch is not visible, why?
// - gradient look is not really awesome, too few colors are used;
- // - stretched bitmap, gradient and hatch are not exported only once
+ // - gradient and hatch are not exported only once
// and then referenced in case more than one slide uses them.
- // - tiled bitmap: an image element is exported for each tile,
- // this is really too expensive!
Reference< XPropertySet > xPropSet( xDrawPage, UNO_QUERY );
if( xPropSet.is() )
{
Reference< XPropertySet > xBackground;
- xPropSet->getPropertyValue( "Background" ) >>= xBackground;
+ if (xPropSet->getPropertySetInfo()->hasPropertyByName("Background"))
+ xPropSet->getPropertyValue( "Background" ) >>= xBackground;
if( xBackground.is() )
{
drawing::FillStyle aFillStyle;
bool assigned = ( xBackground->getPropertyValue( "FillStyle" ) >>= aFillStyle );
- if( assigned && aFillStyle != drawing::FillStyle_NONE
- && aFillStyle != drawing::FillStyle_BITMAP )
+ if( assigned && aFillStyle != drawing::FillStyle_NONE )
{
implCreateObjectsFromBackground( xDrawPage );
}
@@ -2102,11 +2390,12 @@ bool SVGFilter::implCreateObjectsFromShape( const Reference< css::drawing::XDraw
}
else
{
- SdrObject* pObj = GetSdrObjectFromXShape( rxShape );
+ SdrObject* pObj = SdrObject::getSdrObjectFromXShape(rxShape);
if( pObj )
{
- Graphic aGraphic(SdrExchangeView::GetObjGraphic(*pObj));
+ // tdf#155479 need to signal SVG export
+ Graphic aGraphic(SdrExchangeView::GetObjGraphic(*pObj, true));
// Writer graphic shapes are handled differently
if( mbWriterFilter && aGraphic.GetType() == GraphicType::NONE )
@@ -2175,8 +2464,8 @@ bool SVGFilter::implCreateObjectsFromShape( const Reference< css::drawing::XDraw
MetaAction* pAction;
bool bIsTextShapeStarted = false;
const GDIMetaFile& rMtf = aGraphic.GetGDIMetaFile();
- sal_uLong nCount = rMtf.GetActionSize();
- for( sal_uLong nCurAction = 0; nCurAction < nCount; ++nCurAction )
+ size_t nCount = rMtf.GetActionSize();
+ for( size_t nCurAction = 0; nCurAction < nCount; ++nCurAction )
{
pAction = rMtf.GetAction( nCurAction );
const MetaActionType nType = pAction->GetType();
@@ -2227,24 +2516,122 @@ void SVGFilter::implCreateObjectsFromBackground( const Reference< css::drawing::
GDIMetaFile aMtf;
- utl::TempFile aFile;
- aFile.EnableKillingFile();
+ utl::TempFileFast aFile;
+ SvStream* pStream = aFile.GetStream(StreamMode::READWRITE);
- Sequence< PropertyValue > aDescriptor( 3 );
- aDescriptor[0].Name = "FilterName";
- aDescriptor[0].Value <<= OUString( "SVM" );
- aDescriptor[1].Name = "URL";
- aDescriptor[1].Value <<= aFile.GetURL();
- aDescriptor[2].Name = "ExportOnlyBackground";
- aDescriptor[2].Value <<= true;
+ Sequence< PropertyValue > aDescriptor{
+ comphelper::makePropertyValue("FilterName", OUString( "SVM" )),
+ comphelper::makePropertyValue("OutputStream", uno::Reference<XOutputStream>(new utl::OOutputStreamWrapper(*pStream))),
+ comphelper::makePropertyValue("ExportOnlyBackground", true)
+ };
xExporter->setSourceDocument( Reference< XComponent >( rxDrawPage, UNO_QUERY ) );
xExporter->filter( aDescriptor );
- aMtf.Read( *aFile.GetStream( StreamMode::READ ) );
+ pStream->Seek(0);
+ SvmReader aReader( *pStream );
+ aReader.Read( aMtf );
- (*mpObjects)[ rxDrawPage ] = ObjectRepresentation( rxDrawPage, aMtf );
-}
+ bool bIsBitmap = false;
+ bool bIsTiled = false;
+
+ // look for background type
+ Reference< XPropertySet > xPropSet( rxDrawPage, UNO_QUERY );
+ if( xPropSet.is() )
+ {
+ Reference< XPropertySet > xBackground;
+ xPropSet->getPropertyValue( "Background" ) >>= xBackground;
+ if( xBackground.is() )
+ {
+ drawing::FillStyle aFillStyle;
+ if( xBackground->getPropertyValue( "FillStyle" ) >>= aFillStyle )
+ {
+ if( aFillStyle == drawing::FillStyle::FillStyle_BITMAP )
+ {
+ bIsBitmap = true;
+ xBackground->getPropertyValue( "FillBitmapTile" ) >>= bIsTiled;
+
+ // we do not handle tiled background with a row or column offset
+ sal_Int32 nFillBitmapOffsetX = 0, nFillBitmapOffsetY = 0;
+ xBackground->getPropertyValue( "FillBitmapOffsetX" ) >>= nFillBitmapOffsetX;
+ xBackground->getPropertyValue( "FillBitmapOffsetY" ) >>= nFillBitmapOffsetY;
+ bIsTiled = bIsTiled && ( nFillBitmapOffsetX == 0 && nFillBitmapOffsetY == 0 );
+ }
+ }
+ }
+ }
+
+ if( !bIsBitmap )
+ {
+ (*mpObjects)[ rxDrawPage ] = ObjectRepresentation( rxDrawPage, aMtf );
+ return;
+ }
+
+ GDIMetaFile aTiledMtf;
+ bool bBitmapFound = false;
+ MetaAction* pAction;
+ size_t nCount = aMtf.GetActionSize();
+ for( size_t nCurAction = 0; nCurAction < nCount; ++nCurAction )
+ {
+ pAction = aMtf.GetAction( nCurAction );
+ const MetaActionType nType = pAction->GetType();
+ // collect bitmap
+ if( nType == MetaActionType::BMPSCALE || nType == MetaActionType::BMPEXSCALE )
+ {
+ if( bBitmapFound )
+ continue;
+ bBitmapFound = true; // the subsequent bitmaps are still the same just translated
+
+ BitmapChecksum nChecksum = GetBitmapChecksum( pAction );
+ if( maBitmapActionMap.find( nChecksum ) == maBitmapActionMap.end() )
+ {
+ Point aPos; // (0, 0)
+ Size aSize;
+ MetaBitmapActionGetOrigSize( pAction, aSize );
+ MetaAction* pBitmapAction = CreateMetaBitmapAction( pAction, aPos, aSize );
+ if( pBitmapAction )
+ {
+ GDIMetaFile* pEmbeddedBitmapMtf = new GDIMetaFile();
+ pEmbeddedBitmapMtf->AddAction( pBitmapAction );
+ pEmbeddedBitmapMtf->SetPrefSize( aSize );
+ pEmbeddedBitmapMtf->SetPrefMapMode( MapMode(MapUnit::Map100thMM) );
+
+ maBitmapActionMap[ nChecksum ].reset( pEmbeddedBitmapMtf );
+ }
+ }
+
+ if( bIsTiled )
+ {
+ // collect data for <pattern> and <rect>
+ const OUString & sPageId = implGetValidIDFromInterface( rxDrawPage );
+ Point aPos;
+ MetaBitmapActionGetPoint( pAction, aPos );
+ Size aSize;
+ MetaBitmapActionGetSize( pAction, aSize );
+
+ sal_Int32 nSlideWidth = 0, nSlideHeight = 0;
+ xPropSet->getPropertyValue( "Width" ) >>= nSlideWidth;
+ xPropSet->getPropertyValue( "Height" ) >>= nSlideHeight;
+
+ maPatterProps[ sPageId ] = { nChecksum, aPos, aSize, { nSlideWidth, nSlideHeight } };
+
+ // create meta comment action that is used to exporting
+ // a <use> element which points to the group element representing the background
+ const OUString sBgId = getIdForTiledBackground( sPageId, nChecksum );
+ OString sComment = sTiledBackgroundTag + " " + sBgId.toUtf8();
+ MetaCommentAction* pCommentAction = new MetaCommentAction( sComment );
+ if( pCommentAction )
+ aTiledMtf.AddAction( pCommentAction );
+ }
+ }
+ else if( bIsTiled && nType != MetaActionType::CLIPREGION )
+ {
+ aTiledMtf.AddAction( pAction );
+ }
+ }
+
+ (*mpObjects)[ rxDrawPage ] = ObjectRepresentation( rxDrawPage, bIsTiled ? aTiledMtf : aMtf );
+}
OUString SVGFilter::implGetClassFromShape( const Reference< css::drawing::XShape >& rxShape )
{
@@ -2257,14 +2644,16 @@ OUString SVGFilter::implGetClassFromShape( const Reference< css::drawing::XShape
aRet = "Graphic";
else if( aShapeType.lastIndexOf( "drawing.OLE2Shape" ) != -1 )
aRet = "OLE2";
+ else if( aShapeType.lastIndexOf( "drawing.TextShape" ) != -1 )
+ aRet = "TextShape";
else if( aShapeType.lastIndexOf( "presentation.HeaderShape" ) != -1 )
aRet = "Header";
else if( aShapeType.lastIndexOf( "presentation.FooterShape" ) != -1 )
aRet = "Footer";
else if( aShapeType.lastIndexOf( "presentation.DateTimeShape" ) != -1 )
- aRet = "Date/Time";
+ aRet = "DateTime";
else if( aShapeType.lastIndexOf( "presentation.SlideNumberShape" ) != -1 )
- aRet = "Slide_Number";
+ aRet = "PageNumber";
else if( aShapeType.lastIndexOf( "presentation.TitleTextShape" ) != -1 )
aRet = "TitleText";
else if( aShapeType.lastIndexOf( "presentation.OutlinerShape" ) != -1 )
@@ -2311,7 +2700,7 @@ IMPL_LINK( SVGFilter, CalcFieldHdl, EditFieldInfo*, pInfo, void )
{
// to notify to the SVGActionWriter::ImplWriteText method
// that we are dealing with a placeholder shape
- OUStringBuffer aRepresentation = sPlaceholderTag;
+ OUStringBuffer aRepresentation(sPlaceholderTag);
if( !mCreateOjectsCurrentMasterPage.is() )
{
@@ -2320,9 +2709,9 @@ IMPL_LINK( SVGFilter, CalcFieldHdl, EditFieldInfo*, pInfo, void )
}
bool bHasCharSetMap = mTextFieldCharSets.find( mCreateOjectsCurrentMasterPage ) != mTextFieldCharSets.end();
- static const OUString aHeaderId( NSPREFIX "header-field" );
- static const OUString aFooterId( aOOOAttrFooterField );
- static const OUString aDateTimeId( aOOOAttrDateTimeField );
+ static constexpr OUString aHeaderId( NSPREFIX "header-field"_ustr );
+ static constexpr OUString aFooterId( aOOOAttrFooterField );
+ static constexpr OUString aDateTimeId( aOOOAttrDateTimeField );
static const OUString aVariableDateTimeId( aOOOAttrDateTimeField + "-variable" );
const UCharSet * pCharSet = nullptr;
@@ -2429,7 +2818,7 @@ IMPL_LINK( SVGFilter, CalcFieldHdl, EditFieldInfo*, pInfo, void )
// nothing to do here, we always collect the characters needed for these cases.
break;
}
- aRepresentation.append( sDate.makeStringAndClear() );
+ aRepresentation.append( sDate );
}
}
}
@@ -2521,7 +2910,7 @@ void SVGExport::writeMtf( const GDIMetaFile& rMtf )
std::vector< ObjectRepresentation > aObjects;
aObjects.emplace_back( Reference< XInterface >(), rMtf );
- SVGFontExport aSVGFontExport( *this, aObjects );
+ SVGFontExport aSVGFontExport( *this, std::move(aObjects) );
Point aPoint100thmm( OutputDevice::LogicToLogic(rMtf.GetPrefMapMode().GetOrigin(), rMtf.GetPrefMapMode(), MapMode(MapUnit::Map100thMM)) );
Size aSize100thmm( OutputDevice::LogicToLogic(rMtf.GetPrefSize(), rMtf.GetPrefMapMode(), MapMode(MapUnit::Map100thMM)) );
@@ -2532,4 +2921,15 @@ void SVGExport::writeMtf( const GDIMetaFile& rMtf )
}
}
+void SVGExport::SetEmbeddedBulletGlyph(sal_Unicode cBullet)
+{
+ maEmbeddedBulletGlyphs.insert(cBullet);
+}
+
+bool SVGExport::IsEmbeddedBulletGlyph(sal_Unicode cBullet) const
+{
+ auto it = maEmbeddedBulletGlyphs.find(cBullet);
+ return it != maEmbeddedBulletGlyphs.end();
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */