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 :
10 : #include "macros.hxx"
11 : #include "PropertyMapper.hxx"
12 : #include "CommonConverters.hxx"
13 :
14 : #include "AbstractShapeFactory.hxx"
15 : #include <com/sun/star/beans/XPropertySet.hpp>
16 : #include <com/sun/star/drawing/CircleKind.hpp>
17 : #include <com/sun/star/drawing/DoubleSequence.hpp>
18 : #include <com/sun/star/drawing/FlagSequence.hpp>
19 : #include <com/sun/star/drawing/FillStyle.hpp>
20 : #include <com/sun/star/drawing/LineStyle.hpp>
21 : #include <com/sun/star/drawing/NormalsKind.hpp>
22 : #include <com/sun/star/drawing/PointSequence.hpp>
23 : #include <com/sun/star/drawing/PolygonKind.hpp>
24 : #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
25 : #include <com/sun/star/drawing/ProjectionMode.hpp>
26 : #include <com/sun/star/drawing/ShadeMode.hpp>
27 : #include <com/sun/star/drawing/TextFitToSizeType.hpp>
28 : #include <com/sun/star/drawing/TextureProjectionMode.hpp>
29 : #include <com/sun/star/text/XText.hpp>
30 : #include <com/sun/star/uno/Any.hxx>
31 :
32 : #include <editeng/unoprnms.hxx>
33 : #include <rtl/math.hxx>
34 : #include <svx/svdocirc.hxx>
35 : #include <svx/svdopath.hxx>
36 : #include <vcl/svapp.hxx>
37 :
38 : #include <basegfx/point/b2dpoint.hxx>
39 : #include <basegfx/matrix/b2dhommatrix.hxx>
40 : #include <basegfx/matrix/b3dhommatrix.hxx>
41 :
42 : #include <osl/module.hxx>
43 :
44 : #include "OpenglShapeFactory.hxx"
45 : #include "ShapeFactory.hxx"
46 :
47 : using namespace com::sun::star;
48 : using ::com::sun::star::uno::Reference;
49 :
50 : namespace chart {
51 :
52 : namespace {
53 :
54 : typedef opengl::OpenglShapeFactory* (*__getOpenglShapeFactory)(void);
55 :
56 : #ifndef DISABLE_DYNLOADING
57 :
58 0 : static void SAL_CALL thisModule() {}
59 :
60 0 : osl::Module* getOpenGLModule()
61 : {
62 0 : static osl::Module aModule;
63 0 : if (aModule.is())
64 : // Already loaded.
65 0 : return &aModule;
66 :
67 0 : OUString aLibName(SVLIBRARY("chartopengl"));
68 0 : bool bLoaded = aModule.loadRelative(&thisModule, aLibName);
69 0 : if (!bLoaded)
70 0 : bLoaded = aModule.load(aLibName);
71 :
72 0 : return bLoaded ? &aModule : NULL;
73 : }
74 :
75 : #endif
76 :
77 : }
78 :
79 : #ifdef DISABLE_DYNLOADING
80 : extern "C" opengl::OpenglShapeFactory* getOpenglShapeFactory();
81 : #endif
82 :
83 0 : AbstractShapeFactory* AbstractShapeFactory::getOrCreateShapeFactory(uno::Reference< lang::XMultiServiceFactory> xFactory)
84 : {
85 : static AbstractShapeFactory* pShapeFactory = NULL;
86 :
87 0 : if(pShapeFactory)
88 0 : return pShapeFactory;
89 :
90 0 : if(getenv("CHART_DUMMY_FACTORY") && !Application::IsHeadlessModeEnabled())
91 : {
92 : #ifndef DISABLE_DYNLOADING
93 0 : osl::Module* pModule = getOpenGLModule();
94 0 : if(pModule)
95 : {
96 0 : oslGenericFunction fn = pModule->getFunctionSymbol("getOpenglShapeFactory");
97 0 : if(fn)
98 : {
99 :
100 0 : pShapeFactory = reinterpret_cast<__getOpenglShapeFactory>(fn)();
101 0 : pShapeFactory->setShapeFactory(xFactory);
102 : }
103 : }
104 : #elif defined(IOS) || defined(ANDROID) // Library_chartopengl is not portable enough yet
105 : pShapeFactory = NULL;
106 : #else
107 : pShapeFactory = getOpenglShapeFactory();
108 : pShapeFactory->setShapeFactory(xFactory);
109 : #endif
110 : }
111 :
112 :
113 0 : if(!pShapeFactory)
114 0 : pShapeFactory = new ShapeFactory(xFactory);
115 :
116 0 : return pShapeFactory;
117 : }
118 :
119 0 : sal_Int32 AbstractShapeFactory::getSymbolCount()
120 : {
121 0 : return Symbol_COUNT;
122 : }
123 :
124 0 : uno::Reference< drawing::XShapes > AbstractShapeFactory::getChartRootShape(
125 : const uno::Reference< drawing::XDrawPage>& xDrawPage )
126 : {
127 0 : uno::Reference< drawing::XShapes > xRet;
128 0 : uno::Reference< drawing::XShapes > xShapes( xDrawPage, uno::UNO_QUERY );
129 0 : if( xShapes.is() )
130 : {
131 0 : sal_Int32 nCount = xShapes->getCount();
132 0 : uno::Reference< drawing::XShape > xShape;
133 0 : for( sal_Int32 nN = nCount; nN--; )
134 : {
135 0 : if( xShapes->getByIndex( nN ) >>= xShape )
136 : {
137 0 : if( AbstractShapeFactory::getShapeName( xShape ).equals("com.sun.star.chart2.shapes") )
138 : {
139 0 : xRet = uno::Reference< drawing::XShapes >( xShape, uno::UNO_QUERY );
140 0 : break;
141 : }
142 : }
143 0 : }
144 : }
145 0 : return xRet;
146 : }
147 :
148 0 : void AbstractShapeFactory::makeShapeInvisible( const uno::Reference< drawing::XShape >& xShape )
149 : {
150 0 : uno::Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY );
151 : OSL_ENSURE(xShapeProp.is(), "created shape offers no XPropertySet");
152 0 : if( xShapeProp.is())
153 : {
154 : try
155 : {
156 0 : xShapeProp->setPropertyValue( "LineStyle", uno::makeAny( drawing::LineStyle_NONE ));
157 0 : xShapeProp->setPropertyValue( "FillStyle", uno::makeAny( drawing::FillStyle_NONE ));
158 : }
159 0 : catch( const uno::Exception& e )
160 : {
161 : ASSERT_EXCEPTION( e );
162 : }
163 0 : }
164 0 : }
165 :
166 : // set a name/CID at a shape (is used for selection handling)
167 :
168 0 : void AbstractShapeFactory::setShapeName( const uno::Reference< drawing::XShape >& xShape
169 : , const OUString& rName )
170 : {
171 0 : if(!xShape.is())
172 0 : return;
173 0 : uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
174 : OSL_ENSURE(xProp.is(), "shape offers no XPropertySet");
175 0 : if( xProp.is())
176 : {
177 : try
178 : {
179 0 : xProp->setPropertyValue( UNO_NAME_MISC_OBJ_NAME
180 0 : , uno::makeAny( rName ) );
181 : }
182 0 : catch( const uno::Exception& e )
183 : {
184 : ASSERT_EXCEPTION( e );
185 : }
186 0 : }
187 : }
188 :
189 0 : OUString AbstractShapeFactory::getShapeName( const uno::Reference< drawing::XShape >& xShape )
190 : {
191 0 : OUString aRet;
192 :
193 0 : uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
194 : OSL_ENSURE(xProp.is(), "shape offers no XPropertySet");
195 0 : if( xProp.is())
196 : {
197 : try
198 : {
199 0 : xProp->getPropertyValue( UNO_NAME_MISC_OBJ_NAME ) >>= aRet;
200 : }
201 0 : catch( const uno::Exception& e )
202 : {
203 : ASSERT_EXCEPTION( e );
204 : }
205 : }
206 :
207 0 : return aRet;
208 : }
209 :
210 0 : uno::Any AbstractShapeFactory::makeTransformation( const awt::Point& rScreenPosition2D, double fRotationAnglePi )
211 : {
212 0 : ::basegfx::B2DHomMatrix aM;
213 : //As autogrow is active the rectangle is automatically expanded to that side
214 : //to which the text is not adjusted.
215 : // aM.scale( 1, 1 ); Oops? A scale with this parameters is neutral, line commented out
216 0 : aM.rotate( fRotationAnglePi );
217 0 : aM.translate( rScreenPosition2D.X, rScreenPosition2D.Y );
218 0 : uno::Any aATransformation = uno::makeAny( B2DHomMatrixToHomogenMatrix3(aM) );
219 0 : return aATransformation;
220 : }
221 :
222 0 : OUString AbstractShapeFactory::getStackedString( const OUString& rString, bool bStacked )
223 : {
224 0 : sal_Int32 nLen = rString.getLength();
225 0 : if(!bStacked || !nLen)
226 0 : return rString;
227 :
228 0 : OUStringBuffer aStackStr;
229 :
230 : //add a newline after each letter
231 : //as we do not no letters here add a newline after each char
232 0 : for( sal_Int32 nPosSrc=0; nPosSrc < nLen; nPosSrc++ )
233 : {
234 0 : if( nPosSrc )
235 0 : aStackStr.append( '\r' );
236 0 : aStackStr.append(rString[nPosSrc]);
237 : }
238 0 : return aStackStr.makeStringAndClear();
239 : }
240 :
241 0 : bool AbstractShapeFactory::hasPolygonAnyLines( drawing::PolyPolygonShape3D& rPoly)
242 : {
243 : // #i67757# check all contained polygons, if at least one polygon contains 2 or more points, return true
244 0 : for( sal_Int32 nIdx = 0, nCount = rPoly.SequenceX.getLength(); nIdx < nCount; ++nIdx )
245 0 : if( rPoly.SequenceX[ nIdx ].getLength() > 1 )
246 0 : return true;
247 0 : return false;
248 : }
249 :
250 0 : bool AbstractShapeFactory::isPolygonEmptyOrSinglePoint( drawing::PolyPolygonShape3D& rPoly)
251 : {
252 : // true, if empty polypolygon or one polygon with one point
253 0 : return (rPoly.SequenceX.getLength() == 0) ||
254 0 : ((rPoly.SequenceX.getLength() == 1) && (rPoly.SequenceX[0].getLength() <= 1));
255 : }
256 :
257 0 : void AbstractShapeFactory::closePolygon( drawing::PolyPolygonShape3D& rPoly)
258 : {
259 : OSL_ENSURE( rPoly.SequenceX.getLength() <= 1, "AbstractShapeFactory::closePolygon - single polygon expected" );
260 : //add a last point == first point
261 0 : if(isPolygonEmptyOrSinglePoint(rPoly))
262 0 : return;
263 0 : drawing::Position3D aFirst(rPoly.SequenceX[0][0],rPoly.SequenceY[0][0],rPoly.SequenceZ[0][0]);
264 0 : AddPointToPoly( rPoly, aFirst );
265 : }
266 :
267 0 : awt::Size AbstractShapeFactory::calculateNewSizeRespectingAspectRatio(
268 : const awt::Size& rTargetSize
269 : , const awt::Size& rSourceSizeWithCorrectAspectRatio )
270 : {
271 0 : awt::Size aNewSize;
272 :
273 0 : double fFactorWidth = double(rTargetSize.Width)/double(rSourceSizeWithCorrectAspectRatio.Width);
274 0 : double fFactorHeight = double(rTargetSize.Height)/double(rSourceSizeWithCorrectAspectRatio.Height);
275 0 : double fFactor = std::min(fFactorWidth,fFactorHeight);
276 0 : aNewSize.Width=static_cast<sal_Int32>(fFactor*rSourceSizeWithCorrectAspectRatio.Width);
277 0 : aNewSize.Height=static_cast<sal_Int32>(fFactor*rSourceSizeWithCorrectAspectRatio.Height);
278 :
279 0 : return aNewSize;
280 : }
281 :
282 0 : awt::Point AbstractShapeFactory::calculateTopLeftPositionToCenterObject(
283 : const awt::Point& rTargetAreaPosition
284 : , const awt::Size& rTargetAreaSize
285 : , const awt::Size& rObjectSize )
286 : {
287 0 : awt::Point aNewPosition(rTargetAreaPosition);
288 0 : aNewPosition.X += static_cast<sal_Int32>(double(rTargetAreaSize.Width-rObjectSize.Width)/2.0);
289 0 : aNewPosition.Y += static_cast<sal_Int32>(double(rTargetAreaSize.Height-rObjectSize.Height)/2.0);
290 0 : return aNewPosition;
291 : }
292 :
293 0 : ::basegfx::B2IRectangle AbstractShapeFactory::getRectangleOfShape(
294 : const uno::Reference< drawing::XShape >& xShape )
295 : {
296 0 : ::basegfx::B2IRectangle aRet;
297 :
298 0 : if( xShape.is() )
299 : {
300 0 : awt::Point aPos = xShape->getPosition();
301 0 : awt::Size aSize = xShape->getSize();
302 0 : aRet = BaseGFXHelper::makeRectangle(aPos,aSize);
303 : }
304 0 : return aRet;
305 :
306 : }
307 :
308 0 : awt::Size AbstractShapeFactory::getSizeAfterRotation(
309 : const uno::Reference< drawing::XShape >& xShape, double fRotationAngleDegree )
310 : {
311 0 : awt::Size aRet(0,0);
312 0 : if(xShape.is())
313 : {
314 0 : const awt::Size aSize( xShape->getSize() );
315 :
316 0 : if( ::rtl::math::approxEqual( fRotationAngleDegree, 0.0 ) )
317 0 : aRet = aSize;
318 : else
319 : {
320 0 : while(fRotationAngleDegree>=360.0)
321 0 : fRotationAngleDegree-=360.0;
322 0 : while(fRotationAngleDegree<0.0)
323 0 : fRotationAngleDegree+=360.0;
324 0 : if(fRotationAngleDegree>270.0)
325 0 : fRotationAngleDegree=360.0-fRotationAngleDegree;
326 0 : else if(fRotationAngleDegree>180.0)
327 0 : fRotationAngleDegree=fRotationAngleDegree-180.0;
328 0 : else if(fRotationAngleDegree>90.0)
329 0 : fRotationAngleDegree=180.0-fRotationAngleDegree;
330 :
331 0 : const double fAnglePi = fRotationAngleDegree*F_PI/180.0;
332 :
333 : aRet.Height = static_cast<sal_Int32>(
334 0 : aSize.Width*rtl::math::sin( fAnglePi )
335 0 : + aSize.Height*rtl::math::cos( fAnglePi ));
336 : aRet.Width = static_cast<sal_Int32>(
337 0 : aSize.Width*rtl::math::cos( fAnglePi )
338 0 : + aSize.Height*rtl::math::sin( fAnglePi ));
339 : }
340 : }
341 0 : return aRet;
342 : }
343 :
344 0 : void AbstractShapeFactory::removeSubShapes( const uno::Reference< drawing::XShapes >& xShapes )
345 : {
346 0 : if( xShapes.is() )
347 : {
348 0 : sal_Int32 nSubCount = xShapes->getCount();
349 0 : uno::Reference< drawing::XShape > xShape;
350 0 : for( sal_Int32 nS = nSubCount; nS--; )
351 : {
352 0 : if( xShapes->getByIndex( nS ) >>= xShape )
353 0 : xShapes->remove( xShape );
354 0 : }
355 : }
356 0 : }
357 :
358 : }
359 :
360 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|