Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "drawingml/chart/chartdrawingfragment.hxx"
21 :
22 : #include <osl/diagnose.h>
23 :
24 : #include "oox/core/xmlfilterbase.hxx"
25 : #include "oox/drawingml/connectorshapecontext.hxx"
26 : #include "oox/drawingml/graphicshapecontext.hxx"
27 : #include "oox/drawingml/shapecontext.hxx"
28 : #include "oox/drawingml/shapegroupcontext.hxx"
29 :
30 : namespace oox {
31 : namespace drawingml {
32 : namespace chart {
33 :
34 : using namespace ::com::sun::star;
35 : using namespace ::com::sun::star::drawing;
36 : using namespace ::com::sun::star::uno;
37 : using namespace ::oox::core;
38 :
39 1 : ShapeAnchor::ShapeAnchor( bool bRelSize ) :
40 1 : mbRelSize( bRelSize )
41 : {
42 1 : }
43 :
44 0 : void ShapeAnchor::importExt( const AttributeList& rAttribs )
45 : {
46 : OSL_ENSURE( !mbRelSize, "ShapeAnchor::importExt - unexpected 'cdr:ext' element" );
47 0 : maSize.Width = rAttribs.getHyper( XML_cx, 0 );
48 0 : maSize.Height = rAttribs.getHyper( XML_cy, 0 );
49 0 : }
50 :
51 4 : void ShapeAnchor::setPos( sal_Int32 nElement, sal_Int32 nParentContext, const OUString& rValue )
52 : {
53 4 : AnchorPosModel* pAnchorPos = 0;
54 4 : switch( nParentContext )
55 : {
56 : case CDR_TOKEN( from ):
57 2 : pAnchorPos = &maFrom;
58 2 : break;
59 : case CDR_TOKEN( to ):
60 : OSL_ENSURE( mbRelSize, "ShapeAnchor::setPos - unexpected 'cdr:to' element" );
61 2 : pAnchorPos = &maTo;
62 2 : break;
63 : default:
64 : OSL_FAIL( "ShapeAnchor::setPos - unexpected parent element" );
65 : }
66 4 : if( pAnchorPos ) switch( nElement )
67 : {
68 2 : case CDR_TOKEN( x ): pAnchorPos->mfX = rValue.toDouble(); break;
69 2 : case CDR_TOKEN( y ): pAnchorPos->mfY = rValue.toDouble(); break;
70 : default: OSL_FAIL( "ShapeAnchor::setPos - unexpected element" );
71 : }
72 4 : }
73 :
74 1 : EmuRectangle ShapeAnchor::calcAnchorRectEmu( const EmuRectangle& rChartRect ) const
75 : {
76 1 : EmuRectangle aAnchorRect( -1, -1, -1, -1 );
77 :
78 : OSL_ENSURE( maFrom.isValid(), "ShapeAnchor::calcAnchorRectEmu - invalid from position" );
79 : OSL_ENSURE( mbRelSize ? maTo.isValid() : maSize.isValid(), "ShapeAnchor::calcAnchorRectEmu - invalid to/size" );
80 1 : if( maFrom.isValid() && (mbRelSize ? maTo.isValid() : maSize.isValid()) )
81 : {
82 : // calculate shape position
83 1 : aAnchorRect.X = static_cast< sal_Int64 >( maFrom.mfX * rChartRect.Width + 0.5 );
84 1 : aAnchorRect.Y = static_cast< sal_Int64 >( maFrom.mfY * rChartRect.Height + 0.5 );
85 :
86 : // calculate shape size
87 1 : if( mbRelSize )
88 : {
89 1 : aAnchorRect.Width = static_cast< sal_Int64 >( maTo.mfX * rChartRect.Width + 0.5 ) - aAnchorRect.X;
90 1 : if( aAnchorRect.Width < 0 )
91 : {
92 1 : aAnchorRect.X += aAnchorRect.Width;
93 1 : aAnchorRect.Width *= -1;
94 : }
95 1 : aAnchorRect.Height = static_cast< sal_Int64 >( maTo.mfY * rChartRect.Height + 0.5 ) - aAnchorRect.Y;
96 1 : if( aAnchorRect.Height < 0 )
97 : {
98 1 : aAnchorRect.Y += aAnchorRect.Height;
99 1 : aAnchorRect.Height *= -1;
100 : }
101 : }
102 : else
103 : {
104 0 : aAnchorRect.setSize( maSize );
105 : }
106 : }
107 :
108 1 : return aAnchorRect;
109 : }
110 :
111 1 : ChartDrawingFragment::ChartDrawingFragment( XmlFilterBase& rFilter,
112 : const OUString& rFragmentPath, const Reference< XShapes >& rxDrawPage,
113 : const awt::Size& rChartSize, const awt::Point& rShapesOffset, bool bOleSupport ) :
114 : FragmentHandler2( rFilter, rFragmentPath ),
115 : mxDrawPage( rxDrawPage ),
116 1 : mbOleSupport( bOleSupport )
117 : {
118 1 : maChartRectEmu.X = convertHmmToEmu( rShapesOffset.X );
119 1 : maChartRectEmu.Y = convertHmmToEmu( rShapesOffset.Y );
120 1 : maChartRectEmu.Width = convertHmmToEmu( rChartSize.Width );
121 1 : maChartRectEmu.Height = convertHmmToEmu( rChartSize.Height );
122 1 : }
123 :
124 2 : ChartDrawingFragment::~ChartDrawingFragment()
125 : {
126 2 : }
127 :
128 9 : ContextHandlerRef ChartDrawingFragment::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
129 : {
130 9 : switch( getCurrentElement() )
131 : {
132 : case XML_ROOT_CONTEXT:
133 1 : if( nElement == C_TOKEN( userShapes ) ) return this;
134 0 : break;
135 :
136 : case C_TOKEN( userShapes ):
137 1 : switch( nElement )
138 : {
139 : case CDR_TOKEN( absSizeAnchor ):
140 0 : mxAnchor.reset( new ShapeAnchor( false ) );
141 0 : return this;
142 : case CDR_TOKEN( relSizeAnchor ):
143 1 : mxAnchor.reset( new ShapeAnchor( true ) );
144 1 : return this;
145 : }
146 0 : break;
147 :
148 : case CDR_TOKEN( absSizeAnchor ):
149 : case CDR_TOKEN( relSizeAnchor ):
150 3 : switch( nElement )
151 : {
152 : case CDR_TOKEN( sp ):
153 1 : mxShape.reset( new Shape( "com.sun.star.drawing.CustomShape" ) );
154 1 : return new ShapeContext( *this, ShapePtr(), mxShape );
155 : case CDR_TOKEN( cxnSp ):
156 0 : mxShape.reset( new Shape( "com.sun.star.drawing.ConnectorShape" ) );
157 0 : return new ConnectorShapeContext( *this, ShapePtr(), mxShape );
158 : case CDR_TOKEN( pic ):
159 0 : mxShape.reset( new Shape( "com.sun.star.drawing.GraphicObjectShape" ) );
160 0 : return new GraphicShapeContext( *this, ShapePtr(), mxShape );
161 : case CDR_TOKEN( graphicFrame ):
162 0 : if( !mbOleSupport )
163 0 : return 0;
164 0 : mxShape.reset( new Shape( "com.sun.star.drawing.GraphicObjectShape" ) );
165 0 : return new GraphicalObjectFrameContext( *this, ShapePtr(), mxShape, true );
166 : case CDR_TOKEN( grpSp ):
167 0 : mxShape.reset( new Shape( "com.sun.star.drawing.GroupShape" ) );
168 0 : return new ShapeGroupContext( *this, ShapePtr(), mxShape );
169 :
170 : case CDR_TOKEN( from ):
171 : case CDR_TOKEN( to ):
172 2 : return this;
173 :
174 : case CDR_TOKEN( ext ):
175 0 : if( mxAnchor.get() ) mxAnchor->importExt( rAttribs );
176 0 : return 0;
177 : }
178 0 : break;
179 :
180 : case CDR_TOKEN( from ):
181 : case CDR_TOKEN( to ):
182 4 : switch( nElement )
183 : {
184 : case CDR_TOKEN( x ):
185 : case CDR_TOKEN( y ):
186 4 : return this; // collect value in onEndElement()
187 : }
188 0 : break;
189 : }
190 0 : return 0;
191 : }
192 :
193 4 : void ChartDrawingFragment::onCharacters( const OUString& rChars )
194 : {
195 4 : if( isCurrentElement( CDR_TOKEN( x ), CDR_TOKEN( y ) ) && mxAnchor.get() )
196 4 : mxAnchor->setPos( getCurrentElement(), getParentElement(), rChars );
197 4 : }
198 :
199 8 : void ChartDrawingFragment::onEndElement()
200 : {
201 8 : if( isCurrentElement( CDR_TOKEN( absSizeAnchor ), CDR_TOKEN( relSizeAnchor ) ) )
202 : {
203 1 : if( mxDrawPage.is() && mxShape.get() && mxAnchor.get() )
204 : {
205 1 : EmuRectangle aShapeRectEmu = mxAnchor->calcAnchorRectEmu( maChartRectEmu );
206 1 : if( (aShapeRectEmu.X >= 0) && (aShapeRectEmu.Y >= 0) && (aShapeRectEmu.Width >= 0) && (aShapeRectEmu.Height >= 0) )
207 : {
208 : // TODO: DrawingML implementation expects 32-bit coordinates for EMU rectangles (change that to EmuRectangle)
209 : awt::Rectangle aShapeRectEmu32(
210 0 : getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.X, 0, SAL_MAX_INT32 ),
211 0 : getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.Y, 0, SAL_MAX_INT32 ),
212 0 : getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.Width, 0, SAL_MAX_INT32 ),
213 0 : getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.Height, 0, SAL_MAX_INT32 ) );
214 0 : basegfx::B2DHomMatrix aMatrix;
215 0 : mxShape->addShape( getFilter(), getFilter().getCurrentTheme(), mxDrawPage, aMatrix, mxShape->getFillProperties(), &aShapeRectEmu32 );
216 : }
217 : }
218 1 : mxShape.reset();
219 1 : mxAnchor.reset();
220 : }
221 8 : }
222 :
223 : } // namespace chart
224 : } // namespace drawingml
225 246 : } // namespace oox
226 :
227 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|