diff options
author | Ivo Hinkelmann <ihi@openoffice.org> | 2009-07-15 14:57:49 +0000 |
---|---|---|
committer | Ivo Hinkelmann <ihi@openoffice.org> | 2009-07-15 14:57:49 +0000 |
commit | 0851da4d8a0a557f1e9a31af652a530c615c2989 (patch) | |
tree | 4c630979f4764c52e84314e9bb16d22416a447b2 /oox/source/vml | |
parent | e49ca2777ba38f75b24a49d30f59c2f0d2be79e6 (diff) |
CWS-TOOLING: integrate CWS dr68
2009-06-19 17:43:48 +0200 oc r273175 : #i102946# some lines for new dialog added
2009-06-19 14:17:45 +0200 oc r273158 : #i102946# three lines added
2009-05-19 11:56:14 +0200 dr r272065 : #i99677# wrong attribute name
2009-05-18 18:37:05 +0200 dr r272045 : #i10000# suncc warning
2009-05-05 16:46:13 +0200 dr r271536 : #i10000# adoptions after rebase to master containing dr67
2009-05-05 16:01:19 +0200 dr r271530 : #i10000# adoptions after rebase to master containing dr67
2009-05-04 14:20:39 +0200 dr r271453 : CWS-TOOLING: rebase CWS dr68 to trunk@271427 (milestone: DEV300:m47)
2009-04-28 17:01:14 +0200 dr r271332 : CWS-TOOLING: rebase CWS dr68 to trunk@270723 (milestone: DEV300:m46)
2009-04-23 12:21:40 +0200 dr r271149 : #i100688# missing checkins
2009-04-23 12:18:16 +0200 dr r271147 : #i100978# relations path handling
2009-04-22 19:25:45 +0200 nn r271136 : #i49491# show navigator for double click on document position status bar control
2009-04-22 11:28:36 +0200 nn r271085 : #i60401# small text change
2009-04-21 16:53:23 +0200 dr r271044 : #i10000# missing dtor
2009-04-20 13:39:25 +0200 nn r270977 : #i60401# add dialog to extend sort range (patch from maoyg)
2009-04-08 12:11:08 +0200 dr r270630 : #i100943# prevent assertion when loading chart with empty category ranges
2009-04-07 19:03:00 +0200 dr r270609 : #i100688# missing bits for OLE
2009-04-07 17:14:06 +0200 dr r270605 : ported fix for #i100710#
2009-04-07 17:12:50 +0200 dr r270604 : #i10000# wae
2009-04-07 15:31:55 +0200 dr r270598 : import system colors moved to FilterBase class, more rework on fill and color contexts
2009-04-06 15:00:03 +0200 dr r270552 : #i99677# prevent recursive loading of the current document
2009-04-03 18:28:42 +0200 dr r270515 : added import of brightness/contrast and mono/grayscale color effects for image shapes
2009-04-03 17:36:03 +0200 dr r270509 : cache already imported embedded graphics
2009-04-03 16:46:34 +0200 dr r270500 : more rework on bitmap fill and graphic object handling
2009-03-31 12:28:10 +0200 dr r270271 : #i10000# unxlngi6 wae
2009-03-31 09:04:10 +0200 dr r270261 : CWS-TOOLING: rebase CWS dr68 to trunk@270033 (milestone: DEV300:m45)
2009-03-30 17:42:05 +0200 dr r270249 : #i91122# add missing doc
2009-03-30 17:37:08 +0200 dr r270248 : #i91122# add missing doc
2009-03-30 16:59:15 +0200 dr r270241 : #i99677# add import of ActiveX scrollbar controls
2009-03-30 14:30:36 +0200 dr r270230 : #i91122# missing/wrong documentation
2009-03-30 13:03:38 +0200 dr r270220 : #i99677# add import of ActiveX combobox and spinbutton controls
2009-03-27 11:46:59 +0100 dr r270144 : #i99677# import ActiveX listbox controls (Forms.ListBox.1)
2009-03-26 19:58:00 +0100 dr r270104 : #i99677# move more OLE import code into ole submodule
2009-03-26 15:15:02 +0100 dr r270082 : #i100546# add import of chart bitmap fills, add import of X/Y offset in tiled bitmap fills of all shapes
2009-03-25 12:54:59 +0100 dr r270018 : #i99677# import ActiveX edit text control (Forms.TextBox.1)
2009-03-24 10:59:29 +0100 dr r269921 : #i99677# moved import of OLE StdHlink to 'ole' submodule, added string import helpers to BinaryStreamBase class, removed implementation of ST_XString import from docprop in favour of the implementation in class AttributeList
2009-03-24 10:40:18 +0100 dr r269919 : #i100502# implicit precedence of '&&' was intended
2009-03-24 10:18:29 +0100 dr r269917 : #i100502# missing parentheses
2009-03-23 15:17:48 +0100 dr r269876 : #i99677# more code reorg, added graphic helper and OLE helper object per filter, added OLE/control import to PPTX/XLSX filter, moved helpers from XmlFilterBase to FilterBase
2009-03-19 12:45:20 +0100 dr r269740 : #i99677# interface changes in oox
2009-03-18 15:51:50 +0100 dr r269683 : #i99677# improved relation handling (internal/external), added preprocessor for VML streams to eat MS specific instructions, added OCX ToggleButton/OptionButton import, added DIB import for BIFF (page background picture, lots of other minor improvements
2009-03-16 15:25:30 +0100 dr r269551 : #i99677# import excel form control client data (printable, cell link)
2009-03-13 18:37:17 +0100 dr r269494 : #i99677# import image controls and check boxes
2009-03-12 15:08:18 +0100 dr r269420 : #i10000# rebase problems
2009-03-12 14:43:09 +0100 dr r269418 : #i10000# rebase problems
2009-03-12 14:42:41 +0100 dr r269417 : #i10000# missing delivered header
2009-03-12 13:57:06 +0100 dr r269405 : #i10000# typos
2009-03-12 12:58:52 +0100 dr r269391 : CWS-TOOLING: rebase CWS dr68 to trunk@269297 (milestone: DEV300:m43)
2009-03-12 11:11:46 +0100 dr r269374 : #i99677# first step to import BIFF8 page background
2009-03-12 10:21:53 +0100 dr r269364 : #i99677# rework of graphic import in entire filter, added import of AX Label controls
2009-03-09 16:44:50 +0100 dr r269202 : #i99677# import some formatting attributes of command buttons
2009-03-05 15:31:46 +0100 dr r268911 : #i99677# use VML shape client data to import excel VML shape positions
2009-03-05 11:39:48 +0100 dr r268888 : #i99677# create UNO control shapes from VML control shapes
2009-03-05 11:38:59 +0100 dr r268886 : #i99677# change attribute Shapes to DrawPage for import of embedded form controls
2009-03-05 11:30:40 +0100 dr r268885 : #i99677# change attribute Shapes to DrawPage for import of embedded form controls
2009-03-04 18:46:05 +0100 dr r268860 : adapt namespace ids according to oox
2009-03-04 18:43:49 +0100 dr r268859 : #i99677# more VML import rework
2009-03-03 13:38:36 +0100 dr r268721 : #i99677# more cleanup for VML filter
2009-03-03 13:13:15 +0100 dr r268719 : #i99807# do not iterate beyond end of std::list
2009-03-02 11:55:49 +0100 dr r268644 : add ST_XString support (encoded characters in attribute values)
2009-02-26 17:07:18 +0100 dr r268542 : #i99677# first steps of ax control import: dummy AX base classes, reimplement VML import (hopefully without breaking anything), register embedded AX controls at VML drawing
2009-02-23 17:43:50 +0100 dr r268365 : #i99426# remaining work on scenario import
2009-02-19 16:56:25 +0100 dr r268295 : #i99426# base implementations for scenarios import
Diffstat (limited to 'oox/source/vml')
-rw-r--r-- | oox/source/vml/makefile.mk | 11 | ||||
-rw-r--r-- | oox/source/vml/vmldrawing.cxx | 168 | ||||
-rw-r--r-- | oox/source/vml/vmldrawingfragment.cxx | 95 | ||||
-rw-r--r-- | oox/source/vml/vmldrawingfragmenthandler.cxx | 519 | ||||
-rw-r--r-- | oox/source/vml/vmlinputstream.cxx | 94 | ||||
-rw-r--r-- | oox/source/vml/vmlshape.cxx | 650 | ||||
-rw-r--r-- | oox/source/vml/vmlshapecontainer.cxx | 137 | ||||
-rw-r--r-- | oox/source/vml/vmlshapecontext.cxx | 267 |
8 files changed, 1210 insertions, 731 deletions
diff --git a/oox/source/vml/makefile.mk b/oox/source/vml/makefile.mk index 6d5c719ac0c3..305353eb8f02 100644 --- a/oox/source/vml/makefile.mk +++ b/oox/source/vml/makefile.mk @@ -1,7 +1,7 @@ #************************************************************************* # # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# +# # Copyright 2008 by Sun Microsystems, Inc. # # OpenOffice.org - a multi-platform office productivity suite @@ -45,9 +45,12 @@ ENABLE_EXCEPTIONS=TRUE # --- Files -------------------------------------------------------- SLOFILES = \ - $(SLO)$/vmlshape.obj\ - $(SLO)$/vmldrawing.obj\ - $(SLO)$/vmldrawingfragmenthandler.obj + $(SLO)$/vmldrawing.obj \ + $(SLO)$/vmldrawingfragment.obj \ + $(SLO)$/vmlinputstream.obj \ + $(SLO)$/vmlshape.obj \ + $(SLO)$/vmlshapecontainer.obj \ + $(SLO)$/vmlshapecontext.obj # --- Targets ------------------------------------------------------- diff --git a/oox/source/vml/vmldrawing.cxx b/oox/source/vml/vmldrawing.cxx index 9fc0c2efd88a..42529ea4a351 100644 --- a/oox/source/vml/vmldrawing.cxx +++ b/oox/source/vml/vmldrawing.cxx @@ -28,67 +28,141 @@ * ************************************************************************/ -#include "oox/vml/drawing.hxx" -#include "oox/core/namespaces.hxx" +#include "oox/vml/vmldrawing.hxx" +#include <com/sun/star/drawing/XShapes.hpp> #include "tokens.hxx" +#include "oox/core/xmlfilterbase.hxx" +#include "oox/ole/axcontrolhelper.hxx" +#include "oox/vml/vmlshape.hxx" +#include "oox/vml/vmlshapecontainer.hxx" -namespace oox { namespace vml { +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::awt::Rectangle; +using ::com::sun::star::awt::XControlModel; +using ::com::sun::star::drawing::XDrawPage; +using ::com::sun::star::drawing::XShapes; +using ::oox::core::XmlFilterBase; -Drawing::Drawing() +namespace oox { +namespace vml { + +// ============================================================================ + +namespace { + +/** Returns the textual representation of a numeric VML shape identifier. */ +OUString lclGetShapeId( sal_Int32 nShapeId ) +{ + // identifier consists of a literal NUL character, a lowercase 's', and the id + return CREATE_OUSTRING( "\0s" ) + OUString::valueOf( nShapeId ); +} + +} // namespace + +// ============================================================================ + +OleObjectInfo::OleObjectInfo( bool bDmlShape ) : + mbAutoLoad( false ), + mbDmlShape( bDmlShape ) +{ +} + +void OleObjectInfo::setShapeId( sal_Int32 nShapeId ) { + maShapeId = lclGetShapeId( nShapeId ); } + +// ============================================================================ + +ControlInfo::ControlInfo() +{ +} + +void ControlInfo::setShapeId( sal_Int32 nShapeId ) +{ + maShapeId = lclGetShapeId( nShapeId ); +} + +// ============================================================================ + +Drawing::Drawing( XmlFilterBase& rFilter, const Reference< XDrawPage >& rxDrawPage, DrawingType eType ) : + mrFilter( rFilter ), + mxDrawPage( rxDrawPage ), + mxShapes( new ShapeContainer( *this ) ), + meType( eType ) +{ + OSL_ENSURE( mxDrawPage.is(), "Drawing::Drawing - missing UNO draw page" ); +} + Drawing::~Drawing() { } -ShapePtr Drawing::createShapeById( const rtl::OUString sId ) const +::oox::ole::AxControlHelper& Drawing::getControlHelper() const { - ShapePtr pRet, pRef; - std::vector< ShapePtr >::const_iterator aIter( maShapes.begin() ); - while( aIter != maShapes.end() ) - { - if ( (*aIter)->msId == sId ) - { - pRef = (*aIter); - break; - } - aIter++; - } - if ( pRef ) + // create the helper object on demand + if( !mxCtrlHelper.get() ) { - pRet = ShapePtr( new Shape( pRef->msServiceName ) ); - if ( pRef->msType.getLength() ) - { - std::vector< ShapePtr >::const_iterator aShapeTypeIter( maShapeTypes.begin() ); - while( aShapeTypeIter != maShapeTypes.end() ) - { - if ( (*aShapeTypeIter)->msType == pRef->msType ) - { - pRet->applyAttributes( *(*aShapeTypeIter).get() ); - break; - } - aShapeTypeIter++; - } - } - pRet->applyAttributes( *pRef.get() ); + mxCtrlHelper.reset( createControlHelper() ); + OSL_ENSURE( mxCtrlHelper.get(), "Drawing::getControlHelper - cannot create form controls helper" ); } - return pRet; + return *mxCtrlHelper; } -rtl::OUString Drawing::getGraphicUrlById( const rtl::OUString sId ) const +void Drawing::registerOleObject( const OleObjectInfo& rOleObject ) { - rtl::OUString sGraphicURL; - std::vector< ShapePtr >::const_iterator aIter( maShapes.begin() ); - while( aIter != maShapes.end() ) - { - if ( (*aIter)->msId == sId ) - { - sGraphicURL = (*aIter)->msGraphicURL; - break; - } - aIter++; - } - return sGraphicURL; + OSL_ENSURE( rOleObject.maShapeId.getLength() > 0, "Drawing::registerOleObject - missing OLE object shape id" ); + OSL_ENSURE( maOleObjects.count( rOleObject.maShapeId ) == 0, "Drawing::registerOleObject - OLE object already registered" ); + maOleObjects.insert( OleObjectInfoMap::value_type( rOleObject.maShapeId, rOleObject ) ); } -} } +void Drawing::registerControl( const ControlInfo& rControl ) +{ + OSL_ENSURE( rControl.maShapeId.getLength() > 0, "Drawing::registerControl - missing form control shape id" ); + OSL_ENSURE( rControl.maName.getLength() > 0, "Drawing::registerControl - missing form control name" ); + OSL_ENSURE( maControls.count( rControl.maShapeId ) == 0, "Drawing::registerControl - form control already registered" ); + maControls.insert( ControlInfoMap::value_type( rControl.maShapeId, rControl ) ); +} + +void Drawing::finalizeFragmentImport() +{ + mxShapes->finalizeFragmentImport(); +} + +void Drawing::convertAndInsert() const +{ + Reference< XShapes > xShapes( mxDrawPage, UNO_QUERY ); + mxShapes->convertAndInsert( xShapes ); +} + +const OleObjectInfo* Drawing::getOleObjectInfo( const OUString& rShapeId ) const +{ + return ContainerHelper::getMapElement( maOleObjects, rShapeId ); +} + +const ControlInfo* Drawing::getControlInfo( const OUString& rShapeId ) const +{ + return ContainerHelper::getMapElement( maControls, rShapeId ); +} + +bool Drawing::convertShapeClientAnchor( Rectangle& /*orShapeRect*/, const OUString& /*rShapeAnchor*/ ) const +{ + return false; +} + +void Drawing::convertControlClientData( const Reference< XControlModel >& /*rxCtrlModel*/, const ShapeClientData& /*rClientData*/ ) const +{ +} + +::oox::ole::AxControlHelper* Drawing::createControlHelper() const +{ + return new ::oox::ole::AxEmbeddedControlHelper( mrFilter, mxDrawPage ); +} + +// ============================================================================ + +} // namespace vml +} // namespave oox + diff --git a/oox/source/vml/vmldrawingfragment.cxx b/oox/source/vml/vmldrawingfragment.cxx new file mode 100644 index 000000000000..b622df39941c --- /dev/null +++ b/oox/source/vml/vmldrawingfragment.cxx @@ -0,0 +1,95 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: vmldrawingfragmenthandler.cxx,v $ + * $Revision: 1.6 $ + * + * 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. + * + ************************************************************************/ + +#include "oox/vml/vmldrawingfragment.hxx" +#include "oox/vml/vmldrawing.hxx" +#include "oox/vml/vmlinputstream.hxx" +#include "oox/vml/vmlshapecontext.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::io::XInputStream; +using ::oox::core::ContextHandlerRef; +using ::oox::core::FragmentHandler2; +using ::oox::core::XmlFilterBase; + +namespace oox { +namespace vml { + +// ============================================================================ + +DrawingFragment::DrawingFragment( XmlFilterBase& rFilter, const OUString& rFragmentPath, Drawing& rDrawing ) : + FragmentHandler2( rFilter, rFragmentPath ), + mrDrawing( rDrawing ) +{ +} + +Reference< XInputStream > DrawingFragment::openFragmentStream() const +{ + return new InputStream( FragmentHandler2::openFragmentStream() ); +} + +ContextHandlerRef DrawingFragment::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( mrDrawing.getType() ) + { + // DOCX filter handles plain shape elements with this fragment handler + case VMLDRAWING_WORD: + if( isRootElement() ) + return ShapeContextBase::createContext( *this, nElement, rAttribs, mrDrawing.getShapes() ); + break; + + // XLSX and PPTX filters load the entire VML fragment + case VMLDRAWING_EXCEL: + case VMLDRAWING_POWERPOINT: + switch( getCurrentElement() ) + { + case XML_ROOT_CONTEXT: + if( nElement == XML_xml ) return this; + break; + case XML_xml: + return ShapeContextBase::createContext( *this, nElement, rAttribs, mrDrawing.getShapes() ); + } + break; + } + return 0; +} + +void DrawingFragment::finalizeImport() +{ + // resolve shape template references for all shapes + mrDrawing.finalizeFragmentImport(); +} + +// ============================================================================ + +} // namespace vml +} // namespace oox + diff --git a/oox/source/vml/vmldrawingfragmenthandler.cxx b/oox/source/vml/vmldrawingfragmenthandler.cxx deleted file mode 100644 index 28e0eebb5e1c..000000000000 --- a/oox/source/vml/vmldrawingfragmenthandler.cxx +++ /dev/null @@ -1,519 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: vmldrawingfragmenthandler.cxx,v $ - * $Revision: 1.6 $ - * - * 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. - * - ************************************************************************/ - -#include "oox/vml/drawingfragmenthandler.hxx" - -#include "comphelper/anytostring.hxx" -#include "cppuhelper/exc_hlp.hxx" -#include "oox/helper/attributelist.hxx" -#include "oox/core/contexthandler.hxx" -#include <com/sun/star/beans/XMultiPropertySet.hpp> -#include <com/sun/star/container/XNamed.hpp> -#include <com/sun/star/drawing/PointSequence.hpp> -#include <com/sun/star/drawing/PointSequenceSequence.hpp> -#include "oox/core/namespaces.hxx" -#include "tokens.hxx" - -using ::rtl::OUString; -using namespace ::com::sun::star; -using namespace ::oox::core; -using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::xml::sax; -using namespace ::com::sun::star::container; - -namespace oox { namespace vml { - -static sal_Int32 getMeasure( const rtl::OUString& rVal ) -{ - double fVal = rVal.toDouble(); - const sal_Int32 nLen = rVal.getLength(); - if ( nLen >= 2 ) - { - switch( static_cast< sal_Int8 >( rVal[ nLen - 1 ] ) ) - { - case 'n' : fVal *= 2540; break; - case 'm' : rVal[ nLen - 2 ] == 'm' ? fVal *= 100.0 : fVal *= 1000.0; break; - case 't' : fVal *= 2540.0 / 72.0; break; - case 'c' : fVal *= ( 2540.0 / 72.0 ) * 12.0; break; - } - } - return static_cast< sal_Int32 >( fVal ); -} - -// AG_CoreAttributes -static void ApplyCoreAttributes( const Reference< XFastAttributeList >& xAttribs, Shape& rShape ) -{ - // AG_Id - rShape.msId = xAttribs->getOptionalValue( XML_id ); - - // AG_Style - if ( xAttribs->hasAttribute( XML_style ) ) - { - rtl::OUString sStyle( xAttribs->getOptionalValue( XML_style ) ); - sal_Int32 nIndex = 0; - do - { - OUString aStyleToken( sStyle.getToken( 0, ';', nIndex ) ); - if ( aStyleToken.getLength() ) - { - sal_Int32 nIndex2 = 0; - OUString aName( aStyleToken.getToken( 0, ':', nIndex2 ) ); - OUString aVal ( aStyleToken.getToken( 0, ':', nIndex2 ) ); - if ( aName.getLength() && aVal.getLength() ) - { - static const ::rtl::OUString sPosition( RTL_CONSTASCII_USTRINGPARAM( "position" ) ); - static const ::rtl::OUString sLeft( RTL_CONSTASCII_USTRINGPARAM( "left" ) ); - static const ::rtl::OUString sTop( RTL_CONSTASCII_USTRINGPARAM( "top" ) ); - static const ::rtl::OUString sWidth( RTL_CONSTASCII_USTRINGPARAM( "width" ) ); - static const ::rtl::OUString sHeight( RTL_CONSTASCII_USTRINGPARAM( "height" ) ); - static const ::rtl::OUString sMarginLeft( RTL_CONSTASCII_USTRINGPARAM( "margin-left" ) ); - static const ::rtl::OUString sMarginTop( RTL_CONSTASCII_USTRINGPARAM( "margin-top" ) ); - if ( aName == sPosition ) - rShape.msPosition = aVal; - else if ( aName == sLeft ) - rShape.maPosition.X = getMeasure( aVal ); - else if ( aName == sTop ) - rShape.maPosition.Y = getMeasure( aVal ); - else if ( aName == sWidth ) - rShape.maSize.Width = getMeasure( aVal ); - else if ( aName == sHeight ) - rShape.maSize.Height = getMeasure( aVal ); - else if ( aName == sMarginLeft ) - rShape.maPosition.X = getMeasure( aVal ); - else if ( aName == sMarginTop ) - rShape.maPosition.Y = getMeasure( aVal ); - } - } - } - while ( nIndex >= 0 ); - } - - // href - // target - // class - // title - // alt - - // coordsize - rtl::OUString aCoordSize( xAttribs->getOptionalValue( XML_coordsize ) ); - if ( aCoordSize.getLength() ) - { - sal_Int32 nIndex = 0; - rtl::OUString aCoordWidth ( aCoordSize.getToken( 0, ',', nIndex ) ); - rtl::OUString aCoordHeight( aCoordSize.getToken( 0, ',', nIndex ) ); - if ( aCoordWidth.getLength() ) - rShape.mnCoordWidth = aCoordWidth.toInt32(); - if ( aCoordHeight.getLength() ) - rShape.mnCoordHeight = aCoordHeight.toInt32(); - } - - // coordorigin - // wrapcoords - // print -} - -// AG_ShapeAttributes -static void ApplyShapeAttributes( const Reference< XFastAttributeList >& xAttribs, Shape& rShape ) -{ - AttributeList aAttributeList( xAttribs ); - rShape.mnStroked = xAttribs->getOptionalValueToken( XML_stroked, 0 ); - if ( xAttribs->hasAttribute( XML_filled ) ) - rShape.moFilled = ::boost::optional< sal_Bool >( aAttributeList.getBool( XML_filled, sal_False ) ); - if ( xAttribs->hasAttribute( XML_fillcolor ) ) - rShape.moFillColor = ::boost::optional< rtl::OUString >( xAttribs->getOptionalValue( XML_fillcolor ) ); -} - -//-------------------------------------------------------------------------------------------------------------- -// EG_ShapeElements -class BasicShapeContext : public ContextHandler -{ -public: - BasicShapeContext( ContextHandler& rParent, - sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs, Shape& rShape ); - virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 Element, - const Reference< XFastAttributeList >& Attribs ) throw (::com::sun::star::xml::sax::SAXException, RuntimeException); -private: - Shape& mrShape; -}; - -BasicShapeContext::BasicShapeContext( ContextHandler& rParent, - sal_Int32 /* aElement */, const Reference< XFastAttributeList >& xAttribs, Shape& rShape ) -: ContextHandler( rParent ) -, mrShape( rShape ) -{ - mrShape.msType = xAttribs->getOptionalValue( XML_type ); - mrShape.msShapeType = xAttribs->getOptionalValue( NMSP_OFFICE|XML_spt ); -} -Reference< XFastContextHandler > BasicShapeContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) - throw (SAXException, RuntimeException) -{ - Reference< XFastContextHandler > xRet; - switch( aElementToken ) - { - case NMSP_VML|XML_imagedata: - { - OUString aRelId( xAttribs->getOptionalValue( NMSP_OFFICE|XML_relid ) ); - mrShape.msGraphicURL = getFragmentPathFromRelId( aRelId ); - mrShape.msImageTitle = xAttribs->getOptionalValue( NMSP_OFFICE|XML_title ); - } - break; - default: - break; - } - if( !xRet.is() ) - xRet.set( this ); - return xRet; -} - -//-------------------------------------------------------------------------------------------------------------- -// CT_Shapetype -class ShapeTypeContext : public BasicShapeContext -{ -public: - ShapeTypeContext( ContextHandler& rParent, - sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs, Shape& rShape ); - virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 Element, - const Reference< XFastAttributeList >& Attribs ) throw (SAXException, RuntimeException); -}; - -ShapeTypeContext::ShapeTypeContext( ContextHandler& rParent, - sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs, Shape& rShape ) -: BasicShapeContext( rParent, aElement, xAttribs, rShape ) -{ -} - -Reference< XFastContextHandler > ShapeTypeContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) - throw (SAXException, RuntimeException) -{ - Reference< XFastContextHandler > xRet; -// switch( aElementToken ) -// { -// default: - xRet = BasicShapeContext::createFastChildContext( aElementToken, xAttribs ); -// break; -// } - if( !xRet.is() ) - xRet.set( this ); - return xRet; -} -//-------------------------------------------------------------------------------------------------------------- -// CT_PolyLine -class PolyLineContext : public BasicShapeContext -{ -public: - PolyLineContext( ContextHandler& rParent, - sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs, Shape& rShape ); - virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 Element, - const Reference< XFastAttributeList >& Attribs ) throw (SAXException, RuntimeException); -}; - -PolyLineContext::PolyLineContext( ContextHandler& rParent, - sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs, Shape& rShape ) -: BasicShapeContext( rParent, aElement, xAttribs, rShape ) -{ - ApplyShapeAttributes( xAttribs, rShape ); - ApplyCoreAttributes( xAttribs, rShape ); - - rtl::OUString aPoints( xAttribs->getOptionalValue( XML_points ) ); - if ( aPoints.getLength() ) - { - std::vector< awt::Point > vPoints; - sal_Int32 nIndex = 0; - do - { - OUString aX( aPoints.getToken( 0, ',', nIndex ) ); - OUString aY( aPoints.getToken( 0, ',', nIndex ) ); - awt::Point aPt( getMeasure( aX ), getMeasure( aY ) ); - vPoints.push_back( aPt ); - } - while ( nIndex >= 0 ); - - drawing::PointSequenceSequence aPointSeq( 1 ); - aPointSeq[ 0 ] = drawing::PointSequence( &vPoints.front(), vPoints.size() ); - static const ::rtl::OUString sPolyPolygon( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygon" ) ); - rShape.maPath.Name = sPolyPolygon; - rShape.maPath.Value <<= aPointSeq; - -/* not sure if the following is needed - - // calculating the bounding box - sal_Int32 nGlobalLeft = SAL_MAX_INT32; - sal_Int32 nGlobalRight = SAL_MIN_INT32; - sal_Int32 nGlobalTop = SAL_MAX_INT32; - sal_Int32 nGlobalBottom= SAL_MIN_INT32; - std::vector< awt::Point >::const_iterator aIter( vPoints.begin() ); - while( aIter != vPoints.end() ) - { - sal_Int32 x = (*aIter).X; - sal_Int32 y = (*aIter).Y; - if ( nGlobalLeft > x ) - nGlobalLeft = x; - if ( nGlobalRight < x ) - nGlobalRight = x; - if ( nGlobalTop > y ) - nGlobalTop = y; - if ( nGlobalBottom < y ) - nGlobalBottom = y; - aIter++; - } - rShape.maPosition.X = nGlobalLeft; - rShape.maPosition.Y = nGlobalTop; - rShape.maSize.Width = nGlobalRight - nGlobalLeft; - rShape.maSize.Height = nGlobalBottom - nGlobalTop; -*/ - } -} - -Reference< XFastContextHandler > PolyLineContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) - throw (SAXException, RuntimeException) -{ - Reference< XFastContextHandler > xRet; -// switch( aElementToken ) -// { -// default: - xRet = BasicShapeContext::createFastChildContext( aElementToken, xAttribs ); -// break; -// } - if( !xRet.is() ) - xRet.set( this ); - return xRet; -} - -//-------------------------------------------------------------------------------------------------------------- -// CT_Shape -class ShapeContext : public BasicShapeContext -{ -public: - ShapeContext( ContextHandler& rParent, - sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs, Shape& rShape ); - virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 Element, - const Reference< XFastAttributeList >& Attribs ) throw (SAXException, RuntimeException); -}; - -ShapeContext::ShapeContext( ContextHandler& rParent, - sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs, Shape& rShape ) -: BasicShapeContext( rParent, aElement, xAttribs, rShape ) -{ - ApplyShapeAttributes( xAttribs, rShape ); - ApplyCoreAttributes( xAttribs, rShape ); -// rShape.msPath = xAttribs->getOptionalValue( XML_path ); -} - -Reference< XFastContextHandler > ShapeContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) - throw (SAXException, RuntimeException) -{ - Reference< XFastContextHandler > xRet; -// switch( aElementToken ) -// { -// default: - xRet = BasicShapeContext::createFastChildContext( aElementToken, xAttribs ); -// break; -// } - if( !xRet.is() ) - xRet.set( this ); - return xRet; -} - -//-------------------------------------------------------------------------------------------------------------- - -class GroupShapeContext : public BasicShapeContext -{ -public: - GroupShapeContext( ContextHandler& rParent, sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs, - Shape& rShape, std::vector< ShapePtr >& rShapeTypes ); - virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 Element, - const Reference< XFastAttributeList >& Attribs ) throw (::com::sun::star::xml::sax::SAXException, RuntimeException); -private: - Shape& mrShape; - std::vector< ShapePtr >& mrShapeTypes; -}; - -GroupShapeContext::GroupShapeContext( ContextHandler& rParent, - sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs, - Shape& rShape, std::vector< ShapePtr >& rShapeTypes ) -: BasicShapeContext( rParent, aElement, xAttribs, rShape ) -, mrShape( rShape ) -, mrShapeTypes( rShapeTypes ) -{ - AttributeList aAttributeList( xAttribs ); - if ( xAttribs->hasAttribute( XML_filled ) ) - rShape.moFilled = ::boost::optional< sal_Bool >( aAttributeList.getBool( XML_filled, sal_False ) ); - if ( xAttribs->hasAttribute( XML_fillcolor ) ) - rShape.moFillColor = ::boost::optional< rtl::OUString >( xAttribs->getOptionalValue( XML_fillcolor ) ); - ApplyCoreAttributes( xAttribs, rShape ); -} -Reference< XFastContextHandler > GroupShapeContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) - throw (SAXException, RuntimeException) -{ - return DrawingFragmentHandler::StaticCreateContext( *this, aElementToken, xAttribs, mrShape.getChilds(), mrShapeTypes ); -} - -//-------------------------------------------------------------------------------------------------------------- - -DrawingFragmentHandler::DrawingFragmentHandler( XmlFilterBase& rFilter, const OUString& rFragmentPath, - std::vector< ShapePtr >& rShapes, std::vector< ShapePtr >& rShapeTypes ) - throw() -: FragmentHandler( rFilter, rFragmentPath ) -, mrShapes( rShapes ) -, mrShapeTypes( rShapeTypes ) -, maFragmentPath( rFragmentPath ) -{ -} -DrawingFragmentHandler::~DrawingFragmentHandler() - throw() -{ -} - -::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > DrawingFragmentHandler::StaticCreateContext( oox::core::ContextHandler& rParent, - sal_Int32 aElementToken, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs, - std::vector< ShapePtr >& rShapes, std::vector< ShapePtr >& rShapeTypes ) - throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException ) -{ - static const ::rtl::OUString sCustomShape( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.CustomShape" ) ); - - Reference< XFastContextHandler > xRet; - switch( aElementToken ) - { - case NMSP_VML|XML_group : - { - static const ::rtl::OUString sGroupShape( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.GroupShape" ) ); - ShapePtr pShapePtr( new Shape( sGroupShape ) ); - xRet = new GroupShapeContext( rParent, aElementToken, xAttribs, *pShapePtr.get(), rShapeTypes ); - rShapes.push_back( pShapePtr ); - } - break; - case NMSP_VML|XML_shapetype : - { - ShapePtr pShapePtr( new Shape( OUString() ) ); - xRet = new ShapeTypeContext( rParent, aElementToken, xAttribs, *pShapePtr.get() ); - rShapeTypes.push_back( pShapePtr ); - } - break; - case NMSP_VML|XML_shape: - { - ShapePtr pShapePtr( new Shape( sCustomShape ) ); - xRet = new ShapeContext( rParent, aElementToken, xAttribs, *pShapePtr.get() ); - rShapes.push_back( pShapePtr ); - } - break; - case NMSP_VML|XML_oval: - { - static const ::rtl::OUString sEllipseShape( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.EllipseShape" ) ); - ShapePtr pShapePtr( new Shape( sEllipseShape ) ); - xRet = new ShapeContext( rParent, aElementToken, xAttribs, *pShapePtr.get() ); - rShapes.push_back( pShapePtr ); - } - break; - case NMSP_VML|XML_polyline: - { - static const ::rtl::OUString sPolyLineShape( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.PolyLineShape" ) ); - ShapePtr pShapePtr( new Shape( sPolyLineShape ) ); - xRet = new PolyLineContext( rParent, aElementToken, xAttribs, *pShapePtr.get() ); - rShapes.push_back( pShapePtr ); - } - break; - case NMSP_VML|XML_rect: - { - static const ::rtl::OUString sRectangleShape( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.RectangleShape" ) ); - ShapePtr pShapePtr( new Shape( sRectangleShape ) ); - xRet = new ShapeContext( rParent, aElementToken, xAttribs, *pShapePtr.get() ); - rShapes.push_back( pShapePtr ); - } - break; - case NMSP_VML|XML_roundrect: - { - static const ::rtl::OUString sRectangleShape( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.RectangleShape" ) ); - ShapePtr pShapePtr( new Shape( sRectangleShape ) ); - xRet = new ShapeContext( rParent, aElementToken, xAttribs, *pShapePtr.get() ); - rShapes.push_back( pShapePtr ); - } - break; - - // TODO: - case NMSP_VML|XML_arc: - { - ShapePtr pShapePtr( new Shape( sCustomShape ) ); - xRet = new ShapeContext( rParent, aElementToken, xAttribs, *pShapePtr.get() ); - rShapes.push_back( pShapePtr ); - } - break; - case NMSP_VML|XML_curve: - { - ShapePtr pShapePtr( new Shape( sCustomShape ) ); - xRet = new ShapeContext( rParent, aElementToken, xAttribs, *pShapePtr.get() ); - rShapes.push_back( pShapePtr ); - } - break; - case NMSP_VML|XML_line: - { - ShapePtr pShapePtr( new Shape( sCustomShape ) ); - xRet = new ShapeContext( rParent, aElementToken, xAttribs, *pShapePtr.get() ); - rShapes.push_back( pShapePtr ); - } - break; - case NMSP_OFFICE|XML_diagram: - { - ShapePtr pShapePtr( new Shape( sCustomShape ) ); - xRet = new ShapeContext( rParent, aElementToken, xAttribs, *pShapePtr.get() ); - rShapes.push_back( pShapePtr ); - } - break; - case NMSP_VML|XML_image: - { - ShapePtr pShapePtr( new Shape( sCustomShape ) ); - xRet = new ShapeContext( rParent, aElementToken, xAttribs, *pShapePtr.get() ); - rShapes.push_back( pShapePtr ); - } - break; - } - return xRet; -} - - -// CT_GROUP -Reference< XFastContextHandler > DrawingFragmentHandler::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) - throw (SAXException, RuntimeException) -{ - return aElementToken == XML_xml - ? getFastContextHandler() - : StaticCreateContext( *this, aElementToken, xAttribs, mrShapes, mrShapeTypes ); -} - -void SAL_CALL DrawingFragmentHandler::endDocument() - throw (SAXException, RuntimeException) -{ -} - -//-------------------------------------------------------------------------------------------------------------- - - - -} } - diff --git a/oox/source/vml/vmlinputstream.cxx b/oox/source/vml/vmlinputstream.cxx new file mode 100644 index 000000000000..56964ad4ab19 --- /dev/null +++ b/oox/source/vml/vmlinputstream.cxx @@ -0,0 +1,94 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: vmldrawing.cxx,v $ + * $Revision: 1.5 $ + * + * 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. + * + ************************************************************************/ + +#include "oox/vml/vmlinputstream.hxx" +#include <algorithm> +#include <string.h> + +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::io::XInputStream; + +namespace oox { +namespace vml { + +// ============================================================================ + +StreamDataContainer::StreamDataContainer( const Reference< XInputStream >& rxInStrm ) +{ + if( rxInStrm.is() ) try + { + // read all bytes we can read + rxInStrm->readBytes( maDataSeq, SAL_MAX_INT32 ); + } + catch( Exception& ) + { + } + + // parse the data and eat all parser instructions that make expat sad + if( maDataSeq.hasElements() ) + { + sal_Char* pcBeg = reinterpret_cast< sal_Char* >( maDataSeq.getArray() ); + sal_Char* pcEnd = pcBeg + maDataSeq.getLength(); + sal_Char* pcCurr = pcBeg; + while( pcCurr < pcEnd ) + { + pcCurr = ::std::find( pcCurr, pcEnd, '<' ); + sal_Char* pcClose = ::std::find( pcCurr, pcEnd, '>' ); + if( (pcCurr < pcEnd) && (pcClose < pcEnd) && (pcClose - pcCurr >= 5) && (pcCurr[ 1 ] == '!') && (pcCurr[ 2 ] == '[') && (pcClose[ -1 ] == ']') ) + { + ++pcClose; + memmove( pcCurr, pcClose, pcEnd - pcClose ); + pcEnd -= (pcClose - pcCurr); + } + else + pcCurr = pcClose; + } + maDataSeq.realloc( static_cast< sal_Int32 >( pcEnd - pcBeg ) ); + } +} + +// ============================================================================ + +InputStream::InputStream( const Reference< XInputStream >& rxInStrm ) : + StreamDataContainer( rxInStrm ), + ::comphelper::SequenceInputStream( maDataSeq ) +{ +} + +InputStream::~InputStream() +{ +} + +// ============================================================================ + +} // namespace vml +} // namespave oox + diff --git a/oox/source/vml/vmlshape.cxx b/oox/source/vml/vmlshape.cxx index 106eb394651f..e583248adcfa 100644 --- a/oox/source/vml/vmlshape.cxx +++ b/oox/source/vml/vmlshape.cxx @@ -28,206 +28,534 @@ * ************************************************************************/ -#include <rtl/ustring.hxx> -#include "oox/vml/shape.hxx" -#include "oox/core/xmlfilterbase.hxx" -#include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp> +#include "oox/vml/vmlshape.hxx" +#include <rtl/math.hxx> #include <com/sun/star/lang/XMultiServiceFactory.hpp> -#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/PropertyValues.hpp> +#include <com/sun/star/awt/XControlModel.hpp> #include <com/sun/star/drawing/FillStyle.hpp> +#include <com/sun/star/drawing/PointSequenceSequence.hpp> +#include <com/sun/star/drawing/XControlShape.hpp> +#include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp> +#include <com/sun/star/drawing/XShapes.hpp> +#include <com/sun/star/graphic/XGraphic.hpp> +#include "properties.hxx" +#include "oox/helper/propertymap.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/core/xmlfilterbase.hxx" +#include "oox/ole/axcontrol.hxx" +#include "oox/ole/axcontrolfragment.hxx" +#include "oox/ole/oleobjecthelper.hxx" +#include "oox/vml/vmldrawing.hxx" +#include "oox/vml/vmlshapecontainer.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::uno::UNO_SET_THROW; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::awt::Point; +using ::com::sun::star::awt::Rectangle; +using ::com::sun::star::awt::Size; +using ::com::sun::star::awt::XControlModel; +using ::com::sun::star::graphic::XGraphic; +using ::com::sun::star::drawing::PointSequenceSequence; +using ::com::sun::star::drawing::XControlShape; +using ::com::sun::star::drawing::XEnhancedCustomShapeDefaulter; +using ::com::sun::star::drawing::XShape; +using ::com::sun::star::drawing::XShapes; +using ::oox::core::XmlFilterBase; + +namespace oox { +namespace vml { -using namespace com::sun::star; +// ============================================================================ -namespace oox { namespace vml { +namespace { -Shape::Shape( const rtl::OUString& rServiceName ) -: msServiceName( rServiceName ) -, mnCoordWidth( 0 ) -, mnCoordHeight( 0 ) -, mnStroked( 0 ) +sal_Int32 lclGetMeasure( const XmlFilterBase& /*rFilter*/, const OUString& rValue, sal_Int32 nRefValue ) { + // default for missing values is 0 + if( rValue.getLength() == 0 ) + return 0; + + // TODO: according to spec, value may contain "auto" + if( rValue.equalsAscii( "auto" ) ) + return nRefValue; + + // extract the double value and find start position of unit characters + rtl_math_ConversionStatus eConvStatus = rtl_math_ConversionStatus_Ok; + sal_Int32 nEndPos = 0; + double fValue = ::rtl::math::stringToDouble( rValue, '.', '\0', &eConvStatus, &nEndPos ); + if( (eConvStatus != rtl_math_ConversionStatus_Ok) || (fValue == 0.0) ) + return 0; + + // process trailing unit, convert to 1/100 mm + static const OUString saPx = CREATE_OUSTRING( "px" ); + OUString aUnit = ((0 < nEndPos) && (nEndPos < rValue.getLength())) ? rValue.copy( nEndPos ) : saPx; + if( aUnit.getLength() == 2 ) + { + sal_Unicode cChar1 = aUnit[ 0 ]; + sal_Unicode cChar2 = aUnit[ 1 ]; + if( (cChar1 == 'i') && (cChar2 == 'n') ) // 1 inch = 2540 1/100mm + fValue *= 2540.0; + else if( (cChar1 == 'c') && (cChar2 == 'm') ) // 1 cm = 1000 1/100mm + fValue *= 1000.0; + else if( (cChar1 == 'm') && (cChar2 == 'm') ) // 1 mm = 100 1/100mm + fValue *= 100.0; + else if( (cChar1 == 'p') && (cChar2 == 't') ) // 1 point = 1/72 inch + fValue *= 2540.0 / 72.0; + else if( (cChar1 == 'p') && (cChar2 == 'c') ) // 1 pica = 1/6 inch + fValue *= 2540.0 / 6.0; + else if( (cChar1 == 'e') && (cChar2 == 'm') ) // relative to refvalue + fValue *= nRefValue; + else if( (cChar1 == 'p') && (cChar2 == 'x') ) // 1 pixel, dependent on output device + fValue *= 1.0; + } + else if( (aUnit.getLength() == 1) && (aUnit[ 0 ] == '%') ) + { + fValue *= nRefValue / 100.0; + } + else + { + OSL_ENSURE( false, "lclGetMeasure - unknown measure unit" ); + fValue = nRefValue; + } + return static_cast< sal_Int32 >( fValue + 0.5 ); } -Shape::~Shape() + +Point lclGetAbsPoint( const Point& rRelPoint, const Rectangle& rShapeRect, const Rectangle& rCoordSys ) { + double fWidthRatio = static_cast< double >( rShapeRect.Width ) / rCoordSys.Width; + double fHeightRatio = static_cast< double >( rShapeRect.Height ) / rCoordSys.Height; + Point aAbsPoint; + aAbsPoint.X = static_cast< sal_Int32 >( rShapeRect.X + fWidthRatio * (rRelPoint.X - rCoordSys.X) + 0.5 ); + aAbsPoint.Y = static_cast< sal_Int32 >( rShapeRect.Y + fHeightRatio * (rRelPoint.Y - rCoordSys.Y) + 0.5 ); + return aAbsPoint; } -void Shape::applyAttributes( const vml::Shape& rSource ) +Rectangle lclGetAbsRect( const Rectangle& rRelRect, const Rectangle& rShapeRect, const Rectangle& rCoordSys ) { - if ( rSource.msId.getLength() ) - msId = rSource.msId; - if ( rSource.msType.getLength() ) - msType = rSource.msType; - if ( rSource.msShapeType.getLength() ) - msShapeType = rSource.msShapeType; - if ( rSource.mnCoordWidth ) - mnCoordWidth = rSource.mnCoordWidth; - if ( rSource.mnCoordHeight ) - mnCoordHeight = rSource.mnCoordHeight; - if ( rSource.mnStroked ) - mnStroked = rSource.mnStroked; - if ( rSource.moFilled ) - moFilled = rSource.moFilled; - if ( rSource.moFillColor ) - moFillColor = rSource.moFillColor; - if ( rSource.maPath.Name.getLength() ) - maPath = rSource.maPath; - if ( rSource.msPosition.getLength() ) - msPosition = rSource.msPosition; - maPosition = rSource.maPosition; - maSize = rSource.maSize; + double fWidthRatio = static_cast< double >( rShapeRect.Width ) / rCoordSys.Width; + double fHeightRatio = static_cast< double >( rShapeRect.Height ) / rCoordSys.Height; + Rectangle aAbsRect; + aAbsRect.X = static_cast< sal_Int32 >( rShapeRect.X + fWidthRatio * (rRelRect.X - rCoordSys.X) + 0.5 ); + aAbsRect.Y = static_cast< sal_Int32 >( rShapeRect.Y + fHeightRatio * (rRelRect.Y - rCoordSys.Y) + 0.5 ); + aAbsRect.Width = static_cast< sal_Int32 >( fWidthRatio * rRelRect.Width + 0.5 ); + aAbsRect.Height = static_cast< sal_Int32 >( fHeightRatio * rRelRect.Height + 0.5 ); + return aAbsRect; } -::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > Shape::createAndInsert( - const ::oox::core::XmlFilterBase& rFilterBase, const ::oox::vml::Shape& rShape, - const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes, - const awt::Rectangle* pShapeRect ) +Reference< XShape > lclCreateXShape( const XmlFilterBase& rFilter, const OUString& rService ) { - uno::Reference< drawing::XShape > xShape; - if ( rShape.msServiceName ) + OSL_ENSURE( rService.getLength() > 0, "lclCreateXShape - missing UNO shape service name" ); + Reference< XShape > xShape; + try { - try - { - uno::Reference< lang::XMultiServiceFactory > xServiceFact( rFilterBase.getModel(), uno::UNO_QUERY_THROW ); - xShape.set( xServiceFact->createInstance( rShape.msServiceName ), uno::UNO_QUERY_THROW ); - rxShapes->add( xShape ); - awt::Point aPosition; - awt::Size aSize; - if ( pShapeRect ) - { - aPosition.X = pShapeRect->X; - aPosition.Y = pShapeRect->Y; - aSize.Width = pShapeRect->Width; - aSize.Height = pShapeRect->Height; - } - else - { - aPosition = maPosition; - aSize = maSize; - } - xShape->setPosition( aPosition ); - xShape->setSize( aSize ); - uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY ); - try - { - if ( maPath.Name.getLength() ) - xPropSet->setPropertyValue( maPath.Name, maPath.Value ); + Reference< XMultiServiceFactory > xFactory( rFilter.getModel(), UNO_QUERY_THROW ); + xShape.set( xFactory->createInstance( rService ), UNO_QUERY_THROW ); + } + catch( Exception& ) + { + } + OSL_ENSURE( xShape.is(), "lclCreateXShape - cannot instanciate shape object" ); + return xShape; +} - ::rtl::OUString sFillStyle( rtl::OUString::createFromAscii( "FillStyle" ) ); - if ( moFilled ) - xPropSet->setPropertyValue( sFillStyle, uno::Any( *moFilled ? drawing::FillStyle_SOLID : drawing::FillStyle_NONE ) ); - } - catch ( uno::Exception& ) - { - } - ::rtl::OUString rServiceName( rtl::OUString::createFromAscii( "com.sun.star.drawing.CustomShape" ) ); - if ( rShape.msShapeType.getLength() && ( msServiceName == rServiceName ) ) - { - uno::Reference< drawing::XEnhancedCustomShapeDefaulter > xDefaulter( xShape, uno::UNO_QUERY ); - if( xDefaulter.is() ) - xDefaulter->createCustomShapeDefaults( rShape.msShapeType ); - } - mxShape = xShape; - } - catch( uno::Exception& ) - { - } +void lclInsertXShape( const Reference< XShapes >& rxShapes, const Reference< XShape >& rxShape, const Rectangle& rShapeRect ) +{ + OSL_ENSURE( rxShapes.is(), "lclInsertXShape - missing XShapes container" ); + OSL_ENSURE( rxShape.is(), "lclInsertXShape - missing XShape" ); + if( rxShapes.is() && rxShape.is() ) try + { + // insert shape into passed shape collection (maybe drawpage or group shape) + rxShapes->add( rxShape ); + // set position/size + rxShape->setPosition( Point( rShapeRect.X, rShapeRect.Y ) ); + rxShape->setSize( Size( rShapeRect.Width, rShapeRect.Height ) ); + } + catch( Exception& ) + { + } +} + +Reference< XShape > lclCreateAndInsertXShape( const XmlFilterBase& rFilter, + const Reference< XShapes >& rxShapes, const OUString& rService, const Rectangle& rShapeRect ) +{ + Reference< XShape > xShape = lclCreateXShape( rFilter, rService ); + lclInsertXShape( rxShapes, xShape, rShapeRect ); + return xShape; +} + +} // namespace + +// ============================================================================ + +ShapeTypeModel::ShapeTypeModel() +{ +} + +void ShapeTypeModel::assignUsed( const ShapeTypeModel& rSource ) +{ + monShapeType.assignIfUsed( rSource.monShapeType ); + monCoordLeft.assignIfUsed( rSource.monCoordLeft ); + monCoordTop.assignIfUsed( rSource.monCoordTop ); + monCoordWidth.assignIfUsed( rSource.monCoordWidth ); + monCoordHeight.assignIfUsed( rSource.monCoordHeight ); + /* The style properties position, left, top, width, height, margin-left, + margin-top are not derived from shape template to shape. */ + mobStroked.assignIfUsed( rSource.mobStroked ); + moStrokeColor.assignIfUsed( rSource.moStrokeColor ); + mobFilled.assignIfUsed( rSource.mobFilled ); + moFillColor.assignIfUsed( rSource.moFillColor ); + moGraphicPath.assignIfUsed( rSource.moGraphicPath ); + moGraphicTitle.assignIfUsed( rSource.moGraphicTitle ); +} + +// ---------------------------------------------------------------------------- + +ShapeType::ShapeType( const Drawing& rDrawing ) : + mrDrawing( rDrawing ) +{ +} + +ShapeType::~ShapeType() +{ +} + +OUString ShapeType::getGraphicPath() const +{ + return maTypeModel.moGraphicPath.get( OUString() ); +} + +Rectangle ShapeType::getCoordSystem() const +{ + return Rectangle( + maTypeModel.monCoordLeft.get( 0 ), + maTypeModel.monCoordTop.get( 0 ), + maTypeModel.monCoordWidth.get( 1000 ), + maTypeModel.monCoordHeight.get( 1000 ) ); +} + +Rectangle ShapeType::getRectangle( const ShapeParentAnchor* pParentAnchor ) const +{ + return pParentAnchor ? + lclGetAbsRect( getRelRectangle(), pParentAnchor->maShapeRect, pParentAnchor->maCoordSys ) : + getAbsRectangle(); +} + +Rectangle ShapeType::getAbsRectangle() const +{ + const XmlFilterBase& rFilter = mrDrawing.getFilter(); + return Rectangle( + lclGetMeasure( rFilter, maTypeModel.maLeft, 0 ) + lclGetMeasure( rFilter, maTypeModel.maMarginLeft, 0 ), + lclGetMeasure( rFilter, maTypeModel.maTop, 0 ) + lclGetMeasure( rFilter, maTypeModel.maMarginTop, 0 ), + lclGetMeasure( rFilter, maTypeModel.maWidth, 0 ), + lclGetMeasure( rFilter, maTypeModel.maHeight, 0 ) ); +} + +Rectangle ShapeType::getRelRectangle() const +{ + return Rectangle( + maTypeModel.maLeft.toInt32(), + maTypeModel.maTop.toInt32(), + maTypeModel.maWidth.toInt32(), + maTypeModel.maHeight.toInt32() ); +} + +// ============================================================================ + +ShapeClientData::ShapeClientData() : + mnObjType( XML_TOKEN_INVALID ), + mbPrintObject( true ) +{ +} + +// ---------------------------------------------------------------------------- + +ShapeModel::ShapeModel() +{ +} + +ShapeClientData& ShapeModel::createClientData() +{ + mxClientData.reset( new ShapeClientData ); + return *mxClientData; +} + +// ---------------------------------------------------------------------------- + +ShapeBase::ShapeBase( const Drawing& rDrawing ) : + ShapeType( rDrawing ) +{ +} + +void ShapeBase::finalizeFragmentImport() +{ + // resolve shape template reference + if( (maShapeModel.maType.getLength() > 1) && (maShapeModel.maType[ 0 ] == '#') ) + if( const ShapeType* pShapeType = mrDrawing.getShapes().getShapeTypeById( maShapeModel.maType.copy( 1 ), true ) ) + maTypeModel.assignUsed( pShapeType->getTypeModel() ); +} + +const ShapeType* ShapeBase::getChildTypeById( const OUString& ) const +{ + return 0; +} + +const ShapeBase* ShapeBase::getChildById( const OUString& ) const +{ + return 0; +} + +Reference< XShape > ShapeBase::convertAndInsert( const Reference< XShapes >& rxShapes, const ShapeParentAnchor* pParentAnchor ) const +{ + Reference< XShape > xShape; + /* Calculate shape rectangle. Applications may do something special + according to some imported shape client data (e.g. Excel cell anchor). */ + Rectangle aShapeRect; + if( !maShapeModel.mxClientData.get() || !mrDrawing.convertShapeClientAnchor( aShapeRect, maShapeModel.mxClientData->maAnchor ) ) + aShapeRect = getRectangle( pParentAnchor ); + // convert the shape, if the calculated rectangle is not empty + if( (aShapeRect.Width > 0) || (aShapeRect.Height > 0) && rxShapes.is() ) + xShape = implConvertAndInsert( rxShapes, aShapeRect ); + return xShape; +} + +// protected ------------------------------------------------------------------ + +void ShapeBase::convertShapeProperties( const Reference< XShape >& rxShape ) const +{ + // shape properties + PropertySet aPropSet( rxShape ); + + // fill style + bool bFilled = maTypeModel.mobFilled.get( true ); + aPropSet.setProperty( PROP_FillStyle, bFilled ? ::com::sun::star::drawing::FillStyle_SOLID : ::com::sun::star::drawing::FillStyle_NONE ); +} + +// ============================================================================ + +SimpleShape::SimpleShape( const Drawing& rDrawing, const OUString& rService ) : + ShapeBase( rDrawing ), + maService( rService ) +{ +} + +Reference< XShape > SimpleShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const +{ + Reference< XShape > xShape = lclCreateAndInsertXShape( mrDrawing.getFilter(), rxShapes, maService, rShapeRect ); + convertShapeProperties( xShape ); + return xShape; +} + +// ============================================================================ + +RectangleShape::RectangleShape( const Drawing& rDrawing ) : + SimpleShape( rDrawing, CREATE_OUSTRING( "com.sun.star.drawing.RectangleShape" ) ) +{ +} + +// ============================================================================ + +EllipseShape::EllipseShape( const Drawing& rDrawing ) : + SimpleShape( rDrawing, CREATE_OUSTRING( "com.sun.star.drawing.EllipseShape" ) ) +{ +} + +// ============================================================================ + +PolyLineShape::PolyLineShape( const Drawing& rDrawing ) : + SimpleShape( rDrawing, CREATE_OUSTRING( "com.sun.star.drawing.PolyLineShape" ) ) +{ +} + +Reference< XShape > PolyLineShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const +{ + Reference< XShape > xShape = SimpleShape::implConvertAndInsert( rxShapes, rShapeRect ); + // polygon path + Rectangle aCoordSys = getCoordSystem(); + if( !maShapeModel.maPoints.empty() && (aCoordSys.Width > 0) && (aCoordSys.Height > 0) ) + { + ::std::vector< Point > aAbsPoints; + for( ShapeModel::PointVector::const_iterator aIt = maShapeModel.maPoints.begin(), aEnd = maShapeModel.maPoints.end(); aIt != aEnd; ++aIt ) + aAbsPoints.push_back( lclGetAbsPoint( *aIt, rShapeRect, aCoordSys ) ); + PointSequenceSequence aPointSeq( 1 ); + aPointSeq[ 0 ] = ContainerHelper::vectorToSequence( aAbsPoints ); + PropertySet aPropSet( xShape ); + aPropSet.setProperty( PROP_PolyPolygon, aPointSeq ); } return xShape; } -void Shape::addChilds( const ::oox::core::XmlFilterBase& rFilterBase, const ::oox::vml::Drawing& rDrawing, - const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes, - const awt::Rectangle& rClientRect ) +// ============================================================================ + +CustomShape::CustomShape( const Drawing& rDrawing ) : + SimpleShape( rDrawing, CREATE_OUSTRING( "com.sun.star.drawing.CustomShape" ) ) { - sal_Int32 nGlobalLeft = SAL_MAX_INT32; - sal_Int32 nGlobalRight = SAL_MIN_INT32; - sal_Int32 nGlobalTop = SAL_MAX_INT32; - sal_Int32 nGlobalBottom= SAL_MIN_INT32; - std::vector< ShapePtr >::iterator aIter( maChilds.begin() ); - while( aIter != maChilds.end() ) +} + +Reference< XShape > CustomShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const +{ + // try to create a custom shape + Reference< XShape > xShape = SimpleShape::implConvertAndInsert( rxShapes, rShapeRect ); + if( xShape.is() ) try { - sal_Int32 l = (*aIter)->maPosition.X; - sal_Int32 t = (*aIter)->maPosition.Y; - sal_Int32 r = l + (*aIter)->maSize.Width; - sal_Int32 b = t + (*aIter)->maSize.Height; - if ( nGlobalLeft > l ) - nGlobalLeft = l; - if ( nGlobalRight < r ) - nGlobalRight = r; - if ( nGlobalTop > t ) - nGlobalTop = t; - if ( nGlobalBottom < b ) - nGlobalBottom = b; - aIter++; + // create the custom shape geometry + Reference< XEnhancedCustomShapeDefaulter > xDefaulter( xShape, UNO_QUERY_THROW ); + xDefaulter->createCustomShapeDefaults( OUString::valueOf( maTypeModel.monShapeType.get( 0 ) ) ); + // convert common properties + convertShapeProperties( xShape ); } - aIter = maChilds.begin(); - while( aIter != maChilds.end() ) + catch( Exception& ) { - awt::Rectangle aShapeRect; - awt::Rectangle* pShapeRect = 0; - if ( ( nGlobalLeft != SAL_MAX_INT32 ) && ( nGlobalRight != SAL_MIN_INT32 ) && ( nGlobalTop != SAL_MAX_INT32 ) && ( nGlobalBottom != SAL_MIN_INT32 ) ) - { - sal_Int32 nGlobalWidth = nGlobalRight - nGlobalLeft; - sal_Int32 nGlobalHeight = nGlobalBottom - nGlobalTop; - if ( nGlobalWidth && nGlobalHeight ) - { - double fWidth = (*aIter)->maSize.Width; - double fHeight= (*aIter)->maSize.Height; - double fXScale = (double)rClientRect.Width / (double)nGlobalWidth; - double fYScale = (double)rClientRect.Height / (double)nGlobalHeight; - aShapeRect.X = static_cast< sal_Int32 >( ( ( (*aIter)->maPosition.X - nGlobalLeft ) * fXScale ) + rClientRect.X ); - aShapeRect.Y = static_cast< sal_Int32 >( ( ( (*aIter)->maPosition.Y - nGlobalTop ) * fYScale ) + rClientRect.Y ); - fWidth *= fXScale; - fHeight *= fYScale; - aShapeRect.Width = static_cast< sal_Int32 >( fWidth ); - aShapeRect.Height = static_cast< sal_Int32 >( fHeight ); - pShapeRect = &aShapeRect; - } - } - (*aIter++)->addShape( rFilterBase, rDrawing, rxShapes, pShapeRect ); } + return xShape; +} + +// ============================================================================ + +ComplexShape::ComplexShape( const Drawing& rDrawing ) : + CustomShape( rDrawing ) +{ } -void Shape::addShape( const ::oox::core::XmlFilterBase& rFilterBase, const ::oox::vml::Drawing& rDrawing, - const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes, - const awt::Rectangle* pShapeRect ) +Reference< XShape > ComplexShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const { - oox::vml::Shape aShape( msServiceName ); - if ( msType.getLength() ) + XmlFilterBase& rFilter = mrDrawing.getFilter(); + OUString aGraphicPath = getGraphicPath(); + + // try to find registered OLE object info + if( const OleObjectInfo* pOleObjectInfo = mrDrawing.getOleObjectInfo( maTypeModel.maShapeId ) ) { - std::vector< ShapePtr >& rShapeTypes = const_cast< ::oox::vml::Drawing& >( rDrawing ).getShapeTypes(); - std::vector< ShapePtr >::const_iterator aShapeTypeIter( rShapeTypes.begin() ); - while( aShapeTypeIter != rShapeTypes.end() ) + // if OLE object is embedded into a DrawingML shape (PPTX), do not create it here + if( pOleObjectInfo->mbDmlShape ) + return Reference< XShape >(); + + PropertyMap aOleProps; + Size aOleSize( rShapeRect.Width, rShapeRect.Height ); + if( rFilter.getOleObjectHelper().importOleObject( aOleProps, *pOleObjectInfo, aOleSize ) ) { - if ( (*aShapeTypeIter)->msType == aShape.msType ) + Reference< XShape > xShape = lclCreateAndInsertXShape( rFilter, rxShapes, CREATE_OUSTRING( "com.sun.star.drawing.OLE2Shape" ), rShapeRect ); + if( xShape.is() ) { - aShape.applyAttributes( *(*aShapeTypeIter).get() ); - break; + // set the replacement graphic + if( aGraphicPath.getLength() > 0 ) + { + Reference< XGraphic > xGraphic = rFilter.importEmbeddedGraphic( aGraphicPath ); + if( xGraphic.is() ) + aOleProps[ PROP_Graphic ] <<= xGraphic; + } + + PropertySet aPropSet( xShape ); + aPropSet.setProperties( aOleProps ); + + return xShape; } - aShapeTypeIter++; } } - aShape.applyAttributes( *this ); - // creating XShape - uno::Reference< drawing::XShape > xShape( createAndInsert( rFilterBase, aShape, rxShapes, pShapeRect ) ); + // try to find registered form control info + const ControlInfo* pControlInfo = mrDrawing.getControlInfo( maTypeModel.maShapeId ); + if( pControlInfo && (pControlInfo->maFragmentPath.getLength() > 0) && (maTypeModel.maName.getLength() > 0) ) + { + OSL_ENSURE( maTypeModel.maName == pControlInfo->maName, "ComplexShape::implConvertAndInsert - control name mismatch" ); + ::oox::ole::AxControl aControl( maTypeModel.maName ); + // load the control properties from fragment + if( rFilter.importFragment( new ::oox::ole::AxControlFragment( rFilter, pControlInfo->maFragmentPath, aControl ) ) ) try + { + // create control model and insert it into the form of the draw page + Reference< XControlModel > xCtrlModel( aControl.convertAndInsert( mrDrawing.getControlHelper() ), UNO_SET_THROW ); + if( maShapeModel.mxClientData.get() ) + mrDrawing.convertControlClientData( xCtrlModel, *maShapeModel.mxClientData ); - // creating GroupShape if possible - uno::Reference< drawing::XShapes > xShapes( xShape, uno::UNO_QUERY ); - if ( xShapes.is() ) + // create the control shape, set control model at the shape + Reference< XShape > xShape = lclCreateAndInsertXShape( + rFilter, rxShapes, CREATE_OUSTRING( "com.sun.star.drawing.ControlShape" ), rShapeRect ); + Reference< XControlShape > xCtrlShape( xShape, UNO_QUERY ); // do not throw, but always return the shape + if( xCtrlShape.is() ) + xCtrlShape->setControl( xCtrlModel ); + return xShape; + } + catch( Exception& ) + { + } + // on error, proceed and try to create picture from replacement image + } + + // try to create a picture object + if( aGraphicPath.getLength() > 0 ) { - awt::Rectangle aChildRect; - if ( pShapeRect ) - aChildRect = *pShapeRect; - else + Reference< XShape > xShape = lclCreateAndInsertXShape( rFilter, rxShapes, CREATE_OUSTRING( "com.sun.star.drawing.GraphicObjectShape" ), rShapeRect ); + if( xShape.is() ) { - aChildRect.X = maPosition.X; - aChildRect.Y = maPosition.Y; - aChildRect.Width = maSize.Width; - aChildRect.Height = maSize.Height; + OUString aGraphicUrl = rFilter.importEmbeddedGraphicObject( aGraphicPath ); + if( aGraphicUrl.getLength() > 0 ) + { + PropertySet aPropSet( xShape ); + aPropSet.setProperty( PROP_GraphicURL, aGraphicUrl ); + } } - addChilds( rFilterBase, rDrawing, xShapes, aChildRect ); + return xShape; + } + + // default: try to create a custom shape + return CustomShape::implConvertAndInsert( rxShapes, rShapeRect ); +} + +// ============================================================================ + +GroupShape::GroupShape( const Drawing& rDrawing ) : + ShapeBase( rDrawing ), + mxChildren( new ShapeContainer( rDrawing ) ) +{ +} + +GroupShape::~GroupShape() +{ +} + +void GroupShape::finalizeFragmentImport() +{ + // basic shape processing + ShapeBase::finalizeFragmentImport(); + // finalize all child shapes + mxChildren->finalizeFragmentImport(); +} + +const ShapeType* GroupShape::getChildTypeById( const OUString& rShapeId ) const +{ + return mxChildren->getShapeTypeById( rShapeId, true ); +} + +const ShapeBase* GroupShape::getChildById( const OUString& rShapeId ) const +{ + return mxChildren->getShapeById( rShapeId, true ); +} + +Reference< XShape > GroupShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const +{ + Reference< XShape > xShape; + // check that this shape contains children and a valid coordinate system + ShapeParentAnchor aParentAnchor; + aParentAnchor.maShapeRect = rShapeRect; + aParentAnchor.maCoordSys = getCoordSystem(); + if( !mxChildren->empty() && (aParentAnchor.maCoordSys.Width > 0) && (aParentAnchor.maCoordSys.Height > 0) ) try + { + xShape = lclCreateAndInsertXShape( mrDrawing.getFilter(), rxShapes, CREATE_OUSTRING( "com.sun.star.drawing.GroupShape" ), rShapeRect ); + Reference< XShapes > xShapes( xShape, UNO_QUERY_THROW ); + mxChildren->convertAndInsert( xShapes, &aParentAnchor ); } + catch( Exception& ) + { + } + return xShape; } -} } +// ============================================================================ + +} // namespace vml +} // namespace oox + diff --git a/oox/source/vml/vmlshapecontainer.cxx b/oox/source/vml/vmlshapecontainer.cxx new file mode 100644 index 000000000000..3b9346f3096a --- /dev/null +++ b/oox/source/vml/vmlshapecontainer.cxx @@ -0,0 +1,137 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: vmlshapecontainer.cxx,v $ + * $Revision: 1.1 $ + * + * 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. + * + ************************************************************************/ + +#include "oox/vml/vmlshapecontainer.hxx" +#include "oox/vml/vmldrawing.hxx" +#include "oox/vml/vmlshape.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::awt::Rectangle; +using ::com::sun::star::drawing::XShapes; +using ::oox::core::XmlFilterBase; + +namespace oox { +namespace vml { + +// ============================================================================ + +namespace { + +template< typename ShapeType > +void lclMapShapesById( RefMap< OUString, ShapeType >& orMap, const RefVector< ShapeType >& rVector ) +{ + for( typename RefVector< ShapeType >::const_iterator aIt = rVector.begin(), aEnd = rVector.end(); aIt != aEnd; ++aIt ) + { + const OUString& rShapeId = (*aIt)->getShapeId(); + OSL_ENSURE( rShapeId.getLength() > 0, "lclMapShapesById - missing shape identifier" ); + if( rShapeId.getLength() > 0 ) + { + OSL_ENSURE( orMap.find( rShapeId ) == orMap.end(), "lclMapShapesById - shape identifier already used" ); + orMap[ rShapeId ] = *aIt; + } + } +} + +} // namespace + +// ============================================================================ + +ShapeContainer::ShapeContainer( const Drawing& rDrawing ) : + mrDrawing( rDrawing ) +{ +} + +ShapeContainer::~ShapeContainer() +{ +} + +ShapeType& ShapeContainer::createShapeType() +{ + ::boost::shared_ptr< ShapeType > xShape( new ShapeType( mrDrawing ) ); + maTypes.push_back( xShape ); + return *xShape; +} + +void ShapeContainer::finalizeFragmentImport() +{ + // map all shape templates by shape identifier + lclMapShapesById( maTypesById, maTypes ); + // map all shapes by shape identifier + lclMapShapesById( maShapesById, maShapes ); + /* process all shapes (map all children templates/shapes in group shapes, + resolve template references in all shapes) */ + maShapes.forEachMem( &ShapeBase::finalizeFragmentImport ); +} + +const ShapeType* ShapeContainer::getShapeTypeById( const OUString& rShapeId, bool bDeep ) const +{ + // search in own shape template list + if( const ShapeType* pType = maTypesById.get( rShapeId ).get() ) + return pType; + // search deep in child shapes + if( bDeep ) + for( ShapeVector::const_iterator aVIt = maShapes.begin(), aVEnd = maShapes.end(); aVIt != aVEnd; ++aVIt ) + if( const ShapeType* pType = (*aVIt)->getChildTypeById( rShapeId ) ) + return pType; + return 0; +} + +const ShapeBase* ShapeContainer::getShapeById( const OUString& rShapeId, bool bDeep ) const +{ + // search in own shape list + if( const ShapeBase* pShape = maShapesById.get( rShapeId ).get() ) + return pShape; + // search deep in child shapes + if( bDeep ) + for( ShapeVector::const_iterator aVIt = maShapes.begin(), aVEnd = maShapes.end(); aVIt != aVEnd; ++aVIt ) + if( const ShapeBase* pShape = (*aVIt)->getChildById( rShapeId ) ) + return pShape; + return 0; +} + +const ShapeBase* ShapeContainer::getFirstShape() const +{ + OSL_ENSURE( mrDrawing.getType() == VMLDRAWING_WORD, "ShapeContainer::getFirstShape - illegal call, Word filter only" ); + OSL_ENSURE( maShapes.size() == 1, "ShapeContainer::getFirstShape - single shape expected" ); + return maShapes.get( 0 ).get(); +} + +void ShapeContainer::convertAndInsert( const Reference< XShapes >& rxShapes, const ShapeParentAnchor* pParentAnchor ) const +{ + for( ShapeVector::const_iterator aIt = maShapes.begin(), aEnd = maShapes.end(); aIt != aEnd; ++aIt ) + (*aIt)->convertAndInsert( rxShapes, pParentAnchor ); +} + +// ============================================================================ + +} // namespace vml +} // namespace oox + diff --git a/oox/source/vml/vmlshapecontext.cxx b/oox/source/vml/vmlshapecontext.cxx new file mode 100644 index 000000000000..dcf842a67a8f --- /dev/null +++ b/oox/source/vml/vmlshapecontext.cxx @@ -0,0 +1,267 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: vmldrawingfragmenthandler.cxx,v $ + * $Revision: 1.6 $ + * + * 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. + * + ************************************************************************/ + +#include "oox/vml/vmlshapecontext.hxx" +#include "oox/vml/vmlshape.hxx" +#include "oox/vml/vmlshapecontainer.hxx" + +using ::rtl::OUString; +using ::com::sun::star::awt::Point; +using ::oox::core::ContextHandler2; +using ::oox::core::ContextHandler2Helper; +using ::oox::core::ContextHandlerRef; + +namespace oox { +namespace vml { + +// ============================================================================ + +namespace { + +bool lclSeparateValue( OUString& orName, OUString& orValue, const OUString& rAttrib, sal_Unicode cSep = ':' ) +{ + sal_Int32 nSepPos = rAttrib.indexOf( cSep ); + if( nSepPos <= 0 ) return false; + orName = rAttrib.copy( 0, nSepPos ).trim(); + orValue = rAttrib.copy( nSepPos + 1 ).trim(); + return (orName.getLength() > 0) && (orValue.getLength() > 0); +} + +/** Returns the boolean value from the passed string (supported: f, t, False, True). + @param bDefaultForEmpty Default value for the empty string. + */ +bool lclDecodeBool( const OUString& rValue, bool bDefaultForEmpty ) +{ + if( rValue.getLength() == 0 ) return bDefaultForEmpty; + // anything else than 't' or 'True' is considered to be false, as specified + return ((rValue.getLength() == 1) && (rValue[ 0 ] == 't')) || (rValue == CREATE_OUSTRING( "True" )); +} + +} // namespace + +// ============================================================================ + +ShapeClientDataContext::ShapeClientDataContext( ContextHandler2Helper& rParent, + const AttributeList& rAttribs, ShapeClientData& rClientData ) : + ContextHandler2( rParent ), + mrClientData( rClientData ) +{ + mrClientData.mnObjType = rAttribs.getToken( XML_ObjectType, XML_TOKEN_INVALID ); +} + +ContextHandlerRef ShapeClientDataContext::onCreateContext( sal_Int32 /*nElement*/, const AttributeList& /*rAttribs*/ ) +{ + return isRootElement() ? this : 0; +} + +void ShapeClientDataContext::onEndElement( const OUString& rChars ) +{ + switch( getCurrentElement() ) + { + case VMLX_TOKEN( Anchor ): mrClientData.maAnchor = rChars; break; + case VMLX_TOKEN( FmlaLink ): mrClientData.maLinkedCell = rChars; break; + case VMLX_TOKEN( FmlaPict ): mrClientData.maPictureLink = rChars; break; + case VMLX_TOKEN( FmlaRange ): mrClientData.maSourceRange = rChars; break; + case VMLX_TOKEN( PrintObject ): mrClientData.mbPrintObject = lclDecodeBool( rChars, true ); break; + } +} + +// ============================================================================ + +ShapeContextBase::ShapeContextBase( ContextHandler2Helper& rParent ) : + ContextHandler2( rParent ) +{ +} + +/*static*/ ContextHandlerRef ShapeContextBase::createContext( ContextHandler2Helper& rParent, + sal_Int32 nElement, const AttributeList& rAttribs, ShapeContainer& rShapes ) +{ + switch( nElement ) + { + case VML_TOKEN( shapetype ): + return new ShapeTypeContext( rParent, rAttribs, rShapes.createShapeType() ); + case VML_TOKEN( group ): + return new GroupShapeContext( rParent, rAttribs, rShapes.createShape< GroupShape >() ); + case VML_TOKEN( shape ): + return new ShapeContext( rParent, rAttribs, rShapes.createShape< ComplexShape >() ); + case VML_TOKEN( rect ): + case VML_TOKEN( roundrect ): + return new ShapeContext( rParent, rAttribs, rShapes.createShape< RectangleShape >() ); + case VML_TOKEN( oval ): + return new ShapeContext( rParent, rAttribs, rShapes.createShape< EllipseShape >() ); + case VML_TOKEN( polyline ): + return new ShapeContext( rParent, rAttribs, rShapes.createShape< PolyLineShape >() ); + + // TODO: + case VML_TOKEN( arc ): + case VML_TOKEN( curve ): + case VML_TOKEN( line ): + case VML_TOKEN( diagram ): + case VML_TOKEN( image ): + return new ShapeContext( rParent, rAttribs, rShapes.createShape< ComplexShape >() ); + } + return false; +} + +// ============================================================================ + +ShapeTypeContext::ShapeTypeContext( ContextHandler2Helper& rParent, const AttributeList& rAttribs, ShapeType& rShapeType ) : + ShapeContextBase( rParent ), + mrTypeModel( rShapeType.getTypeModel() ) +{ + // shape identifier and shape name + bool bHasOspid = rAttribs.hasAttribute( O_TOKEN( spid ) ); + mrTypeModel.maShapeId = rAttribs.getXString( bHasOspid ? O_TOKEN( spid ) : XML_id, OUString() ); + OSL_ENSURE( mrTypeModel.maShapeId.getLength() > 0, "ShapeTypeContext::ShapeTypeContext - missing shape identifier" ); + // if the o:spid attribute exists, the id attribute contains the user-defined shape name + if( bHasOspid ) + mrTypeModel.maName = rAttribs.getXString( XML_id, OUString() ); + // builtin shape type identifier + mrTypeModel.monShapeType = rAttribs.getInteger( O_TOKEN( spt ) ); + // coordinate system position/size + setCoordOrigin( rAttribs.getString( XML_coordorigin, OUString() ) ); + setCoordSize( rAttribs.getString( XML_coordsize, OUString() ) ); + // CSS style + setStyle( rAttribs.getString( XML_style, OUString() ) ); + // border line + mrTypeModel.mobStroked = rAttribs.getBool( XML_stroked ); + mrTypeModel.moStrokeColor = rAttribs.getString( XML_strokecolor ); + // shape fill + mrTypeModel.mobFilled = rAttribs.getBool( XML_filled ); + mrTypeModel.moFillColor = rAttribs.getString( XML_fillcolor ); +} + +ContextHandlerRef ShapeTypeContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + if( isRootElement() ) switch( nElement ) + { + case VML_TOKEN( imagedata ): + OptValue< OUString > oGraphicRelId = rAttribs.getString( O_TOKEN( relid ) ); + if( oGraphicRelId.has() ) + mrTypeModel.moGraphicPath = getFragmentPathFromRelId( oGraphicRelId.get() ); + mrTypeModel.moGraphicTitle = rAttribs.getString( O_TOKEN( title ) ); + break; + } + return 0; +} + +void ShapeTypeContext::setCoordOrigin( const OUString& rCoordOrigin ) +{ + OUString aCoordL, aCoordT; + if( lclSeparateValue( aCoordL, aCoordT, rCoordOrigin, ',' ) ) + { + mrTypeModel.monCoordLeft = aCoordL.toInt32(); + mrTypeModel.monCoordTop = aCoordT.toInt32(); + } +} + +void ShapeTypeContext::setCoordSize( const OUString& rCoordSize ) +{ + OUString aCoordW, aCoordH; + if( lclSeparateValue( aCoordW, aCoordH, rCoordSize, ',' ) ) + { + mrTypeModel.monCoordWidth = aCoordW.toInt32(); + mrTypeModel.monCoordHeight = aCoordH.toInt32(); + } +} + +void ShapeTypeContext::setStyle( const OUString& rStyle ) +{ + sal_Int32 nIndex = 0; + while( nIndex >= 0 ) + { + OUString aName, aValue; + if( lclSeparateValue( aName, aValue, rStyle.getToken( 0, ';', nIndex ) ) ) + { + if( aName.equalsAscii( "position" ) ) mrTypeModel.maPosition = aValue; + else if( aName.equalsAscii( "left" ) ) mrTypeModel.maLeft = aValue; + else if( aName.equalsAscii( "top" ) ) mrTypeModel.maTop = aValue; + else if( aName.equalsAscii( "width" ) ) mrTypeModel.maWidth = aValue; + else if( aName.equalsAscii( "height" ) ) mrTypeModel.maHeight = aValue; + else if( aName.equalsAscii( "margin-left" ) ) mrTypeModel.maMarginLeft = aValue; + else if( aName.equalsAscii( "margin-top" ) ) mrTypeModel.maMarginTop = aValue; + } + } +} + +// ============================================================================ + +ShapeContext::ShapeContext( ContextHandler2Helper& rParent, const AttributeList& rAttribs, ShapeBase& rShape ) : + ShapeTypeContext( rParent, rAttribs, rShape ), + mrShapeModel( rShape.getShapeModel() ) +{ + // collect shape specific attributes + mrShapeModel.maType = rAttribs.getXString( XML_type, OUString() ); + // polyline path + setPoints( rAttribs.getString( XML_points, OUString() ) ); +} + +ContextHandlerRef ShapeContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + // Excel specific shape client data + if( isRootElement() && (nElement == VMLX_TOKEN( ClientData )) ) + return new ShapeClientDataContext( *this, rAttribs, mrShapeModel.createClientData() ); + // handle remaining stuff in base class + return ShapeTypeContext::onCreateContext( nElement, rAttribs ); +} + +void ShapeContext::setPoints( const OUString& rPoints ) +{ + mrShapeModel.maPoints.clear(); + sal_Int32 nIndex = 0; + while( nIndex >= 0 ) + { + sal_Int32 nX = rPoints.getToken( 0, ',', nIndex ).toInt32(); + sal_Int32 nY = rPoints.getToken( 0, ',', nIndex ).toInt32(); + mrShapeModel.maPoints.push_back( Point( nX, nY ) ); + } +} + +// ============================================================================ + +GroupShapeContext::GroupShapeContext( ContextHandler2Helper& rParent, const AttributeList& rAttribs, GroupShape& rShape ) : + ShapeContext( rParent, rAttribs, rShape ), + mrShapes( rShape.getChildren() ) +{ +} + +ContextHandlerRef GroupShapeContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + // try to create a context of an embedded shape + ContextHandlerRef xContext = ShapeContextBase::createContext( *this, nElement, rAttribs, mrShapes ); + // handle remaining stuff of this shape in base class + return xContext.get() ? xContext : ShapeContext::onCreateContext( nElement, rAttribs ); +} + +// ============================================================================ + +} // namespace vml +} // namespace oox + |