1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
21 #include <sal/log.hxx>
23 #include <o3tl/any.hxx>
24 #include <o3tl/safeint.hxx>
25 #include <vcl/bitmapex.hxx>
26 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
27 #include <com/sun/star/drawing/LineStyle.hpp>
28 #include <com/sun/star/drawing/LineDash.hpp>
29 #include <com/sun/star/drawing/FillStyle.hpp>
30 #include <com/sun/star/drawing/Hatch.hpp>
31 #include <com/sun/star/awt/FontDescriptor.hpp>
32 #include <com/sun/star/awt/FontWeight.hpp>
33 #include <com/sun/star/awt/FontUnderline.hpp>
34 #include <com/sun/star/drawing/XShapeGrouper.hpp>
35 #include <com/sun/star/drawing/CircleKind.hpp>
36 #include <com/sun/star/awt/XBitmap.hpp>
37 #include <com/sun/star/drawing/PointSequenceSequence.hpp>
38 #include <com/sun/star/drawing/PointSequence.hpp>
39 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
40 #include <com/sun/star/drawing/FlagSequence.hpp>
41 #include <com/sun/star/drawing/ShapeCollection.hpp>
42 #include <com/sun/star/drawing/TextAdjust.hpp>
43 #include <com/sun/star/text/XText.hpp>
44 #include <com/sun/star/text/XTextRange.hpp>
45 #include <com/sun/star/style/HorizontalAlignment.hpp>
47 #include <comphelper/processfactory.hxx>
48 #include <toolkit/helper/vclunohelper.hxx>
49 #include <tools/helpers.hxx>
50 #include <comphelper/configuration.hxx>
53 #include "elements.hxx"
56 #define MAX_PAGES_FOR_FUZZING 2048
58 using namespace ::com::sun::star
;
60 CGMImpressOutAct::CGMImpressOutAct(CGM
& rCGM
, const uno::Reference
< frame::XModel
> & rModel
)
68 if ( !mpCGM
->mbStatus
)
71 bool bStatRet
= false;
73 uno::Reference
< drawing::XDrawPagesSupplier
> aDrawPageSup( rModel
, uno::UNO_QUERY
);
74 if( aDrawPageSup
.is() )
76 maXDrawPages
= aDrawPageSup
->getDrawPages();
77 if ( maXDrawPages
.is() )
79 maXMultiServiceFactory
.set( rModel
, uno::UNO_QUERY
);
80 if( maXMultiServiceFactory
.is() )
82 maXDrawPage
= *o3tl::doAccess
<uno::Reference
<drawing::XDrawPage
>>(maXDrawPages
->getByIndex( 0 ));
88 mpCGM
->mbStatus
= bStatRet
;
91 CGMImpressOutAct::~CGMImpressOutAct()
93 for (auto &a
: maLockedNewXShapes
)
94 a
->removeActionLock();
97 bool CGMImpressOutAct::ImplInitPage()
99 bool bStatRet
= false;
100 if( maXDrawPage
.is() )
102 maXShapes
= maXDrawPage
;
103 if ( maXShapes
.is() )
111 bool CGMImpressOutAct::ImplCreateShape( const OUString
& rType
)
113 if (comphelper::IsFuzzing())
115 uno::Reference
< uno::XInterface
> xNewShape( maXMultiServiceFactory
->createInstance( rType
) );
116 maXShape
.set( xNewShape
, uno::UNO_QUERY
);
117 maXPropSet
.set( xNewShape
, uno::UNO_QUERY
);
118 if ( maXShape
.is() && maXPropSet
.is() )
120 maXShapes
->add( maXShape
);
121 uno::Reference
<document::XActionLockable
> xLockable(maXShape
, uno::UNO_QUERY
);
124 xLockable
->addActionLock();
125 maLockedNewXShapes
.push_back(xLockable
);
132 void CGMImpressOutAct::ImplSetOrientation( FloatPoint
const & rRefPoint
, double rOrientation
)
134 maXPropSet
->setPropertyValue( u
"RotationPointX"_ustr
, uno::Any(static_cast<sal_Int32
>(rRefPoint
.X
)) );
135 maXPropSet
->setPropertyValue( u
"RotationPointY"_ustr
, uno::Any(static_cast<sal_Int32
>(rRefPoint
.Y
)) );
136 maXPropSet
->setPropertyValue( u
"RotateAngle"_ustr
, uno::Any(static_cast<sal_Int32
>( rOrientation
* 100.0 )) );
140 void CGMImpressOutAct::ImplSetLineBundle()
142 drawing::LineStyle eLS
;
144 sal_uInt32 nLineColor
;
148 if ( mpCGM
->pElement
->nAspectSourceFlags
& ASF_LINECOLOR
)
149 nLineColor
= mpCGM
->pElement
->pLineBundle
->GetColor();
151 nLineColor
= mpCGM
->pElement
->aLineBundle
.GetColor();
152 if ( mpCGM
->pElement
->nAspectSourceFlags
& ASF_LINETYPE
)
153 eLineType
= mpCGM
->pElement
->pLineBundle
->eLineType
;
155 eLineType
= mpCGM
->pElement
->aLineBundle
.eLineType
;
156 if ( mpCGM
->pElement
->nAspectSourceFlags
& ASF_LINEWIDTH
)
157 fLineWidth
= mpCGM
->pElement
->pLineBundle
->nLineWidth
;
159 fLineWidth
= mpCGM
->pElement
->aLineBundle
.nLineWidth
;
161 maXPropSet
->setPropertyValue( u
"LineColor"_ustr
, uno::Any(static_cast<sal_Int32
>(nLineColor
)) );
163 maXPropSet
->setPropertyValue( u
"LineWidth"_ustr
, uno::Any(static_cast<sal_Int32
>(fLineWidth
)) );
168 eLS
= drawing::LineStyle_NONE
;
173 case LT_DOTDOTSPACE
:
175 case LT_DASHDASHDOT
:
176 eLS
= drawing::LineStyle_DASH
;
180 eLS
= drawing::LineStyle_SOLID
;
183 maXPropSet
->setPropertyValue( u
"LineStyle"_ustr
, uno::Any(eLS
) );
184 if ( eLS
== drawing::LineStyle_DASH
)
186 drawing::LineDash
aLineDash( drawing::DashStyle_RECTRELATIVE
, 1, 50, 3, 33, 100 );
187 maXPropSet
->setPropertyValue( u
"LineDash"_ustr
, uno::Any(aLineDash
) );
191 void CGMImpressOutAct::ImplSetFillBundle()
193 drawing::LineStyle eLS
;
194 drawing::FillStyle eFS
;
196 sal_uInt32 nEdgeColor
= 0;
198 double fEdgeWidth
= 0;
200 sal_uInt32 nFillColor
;
201 FillInteriorStyle eFillStyle
;
202 sal_uInt32 nHatchIndex
;
204 if ( mpCGM
->pElement
->eEdgeVisibility
== EV_ON
)
206 if ( mpCGM
->pElement
->nAspectSourceFlags
& ASF_EDGETYPE
)
207 eEdgeType
= mpCGM
->pElement
->pEdgeBundle
->eEdgeType
;
209 eEdgeType
= mpCGM
->pElement
->aEdgeBundle
.eEdgeType
;
210 if ( mpCGM
->pElement
->nAspectSourceFlags
& ASF_EDGEWIDTH
)
211 fEdgeWidth
= mpCGM
->pElement
->pEdgeBundle
->nEdgeWidth
;
213 fEdgeWidth
= mpCGM
->pElement
->aEdgeBundle
.nEdgeWidth
;
214 if ( mpCGM
->pElement
->nAspectSourceFlags
& ASF_EDGECOLOR
)
215 nEdgeColor
= mpCGM
->pElement
->pEdgeBundle
->GetColor();
217 nEdgeColor
= mpCGM
->pElement
->aEdgeBundle
.GetColor();
222 if ( mpCGM
->pElement
->nAspectSourceFlags
& ASF_FILLINTERIORSTYLE
)
223 eFillStyle
= mpCGM
->pElement
->pFillBundle
->eFillInteriorStyle
;
225 eFillStyle
= mpCGM
->pElement
->aFillBundle
.eFillInteriorStyle
;
226 if ( mpCGM
->pElement
->nAspectSourceFlags
& ASF_FILLCOLOR
)
227 nFillColor
= mpCGM
->pElement
->pFillBundle
->GetColor();
229 nFillColor
= mpCGM
->pElement
->aFillBundle
.GetColor();
230 if ( mpCGM
->pElement
->nAspectSourceFlags
& ASF_HATCHINDEX
)
231 nHatchIndex
= static_cast<sal_uInt32
>(mpCGM
->pElement
->pFillBundle
->nFillHatchIndex
);
233 nHatchIndex
= static_cast<sal_uInt32
>(mpCGM
->pElement
->aFillBundle
.nFillHatchIndex
);
235 maXPropSet
->setPropertyValue( u
"FillColor"_ustr
, uno::Any(static_cast<sal_Int32
>(nFillColor
)) );
237 switch ( eFillStyle
)
241 if ( nHatchIndex
== 0 )
242 eFS
= drawing::FillStyle_NONE
;
244 eFS
= drawing::FillStyle_HATCH
;
250 eFS
= drawing::FillStyle_SOLID
;
254 case FIS_GEOPATTERN
:
256 if ( mpCGM
->pElement
->eTransparency
== T_ON
)
257 nFillColor
= mpCGM
->pElement
->nAuxiliaryColor
;
258 eFS
= drawing::FillStyle_NONE
;
262 case FIS_INTERPOLATED
:
265 eFS
= drawing::FillStyle_GRADIENT
;
273 eFS
= drawing::FillStyle_NONE
;
277 if ( mpCGM
->mnAct4PostReset
& ACT4_GRADIENT_ACTION
)
278 eFS
= drawing::FillStyle_GRADIENT
;
280 if ( eFS
== drawing::FillStyle_GRADIENT
)
282 maXPropSet
->setPropertyValue( u
"FillGradient"_ustr
, uno::Any(*mpGradient
) );
284 maXPropSet
->setPropertyValue( u
"FillStyle"_ustr
, uno::Any(eFS
) );
286 eLS
= drawing::LineStyle_NONE
;
287 if ( eFillStyle
== FIS_HOLLOW
)
289 eLS
= drawing::LineStyle_SOLID
;
290 maXPropSet
->setPropertyValue( u
"LineColor"_ustr
, uno::Any(static_cast<sal_Int32
>(nFillColor
)) );
291 maXPropSet
->setPropertyValue( u
"LineWidth"_ustr
, uno::Any(sal_Int32(0)) );
293 else if ( eEdgeType
!= ET_NONE
)
295 maXPropSet
->setPropertyValue( u
"LineColor"_ustr
, uno::Any(static_cast<sal_Int32
>(nEdgeColor
)) );
297 maXPropSet
->setPropertyValue( u
"LineWidth"_ustr
, uno::Any(static_cast<sal_Int32
>(fEdgeWidth
)) );
305 case ET_DOTDOTSPACE
:
307 case ET_DASHDASHDOT
:
308 default: // case ET_SOLID :
310 eLS
= drawing::LineStyle_SOLID
;
316 maXPropSet
->setPropertyValue( u
"LineStyle"_ustr
, uno::Any(eLS
) );
318 if ( eFS
!= drawing::FillStyle_HATCH
)
321 drawing::Hatch aHatch
;
323 aHatch
.Color
= nFillColor
;
324 if ( mpCGM
->pElement
->maHatchMap
.contains( nHatchIndex
) )
326 HatchEntry
& rHatchEntry
= mpCGM
->pElement
->maHatchMap
[ nHatchIndex
];
327 switch ( rHatchEntry
.HatchStyle
)
329 case 0 : aHatch
.Style
= drawing::HatchStyle_SINGLE
; break;
330 case 1 : aHatch
.Style
= drawing::HatchStyle_DOUBLE
; break;
331 case 2 : aHatch
.Style
= drawing::HatchStyle_TRIPLE
; break;
333 aHatch
.Distance
= rHatchEntry
.HatchDistance
;
334 aHatch
.Angle
= rHatchEntry
.HatchAngle
;
338 aHatch
.Style
= drawing::HatchStyle_TRIPLE
;
339 aHatch
.Distance
= 10 * ( nHatchIndex
& 0x1f ) | 100;
340 aHatch
.Angle
= 15 * ( ( nHatchIndex
& 0x1f ) - 5 );
342 maXPropSet
->setPropertyValue( u
"FillHatch"_ustr
, uno::Any(aHatch
) );
345 void CGMImpressOutAct::ImplSetTextBundle( const uno::Reference
< beans::XPropertySet
> & rProperty
)
347 sal_uInt32 nTextFontIndex
;
348 sal_uInt32 nTextColor
;
350 if ( mpCGM
->pElement
->nAspectSourceFlags
& ASF_TEXTFONTINDEX
)
351 nTextFontIndex
= mpCGM
->pElement
->pTextBundle
->nTextFontIndex
;
353 nTextFontIndex
= mpCGM
->pElement
->aTextBundle
.nTextFontIndex
;
354 if ( mpCGM
->pElement
->nAspectSourceFlags
& ASF_TEXTCOLOR
)
355 nTextColor
= mpCGM
->pElement
->pTextBundle
->GetColor();
357 nTextColor
= mpCGM
->pElement
->aTextBundle
.GetColor();
359 rProperty
->setPropertyValue( u
"CharColor"_ustr
, uno::Any(static_cast<sal_Int32
>(nTextColor
)) );
361 sal_uInt32 nFontType
= 0;
362 awt::FontDescriptor aFontDescriptor
;
363 FontEntry
* pFontEntry
= mpCGM
->pElement
->aFontList
.GetFontEntry( nTextFontIndex
);
366 nFontType
= pFontEntry
->nFontType
;
367 aFontDescriptor
.Name
= OUString(reinterpret_cast<char*>(pFontEntry
->aFontName
.data()),
368 pFontEntry
->aFontName
.size(),
369 RTL_TEXTENCODING_ASCII_US
);
371 aFontDescriptor
.Height
= sal_Int16( mpCGM
->pElement
->nCharacterHeight
* 1.50 );
373 aFontDescriptor
.Slant
= awt::FontSlant_ITALIC
;
375 aFontDescriptor
.Weight
= awt::FontWeight::BOLD
;
377 aFontDescriptor
.Weight
= awt::FontWeight::NORMAL
;
379 if ( mpCGM
->pElement
->eUnderlineMode
!= UM_OFF
)
381 aFontDescriptor
.Underline
= awt::FontUnderline::SINGLE
;
383 rProperty
->setPropertyValue( u
"FontDescriptor"_ustr
, uno::Any(aFontDescriptor
) );
386 void CGMImpressOutAct::InsertPage()
388 if ( mnCurrentPage
) // one side is always existing, therefore the first side will be left out
390 maXDrawPage
= maXDrawPages
->insertNewByIndex(0xffff);
391 if ( !ImplInitPage() )
392 mpCGM
->mbStatus
= false;
393 if (mnCurrentPage
> MAX_PAGES_FOR_FUZZING
&& comphelper::IsFuzzing())
395 // ofz#21753 that's enough pages for fuzzing, we're not doing anything productive now
396 mpCGM
->mbStatus
= false;
402 void CGMImpressOutAct::BeginGroup()
404 if ( mnGroupLevel
< CGM_OUTACT_MAX_GROUP_LEVEL
)
406 maGroupLevel
[mnGroupLevel
] = maXShapes
->getCount();
409 mnGroupActCount
= mpCGM
->mnActCount
;
412 void CGMImpressOutAct::EndGroup()
417 if ( mnGroupLevel
>= CGM_OUTACT_MAX_GROUP_LEVEL
)
420 sal_uInt32 nFirstIndex
= maGroupLevel
[mnGroupLevel
];
421 if ( nFirstIndex
== 0xffffffff )
423 sal_uInt32 nCurrentCount
= maXShapes
->getCount();
424 if ( ( nCurrentCount
- nFirstIndex
) <= 1 )
427 uno::Reference
< drawing::XShapeGrouper
> aXShapeGrouper
;
428 aXShapeGrouper
.set( maXDrawPage
, uno::UNO_QUERY
);
429 if( !aXShapeGrouper
.is() )
432 uno::Reference
< drawing::XShapes
> aXShapes
= drawing::ShapeCollection::create(comphelper::getProcessComponentContext());
433 for ( sal_uInt32 i
= nFirstIndex
; i
< nCurrentCount
; i
++ )
435 uno::Reference
< drawing::XShape
> aXShape
= *o3tl::doAccess
<uno::Reference
<drawing::XShape
>>(maXShapes
->getByIndex( i
));
438 aXShapes
->add( aXShape
);
441 aXShapeGrouper
->group( aXShapes
);
444 void CGMImpressOutAct::EndGrouping()
446 while ( mnGroupLevel
)
452 void CGMImpressOutAct::DrawRectangle( FloatRect
const & rFloatRect
)
454 if (mnGroupActCount
== (mpCGM
->mnActCount
- 1)) // POWERPOINT HACK !!!
456 if (useless(rFloatRect
.Left
))
458 SAL_WARN("filter.icgm", "bad left: " << rFloatRect
.Left
);
461 if (useless(rFloatRect
.Top
))
463 SAL_WARN("filter.icgm", "bad top: " << rFloatRect
.Top
);
466 double fWidth
= rFloatRect
.Right
- rFloatRect
.Left
;
469 SAL_WARN("filter.icgm", "bad width: " << fWidth
);
472 double fHeight
= rFloatRect
.Bottom
- rFloatRect
.Top
;
473 if (useless(fHeight
))
475 SAL_WARN("filter.icgm", "bad height: " << fHeight
);
478 if (!ImplCreateShape( u
"com.sun.star.drawing.RectangleShape"_ustr
))
480 maXShape
->setSize(awt::Size(fWidth
, fHeight
));
481 maXShape
->setPosition(awt::Point(rFloatRect
.Left
, rFloatRect
.Top
));
485 void CGMImpressOutAct::DrawEllipse( FloatPoint
const & rCenter
, FloatPoint
const & rSize
, double& rOrientation
)
487 if ( !ImplCreateShape( u
"com.sun.star.drawing.EllipseShape"_ustr
) )
490 drawing::CircleKind eCircleKind
= drawing::CircleKind_FULL
;
491 uno::Any
aAny( &eCircleKind
, ::cppu::UnoType
<drawing::CircleKind
>::get() );
492 maXPropSet
->setPropertyValue( u
"CircleKind"_ustr
, aAny
);
494 tools::Long nXSize
= static_cast<tools::Long
>( rSize
.X
* 2.0 ); // strange behaviour with an awt::Size of 0
495 tools::Long nYSize
= static_cast<tools::Long
>( rSize
.Y
* 2.0 );
500 maXShape
->setSize( awt::Size( nXSize
, nYSize
) );
501 maXShape
->setPosition( awt::Point( static_cast<tools::Long
>( rCenter
.X
- rSize
.X
), static_cast<tools::Long
>( rCenter
.Y
- rSize
.Y
) ) );
503 if ( rOrientation
!= 0 )
505 ImplSetOrientation( rCenter
, rOrientation
);
510 void CGMImpressOutAct::DrawEllipticalArc( FloatPoint
const & rCenter
, FloatPoint
const & rSize
, double& rOrientation
,
511 sal_uInt32 nType
, double& fStartAngle
, double& fEndAngle
)
513 if ( !ImplCreateShape( u
"com.sun.star.drawing.EllipseShape"_ustr
) )
517 drawing::CircleKind eCircleKind
;
520 tools::Long nXSize
= static_cast<tools::Long
>( rSize
.X
* 2.0 ); // strange behaviour with an awt::Size of 0
521 tools::Long nYSize
= static_cast<tools::Long
>( rSize
.Y
* 2.0 );
527 maXShape
->setSize( awt::Size ( nXSize
, nYSize
) );
529 if ( rOrientation
!= 0 )
531 fStartAngle
= NormAngle360(fStartAngle
+ rOrientation
);
532 fEndAngle
= NormAngle360(fEndAngle
+ rOrientation
);
536 case 0 : eCircleKind
= drawing::CircleKind_SECTION
; break;
537 case 1 : eCircleKind
= drawing::CircleKind_CUT
; break;
538 case 2 : eCircleKind
= drawing::CircleKind_ARC
; break;
539 default : eCircleKind
= drawing::CircleKind_FULL
; break;
541 if ( static_cast<tools::Long
>(fStartAngle
) == static_cast<tools::Long
>(fEndAngle
) )
543 eCircleKind
= drawing::CircleKind_FULL
;
544 maXPropSet
->setPropertyValue( u
"CircleKind"_ustr
, uno::Any(eCircleKind
) );
548 maXPropSet
->setPropertyValue( u
"CircleKind"_ustr
, uno::Any(eCircleKind
) );
549 maXPropSet
->setPropertyValue( u
"CircleStartAngle"_ustr
, uno::Any(static_cast<sal_Int32
>( fStartAngle
* 100 )) );
550 maXPropSet
->setPropertyValue( u
"CircleEndAngle"_ustr
, uno::Any(static_cast<sal_Int32
>( fEndAngle
* 100 )) );
552 maXShape
->setPosition( awt::Point( static_cast<tools::Long
>( rCenter
.X
- rSize
.X
), static_cast<tools::Long
>( rCenter
.Y
- rSize
.Y
) ) );
553 if ( rOrientation
!= 0 )
555 ImplSetOrientation( rCenter
, rOrientation
);
557 if ( eCircleKind
== drawing::CircleKind_ARC
)
567 aAny
<<= drawing::FillStyle_NONE
;
568 maXPropSet
->setPropertyValue( u
"FillStyle"_ustr
, aAny
);
573 void CGMImpressOutAct::DrawBitmap( CGMBitmapDescriptor
* pBmpDesc
)
575 if ( !pBmpDesc
->mbStatus
|| pBmpDesc
->mxBitmap
.IsEmpty() )
578 FloatPoint aOrigin
= pBmpDesc
->mnOrigin
;
579 double fdx
= pBmpDesc
->mndx
;
580 double fdy
= pBmpDesc
->mndy
;
582 BmpMirrorFlags nMirr
= BmpMirrorFlags::NONE
;
583 if ( pBmpDesc
->mbVMirror
)
584 nMirr
|= BmpMirrorFlags::Vertical
;
585 if ( nMirr
!= BmpMirrorFlags::NONE
)
586 pBmpDesc
->mxBitmap
.Mirror( nMirr
);
588 mpCGM
->ImplMapPoint( aOrigin
);
589 mpCGM
->ImplMapX( fdx
);
590 mpCGM
->ImplMapY( fdy
);
592 if ( !ImplCreateShape( u
"com.sun.star.drawing.GraphicObjectShape"_ustr
) )
595 maXShape
->setSize( awt::Size( static_cast<tools::Long
>(fdx
), static_cast<tools::Long
>(fdy
) ) );
596 maXShape
->setPosition( awt::Point( static_cast<tools::Long
>(aOrigin
.X
), static_cast<tools::Long
>(aOrigin
.Y
) ) );
598 if ( pBmpDesc
->mnOrientation
!= 0 )
600 ImplSetOrientation( aOrigin
, pBmpDesc
->mnOrientation
);
603 uno::Reference
< awt::XBitmap
> xBitmap( VCLUnoHelper::CreateBitmap( pBmpDesc
->mxBitmap
) );
604 maXPropSet
->setPropertyValue( u
"GraphicObjectFillBitmap"_ustr
, uno::Any(xBitmap
) );
607 void CGMImpressOutAct::DrawPolygon( tools::Polygon
& rPoly
)
609 sal_uInt16 nPoints
= rPoly
.GetSize();
611 if ( !(( nPoints
> 1 ) && ImplCreateShape( u
"com.sun.star.drawing.PolyPolygonShape"_ustr
)) )
614 drawing::PointSequenceSequence aRetval
;
616 // prepare inside polygons
617 aRetval
.realloc( 1 );
619 // get pointer to outside arrays
620 drawing::PointSequence
* pOuterSequence
= aRetval
.getArray();
622 // make room in arrays
623 pOuterSequence
->realloc(static_cast<sal_Int32
>(nPoints
));
625 // get pointer to arrays
626 awt::Point
* pInnerSequence
= pOuterSequence
->getArray();
628 for( sal_uInt16 n
= 0; n
< nPoints
; n
++ )
629 *pInnerSequence
++ = awt::Point( rPoly
[ n
].X(), rPoly
[n
].Y() );
633 maXPropSet
->setPropertyValue( u
"PolyPolygon"_ustr
, aParam
);
637 void CGMImpressOutAct::DrawPolyLine( tools::Polygon
& rPoly
)
639 sal_uInt16 nPoints
= rPoly
.GetSize();
641 if ( !(( nPoints
> 1 ) && ImplCreateShape( u
"com.sun.star.drawing.PolyLineShape"_ustr
)) )
644 drawing::PointSequenceSequence aRetval
;
646 // prepare inside polygons
647 aRetval
.realloc( 1 );
649 // get pointer to outside arrays
650 drawing::PointSequence
* pOuterSequence
= aRetval
.getArray();
652 // make room in arrays
653 pOuterSequence
->realloc(static_cast<sal_Int32
>(nPoints
));
655 // get pointer to arrays
656 awt::Point
* pInnerSequence
= pOuterSequence
->getArray();
658 for( sal_uInt16 n
= 0; n
< nPoints
; n
++ )
659 *pInnerSequence
++ = awt::Point( rPoly
[ n
].X(), rPoly
[n
].Y() );
663 maXPropSet
->setPropertyValue( u
"PolyPolygon"_ustr
, aParam
);
667 void CGMImpressOutAct::DrawPolybezier( tools::Polygon
& rPolygon
)
669 sal_uInt16 nPoints
= rPolygon
.GetSize();
670 if ( !(( nPoints
> 1 ) && ImplCreateShape( u
"com.sun.star.drawing.OpenBezierShape"_ustr
)) )
673 drawing::PolyPolygonBezierCoords aRetval
;
675 aRetval
.Coordinates
.realloc( 1 );
676 aRetval
.Flags
.realloc( 1 );
678 // get pointer to outside arrays
679 drawing::PointSequence
* pOuterSequence
= aRetval
.Coordinates
.getArray();
680 drawing::FlagSequence
* pOuterFlags
= aRetval
.Flags
.getArray();
682 // make room in arrays
683 pOuterSequence
->realloc( nPoints
);
684 pOuterFlags
->realloc( nPoints
);
686 awt::Point
* pInnerSequence
= pOuterSequence
->getArray();
687 drawing::PolygonFlags
* pInnerFlags
= pOuterFlags
->getArray();
689 for( sal_uInt16 i
= 0; i
< nPoints
; i
++ )
691 *pInnerSequence
++ = awt::Point( rPolygon
[ i
].X(), rPolygon
[ i
].Y() );
692 *pInnerFlags
++ = static_cast<drawing::PolygonFlags
>(rPolygon
.GetFlags( i
));
696 maXPropSet
->setPropertyValue( u
"PolyPolygonBezier"_ustr
, aParam
);
700 void CGMImpressOutAct::DrawPolyPolygon( tools::PolyPolygon
const & rPolyPolygon
)
702 sal_uInt32 nNumPolys
= rPolyPolygon
.Count();
703 if ( !(nNumPolys
&& ImplCreateShape( u
"com.sun.star.drawing.ClosedBezierShape"_ustr
)) )
706 drawing::PolyPolygonBezierCoords aRetval
;
708 // prepare inside polygons
709 aRetval
.Coordinates
.realloc(static_cast<sal_Int32
>(nNumPolys
));
710 aRetval
.Flags
.realloc(static_cast<sal_Int32
>(nNumPolys
));
712 // get pointer to outside arrays
713 drawing::PointSequence
* pOuterSequence
= aRetval
.Coordinates
.getArray();
714 drawing::FlagSequence
* pOuterFlags
= aRetval
.Flags
.getArray();
716 for( sal_uInt32 a
= 0; a
< nNumPolys
; a
++ )
718 const tools::Polygon
& aPolygon( rPolyPolygon
.GetObject( a
) );
719 sal_uInt32 nNumPoints
= aPolygon
.GetSize();
721 // make room in arrays
722 pOuterSequence
->realloc(static_cast<sal_Int32
>(nNumPoints
));
723 pOuterFlags
->realloc(static_cast<sal_Int32
>(nNumPoints
));
725 // get pointer to arrays
726 awt::Point
* pInnerSequence
= pOuterSequence
->getArray();
727 drawing::PolygonFlags
* pInnerFlags
= pOuterFlags
->getArray();
729 for( sal_uInt32 b
= 0; b
< nNumPoints
; b
++ )
731 *pInnerSequence
++ = awt::Point( aPolygon
.GetPoint( b
).X(), aPolygon
.GetPoint( b
).Y() ) ;
732 *pInnerFlags
++ = static_cast<drawing::PolygonFlags
>(aPolygon
.GetFlags( b
));
739 maXPropSet
->setPropertyValue( u
"PolyPolygonBezier"_ustr
, aParam
);
743 void CGMImpressOutAct::DrawText(awt::Point
const & rTextPos
, awt::Size
const & rTextSize
, const OUString
& rString
, FinalFlag eFlag
)
745 if ( !ImplCreateShape( u
"com.sun.star.drawing.TextShape"_ustr
) )
749 tools::Long nWidth
= rTextSize
.Width
;
750 tools::Long nHeight
= rTextSize
.Height
;
752 awt::Point
aTextPos( rTextPos
);
753 switch ( mpCGM
->pElement
->eTextAlignmentV
)
757 aTextPos
.Y
= o3tl::saturating_add(aTextPos
.X
, static_cast<sal_Int32
>((mpCGM
->pElement
->nCharacterHeight
* -1.5) / 2));
764 aTextPos
.Y
= o3tl::saturating_add(aTextPos
.Y
, static_cast<sal_Int32
>(mpCGM
->pElement
->nCharacterHeight
* -1.5));
770 break; // -Wall these two were not here.
777 else if ( nWidth
== 0 )
785 else if ( nHeight
== 0 )
789 maXShape
->setPosition( aTextPos
);
790 maXShape
->setSize( awt::Size( nWidth
, nHeight
) );
791 double nX
= mpCGM
->pElement
->nCharacterOrientation
[ 2 ];
792 double nY
= mpCGM
->pElement
->nCharacterOrientation
[ 3 ];
793 double fSqrt
= std::hypot(nX
, nY
);
794 double nOrientation
= fSqrt
!= 0.0 ? basegfx::rad2deg(acos(nX
/ fSqrt
)) : 0.0;
796 nOrientation
= 360 - nOrientation
;
800 maXPropSet
->setPropertyValue( u
"RotationPointX"_ustr
, uno::Any(aTextPos
.X
) );
801 maXPropSet
->setPropertyValue( u
"RotationPointY"_ustr
, uno::Any(static_cast<sal_Int32
>( aTextPos
.Y
+ nHeight
)) );
802 maXPropSet
->setPropertyValue( u
"RotateAngle"_ustr
, uno::Any(static_cast<sal_Int32
>( nOrientation
* 100 )) );
807 maXPropSet
->setPropertyValue( u
"TextAutoGrowWidth"_ustr
, aAny
);
809 drawing::TextAdjust eTextAdjust
;
810 switch ( mpCGM
->pElement
->eTextAlignmentH
)
813 eTextAdjust
= drawing::TextAdjust_RIGHT
;
818 eTextAdjust
= drawing::TextAdjust_LEFT
;
821 eTextAdjust
= drawing::TextAdjust_CENTER
;
824 maXPropSet
->setPropertyValue( u
"TextHorizontalAdjust"_ustr
, uno::Any(eTextAdjust
) );
828 maXPropSet
->setPropertyValue( u
"TextAutoGrowHeight"_ustr
, uno::Any(true) );
830 uno::Reference
< text::XText
> xText
;
831 uno::Any
aFirstQuery( maXShape
->queryInterface( cppu::UnoType
<text::XText
>::get()));
832 if( aFirstQuery
>>= xText
)
834 uno::Reference
< text::XTextCursor
> aXTextCursor( xText
->createTextCursor() );
836 aXTextCursor
->gotoEnd( false );
837 uno::Reference
< text::XTextRange
> aCursorText
;
838 uno::Any
aSecondQuery( aXTextCursor
->queryInterface( cppu::UnoType
<text::XTextRange
>::get()));
839 if ( aSecondQuery
>>= aCursorText
)
841 uno::Reference
< beans::XPropertySet
> aCursorPropSet
;
843 uno::Any
aQuery( aCursorText
->queryInterface( cppu::UnoType
<beans::XPropertySet
>::get()));
844 if( aQuery
>>= aCursorPropSet
)
846 if ( nWidth
!= -1 ) // paragraph adjusting in a valid textbox ?
848 switch ( mpCGM
->pElement
->eTextAlignmentH
)
851 aAny
<<= sal_Int16(style::HorizontalAlignment_RIGHT
);
856 aAny
<<= sal_Int16(style::HorizontalAlignment_LEFT
);
859 aAny
<<= sal_Int16(style::HorizontalAlignment_CENTER
);
862 aCursorPropSet
->setPropertyValue( u
"ParaAdjust"_ustr
, aAny
);
864 if ( nWidth
> 0 && nHeight
> 0 ) // restricted text
867 maXPropSet
->setPropertyValue( u
"TextFitToSize"_ustr
, aAny
);
869 aCursorText
->setString(rString
);
870 aXTextCursor
->gotoEnd( true );
871 ImplSetTextBundle( aCursorPropSet
);
876 if ( eFlag
== FF_NOT_FINAL
)
878 nFinalTextCount
= maXShapes
->getCount();
882 void CGMImpressOutAct::AppendText( const char* pString
)
884 if ( !nFinalTextCount
)
887 uno::Reference
< drawing::XShape
> aShape
= *o3tl::doAccess
<uno::Reference
<drawing::XShape
>>(maXShapes
->getByIndex( nFinalTextCount
- 1 ));
891 uno::Reference
< text::XText
> xText
;
892 uno::Any
aFirstQuery( aShape
->queryInterface( cppu::UnoType
<text::XText
>::get()) );
893 if( !(aFirstQuery
>>= xText
) )
896 OUString
aStr(pString
, strlen(pString
), RTL_TEXTENCODING_ASCII_US
);
898 uno::Reference
< text::XTextCursor
> aXTextCursor( xText
->createTextCursor() );
899 if ( !aXTextCursor
.is() )
902 aXTextCursor
->gotoEnd( false );
903 uno::Reference
< text::XTextRange
> aCursorText
;
904 uno::Any
aSecondQuery(aXTextCursor
->queryInterface( cppu::UnoType
<text::XTextRange
>::get()));
905 if ( aSecondQuery
>>= aCursorText
)
907 uno::Reference
< beans::XPropertySet
> aPropSet
;
908 uno::Any
aQuery(aCursorText
->queryInterface( cppu::UnoType
<beans::XPropertySet
>::get()));
909 if( aQuery
>>= aPropSet
)
911 aCursorText
->setString( aStr
);
912 aXTextCursor
->gotoEnd( true );
913 ImplSetTextBundle( aPropSet
);
919 void CGMImpressOutAct::BeginFigure()
921 if (!maPoints
.empty())
929 void CGMImpressOutAct::CloseRegion()
931 if (maPoints
.size() > 2)
934 DrawPolyPolygon( maPolyPolygon
);
935 maPolyPolygon
.Clear();
939 void CGMImpressOutAct::NewRegion()
941 if (maPoints
.size() > 2)
943 tools::Polygon
aPolygon(maPoints
.size(), maPoints
.data(), maFlags
.data());
944 maPolyPolygon
.Insert( aPolygon
);
950 void CGMImpressOutAct::EndFigure()
953 DrawPolyPolygon( maPolyPolygon
);
954 maPolyPolygon
.Clear();
960 void CGMImpressOutAct::RegPolyLine( tools::Polygon
const & rPolygon
, bool bReverse
)
962 sal_uInt16 nPoints
= rPolygon
.GetSize();
968 for ( sal_uInt16 i
= 0; i
< nPoints
; i
++ )
970 maPoints
.push_back(rPolygon
.GetPoint(nPoints
- i
- 1));
971 maFlags
.push_back(rPolygon
.GetFlags(nPoints
- i
- 1));
976 for ( sal_uInt16 i
= 0; i
< nPoints
; i
++ )
978 maPoints
.push_back(rPolygon
.GetPoint(i
));
979 maFlags
.push_back(rPolygon
.GetFlags(i
));
984 void CGMImpressOutAct::SetGradientOffset( tools::Long nHorzOfs
, tools::Long nVertOfs
)
987 mpGradient
.reset( new awt::Gradient
);
988 mpGradient
->XOffset
= ( static_cast<sal_uInt16
>(nHorzOfs
) & 0x7f );
989 mpGradient
->YOffset
= ( static_cast<sal_uInt16
>(nVertOfs
) & 0x7f );
992 void CGMImpressOutAct::SetGradientAngle( tools::Long nAngle
)
995 mpGradient
.reset( new awt::Gradient
);
996 mpGradient
->Angle
= sal::static_int_cast
< sal_Int16
>(nAngle
);
999 void CGMImpressOutAct::SetGradientDescriptor( sal_uInt32 nColorFrom
, sal_uInt32 nColorTo
)
1002 mpGradient
.reset( new awt::Gradient
);
1003 mpGradient
->StartColor
= nColorFrom
;
1004 mpGradient
->EndColor
= nColorTo
;
1007 void CGMImpressOutAct::SetGradientStyle( sal_uInt32 nStyle
)
1010 mpGradient
.reset( new awt::Gradient
);
1015 mpGradient
->Style
= awt::GradientStyle_AXIAL
;
1020 mpGradient
->Style
= awt::GradientStyle_RADIAL
; // CONICAL
1025 mpGradient
->Style
= awt::GradientStyle_RECT
;
1030 mpGradient
->Style
= awt::GradientStyle_ELLIPTICAL
;
1035 mpGradient
->Style
= awt::GradientStyle_LINEAR
;
1040 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */