Coverage Report

Created: 2026-11-06 11:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/chart2/source/view/main/ShapeFactory.cxx
Line
Count
Source
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 <ShapeFactory.hxx>
21
#include <BaseGFXHelper.hxx>
22
#include <ViewDefines.hxx>
23
#include <Stripe.hxx>
24
#include <CommonConverters.hxx>
25
#include <RelativeSizeHelper.hxx>
26
#include <PropertyMapper.hxx>
27
#include <VLineProperties.hxx>
28
#include <com/sun/star/beans/XPropertySet.hpp>
29
#include <com/sun/star/chart2/XFormattedString.hpp>
30
#include <com/sun/star/drawing/CircleKind.hpp>
31
#include <com/sun/star/drawing/DoubleSequence.hpp>
32
#include <com/sun/star/drawing/FlagSequence.hpp>
33
#include <com/sun/star/drawing/FillStyle.hpp>
34
#include <com/sun/star/drawing/LineStyle.hpp>
35
#include <com/sun/star/drawing/NormalsKind.hpp>
36
#include <com/sun/star/drawing/PointSequence.hpp>
37
#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
38
#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
39
#include <com/sun/star/drawing/TextureProjectionMode.hpp>
40
#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
41
#include <com/sun/star/drawing/XShapes2.hpp>
42
#include <com/sun/star/graphic/XGraphic.hpp>
43
#include <com/sun/star/style/ParagraphAdjust.hpp>
44
#include <com/sun/star/uno/Sequence.hxx>
45
#include <com/sun/star/uno/Any.hxx>
46
47
#include <editeng/unoprnms.hxx>
48
#include <rtl/math.hxx>
49
50
#include <basegfx/point/b2dpoint.hxx>
51
#include <basegfx/matrix/b3dhommatrix.hxx>
52
#include <svx/svdpage.hxx>
53
#include <svx/svdopath.hxx>
54
#include <svx/svdorect.hxx>
55
#include <comphelper/diagnose_ex.hxx>
56
#include <tools/helpers.hxx>
57
#include <tools/UnitConversion.hxx>
58
#include <sal/log.hxx>
59
60
#include <algorithm>
61
#include <cmath>
62
#include <cstddef>
63
#include <numbers>
64
65
using namespace ::com::sun::star;
66
using ::com::sun::star::uno::Reference;
67
68
namespace chart
69
{
70
71
namespace
72
{
73
74
void lcl_addProperty(uno::Sequence<OUString> & rPropertyNames, uno::Sequence<uno::Any> & rPropertyValues,
75
                 OUString const & rName, uno::Any const & rAny)
76
0
{
77
0
    rPropertyNames.realloc(rPropertyNames.getLength() + 1);
78
0
    rPropertyNames.getArray()[rPropertyNames.getLength() - 1] = rName;
79
80
0
    rPropertyValues.realloc(rPropertyValues.getLength() + 1);
81
0
    rPropertyValues.getArray()[rPropertyValues.getLength() - 1] = rAny;
82
0
}
83
84
css::drawing::PolyPolygonShape3D toPolyPolygonShape3D(const std::vector<std::vector<css::drawing::Position3D>>& rPoints)
85
0
{
86
0
    css::drawing::PolyPolygonShape3D aUnoPoly;
87
0
    aUnoPoly.SequenceX.realloc(rPoints.size());
88
0
    aUnoPoly.SequenceY.realloc(rPoints.size());
89
0
    aUnoPoly.SequenceZ.realloc(rPoints.size());
90
0
    for (std::size_t nPolygonIndex=0; nPolygonIndex<rPoints.size(); ++nPolygonIndex)
91
0
    {
92
0
        drawing::DoubleSequence* pOuterSequenceX = &aUnoPoly.SequenceX.getArray()[nPolygonIndex];
93
0
        drawing::DoubleSequence* pOuterSequenceY = &aUnoPoly.SequenceY.getArray()[nPolygonIndex];
94
0
        drawing::DoubleSequence* pOuterSequenceZ = &aUnoPoly.SequenceZ.getArray()[nPolygonIndex];
95
0
        pOuterSequenceX->realloc(rPoints[nPolygonIndex].size());
96
0
        pOuterSequenceY->realloc(rPoints[nPolygonIndex].size());
97
0
        pOuterSequenceZ->realloc(rPoints[nPolygonIndex].size());
98
0
        double* pInnerSequenceX = pOuterSequenceX->getArray();
99
0
        double* pInnerSequenceY = pOuterSequenceY->getArray();
100
0
        double* pInnerSequenceZ = pOuterSequenceZ->getArray();
101
0
        for (std::size_t nPointIndex=0; nPointIndex<rPoints[nPolygonIndex].size(); ++nPointIndex)
102
0
        {
103
0
            auto& rPos = rPoints[nPolygonIndex][nPointIndex];
104
0
            pInnerSequenceX[nPointIndex] = rPos.PositionX;
105
0
            pInnerSequenceY[nPointIndex] = rPos.PositionY;
106
0
            pInnerSequenceZ[nPointIndex] = rPos.PositionZ;
107
0
        }
108
0
    }
109
0
    return aUnoPoly;
110
0
}
111
112
} // end anonymous namespace
113
114
rtl::Reference<SvxShapeGroupAnyD> ShapeFactory::getOrCreateChartRootShape(
115
    const rtl::Reference<SvxDrawPage>& xDrawPage )
116
0
{
117
0
    rtl::Reference<SvxShapeGroupAnyD> xRet = ShapeFactory::getChartRootShape(xDrawPage);
118
0
    if (xRet.is())
119
0
        return xRet;
120
121
    // Create a new root shape and set it to the bottom of the page.  The root
122
    // shape is identified by having the name com.sun.star.chart2.shapes.
123
0
    rtl::Reference<SvxShapeGroup> xShapeGroup = new SvxShapeGroup(nullptr, nullptr);
124
0
    xShapeGroup->setShapeKind(SdrObjKind::Group);
125
    // cast to resolve ambiguity in converting to XShape
126
0
    xDrawPage->addBottom(static_cast<SvxShape*>(xShapeGroup.get()));
127
128
0
    setShapeName(xShapeGroup, u"com.sun.star.chart2.shapes"_ustr);
129
0
    xShapeGroup->setSize(awt::Size(0,0));
130
131
0
    return xShapeGroup;
132
0
}
133
134
0
void ShapeFactory::setPageSize(const rtl::Reference<SvxShapeGroupAnyD>&, const awt::Size&) {}
135
136
//  diverse tools::PolyPolygon create methods
137
138
static uno::Any createPolyPolygon_Cube(
139
            const drawing::Direction3D& rSize, double fRoundedEdge, bool bRounded )
140
0
{
141
0
    OSL_PRECOND(fRoundedEdge>=0, "fRoundedEdge needs to be >= 0");
142
143
    // always use extra points, so set percent diagonal to 0.4 which is 0% in the UI (old Chart comment)
144
0
    if( fRoundedEdge == 0.0  && bRounded)
145
0
        fRoundedEdge = 0.4 / 200.0;
146
0
    else if(!bRounded)
147
0
        fRoundedEdge = 0.0;
148
149
    //fWidthH stands for Half Width
150
0
    const double fWidthH = rSize.DirectionX >=0.0?  rSize.DirectionX/2.0  : -rSize.DirectionX/2.0;
151
0
    const double fHeight = rSize.DirectionY;
152
153
0
    const double fHeightSign = fHeight >= 0.0 ? 1.0 : -1.0;
154
155
0
    const double fOffset = (fWidthH * fRoundedEdge) * 1.05; // increase by 5% for safety
156
0
    const bool bRoundEdges = fRoundedEdge && fOffset < fWidthH && 2.0 * fOffset < fHeightSign*fHeight;
157
0
    const sal_Int32 nPointCount = bRoundEdges ? 13 : 5;
158
159
0
    drawing::PolyPolygonShape3D aPP;
160
161
0
    aPP.SequenceX.realloc(1);
162
0
    aPP.SequenceY.realloc(1);
163
0
    aPP.SequenceZ.realloc(1);
164
165
0
    drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
166
0
    drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
167
0
    drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
168
169
0
    pOuterSequenceX->realloc(nPointCount);
170
0
    pOuterSequenceY->realloc(nPointCount);
171
0
    pOuterSequenceZ->realloc(nPointCount);
172
173
0
    double* pInnerSequenceX = pOuterSequenceX->getArray();
174
0
    double* pInnerSequenceY = pOuterSequenceY->getArray();
175
0
    double* pInnerSequenceZ = pOuterSequenceZ->getArray();
176
177
0
    for(sal_Int32 nN = nPointCount; nN--;)
178
0
        *pInnerSequenceZ++ = 0.0;
179
180
0
    if(nPointCount == 5)
181
0
    {
182
0
        *pInnerSequenceY++ = 0.0;
183
0
        *pInnerSequenceY++ = 0.0;
184
0
        *pInnerSequenceY++ = fHeight;
185
0
        *pInnerSequenceY++ = fHeight;
186
0
        *pInnerSequenceY++ = 0.0;
187
188
0
        *pInnerSequenceX++ = -fWidthH;
189
0
        *pInnerSequenceX++ = fWidthH;
190
0
        *pInnerSequenceX++ = fWidthH;
191
0
        *pInnerSequenceX++ = -fWidthH;
192
0
        *pInnerSequenceX++ = -fWidthH;
193
0
    }
194
0
    else
195
0
    {
196
0
        *pInnerSequenceY++ = 0.0;
197
0
        *pInnerSequenceY++ = 0.0;
198
0
        *pInnerSequenceY++ = 0.0;
199
0
        *pInnerSequenceY++ = fHeightSign*fOffset;
200
0
        *pInnerSequenceY++ = fHeight - fHeightSign*fOffset;
201
0
        *pInnerSequenceY++ = fHeight;
202
0
        *pInnerSequenceY++ = fHeight;
203
0
        *pInnerSequenceY++ = fHeight;
204
0
        *pInnerSequenceY++ = fHeight;
205
0
        *pInnerSequenceY++ = fHeight - fHeightSign*fOffset;
206
0
        *pInnerSequenceY++ = fHeightSign*fOffset;
207
0
        *pInnerSequenceY++ = 0.0;
208
0
        *pInnerSequenceY++ = 0.0;
209
210
0
        *pInnerSequenceX++ = -fWidthH + fOffset;
211
0
        *pInnerSequenceX++ = fWidthH - fOffset;
212
0
        *pInnerSequenceX++ = fWidthH;
213
0
        *pInnerSequenceX++ = fWidthH;
214
0
        *pInnerSequenceX++ = fWidthH;
215
0
        *pInnerSequenceX++ = fWidthH;
216
0
        *pInnerSequenceX++ = fWidthH - fOffset;
217
0
        *pInnerSequenceX++ = -fWidthH + fOffset;
218
0
        *pInnerSequenceX++ = -fWidthH;
219
0
        *pInnerSequenceX++ = -fWidthH;
220
0
        *pInnerSequenceX++ = -fWidthH;
221
0
        *pInnerSequenceX++ = -fWidthH;
222
0
        *pInnerSequenceX++ = -fWidthH + fOffset;
223
0
    }
224
0
    return uno::Any( &aPP, cppu::UnoType<drawing::PolyPolygonShape3D>::get());
225
0
}
226
227
static uno::Any createPolyPolygon_Cylinder(
228
             double fHeight
229
           , double fRadius
230
           , sal_Int32& nVerticalSegmentCount )
231
0
{
232
    //fHeight may be negative
233
0
    OSL_PRECOND(fRadius>0, "The radius of a cylinder needs to be > 0");
234
235
0
    drawing::PolyPolygonShape3D aPP;
236
237
0
    nVerticalSegmentCount=1;
238
239
0
    aPP.SequenceX.realloc(3);
240
0
    aPP.SequenceY.realloc(3);
241
0
    aPP.SequenceZ.realloc(3);
242
243
0
    drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
244
0
    drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
245
0
    drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
246
247
0
    pOuterSequenceX->realloc(2);
248
0
    pOuterSequenceY->realloc(2);
249
0
    pOuterSequenceZ->realloc(2);
250
251
0
    double* pInnerSequenceX = pOuterSequenceX->getArray();
252
0
    double* pInnerSequenceY = pOuterSequenceY->getArray();
253
0
    double* pInnerSequenceZ = pOuterSequenceZ->getArray();
254
255
0
    double fY1 = 0.0;
256
0
    double fY2 = fHeight;
257
258
0
    if( fHeight<0.0 )
259
0
        std::swap(fY1,fY2);
260
261
0
    for(sal_Int32 nN = 2; nN--;)
262
0
        *pInnerSequenceZ++ = 0.0;
263
264
0
    *pInnerSequenceX++ = 0.0;
265
0
    *pInnerSequenceY++ = fY1;
266
267
0
    *pInnerSequenceX++ = fRadius;
268
0
    *pInnerSequenceY++ = fY1;
269
270
0
    pOuterSequenceX++;pOuterSequenceY++;pOuterSequenceZ++;
271
0
    pOuterSequenceX->realloc(2);
272
0
    pOuterSequenceY->realloc(2);
273
0
    pOuterSequenceZ->realloc(2);
274
275
0
    pInnerSequenceX = pOuterSequenceX->getArray();
276
0
    pInnerSequenceY = pOuterSequenceY->getArray();
277
0
    pInnerSequenceZ = pOuterSequenceZ->getArray();
278
279
0
    for(sal_Int32 nN = 2; nN--;)
280
0
        *pInnerSequenceZ++ = 0.0;
281
282
0
    *pInnerSequenceX++ = fRadius;
283
0
    *pInnerSequenceY++ = fY1;
284
285
0
    *pInnerSequenceX++ = fRadius;
286
0
    *pInnerSequenceY++ = fY2;
287
288
0
    pOuterSequenceX++;pOuterSequenceY++;pOuterSequenceZ++;
289
0
    pOuterSequenceX->realloc(2);
290
0
    pOuterSequenceY->realloc(2);
291
0
    pOuterSequenceZ->realloc(2);
292
293
0
    pInnerSequenceX = pOuterSequenceX->getArray();
294
0
    pInnerSequenceY = pOuterSequenceY->getArray();
295
0
    pInnerSequenceZ = pOuterSequenceZ->getArray();
296
297
0
    for(sal_Int32 nN = 2; nN--;)
298
0
        *pInnerSequenceZ++ = 0.0;
299
300
0
    *pInnerSequenceX++ = fRadius;
301
0
    *pInnerSequenceY++ = fY2;
302
303
0
    *pInnerSequenceX++ = 0.0;
304
0
    *pInnerSequenceY++ = fY2;
305
306
0
    return uno::Any( &aPP, cppu::UnoType<drawing::PolyPolygonShape3D>::get());
307
0
}
308
309
static uno::Any createPolyPolygon_Cone( double fHeight, double fRadius, double fTopHeight
310
            , sal_Int32& nVerticalSegmentCount )
311
0
{
312
0
    OSL_PRECOND(fRadius>0, "The radius of a cone needs to be > 0");
313
314
    //for stacked charts we need cones without top -> fTopHeight != 0 resp. bTopless == true
315
    //fTopHeight indicates the height of the cut top only (not the full height)
316
0
    bool bTopless = !::rtl::math::approxEqual( fHeight, fHeight + fTopHeight );
317
318
0
    double r1= 0.0, r2 = fRadius;
319
0
    if(bTopless)
320
        // #i63212# fHeight may be negative, fTopHeight is always positive -> use fabs(fHeight)
321
0
        r1 = fRadius * fTopHeight/(fabs(fHeight)+fTopHeight);
322
323
0
    nVerticalSegmentCount=1;
324
0
    drawing::PolyPolygonShape3D aPP;
325
326
0
    aPP.SequenceX.realloc(2);
327
0
    aPP.SequenceY.realloc(2);
328
0
    aPP.SequenceZ.realloc(2);
329
330
0
    drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
331
0
    drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
332
0
    drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
333
334
0
    pOuterSequenceX->realloc(2);
335
0
    pOuterSequenceY->realloc(2);
336
0
    pOuterSequenceZ->realloc(2);
337
338
0
    double* pInnerSequenceX = pOuterSequenceX->getArray();
339
0
    double* pInnerSequenceY = pOuterSequenceY->getArray();
340
0
    double* pInnerSequenceZ = pOuterSequenceZ->getArray();
341
342
0
    double fX1 = 0.0;
343
0
    double fX2 = r2;
344
0
    double fX3 = r1;
345
346
0
    double fY1 = 0.0;
347
0
    double fY2 = 0.0;
348
0
    double fY3 = fHeight;
349
350
0
    if( fHeight<0.0 )
351
0
    {
352
0
        std::swap(fX1,fX3);
353
0
        std::swap(fY1,fY3);
354
0
    }
355
356
0
    for(sal_Int32 nN = 2; nN--;)
357
0
        *pInnerSequenceZ++ = 0.0;
358
359
0
    *pInnerSequenceY++ = fY1;
360
0
    *pInnerSequenceX++ = fX1;
361
362
0
    *pInnerSequenceY++ = fY2;
363
0
    *pInnerSequenceX++ = fX2;
364
365
0
    pOuterSequenceX++;pOuterSequenceY++;pOuterSequenceZ++;
366
0
    pOuterSequenceX->realloc(2);
367
0
    pOuterSequenceY->realloc(2);
368
0
    pOuterSequenceZ->realloc(2);
369
370
0
    pInnerSequenceX = pOuterSequenceX->getArray();
371
0
    pInnerSequenceY = pOuterSequenceY->getArray();
372
0
    pInnerSequenceZ = pOuterSequenceZ->getArray();
373
374
0
    for(sal_Int32 nN = 2; nN--;)
375
0
        *pInnerSequenceZ++ = 0.0;
376
377
0
    *pInnerSequenceY++ = fY2;
378
0
    *pInnerSequenceX++ = fX2;
379
380
0
    *pInnerSequenceY++ = fY3;
381
0
    *pInnerSequenceX++ = fX3;
382
383
0
    return uno::Any( &aPP, cppu::UnoType<drawing::PolyPolygonShape3D>::get());
384
0
}
385
386
//  methods for 3D shape creation
387
388
rtl::Reference<Svx3DExtrudeObject>
389
        ShapeFactory::createCube(
390
            const rtl::Reference<SvxShapeGroupAnyD>& xTarget
391
            , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
392
            , sal_Int32 nRotateZAngleHundredthDegree
393
            , const uno::Reference< beans::XPropertySet >& xSourceProp
394
            , const tPropertyNameMap& rPropertyNameMap
395
            , bool bRounded )
396
0
{
397
0
    if( !xTarget.is() )
398
0
        return nullptr;
399
0
    if( bRounded )
400
0
    {
401
0
        try
402
0
        {
403
0
            if( xSourceProp.is() )
404
0
            {
405
0
                drawing::LineStyle aLineStyle;
406
0
                xSourceProp->getPropertyValue( u"BorderStyle"_ustr ) >>= aLineStyle;
407
0
                if( aLineStyle == drawing::LineStyle_SOLID )
408
0
                    bRounded = false;
409
0
            }
410
0
        }
411
0
        catch( const uno::Exception& )
412
0
        {
413
0
            TOOLS_WARN_EXCEPTION("chart2", "" );
414
0
        }
415
0
    }
416
0
    rtl::Reference<Svx3DExtrudeObject> xShape = impl_createCube( xTarget, rPosition, rSize, nRotateZAngleHundredthDegree, bRounded );
417
0
    if( xSourceProp.is())
418
0
        PropertyMapper::setMappedProperties( *xShape, xSourceProp, rPropertyNameMap );
419
0
    return xShape;
420
0
}
421
422
rtl::Reference<Svx3DExtrudeObject>
423
        ShapeFactory::impl_createCube(
424
              const rtl::Reference<SvxShapeGroupAnyD>& xTarget
425
            , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
426
            , sal_Int32 nRotateZAngleHundredthDegree
427
            , bool bRounded )
428
0
{
429
0
    if( !xTarget.is() )
430
0
        return nullptr;
431
432
    //create shape
433
0
    rtl::Reference<Svx3DExtrudeObject> xShape = new Svx3DExtrudeObject(nullptr);
434
0
    xShape->setShapeKind(SdrObjKind::E3D_Extrusion);
435
0
    xTarget->addShape(*xShape);
436
437
    //set properties
438
0
    try
439
0
    {
440
        //depth
441
0
        double fDepth = rSize.DirectionZ;
442
0
        if (fDepth<0)
443
0
            fDepth*=-1.0;
444
445
        //PercentDiagonal
446
0
        sal_Int16 nPercentDiagonal = bRounded ? 3 : 0;
447
448
        //Matrix for position
449
0
        basegfx::B3DHomMatrix aHomMatrix;
450
0
        if (nRotateZAngleHundredthDegree != 0)
451
0
            aHomMatrix.rotate(0.0, 0.0, -basegfx::deg2rad<100>(nRotateZAngleHundredthDegree));
452
0
        aHomMatrix.translate(rPosition.PositionX, rPosition.PositionY,
453
0
                             rPosition.PositionZ - (fDepth / 2.0));
454
455
0
        uno::Sequence<OUString> aPropertyNames {
456
0
            UNO_NAME_3D_EXTRUDE_DEPTH,
457
0
            UNO_NAME_3D_PERCENT_DIAGONAL,
458
0
            UNO_NAME_3D_POLYPOLYGON3D,
459
0
            UNO_NAME_3D_TRANSFORM_MATRIX,
460
0
        };
461
462
0
        uno::Sequence<uno::Any> aPropertyValues {
463
0
            uno::Any(sal_Int32(fDepth)), // Depth
464
0
            uno::Any(nPercentDiagonal),  // PercentDiagonal
465
0
            createPolyPolygon_Cube(rSize, double(nPercentDiagonal) / 200.0, bRounded),
466
0
            uno::Any(B3DHomMatrixToHomogenMatrix(aHomMatrix))
467
0
        };
468
469
0
        xShape->setPropertyValues(aPropertyNames, aPropertyValues);
470
0
    }
471
0
    catch( const uno::Exception& )
472
0
    {
473
0
        TOOLS_WARN_EXCEPTION("chart2", "" );
474
0
    }
475
0
    return xShape;
476
0
}
477
478
rtl::Reference<Svx3DLatheObject>
479
        ShapeFactory::createCylinder(
480
            const rtl::Reference<SvxShapeGroupAnyD>& xTarget
481
          , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
482
          , sal_Int32 nRotateZAngleHundredthDegree )
483
0
{
484
0
    return impl_createConeOrCylinder(
485
0
              xTarget, rPosition, rSize, 0.0, nRotateZAngleHundredthDegree, true );
486
0
}
487
488
rtl::Reference<Svx3DSceneObject>
489
        ShapeFactory::createPyramid(
490
            const rtl::Reference<SvxShapeGroupAnyD>& xTarget
491
          , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
492
          , double fTopHeight, bool bRotateZ
493
          , const uno::Reference< beans::XPropertySet >& xSourceProp
494
          , const tPropertyNameMap& rPropertyNameMap )
495
0
{
496
0
    if( !xTarget.is() )
497
0
        return nullptr;
498
499
0
    rtl::Reference<Svx3DSceneObject> xGroup( ShapeFactory::createGroup3D( xTarget ) );
500
501
0
    bool bDoubleSided = false;
502
0
    short nRotatedTexture = 0;
503
504
0
    const double fWidth = rSize.DirectionX;
505
0
    const double fDepth = rSize.DirectionZ;
506
0
    const double fHeight = rSize.DirectionY;
507
508
0
    drawing::Position3D aBottomP1( rPosition.PositionX, rPosition.PositionY, rPosition.PositionZ - fDepth/2.0  );
509
0
    if(bRotateZ)
510
0
        aBottomP1.PositionY -= fWidth/2.0;
511
0
    else
512
0
        aBottomP1.PositionX -= fWidth/2.0;
513
0
    drawing::Position3D aBottomP2( aBottomP1 );
514
0
    if(bRotateZ)
515
0
        aBottomP2.PositionY += fWidth;
516
0
    else
517
0
        aBottomP2.PositionX += fWidth;
518
0
    drawing::Position3D aBottomP3( aBottomP2 );
519
0
    drawing::Position3D aBottomP4( aBottomP1 );
520
0
    aBottomP3.PositionZ += fDepth;
521
0
    aBottomP4.PositionZ += fDepth;
522
523
0
    const double fTopFactor = fTopHeight/(fabs(fHeight)+fTopHeight);
524
0
    drawing::Position3D aTopP1( rPosition.PositionX, rPosition.PositionY, rPosition.PositionZ - fDepth*fTopFactor/2.0  );
525
0
    if(bRotateZ)
526
0
    {
527
0
        aTopP1.PositionY -= fWidth*fTopFactor/2.0;
528
0
        aTopP1.PositionX += fHeight;
529
0
    }
530
0
    else
531
0
    {
532
0
        aTopP1.PositionX -= fWidth*fTopFactor/2.0;
533
0
        aTopP1.PositionY += fHeight;
534
0
    }
535
0
    drawing::Position3D aTopP2( aTopP1 );
536
0
    if(bRotateZ)
537
0
        aTopP2.PositionY += fWidth*fTopFactor;
538
0
    else
539
0
        aTopP2.PositionX += fWidth*fTopFactor;
540
0
    drawing::Position3D aTopP3( aTopP2 );
541
0
    drawing::Position3D aTopP4( aTopP1 );
542
0
    aTopP3.PositionZ += fDepth*fTopFactor;
543
0
    aTopP4.PositionZ += fDepth*fTopFactor;
544
545
0
    Stripe aStripeBottom( aBottomP1, aBottomP4, aBottomP3, aBottomP2 );
546
547
0
    drawing::Position3D aNormalsBottomP1( aBottomP1 );
548
0
    drawing::Position3D aNormalsBottomP2( aBottomP2 );
549
0
    drawing::Position3D aNormalsBottomP3( aBottomP3 );
550
0
    drawing::Position3D aNormalsBottomP4( aBottomP4 );
551
0
    drawing::Position3D aNormalsTopP1( aBottomP1 );
552
0
    drawing::Position3D aNormalsTopP2( aBottomP2 );
553
0
    drawing::Position3D aNormalsTopP3( aBottomP3 );
554
0
    drawing::Position3D aNormalsTopP4( aBottomP4 );
555
0
    if( bRotateZ )
556
0
    {
557
0
        aNormalsTopP1.PositionX += fHeight;
558
0
        aNormalsTopP2.PositionX += fHeight;
559
0
        aNormalsTopP3.PositionX += fHeight;
560
0
        aNormalsTopP4.PositionX += fHeight;
561
0
    }
562
0
    else
563
0
    {
564
0
        aNormalsTopP1.PositionY += fHeight;
565
0
        aNormalsTopP2.PositionY += fHeight;
566
0
        aNormalsTopP3.PositionY += fHeight;
567
0
        aNormalsTopP4.PositionY += fHeight;
568
0
    }
569
570
0
    bool bInvertPolygon = false;
571
0
    bool bInvertNormals = false;
572
573
0
    if(bRotateZ)
574
0
    {
575
        //bars
576
0
        if(fHeight>=0.0)
577
0
        {
578
0
            nRotatedTexture = 2;
579
0
            bInvertNormals = true;
580
0
            aStripeBottom = Stripe( aBottomP1, aBottomP4, aBottomP3, aBottomP2 );
581
0
        }
582
0
        else
583
0
        {
584
0
            bInvertPolygon = true;
585
0
            nRotatedTexture = 1;
586
0
            aStripeBottom = Stripe( aBottomP2, aBottomP3, aBottomP4, aBottomP1 );
587
0
        }
588
0
    }
589
0
    else
590
0
    {
591
        //columns
592
0
        if(fHeight>=0.0)
593
0
        {
594
0
            bInvertPolygon = true;
595
0
            nRotatedTexture = 2;
596
0
            aStripeBottom = Stripe( aBottomP2, aBottomP3, aBottomP4, aBottomP1 );
597
0
        }
598
0
        else
599
0
        {
600
0
            nRotatedTexture = 3;
601
0
            bInvertNormals = true;
602
0
            aStripeBottom = Stripe( aBottomP4, aBottomP3, aBottomP2, aBottomP1 );
603
0
        }
604
0
    }
605
0
    aStripeBottom.InvertNormal(true);
606
607
0
    Stripe aStripe1( aTopP2, aTopP1, aBottomP1, aBottomP2 );
608
0
    Stripe aStripe2( aTopP3, aTopP2, aBottomP2, aBottomP3 );
609
0
    Stripe aStripe3( aTopP4, aTopP3, aBottomP3, aBottomP4 );
610
0
    Stripe aStripe4( aTopP1, aTopP4, aBottomP4, aBottomP1 );
611
612
0
    if( bInvertPolygon )
613
0
    {
614
0
        aStripe1 = Stripe( aBottomP1, aTopP1, aTopP2, aBottomP2 );
615
0
        aStripe2 = Stripe( aBottomP2, aTopP2, aTopP3, aBottomP3 );
616
0
        aStripe3 = Stripe( aBottomP3, aTopP3, aTopP4, aBottomP4 );
617
0
        aStripe4 = Stripe( aBottomP4, aTopP4, aTopP1, aBottomP1 );
618
0
    }
619
620
0
    Stripe aNormalsStripe1( aNormalsTopP1, aNormalsBottomP1, aNormalsBottomP2, aNormalsTopP2 );
621
0
    Stripe aNormalsStripe2( aNormalsTopP2, aNormalsBottomP2, aNormalsBottomP3, aNormalsTopP3 );
622
0
    Stripe aNormalsStripe3( aNormalsTopP3, aNormalsBottomP3, aNormalsBottomP4, aNormalsTopP4 );
623
0
    Stripe aNormalsStripe4( aNormalsTopP4, aNormalsBottomP4, aNormalsBottomP1, aNormalsTopP1 );
624
625
0
    if( bInvertNormals )
626
0
    {
627
0
        aNormalsStripe1 = Stripe( aNormalsTopP2, aNormalsBottomP2, aNormalsBottomP1, aNormalsTopP1 );
628
0
        aNormalsStripe2 = Stripe( aNormalsTopP3, aNormalsBottomP3, aNormalsBottomP2, aNormalsTopP2 );
629
0
        aNormalsStripe3 = Stripe( aNormalsTopP4, aNormalsBottomP4, aNormalsBottomP3, aNormalsTopP3 );
630
0
        aNormalsStripe4 = Stripe( aNormalsTopP1, aNormalsBottomP1, aNormalsBottomP4, aNormalsTopP4 );
631
0
    }
632
633
0
    aStripe1.SetManualNormal( aNormalsStripe1.getNormal() );
634
0
    aStripe2.SetManualNormal( aNormalsStripe2.getNormal() );
635
0
    aStripe3.SetManualNormal( aNormalsStripe3.getNormal() );
636
0
    aStripe4.SetManualNormal( aNormalsStripe4.getNormal() );
637
638
0
    const bool bFlatNormals = false;
639
0
    ShapeFactory::createStripe( xGroup, aStripe1, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
640
0
    ShapeFactory::createStripe( xGroup, aStripe2, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
641
0
    ShapeFactory::createStripe( xGroup, aStripe3, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
642
0
    ShapeFactory::createStripe( xGroup, aStripe4, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
643
0
    ShapeFactory::createStripe( xGroup, aStripeBottom, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
644
645
0
    return xGroup;
646
0
}
647
648
rtl::Reference<Svx3DLatheObject>
649
        ShapeFactory::createCone(
650
            const rtl::Reference<SvxShapeGroupAnyD>& xTarget
651
          , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
652
          , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree )
653
0
{
654
0
    return impl_createConeOrCylinder( xTarget, rPosition, rSize, fTopHeight, nRotateZAngleHundredthDegree, false );
655
0
}
656
657
rtl::Reference<Svx3DLatheObject>
658
        ShapeFactory::impl_createConeOrCylinder(
659
              const rtl::Reference<SvxShapeGroupAnyD>& xTarget
660
            , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
661
            , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree
662
            , bool bCylinder )
663
0
{
664
0
    if( !xTarget.is() )
665
0
        return nullptr;
666
667
    //create shape
668
0
    rtl::Reference<Svx3DLatheObject> xShape = new Svx3DLatheObject(nullptr);
669
0
    xShape->setShapeKind(SdrObjKind::E3D_Lathe);
670
0
    xTarget->addShape(*xShape);
671
672
0
    double fWidth      = rSize.DirectionX/2.0; //The depth will be corrected within Matrix
673
0
    double fRadius     = fWidth; //!!!!!!!! problem in drawing layer: rotation object calculates wrong needed size -> wrong camera (it's a problem with bounding boxes)
674
0
    double fHeight     = rSize.DirectionY;
675
676
    //set properties
677
0
    try
678
0
    {
679
        //Polygon
680
0
        sal_Int32 nVerticalSegmentCount = 0;
681
0
        uno::Any aPPolygon = bCylinder
682
0
            ? createPolyPolygon_Cylinder(fHeight, fRadius, nVerticalSegmentCount)
683
0
            : createPolyPolygon_Cone(fHeight, fRadius, fTopHeight, nVerticalSegmentCount);
684
685
        //Matrix for position
686
0
        basegfx::B3DHomMatrix aHomMatrix;
687
0
        if (nRotateZAngleHundredthDegree != 0)
688
0
            aHomMatrix.rotate(0.0,0.0,-basegfx::deg2rad<100>(nRotateZAngleHundredthDegree));
689
        //stretch the symmetric objects to given depth
690
0
        aHomMatrix.scale(1.0,1.0,rSize.DirectionZ/rSize.DirectionX);
691
0
        aHomMatrix.translate(rPosition.PositionX, rPosition.PositionY, rPosition.PositionZ);
692
693
0
        uno::Sequence<OUString> aPropertyNames{
694
0
            UNO_NAME_3D_PERCENT_DIAGONAL,
695
0
            UNO_NAME_3D_POLYPOLYGON3D,
696
0
            UNO_NAME_3D_TRANSFORM_MATRIX,
697
0
            UNO_NAME_3D_HORZ_SEGS,
698
0
            UNO_NAME_3D_VERT_SEGS,
699
0
            UNO_NAME_3D_REDUCED_LINE_GEOMETRY
700
0
        };
701
702
0
        uno::Sequence<uno::Any> aPropertyValues {
703
0
            uno::Any(sal_Int16(5)),  // PercentDiagonal
704
0
            aPPolygon,               // Polygon
705
0
            uno::Any(B3DHomMatrixToHomogenMatrix(aHomMatrix)), // Matrix
706
0
            uno::Any(CHART_3DOBJECT_SEGMENTCOUNT), // Horizontal Segments
707
0
            uno::Any(nVerticalSegmentCount),       // Vertical Segments
708
0
            uno::Any(true)                         // Reduced lines
709
0
        };
710
711
0
        xShape->setPropertyValues(aPropertyNames, aPropertyValues);
712
0
    }
713
0
    catch( const uno::Exception& )
714
0
    {
715
0
        TOOLS_WARN_EXCEPTION("chart2", "" );
716
0
    }
717
0
    return xShape;
718
0
}
719
720
static void appendAndCloseBezierCoords( drawing::PolyPolygonBezierCoords& rReturn, const drawing::PolyPolygonBezierCoords& rAdd, bool bAppendInverse )
721
0
{
722
0
    if(!rAdd.Coordinates.hasElements())
723
0
        return;
724
0
    sal_Int32 nAddCount = rAdd.Coordinates[0].getLength();
725
0
    if(!nAddCount)
726
0
        return;
727
728
0
    sal_Int32 nOldCount = rReturn.Coordinates[0].getLength();
729
730
0
    auto pCoordinates = rReturn.Coordinates.getArray();
731
0
    pCoordinates[0].realloc(nOldCount + nAddCount + 1);
732
0
    auto pCoordinates0 = pCoordinates[0].getArray();
733
0
    auto pFlags = rReturn.Flags.getArray();
734
0
    pFlags[0].realloc(nOldCount+nAddCount+1);
735
0
    auto pFlags0 = pFlags[0].getArray();
736
737
0
    for(sal_Int32 nN=0;nN<nAddCount; nN++ )
738
0
    {
739
0
        sal_Int32 nAdd = bAppendInverse ? (nAddCount-1-nN) : nN;
740
0
        pCoordinates0[nOldCount+nN] = rAdd.Coordinates[0][nAdd];
741
0
        pFlags0[nOldCount+nN] = rAdd.Flags[0][nAdd];
742
0
    }
743
744
    //close
745
0
    pCoordinates0[nOldCount+nAddCount] = rReturn.Coordinates[0][0];
746
0
    pFlags0[nOldCount+nAddCount] = rReturn.Flags[0][0];
747
0
}
748
749
static drawing::PolyPolygonBezierCoords getCircularArcBezierCoords(
750
        double fStartAngleRadian, double fWidthAngleRadian, double fUnitRadius
751
        , const ::basegfx::B2DHomMatrix& rTransformationFromUnitCircle
752
        , const double fAngleSubdivisionRadian )
753
0
{
754
    //at least one polygon is created using two normal and two control points
755
    //if the angle is larger it is separated into multiple sub angles
756
757
0
    drawing::PolyPolygonBezierCoords aReturn;
758
0
    sal_Int32 nSegmentCount = static_cast< sal_Int32 >( fWidthAngleRadian/fAngleSubdivisionRadian );
759
0
    if( fWidthAngleRadian > fAngleSubdivisionRadian*nSegmentCount )
760
0
        nSegmentCount++;
761
762
0
    double fFirstSegmentAngle = fAngleSubdivisionRadian;
763
0
    double fLastSegmentAngle = fAngleSubdivisionRadian;
764
0
    if(nSegmentCount==1)
765
0
    {
766
0
        fFirstSegmentAngle = fWidthAngleRadian;
767
0
        fLastSegmentAngle = 0.0;
768
0
    }
769
0
    else
770
0
    {
771
0
        double fFirstAngleOnSubDivision = (static_cast<sal_Int32>(fStartAngleRadian/fAngleSubdivisionRadian)+1)*fAngleSubdivisionRadian;
772
0
        if( !::rtl::math::approxEqual( fStartAngleRadian, fFirstAngleOnSubDivision ) )
773
0
            fFirstSegmentAngle = fFirstAngleOnSubDivision-fStartAngleRadian;
774
775
0
        if(nSegmentCount>1)
776
0
        {
777
0
            fLastSegmentAngle = fWidthAngleRadian-fFirstSegmentAngle-fAngleSubdivisionRadian*(nSegmentCount-2);
778
0
            if( fLastSegmentAngle<0 )
779
0
                nSegmentCount--;
780
0
            if( fLastSegmentAngle>fAngleSubdivisionRadian )
781
0
            {
782
0
                fLastSegmentAngle-=fAngleSubdivisionRadian;
783
0
                nSegmentCount++;
784
0
            }
785
0
        }
786
0
    }
787
788
0
    sal_Int32 nPointCount     = 1 + 3*nSegmentCount; //first point of next segment equals last point of former segment
789
790
0
    drawing::PointSequence aPoints(nPointCount);
791
0
    auto pPoints = aPoints.getArray();
792
0
    drawing::FlagSequence  aFlags(nPointCount);
793
0
    auto pFlags = aFlags.getArray();
794
795
    //!! applying matrix to vector does ignore translation, so it is important to use a B2DPoint here instead of B2DVector
796
0
    ::basegfx::B2DPoint P0,P1,P2,P3;
797
798
0
    sal_Int32 nPoint=0;
799
0
    double fCurrentRotateAngle = fStartAngleRadian;
800
0
    for(sal_Int32 nSegment=0; nSegment<nSegmentCount; nSegment++)
801
0
    {
802
0
        double fCurrentSegmentAngle = fAngleSubdivisionRadian;
803
0
        if(nSegment==0)//first segment gets only a smaller piece until the next subdivision
804
0
            fCurrentSegmentAngle = fFirstSegmentAngle;
805
0
        else if(nSegment==(nSegmentCount-1)) //the last segment gets the rest angle that does not fit into equal pieces
806
0
            fCurrentSegmentAngle = fLastSegmentAngle;
807
808
        //first create untransformed points for a unit circle arc:
809
0
        const double fCos = cos(fCurrentSegmentAngle/2.0);
810
0
        const double fSin = sin(fCurrentSegmentAngle/2.0);
811
0
        P0.setX(fCos);
812
0
        P3.setX(fCos);
813
0
        P0.setY(-fSin);
814
0
        P3.setY(-P0.getY());
815
816
0
        P1.setX((4.0-fCos)/3.0);
817
0
        P2.setX(P1.getX());
818
0
        P1.setY((1.0-fCos)*(fCos-3.0)/(3.0*fSin));
819
0
        P2.setY(-P1.getY());
820
        //transform thus startangle equals NULL
821
0
        ::basegfx::B2DHomMatrix aStart;
822
0
        aStart.rotate(fCurrentSegmentAngle/2.0 + fCurrentRotateAngle );
823
0
        fCurrentRotateAngle+=fCurrentSegmentAngle;
824
825
0
        aStart.scale( fUnitRadius, fUnitRadius );
826
827
        //apply given transformation to get final points
828
0
        P0 = rTransformationFromUnitCircle*(aStart*P0);
829
0
        P1 = rTransformationFromUnitCircle*(aStart*P1);
830
0
        P2 = rTransformationFromUnitCircle*(aStart*P2);
831
0
        P3 = rTransformationFromUnitCircle*(aStart*P3);
832
833
0
        pPoints[nPoint].X = static_cast< sal_Int32 >( P0.getX());
834
0
        pPoints[nPoint].Y = static_cast< sal_Int32 >( P0.getY());
835
0
        pFlags [nPoint++] = drawing::PolygonFlags_NORMAL;
836
837
0
        pPoints[nPoint].X = static_cast< sal_Int32 >( P1.getX());
838
0
        pPoints[nPoint].Y = static_cast< sal_Int32 >( P1.getY());
839
0
        pFlags[nPoint++] = drawing::PolygonFlags_CONTROL;
840
841
0
        pPoints[nPoint].X = static_cast< sal_Int32 >( P2.getX());
842
0
        pPoints[nPoint].Y = static_cast< sal_Int32 >( P2.getY());
843
0
        pFlags [nPoint++] = drawing::PolygonFlags_CONTROL;
844
845
0
        if(nSegment==(nSegmentCount-1))
846
0
        {
847
0
            pPoints[nPoint].X = static_cast< sal_Int32 >( P3.getX());
848
0
            pPoints[nPoint].Y = static_cast< sal_Int32 >( P3.getY());
849
0
            pFlags [nPoint++] = drawing::PolygonFlags_NORMAL;
850
0
        }
851
0
    }
852
853
0
    aReturn.Coordinates = { aPoints };
854
0
    aReturn.Flags = { aFlags };
855
856
0
    return aReturn;
857
0
}
858
859
static drawing::PolyPolygonBezierCoords getRingBezierCoords(
860
            double fUnitCircleInnerRadius
861
            , double fUnitCircleOuterRadius
862
            , double fStartAngleRadian, double fWidthAngleRadian
863
            , const ::basegfx::B2DHomMatrix& aTransformationFromUnitCircle
864
            , const double fAngleSubdivisionRadian )
865
0
{
866
0
    drawing::PolyPolygonBezierCoords aReturn;
867
868
0
    drawing::PolyPolygonBezierCoords aOuterArc = getCircularArcBezierCoords(
869
0
        fStartAngleRadian, fWidthAngleRadian, fUnitCircleOuterRadius, aTransformationFromUnitCircle, fAngleSubdivisionRadian );
870
0
    aReturn.Coordinates = { aOuterArc.Coordinates[0] };
871
0
    aReturn.Flags = { aOuterArc.Flags[0] };
872
873
0
    drawing::PolyPolygonBezierCoords aInnerArc = getCircularArcBezierCoords(
874
0
        fStartAngleRadian, fWidthAngleRadian, fUnitCircleInnerRadius, aTransformationFromUnitCircle, fAngleSubdivisionRadian );
875
0
    appendAndCloseBezierCoords( aReturn, aInnerArc, true );
876
877
0
    return aReturn;
878
0
}
879
880
rtl::Reference<SvxShapePolyPolygon>
881
        ShapeFactory::createPieSegment2D(
882
                    const rtl::Reference<SvxShapeGroupAnyD>& xTarget
883
                    , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree
884
                    , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius
885
                    , const drawing::Direction3D& rOffset
886
                    , const drawing::HomogenMatrix& rUnitCircleToScene )
887
0
{
888
0
    if( !xTarget.is() )
889
0
        return nullptr;
890
891
    // tdf#123504: both 0 and 360 are valid and different values here!
892
0
    while (fUnitCircleWidthAngleDegree > 360)
893
0
        fUnitCircleWidthAngleDegree -= 360.0;
894
0
    while (fUnitCircleWidthAngleDegree < 0)
895
0
        fUnitCircleWidthAngleDegree += 360.0;
896
897
    //create shape
898
0
    rtl::Reference<SvxShapePolyPolygon> xShape = new SvxShapePolyPolygon(nullptr);
899
0
    xShape->setShapeKind(SdrObjKind::PathFill); // aka ClosedBezierShape
900
0
    xTarget->addShape(*xShape); //need to add the shape before setting of properties
901
902
0
    if (std::isnan(fUnitCircleWidthAngleDegree))
903
0
    {
904
0
        SAL_WARN("chart2", "fUnitCircleWidthAngleDegree isNaN");
905
0
        return xShape;
906
0
    }
907
908
    //set properties
909
0
    try
910
0
    {
911
0
        ::basegfx::B2DHomMatrix aTransformationFromUnitCircle( IgnoreZ( HomogenMatrixToB3DHomMatrix(rUnitCircleToScene) ) );
912
0
        aTransformationFromUnitCircle.translate(rOffset.DirectionX,rOffset.DirectionY);
913
914
0
        const double fAngleSubdivisionRadian = M_PI/10.0;
915
916
0
        drawing::PolyPolygonBezierCoords aCoords
917
0
            = getRingBezierCoords(fUnitCircleInnerRadius, fUnitCircleOuterRadius,
918
0
                                  basegfx::deg2rad(fUnitCircleStartAngleDegree),
919
0
                                  basegfx::deg2rad(fUnitCircleWidthAngleDegree),
920
0
                                  aTransformationFromUnitCircle, fAngleSubdivisionRadian);
921
922
0
        xShape->SvxShape::setPropertyValue( u"PolyPolygonBezier"_ustr, uno::Any( aCoords ) );
923
0
    }
924
0
    catch( const uno::Exception& )
925
0
    {
926
0
        TOOLS_WARN_EXCEPTION("chart2", "" );
927
0
    }
928
929
0
    return xShape;
930
0
}
931
932
rtl::Reference<Svx3DExtrudeObject>
933
        ShapeFactory::createPieSegment(
934
                    const rtl::Reference<SvxShapeGroupAnyD>& xTarget
935
                    , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree
936
                    , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius
937
                    , const drawing::Direction3D& rOffset
938
                    , const drawing::HomogenMatrix& rUnitCircleToScene
939
                    , double fDepth )
940
0
{
941
0
    if( !xTarget.is() )
942
0
        return nullptr;
943
944
    // tdf#123504: both 0 and 360 are valid and different values here!
945
0
    while (fUnitCircleWidthAngleDegree > 360)
946
0
        fUnitCircleWidthAngleDegree -= 360.0;
947
0
    while (fUnitCircleWidthAngleDegree < 0)
948
0
        fUnitCircleWidthAngleDegree += 360.0;
949
950
    //create shape
951
0
    rtl::Reference<Svx3DExtrudeObject> xShape = new Svx3DExtrudeObject(nullptr);
952
0
    xShape->setShapeKind(SdrObjKind::E3D_Extrusion);
953
0
    xTarget->addShape(*xShape); //need to add the shape before setting of properties
954
955
    //set properties
956
0
    try
957
0
    {
958
0
        ::basegfx::B2DHomMatrix aTransformationFromUnitCircle( IgnoreZ( HomogenMatrixToB3DHomMatrix(rUnitCircleToScene) ) );
959
0
        aTransformationFromUnitCircle.translate(rOffset.DirectionX,rOffset.DirectionY);
960
961
0
        const double fAngleSubdivisionRadian = M_PI/32.0;
962
963
0
        drawing::PolyPolygonBezierCoords aCoords
964
0
            = getRingBezierCoords(fUnitCircleInnerRadius, fUnitCircleOuterRadius,
965
0
                                  basegfx::deg2rad(fUnitCircleStartAngleDegree),
966
0
                                  basegfx::deg2rad(fUnitCircleWidthAngleDegree),
967
0
                                  aTransformationFromUnitCircle, fAngleSubdivisionRadian);
968
969
        //depth
970
0
        xShape->setPropertyValue( UNO_NAME_3D_EXTRUDE_DEPTH
971
0
            , uno::Any(static_cast<sal_Int32>(fDepth)) );
972
973
        //PercentDiagonal
974
0
        xShape->setPropertyValue( UNO_NAME_3D_PERCENT_DIAGONAL
975
0
            , uno::Any( sal_Int16(0) ) );
976
977
        //Polygon
978
0
        drawing::PolyPolygonShape3D aPoly( BezierToPoly(aCoords) );
979
0
        ShapeFactory::closePolygon( aPoly );
980
0
        xShape->setPropertyValue( UNO_NAME_3D_POLYPOLYGON3D
981
0
            , uno::Any( aPoly ) );
982
983
        //DoubleSided
984
0
        xShape->setPropertyValue( UNO_NAME_3D_DOUBLE_SIDED
985
0
            , uno::Any( true ) );
986
987
        //Reduced lines
988
0
        xShape->setPropertyValue( UNO_NAME_3D_REDUCED_LINE_GEOMETRY
989
0
            , uno::Any( true ) );
990
991
        //TextureProjectionMode
992
0
        xShape->setPropertyValue( UNO_NAME_3D_TEXTURE_PROJ_Y
993
0
            , uno::Any( drawing::TextureProjectionMode_OBJECTSPECIFIC ) );
994
995
        //TextureProjectionMode
996
0
        xShape->setPropertyValue( UNO_NAME_3D_TEXTURE_PROJ_X
997
0
            , uno::Any( drawing::TextureProjectionMode_PARALLEL ) );
998
0
        xShape->setPropertyValue( UNO_NAME_3D_TEXTURE_PROJ_Y
999
0
            , uno::Any( drawing::TextureProjectionMode_OBJECTSPECIFIC ) );
1000
0
    }
1001
0
    catch( const uno::Exception& )
1002
0
    {
1003
0
        TOOLS_WARN_EXCEPTION("chart2", "" );
1004
0
    }
1005
0
    return xShape;
1006
0
}
1007
1008
rtl::Reference<Svx3DPolygonObject>
1009
        ShapeFactory::createStripe( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
1010
                    , const Stripe& rStripe
1011
                    , const uno::Reference< beans::XPropertySet >& xSourceProp
1012
                    , const tPropertyNameMap& rPropertyNameMap
1013
                    , bool bDoubleSided
1014
                    , short nRotatedTexture
1015
                    , bool bFlatNormals )
1016
0
{
1017
0
    if( !xTarget.is() )
1018
0
        return nullptr;
1019
1020
    //create shape
1021
0
    rtl::Reference<Svx3DPolygonObject> xShape = new Svx3DPolygonObject(nullptr);
1022
0
    xShape->setShapeKind(SdrObjKind::E3D_Polygon);
1023
0
    xTarget->addShape(*xShape);
1024
1025
    //set properties
1026
0
    try
1027
0
    {
1028
0
        uno::Sequence<OUString> aPropertyNames{
1029
0
            UNO_NAME_3D_POLYPOLYGON3D,
1030
0
            UNO_NAME_3D_TEXTUREPOLYGON3D,
1031
0
            UNO_NAME_3D_NORMALSPOLYGON3D,
1032
0
            UNO_NAME_3D_LINEONLY,
1033
0
            UNO_NAME_3D_DOUBLE_SIDED
1034
0
        };
1035
1036
0
        uno::Sequence<uno::Any> aPropertyValues {
1037
0
            rStripe.getPolyPolygonShape3D(),            // Polygon
1038
0
            Stripe::getTexturePolygon(nRotatedTexture), // TexturePolygon
1039
0
            rStripe.getNormalsPolygon(),                // Normals Polygon
1040
0
            uno::Any(false),        // LineOnly
1041
0
            uno::Any(bDoubleSided)  // DoubleSided
1042
0
        };
1043
1044
        //NormalsKind
1045
0
        if (bFlatNormals)
1046
0
            lcl_addProperty(aPropertyNames, aPropertyValues,
1047
0
                            UNO_NAME_3D_NORMALS_KIND, uno::Any(drawing::NormalsKind_FLAT));
1048
1049
0
        xShape->setPropertyValues(aPropertyNames, aPropertyValues);
1050
1051
0
        if (xSourceProp)
1052
0
        {
1053
0
            PropertyMapper::setMappedProperties(*xShape, xSourceProp, rPropertyNameMap);
1054
0
        }
1055
0
    }
1056
0
    catch( const uno::Exception& )
1057
0
    {
1058
0
        TOOLS_WARN_EXCEPTION("chart2", "" );
1059
0
    }
1060
0
    return xShape;
1061
0
}
1062
1063
rtl::Reference<Svx3DExtrudeObject>
1064
        ShapeFactory::createArea3D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
1065
                    , const std::vector<std::vector<css::drawing::Position3D>>& rPolyPolygon
1066
                    , double fDepth )
1067
0
{
1068
0
    if( !xTarget.is() )
1069
0
        return nullptr;
1070
1071
0
    if( rPolyPolygon.empty() )
1072
0
        return nullptr;
1073
1074
    //create shape
1075
0
    rtl::Reference<Svx3DExtrudeObject> xShape = new Svx3DExtrudeObject(nullptr);
1076
0
    xShape->setShapeKind(SdrObjKind::E3D_Extrusion);
1077
0
    xTarget->addShape(*xShape);
1078
1079
0
    css::drawing::PolyPolygonShape3D aUnoPolyPolygon = toPolyPolygonShape3D(rPolyPolygon);
1080
1081
    //set properties
1082
0
    try
1083
0
    {
1084
0
        uno::Sequence<OUString> aPropertyNames{
1085
0
            UNO_NAME_3D_EXTRUDE_DEPTH,
1086
0
            UNO_NAME_3D_PERCENT_DIAGONAL,
1087
0
            UNO_NAME_3D_POLYPOLYGON3D,
1088
0
            UNO_NAME_3D_DOUBLE_SIDED,
1089
0
        };
1090
1091
0
        uno::Sequence<uno::Any> aPropertyValues {
1092
0
            uno::Any(sal_Int32(fDepth)), // depth
1093
0
            uno::Any(sal_Int16(0)),      // PercentDiagonal
1094
0
            uno::Any(aUnoPolyPolygon),      // Polygon
1095
0
            uno::Any(true)               // DoubleSided
1096
0
        };
1097
1098
        //the z component of the polygon is now ignored by the drawing layer,
1099
        //so we need to translate the object via transformation matrix
1100
1101
        //Matrix for position
1102
0
        if (!rPolyPolygon[0].empty())
1103
0
        {
1104
0
            basegfx::B3DHomMatrix aM;
1105
0
            aM.translate(0, 0, rPolyPolygon[0][0].PositionZ);
1106
0
            drawing::HomogenMatrix aHM = B3DHomMatrixToHomogenMatrix(aM);
1107
0
            lcl_addProperty(aPropertyNames, aPropertyValues, UNO_NAME_3D_TRANSFORM_MATRIX, uno::Any(aHM));
1108
0
        }
1109
0
        xShape->setPropertyValues(aPropertyNames, aPropertyValues);
1110
0
    }
1111
0
    catch( const uno::Exception& )
1112
0
    {
1113
0
        TOOLS_WARN_EXCEPTION("chart2", "" );
1114
0
    }
1115
0
    return xShape;
1116
0
}
1117
1118
rtl::Reference<SvxShapePolyPolygon>
1119
        ShapeFactory::createArea2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
1120
                    , const std::vector<std::vector<css::drawing::Position3D>>& rPolyPolygon
1121
                    , const std::vector<std::vector<css::drawing::Position3D>>* pClipPolyPolygon )
1122
0
{
1123
0
    if( !xTarget.is() )
1124
0
        return nullptr;
1125
1126
    //create shape
1127
0
    rtl::Reference<SdrPathObj> pPath = new SdrPathObj(xTarget->GetSdrObject()->getSdrModelFromSdrObject(), SdrObjKind::Polygon);
1128
0
    xTarget->GetSdrObject()->GetSubList()->InsertObject(pPath.get());
1129
1130
    //set properties
1131
0
    try
1132
0
    {
1133
        // Polygon
1134
0
        basegfx::B2DPolyPolygon aNewPolyPolygon( PolyToB2DPolyPolygon(rPolyPolygon) );
1135
        // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm
1136
0
        pPath->ForceMetricToItemPoolMetric(aNewPolyPolygon);
1137
0
        pPath->SetPathPoly(aNewPolyPolygon);
1138
1139
0
        if (pClipPolyPolygon && !pClipPolyPolygon->empty())
1140
0
        {
1141
0
            basegfx::B2DPolyPolygon aClipPolyPolygon( PolyToB2DPolyPolygon(*pClipPolyPolygon) );
1142
0
            pPath->ForceMetricToItemPoolMetric(aClipPolyPolygon);
1143
0
            pPath->SetClipPoly(aClipPolyPolygon);
1144
0
        }
1145
0
    }
1146
0
    catch( const uno::Exception& )
1147
0
    {
1148
0
        TOOLS_WARN_EXCEPTION("chart2", "" );
1149
0
    }
1150
0
    return static_cast<SvxShapePolyPolygon*>(pPath->getUnoShape().get());
1151
0
}
1152
1153
static drawing::PointSequenceSequence createPolyPolygon_Symbol( const drawing::Position3D& rPos
1154
                                 , const drawing::Direction3D& rSize
1155
                                 , sal_Int32 nStandardSymbol )
1156
0
{
1157
0
    if(nStandardSymbol<0)
1158
0
        nStandardSymbol*=-1;
1159
0
    nStandardSymbol = nStandardSymbol%ShapeFactory::getSymbolCount();
1160
0
    SymbolEnum eSymbolType=static_cast<SymbolEnum>(nStandardSymbol);
1161
1162
0
    const double& fX = rPos.PositionX;
1163
0
    const double& fY = rPos.PositionY;
1164
1165
0
    const double fWidthH  = rSize.DirectionX/2.0; //fWidthH stands for Half Width
1166
0
    const double fHeightH = rSize.DirectionY/2.0; //fHeightH stands for Half Height
1167
1168
0
    const sal_Int32 nQuarterCount = 35; // points inside a quadrant, used in case circle
1169
1170
0
    sal_Int32 nPointCount = 4; //all arrow symbols only need 4 points
1171
0
    switch( eSymbolType )
1172
0
    {
1173
0
        case Symbol_Square:
1174
0
        case Symbol_Diamond:
1175
0
        case Symbol_Bowtie:
1176
0
        case Symbol_Sandglass:
1177
0
        case Symbol_HorizontalBar:
1178
0
        case Symbol_VerticalBar:
1179
0
            nPointCount = 5;
1180
0
            break;
1181
0
        case Symbol_X:
1182
0
        case Symbol_Plus:
1183
0
            nPointCount = 13;
1184
0
            break;
1185
0
        case Symbol_Star:
1186
0
            nPointCount = 9;
1187
0
            break;
1188
0
        case Symbol_Asterisk:
1189
0
            nPointCount = 19;
1190
0
            break;
1191
0
        case Symbol_Circle:
1192
0
            nPointCount = 5 + 4 * nQuarterCount;
1193
0
            break;
1194
0
        default:
1195
0
            break;
1196
0
    }
1197
1198
0
    drawing::PointSequenceSequence aPP;
1199
1200
0
    aPP.realloc(1);
1201
1202
0
    uno::Sequence<awt::Point>* pOuterSequence = aPP.getArray();
1203
1204
0
    pOuterSequence->realloc(nPointCount);
1205
1206
0
    awt::Point* pInnerSequence = pOuterSequence->getArray();
1207
1208
0
    auto toPoint = [](double x, double y) -> awt::Point
1209
0
        {
1210
0
            return { static_cast<sal_Int32>(x), static_cast<sal_Int32>(y) };
1211
0
        };
1212
0
    switch(eSymbolType)
1213
0
    {
1214
0
        case Symbol_Square:
1215
0
        {
1216
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH );
1217
1218
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY+fHeightH );
1219
1220
0
            *pInnerSequence++ = toPoint( fX+fWidthH, fY+fHeightH );
1221
1222
0
            *pInnerSequence++ = toPoint( fX+fWidthH, fY-fHeightH );
1223
1224
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH );
1225
0
            break;
1226
0
        }
1227
0
        case Symbol_UpArrow:
1228
0
        {
1229
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY+fHeightH );
1230
1231
0
            *pInnerSequence++ = toPoint( fX+fWidthH, fY+fHeightH );
1232
1233
0
            *pInnerSequence++ = toPoint( fX, fY-fHeightH );
1234
1235
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY+fHeightH );
1236
0
            break;
1237
0
        }
1238
0
        case Symbol_DownArrow:
1239
0
        {
1240
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH );
1241
1242
0
            *pInnerSequence++ = toPoint( fX, fY+fHeightH );
1243
1244
0
            *pInnerSequence++ = toPoint( fX+fWidthH, fY-fHeightH );
1245
1246
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH );
1247
0
            break;
1248
0
        }
1249
0
        case Symbol_RightArrow:
1250
0
        {
1251
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH );
1252
1253
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY+fHeightH  );
1254
1255
0
            *pInnerSequence++ = toPoint( fX+fWidthH, fY );
1256
1257
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH );
1258
0
            break;
1259
0
        }
1260
0
        case Symbol_LeftArrow:
1261
0
        {
1262
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY );
1263
1264
0
            *pInnerSequence++ = toPoint( fX+fWidthH, fY+fHeightH );
1265
1266
0
            *pInnerSequence++ = toPoint( fX+fWidthH, fY-fHeightH );
1267
1268
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY );
1269
0
            break;
1270
0
        }
1271
0
        case Symbol_Bowtie:
1272
0
        {
1273
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH );
1274
1275
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY+fHeightH );
1276
1277
0
            *pInnerSequence++ = toPoint( fX+fWidthH, fY-fHeightH );
1278
1279
0
            *pInnerSequence++ = toPoint( fX+fWidthH, fY+fHeightH );
1280
1281
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH );
1282
0
            break;
1283
0
        }
1284
0
        case Symbol_Sandglass:
1285
0
        {
1286
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY+fHeightH );
1287
1288
0
            *pInnerSequence++ = toPoint( fX+fWidthH, fY+fHeightH );
1289
1290
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH );
1291
1292
0
            *pInnerSequence++ = toPoint( fX+fWidthH, fY-fHeightH );
1293
1294
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY+fHeightH );
1295
0
            break;
1296
0
        }
1297
0
        case Symbol_Diamond:
1298
0
        {
1299
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY );
1300
1301
0
            *pInnerSequence++ = toPoint( fX, fY+fHeightH );
1302
1303
0
            *pInnerSequence++ = toPoint( fX+fWidthH, fY );
1304
1305
0
            *pInnerSequence++ = toPoint( fX, fY-fHeightH );
1306
1307
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY );
1308
0
            break;
1309
0
        }
1310
0
        case Symbol_HorizontalBar:
1311
0
        {
1312
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY-0.2*fHeightH );
1313
1314
0
            *pInnerSequence++ = toPoint( fX+fWidthH, fY-0.2*fHeightH );
1315
1316
0
            *pInnerSequence++ = toPoint( fX+fWidthH, fY+0.2*fHeightH );
1317
1318
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY+0.2*fHeightH );
1319
1320
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY-0.2*fHeightH );
1321
0
            break;
1322
0
        }
1323
0
        case Symbol_VerticalBar:
1324
0
        {
1325
0
            *pInnerSequence++ = toPoint( fX-0.2*fWidthH, fY-fHeightH );
1326
1327
0
            *pInnerSequence++ = toPoint( fX+0.2*fWidthH, fY-fHeightH );
1328
1329
0
            *pInnerSequence++ = toPoint( fX+0.2*fWidthH, fY+fHeightH );
1330
1331
0
            *pInnerSequence++ = toPoint( fX-0.2*fWidthH, fY+fHeightH );
1332
1333
0
            *pInnerSequence++ = toPoint( fX-0.2*fWidthH, fY-fHeightH );
1334
1335
0
            break;
1336
0
        }
1337
0
        case Symbol_Circle:
1338
0
        {
1339
0
            double fOmega = M_PI_2 / (nQuarterCount + 1.0);
1340
            // one point in the middle of each edge to get full size bounding rectangle
1341
0
            *pInnerSequence++ = toPoint( fX + fWidthH, fY );
1342
            // 0 to PI/2
1343
0
            for (sal_Int32 i = 1; i <= nQuarterCount; ++i)
1344
0
            {
1345
0
                *pInnerSequence++ = toPoint( fX + fWidthH * cos( i * fOmega ), fY - fHeightH * sin( i * fOmega ) );
1346
0
            }
1347
            // PI/2 to PI
1348
0
            *pInnerSequence++ = toPoint( fX, fY - fHeightH );
1349
0
            for (sal_Int32 i = 1; i <= nQuarterCount; ++i)
1350
0
            {
1351
0
                *pInnerSequence++ = toPoint( fX - fWidthH * sin( i * fOmega), fY - fHeightH * cos( i * fOmega) );
1352
0
            }
1353
            // PI to 3/2*PI
1354
0
            *pInnerSequence++ = toPoint( fX - fWidthH, fY );
1355
0
            for (sal_Int32 i = 1; i <= nQuarterCount; ++i)
1356
0
            {
1357
0
                *pInnerSequence++ = toPoint( fX - fWidthH * cos( i * fOmega), fY + fHeightH * sin( i * fOmega) );
1358
0
            }
1359
            // 3/2*PI to 2*PI
1360
0
            *pInnerSequence++ = toPoint( fX, fY + fHeightH );
1361
0
            for (sal_Int32 i = 1; i <= nQuarterCount; ++i)
1362
0
            {
1363
0
                *pInnerSequence++ = toPoint( fX + fWidthH * sin(i * fOmega), fY + fHeightH * cos(i * fOmega) );
1364
0
            }
1365
            // close polygon
1366
0
            *pInnerSequence++ = toPoint( fX + fWidthH, fY );
1367
0
            break;
1368
0
        }
1369
0
        case Symbol_Star:
1370
0
        {
1371
0
            *pInnerSequence++ = toPoint( fX, fY-fHeightH );
1372
1373
0
            *pInnerSequence++ = toPoint( fX+0.2*fWidthH, fY-0.2*fHeightH );
1374
1375
0
            *pInnerSequence++ = toPoint( fX+fWidthH, fY );
1376
1377
0
            *pInnerSequence++ = toPoint( fX+0.2*fWidthH, fY+0.2*fHeightH );
1378
1379
0
            *pInnerSequence++ = toPoint( fX, fY+fHeightH );
1380
1381
0
            *pInnerSequence++ = toPoint( fX-0.2*fWidthH, fY+0.2*fHeightH );
1382
1383
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY );
1384
1385
0
            *pInnerSequence++ = toPoint( fX-0.2*fWidthH, fY-0.2*fHeightH );
1386
1387
0
            *pInnerSequence++ = toPoint( fX, fY-fHeightH );
1388
0
            break;
1389
0
        }
1390
0
        case Symbol_X:
1391
0
        {
1392
0
            const double fScaleX = fWidthH / 128.0;
1393
0
            const double fScaleY = fHeightH / 128.0;
1394
0
            constexpr double fSmall = std::numbers::sqrt2 * 10;
1395
0
            constexpr double fLarge = 128.0 - fSmall;
1396
1397
0
            *pInnerSequence++ = toPoint( fX, fY - fScaleY * fSmall );
1398
1399
0
            *pInnerSequence++ = toPoint( fX - fScaleX * fLarge, fY - fHeightH );
1400
1401
0
            *pInnerSequence++ = toPoint( fX - fWidthH, fY - fScaleY * fLarge );
1402
1403
0
            *pInnerSequence++ = toPoint( fX - fScaleX * fSmall, fY );
1404
1405
0
            *pInnerSequence++ = toPoint( fX - fWidthH, fY + fScaleY * fLarge );
1406
1407
0
            *pInnerSequence++ = toPoint( fX - fScaleX * fLarge, fY + fHeightH );
1408
1409
0
            *pInnerSequence++ = toPoint( fX, fY + fScaleY * fSmall );
1410
1411
0
            *pInnerSequence++ = toPoint( fX + fScaleX * fLarge, fY + fHeightH );
1412
1413
0
            *pInnerSequence++ = toPoint( fX + fWidthH, fY + fScaleY * fLarge );
1414
1415
0
            *pInnerSequence++ = toPoint( fX + fScaleX * fSmall, fY );
1416
1417
0
            *pInnerSequence++ = toPoint( fX + fWidthH, fY - fScaleY * fLarge );
1418
1419
0
            *pInnerSequence++ = toPoint( fX + fScaleX * fLarge, fY - fHeightH );
1420
1421
0
            *pInnerSequence++ = toPoint( fX, fY - fScaleY * fSmall );
1422
0
            break;
1423
1424
0
        }
1425
0
        case Symbol_Plus:
1426
0
        {
1427
0
            const double fScaleX = fWidthH / 128.0;
1428
0
            const double fScaleY = fHeightH / 128.0;
1429
0
            constexpr double fHalf = 10.0; //half line width on 256 size square
1430
0
            const double fdX = fScaleX * fHalf;
1431
0
            const double fdY = fScaleY * fHalf;
1432
1433
0
            *pInnerSequence++ = toPoint( fX-fdX, fY-fHeightH );
1434
1435
0
            *pInnerSequence++ = toPoint( fX-fdX, fY-fdY );
1436
1437
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY-fdY );
1438
1439
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY+fdY );
1440
1441
0
            *pInnerSequence++ = toPoint( fX-fdX, fY+fdY );
1442
1443
0
            *pInnerSequence++ = toPoint( fX-fdX, fY+fHeightH );
1444
1445
0
            *pInnerSequence++ = toPoint( fX+fdX, fY+fHeightH );
1446
1447
0
            *pInnerSequence++ = toPoint( fX+fdX, fY+fdY );
1448
1449
0
            *pInnerSequence++ = toPoint( fX+fWidthH, fY+fdY );
1450
1451
0
            *pInnerSequence++ = toPoint( fX+fWidthH, fY-fdY );
1452
1453
0
            *pInnerSequence++ = toPoint( fX+fdX, fY-fdY );
1454
1455
0
            *pInnerSequence++ = toPoint( fX+fdY, fY-fHeightH );
1456
1457
0
            *pInnerSequence++ = toPoint( fX-fdX, fY-fHeightH );
1458
0
            break;
1459
1460
0
        }
1461
0
        case Symbol_Asterisk:
1462
0
        {
1463
0
            constexpr double fHalf = 10.0; // half line width on 256 size square
1464
0
            constexpr double fTwoY = fHalf * std::numbers::sqrt3;
1465
0
            constexpr double fFourY = (128.0 - 2.0 * fHalf ) * std::numbers::inv_sqrt3;
1466
0
            constexpr double fThreeX = 128.0 - fHalf;
1467
0
            constexpr double fThreeY = fHalf * std::numbers::sqrt3 + fFourY;
1468
0
            constexpr double fFiveX = 2.0 * fHalf;
1469
1470
0
            const double fScaleX = fWidthH / 128.0;
1471
0
            const double fScaleY = fHeightH / 128.0;
1472
1473
            //1
1474
0
            *pInnerSequence++ = toPoint( fX-fScaleX * fHalf, fY-fHeightH );
1475
            //2
1476
0
            *pInnerSequence++ = toPoint( fX-fScaleX * fHalf, fY-fScaleY * fTwoY );
1477
            //3
1478
0
            *pInnerSequence++ = toPoint( fX-fScaleX * fThreeX, fY-fScaleY * fThreeY );
1479
            //4
1480
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY-fScaleY * fFourY );
1481
            //5
1482
0
            *pInnerSequence++ = toPoint( fX-fScaleX * fFiveX, fY );
1483
            //6 as 4
1484
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY+fScaleY * fFourY );
1485
            //7 as 3
1486
0
            *pInnerSequence++ = toPoint( fX-fScaleX * fThreeX, fY+fScaleY * fThreeY );
1487
            //8 as 2
1488
0
            *pInnerSequence++ = toPoint( fX-fScaleX * fHalf, fY+fScaleY * fTwoY );
1489
            //9 as 1
1490
0
            *pInnerSequence++ = toPoint( fX-fScaleX * fHalf, fY+fHeightH );
1491
            //10 as 1
1492
0
            *pInnerSequence++ = toPoint( fX+fScaleX * fHalf, fY+fHeightH );
1493
            //11 as 2
1494
0
            *pInnerSequence++ = toPoint( fX+fScaleX * fHalf, fY+fScaleY * fTwoY );
1495
            //12 as 3
1496
0
            *pInnerSequence++ = toPoint( fX+fScaleX * fThreeX, fY+fScaleY * fThreeY );
1497
            //13 as 4
1498
0
            *pInnerSequence++ = toPoint( fX+fWidthH, fY+fScaleY * fFourY );
1499
            //14 as 5
1500
0
            *pInnerSequence++ = toPoint( fX+fScaleX * fFiveX, fY );
1501
            //15 as 4
1502
0
            *pInnerSequence++ = toPoint( fX+fWidthH, fY-fScaleY * fFourY );
1503
            //16 as 3
1504
0
            *pInnerSequence++ = toPoint( fX+fScaleX * fThreeX, fY-fScaleY * fThreeY );
1505
            //17 as 2
1506
0
            *pInnerSequence++ = toPoint( fX+fScaleX * fHalf, fY-fScaleY * fTwoY );
1507
            // 18 as 1
1508
0
            *pInnerSequence++ = toPoint( fX+fScaleX * fHalf, fY-fHeightH );
1509
            // 19 = 1, closing
1510
0
            *pInnerSequence++ = toPoint( fX-fScaleX * fHalf, fY-fHeightH );
1511
0
            break;
1512
0
        }
1513
0
        default: //case Symbol_Square:
1514
0
        {
1515
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH );
1516
1517
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY+fHeightH );
1518
1519
0
            *pInnerSequence++ = toPoint( fX+fWidthH, fY+fHeightH );
1520
1521
0
            *pInnerSequence++ = toPoint( fX+fWidthH, fY-fHeightH );
1522
1523
0
            *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH );
1524
0
            break;
1525
0
        }
1526
0
    }
1527
1528
0
    return aPP;
1529
0
}
1530
1531
rtl::Reference<SvxShapePolyPolygon>
1532
        ShapeFactory::createSymbol2D(
1533
                      const rtl::Reference<SvxShapeGroupAnyD>& xTarget
1534
                    , const drawing::Position3D& rPosition
1535
                    , const drawing::Direction3D& rSize
1536
                    , sal_Int32 nStandardSymbol
1537
                    , sal_Int32 nBorderColor
1538
                    , sal_Int32 nFillColor )
1539
0
{
1540
0
    if( !xTarget.is() )
1541
0
        return nullptr;
1542
1543
    //create shape
1544
0
    rtl::Reference<SvxShapePolyPolygon> xShape = new SvxShapePolyPolygon(nullptr);
1545
0
    xShape->setShapeKind(SdrObjKind::Polygon);
1546
0
    xTarget->addShape(*xShape);
1547
1548
    //set properties
1549
0
    try
1550
0
    {
1551
0
        drawing::PointSequenceSequence aPoints =
1552
0
            createPolyPolygon_Symbol( rPosition, rSize, nStandardSymbol );
1553
1554
        //Polygon
1555
0
        xShape->SvxShape::setPropertyValue( UNO_NAME_POLYPOLYGON
1556
0
            , uno::Any( aPoints ) );
1557
1558
        //LineColor
1559
0
        xShape->SvxShape::setPropertyValue( UNO_NAME_LINECOLOR
1560
0
            , uno::Any( nBorderColor ) );
1561
1562
        //FillColor
1563
0
        xShape->SvxShape::setPropertyValue( UNO_NAME_FILLCOLOR
1564
0
            , uno::Any( nFillColor ) );
1565
0
    }
1566
0
    catch( const uno::Exception& )
1567
0
    {
1568
0
        TOOLS_WARN_EXCEPTION("chart2", "" );
1569
0
    }
1570
0
    return xShape;
1571
0
}
1572
1573
rtl::Reference<SvxGraphicObject>
1574
        ShapeFactory::createGraphic2D(
1575
                      const rtl::Reference<SvxShapeGroupAnyD>& xTarget
1576
                    , const drawing::Position3D& rPosition
1577
                    , const drawing::Direction3D& rSize
1578
                    , const uno::Reference< graphic::XGraphic >& xGraphic )
1579
0
{
1580
0
    if( !xTarget.is() || !xGraphic.is() )
1581
0
        return nullptr;
1582
1583
    // @todo: change this to a rectangle shape with a fill bitmap for
1584
    // performance reasons (ask AW, said CL)
1585
1586
    //create shape
1587
0
    rtl::Reference<SvxGraphicObject> xShape = new SvxGraphicObject(nullptr);
1588
0
    xShape->setShapeKind(SdrObjKind::Graphic);
1589
0
    xTarget->addShape(*xShape);
1590
1591
0
    try
1592
0
    {
1593
        // assume position is upper left corner. Transform to center.
1594
0
        drawing::Position3D aCenterPosition(
1595
0
            rPosition.PositionX - (rSize.DirectionX / 2.0),
1596
0
            rPosition.PositionY - (rSize.DirectionY / 2.0),
1597
0
            rPosition.PositionZ );
1598
0
        xShape->setPosition( Position3DToAWTPoint( aCenterPosition ));
1599
0
        xShape->setSize( Direction3DToAWTSize( rSize ));
1600
0
    }
1601
0
    catch( const uno::Exception & )
1602
0
    {
1603
0
        TOOLS_WARN_EXCEPTION("chart2", "" );
1604
0
    }
1605
0
    try
1606
0
    {
1607
0
        xShape->SvxShape::setPropertyValue( u"Graphic"_ustr, uno::Any( xGraphic ));
1608
0
    }
1609
0
    catch( const uno::Exception& )
1610
0
    {
1611
0
        TOOLS_WARN_EXCEPTION("chart2", "" );
1612
0
    }
1613
0
    return xShape;
1614
0
}
1615
1616
rtl::Reference< SvxShapeGroup >
1617
        ShapeFactory::createGroup2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
1618
        , const OUString& aName )
1619
0
{
1620
0
    if( !xTarget.is() )
1621
0
        return nullptr;
1622
0
    try
1623
0
    {
1624
        //create and add to target
1625
0
        rtl::Reference<SvxShapeGroup> xShapeGroup = new SvxShapeGroup(nullptr, nullptr);
1626
0
        xShapeGroup->setShapeKind(SdrObjKind::Group);
1627
        // cast to resolve ambiguity in converting to XShape
1628
0
        xTarget->addShape(*xShapeGroup);
1629
1630
        //set name
1631
0
        if(!aName.isEmpty())
1632
0
            setShapeName( xShapeGroup, aName );
1633
1634
0
        {//workaround
1635
            //need this null size as otherwise empty group shapes where painted with a gray border
1636
0
            xShapeGroup->setSize(awt::Size(0,0));
1637
0
        }
1638
1639
0
        return xShapeGroup;
1640
0
    }
1641
0
    catch( const uno::Exception& )
1642
0
    {
1643
0
        TOOLS_WARN_EXCEPTION("chart2", "" );
1644
0
    }
1645
0
    return nullptr;
1646
0
}
1647
1648
rtl::Reference< SvxShapeGroup >
1649
        ShapeFactory::createGroup2D( const rtl::Reference<SvxDrawPage>& xTarget
1650
        , const OUString& aName )
1651
0
{
1652
0
    if( !xTarget.is() )
1653
0
        return nullptr;
1654
0
    try
1655
0
    {
1656
        //create and add to target
1657
0
        rtl::Reference<SvxShapeGroup> xShapeGroup = new SvxShapeGroup(nullptr, nullptr);
1658
0
        xShapeGroup->setShapeKind(SdrObjKind::Group);
1659
        // cast to resolve ambiguity in converting to XShape
1660
0
        xTarget->add(static_cast<SvxShape*>(xShapeGroup.get()));
1661
1662
        //set name
1663
0
        if(!aName.isEmpty())
1664
0
            setShapeName( xShapeGroup, aName );
1665
1666
0
        {//workaround
1667
            //need this null size as otherwise empty group shapes where painted with a gray border
1668
0
            xShapeGroup->setSize(awt::Size(0,0));
1669
0
        }
1670
1671
0
        return xShapeGroup;
1672
0
    }
1673
0
    catch( const uno::Exception& )
1674
0
    {
1675
0
        TOOLS_WARN_EXCEPTION("chart2", "" );
1676
0
    }
1677
0
    return nullptr;
1678
0
}
1679
1680
rtl::Reference<Svx3DSceneObject>
1681
        ShapeFactory::createGroup3D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
1682
        , const OUString& aName )
1683
0
{
1684
0
    if( !xTarget.is() )
1685
0
        return nullptr;
1686
0
    try
1687
0
    {
1688
        //create shape
1689
0
        rtl::Reference<Svx3DSceneObject> xShape = new Svx3DSceneObject(nullptr, nullptr);
1690
0
        xShape->setShapeKind(SdrObjKind::E3D_Scene);
1691
0
        xTarget->addShape(*xShape);
1692
1693
        //it is necessary to set the transform matrix to initialize the scene properly
1694
        //otherwise all objects which are placed into this Group will not be visible
1695
        //the following should be unnecessary after the bug is fixed
1696
        //set properties
1697
0
        try
1698
0
        {
1699
0
            ::basegfx::B3DHomMatrix aM;
1700
0
            xShape->SvxShape::setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX
1701
0
                , uno::Any(B3DHomMatrixToHomogenMatrix(aM)) );
1702
0
        }
1703
0
        catch( const uno::Exception& )
1704
0
        {
1705
0
            TOOLS_WARN_EXCEPTION("chart2", "" );
1706
0
        }
1707
1708
        //set name
1709
0
        if(!aName.isEmpty())
1710
0
            setShapeName( xShape , aName );
1711
1712
        //return
1713
0
        return xShape;
1714
0
    }
1715
0
    catch( const uno::Exception& )
1716
0
    {
1717
0
        TOOLS_WARN_EXCEPTION("chart2", "" );
1718
0
    }
1719
0
    return nullptr;
1720
0
}
1721
1722
rtl::Reference<SvxShapeCircle>
1723
        ShapeFactory::createCircle2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
1724
                    , const drawing::Position3D& rPosition
1725
                    , const drawing::Direction3D& rSize )
1726
0
{
1727
0
    if( !xTarget.is() )
1728
0
        return nullptr;
1729
1730
    //create shape
1731
0
    rtl::Reference<SvxShapeCircle> xShape = new SvxShapeCircle(nullptr);
1732
0
    xShape->setShapeKind(SdrObjKind::CircleOrEllipse);
1733
0
    xTarget->addShape(*xShape);
1734
1735
0
    try
1736
0
    {
1737
0
        drawing::Position3D aCenterPosition(
1738
0
            rPosition.PositionX - (rSize.DirectionX / 2.0),
1739
0
            rPosition.PositionY - (rSize.DirectionY / 2.0),
1740
0
            rPosition.PositionZ );
1741
0
        xShape->setPosition( Position3DToAWTPoint( aCenterPosition ));
1742
0
        xShape->setSize( Direction3DToAWTSize( rSize ));
1743
0
    }
1744
0
    catch( const uno::Exception & )
1745
0
    {
1746
0
        TOOLS_WARN_EXCEPTION("chart2", "" );
1747
0
    }
1748
1749
    //set properties
1750
0
    try
1751
0
    {
1752
0
        xShape->SvxShape::setPropertyValue( UNO_NAME_CIRCKIND, uno::Any( drawing::CircleKind_FULL ) );
1753
0
    }
1754
0
    catch( const uno::Exception& )
1755
0
    {
1756
0
        TOOLS_WARN_EXCEPTION("chart2", "" );
1757
0
    }
1758
1759
0
    return xShape;
1760
0
}
1761
1762
rtl::Reference<SvxShapeCircle>
1763
    ShapeFactory::createCircle( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
1764
                    , const awt::Size& rSize
1765
                    , const awt::Point& rPosition )
1766
0
{
1767
0
    rtl::Reference<SvxShapeCircle> xShape = new SvxShapeCircle(nullptr);
1768
0
    xShape->setShapeKind(SdrObjKind::CircleOrEllipse);
1769
0
    xTarget->addShape(*xShape);
1770
0
    xShape->setSize( rSize );
1771
0
    xShape->setPosition( rPosition );
1772
1773
0
    return xShape;
1774
0
}
1775
1776
rtl::Reference<Svx3DPolygonObject>
1777
        ShapeFactory::createLine3D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
1778
                    , const std::vector<std::vector<css::drawing::Position3D>>& rPoints
1779
                    , const VLineProperties& rLineProperties )
1780
0
{
1781
0
    if( !xTarget.is() )
1782
0
        return nullptr;
1783
1784
0
    if(rPoints.empty())
1785
0
        return nullptr;
1786
1787
    //create shape
1788
0
    rtl::Reference<Svx3DPolygonObject> xShape = new Svx3DPolygonObject(nullptr);
1789
0
    xShape->setShapeKind(SdrObjKind::E3D_Polygon);
1790
0
    xTarget->addShape(*xShape);
1791
1792
0
    css::drawing::PolyPolygonShape3D aUnoPoly = toPolyPolygonShape3D(rPoints);
1793
1794
    //set properties
1795
0
    try
1796
0
    {
1797
0
        uno::Sequence<OUString> aPropertyNames {
1798
0
            UNO_NAME_3D_POLYPOLYGON3D,
1799
0
            UNO_NAME_3D_LINEONLY
1800
0
        };
1801
1802
0
        uno::Sequence<uno::Any> aPropertyValues {
1803
0
            uno::Any(aUnoPoly),  // Polygon
1804
0
            uno::Any(true)      // LineOnly
1805
0
        };
1806
1807
        //Transparency
1808
0
        if(rLineProperties.Transparence.hasValue())
1809
0
        {
1810
0
            lcl_addProperty(aPropertyNames, aPropertyValues,
1811
0
                            UNO_NAME_LINETRANSPARENCE,
1812
0
                            rLineProperties.Transparence);
1813
0
        }
1814
1815
        //LineStyle
1816
0
        if(rLineProperties.LineStyle.hasValue())
1817
0
        {
1818
0
            lcl_addProperty(aPropertyNames, aPropertyValues,
1819
0
                            UNO_NAME_LINESTYLE,
1820
0
                            rLineProperties.LineStyle);
1821
0
        }
1822
1823
        //LineWidth
1824
0
        if(rLineProperties.Width.hasValue())
1825
0
        {
1826
0
            lcl_addProperty(aPropertyNames, aPropertyValues,
1827
0
                            UNO_NAME_LINEWIDTH,
1828
0
                            rLineProperties.Width);
1829
0
        }
1830
1831
        //LineColor
1832
0
        if(rLineProperties.Color.hasValue())
1833
0
        {
1834
0
            lcl_addProperty(aPropertyNames, aPropertyValues,
1835
0
                            UNO_NAME_LINECOLOR,
1836
0
                            rLineProperties.Color);
1837
0
        }
1838
0
        xShape->setPropertyValues(aPropertyNames, aPropertyValues);
1839
0
    }
1840
0
    catch( const uno::Exception& )
1841
0
    {
1842
0
        TOOLS_WARN_EXCEPTION("chart2", "" );
1843
0
    }
1844
0
    return xShape;
1845
0
}
1846
1847
rtl::Reference<SvxShapePolyPolygon>
1848
        ShapeFactory::createLine2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
1849
                    , const drawing::PointSequenceSequence& rPoints
1850
                    , const VLineProperties* pLineProperties )
1851
0
{
1852
0
    if( !xTarget.is() )
1853
0
        return nullptr;
1854
1855
0
    if(!rPoints.hasElements())
1856
0
        return nullptr;
1857
1858
    //create shape
1859
0
    rtl::Reference<SvxShapePolyPolygon> xShape = new SvxShapePolyPolygon(nullptr);
1860
0
    xShape->setShapeKind(SdrObjKind::PolyLine);
1861
0
    xTarget->addShape(*xShape);
1862
1863
    //set properties
1864
0
    try
1865
0
    {
1866
        //Polygon
1867
0
        xShape->SvxShape::setPropertyValue( UNO_NAME_POLYPOLYGON
1868
0
            , uno::Any( rPoints ) );
1869
1870
0
        if(pLineProperties)
1871
0
        {
1872
            //Transparency
1873
0
            if(pLineProperties->Transparence.hasValue())
1874
0
                xShape->SvxShape::setPropertyValue( UNO_NAME_LINETRANSPARENCE
1875
0
                    , pLineProperties->Transparence );
1876
1877
            //LineStyle
1878
0
            if(pLineProperties->LineStyle.hasValue())
1879
0
                xShape->SvxShape::setPropertyValue( UNO_NAME_LINESTYLE
1880
0
                    , pLineProperties->LineStyle );
1881
1882
            //LineWidth
1883
0
            if(pLineProperties->Width.hasValue())
1884
0
                xShape->SvxShape::setPropertyValue( UNO_NAME_LINEWIDTH
1885
0
                    , pLineProperties->Width );
1886
1887
            //LineColor
1888
0
            if(pLineProperties->Color.hasValue())
1889
0
                xShape->SvxShape::setPropertyValue( UNO_NAME_LINECOLOR
1890
0
                    , pLineProperties->Color );
1891
1892
            //LineDashName
1893
0
            if(pLineProperties->DashName.hasValue())
1894
0
                xShape->SvxShape::setPropertyValue( u"LineDashName"_ustr
1895
0
                    , pLineProperties->DashName );
1896
1897
            //LineCap
1898
0
            if(pLineProperties->LineCap.hasValue())
1899
0
                xShape->SvxShape::setPropertyValue( UNO_NAME_LINECAP
1900
0
                    , pLineProperties->LineCap );
1901
0
        }
1902
0
    }
1903
0
    catch( const uno::Exception& )
1904
0
    {
1905
0
        TOOLS_WARN_EXCEPTION("chart2", "" );
1906
0
    }
1907
0
    return xShape;
1908
0
}
1909
1910
rtl::Reference<SvxShapePolyPolygon>
1911
        ShapeFactory::createLine2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
1912
                    , const std::vector<std::vector<css::drawing::Position3D>>& rPoints
1913
                    , const VLineProperties* pLineProperties )
1914
0
{
1915
0
    if( !xTarget.is() )
1916
0
        return nullptr;
1917
1918
0
    if(rPoints.empty())
1919
0
        return nullptr;
1920
1921
    //create shape
1922
0
    rtl::Reference<SvxShapePolyPolygon> xShape = new SvxShapePolyPolygon(nullptr);
1923
0
    xShape->setShapeKind(SdrObjKind::PolyLine);
1924
0
    xTarget->addShape(*xShape);
1925
1926
0
    drawing::PointSequenceSequence aAnyPoints = PolyToPointSequence(rPoints);
1927
1928
    //set properties
1929
0
    try
1930
0
    {
1931
        //Polygon
1932
0
        xShape->SvxShape::setPropertyValue( UNO_NAME_POLYPOLYGON
1933
0
            , uno::Any( aAnyPoints ) );
1934
1935
0
        if(pLineProperties)
1936
0
        {
1937
            //Transparency
1938
0
            if(pLineProperties->Transparence.hasValue())
1939
0
                xShape->SvxShape::setPropertyValue( UNO_NAME_LINETRANSPARENCE
1940
0
                    , pLineProperties->Transparence );
1941
1942
            //LineStyle
1943
0
            if(pLineProperties->LineStyle.hasValue())
1944
0
                xShape->SvxShape::setPropertyValue( UNO_NAME_LINESTYLE
1945
0
                    , pLineProperties->LineStyle );
1946
1947
            //LineWidth
1948
0
            if(pLineProperties->Width.hasValue())
1949
0
                xShape->SvxShape::setPropertyValue( UNO_NAME_LINEWIDTH
1950
0
                    , pLineProperties->Width );
1951
1952
            //LineColor
1953
0
            if(pLineProperties->Color.hasValue())
1954
0
                xShape->SvxShape::setPropertyValue( UNO_NAME_LINECOLOR
1955
0
                    , pLineProperties->Color );
1956
1957
            //LineDashName
1958
0
            if(pLineProperties->DashName.hasValue())
1959
0
                xShape->SvxShape::setPropertyValue( u"LineDashName"_ustr
1960
0
                    , pLineProperties->DashName );
1961
1962
            //LineCap
1963
0
            if(pLineProperties->LineCap.hasValue())
1964
0
                xShape->SvxShape::setPropertyValue( UNO_NAME_LINECAP
1965
0
                    , pLineProperties->LineCap );
1966
0
        }
1967
0
    }
1968
0
    catch( const uno::Exception& )
1969
0
    {
1970
0
        TOOLS_WARN_EXCEPTION("chart2", "" );
1971
0
    }
1972
0
    return xShape;
1973
0
}
1974
1975
rtl::Reference<SvxShapePolyPolygon>
1976
    ShapeFactory::createLine ( const rtl::Reference<SvxShapeGroupAnyD>& xTarget,
1977
            const awt::Size& rSize, const awt::Point& rPosition )
1978
0
{
1979
    //create shape
1980
0
    rtl::Reference<SvxShapePolyPolygon> xShape = new SvxShapePolyPolygon(nullptr);
1981
0
    xShape->setShapeKind(SdrObjKind::Line);
1982
0
    xTarget->addShape(*xShape);
1983
0
    xShape->setSize( rSize );
1984
0
    xShape->setPosition( rPosition );
1985
1986
0
    return xShape;
1987
0
}
1988
1989
rtl::Reference<SvxShapeRect> ShapeFactory::createInvisibleRectangle(
1990
            const rtl::Reference<SvxShapeGroupAnyD>& xTarget
1991
            , const awt::Size& rSize )
1992
0
{
1993
0
    try
1994
0
    {
1995
0
        if(!xTarget.is())
1996
0
            return nullptr;
1997
1998
0
        rtl::Reference<SvxShapeRect> xShape = new SvxShapeRect(nullptr);
1999
0
        xShape->setShapeKind(SdrObjKind::Rectangle);
2000
0
        xTarget->addShape( *xShape );
2001
0
        ShapeFactory::makeShapeInvisible( xShape );
2002
0
        xShape->setSize( rSize );
2003
0
        return xShape;
2004
0
    }
2005
0
    catch( const uno::Exception & )
2006
0
    {
2007
0
        DBG_UNHANDLED_EXCEPTION("chart2");
2008
0
    }
2009
0
    return nullptr;
2010
0
}
2011
2012
rtl::Reference<SvxShapeRect> ShapeFactory::createRectangle(
2013
    const rtl::Reference<SvxShapeGroupAnyD>& xTarget,
2014
    const awt::Size& rSize,
2015
    const awt::Point& rPosition,
2016
    const tNameSequence& rPropNames,
2017
    const tAnySequence& rPropValues,
2018
    StackPosition ePos )
2019
0
{
2020
0
    rtl::Reference<SvxShapeRect> xShape = new SvxShapeRect(nullptr);
2021
0
    xShape->setShapeKind(SdrObjKind::Rectangle);
2022
0
    if (ePos == StackPosition::Bottom)
2023
0
    {
2024
0
        uno::Reference<drawing::XShapes2> xTarget2(static_cast<cppu::OWeakObject*>(xTarget.get()), uno::UNO_QUERY);
2025
0
        assert(xTarget2);
2026
0
        if (xTarget2.is())
2027
0
            xTarget2->addBottom(xShape);
2028
0
    }
2029
0
    else
2030
0
        xTarget->addShape(*xShape);
2031
2032
0
    xShape->setPosition( rPosition );
2033
0
    xShape->setSize( rSize );
2034
0
    PropertyMapper::setMultiProperties( rPropNames, rPropValues, *xShape );
2035
2036
0
    return xShape;
2037
0
}
2038
2039
rtl::Reference<SvxShapeRect>
2040
    ShapeFactory::createRectangle(
2041
            const rtl::Reference<SvxShapeGroupAnyD>& xTarget )
2042
0
{
2043
0
    rtl::Reference<SvxShapeRect> xShape = new SvxShapeRect(nullptr);
2044
0
    xShape->setShapeKind(SdrObjKind::Rectangle);
2045
0
    xTarget->addShape( *xShape );
2046
2047
0
    return xShape;
2048
0
}
2049
2050
rtl::Reference<SvxShapeText>
2051
        ShapeFactory::createText( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
2052
                    , const OUString& rText
2053
                    , const tNameSequence& rPropNames
2054
                    , const tAnySequence& rPropValues
2055
                    , const uno::Any& rATransformation )
2056
0
{
2057
0
    if( !xTarget.is() )
2058
0
        return nullptr;
2059
2060
0
    if(rText.isEmpty())
2061
0
        return nullptr;
2062
2063
    //create shape and add to page
2064
0
    rtl::Reference<SvxShapeText> xShape = new SvxShapeText(nullptr);
2065
0
    xShape->setShapeKind(SdrObjKind::Text);
2066
0
    xTarget->addShape(*xShape);
2067
2068
    //set text
2069
0
    xShape->setString( rText );
2070
2071
    //set properties
2072
0
    PropertyMapper::setMultiProperties( rPropNames, rPropValues, *xShape );
2073
2074
    //set position matrix
2075
    //the matrix needs to be set at the end behind autogrow and such position influencing properties
2076
0
    try
2077
0
    {
2078
0
        if (rATransformation.hasValue())
2079
0
            xShape->SvxShape::setPropertyValue( u"Transformation"_ustr, rATransformation );
2080
0
        else
2081
0
            SAL_INFO("chart2", "No rATransformation value is given to ShapeFactory::createText()");
2082
2083
0
    }
2084
0
    catch( const uno::Exception& )
2085
0
    {
2086
0
        TOOLS_WARN_EXCEPTION("chart2", "" );
2087
0
    }
2088
0
    return xShape;
2089
0
}
2090
2091
rtl::Reference<SvxShapeText>
2092
    ShapeFactory::createText( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
2093
                , const uno::Sequence< uno::Reference< chart2::XFormattedString > >& xFormattedString
2094
                , const tNameSequence& rPropNames
2095
                , const tAnySequence& rPropValues
2096
                , const uno::Any& rATransformation )
2097
0
{
2098
0
    if( !xTarget.is() )
2099
0
        return nullptr;
2100
2101
0
    if( !xFormattedString.hasElements() )
2102
0
        return nullptr;
2103
2104
0
    sal_Int32 nNumberOfParagraphs = xFormattedString.getLength();
2105
2106
0
    bool bNotEmpty = false;
2107
0
    for( sal_Int32 nN = 0; nN < nNumberOfParagraphs; ++nN )
2108
0
    {
2109
0
        if( !xFormattedString[nN]->getString().isEmpty() )
2110
0
        {
2111
0
            bNotEmpty = true;
2112
0
            break;
2113
0
        }
2114
0
    }
2115
0
    if( !bNotEmpty )
2116
0
        return nullptr;
2117
2118
    //create shape and add to page
2119
0
    rtl::Reference<SvxShapeText> xShape = new SvxShapeText(nullptr);
2120
0
    xShape->setShapeKind(SdrObjKind::Text);
2121
0
    xTarget->addShape(*xShape);
2122
2123
    //set paragraph properties
2124
0
    bNotEmpty = false;
2125
    // the first cursor is used for appending the next paragraph,
2126
    // after a new string has been inserted the cursor is moved at the end
2127
    // of the inserted string
2128
    // the second cursor is used for selecting the paragraph and apply the
2129
    // passed text properties
2130
0
    Reference< text::XTextCursor > xInsertCursor = xShape->createTextCursor();
2131
0
    Reference< text::XTextCursor > xSelectionCursor = xShape->createTextCursor();
2132
0
    if( xInsertCursor.is() && xSelectionCursor.is() )
2133
0
    {
2134
0
        uno::Reference< beans::XPropertySet > xSelectionProp( xSelectionCursor, uno::UNO_QUERY );
2135
0
        if( xSelectionProp.is() )
2136
0
        {
2137
0
            for( sal_Int32 nN = 0; nN < nNumberOfParagraphs; ++nN )
2138
0
            {
2139
0
                if( !xFormattedString[nN]->getString().isEmpty() )
2140
0
                {
2141
0
                    xInsertCursor->gotoEnd( false );
2142
0
                    xSelectionCursor->gotoEnd( false );
2143
0
                    xShape->insertString( xInsertCursor, xFormattedString[nN]->getString(), false );
2144
0
                    bNotEmpty = true;
2145
0
                    xSelectionCursor->gotoEnd( true ); // select current paragraph
2146
0
                    uno::Reference< beans::XPropertySet > xStringProperties( xFormattedString[nN], uno::UNO_QUERY );
2147
0
                    PropertyMapper::setMappedProperties( xSelectionProp, xStringProperties,
2148
0
                        PropertyMapper::getPropertyNameMapForTextShapeProperties() );
2149
0
                }
2150
0
            }
2151
0
        }
2152
0
    }
2153
2154
0
    if( !bNotEmpty )
2155
0
        return nullptr;
2156
2157
    //set whole text shape properties
2158
0
    PropertyMapper::setMultiProperties( rPropNames, rPropValues, *xShape );
2159
2160
0
    if( rATransformation.hasValue() )
2161
0
    {
2162
        //set position matrix
2163
        //the matrix needs to be set at the end behind autogrow and such position influencing properties
2164
0
        try
2165
0
        {
2166
0
            xShape->SvxShape::setPropertyValue( u"Transformation"_ustr, rATransformation );
2167
0
        }
2168
0
        catch( const uno::Exception& )
2169
0
        {
2170
0
            TOOLS_WARN_EXCEPTION("chart2", "" );
2171
0
        }
2172
0
    }
2173
0
    return xShape;
2174
0
}
2175
2176
rtl::Reference<SvxShapeText>
2177
        ShapeFactory::createText( const rtl::Reference<SvxShapeGroupAnyD>& xTarget,
2178
                const awt::Size& rSize,
2179
                const awt::Point& rPos,
2180
                uno::Sequence< uno::Reference< chart2::XFormattedString > >& xFormattedString,
2181
                const uno::Reference<
2182
                beans::XPropertySet > & xTextProperties,
2183
                double nRotation, const OUString& aName, sal_Int32 nTextMaxWidth )
2184
0
{
2185
    //create shape and add to page
2186
0
    rtl::Reference<SvxShapeText> xShape = new SvxShapeText(nullptr);
2187
0
    xShape->setShapeKind(SdrObjKind::Text);
2188
0
    try
2189
0
    {
2190
0
        xTarget->addShape(*xShape);
2191
2192
        //set text and text properties
2193
0
        uno::Reference< text::XTextCursor > xTextCursor( xShape->createTextCursor() );
2194
0
        uno::Reference< text::XTextCursor > xSelectionCursor( xShape->createTextCursor() );
2195
0
        if( !xTextCursor.is() || !xSelectionCursor.is() )
2196
0
            return xShape;
2197
2198
0
        tPropertyNameValueMap aValueMap;
2199
        //fill line-, fill- and paragraph-properties into the ValueMap
2200
0
        {
2201
0
            tPropertyNameMap aNameMap = PropertyMapper::getPropertyNameMapForParagraphProperties();
2202
0
            auto const & add = PropertyMapper::getPropertyNameMapForFillAndLineProperties();
2203
0
            aNameMap.insert(add.begin(), add.end());
2204
2205
0
            PropertyMapper::getValueMap( aValueMap, aNameMap, xTextProperties );
2206
0
        }
2207
2208
        //fill some more shape properties into the ValueMap
2209
0
        {
2210
0
            aValueMap.insert( { u"TextHorizontalAdjust"_ustr, uno::Any(drawing::TextHorizontalAdjust_CENTER) } ); // drawing::TextHorizontalAdjust
2211
0
            aValueMap.insert( { u"TextVerticalAdjust"_ustr, uno::Any(drawing::TextVerticalAdjust_CENTER) } ); //drawing::TextVerticalAdjust
2212
0
            aValueMap.insert( { u"TextAutoGrowHeight"_ustr, uno::Any(true) } ); // sal_Bool
2213
0
            aValueMap.insert( { u"TextAutoGrowWidth"_ustr, uno::Any(true) } ); // sal_Bool
2214
0
            aValueMap.insert( { u"TextMaximumFrameWidth"_ustr, uno::Any(nTextMaxWidth) } ); // sal_Int32
2215
2216
            //set name/classified ObjectID (CID)
2217
0
            if( !aName.isEmpty() )
2218
0
                aValueMap.emplace( u"Name"_ustr, uno::Any( aName ) ); //CID OUString
2219
0
        }
2220
2221
        //set global title properties
2222
0
        {
2223
0
            tNameSequence aPropNames;
2224
0
            tAnySequence aPropValues;
2225
0
            PropertyMapper::getMultiPropertyListsFromValueMap( aPropNames, aPropValues, aValueMap );
2226
0
            PropertyMapper::setMultiProperties( aPropNames, aPropValues, *xShape );
2227
0
        }
2228
2229
0
        if( xFormattedString.hasElements() )
2230
0
        {
2231
0
            bool bStackCharacters(false);
2232
0
            try
2233
0
            {
2234
0
                xTextProperties->getPropertyValue( u"StackCharacters"_ustr ) >>= bStackCharacters;
2235
0
            }
2236
0
            catch( const uno::Exception& )
2237
0
            {
2238
0
                TOOLS_WARN_EXCEPTION("chart2", "" );
2239
0
            }
2240
2241
            // Lock during property update to prevent unnecessary layout work.
2242
0
            xShape->addActionLock();
2243
2244
0
            if(bStackCharacters)
2245
0
            {
2246
                //if the characters should be stacked we use only the first character properties for code simplicity
2247
0
                size_t nLBreaks = xFormattedString.size() - 1;
2248
0
                for (const uno::Reference<chart2::XFormattedString>& rxFS : xFormattedString)
2249
0
                {
2250
0
                    if (!rxFS->getString().isEmpty())
2251
0
                    {
2252
0
                        OUString aLabel = ShapeFactory::getStackedString(rxFS->getString(), bStackCharacters);
2253
0
                        if (nLBreaks-- > 0)
2254
0
                            aLabel += OUStringChar('\r');
2255
0
                        uno::Reference< beans::XPropertySet > xSourceProps(rxFS, uno::UNO_QUERY);
2256
0
                        uno::Sequence<beans::PropertyValue> aPropVals =
2257
0
                            PropertyMapper::getPropVals(xSourceProps,
2258
0
                                PropertyMapper::getPropertyNameMapForTextShapeProperties());
2259
0
                        xShape->appendTextPortion(aLabel, aPropVals);
2260
0
                    }
2261
0
                }
2262
0
            }
2263
0
            else
2264
0
            {
2265
0
                for (const uno::Reference<chart2::XFormattedString>& rxFS : xFormattedString)
2266
0
                {
2267
0
                    if (!rxFS->getString().isEmpty())
2268
0
                    {
2269
0
                        uno::Reference< beans::XPropertySet > xSourceProps(rxFS, uno::UNO_QUERY);
2270
0
                        uno::Sequence<beans::PropertyValue> aPropVals =
2271
0
                            PropertyMapper::getPropVals(xSourceProps,
2272
0
                                PropertyMapper::getPropertyNameMapForTextShapeProperties());
2273
0
                        xShape->appendTextPortion(rxFS->getString(), aPropVals);
2274
0
                    }
2275
0
                }
2276
0
            }
2277
2278
0
            xShape->removeActionLock();
2279
2280
            // adapt font size according to page size
2281
0
            awt::Size aOldRefSize;
2282
0
            if( xTextProperties->getPropertyValue(u"ReferencePageSize"_ustr) >>= aOldRefSize )
2283
0
            {
2284
0
                RelativeSizeHelper::adaptFontSizes( *xShape, aOldRefSize, rSize );
2285
0
            }
2286
0
        }
2287
2288
        // #i109336# Improve auto positioning in chart
2289
0
        float fFontHeight = 0.0;
2290
0
        if ( xShape->SvxShape::getPropertyValue( u"CharHeight"_ustr ) >>= fFontHeight )
2291
0
        {
2292
0
            fFontHeight = convertPointToMm100(fFontHeight);
2293
0
            sal_Int32 nXDistance = static_cast< sal_Int32 >( ::rtl::math::round( fFontHeight * 0.18f ) );
2294
0
            sal_Int32 nYDistance = static_cast< sal_Int32 >( ::rtl::math::round( fFontHeight * 0.30f ) );
2295
0
            uno::Sequence<OUString> aPropNames {
2296
0
                u"TextLeftDistance"_ustr,
2297
0
                u"TextRightDistance"_ustr,
2298
0
                u"TextUpperDistance"_ustr,
2299
0
                u"TextLowerDistance"_ustr,
2300
0
            };
2301
0
            uno::Sequence<uno::Any> aPropVals {
2302
0
                uno::Any( nXDistance ),
2303
0
                uno::Any( nXDistance ),
2304
0
                uno::Any( nYDistance ),
2305
0
                uno::Any( nYDistance ),
2306
0
            };
2307
0
            xShape->SvxShape::setPropertyValues( aPropNames, aPropVals );
2308
0
        }
2309
0
        sal_Int32 nXPos = rPos.X;
2310
0
        sal_Int32 nYPos = rPos.Y;
2311
2312
        //set position matrix
2313
        //the matrix needs to be set at the end behind autogrow and such position influencing properties
2314
0
        ::basegfx::B2DHomMatrix aM;
2315
0
        aM.rotate( -basegfx::deg2rad(nRotation) );//#i78696#->#i80521#
2316
0
        aM.translate( nXPos, nYPos );
2317
0
        uno::Sequence<OUString> aPropNames {
2318
0
             u"Transformation"_ustr,
2319
0
             u"ParaAdjust"_ustr
2320
0
        };
2321
0
        uno::Sequence<uno::Any> aPropVals {
2322
0
            uno::Any( B2DHomMatrixToHomogenMatrix3(aM) ),
2323
0
            uno::Any( style::ParagraphAdjust_CENTER )
2324
0
        };
2325
0
        xShape->SvxShape::setPropertyValues( aPropNames, aPropVals );
2326
0
    }
2327
0
    catch( const uno::Exception& )
2328
0
    {
2329
0
        TOOLS_WARN_EXCEPTION("chart2", "" );
2330
0
    }
2331
0
    return xShape;
2332
0
}
2333
2334
rtl::Reference<SvxShapeGroupAnyD> ShapeFactory::getChartRootShape(
2335
    const rtl::Reference<SvxDrawPage>& xDrawPage )
2336
0
{
2337
0
    rtl::Reference<SvxShapeGroupAnyD> xRet;
2338
0
    if( xDrawPage.is() )
2339
0
    {
2340
0
        sal_Int32 nCount = xDrawPage->getCount();
2341
0
        uno::Reference< drawing::XShape > xShape;
2342
0
        for( sal_Int32 nN = nCount; nN--; )
2343
0
        {
2344
0
            if( xDrawPage->getByIndex( nN ) >>= xShape )
2345
0
            {
2346
0
                if( ShapeFactory::getShapeName( xShape ) == "com.sun.star.chart2.shapes" )
2347
0
                {
2348
0
                    xRet = dynamic_cast<SvxShapeGroupAnyD*>(xShape.get());
2349
0
                    assert(xRet);
2350
0
                    break;
2351
0
                }
2352
0
            }
2353
0
        }
2354
0
    }
2355
0
    return xRet;
2356
0
}
2357
2358
void ShapeFactory::makeShapeInvisible( const rtl::Reference< SvxShape >& xShape )
2359
0
{
2360
0
    try
2361
0
    {
2362
0
        xShape->setPropertyValue( u"LineStyle"_ustr, uno::Any( drawing::LineStyle_NONE ));
2363
0
        xShape->setPropertyValue( u"FillStyle"_ustr, uno::Any( drawing::FillStyle_NONE ));
2364
0
    }
2365
0
    catch( const uno::Exception& )
2366
0
    {
2367
0
        TOOLS_WARN_EXCEPTION("chart2", "" );
2368
0
    }
2369
0
}
2370
2371
// set a name/CID at a shape (is used for selection handling)
2372
2373
void ShapeFactory::setShapeName( const rtl::Reference< SvxShape >& xShape
2374
                               , const OUString& rName )
2375
0
{
2376
0
    if(!xShape.is())
2377
0
        return;
2378
0
    try
2379
0
    {
2380
0
        xShape->setPropertyValue( UNO_NAME_MISC_OBJ_NAME
2381
0
            , uno::Any( rName ) );
2382
0
    }
2383
0
    catch( const uno::Exception& )
2384
0
    {
2385
0
        TOOLS_WARN_EXCEPTION("chart2", "" );
2386
0
    }
2387
0
}
2388
2389
OUString ShapeFactory::getShapeName( const uno::Reference< drawing::XShape >& xShape )
2390
0
{
2391
0
    OUString aRet;
2392
2393
0
    uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
2394
0
    OSL_ENSURE(xProp.is(), "shape offers no XPropertySet");
2395
0
    if( xProp.is())
2396
0
    {
2397
0
        try
2398
0
        {
2399
0
            xProp->getPropertyValue( UNO_NAME_MISC_OBJ_NAME ) >>= aRet;
2400
0
        }
2401
0
        catch( const uno::Exception& )
2402
0
        {
2403
0
            TOOLS_WARN_EXCEPTION("chart2", "" );
2404
0
        }
2405
0
    }
2406
2407
0
    return aRet;
2408
0
}
2409
2410
uno::Any ShapeFactory::makeTransformation( const awt::Point& rScreenPosition2D, double fRotationAnglePi )
2411
0
{
2412
0
    ::basegfx::B2DHomMatrix aM;
2413
    //As autogrow is active the rectangle is automatically expanded to that side
2414
    //to which the text is not adjusted.
2415
    // aM.scale( 1, 1 ); Oops? A scale with this parameters is neutral, line commented out
2416
0
    aM.rotate( fRotationAnglePi );
2417
0
    aM.translate( rScreenPosition2D.X, rScreenPosition2D.Y );
2418
0
    uno::Any aATransformation( B2DHomMatrixToHomogenMatrix3(aM) );
2419
0
    return aATransformation;
2420
0
}
2421
2422
OUString ShapeFactory::getStackedString( const OUString& rString, bool bStacked )
2423
0
{
2424
0
    sal_Int32 nLen = rString.getLength();
2425
0
    if(!bStacked || !nLen)
2426
0
        return rString;
2427
2428
0
    OUStringBuffer aStackStr;
2429
2430
    //add a newline after each letter
2431
    //as we do not know letters here add a newline after each char
2432
0
    for( sal_Int32 nPosSrc=0; nPosSrc < nLen; nPosSrc++ )
2433
0
    {
2434
0
        if( nPosSrc )
2435
0
            aStackStr.append( '\r' );
2436
0
        aStackStr.append(rString[nPosSrc]);
2437
0
    }
2438
0
    return aStackStr.makeStringAndClear();
2439
0
}
2440
2441
bool ShapeFactory::hasPolygonAnyLines( const std::vector<std::vector<css::drawing::Position3D>>& rPoly)
2442
0
{
2443
    // #i67757# check all contained polygons, if at least one polygon contains 2 or more points, return true
2444
0
    for( auto const & i : rPoly )
2445
0
        if( i.size() > 1 )
2446
0
            return true;
2447
0
    return false;
2448
0
}
2449
2450
bool ShapeFactory::isPolygonEmptyOrSinglePoint( const drawing::PolyPolygonShape3D& rPoly)
2451
0
{
2452
    // true, if empty polypolygon or one polygon with one point
2453
0
    return !rPoly.SequenceX.hasElements() ||
2454
0
        ((rPoly.SequenceX.getLength() == 1) && (rPoly.SequenceX[0].getLength() <= 1));
2455
0
}
2456
2457
bool ShapeFactory::isPolygonEmptyOrSinglePoint( const std::vector<std::vector<css::drawing::Position3D>>& rPoly)
2458
0
{
2459
    // true, if empty polypolygon or one polygon with one point
2460
0
    return rPoly.empty() || ((rPoly.size() == 1) && (rPoly[0].size() <= 1));
2461
0
}
2462
2463
void ShapeFactory::closePolygon( drawing::PolyPolygonShape3D& rPoly)
2464
0
{
2465
0
    OSL_ENSURE( rPoly.SequenceX.getLength() <= 1, "ShapeFactory::closePolygon - single polygon expected" );
2466
    //add a last point == first point
2467
0
    if(isPolygonEmptyOrSinglePoint(rPoly))
2468
0
        return;
2469
0
    drawing::Position3D aFirst(rPoly.SequenceX[0][0],rPoly.SequenceY[0][0],rPoly.SequenceZ[0][0]);
2470
0
    AddPointToPoly( rPoly, aFirst );
2471
0
}
2472
2473
void ShapeFactory::closePolygon( std::vector<std::vector<css::drawing::Position3D>>& rPoly)
2474
0
{
2475
0
    OSL_ENSURE( rPoly.size() <= 1, "ShapeFactory::closePolygon - single polygon expected" );
2476
    //add a last point == first point
2477
0
    if(isPolygonEmptyOrSinglePoint(rPoly))
2478
0
        return;
2479
0
    drawing::Position3D aFirst(rPoly[0][0]);
2480
0
    AddPointToPoly( rPoly, aFirst );
2481
0
}
2482
2483
awt::Size ShapeFactory::calculateNewSizeRespectingAspectRatio(
2484
         const awt::Size& rTargetSize
2485
         , const awt::Size& rSourceSizeWithCorrectAspectRatio )
2486
0
{
2487
0
    awt::Size aNewSize;
2488
2489
0
    double fFactorWidth = double(rTargetSize.Width)/double(rSourceSizeWithCorrectAspectRatio.Width);
2490
0
    double fFactorHeight = double(rTargetSize.Height)/double(rSourceSizeWithCorrectAspectRatio.Height);
2491
0
    double fFactor = std::min(fFactorWidth,fFactorHeight);
2492
0
    aNewSize.Width=static_cast<sal_Int32>(fFactor*rSourceSizeWithCorrectAspectRatio.Width);
2493
0
    aNewSize.Height=static_cast<sal_Int32>(fFactor*rSourceSizeWithCorrectAspectRatio.Height);
2494
2495
0
    return aNewSize;
2496
0
}
2497
2498
awt::Point ShapeFactory::calculateTopLeftPositionToCenterObject(
2499
           const awt::Point& rTargetAreaPosition
2500
         , const awt::Size& rTargetAreaSize
2501
         , const awt::Size& rObjectSize )
2502
0
{
2503
0
    awt::Point aNewPosition(rTargetAreaPosition);
2504
0
    aNewPosition.X += static_cast<sal_Int32>(double(rTargetAreaSize.Width-rObjectSize.Width)/2.0);
2505
0
    aNewPosition.Y += static_cast<sal_Int32>(double(rTargetAreaSize.Height-rObjectSize.Height)/2.0);
2506
0
    return aNewPosition;
2507
0
}
2508
2509
::basegfx::B2IRectangle ShapeFactory::getRectangleOfShape( SvxShape& rShape )
2510
0
{
2511
0
    ::basegfx::B2IRectangle aRet;
2512
2513
0
    awt::Point aPos = rShape.getPosition();
2514
0
    awt::Size aSize = rShape.getSize();
2515
0
    aRet = BaseGFXHelper::makeRectangle(aPos,aSize);
2516
2517
0
    return aRet;
2518
0
}
2519
2520
awt::Size ShapeFactory::getSizeAfterRotation(
2521
         SvxShape& rShape, double fRotationAngleDegree )
2522
0
{
2523
0
    awt::Size aRet(0,0);
2524
0
    const awt::Size aSize( rShape.getSize() );
2525
2526
0
    if( fRotationAngleDegree == 0.0 )
2527
0
        aRet = aSize;
2528
0
    else
2529
0
    {
2530
0
        fRotationAngleDegree = NormAngle360(fRotationAngleDegree);
2531
0
        if(fRotationAngleDegree>270.0)
2532
0
            fRotationAngleDegree=360.0-fRotationAngleDegree;
2533
0
        else if(fRotationAngleDegree>180.0)
2534
0
            fRotationAngleDegree=fRotationAngleDegree-180.0;
2535
0
        else if(fRotationAngleDegree>90.0)
2536
0
            fRotationAngleDegree=180.0-fRotationAngleDegree;
2537
2538
0
        const double fAnglePi = basegfx::deg2rad(fRotationAngleDegree);
2539
2540
0
        aRet.Height = static_cast<sal_Int32>(
2541
0
            aSize.Width*std::sin( fAnglePi )
2542
0
            + aSize.Height*std::cos( fAnglePi ));
2543
0
        aRet.Width = static_cast<sal_Int32>(
2544
0
            aSize.Width*std::cos( fAnglePi )
2545
0
            + aSize.Height*std::sin( fAnglePi ));
2546
0
    }
2547
0
    return aRet;
2548
0
}
2549
2550
void ShapeFactory::removeSubShapes( const rtl::Reference<SvxShapeGroupAnyD>& xShapes )
2551
0
{
2552
0
    if( xShapes.is() )
2553
0
    {
2554
0
        sal_Int32 nSubCount = xShapes->getCount();
2555
0
        uno::Reference< drawing::XShape > xShape;
2556
0
        for( sal_Int32 nS = nSubCount; nS--; )
2557
0
        {
2558
0
            if( xShapes->getByIndex( nS ) >>= xShape )
2559
0
                xShapes->remove( xShape );
2560
0
        }
2561
0
    }
2562
0
}
2563
2564
rtl::Reference<SvxTableShape>
2565
ShapeFactory::createTable(rtl::Reference<SvxShapeGroupAnyD> const& xTarget, OUString const& rName)
2566
0
{
2567
0
    if (!xTarget.is())
2568
0
        return nullptr;
2569
2570
    //create table shape
2571
0
    rtl::Reference<SvxTableShape> xShape = new SvxTableShape(nullptr);
2572
0
    xShape->setShapeKind(SdrObjKind::Table);
2573
0
    xTarget->addShape(*xShape);
2574
0
    if (!rName.isEmpty())
2575
0
        setShapeName(xShape, rName);
2576
0
    return xShape;
2577
0
}
2578
2579
} //namespace chart
2580
2581
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */