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