xref: /aoo42x/main/oox/source/vml/vmldrawing.cxx (revision ca5ec200)
1*ca5ec200SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*ca5ec200SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*ca5ec200SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*ca5ec200SAndrew Rist  * distributed with this work for additional information
6*ca5ec200SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*ca5ec200SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*ca5ec200SAndrew Rist  * "License"); you may not use this file except in compliance
9*ca5ec200SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*ca5ec200SAndrew Rist  *
11*ca5ec200SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*ca5ec200SAndrew Rist  *
13*ca5ec200SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*ca5ec200SAndrew Rist  * software distributed under the License is distributed on an
15*ca5ec200SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*ca5ec200SAndrew Rist  * KIND, either express or implied.  See the License for the
17*ca5ec200SAndrew Rist  * specific language governing permissions and limitations
18*ca5ec200SAndrew Rist  * under the License.
19*ca5ec200SAndrew Rist  *
20*ca5ec200SAndrew Rist  *************************************************************/
21*ca5ec200SAndrew Rist 
22*ca5ec200SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #include "oox/vml/vmldrawing.hxx"
25cdf0e10cSrcweir 
26cdf0e10cSrcweir #include <algorithm>
27cdf0e10cSrcweir #include <com/sun/star/drawing/XControlShape.hpp>
28cdf0e10cSrcweir #include <com/sun/star/drawing/XShapes.hpp>
29cdf0e10cSrcweir #include <com/sun/star/lang/XMultiServiceFactory.hpp>
30cdf0e10cSrcweir #include "oox/core/xmlfilterbase.hxx"
31cdf0e10cSrcweir #include "oox/helper/containerhelper.hxx"
32cdf0e10cSrcweir #include "oox/ole/axcontrol.hxx"
33cdf0e10cSrcweir #include "oox/vml/vmlshape.hxx"
34cdf0e10cSrcweir #include "oox/vml/vmlshapecontainer.hxx"
35cdf0e10cSrcweir 
36cdf0e10cSrcweir namespace oox {
37cdf0e10cSrcweir namespace vml {
38cdf0e10cSrcweir 
39cdf0e10cSrcweir // ============================================================================
40cdf0e10cSrcweir 
41cdf0e10cSrcweir using namespace ::com::sun::star::awt;
42cdf0e10cSrcweir using namespace ::com::sun::star::drawing;
43cdf0e10cSrcweir using namespace ::com::sun::star::lang;
44cdf0e10cSrcweir using namespace ::com::sun::star::uno;
45cdf0e10cSrcweir 
46cdf0e10cSrcweir using ::oox::core::XmlFilterBase;
47cdf0e10cSrcweir using ::rtl::OUString;
48cdf0e10cSrcweir 
49cdf0e10cSrcweir // ============================================================================
50cdf0e10cSrcweir 
51cdf0e10cSrcweir namespace {
52cdf0e10cSrcweir 
53cdf0e10cSrcweir /** Returns the textual representation of a numeric VML shape identifier. */
lclGetShapeId(sal_Int32 nShapeId)54cdf0e10cSrcweir OUString lclGetShapeId( sal_Int32 nShapeId )
55cdf0e10cSrcweir {
56cdf0e10cSrcweir     // identifier consists of a literal NUL character, a lowercase 's', and the id
57cdf0e10cSrcweir     return CREATE_OUSTRING( "\0s" ) + OUString::valueOf( nShapeId );
58cdf0e10cSrcweir }
59cdf0e10cSrcweir 
60cdf0e10cSrcweir /** Returns the numeric VML shape identifier from its textual representation. */
lclGetShapeId(const OUString & rShapeId)61cdf0e10cSrcweir sal_Int32 lclGetShapeId( const OUString& rShapeId )
62cdf0e10cSrcweir {
63cdf0e10cSrcweir     // identifier consists of a literal NUL character, a lowercase 's', and the id
64cdf0e10cSrcweir     return ((rShapeId.getLength() >= 3) && (rShapeId[ 0 ] == '\0') && (rShapeId[ 1 ] == 's')) ? rShapeId.copy( 2 ).toInt32() : -1;
65cdf0e10cSrcweir }
66cdf0e10cSrcweir 
67cdf0e10cSrcweir } // namespace
68cdf0e10cSrcweir 
69cdf0e10cSrcweir // ============================================================================
70cdf0e10cSrcweir 
OleObjectInfo(bool bDmlShape)71cdf0e10cSrcweir OleObjectInfo::OleObjectInfo( bool bDmlShape ) :
72cdf0e10cSrcweir     mbAutoLoad( false ),
73cdf0e10cSrcweir     mbDmlShape( bDmlShape )
74cdf0e10cSrcweir {
75cdf0e10cSrcweir }
76cdf0e10cSrcweir 
setShapeId(sal_Int32 nShapeId)77cdf0e10cSrcweir void OleObjectInfo::setShapeId( sal_Int32 nShapeId )
78cdf0e10cSrcweir {
79cdf0e10cSrcweir     maShapeId = lclGetShapeId( nShapeId );
80cdf0e10cSrcweir }
81cdf0e10cSrcweir 
82cdf0e10cSrcweir // ============================================================================
83cdf0e10cSrcweir 
ControlInfo()84cdf0e10cSrcweir ControlInfo::ControlInfo()
85cdf0e10cSrcweir {
86cdf0e10cSrcweir }
87cdf0e10cSrcweir 
setShapeId(sal_Int32 nShapeId)88cdf0e10cSrcweir void ControlInfo::setShapeId( sal_Int32 nShapeId )
89cdf0e10cSrcweir {
90cdf0e10cSrcweir     maShapeId = lclGetShapeId( nShapeId );
91cdf0e10cSrcweir }
92cdf0e10cSrcweir 
93cdf0e10cSrcweir // ============================================================================
94cdf0e10cSrcweir 
Drawing(XmlFilterBase & rFilter,const Reference<XDrawPage> & rxDrawPage,DrawingType eType)95cdf0e10cSrcweir Drawing::Drawing( XmlFilterBase& rFilter, const Reference< XDrawPage >& rxDrawPage, DrawingType eType ) :
96cdf0e10cSrcweir     mrFilter( rFilter ),
97cdf0e10cSrcweir     mxDrawPage( rxDrawPage ),
98cdf0e10cSrcweir     mxShapes( new ShapeContainer( *this ) ),
99cdf0e10cSrcweir     meType( eType )
100cdf0e10cSrcweir {
101cdf0e10cSrcweir     OSL_ENSURE( mxDrawPage.is(), "Drawing::Drawing - missing UNO draw page" );
102cdf0e10cSrcweir }
103cdf0e10cSrcweir 
~Drawing()104cdf0e10cSrcweir Drawing::~Drawing()
105cdf0e10cSrcweir {
106cdf0e10cSrcweir }
107cdf0e10cSrcweir 
getControlForm() const108cdf0e10cSrcweir ::oox::ole::EmbeddedForm& Drawing::getControlForm() const
109cdf0e10cSrcweir {
110cdf0e10cSrcweir     if( !mxCtrlForm.get() )
111cdf0e10cSrcweir         mxCtrlForm.reset( new ::oox::ole::EmbeddedForm(
112cdf0e10cSrcweir             mrFilter.getModel(), mxDrawPage, mrFilter.getGraphicHelper() ) );
113cdf0e10cSrcweir     return *mxCtrlForm;
114cdf0e10cSrcweir }
115cdf0e10cSrcweir 
registerBlockId(sal_Int32 nBlockId)116cdf0e10cSrcweir void Drawing::registerBlockId( sal_Int32 nBlockId )
117cdf0e10cSrcweir {
118cdf0e10cSrcweir     OSL_ENSURE( nBlockId > 0, "Drawing::registerBlockId - invalid block index" );
119cdf0e10cSrcweir     if( nBlockId > 0 )
120cdf0e10cSrcweir     {
121cdf0e10cSrcweir         // lower_bound() returns iterator pointing to element equal to nBlockId, if existing
122cdf0e10cSrcweir         BlockIdVector::iterator aIt = ::std::lower_bound( maBlockIds.begin(), maBlockIds.end(), nBlockId );
123cdf0e10cSrcweir         if( (aIt == maBlockIds.end()) || (nBlockId != *aIt) )
124cdf0e10cSrcweir             maBlockIds.insert( aIt, nBlockId );
125cdf0e10cSrcweir     }
126cdf0e10cSrcweir }
127cdf0e10cSrcweir 
registerOleObject(const OleObjectInfo & rOleObject)128cdf0e10cSrcweir void Drawing::registerOleObject( const OleObjectInfo& rOleObject )
129cdf0e10cSrcweir {
130cdf0e10cSrcweir     OSL_ENSURE( rOleObject.maShapeId.getLength() > 0, "Drawing::registerOleObject - missing OLE object shape id" );
131cdf0e10cSrcweir     OSL_ENSURE( maOleObjects.count( rOleObject.maShapeId ) == 0, "Drawing::registerOleObject - OLE object already registered" );
132cdf0e10cSrcweir     maOleObjects.insert( OleObjectInfoMap::value_type( rOleObject.maShapeId, rOleObject ) );
133cdf0e10cSrcweir }
134cdf0e10cSrcweir 
registerControl(const ControlInfo & rControl)135cdf0e10cSrcweir void Drawing::registerControl( const ControlInfo& rControl )
136cdf0e10cSrcweir {
137cdf0e10cSrcweir     OSL_ENSURE( rControl.maShapeId.getLength() > 0, "Drawing::registerControl - missing form control shape id" );
138cdf0e10cSrcweir     OSL_ENSURE( rControl.maName.getLength() > 0, "Drawing::registerControl - missing form control name" );
139cdf0e10cSrcweir     OSL_ENSURE( maControls.count( rControl.maShapeId ) == 0, "Drawing::registerControl - form control already registered" );
140cdf0e10cSrcweir     maControls.insert( ControlInfoMap::value_type( rControl.maShapeId, rControl ) );
141cdf0e10cSrcweir }
142cdf0e10cSrcweir 
finalizeFragmentImport()143cdf0e10cSrcweir void Drawing::finalizeFragmentImport()
144cdf0e10cSrcweir {
145cdf0e10cSrcweir     mxShapes->finalizeFragmentImport();
146cdf0e10cSrcweir }
147cdf0e10cSrcweir 
convertAndInsert() const148cdf0e10cSrcweir void Drawing::convertAndInsert() const
149cdf0e10cSrcweir {
150cdf0e10cSrcweir     Reference< XShapes > xShapes( mxDrawPage, UNO_QUERY );
151cdf0e10cSrcweir     mxShapes->convertAndInsert( xShapes );
152cdf0e10cSrcweir }
153cdf0e10cSrcweir 
getLocalShapeIndex(const OUString & rShapeId) const154cdf0e10cSrcweir sal_Int32 Drawing::getLocalShapeIndex( const OUString& rShapeId ) const
155cdf0e10cSrcweir {
156cdf0e10cSrcweir     sal_Int32 nShapeId = lclGetShapeId( rShapeId );
157cdf0e10cSrcweir     if( nShapeId <= 0 ) return -1;
158cdf0e10cSrcweir 
159cdf0e10cSrcweir     /*  Shapes in a drawing are counted per registered shape identifier blocks
160cdf0e10cSrcweir         as stored in the o:idmap element. The contents of this element have
161cdf0e10cSrcweir         been stored in our member maBlockIds. Each block represents 1024 shape
162cdf0e10cSrcweir         identifiers, starting with identifier 1 for the block #0. This means,
163cdf0e10cSrcweir         block #0 represents the identifiers 1-1024, block #1 represents the
164cdf0e10cSrcweir         identifiers 1025-2048, and so on. The local shape index has to be
165cdf0e10cSrcweir         calculated according to all blocks registered for this drawing.
166cdf0e10cSrcweir 
167cdf0e10cSrcweir         Example:
168cdf0e10cSrcweir             Registered for this drawing are blocks #1 and #3 (shape identifiers
169cdf0e10cSrcweir             1025-2048 and 3073-4096).
170cdf0e10cSrcweir             Shape identifier 1025 -> local shape index 1.
171cdf0e10cSrcweir             Shape identifier 1026 -> local shape index 2.
172cdf0e10cSrcweir             ...
173cdf0e10cSrcweir             Shape identifier 2048 -> local shape index 1024.
174cdf0e10cSrcweir             Shape identifier 3073 -> local shape index 1025.
175cdf0e10cSrcweir             ...
176cdf0e10cSrcweir             Shape identifier 4096 -> local shape index 2048.
177cdf0e10cSrcweir      */
178cdf0e10cSrcweir 
179cdf0e10cSrcweir     // get block id from shape id and find its index in the list of used blocks
180cdf0e10cSrcweir     sal_Int32 nBlockId = (nShapeId - 1) / 1024;
181cdf0e10cSrcweir     BlockIdVector::iterator aIt = ::std::lower_bound( maBlockIds.begin(), maBlockIds.end(), nBlockId );
182cdf0e10cSrcweir     sal_Int32 nIndex = static_cast< sal_Int32 >( aIt - maBlockIds.begin() );
183cdf0e10cSrcweir 
184cdf0e10cSrcweir     // block id not found in set -> register it now (value of nIndex remains valid)
185cdf0e10cSrcweir     if( (aIt == maBlockIds.end()) || (*aIt != nBlockId) )
186cdf0e10cSrcweir         maBlockIds.insert( aIt, nBlockId );
187cdf0e10cSrcweir 
188cdf0e10cSrcweir     // get one-based offset of shape id in its block
189cdf0e10cSrcweir     sal_Int32 nBlockOffset = (nShapeId - 1) % 1024 + 1;
190cdf0e10cSrcweir 
191cdf0e10cSrcweir     // calculate the local shape index
192cdf0e10cSrcweir     return 1024 * nIndex + nBlockOffset;
193cdf0e10cSrcweir }
194cdf0e10cSrcweir 
getOleObjectInfo(const OUString & rShapeId) const195cdf0e10cSrcweir const OleObjectInfo* Drawing::getOleObjectInfo( const OUString& rShapeId ) const
196cdf0e10cSrcweir {
197cdf0e10cSrcweir     return ContainerHelper::getMapElement( maOleObjects, rShapeId );
198cdf0e10cSrcweir }
199cdf0e10cSrcweir 
getControlInfo(const OUString & rShapeId) const200cdf0e10cSrcweir const ControlInfo* Drawing::getControlInfo( const OUString& rShapeId ) const
201cdf0e10cSrcweir {
202cdf0e10cSrcweir     return ContainerHelper::getMapElement( maControls, rShapeId );
203cdf0e10cSrcweir }
204cdf0e10cSrcweir 
createAndInsertXShape(const OUString & rService,const Reference<XShapes> & rxShapes,const Rectangle & rShapeRect) const205cdf0e10cSrcweir Reference< XShape > Drawing::createAndInsertXShape( const OUString& rService,
206cdf0e10cSrcweir         const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
207cdf0e10cSrcweir {
208cdf0e10cSrcweir     OSL_ENSURE( rService.getLength() > 0, "Drawing::createAndInsertXShape - missing UNO shape service name" );
209cdf0e10cSrcweir     OSL_ENSURE( rxShapes.is(), "Drawing::createAndInsertXShape - missing XShapes container" );
210cdf0e10cSrcweir     Reference< XShape > xShape;
211cdf0e10cSrcweir     if( (rService.getLength() > 0) && rxShapes.is() ) try
212cdf0e10cSrcweir     {
213cdf0e10cSrcweir         Reference< XMultiServiceFactory > xModelFactory( mrFilter.getModelFactory(), UNO_SET_THROW );
214cdf0e10cSrcweir         xShape.set( xModelFactory->createInstance( rService ), UNO_QUERY_THROW );
215cdf0e10cSrcweir         // insert shape into passed shape collection (maybe drawpage or group shape)
216cdf0e10cSrcweir         rxShapes->add( xShape );
217cdf0e10cSrcweir         xShape->setPosition( Point( rShapeRect.X, rShapeRect.Y ) );
218cdf0e10cSrcweir         xShape->setSize( Size( rShapeRect.Width, rShapeRect.Height ) );
219cdf0e10cSrcweir     }
220cdf0e10cSrcweir     catch( Exception& )
221cdf0e10cSrcweir     {
222cdf0e10cSrcweir     }
223cdf0e10cSrcweir     OSL_ENSURE( xShape.is(), "Drawing::createAndInsertXShape - cannot instanciate shape object" );
224cdf0e10cSrcweir     return xShape;
225cdf0e10cSrcweir }
226cdf0e10cSrcweir 
createAndInsertXControlShape(const::oox::ole::EmbeddedControl & rControl,const Reference<XShapes> & rxShapes,const Rectangle & rShapeRect,sal_Int32 & rnCtrlIndex) const227cdf0e10cSrcweir Reference< XShape > Drawing::createAndInsertXControlShape( const ::oox::ole::EmbeddedControl& rControl,
228cdf0e10cSrcweir         const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect, sal_Int32& rnCtrlIndex ) const
229cdf0e10cSrcweir {
230cdf0e10cSrcweir     Reference< XShape > xShape;
231cdf0e10cSrcweir     try
232cdf0e10cSrcweir     {
233cdf0e10cSrcweir         // create control model and insert it into the form of the draw page
234cdf0e10cSrcweir         Reference< XControlModel > xCtrlModel( getControlForm().convertAndInsert( rControl, rnCtrlIndex ), UNO_SET_THROW );
235cdf0e10cSrcweir 
236cdf0e10cSrcweir         // create the control shape
237cdf0e10cSrcweir         xShape = createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.ControlShape" ), rxShapes, rShapeRect );
238cdf0e10cSrcweir 
239cdf0e10cSrcweir         // set the control model at the shape
240cdf0e10cSrcweir         Reference< XControlShape >( xShape, UNO_QUERY_THROW )->setControl( xCtrlModel );
241cdf0e10cSrcweir     }
242cdf0e10cSrcweir     catch( Exception& )
243cdf0e10cSrcweir     {
244cdf0e10cSrcweir     }
245cdf0e10cSrcweir     return xShape;
246cdf0e10cSrcweir }
247cdf0e10cSrcweir 
isShapeSupported(const ShapeBase &) const248cdf0e10cSrcweir bool Drawing::isShapeSupported( const ShapeBase& /*rShape*/ ) const
249cdf0e10cSrcweir {
250cdf0e10cSrcweir     return true;
251cdf0e10cSrcweir }
252cdf0e10cSrcweir 
getShapeBaseName(const ShapeBase &) const253cdf0e10cSrcweir OUString Drawing::getShapeBaseName( const ShapeBase& /*rShape*/ ) const
254cdf0e10cSrcweir {
255cdf0e10cSrcweir     return OUString();
256cdf0e10cSrcweir }
257cdf0e10cSrcweir 
convertClientAnchor(Rectangle &,const OUString &) const258cdf0e10cSrcweir bool Drawing::convertClientAnchor( Rectangle& /*orShapeRect*/, const OUString& /*rShapeAnchor*/ ) const
259cdf0e10cSrcweir {
260cdf0e10cSrcweir     return false;
261cdf0e10cSrcweir }
262cdf0e10cSrcweir 
createAndInsertClientXShape(const ShapeBase &,const Reference<XShapes> &,const Rectangle &) const263cdf0e10cSrcweir Reference< XShape > Drawing::createAndInsertClientXShape( const ShapeBase& /*rShape*/,
264cdf0e10cSrcweir         const Reference< XShapes >& /*rxShapes*/, const Rectangle& /*rShapeRect*/ ) const
265cdf0e10cSrcweir {
266cdf0e10cSrcweir     return Reference< XShape >();
267cdf0e10cSrcweir }
268cdf0e10cSrcweir 
notifyXShapeInserted(const Reference<XShape> &,const Rectangle &,const ShapeBase &,bool)269cdf0e10cSrcweir void Drawing::notifyXShapeInserted( const Reference< XShape >& /*rxShape*/,
270cdf0e10cSrcweir         const Rectangle& /*rShapeRect*/, const ShapeBase& /*rShape*/, bool /*bGroupChild*/ )
271cdf0e10cSrcweir {
272cdf0e10cSrcweir }
273cdf0e10cSrcweir 
274cdf0e10cSrcweir // ============================================================================
275cdf0e10cSrcweir 
276cdf0e10cSrcweir } // namespace vml
277cdf0e10cSrcweir } // namespave oox
278