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