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/drawingml/chart/chartdrawingfragment.hxx" 29 30 #include "oox/core/xmlfilterbase.hxx" 31 #include "oox/drawingml/connectorshapecontext.hxx" 32 #include "oox/drawingml/graphicshapecontext.hxx" 33 #include "oox/drawingml/shapecontext.hxx" 34 #include "oox/drawingml/shapegroupcontext.hxx" 35 36 namespace oox { 37 namespace drawingml { 38 namespace chart { 39 40 // ============================================================================ 41 42 using namespace ::com::sun::star::awt; 43 using namespace ::com::sun::star::drawing; 44 using namespace ::com::sun::star::uno; 45 using namespace ::oox::core; 46 47 using ::rtl::OUString; 48 49 // ============================================================================ 50 51 ShapeAnchor::ShapeAnchor( bool bRelSize ) : 52 mbRelSize( bRelSize ) 53 { 54 } 55 56 void ShapeAnchor::importExt( const AttributeList& rAttribs ) 57 { 58 OSL_ENSURE( !mbRelSize, "ShapeAnchor::importExt - unexpected 'cdr:ext' element" ); 59 maSize.Width = rAttribs.getHyper( XML_cx, 0 ); 60 maSize.Height = rAttribs.getHyper( XML_cy, 0 ); 61 } 62 63 void ShapeAnchor::setPos( sal_Int32 nElement, sal_Int32 nParentContext, const OUString& rValue ) 64 { 65 AnchorPosModel* pAnchorPos = 0; 66 switch( nParentContext ) 67 { 68 case CDR_TOKEN( from ): 69 pAnchorPos = &maFrom; 70 break; 71 case CDR_TOKEN( to ): 72 OSL_ENSURE( mbRelSize, "ShapeAnchor::setPos - unexpected 'cdr:to' element" ); 73 pAnchorPos = &maTo; 74 break; 75 default: 76 OSL_ENSURE( false, "ShapeAnchor::setPos - unexpected parent element" ); 77 } 78 if( pAnchorPos ) switch( nElement ) 79 { 80 case CDR_TOKEN( x ): pAnchorPos->mfX = rValue.toDouble(); break; 81 case CDR_TOKEN( y ): pAnchorPos->mfY = rValue.toDouble(); break; 82 default: OSL_ENSURE( false, "ShapeAnchor::setPos - unexpected element" ); 83 } 84 } 85 86 EmuRectangle ShapeAnchor::calcAnchorRectEmu( const EmuRectangle& rChartRect ) const 87 { 88 EmuRectangle aAnchorRect( -1, -1, -1, -1 ); 89 90 OSL_ENSURE( maFrom.isValid(), "ShapeAnchor::calcAnchorRectEmu - invalid from position" ); 91 OSL_ENSURE( mbRelSize ? maTo.isValid() : maSize.isValid(), "ShapeAnchor::calcAnchorRectEmu - invalid to/size" ); 92 if( maFrom.isValid() && (mbRelSize ? maTo.isValid() : maSize.isValid()) ) 93 { 94 // calculate shape position 95 aAnchorRect.X = static_cast< sal_Int64 >( maFrom.mfX * rChartRect.Width + 0.5 ); 96 aAnchorRect.Y = static_cast< sal_Int64 >( maFrom.mfY * rChartRect.Height + 0.5 ); 97 98 // calculate shape size 99 if( mbRelSize ) 100 { 101 aAnchorRect.Width = static_cast< sal_Int64 >( maTo.mfX * rChartRect.Width + 0.5 ) - aAnchorRect.X; 102 if( aAnchorRect.Width < 0 ) 103 { 104 aAnchorRect.X += aAnchorRect.Width; 105 aAnchorRect.Width *= -1; 106 } 107 aAnchorRect.Height = static_cast< sal_Int64 >( maTo.mfY * rChartRect.Height + 0.5 ) - aAnchorRect.Y; 108 if( aAnchorRect.Height < 0 ) 109 { 110 aAnchorRect.Y += aAnchorRect.Height; 111 aAnchorRect.Height *= -1; 112 } 113 } 114 else 115 { 116 aAnchorRect.setSize( maSize ); 117 } 118 } 119 120 return aAnchorRect; 121 } 122 // ============================================================================ 123 124 ChartDrawingFragment::ChartDrawingFragment( XmlFilterBase& rFilter, 125 const OUString& rFragmentPath, const Reference< XShapes >& rxDrawPage, 126 const Size& rChartSize, const Point& rShapesOffset, bool bOleSupport ) : 127 FragmentHandler2( rFilter, rFragmentPath ), 128 mxDrawPage( rxDrawPage ), 129 mbOleSupport( bOleSupport ) 130 { 131 maChartRectEmu.X = convertHmmToEmu( rShapesOffset.X ); 132 maChartRectEmu.Y = convertHmmToEmu( rShapesOffset.Y ); 133 maChartRectEmu.Width = convertHmmToEmu( rChartSize.Width ); 134 maChartRectEmu.Height = convertHmmToEmu( rChartSize.Height ); 135 } 136 137 ChartDrawingFragment::~ChartDrawingFragment() 138 { 139 } 140 141 ContextHandlerRef ChartDrawingFragment::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) 142 { 143 switch( getCurrentElement() ) 144 { 145 case XML_ROOT_CONTEXT: 146 if( nElement == C_TOKEN( userShapes ) ) return this; 147 break; 148 149 case C_TOKEN( userShapes ): 150 switch( nElement ) 151 { 152 case CDR_TOKEN( absSizeAnchor ): 153 mxAnchor.reset( new ShapeAnchor( false ) ); 154 return this; 155 case CDR_TOKEN( relSizeAnchor ): 156 mxAnchor.reset( new ShapeAnchor( true ) ); 157 return this; 158 } 159 break; 160 161 case CDR_TOKEN( absSizeAnchor ): 162 case CDR_TOKEN( relSizeAnchor ): 163 switch( nElement ) 164 { 165 case CDR_TOKEN( sp ): 166 mxShape.reset( new Shape( "com.sun.star.drawing.CustomShape" ) ); 167 return new ShapeContext( *this, ShapePtr(), mxShape ); 168 case CDR_TOKEN( cxnSp ): 169 mxShape.reset( new Shape( "com.sun.star.drawing.ConnectorShape" ) ); 170 return new ConnectorShapeContext( *this, ShapePtr(), mxShape ); 171 case CDR_TOKEN( pic ): 172 mxShape.reset( new Shape( "com.sun.star.drawing.GraphicObjectShape" ) ); 173 return new GraphicShapeContext( *this, ShapePtr(), mxShape ); 174 case CDR_TOKEN( graphicFrame ): 175 if( !mbOleSupport ) 176 return 0; 177 mxShape.reset( new Shape( "com.sun.star.drawing.GraphicObjectShape" ) ); 178 return new GraphicalObjectFrameContext( *this, ShapePtr(), mxShape, true ); 179 case CDR_TOKEN( grpSp ): 180 mxShape.reset( new Shape( "com.sun.star.drawing.GroupShape" ) ); 181 return new ShapeGroupContext( *this, ShapePtr(), mxShape ); 182 183 case CDR_TOKEN( from ): 184 case CDR_TOKEN( to ): 185 return this; 186 187 case CDR_TOKEN( ext ): 188 if( mxAnchor.get() ) mxAnchor->importExt( rAttribs ); 189 return 0; 190 } 191 break; 192 193 case CDR_TOKEN( from ): 194 case CDR_TOKEN( to ): 195 switch( nElement ) 196 { 197 case CDR_TOKEN( x ): 198 case CDR_TOKEN( y ): 199 return this; // collect value in onEndElement() 200 } 201 break; 202 } 203 return 0; 204 } 205 206 void ChartDrawingFragment::onCharacters( const OUString& rChars ) 207 { 208 if( isCurrentElement( CDR_TOKEN( x ), CDR_TOKEN( y ) ) && mxAnchor.get() ) 209 mxAnchor->setPos( getCurrentElement(), getParentElement(), rChars ); 210 } 211 212 void ChartDrawingFragment::onEndElement() 213 { 214 if( isCurrentElement( CDR_TOKEN( absSizeAnchor ), CDR_TOKEN( relSizeAnchor ) ) ) 215 { 216 if( mxDrawPage.is() && mxShape.get() && mxAnchor.get() ) 217 { 218 EmuRectangle aShapeRectEmu = mxAnchor->calcAnchorRectEmu( maChartRectEmu ); 219 if( (aShapeRectEmu.X >= 0) && (aShapeRectEmu.Y >= 0) && (aShapeRectEmu.Width >= 0) && (aShapeRectEmu.Height >= 0) ) 220 { 221 // TODO: DrawingML implementation expects 32-bit coordinates for EMU rectangles (change that to EmuRectangle) 222 Rectangle aShapeRectEmu32( 223 getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.X, 0, SAL_MAX_INT32 ), 224 getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.Y, 0, SAL_MAX_INT32 ), 225 getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.Width, 0, SAL_MAX_INT32 ), 226 getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.Height, 0, SAL_MAX_INT32 ) ); 227 mxShape->addShape( getFilter(), getFilter().getCurrentTheme(), mxDrawPage, &aShapeRectEmu32 ); 228 } 229 } 230 mxShape.reset(); 231 mxAnchor.reset(); 232 } 233 } 234 235 // ============================================================================ 236 237 } // namespace chart 238 } // namespace drawingml 239 } // namespace oox 240