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