diff options
Diffstat (limited to 'filter/source/svg')
-rw-r--r-- | filter/source/svg/SOTranscoder.java | 45 | ||||
-rw-r--r-- | filter/source/svg/makefile.mk | 91 | ||||
-rw-r--r-- | filter/source/svg/svgexport.cxx | 1007 | ||||
-rw-r--r-- | filter/source/svg/svgfilter.component | 34 | ||||
-rw-r--r-- | filter/source/svg/svgfilter.cxx | 229 | ||||
-rw-r--r-- | filter/source/svg/svgfilter.hxx | 296 | ||||
-rw-r--r-- | filter/source/svg/svgfontexport.cxx | 258 | ||||
-rw-r--r-- | filter/source/svg/svgfontexport.hxx | 64 | ||||
-rw-r--r-- | filter/source/svg/svgimport.cxx | 188 | ||||
-rw-r--r-- | filter/source/svg/svgscript.hxx | 209 | ||||
-rw-r--r-- | filter/source/svg/svguno.cxx | 76 | ||||
-rw-r--r-- | filter/source/svg/svgwriter.cxx | 1657 | ||||
-rw-r--r-- | filter/source/svg/svgwriter.hxx | 225 |
13 files changed, 4379 insertions, 0 deletions
diff --git a/filter/source/svg/SOTranscoder.java b/filter/source/svg/SOTranscoder.java new file mode 100644 index 000000000000..d0b3728e5978 --- /dev/null +++ b/filter/source/svg/SOTranscoder.java @@ -0,0 +1,45 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +import java.io.*; +import org.apache.batik.transcoder.image.PNGTranscoder; +import org.apache.batik.transcoder.TranscoderInput; +import org.apache.batik.transcoder.TranscoderOutput; + +public class SOTranscoder +{ + public static void main(String [] args) throws Exception + { + PNGTranscoder aTranscoder = new PNGTranscoder(); + OutputStream aOStm = new FileOutputStream( args[ 1 ] ); + + aTranscoder.transcode( new TranscoderInput( new File( args[ 0 ] ).toURL().toString() ), new TranscoderOutput( aOStm ) ); + + aOStm.flush(); + aOStm.close(); + } +} diff --git a/filter/source/svg/makefile.mk b/filter/source/svg/makefile.mk new file mode 100644 index 000000000000..44bac23381f5 --- /dev/null +++ b/filter/source/svg/makefile.mk @@ -0,0 +1,91 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. +PRJNAME=filter +TARGET=svgfilter + +ENABLE_EXCEPTIONS=TRUE +VISIBILITY_HIDDEN=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk + +# --- Types ------------------------------------- + +SLOFILES= $(SLO)$/svguno.obj \ + $(SLO)$/svgfilter.obj \ + $(SLO)$/svgexport.obj \ + $(SLO)$/svgfontexport.obj \ + $(SLO)$/svgwriter.obj +.IF "$(SOLAR_JAVA)"!="" +SLOFILES+= $(SLO)$/svgimport.obj +.ENDIF + +# --- Library ----------------------------------- + +SHL1TARGET=$(TARGET)$(DLLPOSTFIX) + +SHL1STDLIBS=\ + $(EDITENGLIB) \ + $(SVXCORELIB) \ + $(XMLOFFLIB) \ + $(SVTOOLLIB) \ + $(VCLLIB) \ + $(UNOTOOLSLIB) \ + $(TOOLSLIB) \ + $(COMPHELPERLIB) \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) + +.IF "$(SOLAR_JAVA)"!="" +SHL1STDLIBS+=\ + $(JVMACCESSLIB) +.ENDIF + + +SHL1DEPN= +SHL1IMPLIB= i$(SHL1TARGET) +SHL1LIBS= $(SLB)$/$(TARGET).lib +SHL1VERSIONMAP=$(SOLARENV)/src/component.map +SHL1DEF= $(MISC)$/$(SHL1TARGET).def + +DEF1NAME=$(SHL1TARGET) + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + +ALLTAR : $(MISC)/svgfilter.component + +$(MISC)/svgfilter.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + svgfilter.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt svgfilter.component diff --git a/filter/source/svg/svgexport.cxx b/filter/source/svg/svgexport.cxx new file mode 100644 index 000000000000..081a914934c7 --- /dev/null +++ b/filter/source/svg/svgexport.cxx @@ -0,0 +1,1007 @@ + /************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * 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 <svx/unopage.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdoutl.hxx> +#include <editeng/outliner.hxx> +#include <editeng/flditem.hxx> +#include <editeng/numitem.hxx> + +using ::rtl::OUString; + +// ------------- +// - SVGExport - +// ------------- + +// #110680# +SVGExport::SVGExport( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory, + const Reference< XDocumentHandler >& rxHandler ) +: SvXMLExport( xServiceFactory, OUString(), rxHandler ) +{ + GetDocHandler()->startDocument(); +} + +// ----------------------------------------------------------------------------- + +SVGExport::~SVGExport() +{ + GetDocHandler()->endDocument(); +} + +// ------------------------ +// - 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; +} + +// ----------------------------------------------------------------------------- + +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; + + 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; + } + + 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() && xDrawPages->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 ); + + 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() ) + xExtDocHandler->unknown( SVG_DTD_STRING ); + +#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, "version", B2UCONST( "1.1" ) ); + mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "viewBox", aAttr ); + mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "preserveAspectRatio", B2UCONST( "xMidYMid" ) ); + mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "fill-rule", B2UCONST( "evenodd" ) ); + + 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" ) ); + + mpSVGDoc = new SvXMLElementExport( *mpSVGExport, XML_NAMESPACE_NONE, "svg", TRUE, 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; + } + +#ifdef _SVG_EMBED_FONTS + mpSVGFontExport->EmbedFonts(); +#endif + + 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", TRUE, 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", TRUE, 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", TRUE, 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 aAttr; + + if( i == nVisiblePage ) + aAttr = B2UCONST( "visible" ); + else + aAttr = B2UCONST( "hidden" ); + + mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "visibility", aAttr ); + mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", implGetValidIDFromInterface( xShapes ) ); + + { + SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", TRUE, TRUE ); + const Point aNullPt; + + { + Reference< XExtendedDocumentHandler > xExtDocHandler( mpSVGExport->GetDocHandler(), UNO_QUERY ); + + if( xExtDocHandler.is() ) + { + SvXMLElementExport aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "desc", TRUE, 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() ); + bool bHideObj = 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() ) + { + static const ::rtl::OUString aHeaderString( B2UCONST( "IsHeaderVisible" ) ); + static const ::rtl::OUString aFooterString( B2UCONST( "IsFooterVisible" ) ); + static const ::rtl::OUString aDateTimeString( B2UCONST( "IsDateTimeVisible" ) ); + static const ::rtl::OUString aPageNumberString( B2UCONST( "IsPageNumberVisible" ) ); + + Any aProperty; + bool bValue = sal_False; + + if( ( aShapeType.lastIndexOf( B2UCONST( "presentation.HeaderShape" ) ) != -1 ) && + xPagePropSetInfo->hasPropertyByName( aHeaderString ) && + ( ( aProperty = xDefaultPagePropertySet->getPropertyValue( aHeaderString ) ) >>= bValue ) && + !bValue ) + { + bHideObj = true; + } + else if( ( aShapeType.lastIndexOf( B2UCONST( "presentation.FooterShape" ) ) != -1 ) && + xPagePropSetInfo->hasPropertyByName( aFooterString ) && + ( ( aProperty = xDefaultPagePropertySet->getPropertyValue( aFooterString ) ) >>= bValue ) && + !bValue ) + { + bHideObj = true; + } + else if( ( aShapeType.lastIndexOf( B2UCONST( "presentation.DateTimeShape" ) ) != -1 ) && + xPagePropSetInfo->hasPropertyByName( aDateTimeString ) && + ( ( aProperty = xDefaultPagePropertySet->getPropertyValue( aDateTimeString ) ) >>= bValue ) && + !bValue ) + { + bHideObj = true; + } + else if( ( aShapeType.lastIndexOf( B2UCONST( "presentation.SlideNumberShape" ) ) != -1 ) && + xPagePropSetInfo->hasPropertyByName( aPageNumberString ) && + ( ( aProperty = xDefaultPagePropertySet->getPropertyValue( aPageNumberString ) ) >>= bValue ) && + !bValue ) + { + bHideObj = true; + } + } + } + } + + if( !bHideObj ) + { + OUString aObjName( implGetValidIDFromInterface( rxShape ) ), aObjDesc; + + if( aObjName.getLength() ) + mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", aObjName ); + + if( aShapeType.lastIndexOf( B2UCONST( "drawing.GroupShape" ) ) != -1 ) + { + Reference< XShapes > xShapes( rxShape, UNO_QUERY ); + + if( xShapes.is() ) + { + SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", TRUE, TRUE ); + + { + SvXMLElementExport aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "desc", TRUE, TRUE ); + Reference< XExtendedDocumentHandler > xExtDocHandler( mpSVGExport->GetDocHandler(), UNO_QUERY ); + + xExtDocHandler->unknown( B2UCONST( "Group" ) ); + } + + bRet = implExportShapes( xShapes ); + } + } + + if( !bRet ) + { + 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 ); + + { + SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", TRUE, TRUE ); + + { + SvXMLElementExport aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "desc", TRUE, TRUE ); + Reference< XExtendedDocumentHandler > xExtDocHandler( mpSVGExport->GetDocHandler(), UNO_QUERY ); + + xExtDocHandler->unknown( implGetDescriptionFromShape( rxShape ) ); + } + + if( rMtf.GetActionCount() ) + { + if( ( aShapeType.lastIndexOf( B2UCONST( "drawing.OLE2Shape" ) ) != -1 ) || + ( aShapeType.lastIndexOf( B2UCONST( "drawing.GraphicObjectShape" ) ) != -1 ) ) + { + SvXMLElementExport aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "g", TRUE, TRUE ); + mpSVGWriter->WriteMetaFile( aTopLeft, aSize, rMtf, SVGWRITER_WRITE_ALL); + } + else + { + // write geometries + SvXMLElementExport aGeometryExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", TRUE, TRUE ); + mpSVGWriter->WriteMetaFile( aTopLeft, aSize, rMtf, SVGWRITER_WRITE_FILL ); + + // write text separately + SvXMLElementExport aTextExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", TRUE, TRUE ); + mpSVGWriter->WriteMetaFile( aTopLeft, aSize, rMtf, SVGWRITER_WRITE_TEXT ); + } + } + } + + 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 ) +{ + Reference< XNamed > xNamed( rxIf, UNO_QUERY ); + OUString aRet; + + if( xNamed.is() ) + aRet = xNamed->getName().replace( ' ', '_' ); + + return aRet; +} + +// ----------------------------------------------------------------------------- + +IMPL_LINK( SVGFilter, CalcFieldHdl, EditFieldInfo*, pInfo ) +{ + OUString aRepresentation; + bool bFieldProcessed = false; + + if( pInfo ) + { + static const ::rtl::OUString aHeaderText( B2UCONST( "HeaderText" ) ); + static const ::rtl::OUString aFooterText( B2UCONST( "FooterText" ) ); + static const ::rtl::OUString aDateTimeText( B2UCONST( "DateTimeText" ) ); + static 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 = true; + } + else if( pField->ISA( SvxFooterField ) && + xDefaultPagePropSetInfo->hasPropertyByName( aFooterText ) ) + { + xDefaultPagePropertySet->getPropertyValue( aFooterText ) >>= aRepresentation; + bFieldProcessed = true; + } + else if( pField->ISA( SvxDateTimeField ) && + xDefaultPagePropSetInfo->hasPropertyByName( aDateTimeText ) ) + { + xDefaultPagePropertySet->getPropertyValue( aDateTimeText ) >>= aRepresentation; + bFieldProcessed = true; + } + else if( pField->ISA( SvxPageField ) && + xDefaultPagePropSetInfo->hasPropertyByName( aPageNumberText ) ) + { + String aPageNumValue; + sal_Int16 nPageNumber = 0; + + xDefaultPagePropertySet->getPropertyValue( aPageNumberText ) >>= nPageNumber; + + if( mpSdrModel ) + { + bool bUpper = 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 = 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 = true; + } + } + + pInfo->SetRepresentation( aRepresentation ); + } + + return( bFieldProcessed ? 0 : maOldFieldHdl.Call( pInfo ) ); +} diff --git a/filter/source/svg/svgfilter.component b/filter/source/svg/svgfilter.component new file mode 100644 index 000000000000..82db624ff9e0 --- /dev/null +++ b/filter/source/svg/svgfilter.component @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* 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 +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.Draw.SVGFilter"> + <service name="com.sun.star.document.SVGFilter"/> + </implementation> +</component> diff --git a/filter/source/svg/svgfilter.cxx b/filter/source/svg/svgfilter.cxx new file mode 100644 index 000000000000..118474bbe2b0 --- /dev/null +++ b/filter/source/svg/svgfilter.cxx @@ -0,0 +1,229 @@ + /************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_filter.hxx" + +#include <cstdio> + +#include "svgfilter.hxx" +#include <com/sun/star/drawing/XDrawPage.hpp> +#include <com/sun/star/drawing/XDrawView.hpp> +#include <com/sun/star/frame/XDesktop.hdl> +#include <com/sun/star/frame/XController.hdl> +#include <vos/mutex.hxx> + +using ::rtl::OUString; +using namespace ::com::sun::star; + +// ------------- +// - SVGFilter - +// ------------- + +SVGFilter::SVGFilter( const Reference< XMultiServiceFactory > &rxMSF ) : + mxMSF( rxMSF ), + mpSVGDoc( NULL ), + mpSVGExport( NULL ), + mpSVGFontExport( NULL ), + mpSVGWriter( NULL ), + mpDefaultSdrPage( NULL ), + mpSdrModel( NULL ), + mbPresentation( sal_False ) +{ +} + +// ----------------------------------------------------------------------------- + +SVGFilter::~SVGFilter() +{ + DBG_ASSERT( mpSVGDoc == NULL, "mpSVGDoc not destroyed" ); + DBG_ASSERT( mpSVGExport == NULL, "mpSVGExport not destroyed" ); + DBG_ASSERT( mpSVGFontExport == NULL, "mpSVGFontExport not destroyed" ); + DBG_ASSERT( mpSVGWriter == NULL, "mpSVGWriter not destroyed" ); + DBG_ASSERT( mpObjects == NULL, "mpObjects not destroyed" ); +} + +// ----------------------------------------------------------------------------- + +sal_Bool SAL_CALL SVGFilter::filter( const Sequence< PropertyValue >& rDescriptor ) + throw (RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + Window* pFocusWindow = Application::GetFocusWindow(); + sal_Int16 nCurrentPageNumber = -1; + sal_Bool bRet; + + if( pFocusWindow ) + pFocusWindow->EnterWait(); + +#ifdef SOLAR_JAVA + if( mxDstDoc.is() ) + bRet = implImport( rDescriptor ); + else +#endif + if( mxSrcDoc.is() ) + { + uno::Reference< frame::XDesktop > xDesktop( mxMSF->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.frame.Desktop" ) ), + uno::UNO_QUERY); + if( xDesktop.is() ) + { + uno::Reference< frame::XFrame > xFrame( xDesktop->getCurrentFrame() ); + + if( xFrame.is() ) + { + uno::Reference< frame::XController > xController( xFrame->getController() ); + + if( xController.is() ) + { + uno::Reference< drawing::XDrawView > xDrawView( xController, uno::UNO_QUERY ); + + if( xDrawView.is() ) + { + uno::Reference< drawing::XDrawPage > xDrawPage( xDrawView->getCurrentPage() ); + + if( xDrawPage.is() ) + { + uno::Reference< beans::XPropertySet >( xDrawPage, uno::UNO_QUERY )-> + getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Number" ) ) ) >>= nCurrentPageNumber; + } + } + } + } + } + + Sequence< PropertyValue > aNewDescritor( rDescriptor ); + + if( nCurrentPageNumber > 0 ) + { + const sal_uInt32 nOldLength = rDescriptor.getLength(); + + aNewDescritor.realloc( nOldLength + 1 ); + aNewDescritor[ nOldLength ].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PagePos" ) ); + aNewDescritor[ nOldLength ].Value <<= static_cast< sal_Int16 >( nCurrentPageNumber - 1 ); + } + + bRet = implExport( aNewDescritor ); + } + else + bRet = sal_False; + + if( pFocusWindow ) + pFocusWindow->LeaveWait(); + + return bRet; +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL SVGFilter::cancel( ) throw (RuntimeException) +{ +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL SVGFilter::setSourceDocument( const Reference< XComponent >& xDoc ) + throw (IllegalArgumentException, RuntimeException) +{ + mxSrcDoc = xDoc; +} + +// ----------------------------------------------------------------------------- + +#ifdef SOLAR_JAVA +void SAL_CALL SVGFilter::setTargetDocument( const Reference< XComponent >& xDoc ) + throw (::com::sun::star::lang::IllegalArgumentException, RuntimeException) +{ + mxDstDoc = xDoc; +} +#endif + +// ----------------------------------------------------------------------------- + +void SAL_CALL SVGFilter::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& /* aArguments */ ) + throw (Exception, RuntimeException) +{ +} + +// ----------------------------------------------------------------------------- + +OUString SVGFilter_getImplementationName () + throw (RuntimeException) +{ + return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Draw.SVGFilter" ) ); +} + +// ----------------------------------------------------------------------------- + +#define SERVICE_NAME "com.sun.star.document.SVGFilter" + +sal_Bool SAL_CALL SVGFilter_supportsService( const OUString& ServiceName ) + throw (RuntimeException) +{ + return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) ); +} + +// ----------------------------------------------------------------------------- + +Sequence< OUString > SAL_CALL SVGFilter_getSupportedServiceNames( ) throw (RuntimeException) +{ + Sequence < OUString > aRet(1); + OUString* pArray = aRet.getArray(); + pArray[0] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) ); + return aRet; +} + +#undef SERVICE_NAME + +// ----------------------------------------------------------------------------- + +Reference< XInterface > SAL_CALL SVGFilter_createInstance( const Reference< XMultiServiceFactory > & rSMgr) throw( Exception ) +{ + return (cppu::OWeakObject*) new SVGFilter( rSMgr ); +} + +// ----------------------------------------------------------------------------- + +OUString SAL_CALL SVGFilter::getImplementationName( ) + throw (RuntimeException) +{ + return SVGFilter_getImplementationName(); +} + +// ----------------------------------------------------------------------------- + +sal_Bool SAL_CALL SVGFilter::supportsService( const OUString& rServiceName ) + throw (RuntimeException) +{ + return SVGFilter_supportsService( rServiceName ); +} + +// ----------------------------------------------------------------------------- + +::com::sun::star::uno::Sequence< OUString > SAL_CALL SVGFilter::getSupportedServiceNames( ) throw (RuntimeException) +{ + return SVGFilter_getSupportedServiceNames(); +} diff --git a/filter/source/svg/svgfilter.hxx b/filter/source/svg/svgfilter.hxx new file mode 100644 index 000000000000..0bbc64e2c244 --- /dev/null +++ b/filter/source/svg/svgfilter.hxx @@ -0,0 +1,296 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SVGFILTER_HXX +#define SVGFILTER_HXX + +#include <com/sun/star/drawing/XMasterPageTarget.hpp> +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/drawing/XMasterPagesSupplier.hpp> +#include <com/sun/star/presentation/XPresentationSupplier.hpp> +#include <com/sun/star/document/XFilter.hpp> +#ifdef SOLAR_JAVA +#include <com/sun/star/document/XImporter.hpp> +#endif // SOLAR_JAVA +#include <com/sun/star/document/XExporter.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <cppuhelper/implbase1.hxx> +#ifdef SOLAR_JAVA +#include <cppuhelper/implbase5.hxx> +#else // !SOLAR_JAVA +#include <cppuhelper/implbase4.hxx> +#endif +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/presentation/AnimationEffect.hpp> +#include <com/sun/star/presentation/AnimationSpeed.hpp> +#include <com/sun/star/presentation/ClickAction.hpp> +#include <com/sun/star/presentation/FadeEffect.hpp> +#include <com/sun/star/text/XText.hpp> +#include <com/sun/star/frame/XDesktop.hpp> +#include <com/sun/star/java/XJavaVM.hpp> +#include <com/sun/star/java/XJavaThreadRegister_11.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +#include <hash_map> +#include <osl/diagnose.h> +#include <rtl/process.h> +#include <tools/debug.hxx> +#include <comphelper/processfactory.hxx> +#include <unotools/tempfile.hxx> +#include <unotools/localfilehelper.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <unotools/streamwrap.hxx> +#include <vcl/cvtgrf.hxx> +#include <vcl/svapp.hxx> +#include <vcl/outdev.hxx> +#include <vcl/metaact.hxx> +#include <svtools/grfmgr.hxx> +#include <svx/unomodel.hxx> +#include <svx/unoapi.hxx> +#include <svx/svdxcgv.hxx> +#include <svx/svdobj.hxx> +#include <xmloff/xmlexp.hxx> + +#include "svgfilter.hxx" +#include "svgscript.hxx" + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::java; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::presentation; +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::xml::sax; +using namespace ::std; + +// ----------- +// - Defines - +// ----------- + +#define SVG_EXPORT_ALLPAGES ((sal_Int32)-1) + +// ------------- +// - SVGExport - +// ------------- + +// #110680# +class SVGExport : public SvXMLExport +{ +private: + + SVGExport(); + +protected: + + virtual void _ExportMeta() {} + virtual void _ExportStyles( BOOL /* bUsed */ ) {} + virtual void _ExportAutoStyles() {} + virtual void _ExportContent() {} + virtual void _ExportMasterStyles() {} + virtual sal_uInt32 exportDoc( enum ::xmloff::token::XMLTokenEnum /* eClass */ ) { return 0; } + +public: + + SVGExport( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory, + const Reference< XDocumentHandler >& rxHandler ); + virtual ~SVGExport(); +}; + +// ------------------------ +// - ObjectRepresentation - +// ------------------------ + +class ObjectRepresentation +{ +private: + + Reference< XInterface > mxObject; + GDIMetaFile* mpMtf; + +public: + + ObjectRepresentation(); + ObjectRepresentation( const Reference< XInterface >& rxIf, + const GDIMetaFile& rMtf ); + ObjectRepresentation( const ObjectRepresentation& rPresentation ); + ~ObjectRepresentation(); + + ObjectRepresentation& operator=( const ObjectRepresentation& rPresentation ); + bool operator==( const ObjectRepresentation& rPresentation ) const; + + const Reference< XInterface >& GetObject() const { return mxObject; } + sal_Bool HasRepresentation() const { return mpMtf != NULL; } + const GDIMetaFile& GetRepresentation() const { return *mpMtf; } +}; + +// --------------------------- +// - HashReferenceXInterface - +// --------------------------- + +struct HashReferenceXInterface +{ + size_t operator()( const Reference< XInterface >& rxIf ) const { return reinterpret_cast< size_t >( rxIf.get() ); } +}; + +// ------------- +// - SVGFilter - +// ------------- + +class SVGFontExport; +class SVGActionWriter; +class EditFieldInfo; + +#ifdef SOLAR_JAVA +class SVGFilter : public cppu::WeakImplHelper5 < XFilter, + XImporter, + XExporter, + XInitialization, + XServiceInfo > +#else // !SOLAR_JAVA +class SVGFilter : public cppu::WeakImplHelper4 < XFilter, + XExporter, + XInitialization, + XServiceInfo > +#endif +{ + typedef ::std::hash_map< Reference< XInterface >, ObjectRepresentation, HashReferenceXInterface > ObjectMap; + +private: + + Reference< XMultiServiceFactory > mxMSF; + SvXMLElementExport* mpSVGDoc; + SVGExport* mpSVGExport; + SVGFontExport* mpSVGFontExport; + SVGActionWriter* mpSVGWriter; + SdrPage* mpDefaultSdrPage; + SdrModel* mpSdrModel; + sal_Bool mbPresentation; + + ObjectMap* mpObjects; + Reference< XComponent > mxSrcDoc; +#ifdef SOLAR_JAVA + Reference< XComponent > mxDstDoc; +#endif + Reference< XDrawPage > mxDefaultPage; + Link maOldFieldHdl; + +#ifdef SOLAR_JAVA + sal_Bool implImport( const Sequence< PropertyValue >& rDescriptor ) throw (RuntimeException); +#endif + + sal_Bool implExport( const Sequence< PropertyValue >& rDescriptor ) throw (RuntimeException); + Reference< XDocumentHandler > implCreateExportDocumentHandler( const Reference< XOutputStream >& rxOStm ); + + sal_Bool implGenerateMetaData( const Reference< XDrawPages >& rxMasterPages, + const Reference< XDrawPages >& rxDrawPages ); + sal_Bool implGenerateScript( const Reference< XDrawPages >& rxMasterPages, + const Reference< XDrawPages >& rxDrawPages ); + + sal_Bool implExportDocument( const Reference< XDrawPages >& rxMasterPages, + const Reference< XDrawPages >& rxDrawPages, + sal_Int32 nPageToExport ); + + sal_Bool implExportPages( const Reference< XDrawPages >& rxPages, + sal_Int32 nFirstPage, sal_Int32 nLastPage, + sal_Int32 nVisiblePage, sal_Bool bMaster ); + + sal_Bool implExportShapes( const Reference< XShapes >& rxShapes ); + sal_Bool implExportShape( const Reference< XShape >& rxShape ); + + sal_Bool implCreateObjects( const Reference< XDrawPages >& rxMasterPages, + const Reference< XDrawPages >& rxDrawPages, + sal_Int32 nPageToExport ); + sal_Bool implCreateObjectsFromShapes( const Reference< XShapes >& rxShapes ); + sal_Bool implCreateObjectsFromShape( const Reference< XShape >& rxShape ); + sal_Bool implCreateObjectsFromBackground( const Reference< XDrawPage >& rxMasterPage ); + + ::rtl::OUString implGetDescriptionFromShape( const Reference< XShape >& rxShape ); + ::rtl::OUString implGetValidIDFromInterface( const Reference< XInterface >& rxIf ); + + DECL_LINK( CalcFieldHdl, EditFieldInfo* ); + +protected: + + // XFilter + virtual sal_Bool SAL_CALL filter( const Sequence< PropertyValue >& rDescriptor ) throw(RuntimeException); + virtual void SAL_CALL cancel( ) throw (RuntimeException); + +#ifdef SOLAR_JAVA + // XImporter + virtual void SAL_CALL setTargetDocument( const Reference< XComponent >& xDoc ) throw(IllegalArgumentException, RuntimeException); +#endif + + // XExporter + virtual void SAL_CALL setSourceDocument( const Reference< XComponent >& xDoc ) throw(IllegalArgumentException, RuntimeException); + + // XInitialization + virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) throw(Exception, RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() throw(RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(RuntimeException); + virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw(RuntimeException); + +public: + + SVGFilter( const Reference< XMultiServiceFactory > &rxMSF ); + virtual ~SVGFilter(); +}; + +// ----------------------------------------------------------------------------- + +::rtl::OUString SVGFilter_getImplementationName () + throw ( ::com::sun::star::uno::RuntimeException ); + +// ----------------------------------------------------------------------------- + +sal_Bool SAL_CALL SVGFilter_supportsService( const ::rtl::OUString& ServiceName ) + throw ( ::com::sun::star::uno::RuntimeException ); + +// ----------------------------------------------------------------------------- + +::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL SVGFilter_getSupportedServiceNames( ) + throw ( ::com::sun::star::uno::RuntimeException ); + +// ----------------------------------------------------------------------------- + +::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > +SAL_CALL SVGFilter_createInstance( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & rSMgr) + throw ( ::com::sun::star::uno::Exception ); + +#endif // SVGFILTER_HXX diff --git a/filter/source/svg/svgfontexport.cxx b/filter/source/svg/svgfontexport.cxx new file mode 100644 index 000000000000..8fa9db03eacf --- /dev/null +++ b/filter/source/svg/svgfontexport.cxx @@ -0,0 +1,258 @@ + /************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_filter.hxx" + + +#include "svgfontexport.hxx" + +static const sal_Int32 nFontEM = 2048; + +// ----------------- +// - SVGFontExport - +// ----------------- + +SVGFontExport::SVGFontExport( SvXMLExport& rExport, const ::std::vector< ObjectRepresentation >& rObjects ) : + mrExport( rExport ), + maObjects( rObjects ), + mnCurFontId( 0 ) +{ +} + +// ----------------------------------------------------------------------------- + +SVGFontExport::~SVGFontExport() +{ +} + +// ----------------------------------------------------------------------------- + +void SVGFontExport::implCollectGlyphs() +{ + VirtualDevice aVDev; + ObjectVector::const_iterator aIter( maObjects.begin() ); + + aVDev.EnableOutput( sal_False ); + + while( aIter != maObjects.end() ) + { + if( (*aIter).HasRepresentation() ) + { + const GDIMetaFile& rMtf = (*aIter).GetRepresentation(); + + aVDev.Push(); + + for( sal_uInt32 i = 0, nCount = rMtf.GetActionCount(); i < nCount; ++i ) + { + ::rtl::OUString aText; + MetaAction* pAction = rMtf.GetAction( i ); + const USHORT nType = pAction->GetType(); + + switch( nType ) + { + case( META_TEXT_ACTION ): + { + const MetaTextAction* pA = (const MetaTextAction*) pAction; + aText = String( pA->GetText(), pA->GetIndex(), pA->GetLen() ); + } + break; + + case( META_TEXTRECT_ACTION ): + { + const MetaTextRectAction* pA = (const MetaTextRectAction*) pAction; + aText = pA->GetText(); + } + break; + + case( META_TEXTARRAY_ACTION ): + { + const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pAction; + aText = String( pA->GetText(), pA->GetIndex(), pA->GetLen() ); + } + break; + + case( META_STRETCHTEXT_ACTION ): + { + const MetaStretchTextAction* pA = (const MetaStretchTextAction*) pAction; + aText = String( pA->GetText(), pA->GetIndex(), pA->GetLen() ); + } + break; + + default: + pAction->Execute( &aVDev ); + break; + } + + if( aText.getLength() ) + { + const String& rFontName = aVDev.GetFont().GetName(); + const sal_Unicode* pStr = aText.getStr(); + + for( sal_uInt32 j = 0, nLen = aText.getLength(); j < nLen; ++j ) + maGlyphs[ rFontName ].insert( pStr[ j ] ); + } + } + + aVDev.Pop(); + } + + ++aIter; + } +} + +// ----------------------------------------------------------------------------- + +void SVGFontExport::implEmbedFont( const ::rtl::OUString& rFontName, const ::std::set< sal_Unicode >& rGlyphs ) +{ +#ifdef _SVG_EMBED_FONTS + ::std::set< sal_Unicode >::const_iterator aIter( rGlyphs.begin() ); + const ::rtl::OUString aEmbeddedFontStr( B2UCONST( "EmbeddedFont_" ) ); + + { + SvXMLElementExport aExp( mrExport, XML_NAMESPACE_NONE, "defs", TRUE, TRUE ); + ::rtl::OUString aCurIdStr( aEmbeddedFontStr ); + ::rtl::OUString aUnitsPerEM( SVGActionWriter::GetValueString( nFontEM ) ); + VirtualDevice aVDev; + Font aFont( rFontName, Size( 0, nFontEM ) ); + + aVDev.SetMapMode( MAP_100TH_MM ); + aFont.SetAlign( ALIGN_BASELINE ); + aVDev.SetFont( aFont ); + + mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", aCurIdStr += SVGActionWriter::GetValueString( ++mnCurFontId ) ); + mrExport.AddAttribute( XML_NAMESPACE_NONE, "horiz-adv-x", aUnitsPerEM ); + + { + SvXMLElementExport aExp2( mrExport, XML_NAMESPACE_NONE, "font", TRUE, TRUE ); + Point aPos; + Size aSize( nFontEM, nFontEM ); + PolyPolygon aMissingGlyphPolyPoly( Rectangle( aPos, aSize ) ); + + aMissingGlyphPolyPoly.Move( 0, -nFontEM ); + aMissingGlyphPolyPoly.Scale( 1.0, -1.0 ); + + mrExport.AddAttribute( XML_NAMESPACE_NONE, "font-family", GetMappedFontName( rFontName ) ); + mrExport.AddAttribute( XML_NAMESPACE_NONE, "units-per-em", aUnitsPerEM ); + mrExport.AddAttribute( XML_NAMESPACE_NONE, "ascent", SVGActionWriter::GetValueString( aVDev.GetFontMetric().GetAscent() ) ); + mrExport.AddAttribute( XML_NAMESPACE_NONE, "descent", SVGActionWriter::GetValueString( aVDev.GetFontMetric().GetDescent() ) ); + + { + SvXMLElementExport aExp3( mrExport, XML_NAMESPACE_NONE, "font-face", TRUE, TRUE ); + } + + mrExport.AddAttribute( XML_NAMESPACE_NONE, "horiz-adv-x", SVGActionWriter::GetValueString( aSize.Width() ) ); + + { + SvXMLElementExport aExp3( mrExport, XML_NAMESPACE_NONE, "missing-glyph", TRUE, TRUE ); + + mrExport.AddAttribute( XML_NAMESPACE_NONE, "style", B2UCONST( "fill:none;stroke:black;stroke-width:33" ) ); + mrExport.AddAttribute( XML_NAMESPACE_NONE, "d", SVGActionWriter::GetPathString( aMissingGlyphPolyPoly, sal_False ) ); + + { + SvXMLElementExport aExp4( mrExport, XML_NAMESPACE_NONE, "path", TRUE, TRUE ); + } + } + + while( aIter != rGlyphs.end() ) + { + implEmbedGlyph( aVDev, ::rtl::OUString( *aIter ) ); + ++aIter; + } + } + } +#endif +} + +// ----------------------------------------------------------------------------- + +void SVGFontExport::implEmbedGlyph( OutputDevice& rOut, const ::rtl::OUString& rGlyphs ) +{ + PolyPolygon aPolyPoly; + ::rtl::OUString aStr( rGlyphs ); + const sal_Unicode nSpace = ' '; + + if( rOut.GetTextOutline( aPolyPoly, aStr ) ) + { + Rectangle aBoundRect; + + aPolyPoly.Scale( 1.0, -1.0 ); + + if( !rOut.GetTextBoundRect( aBoundRect, aStr ) ) + aBoundRect = Rectangle( Point( 0, 0 ), Size( rOut.GetTextWidth( aStr ), 0 ) ); + + mrExport.AddAttribute( XML_NAMESPACE_NONE, "unicode", aStr ); + + if( rGlyphs[ 0 ] == nSpace ) + aBoundRect = Rectangle( Point( 0, 0 ), Size( rOut.GetTextWidth( sal_Unicode( 'x' ) ), 0 ) ); + + mrExport.AddAttribute( XML_NAMESPACE_NONE, "horiz-adv-x", SVGActionWriter::GetValueString( aBoundRect.GetWidth() ) ); + + { + SvXMLElementExport aExp( mrExport, XML_NAMESPACE_NONE, "glyph", TRUE, TRUE ); + const ::rtl::OUString aPathString( SVGActionWriter::GetPathString( aPolyPoly, sal_False ) ); + + if( aPathString.getLength() ) + { + mrExport.AddAttribute( XML_NAMESPACE_NONE, "d", aPathString ); + + { + SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, B2UCONST( "path" ), TRUE, TRUE ); + } + } + } + } +} + +// ----------------------------------------------------------------------------- + +void SVGFontExport::EmbedFonts() +{ + implCollectGlyphs(); + + GlyphMap::const_iterator aIter( maGlyphs.begin() ); + + while( aIter != maGlyphs.end() ) + { + implEmbedFont( (*aIter).first, (*aIter).second ); + ++aIter; + } +} + +// ----------------------------------------------------------------------------- + +::rtl::OUString SVGFontExport::GetMappedFontName( const ::rtl::OUString& rFontName ) const +{ + ::rtl::OUString aRet( String( rFontName ).GetToken( 0, ';' ) ); + +#ifdef _SVG_EMBED_FONTS + if( mnCurFontId ) + aRet += B2UCONST( " embedded" ); +#endif + + return aRet; +} diff --git a/filter/source/svg/svgfontexport.hxx b/filter/source/svg/svgfontexport.hxx new file mode 100644 index 000000000000..9147efb27a55 --- /dev/null +++ b/filter/source/svg/svgfontexport.hxx @@ -0,0 +1,64 @@ + /************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SVGFONTEXPORT_HXX +#define SVGFONTEXPORT_HXX + +#include <comphelper/stl_types.hxx> +#include "svgfilter.hxx" +#include "svgwriter.hxx" + +// ----------------- +// - SVGFontExport - +// ----------------- + +class SVGFontExport +{ + typedef ::std::hash_map< ::rtl::OUString, ::std::set< sal_Unicode >, ::comphelper::UStringHash > GlyphMap; + typedef ::std::vector< ObjectRepresentation > ObjectVector; + +private: + + SvXMLExport& mrExport; + GlyphMap maGlyphs; + ObjectVector maObjects; + sal_uInt32 mnCurFontId; + + void implCollectGlyphs(); + void implEmbedFont( const ::rtl::OUString& rFontName, const ::std::set< sal_Unicode >& rGlyphs ); + void implEmbedGlyph( OutputDevice& rOut, const ::rtl::OUString& rGlyphs ); + +public: + + SVGFontExport( SvXMLExport& rExport, const ::std::vector< ObjectRepresentation >& rObjects ); + ~SVGFontExport(); + + void EmbedFonts(); + ::rtl::OUString GetMappedFontName( const ::rtl::OUString& rFontName ) const; +}; + +#endif diff --git a/filter/source/svg/svgimport.cxx b/filter/source/svg/svgimport.cxx new file mode 100644 index 000000000000..fd4f711cb085 --- /dev/null +++ b/filter/source/svg/svgimport.cxx @@ -0,0 +1,188 @@ + /************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_filter.hxx" + +#include "svgfilter.hxx" +#include "rtl/ref.hxx" +#include "jvmaccess/virtualmachine.hxx" +// ------------- +// - SVGFilter - +// ------------- + +sal_Bool SVGFilter::implImport( const Sequence< PropertyValue >& rDescriptor ) + throw (RuntimeException) +{ + Reference< XMultiServiceFactory > xServiceFactory( ::comphelper::getProcessServiceFactory() ) ; + rtl::OUString aTmpFileName; + String aFileName; + sal_Int32 nLength = rDescriptor.getLength(); + const PropertyValue* pValue = rDescriptor.getConstArray(); + sal_Bool bRet = sal_False; + + for( sal_Int32 i = 0 ; ( i < nLength ) && !aTmpFileName.getLength(); i++) + if( pValue[ i ].Name.equalsAscii( "FileName" ) ) + pValue[ i ].Value >>= aTmpFileName; + + if( aTmpFileName.getLength() && xServiceFactory.is() ) + { + + Reference< XJavaVM > xJavaVM( xServiceFactory->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.java.JavaVirtualMachine") ) ), UNO_QUERY ); + Sequence< sal_Int8 > aProcessID( 17 ); + String aLocalFile; + + if( ::utl::LocalFileHelper::ConvertURLToPhysicalName( aTmpFileName, aLocalFile ) && aLocalFile.Len() ) + { + rtl_getGlobalProcessId( (sal_uInt8 *) aProcessID.getArray() ); + aProcessID[16] = 0; + + OSL_ENSURE(sizeof (sal_Int64) + >= sizeof (jvmaccess::VirtualMachine *), + "Pointer cannot be represented as sal_Int64"); + sal_Int64 nPointer = reinterpret_cast< sal_Int64 >( + static_cast< jvmaccess::VirtualMachine * >(0)); + xJavaVM->getJavaVM(aProcessID) >>= nPointer; + rtl::Reference<jvmaccess::VirtualMachine> _virtualMachine = + reinterpret_cast< jvmaccess::VirtualMachine * >(nPointer); + if (!_virtualMachine.is()) + return bRet; + + jobjectArray aArgs; + jclass aClass; + jmethodID aMId; + jstring aJStr; + + try + { + jvmaccess::VirtualMachine::AttachGuard vmGuard(_virtualMachine); + + JNIEnv * pEnv = vmGuard.getEnvironment(); + + aClass = pEnv->FindClass( "SOTranscoder" ); + + if( aClass ) + { + aMId = pEnv->GetStaticMethodID( aClass, "main", "([Ljava/lang/String;)V" ); + if ( aMId ) + { + + ::utl::TempFile aTempFile; + String aOutputURL( aTempFile.GetURL() ); + String aOutputFile; + + aTempFile.EnableKillingFile(); + + if( ::utl::LocalFileHelper::ConvertURLToPhysicalName( aOutputURL, aOutputFile ) && aOutputFile.Len() ) + { + aJStr = pEnv->NewStringUTF( ByteString( aLocalFile.GetBuffer(), RTL_TEXTENCODING_UTF8 ).GetBuffer() ); + aArgs = static_cast<jobjectArray>(pEnv->NewObjectArray( 2, pEnv->FindClass( "java/lang/String" ), aJStr )); + aJStr = pEnv->NewStringUTF( ByteString( aOutputFile.GetBuffer(), RTL_TEXTENCODING_UTF8 ).GetBuffer() ); + pEnv->SetObjectArrayElement( aArgs, 1, aJStr ); + pEnv->CallStaticVoidMethod( aClass, aMId, aArgs ); + + Graphic aGraphic; + SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( aOutputURL, STREAM_READ ); + + if( pIStm ) + { + GraphicConverter::Import( *pIStm, aGraphic ); + delete pIStm; + } + + Reference< XDrawPagesSupplier > xDrawPagesSupplier( mxDstDoc, UNO_QUERY ); + + if( xDrawPagesSupplier.is() && ( aGraphic.GetType() != GRAPHIC_NONE ) ) + { + Reference< XDrawPages > xDrawPages( xDrawPagesSupplier->getDrawPages() ); + + if( xDrawPages.is() && xDrawPages->getCount() ) + { + Reference< XDrawPage > xDrawPage; + + if( xDrawPages->getByIndex( 0 ) >>= xDrawPage ) + { + Reference< XShapes > xShapes( xDrawPage, UNO_QUERY ); + Reference< XPropertySet> xPagePropSet( xDrawPage, UNO_QUERY ); + Reference< XShape > xShape( Reference< XMultiServiceFactory >( mxDstDoc, UNO_QUERY )->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.GraphicObjectShape" ) ) ), UNO_QUERY ); + + if( xPagePropSet.is() && xShapes.is() && xShape.is() ) + { + Reference< XPropertySet > xPropSet( xShape, UNO_QUERY ); + sal_Int32 nPageWidth = 0, nPageHeight = 0; + + xPagePropSet->getPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Width" ) ) ) >>= nPageWidth; + xPagePropSet->getPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Height" ) ) ) >>= nPageHeight; + + if( xPropSet.is() && nPageWidth && nPageHeight ) + { + xShapes->add( xShape ); + + ::com::sun::star::awt::Point aPos; + ::com::sun::star::awt::Size aSize; + GraphicObject aGraphObj( aGraphic ); + String aGraphURL( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.GraphicObject:" ) ); + Any aValue; + Size aGraphicSize; + const MapMode aTargetMapMode( MAP_100TH_MM ); + + if( aGraphObj.GetPrefMapMode().GetMapUnit() == MAP_PIXEL ) + aGraphicSize = Application::GetDefaultDevice()->PixelToLogic( aGraphObj.GetPrefSize(), aTargetMapMode ); + else + aGraphicSize = OutputDevice::LogicToLogic( aGraphObj.GetPrefSize(), aGraphObj.GetPrefMapMode(), aTargetMapMode ); + + aGraphURL += String( aGraphObj.GetUniqueID(), RTL_TEXTENCODING_ASCII_US ); + aValue <<= rtl::OUString( aGraphURL ); + xPropSet->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "GraphicURL" ) ), aValue ); + + aPos.X = ( nPageWidth - aGraphicSize.Width() ) >> 1; + aPos.Y = ( nPageHeight - aGraphicSize.Height() ) >> 1; + + aSize.Width = aGraphicSize.Width(); + aSize.Height = aGraphicSize.Height(); + + xShape->setPosition( aPos ); + xShape->setSize( aSize ); + + bRet = sal_True; + } + } + } + } + } + } + } + } + } + catch (jvmaccess::VirtualMachine::AttachGuard::CreationException &) + { + } + } + } + return bRet; +} + diff --git a/filter/source/svg/svgscript.hxx b/filter/source/svg/svgscript.hxx new file mode 100644 index 000000000000..9be9f268dd91 --- /dev/null +++ b/filter/source/svg/svgscript.hxx @@ -0,0 +1,209 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +static const char aSVGScript1[] = +"<![CDATA[\n\ + var nCurSlide = 0;\n\ + var nSlides = 0;\n\ + var aSlides = new Object();\n\ + var aMasters = new Object();\n\ + var aMasterVisibilities = new Object();\n\ +\n\ + function onClick( aEvt )\n\ + {\n\ + var nOffset = 0;\n\ +\n\ + if( aEvt.getButton() == 0 ) \n\ + nOffset = 1;\n\ + else if( aEvt.getButton() == 2 ) \n\ + nOffset = -1;\n\ +\n\ + if( 0 != nOffset )\n\ + switchSlide( aEvt, nOffset );\n\ + }\n\ +\n\ + function onKeyPress( aEvt ) \n\ + {\n\ + var nCode = String.fromCharCode( aEvt.getCharCode() );\n\ + var nOffset = 0;\n\ +\n\ + if( ( ' ' == nCode ) || \n\ + ( ( !aEvt.getCtrlKey() && !aEvt.getAltKey() && !aEvt.getMetaKey() && !aEvt.getShiftKey() ) && \n\ + ( aEvt.getKeyCode() == aEvt.DOM_VK_PAGE_DOWN() ||\n\ + aEvt.getKeyCode() == aEvt.DOM_VK_PAGE_RIGHT() ) ) )\n\ + {\n\ + nOffset = 1;\n\ + }\n\ + else if( ( !aEvt.getCtrlKey() && !aEvt.getAltKey() && !aEvt.getMetaKey() && !aEvt.getShiftKey() ) && \n\ + ( aEvt.getKeyCode() == aEvt.DOM_VK_PAGE_UP() ||\n\ + aEvt.getKeyCode() == aEvt.DOM_VK_LEFT() ) )\n\ + {\n\ + nOffset = -1\n\ + }\n\ +\n\ + if( 0 != nOffset )\n\ + switchSlide( aEvt, nOffset );\n\ + }\n\ +\n\ +"; + +static const char aSVGScript2[] = +" function switchSlide( aEvt, nOffset ) \n\ + {\n\ + var nNextSlide = nCurSlide + nOffset;\n\ +\n\ + if( nNextSlide < 0 && nSlides > 0 )\n\ + nNextSlide = nSlides - 1;\n\ + else if( nNextSlide >= nSlides ) \n\ + nNextSlide = 0;\n\ +\n\ + aSlides[ nCurSlide ].setAttributeNS( null, \"visibility\", \"hidden\" );\n\ + aSlides[ nNextSlide ].setAttributeNS( null, \"visibility\", \"visible\" );\n\ +\n\ + var aCurMaster = aMasters[ nCurSlide ];\n\ + var aCurMasterVisibility = aMasterVisibilities[ nCurSlide ];\n\ + \n\ + var aNextMaster = aMasters[ nNextSlide ];\n\ + var aNextMasterVisibility = aMasterVisibilities[ nNextSlide ];\n\ +\n\ + if( ( aCurMaster != aNextMaster ) || ( aCurMasterVisibility != aNextMasterVisibility ) ) \n\ + {\n\ + if( aCurMaster != aNextMaster )\n\ + aCurMaster.setAttributeNS( null, \"visibility\", \"hidden\" );\n\ + \n\ + aNextMaster.setAttributeNS( null, \"visibility\", aNextMasterVisibility );\n\ + }\n\ +\n\ + nCurSlide = nNextSlide; \n\ + }\n\ +\n\ + function init() \n\ + {\n\ + nSlides = document.getElementById( \"meta_slides\" ).getAttributeNS( null, \"numberOfSlides\" );\n\ +\n\ + for( i = 0; i < nSlides; i++ )\n\ + {\n\ + var aSlide = document.getElementById( \"meta_slide\" + i );\n\ + \n\ + aSlides[ i ] = document.getElementById( aSlide.getAttributeNS( null, \"slide\" ) );\n\ + aMasters[ i ] = document.getElementById( aSlide.getAttributeNS( null, \"master\" ) );\n\ + aMasterVisibilities[ i ] = aSlide.getAttributeNS( null, \"master-visibility\" );\n\ + }\n\ + }\n\ +\n\ + init();\n\ +]]>"; + +/* +<![CDATA[ + var nCurSlide = 0; + var nSlides = 0; + var aSlides = new Object(); + var aMasters = new Object(); + var aMasterVisibilities; + + function onClick( aEvt ) + { + var nOffset = 0; + + if( aEvt.getButton() == 0 ) + nOffset = 1; + else if( aEvt.getButton() == 2 ) + nOffset = -1; + + if( 0 != nOffset ) + switchSlide( aEvt, nOffset ); + } + + function onKeyPress( aEvt ) + { + var nCode = String.fromCharCode( aEvt.getCharCode() ); + var nOffset = 0; + + if( ( ' ' == nCode ) || + ( ( !aEvt.getCtrlKey() && !aEvt.getAltKey() && !aEvt.getMetaKey() && !aEvt.getShiftKey() ) && + ( aEvt.getKeyCode() == aEvt.DOM_VK_PAGE_DOWN() || + aEvt.getKeyCode() == aEvt.DOM_VK_PAGE_RIGHT() ) ) ) + { + nOffset = 1; + } + else if( ( !aEvt.getCtrlKey() && !aEvt.getAltKey() && !aEvt.getMetaKey() && !aEvt.getShiftKey() ) && + ( aEvt.getKeyCode() == aEvt.DOM_VK_PAGE_UP() || + aEvt.getKeyCode() == aEvt.DOM_VK_LEFT() ) ) + { + nOffset = -1 + } + + if( 0 != nOffset ) + switchSlide( aEvt, nOffset ); + } + + function switchSlide( aEvt, nOffset ) + { + var nNextSlide = nCurSlide + nOffset; + + if( nNextSlide < 0 && nSlides > 0 ) + nNextSlide = nSlides - 1; + else if( nNextSlide >= nSlides ) + nNextSlide = 0; + + aSlides[ nCurSlide ].setAttributeNS( null, "visibility", "hidden" ); + aSlides[ nNextSlide ].setAttributeNS( null, "visibility", "visible" ); + + var aCurMaster = aMasters[ nCurSlide ]; + var aCurMasterVisibility = aMasterVisibilities[ nCurSlide ]; + + var aNextMaster = aMasters[ nNextSlide ]; + var aNextMasterVisibility = aMasterVisibilities[ nNextSlide ]; + + if( ( aCurMaster != aNextMaster ) || ( aCurMasterVisibility != aNextMasterVisibility ) ) + { + if( aCurMaster != aNextMaster ) + aCurMaster.setAttributeNS( null, "visibility", "hidden" ); + + aNextMaster.setAttributeNS( null, "visibility", aNextMasterVisibility ); + } + + nCurSlide = nNextSlide; + } + + function init() + { + nSlides = document.getElementById( "meta_slides" ).getAttributeNS( null, "numberOfSlides" ); + + for( i = 0; i < nSlides; i++ ) + { + var aSlide = document.getElementById( "meta_slide" + i ); + + aSlides[ i ] = document.getElementById( aSlide.getAttributeNS( null, "slide" ) ); + aMasters[ i ] = document.getElementById( aSlide.getAttributeNS( null, "master" ) ); + aMasterVisibilities[ i ] = aSlide.getAttributeNS( null, "master-visibility" ); + } + } + + init(); +]]*/ diff --git a/filter/source/svg/svguno.cxx b/filter/source/svg/svguno.cxx new file mode 100644 index 000000000000..f20bfb6a526d --- /dev/null +++ b/filter/source/svg/svguno.cxx @@ -0,0 +1,76 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_filter.hxx" + +#include <stdio.h> +#include <osl/mutex.hxx> +#include <osl/thread.h> +#include <cppuhelper/factory.hxx> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> + +#include <svgfilter.hxx> + +using ::rtl::OUString; +using namespace ::cppu; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::registry; + +extern "C" +{ + //================================================================================================== + SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */ ) + { + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; + } + //================================================================================================== + SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * /* pRegistryKey */ ) + { + void * pRet = 0; + + OUString implName = OUString::createFromAscii( pImplName ); + if ( pServiceManager && implName.equals(SVGFilter_getImplementationName()) ) + { + Reference< XSingleServiceFactory > xFactory( createSingleFactory( + reinterpret_cast< XMultiServiceFactory * >( pServiceManager ), + OUString::createFromAscii( pImplName ), + SVGFilter_createInstance, SVGFilter_getSupportedServiceNames() ) ); + + if (xFactory.is()) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + } + + return pRet; + } +} diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx new file mode 100644 index 000000000000..15f83c3be407 --- /dev/null +++ b/filter/source/svg/svgwriter.cxx @@ -0,0 +1,1657 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_filter.hxx" + +#include "svgfontexport.hxx" +#include "svgwriter.hxx" + +// ----------- +// - statics - +// ----------- + +static const char aXMLElemG[] = "g"; +static const char aXMLElemDefs[] = "defs"; +static const char aXMLElemClipPath[] = "clipPath"; +static const char aXMLElemLine[] = "line"; +static const char aXMLElemRect[] = "rect"; +static const char aXMLElemEllipse[] = "ellipse"; +static const char aXMLElemPath[] = "path"; +static const char aXMLElemPolygon[] = "polygon"; +static const char aXMLElemPolyLine[] = "polyline"; +static const char aXMLElemText[] = "text"; +static const char aXMLElemTSpan[] = "tspan"; +static const char aXMLElemImage[] = "image"; + +static const char aXMLAttrTransform[] = "transform"; +static const char aXMLAttrStyle[] = "style"; +static const char aXMLAttrId[] = "id"; +static const char aXMLAttrD[] = "d"; +static const char aXMLAttrX[] = "x"; +static const char aXMLAttrY[] = "y"; +static const char aXMLAttrX1[] = "x1"; +static const char aXMLAttrY1[] = "y1"; +static const char aXMLAttrX2[] = "x2"; +static const char aXMLAttrY2[] = "y2"; +static const char aXMLAttrCX[] = "cx"; +static const char aXMLAttrCY[] = "cy"; +static const char aXMLAttrRX[] = "rx"; +static const char aXMLAttrRY[] = "ry"; +static const char aXMLAttrWidth[] = "width"; +static const char aXMLAttrHeight[] = "height"; +static const char aXMLAttrPoints[] = "points"; +static const char aXMLAttrXLinkHRef[] = "xlink:href"; + +static const sal_Unicode pBase64[] = +{ + //0 1 2 3 4 5 6 7 + 'A','B','C','D','E','F','G','H', // 0 + 'I','J','K','L','M','N','O','P', // 1 + 'Q','R','S','T','U','V','W','X', // 2 + 'Y','Z','a','b','c','d','e','f', // 3 + 'g','h','i','j','k','l','m','n', // 4 + 'o','p','q','r','s','t','u','v', // 5 + 'w','x','y','z','0','1','2','3', // 6 + '4','5','6','7','8','9','+','/' // 7 +}; + +// -------------- +// - FastString - +// -------------- + +FastString::FastString( sal_uInt32 nInitLen, sal_uInt32 nIncrement ) : + mnBufLen( nInitLen ), + mnCurLen( 0 ), + mnBufInc( nIncrement ), + mpBuffer( new sal_Unicode[ nInitLen * sizeof( sal_Unicode ) ] ), + mnPartPos( 0 ) +{ + DBG_ASSERT( nInitLen, "invalid initial length" ); + DBG_ASSERT( nIncrement, "invalid increment" ); +} + +// ----------------------------------------------------------------------------- + +FastString::FastString( sal_Char* pBufferForBase64Encoding, sal_uInt32 nBufLen ) : + mnBufInc( 2048 ), + mnPartPos( 0 ) +{ + DBG_ASSERT( pBufferForBase64Encoding && nBufLen, "invalid arguments" ); + + const sal_uInt32 nQuadCount = nBufLen / 3; + const sal_uInt32 nRest = nBufLen % 3; + + if( nQuadCount || nRest ) + { + mnBufLen = mnCurLen = ( ( nQuadCount + ( nRest ? 1 : 0 ) ) << 2 ); + mpBuffer = new sal_Unicode[ mnBufLen * sizeof( sal_Unicode ) ]; + + sal_Char* pTmpSrc = pBufferForBase64Encoding; + sal_Unicode* pTmpDst = mpBuffer; + + for( sal_uInt32 i = 0; i < nQuadCount; i++ ) + { + const sal_Int32 nA = *pTmpSrc++; + const sal_Int32 nB = *pTmpSrc++; + const sal_Int32 nC = *pTmpSrc++; + + *pTmpDst++ = pBase64[ ( nA >> 2 ) & 0x3f ]; + *pTmpDst++ = pBase64[ ( ( nA << 4 ) & 0x30 ) + ( ( nB >> 4 ) & 0xf ) ]; + *pTmpDst++ = pBase64[ ( ( nB << 2 ) & 0x3c ) + ( ( nC >> 6 ) & 0x3 ) ]; + *pTmpDst++ = pBase64[ nC & 0x3f ]; + } + + if( 1 == nRest ) + { + const sal_Int32 nA = *pTmpSrc; + + *pTmpDst++ = pBase64[ ( nA >> 2 ) & 0x3f ]; + *pTmpDst++ = pBase64[ ( nA << 4 ) & 0x30 ]; + *pTmpDst++ = '='; + *pTmpDst = '='; + } + else if( 2 == nRest ) + { + const sal_Int32 nA = *pTmpSrc++; + const sal_Int32 nB = *pTmpSrc; + + *pTmpDst++ = pBase64[ ( nA >> 2 ) & 0x3f ]; + *pTmpDst++ = pBase64[ ( ( nA << 4 ) & 0x30 ) + ( ( nB >> 4 ) & 0xf ) ]; + *pTmpDst++ = pBase64[ ( nB << 2 ) & 0x3c ]; + *pTmpDst = '='; + } + } + else + { + mpBuffer = new sal_Unicode[ ( mnBufLen = 1 ) * sizeof( sal_Unicode ) ]; + mnCurLen = 0; + } +} + +// ----------------------------------------------------------------------------- + +FastString::~FastString() +{ + delete[] mpBuffer; +} + +// ----------------------------------------------------------------------------- + +FastString& FastString::operator+=( const NMSP_RTL::OUString& rStr ) +{ + if( rStr.getLength() ) + { + if( ( mnCurLen + rStr.getLength() ) > mnBufLen ) + { + const sal_uInt32 nNewBufLen = ( mnBufLen + ( ( ( mnCurLen + rStr.getLength() ) - mnBufLen ) / mnBufInc + 1 ) * mnBufInc ); + sal_Unicode* pNewBuffer = new sal_Unicode[ nNewBufLen * sizeof( sal_Unicode ) ]; + + memcpy( pNewBuffer, mpBuffer, mnBufLen * sizeof( sal_Unicode ) ); + delete[] mpBuffer; + mpBuffer = pNewBuffer; + mnBufLen = nNewBufLen; + } + + memcpy( mpBuffer + mnCurLen, rStr.getStr(), rStr.getLength() * sizeof( sal_Unicode ) ); + mnCurLen += rStr.getLength(); + + if( maString.getLength() ) + maString = NMSP_RTL::OUString(); + } + + return *this; +} + +// ----------------------------------------------------------------------------- + +const NMSP_RTL::OUString& FastString::GetString() const +{ + if( !maString.getLength() && mnCurLen ) + ( (FastString*) this )->maString = NMSP_RTL::OUString( mpBuffer, mnCurLen ); + + return maString; +} + +// ----------------------------------------------------------------------------- + +sal_Bool FastString::GetFirstPartString( const sal_uInt32 nPartLen, NMSP_RTL::OUString& rPartString ) +{ + const sal_uInt32 nLength = Min( mnCurLen, nPartLen ); + + mnPartPos = 0; + + if( nLength ) + { + rPartString = NMSP_RTL::OUString( mpBuffer, nLength ); + mnPartPos = nLength; + } + + return( rPartString.getLength() > 0 ); +} + +// ----------------------------------------------------------------------------- + +sal_Bool FastString::GetNextPartString( const sal_uInt32 nPartLen, NMSP_RTL::OUString& rPartString ) +{ + if( mnPartPos < mnCurLen ) + { + const sal_uInt32 nLength = Min( mnCurLen - mnPartPos, nPartLen ); + rPartString = NMSP_RTL::OUString( mpBuffer + mnPartPos, nLength ); + mnPartPos += nLength; + } + else + rPartString = NMSP_RTL::OUString(); + + return( rPartString.getLength() > 0 ); +} + +// ---------------------- +// - SVGAttributeWriter - +// ---------------------- + +SVGAttributeWriter::SVGAttributeWriter( SvXMLExport& rExport, SVGFontExport& rFontExport ) : + mrExport( rExport ), + mrFontExport( rFontExport ), + mpElemFont( NULL ), + mpElemPaint( NULL ) +{ +} + +// ----------------------------------------------------------------------------- + +SVGAttributeWriter::~SVGAttributeWriter() +{ + delete mpElemPaint; + delete mpElemFont; +} + +// ----------------------------------------------------------------------------- + +NMSP_RTL::OUString SVGAttributeWriter::GetFontStyle( const Font& rFont ) +{ + FastString aStyle; + + // font family + aStyle += B2UCONST( "font-family:" ); + aStyle += mrFontExport.GetMappedFontName( rFont.GetName() ); + + // font size + aStyle += B2UCONST( ";" ); + aStyle += B2UCONST( "font-size:" ); + aStyle += SVGActionWriter::GetValueString( rFont.GetHeight() ); + + // font style +/* + if( rFont.GetItalic() != ITALIC_NONE ) + { + aStyle += B2UCONST( ";" ); + aStyle += B2UCONST( "font-style:" ); + + if( rFont.GetItalic() == ITALIC_OBLIQUE ) + aStyle += B2UCONST( "oblique" ); + else + aStyle += B2UCONST( "italic" ); + } +*/ + + // font weight + sal_Int32 nFontWeight; + + switch( rFont.GetWeight() ) + { + case WEIGHT_THIN: nFontWeight = 100; break; + case WEIGHT_ULTRALIGHT: nFontWeight = 200; break; + case WEIGHT_LIGHT: nFontWeight = 300; break; + case WEIGHT_SEMILIGHT: nFontWeight = 400; break; + case WEIGHT_NORMAL: nFontWeight = 400; break; + case WEIGHT_MEDIUM: nFontWeight = 500; break; + case WEIGHT_SEMIBOLD: nFontWeight = 600; break; + case WEIGHT_BOLD: nFontWeight = 700; break; + case WEIGHT_ULTRABOLD: nFontWeight = 800; break; + case WEIGHT_BLACK: nFontWeight = 900; break; + default: nFontWeight = 400; break; + } + + aStyle += B2UCONST( ";" ); + aStyle += B2UCONST( "font-weight:" ); + aStyle += NMSP_RTL::OUString::valueOf( nFontWeight ); + + // !!! + // font-variant + // font-stretch + // font-size-adjust + +#ifdef _SVG_USE_NATIVE_TEXTDECORATION + + if( rFont.GetUnderline() != UNDERLINE_NONE || rFont.GetStrikeout() != STRIKEOUT_NONE ) + { + aStyle += B2UCONST( ";" ); + aStyle += B2UCONST( "text-decoration:" ); + + if( rFont.GetUnderline() != UNDERLINE_NONE ) + aStyle += B2UCONST( " underline" ); + + if( rFont.GetStrikeout() != STRIKEOUT_NONE ) + aStyle += B2UCONST( " line-through" ); + } + +#endif // _SVG_USE_NATIVE_TEXTDECORATION + + return aStyle.GetString(); +} + +// ----------------------------------------------------------------------------- + +NMSP_RTL::OUString SVGAttributeWriter::GetPaintStyle( const Color& rLineColor, const Color& rFillColor, const LineInfo* pLineInfo ) +{ + FastString aStyle; + + // line color + aStyle += B2UCONST( "stroke:" ); + + if( rLineColor.GetTransparency() == 255 ) + aStyle += B2UCONST( "none" ); + else + { + // line color value in rgb + aStyle += B2UCONST( "rgb(" ); + aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rLineColor.GetRed() ); + aStyle += B2UCONST( "," ); + aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rLineColor.GetGreen() ); + aStyle += B2UCONST( "," ); + aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rLineColor.GetBlue() ); + aStyle += B2UCONST( ")" ); + + // line color opacity in percent if neccessary + if( rLineColor.GetTransparency() ) + { + aStyle += B2UCONST( ";" ); + aStyle += B2UCONST( "stroke-opacity:" ); + aStyle += NMSP_RTL::OUString::valueOf( ( 255 - (double) rLineColor.GetTransparency() ) / 255.0 ); + } + + if(pLineInfo) + { + // more infos for line needed + if(pLineInfo->GetWidth() > 1) + { + aStyle += B2UCONST( ";" ); + aStyle += B2UCONST( "stroke-width:" ); + aStyle += NMSP_RTL::OUString::valueOf(pLineInfo->GetWidth()); + } + + if(LINE_DASH == pLineInfo->GetStyle()) + { + aStyle += B2UCONST( ";" ); + aStyle += B2UCONST( "stroke-dasharray:" ); + const long nDashLen(pLineInfo->GetDashLen()); + const long nDotLen(pLineInfo->GetDotLen()); + const long nDistance(pLineInfo->GetDistance()); + bool bIsFirst(true); + + for(sal_uInt16 a(0); a < pLineInfo->GetDashCount(); a++) + { + if(bIsFirst) + aStyle += B2UCONST(" "), bIsFirst = false; + else + aStyle += B2UCONST(","); + aStyle += NMSP_RTL::OUString::valueOf(nDashLen); + aStyle += B2UCONST(","); + aStyle += NMSP_RTL::OUString::valueOf(nDistance); + } + + for(sal_uInt16 b(0); b < pLineInfo->GetDotCount(); b++) + { + if(bIsFirst) + aStyle += B2UCONST(" "), bIsFirst = false; + else + aStyle += B2UCONST(","); + aStyle += NMSP_RTL::OUString::valueOf(nDotLen); + aStyle += B2UCONST(","); + aStyle += NMSP_RTL::OUString::valueOf(nDistance); + } + } + + if(basegfx::B2DLINEJOIN_MITER != pLineInfo->GetLineJoin()) + { + aStyle += B2UCONST( ";" ); + aStyle += B2UCONST( "stroke-linejoin:" ); + + switch(pLineInfo->GetLineJoin()) + { + default: // B2DLINEJOIN_NONE, B2DLINEJOIN_MIDDLE, B2DLINEJOIN_MITER + aStyle += B2UCONST( "miter" ); + break; + case basegfx::B2DLINEJOIN_ROUND: + aStyle += B2UCONST( "round" ); + break; + case basegfx::B2DLINEJOIN_BEVEL: + aStyle += B2UCONST( "bevel" ); + break; + } + } + } + } + + // fill color + aStyle += B2UCONST( ";" ); + aStyle += B2UCONST( "fill:" ); + + if( rFillColor.GetTransparency() == 255 ) + aStyle += B2UCONST( "none" ); + else + { + // fill color value in rgb + aStyle += B2UCONST( "rgb(" ); + aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rFillColor.GetRed() ); + aStyle += B2UCONST( "," ); + aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rFillColor.GetGreen() ); + aStyle += B2UCONST( "," ); + aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rFillColor.GetBlue() ); + aStyle += B2UCONST( ")" ); + + // fill color opacity in percent if neccessary + if( rFillColor.GetTransparency() ) + { + aStyle += B2UCONST( ";" ); + aStyle += B2UCONST( "fill-opacity:" ); + aStyle += NMSP_RTL::OUString::valueOf( ( 255 - (double) rFillColor.GetTransparency() ) / 255.0 ); + } + } + + return aStyle.GetString(); +} + +// ----------------------------------------------------------------------------- + +void SVGAttributeWriter::SetFontAttr( const Font& rFont ) +{ + if( !mpElemFont || ( rFont != maCurFont ) ) + { + delete mpElemPaint, mpElemPaint = NULL; + delete mpElemFont; + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, GetFontStyle( maCurFont = rFont ) ); + mpElemFont = new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE ); + } +} + +// ----------------------------------------------------------------------------- + +void SVGAttributeWriter::SetPaintAttr( const Color& rLineColor, const Color& rFillColor, const LineInfo* pLineInfo ) +{ + if( !mpElemPaint || ( rLineColor != maCurLineColor ) || ( rFillColor != maCurFillColor ) ) + { + delete mpElemPaint; + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, GetPaintStyle( maCurLineColor = rLineColor, maCurFillColor = rFillColor, pLineInfo ) ); + mpElemPaint = new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE ); + } +} + +// ------------------- +// - SVGActionWriter - +// ------------------- + +SVGActionWriter::SVGActionWriter( SvXMLExport& rExport, SVGFontExport& rFontExport ) : + mrExport( rExport ), + mrFontExport( rFontExport ), + mpContext( NULL ), + mbClipAttrChanged( sal_False ), + mnCurClipId( 1 ) +{ + mpVDev = new VirtualDevice; + mpVDev->EnableOutput( sal_False ); + maTargetMapMode = MAP_100TH_MM; +} + +// ----------------------------------------------------------------------------- + +SVGActionWriter::~SVGActionWriter() +{ + DBG_ASSERT( !mpContext, "Not all contexts are closed" ); + delete mpVDev; +} + +// ----------------------------------------------------------------------------- + +long SVGActionWriter::ImplMap( sal_Int32 nVal ) const +{ + return ImplMap( Size( nVal, nVal ) ).Width(); +} + +// ----------------------------------------------------------------------------- + +Point SVGActionWriter::ImplMap( const Point& rPt ) const +{ + return mpVDev->LogicToLogic( rPt, mpVDev->GetMapMode(), maTargetMapMode ); +} + +// ----------------------------------------------------------------------------- + +Size SVGActionWriter::ImplMap( const Size& rSz ) const +{ + return mpVDev->LogicToLogic( rSz, mpVDev->GetMapMode(), maTargetMapMode ); +} + +// ----------------------------------------------------------------------------- + +LineInfo SVGActionWriter::ImplMap( const LineInfo& rLineInfo ) const +{ + LineInfo aInfo(rLineInfo); + long aTemp(0); + + if(aInfo.GetStyle() == LINE_DASH) + { + if(aInfo.GetDotCount() && aInfo.GetDotLen()) + { + aTemp = aInfo.GetDotLen(); + mpVDev->LogicToLogic(&aTemp, 1, &mpVDev->GetMapMode(), &maTargetMapMode); + aInfo.SetDotLen(Max(aTemp, 1L)); + } + else + aInfo.SetDotCount(0); + + if(aInfo.GetDashCount() && aInfo.GetDashLen()) + { + aTemp = aInfo.GetDashLen(); + mpVDev->LogicToLogic(&aTemp, 1, &mpVDev->GetMapMode(), &maTargetMapMode); + aInfo.SetDashLen(Max(aTemp, 1L)); + } + else + aInfo.SetDashCount(0); + + aTemp = aInfo.GetDistance(); + mpVDev->LogicToLogic(&aTemp, 1, &mpVDev->GetMapMode(), &maTargetMapMode); + aInfo.SetDistance(aTemp); + + if((!aInfo.GetDashCount() && !aInfo.GetDotCount()) || !aInfo.GetDistance()) + aInfo.SetStyle(LINE_SOLID); + } + + aTemp = aInfo.GetWidth(); + mpVDev->LogicToLogic(&aTemp, 1, &mpVDev->GetMapMode(), &maTargetMapMode); + aInfo.SetWidth(aTemp); + + return aInfo; +} + +// ----------------------------------------------------------------------------- + +NMSP_RTL::OUString SVGActionWriter::GetValueString( sal_Int32 nVal ) +{ + return ::rtl::OUString::valueOf( nVal ); +} + +// ----------------------------------------------------------------------------- + +NMSP_RTL::OUString SVGActionWriter::GetPathString( const PolyPolygon& rPolyPoly, sal_Bool bLine ) +{ + FastString aPathData; + const NMSP_RTL::OUString aBlank( B2UCONST( " " ) ); + const NMSP_RTL::OUString aComma( B2UCONST( "," ) ); + Point aPolyPoint; + + for( long i = 0, nCount = rPolyPoly.Count(); i < nCount; i++ ) + { + const Polygon& rPoly = rPolyPoly[ (USHORT) i ]; + USHORT n = 1, nSize = rPoly.GetSize(); + + if( nSize > 1 ) + { + aPathData += B2UCONST( "M " ); + aPathData += GetValueString( ( aPolyPoint = rPoly[ 0 ] ).X() ); + aPathData += aComma; + aPathData += GetValueString( aPolyPoint.Y() ); + sal_Char nCurrentMode = 0; + + while( n < nSize ) + { + aPathData += aBlank; + if ( ( rPoly.GetFlags( n ) == POLY_CONTROL ) && ( ( n + 2 ) < nSize ) ) + { + if ( nCurrentMode != 'C' ) + { + nCurrentMode = 'C'; + aPathData += B2UCONST( "C " ); + } + for ( int j = 0; j < 3; j++ ) + { + if ( j ) + aPathData += aBlank; + aPathData += GetValueString( ( aPolyPoint = rPoly[ n++ ] ).X() ); + aPathData += aComma; + aPathData += GetValueString( aPolyPoint.Y() ); + } + } + else + { + if ( nCurrentMode != 'L' ) + { + nCurrentMode = 'L'; + aPathData += B2UCONST( "L " ); + } + aPathData += GetValueString( ( aPolyPoint = rPoly[ n++ ] ).X() ); + aPathData += aComma; + aPathData += GetValueString( aPolyPoint.Y() ); + } + } + + if( !bLine ) + aPathData += B2UCONST( " Z" ); + + if( i < ( nCount - 1 ) ) + aPathData += aBlank; + } + } + + return aPathData.GetString(); +} + +// ----------------------------------------------------------------------------- + +void SVGActionWriter::ImplWriteLine( const Point& rPt1, const Point& rPt2, const Color* pLineColor, + const NMSP_RTL::OUString* pStyle ) +{ + const Point aPt1( ImplMap( rPt1 ) ); + const Point aPt2( ImplMap( rPt2 ) ); + + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX1, GetValueString( aPt1.X() ) ); + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY1, GetValueString( aPt1.Y() ) ); + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX2, GetValueString( aPt2.X() ) ); + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY2, GetValueString( aPt2.Y() ) ); + + // add additional style if requested + if( pStyle ) + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, *pStyle ); + + if( pLineColor ) + { + // !!! mrExport.AddAttribute( XML_NAMESPACE_NONE, ... ) + DBG_ERROR( "SVGActionWriter::ImplWriteLine: Line color not implemented" ); + } + + { + SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemLine, TRUE, TRUE ); + } +} + +// ----------------------------------------------------------------------------- + +void SVGActionWriter::ImplWriteRect( const Rectangle& rRect, long nRadX, long nRadY, + const NMSP_RTL::OUString* pStyle ) +{ + const Rectangle aRect( ImplMap( rRect ) ); + + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, GetValueString( aRect.Left() ) ); + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, GetValueString( aRect.Top() ) ); + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrWidth, GetValueString( aRect.GetWidth() ) ); + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrHeight, GetValueString( aRect.GetHeight() ) ); + + if( nRadX ) + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrRX, GetValueString( ImplMap( nRadX ) ) ); + + if( nRadY ) + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrRY, GetValueString( ImplMap( nRadY ) ) ); + + // add additional style if requested + if( pStyle ) + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, *pStyle ); + + { + SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemRect, TRUE, TRUE ); + } +} + +// ----------------------------------------------------------------------------- + +void SVGActionWriter::ImplWriteEllipse( const Point& rCenter, long nRadX, long nRadY, + const NMSP_RTL::OUString* pStyle ) +{ + const Point aCenter( ImplMap( rCenter ) ); + + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrCX, GetValueString( aCenter.X() ) ); + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrCY, GetValueString( aCenter.Y() ) ); + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrRX, GetValueString( ImplMap( nRadX ) ) ); + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrRY, GetValueString( ImplMap( nRadY ) ) ); + + // add additional style if requested + if( pStyle ) + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, *pStyle ); + + { + SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemEllipse, TRUE, TRUE ); + } +} + +// ----------------------------------------------------------------------------- + +void SVGActionWriter::ImplWritePolyPolygon( const PolyPolygon& rPolyPoly, sal_Bool bLineOnly, + const NMSP_RTL::OUString* pStyle ) +{ + if( rPolyPoly.Count() ) + { + PolyPolygon aMappedPolyPoly; + FastString aStyle; + + for( USHORT i = 0, nCount = rPolyPoly.Count(); i < nCount; i++ ) + { + const Polygon& rPoly = rPolyPoly[ i ]; + const USHORT nSize = rPoly.GetSize(); + + // #i102224# congratulations, this throws away the curve flags + // and makes ANY curved polygon look bad. The Flags HAVE to be + // copied, too. It's NOT enough to copy the mapped points. Just + // copy the original polygon completely and REPLACE the points + + // old: Polygon aMappedPoly( nSize ); + // new: + Polygon aMappedPoly(rPoly); + + for( USHORT n = 0; n < nSize; n++ ) + aMappedPoly[ n ] = ImplMap( rPoly[ n ] ); + + aMappedPolyPoly.Insert( aMappedPoly ); + } + + if( bLineOnly ) + { + aStyle += B2UCONST( "fill:none" ); + if( pStyle ) + aStyle += B2UCONST( ";" ); + } + if( pStyle ) + aStyle += *pStyle; + + // add style attribute + if( aStyle.GetLength() ) + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, aStyle.GetString() ); + + // add path data attribute + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrD, GetPathString( aMappedPolyPoly, bLineOnly ) ); + { + // write polyline/polygon element + SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemPath, TRUE, TRUE ); + } + } +} + +// ----------------------------------------------------------------------------- + +void SVGActionWriter::ImplWriteGradientEx( const PolyPolygon& rPolyPoly, const Gradient& rGradient, + const NMSP_RTL::OUString* pStyle, sal_uInt32 nWriteFlags ) +{ + if( rPolyPoly.Count() ) + { + SvXMLElementExport aElemG( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE ); + FastString aClipId; + FastString aClipStyle; + + aClipId += B2UCONST( "clip" ); + aClipId += NMSP_RTL::OUString::valueOf( ImplGetNextClipId() ); + + { + SvXMLElementExport aElemDefs( mrExport, XML_NAMESPACE_NONE, aXMLElemDefs, TRUE, TRUE ); + + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrId, aClipId.GetString() ); + + { + SvXMLElementExport aElemClipPath( mrExport, XML_NAMESPACE_NONE, aXMLElemClipPath, TRUE, TRUE ); + ImplWritePolyPolygon( rPolyPoly, sal_False ); + } + } + + // create new context with clippath set + aClipStyle += B2UCONST( "clip-path:URL(#" ); + aClipStyle += aClipId.GetString(); + aClipStyle += B2UCONST( ")" ); + + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, aClipStyle.GetString() ); + + { + GDIMetaFile aTmpMtf; + SvXMLElementExport aElemG2( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE ); + + mpVDev->AddGradientActions( rPolyPoly.GetBoundRect(), rGradient, aTmpMtf ); + ImplWriteActions( aTmpMtf, pStyle, nWriteFlags ); + } + } +} + +// ----------------------------------------------------------------------------- + +void SVGActionWriter::ImplWriteText( const Point& rPos, const String& rText, + const sal_Int32* pDXArray, long nWidth, + const NMSP_RTL::OUString* pStyle ) +{ + long nLen = rText.Len(), i; + + if( nLen ) + { + Size aNormSize; + sal_Int32* pOwnArray; + sal_Int32* pDX; + + // get text sizes + if( pDXArray ) + { + pOwnArray = NULL; + aNormSize = Size( mpVDev->GetTextWidth( rText ), 0 ); + pDX = (sal_Int32*) pDXArray; + } + else + { + pOwnArray = new sal_Int32[ nLen ]; + aNormSize = Size( mpVDev->GetTextArray( rText, pOwnArray ), 0 ); + pDX = pOwnArray; + } + + if( nLen > 1 ) + { + aNormSize.Width() = pDX[ nLen - 2 ] + mpVDev->GetTextWidth( rText.GetChar( sal::static_int_cast<USHORT>( nLen - 1 ) ) ); + + if( nWidth && aNormSize.Width() && ( nWidth != aNormSize.Width() ) ) + { + const double fFactor = (double) nWidth / aNormSize.Width(); + + for( i = 0; i < ( nLen - 1 ); i++ ) + pDX[ i ] = FRound( pDX[ i ] * fFactor ); + } + } + + FastString aStyle; + const Font& rFont = mpVDev->GetFont(); + const FontMetric aMetric( mpVDev->GetFontMetric() ); + Point aBaseLinePos( rPos ); + SvXMLElementExport* pTransform = NULL; + + // always adjust text position to match baseline alignment + switch( rFont.GetAlign() ) + { + case( ALIGN_TOP ): + aBaseLinePos.Y() += aMetric.GetAscent(); + break; + + case( ALIGN_BOTTOM ): + aBaseLinePos.Y() -= aMetric.GetDescent(); + break; + + default: + break; + } + + // get mapped text position + const Point aPt( ImplMap( aBaseLinePos ) ); + + // if text is italic, set transform at new g element + if( ( rFont.GetItalic() != ITALIC_NONE ) || rFont.GetOrientation() ) + { + String aTransform; + + aTransform = NMSP_RTL::OUString::createFromAscii( "translate" ); + aTransform += '('; + aTransform += String( GetValueString( aPt.X() ) ); + aTransform += ','; + aTransform += String( GetValueString( aPt.Y() ) ); + aTransform += ')'; + + if( rFont.GetOrientation() ) + { + aTransform += String( NMSP_RTL::OUString::createFromAscii( " rotate" ) ); + aTransform += '('; + aTransform += String( NMSP_RTL::OUString::valueOf( rFont.GetOrientation() * -0.1 ) ); + aTransform += ')'; + } + + if( rFont.GetItalic() != ITALIC_NONE ) + { + aTransform += String( NMSP_RTL::OUString::createFromAscii( " skewX" ) ); + aTransform += '('; + aTransform += String( NMSP_RTL::OUString::valueOf( (sal_Int32) -10 ) ); + aTransform += ')'; + } + + aTransform += String( NMSP_RTL::OUString::createFromAscii( " translate" ) ); + aTransform += '('; + aTransform += String( GetValueString( -aPt.X() ) ); + aTransform += ','; + aTransform += String( GetValueString( -aPt.Y() ) ); + aTransform += ')'; + + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrTransform, aTransform ); + pTransform = new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE ); + } + + // add additional style if requested + if( pStyle && pStyle->getLength() ) + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, *pStyle ); + + // write text element + { +#ifdef _SVG_USE_TSPANS + SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemText, TRUE, TRUE ); + FastString aTSpanX; + const NMSP_RTL::OUString aSpace( ' ' ); + String aOutputText( rText ); + long nCurPos = 0; + bool bIgnoreWhitespace = true; + + for( long j = 0, nX = aPt.X(); j < nLen; ++j ) + { + const sal_Unicode cCode = rText.GetChar( sal::static_int_cast<USHORT>( j ) ); + + // don't take more than one whitespace into account + if( !bIgnoreWhitespace || ( ' ' != cCode ) ) + { + aOutputText.SetChar( sal::static_int_cast<USHORT>( nCurPos++ ), cCode ); + ( aTSpanX += GetValueString( nX + ( ( j > 0 ) ? pDX[ j - 1 ] : 0 ) ) ) += aSpace; + bIgnoreWhitespace = ( ' ' == cCode ); + } + } + + if( nCurPos < nLen ) + aOutputText.Erase( sal::static_int_cast<USHORT>( nCurPos ) ); + + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, aTSpanX.GetString() ); + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, GetValueString( aPt.Y() ) ); + + { + SvXMLElementExport aElem2( mrExport, XML_NAMESPACE_NONE, aXMLElemTSpan, TRUE, TRUE ); + mrExport.GetDocHandler()->characters( aOutputText ); + } +#else + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, GetValueString( aPt.X() ) ); + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, GetValueString( aPt.Y() ) ); + + { + SvXMLElementExport aElem2( mrExport, XML_NAMESPACE_NONE, aXMLElemText, TRUE, TRUE ); + mrExport.GetDocHandler()->characters( rText ); + } +#endif + } + +#ifndef _SVG_USE_NATIVE_TEXTDECORATION + // write strikeout if neccessary + if( rFont.GetStrikeout() || rFont.GetUnderline() ) + { + Polygon aPoly( 4 ); + const long nLineHeight = Max( (long) FRound( aMetric.GetLineHeight() * 0.05 ), (long) 1 ); + + if( rFont.GetStrikeout() ) + { + const long nYLinePos = aBaseLinePos.Y() - FRound( aMetric.GetAscent() * 0.26 ); + + aPoly[ 0 ].X() = aBaseLinePos.X(); aPoly[ 0 ].Y() = nYLinePos - ( nLineHeight >> 1 ); + aPoly[ 1 ].X() = aBaseLinePos.X() + aNormSize.Width() - 1; aPoly[ 1 ].Y() = aPoly[ 0 ].Y(); + aPoly[ 2 ].X() = aPoly[ 1 ].X(); aPoly[ 2 ].Y() = aPoly[ 0 ].Y() + nLineHeight - 1; + aPoly[ 3 ].X() = aPoly[ 0 ].X(); aPoly[ 3 ].Y() = aPoly[ 2 ].Y(); + + ImplWritePolyPolygon( aPoly, sal_False ); + } + + if( rFont.GetUnderline() ) + { + const long nYLinePos = aBaseLinePos.Y() + ( nLineHeight << 1 ); + + aPoly[ 0 ].X() = aBaseLinePos.X(); aPoly[ 0 ].Y() = nYLinePos - ( nLineHeight >> 1 ); + aPoly[ 1 ].X() = aBaseLinePos.X() + aNormSize.Width() - 1; aPoly[ 1 ].Y() = aPoly[ 0 ].Y(); + aPoly[ 2 ].X() = aPoly[ 1 ].X(); aPoly[ 2 ].Y() = aPoly[ 0 ].Y() + nLineHeight - 1; + aPoly[ 3 ].X() = aPoly[ 0 ].X(); aPoly[ 3 ].Y() = aPoly[ 2 ].Y(); + + ImplWritePolyPolygon( aPoly, sal_False ); + } + } +#endif // _SVG_USE_NATIVE_TEXTDECORATION + + delete[] pOwnArray; + delete pTransform; + } +} + +// ----------------------------------------------------------------------------- + +void SVGActionWriter::ImplWriteBmp( const BitmapEx& rBmpEx, + const Point& rPt, const Size& rSz, + const Point& rSrcPt, const Size& rSrcSz, + const NMSP_RTL::OUString* /* pStyle */ ) +{ + if( !!rBmpEx ) + { + BitmapEx aBmpEx( rBmpEx ); + Point aPoint = Point(); + const Rectangle aBmpRect( aPoint, rBmpEx.GetSizePixel() ); + const Rectangle aSrcRect( rSrcPt, rSrcSz ); + + if( aSrcRect != aBmpRect ) + aBmpEx.Crop( aSrcRect ); + + if( !!aBmpEx ) + { + SvMemoryStream aOStm( 65535, 65535 ); + + if( GraphicConverter::Export( aOStm, rBmpEx, CVT_PNG ) == ERRCODE_NONE ) + { + const Point aPt( ImplMap( rPt ) ); + const Size aSz( ImplMap( rSz ) ); + FastString aImageData( (sal_Char*) aOStm.GetData(), aOStm.Tell() ); + REF( NMSP_SAX::XExtendedDocumentHandler ) xExtDocHandler( mrExport.GetDocHandler(), NMSP_UNO::UNO_QUERY ); + + if( xExtDocHandler.is() ) + { + static const sal_uInt32 nPartLen = 64; + const NMSP_RTL::OUString aSpace( ' ' ); + const NMSP_RTL::OUString aLineFeed( NMSP_RTL::OUString::valueOf( (sal_Unicode) 0x0a ) ); + NMSP_RTL::OUString aString; + NMSP_RTL::OUString aImageString; + + aString = aLineFeed; + aString += B2UCONST( "<" ); + aString += NMSP_RTL::OUString::createFromAscii( aXMLElemImage ); + aString += aSpace; + + aString += NMSP_RTL::OUString::createFromAscii( aXMLAttrX ); + aString += B2UCONST( "=\"" ); + aString += GetValueString( aPt.X() ); + aString += B2UCONST( "\" " ); + + aString += NMSP_RTL::OUString::createFromAscii( aXMLAttrY ); + aString += B2UCONST( "=\"" ); + aString += GetValueString( aPt.Y() ); + aString += B2UCONST( "\" " ); + + aString += NMSP_RTL::OUString::createFromAscii( aXMLAttrWidth ); + aString += B2UCONST( "=\"" ); + aString += GetValueString( aSz.Width() ); + aString += B2UCONST( "\" " ); + + aString += NMSP_RTL::OUString::createFromAscii( aXMLAttrHeight ); + aString += B2UCONST( "=\"" ); + aString += GetValueString( aSz.Height() ); + aString += B2UCONST( "\" " ); + + aString += NMSP_RTL::OUString::createFromAscii( aXMLAttrXLinkHRef ); + aString += B2UCONST( "=\"data:image/png;base64," ); + + if( aImageData.GetFirstPartString( nPartLen, aImageString ) ) + { + xExtDocHandler->unknown( aString += aImageString ); + + while( aImageData.GetNextPartString( nPartLen, aImageString ) ) + { + xExtDocHandler->unknown( aLineFeed ); + xExtDocHandler->unknown( aImageString ); + } + } + + xExtDocHandler->unknown( B2UCONST( "\"/>" ) ); + } + } + } + } +} + +// ----------------------------------------------------------------------------- + +void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf, + const NMSP_RTL::OUString* pStyle, + sal_uInt32 nWriteFlags ) +{ + ImplAcquireContext(); + + for( ULONG i = 0, nCount = rMtf.GetActionCount(); i < nCount; i++ ) + { + const MetaAction* pAction = rMtf.GetAction( i ); + const USHORT nType = pAction->GetType(); + + switch( nType ) + { + case( META_PIXEL_ACTION ): + { + if( nWriteFlags & SVGWRITER_WRITE_FILL ) + { + const MetaPixelAction* pA = (const MetaPixelAction*) pAction; + + mpContext->SetPaintAttr( pA->GetColor(), pA->GetColor() ); + ImplWriteLine( pA->GetPoint(), pA->GetPoint(), &pA->GetColor(), pStyle ); + } + } + break; + + case( META_POINT_ACTION ): + { + if( nWriteFlags & SVGWRITER_WRITE_FILL ) + { + const MetaPointAction* pA = (const MetaPointAction*) pAction; + + mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetLineColor() ); + ImplWriteLine( pA->GetPoint(), pA->GetPoint(), NULL, pStyle ); + } + } + break; + + case( META_LINE_ACTION ): + { + if( nWriteFlags & SVGWRITER_WRITE_FILL ) + { + const MetaLineAction* pA = (const MetaLineAction*) pAction; + + if(pA->GetLineInfo().IsDefault()) + { + mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetLineColor() ); + } + else + { + const LineInfo aMappedLineInfo(ImplMap(pA->GetLineInfo())); + mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetLineColor(), &aMappedLineInfo ); + } + + ImplWriteLine( pA->GetStartPoint(), pA->GetEndPoint(), NULL, pStyle ); + } + } + break; + + case( META_RECT_ACTION ): + { + if( nWriteFlags & SVGWRITER_WRITE_FILL ) + { + mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() ); + ImplWriteRect( ( (const MetaRectAction*) pAction )->GetRect(), 0, 0, pStyle ); + } + } + break; + + case( META_ROUNDRECT_ACTION ): + { + if( nWriteFlags & SVGWRITER_WRITE_FILL ) + { + const MetaRoundRectAction* pA = (const MetaRoundRectAction*) pAction; + + mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() ); + ImplWriteRect( pA->GetRect(), pA->GetHorzRound(), pA->GetVertRound(), pStyle ); + } + } + break; + + case( META_ELLIPSE_ACTION ): + { + if( nWriteFlags & SVGWRITER_WRITE_FILL ) + { + const MetaEllipseAction* pA = (const MetaEllipseAction*) pAction; + const Rectangle& rRect = pA->GetRect(); + + mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() ); + ImplWriteEllipse( rRect.Center(), rRect.GetWidth() >> 1, rRect.GetHeight() >> 1, pStyle ); + } + } + break; + + case( META_ARC_ACTION ): + case( META_PIE_ACTION ): + case( META_CHORD_ACTION ): + case( META_POLYGON_ACTION ): + { + if( nWriteFlags & SVGWRITER_WRITE_FILL ) + { + Polygon aPoly; + + switch( nType ) + { + case( META_ARC_ACTION ): + { + const MetaArcAction* pA = (const MetaArcAction*) pAction; + aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_ARC ); + } + break; + + case( META_PIE_ACTION ): + { + const MetaPieAction* pA = (const MetaPieAction*) pAction; + aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_PIE ); + } + break; + + case( META_CHORD_ACTION ): + { + const MetaChordAction* pA = (const MetaChordAction*) pAction; + aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_CHORD ); + } + break; + + case( META_POLYGON_ACTION ): + aPoly = ( (const MetaPolygonAction*) pAction )->GetPolygon(); + break; + } + + if( aPoly.GetSize() ) + { + mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() ); + ImplWritePolyPolygon( aPoly, sal_False, pStyle ); + } + } + } + break; + + case( META_POLYLINE_ACTION ): + { + if( nWriteFlags & SVGWRITER_WRITE_FILL ) + { + const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pAction; + const Polygon& rPoly = pA->GetPolygon(); + + if( rPoly.GetSize() ) + { + bool bNoLineJoin(false); + + if(pA->GetLineInfo().IsDefault()) + { + mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() ); + } + else + { + const LineInfo aMappedLineInfo(ImplMap(pA->GetLineInfo())); + bNoLineJoin = basegfx::B2DLINEJOIN_NONE == aMappedLineInfo.GetLineJoin(); + mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor(), &aMappedLineInfo ); + } + + if(bNoLineJoin) + { + // emulate B2DLINEJOIN_NONE by creating single edges + const sal_uInt16 nPoints(rPoly.GetSize()); + const bool bCurve(rPoly.HasFlags()); + + for(sal_uInt16 a(0); a + 1 < nPoints; a++) + { + if(bCurve + && POLY_NORMAL != rPoly.GetFlags(a + 1) + && a + 2 < nPoints + && POLY_NORMAL != rPoly.GetFlags(a + 2) + && a + 3 < nPoints) + { + const Polygon aSnippet(4, + rPoly.GetConstPointAry() + a, + rPoly.GetConstFlagAry() + a); + ImplWritePolyPolygon( aSnippet, sal_True, pStyle ); + a += 2; + } + else + { + const Polygon aSnippet(2, + rPoly.GetConstPointAry() + a); + ImplWritePolyPolygon( aSnippet, sal_True, pStyle ); + } + } + } + else + { + ImplWritePolyPolygon( rPoly, sal_True, pStyle ); + } + } + } + } + break; + + case( META_POLYPOLYGON_ACTION ): + { + if( nWriteFlags & SVGWRITER_WRITE_FILL ) + { + const MetaPolyPolygonAction* pA = (const MetaPolyPolygonAction*) pAction; + const PolyPolygon& rPolyPoly = pA->GetPolyPolygon(); + + if( rPolyPoly.Count() ) + { + mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() ); + ImplWritePolyPolygon( rPolyPoly, sal_False, pStyle ); + } + } + } + break; + + case( META_GRADIENT_ACTION ): + { + if( nWriteFlags & SVGWRITER_WRITE_FILL ) + { + const MetaGradientAction* pA = (const MetaGradientAction*) pAction; + const Polygon aRectPoly( pA->GetRect() ); + const PolyPolygon aRectPolyPoly( aRectPoly ); + + ImplWriteGradientEx( aRectPolyPoly, pA->GetGradient(), pStyle, nWriteFlags ); + } + } + break; + + case( META_GRADIENTEX_ACTION ): + { + if( nWriteFlags & SVGWRITER_WRITE_FILL ) + { + const MetaGradientExAction* pA = (const MetaGradientExAction*) pAction; + ImplWriteGradientEx( pA->GetPolyPolygon(), pA->GetGradient(), pStyle, nWriteFlags ); + } + } + break; + + case META_HATCH_ACTION: + { + if( nWriteFlags & SVGWRITER_WRITE_FILL ) + { + const MetaHatchAction* pA = (const MetaHatchAction*) pAction; + GDIMetaFile aTmpMtf; + + mpVDev->AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf ); + ImplWriteActions( aTmpMtf, pStyle, nWriteFlags ); + } + } + break; + + case( META_TRANSPARENT_ACTION ): + { + if( nWriteFlags & SVGWRITER_WRITE_FILL ) + { + const MetaTransparentAction* pA = (const MetaTransparentAction*) pAction; + const PolyPolygon& rPolyPoly = pA->GetPolyPolygon(); + + if( rPolyPoly.Count() ) + { + const Color aOldLineColor( mpVDev->GetLineColor() ), aOldFillColor( mpVDev->GetFillColor() ); + Color aNewLineColor( aOldLineColor ), aNewFillColor( aOldFillColor ); + + aNewLineColor.SetTransparency( sal::static_int_cast<UINT8>( FRound( pA->GetTransparence() * 2.55 ) ) ); + aNewFillColor.SetTransparency( sal::static_int_cast<UINT8>( FRound( pA->GetTransparence() * 2.55 ) ) ); + + mpContext->SetPaintAttr( aNewLineColor, aNewFillColor ); + ImplWritePolyPolygon( rPolyPoly, sal_False, pStyle ); + mpContext->SetPaintAttr( aOldLineColor, aOldFillColor ); + } + } + } + break; + + case( META_FLOATTRANSPARENT_ACTION ): + { + if( nWriteFlags & SVGWRITER_WRITE_FILL ) + { + const MetaFloatTransparentAction* pA = (const MetaFloatTransparentAction*) pAction; + GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() ); + Point aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() ); + const Size aSrcSize( aTmpMtf.GetPrefSize() ); + const Point aDestPt( pA->GetPoint() ); + const Size aDestSize( pA->GetSize() ); + const double fScaleX = aSrcSize.Width() ? (double) aDestSize.Width() / aSrcSize.Width() : 1.0; + const double fScaleY = aSrcSize.Height() ? (double) aDestSize.Height() / aSrcSize.Height() : 1.0; + long nMoveX, nMoveY; + + if( fScaleX != 1.0 || fScaleY != 1.0 ) + { + aTmpMtf.Scale( fScaleX, fScaleY ); + aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY ); + } + + nMoveX = aDestPt.X() - aSrcPt.X(), nMoveY = aDestPt.Y() - aSrcPt.Y(); + + if( nMoveX || nMoveY ) + aTmpMtf.Move( nMoveX, nMoveY ); + + mpVDev->Push(); + ImplWriteActions( aTmpMtf, pStyle, nWriteFlags ); + mpVDev->Pop(); + } + } + break; + + case( META_EPS_ACTION ): + { + if( nWriteFlags & SVGWRITER_WRITE_FILL ) + { + const MetaEPSAction* pA = (const MetaEPSAction*) pAction; + const GDIMetaFile aGDIMetaFile( pA->GetSubstitute() ); + sal_Bool bFound = sal_False; + + for( ULONG j = 0, nC = aGDIMetaFile.GetActionCount(); ( j < nC ) && !bFound; j++ ) + { + const MetaAction* pSubstAct = aGDIMetaFile.GetAction( j ); + + if( pSubstAct->GetType() == META_BMPSCALE_ACTION ) + { + bFound = sal_True; + const MetaBmpScaleAction* pBmpScaleAction = (const MetaBmpScaleAction*) pSubstAct; + mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() ); + ImplWriteBmp( pBmpScaleAction->GetBitmap(), + pA->GetPoint(), pA->GetSize(), + Point(), pBmpScaleAction->GetBitmap().GetSizePixel(), pStyle ); + } + } + } + } + break; + + case( META_COMMENT_ACTION ): + { + const MetaCommentAction* pA = (const MetaCommentAction*) pAction; + String aSkipComment; + + if( ( pA->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_BEGIN" ) == COMPARE_EQUAL ) && + ( nWriteFlags & SVGWRITER_WRITE_FILL ) ) + { + const MetaGradientExAction* pGradAction = NULL; + sal_Bool bDone = sal_False; + + while( !bDone && ( ++i < nCount ) ) + { + pAction = rMtf.GetAction( i ); + + if( pAction->GetType() == META_GRADIENTEX_ACTION ) + pGradAction = (const MetaGradientExAction*) pAction; + else if( ( pAction->GetType() == META_COMMENT_ACTION ) && + ( ( (const MetaCommentAction*) pAction )->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_END" ) == COMPARE_EQUAL ) ) + { + bDone = sal_True; + } + } + + if( pGradAction ) + ImplWriteGradientEx( pGradAction->GetPolyPolygon(), pGradAction->GetGradient(), pStyle, nWriteFlags ); + } + } + break; + + case( META_BMP_ACTION ): + { + if( nWriteFlags & SVGWRITER_WRITE_FILL ) + { + const MetaBmpAction* pA = (const MetaBmpAction*) pAction; + + mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() ); + ImplWriteBmp( pA->GetBitmap(), + pA->GetPoint(), mpVDev->PixelToLogic( pA->GetBitmap().GetSizePixel() ), + Point(), pA->GetBitmap().GetSizePixel(), pStyle ); + } + } + break; + + case( META_BMPSCALE_ACTION ): + { + if( nWriteFlags & SVGWRITER_WRITE_FILL ) + { + const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction; + + mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() ); + ImplWriteBmp( pA->GetBitmap(), + pA->GetPoint(), pA->GetSize(), + Point(), pA->GetBitmap().GetSizePixel(), pStyle ); + } + } + break; + + case( META_BMPSCALEPART_ACTION ): + { + if( nWriteFlags & SVGWRITER_WRITE_FILL ) + { + const MetaBmpScalePartAction* pA = (const MetaBmpScalePartAction*) pAction; + + mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() ); + ImplWriteBmp( pA->GetBitmap(), + pA->GetDestPoint(), pA->GetDestSize(), + pA->GetSrcPoint(), pA->GetSrcSize(), pStyle ); + } + } + break; + + case( META_BMPEX_ACTION ): + { + if( nWriteFlags & SVGWRITER_WRITE_FILL ) + { + const MetaBmpExAction* pA = (const MetaBmpExAction*) pAction; + + mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() ); + ImplWriteBmp( pA->GetBitmapEx(), + pA->GetPoint(), mpVDev->PixelToLogic( pA->GetBitmapEx().GetSizePixel() ), + Point(), pA->GetBitmapEx().GetSizePixel(), pStyle ); + } + } + break; + + case( META_BMPEXSCALE_ACTION ): + { + if( nWriteFlags & SVGWRITER_WRITE_FILL ) + { + const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction; + + mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() ); + ImplWriteBmp( pA->GetBitmapEx(), + pA->GetPoint(), pA->GetSize(), + Point(), pA->GetBitmapEx().GetSizePixel(), pStyle ); + } + } + break; + + case( META_BMPEXSCALEPART_ACTION ): + { + if( nWriteFlags & SVGWRITER_WRITE_FILL ) + { + const MetaBmpExScalePartAction* pA = (const MetaBmpExScalePartAction*) pAction; + + mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() ); + ImplWriteBmp( pA->GetBitmapEx(), + pA->GetDestPoint(), pA->GetDestSize(), + pA->GetSrcPoint(), pA->GetSrcSize(), pStyle ); + } + } + break; + + case( META_TEXT_ACTION ): + { + if( nWriteFlags & SVGWRITER_WRITE_TEXT ) + { + const MetaTextAction* pA = (const MetaTextAction*) pAction; + Font aFont( mpVDev->GetFont() ); + + aFont.SetHeight( ImplMap( Size( 0, aFont.GetHeight() ) ).Height() ); + mpContext->SetFontAttr( aFont ); + mpContext->SetPaintAttr( COL_TRANSPARENT, aFont.GetColor() ); + ImplWriteText( pA->GetPoint(), String( pA->GetText(), pA->GetIndex(), pA->GetLen() ), NULL, 0, pStyle ); + } + } + break; + + case( META_TEXTRECT_ACTION ): + { + if( nWriteFlags & SVGWRITER_WRITE_TEXT ) + { + const MetaTextRectAction* pA = (const MetaTextRectAction*) pAction; + Font aFont( mpVDev->GetFont() ); + + aFont.SetHeight( ImplMap( Size( 0, aFont.GetHeight() ) ).Height() ); + mpContext->SetFontAttr( aFont ); + mpContext->SetPaintAttr( COL_TRANSPARENT, aFont.GetColor() ); + ImplWriteText( pA->GetRect().TopLeft(), pA->GetText(), NULL, 0, pStyle ); + } + } + break; + + case( META_TEXTARRAY_ACTION ): + { + if( nWriteFlags & SVGWRITER_WRITE_TEXT ) + { + const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pAction; + const Point aPos( ImplMap( pA->GetPoint() ) ); + Font aFont( mpVDev->GetFont() ); + + aFont.SetHeight( ImplMap( Size( 0, aFont.GetHeight() ) ).Height() ); + mpContext->SetFontAttr( aFont ); + mpContext->SetPaintAttr( COL_TRANSPARENT, aFont.GetColor() ); + ImplWriteText( pA->GetPoint(), String( pA->GetText(), pA->GetIndex(), pA->GetLen() ), pA->GetDXArray(), 0, pStyle ); + } + } + break; + + case( META_STRETCHTEXT_ACTION ): + { + if( nWriteFlags & SVGWRITER_WRITE_TEXT ) + { + const MetaStretchTextAction* pA = (const MetaStretchTextAction*) pAction; + Font aFont( mpVDev->GetFont() ); + + aFont.SetHeight( ImplMap( Size( 0, aFont.GetHeight() ) ).Height() ); + mpContext->SetFontAttr( aFont ); + mpContext->SetPaintAttr( COL_TRANSPARENT, aFont.GetColor() ); + ImplWriteText( pA->GetPoint(), String( pA->GetText(), pA->GetIndex(), pA->GetLen() ), NULL, pA->GetWidth(), pStyle ); + } + } + break; + + case( META_CLIPREGION_ACTION ): + case( META_ISECTRECTCLIPREGION_ACTION ): + case( META_ISECTREGIONCLIPREGION_ACTION ): + case( META_MOVECLIPREGION_ACTION ): + { + ( (MetaAction*) pAction )->Execute( mpVDev ); + mbClipAttrChanged = sal_True; + } + break; + + case( META_REFPOINT_ACTION ): + case( META_MAPMODE_ACTION ): + case( META_LINECOLOR_ACTION ): + case( META_FILLCOLOR_ACTION ): + case( META_TEXTLINECOLOR_ACTION ): + case( META_TEXTFILLCOLOR_ACTION ): + case( META_TEXTCOLOR_ACTION ): + case( META_TEXTALIGN_ACTION ): + case( META_FONT_ACTION ): + case( META_PUSH_ACTION ): + case( META_POP_ACTION ): + case( META_LAYOUTMODE_ACTION ): + { + ( (MetaAction*) pAction )->Execute( mpVDev ); + } + break; + + case( META_RASTEROP_ACTION ): + case( META_MASK_ACTION ): + case( META_MASKSCALE_ACTION ): + case( META_MASKSCALEPART_ACTION ): + case( META_WALLPAPER_ACTION ): + case( META_TEXTLINE_ACTION ): + { + // !!! >>> we don't want to support these actions + } + break; + + default: + DBG_ERROR( "SVGActionWriter::ImplWriteActions: unsupported MetaAction #" ); + break; + } + } + + ImplReleaseContext(); +} + +// ----------------------------------------------------------------------------- + +void SVGActionWriter::WriteMetaFile( const Point& rPos100thmm, + const Size& rSize100thmm, + const GDIMetaFile& rMtf, + sal_uInt32 nWriteFlags ) +{ + MapMode aMapMode( rMtf.GetPrefMapMode() ); + Size aPrefSize( rMtf.GetPrefSize() ); + Fraction aFractionX( aMapMode.GetScaleX() ); + Fraction aFractionY( aMapMode.GetScaleY() ); + + mpVDev->Push(); + + Size aSize( OutputDevice::LogicToLogic( rSize100thmm, MAP_100TH_MM, aMapMode ) ); + aMapMode.SetScaleX( aFractionX *= Fraction( aSize.Width(), aPrefSize.Width() ) ); + aMapMode.SetScaleY( aFractionY *= Fraction( aSize.Height(), aPrefSize.Height() ) ); + + Point aOffset( OutputDevice::LogicToLogic( rPos100thmm, MAP_100TH_MM, aMapMode ) ); + aMapMode.SetOrigin( aOffset += aMapMode.GetOrigin() ); + + mpVDev->SetMapMode( aMapMode ); + + ImplWriteActions( rMtf, NULL, nWriteFlags ); + + mpVDev->Pop(); +} diff --git a/filter/source/svg/svgwriter.hxx b/filter/source/svg/svgwriter.hxx new file mode 100644 index 000000000000..113448a551d5 --- /dev/null +++ b/filter/source/svg/svgwriter.hxx @@ -0,0 +1,225 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SVGWRITER_HXX +#define SVGWRITER_HXX + +#include <cppuhelper/weak.hxx> +#include <rtl/ustring.hxx> +#include <tools/debug.hxx> +#include <tools/stream.hxx> +#include <tools/string.hxx> +#include <tools/urlobj.hxx> +#include <tools/stack.hxx> +#ifndef _SALBTYPE_HXX +#include <vcl/salbtype.hxx> +#endif +#ifndef _GDIMTF_HXX +#include <vcl/gdimtf.hxx> +#endif +#ifndef _METAACT_HXX +#include <vcl/metaact.hxx> +#endif +#ifndef _METAACT_HXX +#include <vcl/metric.hxx> +#endif +#ifndef _VIRDEV_HXX +#include <vcl/virdev.hxx> +#endif +#ifndef _CVTGRF_HXX +#include <vcl/cvtgrf.hxx> +#endif +#include <xmloff/xmlexp.hxx> +#include <xmloff/nmspmap.hxx> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> + +// ----------------------------------------------------------------------------- + +#define _SVG_USE_NATIVE_TEXTDECORATION +#define _SVG_USE_TSPANS 1 +#undef _SVG_WRITE_EXTENTS +#define _SVG_EMBED_FONTS 1 + +// ----------------------------------------------------------------------------- + +#define NMSP_CPPU cppu +#define NMSP_RTL rtl +#define NMSP_UNO com::sun::star::uno +#define NMSP_LANG com::sun::star::lang +#define NMSP_SAX com::sun::star::xml::sax +#define NMSP_SVG com::sun::star::svg +#define NMSP_REGISTRY com::sun::star::registry + + +#define REF( _def_Obj ) NMSP_UNO::Reference< _def_Obj > +#define SEQ( _def_Obj ) NMSP_UNO::Sequence< _def_Obj > +#define B2UCONST( _def_pChar ) (NMSP_RTL::OUString(RTL_CONSTASCII_USTRINGPARAM(_def_pChar ))) +#define SVG_DTD_STRING B2UCONST( "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">" ) + +#define SVGWRITER_WRITE_NONE 0x00000000 +#define SVGWRITER_WRITE_FILL 0x00000001 +#define SVGWRITER_WRITE_TEXT 0x00000002 +#define SVGWRITER_WRITE_ALL 0xFFFFFFFF + +// -------------- +// - FastString - +// -------------- + +class FastString +{ +private: + + sal_uInt32 mnBufLen; + sal_uInt32 mnCurLen; + sal_uInt32 mnBufInc; + sal_Unicode* mpBuffer; + sal_uInt32 mnPartPos; + rtl::OUString maString; + +public: + + FastString( sal_uInt32 nInitLen = 2048, sal_uInt32 nIncrement = 2048 ); + FastString( sal_Char* pBufferForBase64Encoding, sal_uInt32 nBufLen ); + ~FastString(); + + FastString& operator+=( const ::rtl::OUString& rStr ); + + const ::rtl::OUString& GetString() const; + sal_Bool GetFirstPartString( const sal_uInt32 nPartLen, ::rtl::OUString& rPartString ); + sal_Bool GetNextPartString( const sal_uInt32 nPartLen, ::rtl::OUString& rPartString ); + + sal_uInt32 GetLength() const { return mnCurLen; } + void Clear() { mnCurLen = 0, maString = ::rtl::OUString(); } +}; + +// ---------------------- +// - SVGAttributeWriter - +// ---------------------- + +class SVGActionWriter; +class SVGFontExport; + +class SVGAttributeWriter +{ +private: + + Font maCurFont; + Color maCurLineColor; + Color maCurFillColor; + SvXMLExport& mrExport; + SVGFontExport& mrFontExport; + SvXMLElementExport* mpElemFont; + SvXMLElementExport* mpElemPaint; + + SVGAttributeWriter(); + +public: + + SVGAttributeWriter( SvXMLExport& rExport, SVGFontExport& rFontExport ); + virtual ~SVGAttributeWriter(); + + ::rtl::OUString GetFontStyle( const Font& rFont ); + ::rtl::OUString GetPaintStyle( const Color& rLineColor, const Color& rFillColor, const LineInfo* pLineInfo ); + + void SetFontAttr( const Font& rFont ); + void SetPaintAttr( const Color& rLineColor, const Color& rFillColor, const LineInfo* pLineInfo = 0); +}; + +// ------------------- +// - SVGActionWriter - +// ------------------- + +class SVGAttributeWriter; +class SvXMLExport; +class GDIMetaFile; + +class SVGActionWriter +{ +private: + + SvXMLExport& mrExport; + SVGFontExport& mrFontExport; + SVGAttributeWriter* mpContext; + sal_Bool mbClipAttrChanged; + sal_Int32 mnCurClipId; + Stack maContextStack; + VirtualDevice* mpVDev; + MapMode maTargetMapMode; + sal_Bool mbDestroyVDev; + sal_Bool mbPaintAttrChanged; + sal_Bool mbFontAttrChanged; + + SVGAttributeWriter* ImplAcquireContext() { maContextStack.Push( mpContext = new SVGAttributeWriter( mrExport, mrFontExport ) ); return mpContext; } + void ImplReleaseContext() { delete (SVGAttributeWriter*) maContextStack.Pop(); mpContext = (SVGAttributeWriter*) maContextStack.Top(); } + + long ImplMap( sal_Int32 nVal ) const; + Point ImplMap( const Point& rPt ) const; + Size ImplMap( const Size& rSz ) const; + LineInfo ImplMap( const LineInfo& rLineInfo ) const; + inline Rectangle ImplMap( const Rectangle& rRect ) const { return Rectangle( ImplMap( rRect.TopLeft() ), ImplMap( rRect.GetSize() ) ); } + + void ImplWriteLine( const Point& rPt1, const Point& rPt2, const Color* pLineColor = NULL, const ::rtl::OUString* pStyle = NULL ); + void ImplWriteRect( const Rectangle& rRect, long nRadX = 0, long nRadY = 0, const ::rtl::OUString* pStyle = NULL ); + void ImplWriteEllipse( const Point& rCenter, long nRadX, long nRadY, const ::rtl::OUString* pStyle = NULL ); + void ImplWritePolyPolygon( const PolyPolygon& rPolyPoly, sal_Bool bLineOnly, const ::rtl::OUString* pStyle = NULL ); + void ImplWriteGradientEx( const PolyPolygon& rPolyPoly, const Gradient& rGradient, const ::rtl::OUString* pStyle, sal_uInt32 nWriteFlags ); + void ImplWriteText( const Point& rPos, const String& rText, const sal_Int32* pDXArray, long nWidth, const ::rtl::OUString* pStyle = NULL ); + void ImplWriteBmp( const BitmapEx& rBmpEx, const Point& rPt, const Size& rSz, const Point& rSrcPt, const Size& rSrcSz, const ::rtl::OUString* pStyle = NULL ); + + void ImplCheckFontAttributes(); + void ImplCheckPaintAttributes(); + + void ImplWriteActions( const GDIMetaFile& rMtf, const ::rtl::OUString* pStyle, sal_uInt32 nWriteFlags ); + sal_Int32 ImplGetNextClipId() { return mnCurClipId++; } + +public: + + static ::rtl::OUString GetValueString( sal_Int32 nVal ); + static ::rtl::OUString GetPathString( const PolyPolygon& rPolyPoly, sal_Bool bLine ); + +public: + + SVGActionWriter( SvXMLExport& rExport, SVGFontExport& rFontExport ); + virtual ~SVGActionWriter(); + + void WriteMetaFile( const Point& rPos100thmm, + const Size& rSize100thmm, + const GDIMetaFile& rMtf, + sal_uInt32 nWriteFlags = SVGWRITER_WRITE_ALL ); +}; + +#endif |