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