1ca5ec200SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3ca5ec200SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4ca5ec200SAndrew Rist * or more contributor license agreements. See the NOTICE file 5ca5ec200SAndrew Rist * distributed with this work for additional information 6ca5ec200SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7ca5ec200SAndrew Rist * to you under the Apache License, Version 2.0 (the 8ca5ec200SAndrew Rist * "License"); you may not use this file except in compliance 9ca5ec200SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11ca5ec200SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13ca5ec200SAndrew Rist * Unless required by applicable law or agreed to in writing, 14ca5ec200SAndrew Rist * software distributed under the License is distributed on an 15ca5ec200SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16ca5ec200SAndrew Rist * KIND, either express or implied. See the License for the 17ca5ec200SAndrew Rist * specific language governing permissions and limitations 18ca5ec200SAndrew Rist * under the License. 19cdf0e10cSrcweir * 20ca5ec200SAndrew Rist *************************************************************/ 21ca5ec200SAndrew Rist 22ca5ec200SAndrew 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. */ 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. */ 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 71cdf0e10cSrcweir OleObjectInfo::OleObjectInfo( bool bDmlShape ) : 72cdf0e10cSrcweir mbAutoLoad( false ), 73cdf0e10cSrcweir mbDmlShape( bDmlShape ) 74cdf0e10cSrcweir { 75cdf0e10cSrcweir } 76cdf0e10cSrcweir 77cdf0e10cSrcweir void OleObjectInfo::setShapeId( sal_Int32 nShapeId ) 78cdf0e10cSrcweir { 79cdf0e10cSrcweir maShapeId = lclGetShapeId( nShapeId ); 80cdf0e10cSrcweir } 81cdf0e10cSrcweir 82cdf0e10cSrcweir // ============================================================================ 83cdf0e10cSrcweir 84cdf0e10cSrcweir ControlInfo::ControlInfo() 85cdf0e10cSrcweir { 86cdf0e10cSrcweir } 87cdf0e10cSrcweir 88cdf0e10cSrcweir void ControlInfo::setShapeId( sal_Int32 nShapeId ) 89cdf0e10cSrcweir { 90cdf0e10cSrcweir maShapeId = lclGetShapeId( nShapeId ); 91cdf0e10cSrcweir } 92cdf0e10cSrcweir 93cdf0e10cSrcweir // ============================================================================ 94cdf0e10cSrcweir 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 104cdf0e10cSrcweir Drawing::~Drawing() 105cdf0e10cSrcweir { 106cdf0e10cSrcweir } 107cdf0e10cSrcweir 108cdf0e10cSrcweir ::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 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 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 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 143cdf0e10cSrcweir void Drawing::finalizeFragmentImport() 144cdf0e10cSrcweir { 145cdf0e10cSrcweir mxShapes->finalizeFragmentImport(); 146cdf0e10cSrcweir } 147cdf0e10cSrcweir 148cdf0e10cSrcweir void Drawing::convertAndInsert() const 149cdf0e10cSrcweir { 150cdf0e10cSrcweir Reference< XShapes > xShapes( mxDrawPage, UNO_QUERY ); 151cdf0e10cSrcweir mxShapes->convertAndInsert( xShapes ); 152cdf0e10cSrcweir } 153cdf0e10cSrcweir 154cdf0e10cSrcweir 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 195cdf0e10cSrcweir const OleObjectInfo* Drawing::getOleObjectInfo( const OUString& rShapeId ) const 196cdf0e10cSrcweir { 197cdf0e10cSrcweir return ContainerHelper::getMapElement( maOleObjects, rShapeId ); 198cdf0e10cSrcweir } 199cdf0e10cSrcweir 200cdf0e10cSrcweir const ControlInfo* Drawing::getControlInfo( const OUString& rShapeId ) const 201cdf0e10cSrcweir { 202cdf0e10cSrcweir return ContainerHelper::getMapElement( maControls, rShapeId ); 203cdf0e10cSrcweir } 204cdf0e10cSrcweir 205cdf0e10cSrcweir 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 } 223*5e7dbebbSJohn Bampton OSL_ENSURE( xShape.is(), "Drawing::createAndInsertXShape - cannot instantiate shape object" ); 224cdf0e10cSrcweir return xShape; 225cdf0e10cSrcweir } 226cdf0e10cSrcweir 227cdf0e10cSrcweir 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 248cdf0e10cSrcweir bool Drawing::isShapeSupported( const ShapeBase& /*rShape*/ ) const 249cdf0e10cSrcweir { 250cdf0e10cSrcweir return true; 251cdf0e10cSrcweir } 252cdf0e10cSrcweir 253cdf0e10cSrcweir OUString Drawing::getShapeBaseName( const ShapeBase& /*rShape*/ ) const 254cdf0e10cSrcweir { 255cdf0e10cSrcweir return OUString(); 256cdf0e10cSrcweir } 257cdf0e10cSrcweir 258cdf0e10cSrcweir bool Drawing::convertClientAnchor( Rectangle& /*orShapeRect*/, const OUString& /*rShapeAnchor*/ ) const 259cdf0e10cSrcweir { 260cdf0e10cSrcweir return false; 261cdf0e10cSrcweir } 262cdf0e10cSrcweir 263cdf0e10cSrcweir Reference< XShape > Drawing::createAndInsertClientXShape( const ShapeBase& /*rShape*/, 264cdf0e10cSrcweir const Reference< XShapes >& /*rxShapes*/, const Rectangle& /*rShapeRect*/ ) const 265cdf0e10cSrcweir { 266cdf0e10cSrcweir return Reference< XShape >(); 267cdf0e10cSrcweir } 268cdf0e10cSrcweir 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