/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2008 by Sun Microsystems, Inc. * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: svgexport.cxx,v $ * $Revision: 1.12.62.15 $ * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_filter.hxx" #define ITEMID_FIELD 0 #include "svgwriter.hxx" #include "svgfontexport.hxx" #include "svgfilter.hxx" #include "impsvgdialog.hxx" #include #include #include #include #include #include #include #include using ::rtl::OUString; // ------------- // - SVGExport - // ------------- SVGExport::SVGExport( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory, const Reference< XDocumentHandler >& rxHandler, const Sequence< PropertyValue >& rFilterData ) : SvXMLExport( xServiceFactory, MAP_100TH_MM ), mrFilterData( rFilterData ) { SetDocHandler( rxHandler ); GetDocHandler()->startDocument(); } // ----------------------------------------------------------------------------- SVGExport::~SVGExport() { GetDocHandler()->endDocument(); } // ----------------------------------------------------------------------------- sal_Bool SVGExport::IsUseTinyProfile() const { sal_Bool bRet = sal_False; if( mrFilterData.getLength() > 0 ) mrFilterData[ 0 ].Value >>= bRet; return bRet; } // ----------------------------------------------------------------------------- sal_Bool SVGExport::IsEmbedFonts() const { sal_Bool bRet = sal_False; if( mrFilterData.getLength() > 1 ) mrFilterData[ 1 ].Value >>= bRet; return bRet; } // ----------------------------------------------------------------------------- sal_Bool SVGExport::IsUseNativeTextDecoration() const { sal_Bool bRet = !IsUseTinyProfile(); if( bRet && ( mrFilterData.getLength() > 2 ) ) mrFilterData[ 2 ].Value >>= bRet; return bRet; } // ----------------------------------------------------------------------------- ::rtl::OUString SVGExport::GetGlyphPlacement() const { ::rtl::OUString aRet; if( mrFilterData.getLength() > 3 ) mrFilterData[ 3 ].Value >>= aRet; else aRet = B2UCONST( "abs" ); return aRet; } // ----------------------------------------------------------------------------- sal_Bool SVGExport::IsUseOpacity() const { sal_Bool bRet = !IsUseTinyProfile(); if( !bRet && ( mrFilterData.getLength() > 4 ) ) mrFilterData[ 4 ].Value >>= bRet; return bRet; } // ----------------------------------------------------------------------------- sal_Bool SVGExport::IsUseGradient() const { sal_Bool bRet = !IsUseTinyProfile(); if( !bRet && ( mrFilterData.getLength() > 5 ) ) mrFilterData[ 5 ].Value >>= bRet; return bRet; } // ----------------------------------------------------------------------------- void SVGExport::pushClip( const ::basegfx::B2DPolyPolygon& rPolyPoly ) { maClipList.push_front( ::basegfx::tools::correctOrientations( rPolyPoly ) ); } // ----------------------------------------------------------------------------- void SVGExport::popClip() { if( !maClipList.empty() ) maClipList.pop_front(); } // ----------------------------------------------------------------------------- sal_Bool SVGExport::hasClip() const { return( !maClipList.empty() ); } // ----------------------------------------------------------------------------- const ::basegfx::B2DPolyPolygon* SVGExport::getCurClip() const { return( maClipList.empty() ? NULL : &( *maClipList.begin() ) ); } // ------------------------ // - ObjectRepresentation - // ------------------------ ObjectRepresentation::ObjectRepresentation() : mpMtf( NULL ) { } // ----------------------------------------------------------------------------- ObjectRepresentation::ObjectRepresentation( const Reference< XInterface >& rxObject, const GDIMetaFile& rMtf ) : mxObject( rxObject ), mpMtf( new GDIMetaFile( rMtf ) ) { } // ----------------------------------------------------------------------------- ObjectRepresentation::ObjectRepresentation( const ObjectRepresentation& rPresentation ) : mxObject( rPresentation.mxObject ), mpMtf( rPresentation.mpMtf ? new GDIMetaFile( *rPresentation.mpMtf ) : NULL ) { } // ----------------------------------------------------------------------------- ObjectRepresentation::~ObjectRepresentation() { delete mpMtf; } // ----------------------------------------------------------------------------- ObjectRepresentation& ObjectRepresentation::operator=( const ObjectRepresentation& rPresentation ) { mxObject = rPresentation.mxObject; delete mpMtf, ( mpMtf = rPresentation.mpMtf ? new GDIMetaFile( *rPresentation.mpMtf ) : NULL ); return *this; } // ----------------------------------------------------------------------------- sal_Bool ObjectRepresentation::operator==( const ObjectRepresentation& rPresentation ) const { return( ( mxObject == rPresentation.mxObject ) && ( *mpMtf == *rPresentation.mpMtf ) ); } // ------------- // - SVGFilter - // ------------- sal_Bool SVGFilter::implExport( const Sequence< PropertyValue >& rDescriptor ) throw (RuntimeException) { Reference< XMultiServiceFactory > xServiceFactory( ::comphelper::getProcessServiceFactory() ) ; Reference< XOutputStream > xOStm; SvStream* pOStm = NULL; sal_Int32 nLength = rDescriptor.getLength(); sal_Int32 nPageToExport = SVG_EXPORT_ALLPAGES; const PropertyValue* pValue = rDescriptor.getConstArray(); sal_Bool bRet = sal_False; mnMasterSlideId = mnSlideId = mnDrawingGroupId = mnDrawingId = 0; maFilterData.realloc( 0 ); for ( sal_Int32 i = 0 ; i < nLength; ++i) { if( pValue[ i ].Name.equalsAscii( "OutputStream" ) ) pValue[ i ].Value >>= xOStm; else if( pValue[ i ].Name.equalsAscii( "FileName" ) ) { ::rtl::OUString aFileName; pValue[ i ].Value >>= aFileName; pOStm = ::utl::UcbStreamHelper::CreateStream( aFileName, STREAM_WRITE | STREAM_TRUNC ); if( pOStm ) xOStm = Reference< XOutputStream >( new ::utl::OOutputStreamWrapper ( *pOStm ) ); } else if( pValue[ i ].Name.equalsAscii( "PagePos" ) ) { pValue[ i ].Value >>= nPageToExport; } else if( pValue[ i ].Name.equalsAscii( "FilterData" ) ) { pValue[ i ].Value >>= maFilterData; } } // if no filter data is given use stored/prepared ones if( !maFilterData.getLength() ) { #ifdef _SVG_USE_CONFIG FilterConfigItem aCfgItem( String( RTL_CONSTASCII_USTRINGPARAM( SVG_EXPORTFILTER_CONFIGPATH ) ) ); aCfgItem.ReadBool( String( RTL_CONSTASCII_USTRINGPARAM( SVG_PROP_TINYPROFILE ) ), sal_True ); aCfgItem.ReadBool( String( RTL_CONSTASCII_USTRINGPARAM( SVG_PROP_EMBEDFONTS ) ), sal_True ); aCfgItem.ReadBool( String( RTL_CONSTASCII_USTRINGPARAM( SVG_PROP_NATIVEDECORATION ) ), sal_False ); aCfgItem.ReadString( String( RTL_CONSTASCII_USTRINGPARAM( SVG_PROP_NATIVEDECORATION ) ), B2UCONST( "xlist" ) ); aCfgItem.ReadString( String( RTL_CONSTASCII_USTRINGPARAM( SVG_PROP_OPACITY ) ), sal_True ); aCfgItem.ReadString( String( RTL_CONSTASCII_USTRINGPARAM( SVG_PROP_GRADIENT ) ), sal_True ); maFilterData = aCfgItem.GetFilterData(); #else maFilterData.realloc( 6 ); maFilterData[ 0 ].Name = B2UCONST( SVG_PROP_TINYPROFILE ); maFilterData[ 0 ].Value <<= (sal_Bool) sal_True; // font embedding const char* pSVGDisableFontEmbedding = getenv( "SVG_DISABLE_FONT_EMBEDDING" ); maFilterData[ 1 ].Name = B2UCONST( SVG_PROP_EMBEDFONTS ); maFilterData[ 1 ].Value <<= (sal_Bool) ( pSVGDisableFontEmbedding ? sal_False : sal_True ); // Native decoration maFilterData[ 2 ].Name = B2UCONST( SVG_PROP_NATIVEDECORATION ); maFilterData[ 2 ].Value <<= (sal_Bool) sal_False; // glyph placement const char* pSVGGlyphPlacement = getenv( "SVG_GLYPH_PLACEMENT" ); maFilterData[ 3 ].Name = B2UCONST( SVG_PROP_GLYPHPLACEMENT ); if( pSVGGlyphPlacement ) maFilterData[ 3 ].Value <<= ::rtl::OUString::createFromAscii( pSVGGlyphPlacement ); else maFilterData[ 3 ].Value <<= B2UCONST( "xlist" ); // Tiny Opacity maFilterData[ 4 ].Name = B2UCONST( SVG_PROP_OPACITY ); maFilterData[ 4 ].Value <<= (sal_Bool) sal_True; // Tiny Gradient maFilterData[ 5 ].Name = B2UCONST( SVG_PROP_GRADIENT ); maFilterData[ 5 ].Value <<= (sal_Bool) sal_False; #endif } if( xOStm.is() && xServiceFactory.is() ) { Reference< XMasterPagesSupplier > xMasterPagesSupplier( mxSrcDoc, UNO_QUERY ); Reference< XDrawPagesSupplier > xDrawPagesSupplier( mxSrcDoc, UNO_QUERY ); if( xMasterPagesSupplier.is() && xDrawPagesSupplier.is() ) { Reference< XDrawPages > xMasterPages( xMasterPagesSupplier->getMasterPages(), UNO_QUERY ); Reference< XDrawPages > xDrawPages( xDrawPagesSupplier->getDrawPages(), UNO_QUERY ); if( xMasterPages.is() && xMasterPages->getCount() && xDrawPages.is() && xDrawPages->getCount() ) { Reference< XDocumentHandler > xDocHandler( implCreateExportDocumentHandler( xOStm ) ); if( xDocHandler.is() ) { mbPresentation = Reference< XPresentationSupplier >( mxSrcDoc, UNO_QUERY ).is(); mpObjects = new ObjectMap; // #110680# // mpSVGExport = new SVGExport( xDocHandler ); mpSVGExport = new SVGExport( xServiceFactory, xDocHandler, maFilterData ); if( nPageToExport < 0 || nPageToExport >= xDrawPages->getCount() ) nPageToExport = SVG_EXPORT_ALLPAGES; try { const sal_Int32 nDefaultPage = ( ( SVG_EXPORT_ALLPAGES == nPageToExport ) ? 0 : nPageToExport ); xDrawPages->getByIndex( nDefaultPage ) >>= mxDefaultPage; if( mxDefaultPage.is() ) { SvxDrawPage* pSvxDrawPage = SvxDrawPage::getImplementation( mxDefaultPage ); if( pSvxDrawPage ) { mpDefaultSdrPage = pSvxDrawPage->GetSdrPage(); mpSdrModel = mpDefaultSdrPage->GetModel(); if( mpSdrModel ) { SdrOutliner& rOutl = mpSdrModel->GetDrawOutliner(NULL); maOldFieldHdl = rOutl.GetCalcFieldValueHdl(); rOutl.SetCalcFieldValueHdl( LINK( this, SVGFilter, CalcFieldHdl) ); } } if( implCreateObjects( xMasterPages, xDrawPages, nPageToExport ) ) { ObjectMap::const_iterator aIter( mpObjects->begin() ); ::std::vector< ObjectRepresentation > aObjects( mpObjects->size() ); sal_uInt32 nPos = 0; while( aIter != mpObjects->end() ) { aObjects[ nPos++ ] = (*aIter).second; ++aIter; } mpSVGFontExport = new SVGFontExport( *mpSVGExport, aObjects ); mpSVGWriter = new SVGActionWriter( *mpSVGExport, *mpSVGFontExport ); bRet = implExportDocument( xMasterPages, xDrawPages, nPageToExport ); } } } catch( ... ) { delete mpSVGDoc, mpSVGDoc = NULL; DBG_ERROR( "Exception caught" ); } if( mpSdrModel ) mpSdrModel->GetDrawOutliner( NULL ).SetCalcFieldValueHdl( maOldFieldHdl ); delete mpSVGWriter, mpSVGWriter = NULL; delete mpSVGExport, mpSVGExport = NULL; delete mpSVGFontExport, mpSVGFontExport = NULL; delete mpObjects, mpObjects = NULL; mbPresentation = sal_False; } } } } delete pOStm; return bRet; } // ----------------------------------------------------------------------------- Reference< XDocumentHandler > SVGFilter::implCreateExportDocumentHandler( const Reference< XOutputStream >& rxOStm ) { Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() ); Reference< XDocumentHandler > xSaxWriter; if( xMgr.is() && rxOStm.is() ) { xSaxWriter = Reference< XDocumentHandler >( xMgr->createInstance( B2UCONST( "com.sun.star.xml.sax.Writer" ) ), UNO_QUERY ); if( xSaxWriter.is() ) { Reference< XActiveDataSource > xActiveDataSource( xSaxWriter, UNO_QUERY ); if( xActiveDataSource.is() ) xActiveDataSource->setOutputStream( rxOStm ); else xSaxWriter = NULL; } } return xSaxWriter; } // ----------------------------------------------------------------------------- sal_Bool SVGFilter::implExportDocument( const Reference< XDrawPages >& rxMasterPages, const Reference< XDrawPages >& rxDrawPages, sal_Int32 nPageToExport ) { DBG_ASSERT( rxMasterPages.is() && rxDrawPages.is(), "SVGFilter::implExportDocument: invalid parameter" ); OUString aAttr; sal_Int32 nDocWidth = 0, nDocHeight = 0; sal_Int32 nVisible = -1, nVisibleMaster = -1; sal_Bool bRet = sal_False; const sal_Bool bSinglePage = ( rxDrawPages->getCount() == 1 ) || ( SVG_EXPORT_ALLPAGES != nPageToExport ); const sal_Int32 nFirstPage = ( ( SVG_EXPORT_ALLPAGES == nPageToExport ) ? 0 : nPageToExport ); sal_Int32 nCurPage = nFirstPage, nLastPage = ( bSinglePage ? nFirstPage : ( rxDrawPages->getCount() - 1 ) ); const Reference< XPropertySet > xDefaultPagePropertySet( mxDefaultPage, UNO_QUERY ); const Reference< XExtendedDocumentHandler > xExtDocHandler( mpSVGExport->GetDocHandler(), UNO_QUERY ); if( xDefaultPagePropertySet.is() ) { xDefaultPagePropertySet->getPropertyValue( B2UCONST( "Width" ) ) >>= nDocWidth; xDefaultPagePropertySet->getPropertyValue( B2UCONST( "Height" ) ) >>= nDocHeight; } if( xExtDocHandler.is() && !mpSVGExport->IsUseTinyProfile() ) { xExtDocHandler->unknown( SVG_DTD_STRING ); } mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "version", B2UCONST( "1.2" ) ); if( mpSVGExport->IsUseTinyProfile() ) mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "baseProfile", B2UCONST( "tiny" ) ); #ifdef _SVG_WRITE_EXTENTS aAttr = OUString::valueOf( nDocWidth * 0.01 ); aAttr += B2UCONST( "mm" ); mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "width", aAttr ); aAttr = OUString::valueOf( nDocHeight * 0.01 ); aAttr += B2UCONST( "mm" ); mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "height", aAttr ); #endif aAttr = B2UCONST( "0 0 " ); aAttr += OUString::valueOf( nDocWidth ); aAttr += B2UCONST( " " ); aAttr += OUString::valueOf( nDocHeight ); mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "viewBox", aAttr ); mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "preserveAspectRatio", B2UCONST( "xMidYMid" ) ); mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "fill-rule", B2UCONST( "evenodd" ) ); // standard line width is based on 1 pixel on a 90 DPI device (0.28222mmm) mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "stroke-width", OUString::valueOf( 28.222 ) ); mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "stroke-linejoin", B2UCONST( "round" ) ); if( !bSinglePage ) { mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xmlns:ooo", B2UCONST( "http://xml.openoffice.org/svg/export" ) ); mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "onclick", B2UCONST( "onClick(evt)" ) ); mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "onkeypress", B2UCONST( "onKeyPress(evt)" ) ); } mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xmlns", B2UCONST( "http://www.w3.org/2000/svg" ) ); mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xmlns:xlink", B2UCONST( "http://www.w3.org/1999/xlink" ) ); mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xml:space", B2UCONST( "preserve" ) ); mpSVGDoc = new SvXMLElementExport( *mpSVGExport, XML_NAMESPACE_NONE, "svg", sal_True, sal_True ); while( ( nCurPage <= nLastPage ) && ( -1 == nVisible ) ) { Reference< XDrawPage > xDrawPage; rxDrawPages->getByIndex( nCurPage ) >>= xDrawPage; if( xDrawPage.is() ) { Reference< XPropertySet > xPropSet( xDrawPage, UNO_QUERY ); if( xPropSet.is() ) { sal_Bool bVisible = sal_False; if( !mbPresentation || bSinglePage || ( ( xPropSet->getPropertyValue( B2UCONST( "Visible" ) ) >>= bVisible ) && bVisible ) ) { Reference< XMasterPageTarget > xMasterTarget( xDrawPage, UNO_QUERY ); if( xMasterTarget.is() ) { Reference< XDrawPage > xMasterPage( xMasterTarget->getMasterPage() ); nVisible = nCurPage; for( sal_Int32 nMaster = 0, nMasterCount = rxMasterPages->getCount(); ( nMaster < nMasterCount ) && ( -1 == nVisibleMaster ); ++nMaster ) { Reference< XDrawPage > xMasterTestPage; rxMasterPages->getByIndex( nMaster ) >>= xMasterTestPage; if( xMasterTestPage == xMasterPage ) nVisibleMaster = nMaster; } } } } } ++nCurPage; } if( mpSVGExport->IsEmbedFonts() ) { mpSVGFontExport->EmbedFonts(); } if( -1 != nVisible ) { if( bSinglePage ) implExportPages( rxMasterPages, nVisibleMaster, nVisibleMaster, nVisibleMaster, sal_True ); else { implGenerateMetaData( rxMasterPages, rxDrawPages ); implGenerateScript( rxMasterPages, rxDrawPages ); implExportPages( rxMasterPages, 0, rxMasterPages->getCount() - 1, nVisibleMaster, sal_True ); } implExportPages( rxDrawPages, nFirstPage, nLastPage, nVisible, sal_False ); delete mpSVGDoc, mpSVGDoc = NULL; bRet = sal_True; } return bRet; } // ----------------------------------------------------------------------------- sal_Bool SVGFilter::implGenerateMetaData( const Reference< XDrawPages >& /* rxMasterPages */, const Reference< XDrawPages >& rxDrawPages ) { sal_Bool bRet = sal_False; if( rxDrawPages->getCount() ) { mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", B2UCONST( "meta_slides" ) ); mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "numberOfSlides", OUString::valueOf( rxDrawPages->getCount() ) ); { SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "ooo:slidesInfo", sal_True, sal_True ); const OUString aId( B2UCONST( "meta_slide" ) ); for( sal_Int32 i = 0, nCount = rxDrawPages->getCount(); i < nCount; ++i ) { OUString aSlideId( aId ); Reference< XDrawPage > xDrawPage( rxDrawPages->getByIndex( i ), UNO_QUERY ); Reference< XMasterPageTarget > xMasterPageTarget( xDrawPage, UNO_QUERY ); Reference< XDrawPage > xMasterPage( xMasterPageTarget->getMasterPage(), UNO_QUERY ); sal_Bool bMasterVisible = sal_True; OUString aMasterVisibility; aSlideId += OUString::valueOf( i ); if( mbPresentation ) { Reference< XPropertySet > xPropSet( xDrawPage, UNO_QUERY ); if( xPropSet.is() ) xPropSet->getPropertyValue( B2UCONST( "Background" ) ) >>= bMasterVisible; } if( bMasterVisible ) aMasterVisibility = B2UCONST( "visible" ); else aMasterVisibility = B2UCONST( "hidden" ); mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", aSlideId ); mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "slide", implGetValidIDFromInterface( xDrawPage ) ); mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "master", implGetValidIDFromInterface( xMasterPage ) ); mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "master-visibility", aMasterVisibility ); { SvXMLElementExport aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "ooo:slideInfo", sal_True, sal_True ); } } } bRet =sal_True; } return bRet; } // ----------------------------------------------------------------------------- sal_Bool SVGFilter::implGenerateScript( const Reference< XDrawPages >& /* rxMasterPages */, const Reference< XDrawPages >& /* rxDrawPages */ ) { mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "type", B2UCONST( "text/ecmascript" ) ); { SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "script", sal_True, sal_True ); Reference< XExtendedDocumentHandler > xExtDocHandler( mpSVGExport->GetDocHandler(), UNO_QUERY ); if( xExtDocHandler.is() ) { xExtDocHandler->unknown( OUString::createFromAscii( aSVGScript1 ) ); xExtDocHandler->unknown( OUString::createFromAscii( aSVGScript2 ) ); } } return sal_True; } // ----------------------------------------------------------------------------- sal_Bool SVGFilter::implExportPages( const Reference< XDrawPages >& rxPages, sal_Int32 nFirstPage, sal_Int32 nLastPage, sal_Int32 nVisiblePage, sal_Bool bMaster ) { DBG_ASSERT( nFirstPage <= nLastPage, "SVGFilter::implExportPages: nFirstPage > nLastPage" ); sal_Bool bRet = sal_False; for( sal_Int32 i = nFirstPage; i <= nLastPage; ++i ) { Reference< XDrawPage > xDrawPage; rxPages->getByIndex( i ) >>= xDrawPage; if( xDrawPage.is() ) { Reference< XShapes > xShapes( xDrawPage, UNO_QUERY ); if( xShapes.is() ) { OUString aVisibility, aId, aSlideName( implGetValidIDFromInterface( xShapes, sal_True ) ); // add visibility attribute if( i == nVisiblePage ) aVisibility = B2UCONST( "visible" ); else aVisibility = B2UCONST( "hidden" ); mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "visibility", aVisibility ); // add id attribute if( bMaster ) aId = ( B2UCONST( "MasterSlide_" ) ) += ::rtl::OUString::valueOf( ++mnMasterSlideId ); else aId = ( B2UCONST( "Slide_" ) ) += ::rtl::OUString::valueOf( ++mnSlideId ); if( aSlideName.getLength() ) ( ( aId += B2UCONST( "(" ) ) += aSlideName ) += B2UCONST( ")" ); mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", aId ); { SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True ); const Point aNullPt; if( mpObjects->find( xDrawPage ) != mpObjects->end() ) { Reference< XExtendedDocumentHandler > xExtDocHandler( mpSVGExport->GetDocHandler(), UNO_QUERY ); if( xExtDocHandler.is() ) { SvXMLElementExport aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "desc", sal_True, sal_True ); OUString aDesc; if( bMaster ) aDesc = B2UCONST( "Master slide" ); else aDesc = B2UCONST( "Slide" ); xExtDocHandler->unknown( aDesc ); } } if( bMaster ) { const GDIMetaFile& rMtf = (*mpObjects)[ xDrawPage ].GetRepresentation(); mpSVGWriter->WriteMetaFile( aNullPt, rMtf.GetPrefSize(), rMtf, SVGWRITER_WRITE_FILL ); } bRet = implExportShapes( xShapes ) || bRet; } } } } return bRet; } // ----------------------------------------------------------------------------- sal_Bool SVGFilter::implExportShapes( const Reference< XShapes >& rxShapes ) { Reference< XShape > xShape; sal_Bool bRet = sal_False; for( sal_Int32 i = 0, nCount = rxShapes->getCount(); i < nCount; ++i ) { if( ( rxShapes->getByIndex( i ) >>= xShape ) && xShape.is() ) bRet = implExportShape( xShape ) || bRet; xShape = NULL; } return bRet; } // ----------------------------------------------------------------------------- sal_Bool SVGFilter::implExportShape( const Reference< XShape >& rxShape ) { Reference< XPropertySet > xShapePropSet( rxShape, UNO_QUERY ); sal_Bool bRet = sal_False; if( xShapePropSet.is() ) { const ::rtl::OUString aShapeType( rxShape->getShapeType() ); sal_Bool bHideObj = sal_False; if( mbPresentation ) { xShapePropSet->getPropertyValue( B2UCONST( "IsEmptyPresentationObject" ) ) >>= bHideObj; if( !bHideObj ) { const Reference< XPropertySet > xDefaultPagePropertySet( mxDefaultPage, UNO_QUERY ); Reference< XPropertySetInfo > xPagePropSetInfo( xDefaultPagePropertySet->getPropertySetInfo() ); if( xPagePropSetInfo.is() ) { const ::rtl::OUString aHeaderString( B2UCONST( "IsHeaderVisible" ) ); const ::rtl::OUString aFooterString( B2UCONST( "IsFooterVisible" ) ); const ::rtl::OUString aDateTimeString( B2UCONST( "IsDateTimeVisible" ) ); const ::rtl::OUString aPageNumberString( B2UCONST( "IsPageNumberVisible" ) ); Any aProperty; sal_Bool bValue = sal_False; if( ( aShapeType.lastIndexOf( B2UCONST( "presentation.HeaderShape" ) ) != -1 ) && xPagePropSetInfo->hasPropertyByName( aHeaderString ) && ( ( aProperty = xDefaultPagePropertySet->getPropertyValue( aHeaderString ) ) >>= bValue ) && !bValue ) { bHideObj = sal_True; } else if( ( aShapeType.lastIndexOf( B2UCONST( "presentation.FooterShape" ) ) != -1 ) && xPagePropSetInfo->hasPropertyByName( aFooterString ) && ( ( aProperty = xDefaultPagePropertySet->getPropertyValue( aFooterString ) ) >>= bValue ) && !bValue ) { bHideObj = sal_True; } else if( ( aShapeType.lastIndexOf( B2UCONST( "presentation.DateTimeShape" ) ) != -1 ) && xPagePropSetInfo->hasPropertyByName( aDateTimeString ) && ( ( aProperty = xDefaultPagePropertySet->getPropertyValue( aDateTimeString ) ) >>= bValue ) && !bValue ) { bHideObj = sal_True; } else if( ( aShapeType.lastIndexOf( B2UCONST( "presentation.SlideNumberShape" ) ) != -1 ) && xPagePropSetInfo->hasPropertyByName( aPageNumberString ) && ( ( aProperty = xDefaultPagePropertySet->getPropertyValue( aPageNumberString ) ) >>= bValue ) && !bValue ) { bHideObj = sal_True; } } } } if( !bHideObj ) { if( aShapeType.lastIndexOf( B2UCONST( "drawing.GroupShape" ) ) != -1 ) { Reference< XShapes > xShapes( rxShape, UNO_QUERY ); if( xShapes.is() ) { OUString aId( B2UCONST( "DrawingGroup_" ) ); OUString aObjName( implGetValidIDFromInterface( rxShape, sal_True ) ), aObjDesc; aId += ::rtl::OUString::valueOf( ++mnDrawingGroupId ); if( aObjName.getLength() ) ( ( aId += B2UCONST( "(" ) ) += aObjName ) += B2UCONST( ")" ); mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", aId ); { SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True ); bRet = implExportShapes( xShapes ); } } } if( !bRet && mpObjects->find( rxShape ) != mpObjects->end() ) { Reference< XText > xText( rxShape, UNO_QUERY ); ::com::sun::star::awt::Rectangle aBoundRect; const GDIMetaFile& rMtf = (*mpObjects)[ rxShape ].GetRepresentation(); xShapePropSet->getPropertyValue( B2UCONST( "BoundRect" ) ) >>= aBoundRect; const Point aTopLeft( aBoundRect.X, aBoundRect.Y ); const Size aSize( aBoundRect.Width, aBoundRect.Height ); if( rMtf.GetActionCount() ) { OUString aId( B2UCONST( "Drawing_" ) ); OUString aObjName( implGetValidIDFromInterface( rxShape, sal_True ) ), aObjDesc; aId += ::rtl::OUString::valueOf( ++mnDrawingId ); if( aObjName.getLength() ) ( ( aId += B2UCONST( "(" ) ) += aObjName ) += B2UCONST( ")" ); { if( ( aShapeType.lastIndexOf( B2UCONST( "drawing.OLE2Shape" ) ) != -1 ) || ( aShapeType.lastIndexOf( B2UCONST( "drawing.GraphicObjectShape" ) ) != -1 ) ) { mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", aId ); { SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True ); mpSVGWriter->WriteMetaFile( aTopLeft, aSize, rMtf, SVGWRITER_WRITE_FILL | SVGWRITER_WRITE_TEXT ); } } else { if( implHasText( rMtf ) ) { mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", aId ); { SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True ); mpSVGWriter->WriteMetaFile( aTopLeft, aSize, rMtf, SVGWRITER_WRITE_FILL ); mpSVGWriter->WriteMetaFile( aTopLeft, aSize, rMtf, SVGWRITER_WRITE_TEXT ); } } else { SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True ); mpSVGWriter->WriteMetaFile( aTopLeft, aSize, rMtf, SVGWRITER_WRITE_FILL | SVGWRITER_WRITE_TEXT, &aId ); } } } } bRet = sal_True; } } } return bRet; } // ----------------------------------------------------------------------------- sal_Bool SVGFilter::implCreateObjects( const Reference< XDrawPages >& rxMasterPages, const Reference< XDrawPages >& rxDrawPages, sal_Int32 nPageToExport ) { if( SVG_EXPORT_ALLPAGES == nPageToExport ) { sal_Int32 i, nCount; for( i = 0, nCount = rxMasterPages->getCount(); i < nCount; ++i ) { Reference< XDrawPage > xMasterPage; rxMasterPages->getByIndex( i ) >>= xMasterPage; if( xMasterPage.is() ) { Reference< XShapes > xShapes( xMasterPage, UNO_QUERY ); implCreateObjectsFromBackground( xMasterPage ); if( xShapes.is() ) implCreateObjectsFromShapes( xShapes ); } } for( i = 0, nCount = rxDrawPages->getCount(); i < nCount; ++i ) { Reference< XDrawPage > xDrawPage; rxDrawPages->getByIndex( i ) >>= xDrawPage; if( xDrawPage.is() ) { Reference< XShapes > xShapes( xDrawPage, UNO_QUERY ); if( xShapes.is() ) implCreateObjectsFromShapes( xShapes ); } } } else { DBG_ASSERT( nPageToExport >= 0 && nPageToExport < rxDrawPages->getCount(), "SVGFilter::implCreateObjects: invalid page number to export" ); Reference< XDrawPage > xDrawPage; rxDrawPages->getByIndex( nPageToExport ) >>= xDrawPage; if( xDrawPage.is() ) { Reference< XMasterPageTarget > xMasterTarget( xDrawPage, UNO_QUERY ); if( xMasterTarget.is() ) { Reference< XDrawPage > xMasterPage( xMasterTarget->getMasterPage() ); if( xMasterPage.is() ) { Reference< XShapes > xShapes( xMasterPage, UNO_QUERY ); implCreateObjectsFromBackground( xMasterPage ); if( xShapes.is() ) implCreateObjectsFromShapes( xShapes ); } } Reference< XShapes > xShapes( xDrawPage, UNO_QUERY ); if( xShapes.is() ) implCreateObjectsFromShapes( xShapes ); } } return sal_True; } // ----------------------------------------------------------------------------- sal_Bool SVGFilter::implCreateObjectsFromShapes( const Reference< XShapes >& rxShapes ) { Reference< XShape > xShape; sal_Bool bRet = sal_False; for( sal_Int32 i = 0, nCount = rxShapes->getCount(); i < nCount; ++i ) { if( ( rxShapes->getByIndex( i ) >>= xShape ) && xShape.is() ) bRet = implCreateObjectsFromShape( xShape ) || bRet; xShape = NULL; } return bRet; } // ----------------------------------------------------------------------------- sal_Bool SVGFilter::implCreateObjectsFromShape( const Reference< XShape >& rxShape ) { sal_Bool bRet = sal_False; if( rxShape->getShapeType().lastIndexOf( B2UCONST( "drawing.GroupShape" ) ) != -1 ) { Reference< XShapes > xShapes( rxShape, UNO_QUERY ); if( xShapes.is() ) bRet = implCreateObjectsFromShapes( xShapes ); } else { SdrObject* pObj = GetSdrObjectFromXShape( rxShape ); if( pObj ) { Graphic aGraphic( SdrExchangeView::GetObjGraphic( pObj->GetModel(), pObj ) ); if( aGraphic.GetType() != GRAPHIC_NONE ) { if( aGraphic.GetType() == GRAPHIC_BITMAP ) { GDIMetaFile aMtf; const Point aNullPt; const Size aSize( pObj->GetCurrentBoundRect().GetSize() ); aMtf.AddAction( new MetaBmpExScaleAction( aNullPt, aSize, aGraphic.GetBitmapEx() ) ); aMtf.SetPrefSize( aSize ); aMtf.SetPrefMapMode( MAP_100TH_MM ); (*mpObjects)[ rxShape ] = ObjectRepresentation( rxShape, aMtf ); } else (*mpObjects)[ rxShape ] = ObjectRepresentation( rxShape, aGraphic.GetGDIMetaFile() ); bRet = sal_True; } } } return bRet; } // ----------------------------------------------------------------------------- sal_Bool SVGFilter::implCreateObjectsFromBackground( const Reference< XDrawPage >& rxMasterPage ) { Reference< XExporter > xExporter( mxMSF->createInstance( B2UCONST( "com.sun.star.drawing.GraphicExportFilter" ) ), UNO_QUERY ); sal_Bool bRet = sal_False; if( xExporter.is() ) { GDIMetaFile aMtf; Reference< XFilter > xFilter( xExporter, UNO_QUERY ); utl::TempFile aFile; aFile.EnableKillingFile(); Sequence< PropertyValue > aDescriptor( 3 ); aDescriptor[0].Name = B2UCONST( "FilterName" ); aDescriptor[0].Value <<= B2UCONST( "SVM" ); aDescriptor[1].Name = B2UCONST( "URL" ); aDescriptor[1].Value <<= OUString( aFile.GetURL() ); aDescriptor[2].Name = B2UCONST( "ExportOnlyBackground" ); aDescriptor[2].Value <<= (sal_Bool) sal_True; xExporter->setSourceDocument( Reference< XComponent >( rxMasterPage, UNO_QUERY ) ); xFilter->filter( aDescriptor ); aMtf.Read( *aFile.GetStream( STREAM_READ ) ); (*mpObjects)[ rxMasterPage ] = ObjectRepresentation( rxMasterPage, aMtf ); bRet = sal_True; } return bRet; } // ----------------------------------------------------------------------------- OUString SVGFilter::implGetDescriptionFromShape( const Reference< XShape >& rxShape ) { OUString aRet; const OUString aShapeType( rxShape->getShapeType() ); if( aShapeType.lastIndexOf( B2UCONST( "drawing.GroupShape" ) ) != -1 ) aRet = B2UCONST( "Group" ); else if( aShapeType.lastIndexOf( B2UCONST( "drawing.GraphicObjectShape" ) ) != -1 ) aRet = B2UCONST( "Graphic" ); else if( aShapeType.lastIndexOf( B2UCONST( "drawing.OLE2Shape" ) ) != -1 ) aRet = B2UCONST( "OLE2" ); else if( aShapeType.lastIndexOf( B2UCONST( "presentation.HeaderShape" ) ) != -1 ) aRet = B2UCONST( "Header" ); else if( aShapeType.lastIndexOf( B2UCONST( "presentation.FooterShape" ) ) != -1 ) aRet = B2UCONST( "Footer" ); else if( aShapeType.lastIndexOf( B2UCONST( "presentation.DateTimeShape" ) ) != -1 ) aRet = B2UCONST( "Date/Time" ); else if( aShapeType.lastIndexOf( B2UCONST( "presentation.SlideNumberShape" ) ) != -1 ) aRet = B2UCONST( "Slide Number" ); else aRet = B2UCONST( "Drawing" ); return aRet; } // ----------------------------------------------------------------------------- OUString SVGFilter::implGetValidIDFromInterface( const Reference< XInterface >& rxIf, sal_Bool bUnique ) { Reference< XNamed > xNamed( rxIf, UNO_QUERY ); OUString aRet; if( xNamed.is() ) { aRet = xNamed->getName().replace( ' ', '_' ). replace( ':', '_' ). replace( ',', '_' ). replace( ';', '_' ). replace( '&', '_' ). replace( '!', '_' ). replace( '|', '_' ); } if( ( aRet.getLength() > 0 ) && bUnique ) { while( ::std::find( maUniqueIdVector.begin(), maUniqueIdVector.end(), aRet ) != maUniqueIdVector.end() ) { aRet += B2UCONST( "_" ); } maUniqueIdVector.push_back( aRet ); } return aRet; } // ----------------------------------------------------------------------------- sal_Bool SVGFilter::implHasText( const GDIMetaFile& rMtf ) const { sal_Bool bRet = sal_False; for( sal_uInt32 nCurAction = 0, nCount = rMtf.GetActionCount(); ( nCurAction < nCount ) && !bRet; ++nCurAction ) { switch( rMtf.GetAction( nCurAction )->GetType() ) { case( META_TEXT_ACTION ): case( META_TEXTRECT_ACTION ): case( META_TEXTARRAY_ACTION ): case( META_STRETCHTEXT_ACTION ): { bRet = sal_True; } break; default: break; } } return bRet; } // ----------------------------------------------------------------------------- IMPL_LINK( SVGFilter, CalcFieldHdl, EditFieldInfo*, pInfo ) { OUString aRepresentation; sal_Bool bFieldProcessed = sal_False; if( pInfo ) { const ::rtl::OUString aHeaderText( B2UCONST( "HeaderText" ) ); const ::rtl::OUString aFooterText( B2UCONST( "FooterText" ) ); const ::rtl::OUString aDateTimeText( B2UCONST( "DateTimeText" ) ); const ::rtl::OUString aPageNumberText( B2UCONST( "Number" ) ); const Reference< XPropertySet > xDefaultPagePropertySet( mxDefaultPage, UNO_QUERY ); Reference< XPropertySetInfo > xDefaultPagePropSetInfo( xDefaultPagePropertySet->getPropertySetInfo() ); if( xDefaultPagePropSetInfo.is() ) { const SvxFieldData* pField = pInfo->GetField().GetField(); Any aProperty; if( pField->ISA( SvxHeaderField ) && xDefaultPagePropSetInfo->hasPropertyByName( aHeaderText ) ) { xDefaultPagePropertySet->getPropertyValue( aHeaderText ) >>= aRepresentation; bFieldProcessed = sal_True; } else if( pField->ISA( SvxFooterField ) && xDefaultPagePropSetInfo->hasPropertyByName( aFooterText ) ) { xDefaultPagePropertySet->getPropertyValue( aFooterText ) >>= aRepresentation; bFieldProcessed = sal_True; } else if( pField->ISA( SvxDateTimeField ) && xDefaultPagePropSetInfo->hasPropertyByName( aDateTimeText ) ) { xDefaultPagePropertySet->getPropertyValue( aDateTimeText ) >>= aRepresentation; bFieldProcessed = sal_True; } else if( pField->ISA( SvxPageField ) && xDefaultPagePropSetInfo->hasPropertyByName( aPageNumberText ) ) { String aPageNumValue; sal_Int16 nPageNumber = 0; xDefaultPagePropertySet->getPropertyValue( aPageNumberText ) >>= nPageNumber; if( mpSdrModel ) { sal_Bool bUpper = sal_False; switch( mpSdrModel->GetPageNumType() ) { case SVX_CHARS_UPPER_LETTER: aPageNumValue += (sal_Unicode)(char)( ( nPageNumber - 1 ) % 26 + 'A' ); break; case SVX_CHARS_LOWER_LETTER: aPageNumValue += (sal_Unicode)(char)( ( nPageNumber- 1 ) % 26 + 'a' ); break; case SVX_ROMAN_UPPER: bUpper = sal_True; case SVX_ROMAN_LOWER: aPageNumValue += SvxNumberFormat::CreateRomanString( nPageNumber, bUpper ); break; case SVX_NUMBER_NONE: aPageNumValue.Erase(); aPageNumValue += sal_Unicode(' '); break; default : break; } } if( !aPageNumValue.Len() ) aPageNumValue += String::CreateFromInt32( nPageNumber ); aRepresentation = aPageNumValue; bFieldProcessed = sal_True; } } pInfo->SetRepresentation( aRepresentation ); } return( bFieldProcessed ? 0 : maOldFieldHdl.Call( pInfo ) ); }