LibreOffice Module oox (master)  1
chartdrawingfragment.cxx
Go to the documentation of this file.
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 
21 
22 #include <osl/diagnose.h>
23 
25 #include <com/sun/star/awt/Rectangle.hpp>
32 #include <oox/token/namespaces.hxx>
33 #include <oox/token/tokens.hxx>
34 
35 namespace oox::drawingml::chart {
36 
37 using namespace ::com::sun::star;
38 using namespace ::com::sun::star::drawing;
39 using namespace ::com::sun::star::uno;
40 using namespace ::oox::core;
41 
42 ShapeAnchor::ShapeAnchor( bool bRelSize ) :
43  mbRelSize( bRelSize )
44 {
45 }
46 
47 void ShapeAnchor::importExt( const AttributeList& rAttribs )
48 {
49  OSL_ENSURE( !mbRelSize, "ShapeAnchor::importExt - unexpected 'cdr:ext' element" );
50  maSize.Width = rAttribs.getHyper( XML_cx, 0 );
51  maSize.Height = rAttribs.getHyper( XML_cy, 0 );
52 }
53 
54 void ShapeAnchor::setPos( sal_Int32 nElement, sal_Int32 nParentContext, const OUString& rValue )
55 {
56  AnchorPosModel* pAnchorPos = nullptr;
57  switch( nParentContext )
58  {
59  case CDR_TOKEN( from ):
60  pAnchorPos = &maFrom;
61  break;
62  case CDR_TOKEN( to ):
63  OSL_ENSURE( mbRelSize, "ShapeAnchor::setPos - unexpected 'cdr:to' element" );
64  pAnchorPos = &maTo;
65  break;
66  default:
67  OSL_FAIL( "ShapeAnchor::setPos - unexpected parent element" );
68  }
69  if( pAnchorPos ) switch( nElement )
70  {
71  case CDR_TOKEN( x ): pAnchorPos->mfX = rValue.toDouble(); break;
72  case CDR_TOKEN( y ): pAnchorPos->mfY = rValue.toDouble(); break;
73  default: OSL_FAIL( "ShapeAnchor::setPos - unexpected element" );
74  }
75 }
76 
78 {
79  EmuRectangle aAnchorRect( -1, -1, -1, -1 );
80 
81  OSL_ENSURE( maFrom.isValid(), "ShapeAnchor::calcAnchorRectEmu - invalid from position" );
82  OSL_ENSURE( mbRelSize ? maTo.isValid() : maSize.isValid(), "ShapeAnchor::calcAnchorRectEmu - invalid to/size" );
83  if( maFrom.isValid() && (mbRelSize ? maTo.isValid() : maSize.isValid()) )
84  {
85  // calculate shape position
86  aAnchorRect.X = static_cast< sal_Int64 >( maFrom.mfX * rChartRect.Width + 0.5 );
87  aAnchorRect.Y = static_cast< sal_Int64 >( maFrom.mfY * rChartRect.Height + 0.5 );
88 
89  // calculate shape size
90  if( mbRelSize )
91  {
92  aAnchorRect.Width = static_cast< sal_Int64 >( maTo.mfX * rChartRect.Width + 0.5 ) - aAnchorRect.X;
93  if( aAnchorRect.Width < 0 )
94  {
95  aAnchorRect.X += aAnchorRect.Width;
96  aAnchorRect.Width *= -1;
97  }
98  aAnchorRect.Height = static_cast< sal_Int64 >( maTo.mfY * rChartRect.Height + 0.5 ) - aAnchorRect.Y;
99  if( aAnchorRect.Height < 0 )
100  {
101  aAnchorRect.Y += aAnchorRect.Height;
102  aAnchorRect.Height *= -1;
103  }
104  }
105  else
106  {
107  aAnchorRect.setSize( maSize );
108  }
109  }
110 
111  return aAnchorRect;
112 }
113 
115  const OUString& rFragmentPath, const Reference< XShapes >& rxDrawPage,
116  const awt::Size& rChartSize, const awt::Point& rShapesOffset, bool bOleSupport ) :
117  FragmentHandler2( rFilter, rFragmentPath ),
118  mxDrawPage( rxDrawPage ),
119  mbOleSupport( bOleSupport )
120 {
121  maChartRectEmu.X = convertHmmToEmu( rShapesOffset.X );
122  maChartRectEmu.Y = convertHmmToEmu( rShapesOffset.Y );
123  maChartRectEmu.Width = convertHmmToEmu( rChartSize.Width );
124  maChartRectEmu.Height = convertHmmToEmu( rChartSize.Height );
125 }
126 
128 {
129 }
130 
132 {
133  switch( getCurrentElement() )
134  {
135  case XML_ROOT_CONTEXT:
136  if( nElement == C_TOKEN( userShapes ) ) return this;
137  break;
138 
139  case C_TOKEN( userShapes ):
140  switch( nElement )
141  {
142  case CDR_TOKEN( absSizeAnchor ):
143  mxAnchor = std::make_shared<ShapeAnchor>( false );
144  return this;
145  case CDR_TOKEN( relSizeAnchor ):
146  mxAnchor = std::make_shared<ShapeAnchor>( true );
147  return this;
148  }
149  break;
150 
151  case CDR_TOKEN( absSizeAnchor ):
152  case CDR_TOKEN( relSizeAnchor ):
153  switch( nElement )
154  {
155  case CDR_TOKEN( sp ):
156  mxShape = std::make_shared<Shape>( "com.sun.star.drawing.CustomShape" );
157  return new ShapeContext( *this, ShapePtr(), mxShape );
158  case CDR_TOKEN( cxnSp ):
159  mxShape = std::make_shared<Shape>( "com.sun.star.drawing.ConnectorShape" );
160  return new ConnectorShapeContext( *this, ShapePtr(), mxShape );
161  case CDR_TOKEN( pic ):
162  mxShape = std::make_shared<Shape>( "com.sun.star.drawing.GraphicObjectShape" );
163  return new GraphicShapeContext( *this, ShapePtr(), mxShape );
164  case CDR_TOKEN( graphicFrame ):
165  if( !mbOleSupport )
166  return nullptr;
167  mxShape = std::make_shared<Shape>( "com.sun.star.drawing.GraphicObjectShape" );
168  return new GraphicalObjectFrameContext( *this, ShapePtr(), mxShape, true );
169  case CDR_TOKEN( grpSp ):
170  mxShape = std::make_shared<Shape>( "com.sun.star.drawing.GroupShape" );
171  return new ShapeGroupContext( *this, ShapePtr(), mxShape );
172 
173  case CDR_TOKEN( from ):
174  case CDR_TOKEN( to ):
175  return this;
176 
177  case CDR_TOKEN( ext ):
178  if( mxAnchor ) mxAnchor->importExt( rAttribs );
179  return nullptr;
180  }
181  break;
182 
183  case CDR_TOKEN( from ):
184  case CDR_TOKEN( to ):
185  switch( nElement )
186  {
187  case CDR_TOKEN( x ):
188  case CDR_TOKEN( y ):
189  return this; // collect value in onEndElement()
190  }
191  break;
192  }
193  return nullptr;
194 }
195 
196 void ChartDrawingFragment::onCharacters( const OUString& rChars )
197 {
198  if( isCurrentElement( CDR_TOKEN( x ), CDR_TOKEN( y ) ) && mxAnchor )
199  mxAnchor->setPos( getCurrentElement(), getParentElement(), rChars );
200 }
201 
203 {
204  if( !isCurrentElement( CDR_TOKEN( absSizeAnchor ), CDR_TOKEN( relSizeAnchor ) ) )
205  return;
206 
207  if( mxDrawPage.is() && mxShape && mxAnchor )
208  {
209  EmuRectangle aShapeRectEmu = mxAnchor->calcAnchorRectEmu( maChartRectEmu );
210  if( (aShapeRectEmu.X >= 0) && (aShapeRectEmu.Y >= 0) && (aShapeRectEmu.Width >= 0) && (aShapeRectEmu.Height >= 0) )
211  {
212  const sal_Int32 aRotation = mxShape->getRotation();
213  if( (aRotation >= 45 * PER_DEGREE && aRotation < 135 * PER_DEGREE) || (aRotation >= 225 * PER_DEGREE && aRotation < 315 * PER_DEGREE) )
214  {
215  sal_Int64 nHalfWidth = aShapeRectEmu.Width / 2;
216  sal_Int64 nHalfHeight = aShapeRectEmu.Height / 2;
217  aShapeRectEmu.X = aShapeRectEmu.X + nHalfWidth - nHalfHeight;
218  aShapeRectEmu.Y = aShapeRectEmu.Y + nHalfHeight - nHalfWidth;
219  std::swap(aShapeRectEmu.Width, aShapeRectEmu.Height);
220  }
221  // TODO: DrawingML implementation expects 32-bit coordinates for EMU rectangles (change that to EmuRectangle)
222  awt::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 
228  // Set the position and size before calling addShape().
229  mxShape->setPosition(awt::Point(aShapeRectEmu32.X, aShapeRectEmu32.Y));
230  mxShape->setSize(awt::Size(aShapeRectEmu32.Width, aShapeRectEmu32.Height));
231 
232  basegfx::B2DHomMatrix aMatrix;
233  mxShape->addShape( getFilter(), getFilter().getCurrentTheme(), mxDrawPage, aMatrix, mxShape->getFillProperties() );
234  }
235  }
236  mxShape.reset();
237  mxAnchor.reset();
238 }
239 
240 } // namespace oox::drawingml::chart
241 
242 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool mbRelSize
Shape size, if anchor has absolute size.
const sal_Int32 PER_DEGREE
::oox::drawingml::ShapePtr mxShape
Drawing page of this sheet.
virtual void onEndElement() override
Will be called when the current element is about to be left.
bool isCurrentElement(sal_Int32 nElement) const
Returns true, if nElement contains the identifier of the currently processed element.
css::uno::Reference< css::drawing::XShapes > mxDrawPage
void importExt(const AttributeList &rAttribs)
Imports the absolute anchor size from the cdr:ext element.
bool mbOleSupport
Position and size of the chart object for embedded shapes (in EMUs).
uno::Reference< drawing::XDrawPage > mxDrawPage
EmuRectangle maChartRectEmu
Current anchor of top-level shape.
float x
sal_Int32 getParentElement(sal_Int32 nCountBack=1) const
Returns the identifier of the specified parent element.
AnchorSizeModel maSize
Bottom-right position relative to chart object.
virtual ::oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement, const AttributeList &rAttribs) override
Will be called to create a context handler for the passed element.
double mfY
X coordinate relative to chart object (0.0 to 1.0).
ChartDrawingFragment(::oox::core::XmlFilterBase &rFilter, const OUString &rFragmentPath, const css::uno::Reference< css::drawing::XShapes > &rxDrawPage, const css::awt::Size &rChartSize, const css::awt::Point &rShapesOffset, bool bOleSupport)
UBlockCode from
UBlockCode to
void setPos(sal_Int32 nElement, sal_Int32 nParentContext, const OUString &rValue)
Sets the relative anchor position from the cdr:from or cdr:to element.
float y
OptValue< sal_Int64 > getHyper(sal_Int32 nAttrToken) const
Returns the 64-bit signed integer value of the specified attribute (decimal).
#define SAL_MAX_INT32
sal_Int64 convertHmmToEmu(sal_Int32 nValue)
Converts the passed 32-bit integer value from 1/100 mm to EMUs.
sal_Int32 getCurrentElement() const
Returns the identifier of the currently processed element.
Provides access to attribute values of an element.
AnchorPosModel maTo
Top-left position relative to chart object.
virtual void onCharacters(const OUString &rChars) override
Will be called before a new child element starts, or if the current element is about to be left...
A structure for a rectangle with 64-bit integer components.
std::shared_ptr< ShapeAnchor > mxAnchor
Current top-level shape.
const sal_Int32 XML_ROOT_CONTEXT
std::shared_ptr< Shape > ShapePtr
void setSize(const EmuSize &rSize)
Relative shape position in a chart object.
EmuRectangle calcAnchorRectEmu(const EmuRectangle &rChartRect) const
Calculates the resulting shape anchor in EMUs.