nss: upgrade to release 3.73
[LibreOffice.git] / filter / source / graphicfilter / icgm / actimpr.cxx
blob48a71609519e362aa0836fe32e4fa1d9feca7339
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
22 #include <o3tl/any.hxx>
23 #include <o3tl/safeint.hxx>
24 #include <vcl/bitmapex.hxx>
25 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
26 #include <com/sun/star/drawing/LineStyle.hpp>
27 #include <com/sun/star/drawing/LineDash.hpp>
28 #include <com/sun/star/drawing/FillStyle.hpp>
29 #include <com/sun/star/drawing/Hatch.hpp>
30 #include <com/sun/star/awt/FontDescriptor.hpp>
31 #include <com/sun/star/awt/FontWeight.hpp>
32 #include <com/sun/star/awt/FontUnderline.hpp>
33 #include <com/sun/star/drawing/XShapeGrouper.hpp>
34 #include <com/sun/star/drawing/CircleKind.hpp>
35 #include <com/sun/star/awt/XBitmap.hpp>
36 #include <com/sun/star/drawing/PointSequenceSequence.hpp>
37 #include <com/sun/star/drawing/PointSequence.hpp>
38 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
39 #include <com/sun/star/drawing/FlagSequence.hpp>
40 #include <com/sun/star/drawing/ShapeCollection.hpp>
41 #include <com/sun/star/drawing/TextAdjust.hpp>
42 #include <com/sun/star/text/XText.hpp>
43 #include <com/sun/star/text/XTextRange.hpp>
44 #include <com/sun/star/style/HorizontalAlignment.hpp>
46 #include <comphelper/processfactory.hxx>
47 #include <toolkit/helper/vclunohelper.hxx>
48 #include <tools/helpers.hxx>
49 #include <unotools/configmgr.hxx>
51 #include "bitmap.hxx"
52 #include "elements.hxx"
53 #include "outact.hxx"
55 #define MAX_PAGES_FOR_FUZZING 2048
57 using namespace ::com::sun::star;
59 CGMImpressOutAct::CGMImpressOutAct(CGM& rCGM, const uno::Reference< frame::XModel > & rModel)
60 : mnCurrentPage(0)
61 , mnGroupActCount(0)
62 , mnGroupLevel(0)
63 , maGroupLevel()
64 , mpCGM(&rCGM)
65 , nFinalTextCount(0)
67 if ( !mpCGM->mbStatus )
68 return;
70 bool bStatRet = false;
72 uno::Reference< drawing::XDrawPagesSupplier > aDrawPageSup( rModel, uno::UNO_QUERY );
73 if( aDrawPageSup.is() )
75 maXDrawPages = aDrawPageSup->getDrawPages();
76 if ( maXDrawPages.is() )
78 maXMultiServiceFactory.set( rModel, uno::UNO_QUERY);
79 if( maXMultiServiceFactory.is() )
81 maXDrawPage = *o3tl::doAccess<uno::Reference<drawing::XDrawPage>>(maXDrawPages->getByIndex( 0 ));
82 if ( ImplInitPage() )
83 bStatRet = true;
87 mpCGM->mbStatus = bStatRet;
90 CGMImpressOutAct::~CGMImpressOutAct()
92 for (auto &a : maLockedNewXShapes)
93 a->removeActionLock();
96 bool CGMImpressOutAct::ImplInitPage()
98 bool bStatRet = false;
99 if( maXDrawPage.is() )
101 maXShapes = maXDrawPage;
102 if ( maXShapes.is() )
104 bStatRet = true;
107 return bStatRet;
110 bool CGMImpressOutAct::ImplCreateShape( const OUString& rType )
112 if (utl::ConfigManager::IsFuzzing())
113 return false;
114 uno::Reference< uno::XInterface > xNewShape( maXMultiServiceFactory->createInstance( rType ) );
115 maXShape.set( xNewShape, uno::UNO_QUERY );
116 maXPropSet.set( xNewShape, uno::UNO_QUERY );
117 if ( maXShape.is() && maXPropSet.is() )
119 maXShapes->add( maXShape );
120 uno::Reference<document::XActionLockable> xLockable(maXShape, uno::UNO_QUERY);
121 if (xLockable)
123 xLockable->addActionLock();
124 maLockedNewXShapes.push_back(xLockable);
126 return true;
128 return false;
131 void CGMImpressOutAct::ImplSetOrientation( FloatPoint const & rRefPoint, double rOrientation )
133 maXPropSet->setPropertyValue( "RotationPointX", uno::Any(static_cast<sal_Int32>(rRefPoint.X)) );
134 maXPropSet->setPropertyValue( "RotationPointY", uno::Any(static_cast<sal_Int32>(rRefPoint.Y)) );
135 maXPropSet->setPropertyValue( "RotateAngle", uno::Any(static_cast<sal_Int32>( rOrientation * 100.0 )) );
139 void CGMImpressOutAct::ImplSetLineBundle()
141 drawing::LineStyle eLS;
143 sal_uInt32 nLineColor;
144 LineType eLineType;
145 double fLineWidth;
147 if ( mpCGM->pElement->nAspectSourceFlags & ASF_LINECOLOR )
148 nLineColor = mpCGM->pElement->pLineBundle->GetColor();
149 else
150 nLineColor = mpCGM->pElement->aLineBundle.GetColor();
151 if ( mpCGM->pElement->nAspectSourceFlags & ASF_LINETYPE )
152 eLineType = mpCGM->pElement->pLineBundle->eLineType;
153 else
154 eLineType = mpCGM->pElement->aLineBundle.eLineType;
155 if ( mpCGM->pElement->nAspectSourceFlags & ASF_LINEWIDTH )
156 fLineWidth = mpCGM->pElement->pLineBundle->nLineWidth;
157 else
158 fLineWidth = mpCGM->pElement->aLineBundle.nLineWidth;
160 maXPropSet->setPropertyValue( "LineColor", uno::Any(static_cast<sal_Int32>(nLineColor)) );
162 maXPropSet->setPropertyValue( "LineWidth", uno::Any(static_cast<sal_Int32>(fLineWidth)) );
164 switch( eLineType )
166 case LT_NONE :
167 eLS = drawing::LineStyle_NONE;
168 break;
169 case LT_DASH :
170 case LT_DOT :
171 case LT_DASHDOT :
172 case LT_DOTDOTSPACE :
173 case LT_LONGDASH :
174 case LT_DASHDASHDOT :
175 eLS = drawing::LineStyle_DASH;
176 break;
177 case LT_SOLID :
178 default:
179 eLS = drawing::LineStyle_SOLID;
180 break;
182 maXPropSet->setPropertyValue( "LineStyle", uno::Any(eLS) );
183 if ( eLS == drawing::LineStyle_DASH )
185 drawing::LineDash aLineDash( drawing::DashStyle_RECTRELATIVE, 1, 50, 3, 33, 100 );
186 maXPropSet->setPropertyValue( "LineDash", uno::Any(aLineDash) );
190 void CGMImpressOutAct::ImplSetFillBundle()
192 drawing::LineStyle eLS;
193 drawing::FillStyle eFS;
195 sal_uInt32 nEdgeColor = 0;
196 EdgeType eEdgeType;
197 double fEdgeWidth = 0;
199 sal_uInt32 nFillColor;
200 FillInteriorStyle eFillStyle;
201 sal_uInt32 nHatchIndex;
203 if ( mpCGM->pElement->eEdgeVisibility == EV_ON )
205 if ( mpCGM->pElement->nAspectSourceFlags & ASF_EDGETYPE )
206 eEdgeType = mpCGM->pElement->pEdgeBundle->eEdgeType;
207 else
208 eEdgeType = mpCGM->pElement->aEdgeBundle.eEdgeType;
209 if ( mpCGM->pElement->nAspectSourceFlags & ASF_EDGEWIDTH )
210 fEdgeWidth = mpCGM->pElement->pEdgeBundle->nEdgeWidth;
211 else
212 fEdgeWidth = mpCGM->pElement->aEdgeBundle.nEdgeWidth;
213 if ( mpCGM->pElement->nAspectSourceFlags & ASF_EDGECOLOR )
214 nEdgeColor = mpCGM->pElement->pEdgeBundle->GetColor();
215 else
216 nEdgeColor = mpCGM->pElement->aEdgeBundle.GetColor();
218 else
219 eEdgeType = ET_NONE;
221 if ( mpCGM->pElement->nAspectSourceFlags & ASF_FILLINTERIORSTYLE )
222 eFillStyle = mpCGM->pElement->pFillBundle->eFillInteriorStyle;
223 else
224 eFillStyle = mpCGM->pElement->aFillBundle.eFillInteriorStyle;
225 if ( mpCGM->pElement->nAspectSourceFlags & ASF_FILLCOLOR )
226 nFillColor = mpCGM->pElement->pFillBundle->GetColor();
227 else
228 nFillColor = mpCGM->pElement->aFillBundle.GetColor();
229 if ( mpCGM->pElement->nAspectSourceFlags & ASF_HATCHINDEX )
230 nHatchIndex = static_cast<sal_uInt32>(mpCGM->pElement->pFillBundle->nFillHatchIndex);
231 else
232 nHatchIndex = static_cast<sal_uInt32>(mpCGM->pElement->aFillBundle.nFillHatchIndex);
234 maXPropSet->setPropertyValue( "FillColor", uno::Any(static_cast<sal_Int32>(nFillColor)) );
236 switch ( eFillStyle )
238 case FIS_HATCH :
240 if ( nHatchIndex == 0 )
241 eFS = drawing::FillStyle_NONE;
242 else
243 eFS = drawing::FillStyle_HATCH;
245 break;
246 case FIS_PATTERN :
247 case FIS_SOLID :
249 eFS = drawing::FillStyle_SOLID;
251 break;
253 case FIS_GEOPATTERN :
255 if ( mpCGM->pElement->eTransparency == T_ON )
256 nFillColor = mpCGM->pElement->nAuxiliaryColor;
257 eFS = drawing::FillStyle_NONE;
259 break;
261 case FIS_INTERPOLATED :
262 case FIS_GRADIENT :
264 eFS = drawing::FillStyle_GRADIENT;
266 break;
268 case FIS_HOLLOW :
269 case FIS_EMPTY :
270 default:
272 eFS = drawing::FillStyle_NONE;
276 if ( mpCGM->mnAct4PostReset & ACT4_GRADIENT_ACTION )
277 eFS = drawing::FillStyle_GRADIENT;
279 if ( eFS == drawing::FillStyle_GRADIENT )
281 maXPropSet->setPropertyValue( "FillGradient", uno::Any(*mpGradient) );
283 maXPropSet->setPropertyValue( "FillStyle", uno::Any(eFS) );
285 eLS = drawing::LineStyle_NONE;
286 if ( eFillStyle == FIS_HOLLOW )
288 eLS = drawing::LineStyle_SOLID;
289 maXPropSet->setPropertyValue( "LineColor", uno::Any(static_cast<sal_Int32>(nFillColor)) );
290 maXPropSet->setPropertyValue( "LineWidth", uno::Any(sal_Int32(0)) );
292 else if ( eEdgeType != ET_NONE )
294 maXPropSet->setPropertyValue( "LineColor", uno::Any(static_cast<sal_Int32>(nEdgeColor)) );
296 maXPropSet->setPropertyValue( "LineWidth", uno::Any(static_cast<sal_Int32>(fEdgeWidth)) );
298 switch( eEdgeType )
300 case ET_DASH :
301 case ET_DOT :
302 case ET_DASHDOT :
303 case ET_DASHDOTDOT :
304 case ET_DOTDOTSPACE :
305 case ET_LONGDASH :
306 case ET_DASHDASHDOT :
307 default: // case ET_SOLID :
309 eLS = drawing::LineStyle_SOLID;
311 break;
315 maXPropSet->setPropertyValue( "LineStyle", uno::Any(eLS) );
317 if ( eFS != drawing::FillStyle_HATCH )
318 return;
320 drawing::Hatch aHatch;
322 aHatch.Color = nFillColor;
323 if ( mpCGM->pElement->maHatchMap.find( nHatchIndex ) != mpCGM->pElement->maHatchMap.end() )
325 HatchEntry& rHatchEntry = mpCGM->pElement->maHatchMap[ nHatchIndex ];
326 switch ( rHatchEntry.HatchStyle )
328 case 0 : aHatch.Style = drawing::HatchStyle_SINGLE; break;
329 case 1 : aHatch.Style = drawing::HatchStyle_DOUBLE; break;
330 case 2 : aHatch.Style = drawing::HatchStyle_TRIPLE; break;
332 aHatch.Distance = rHatchEntry.HatchDistance;
333 aHatch.Angle = rHatchEntry.HatchAngle;
335 else
337 aHatch.Style = drawing::HatchStyle_TRIPLE;
338 aHatch.Distance = 10 * ( nHatchIndex & 0x1f ) | 100;
339 aHatch.Angle = 15 * ( ( nHatchIndex & 0x1f ) - 5 );
341 maXPropSet->setPropertyValue( "FillHatch", uno::Any(aHatch) );
344 void CGMImpressOutAct::ImplSetTextBundle( const uno::Reference< beans::XPropertySet > & rProperty )
346 sal_uInt32 nTextFontIndex;
347 sal_uInt32 nTextColor;
349 if ( mpCGM->pElement->nAspectSourceFlags & ASF_TEXTFONTINDEX )
350 nTextFontIndex = mpCGM->pElement->pTextBundle->nTextFontIndex;
351 else
352 nTextFontIndex = mpCGM->pElement->aTextBundle.nTextFontIndex;
353 if ( mpCGM->pElement->nAspectSourceFlags & ASF_TEXTCOLOR )
354 nTextColor = mpCGM->pElement->pTextBundle->GetColor();
355 else
356 nTextColor = mpCGM->pElement->aTextBundle.GetColor();
358 rProperty->setPropertyValue( "CharColor", uno::Any(static_cast<sal_Int32>(nTextColor)) );
360 sal_uInt32 nFontType = 0;
361 awt::FontDescriptor aFontDescriptor;
362 FontEntry* pFontEntry = mpCGM->pElement->aFontList.GetFontEntry( nTextFontIndex );
363 if ( pFontEntry )
365 nFontType = pFontEntry->nFontType;
366 aFontDescriptor.Name = OUString(reinterpret_cast<char*>(pFontEntry->aFontName.data()),
367 pFontEntry->aFontName.size(),
368 RTL_TEXTENCODING_ASCII_US);
370 aFontDescriptor.Height = sal_Int16( mpCGM->pElement->nCharacterHeight * 1.50 );
371 if ( nFontType & 1 )
372 aFontDescriptor.Slant = awt::FontSlant_ITALIC;
373 if ( nFontType & 2 )
374 aFontDescriptor.Weight = awt::FontWeight::BOLD;
375 else
376 aFontDescriptor.Weight = awt::FontWeight::NORMAL;
378 if ( mpCGM->pElement->eUnderlineMode != UM_OFF )
380 aFontDescriptor.Underline = awt::FontUnderline::SINGLE;
382 rProperty->setPropertyValue( "FontDescriptor", uno::Any(aFontDescriptor) );
385 void CGMImpressOutAct::InsertPage()
387 if ( mnCurrentPage ) // one side is always existing, therefore the first side will be left out
389 uno::Reference< drawing::XDrawPage > xPage = maXDrawPages->insertNewByIndex( 0xffff );
390 maXDrawPage = xPage;
391 if ( !ImplInitPage() )
392 mpCGM->mbStatus = false;
393 if (mnCurrentPage > MAX_PAGES_FOR_FUZZING && utl::ConfigManager::IsFuzzing())
395 // ofz#21753 that's enough pages for fuzzing, we're not doing anything productive now
396 mpCGM->mbStatus = false;
399 mnCurrentPage++;
402 void CGMImpressOutAct::BeginGroup()
404 if ( mnGroupLevel < CGM_OUTACT_MAX_GROUP_LEVEL )
406 maGroupLevel[mnGroupLevel] = maXShapes->getCount();
408 ++mnGroupLevel;
409 mnGroupActCount = mpCGM->mnActCount;
412 void CGMImpressOutAct::EndGroup()
414 if (!mnGroupLevel)
415 return;
416 --mnGroupLevel;
417 if ( mnGroupLevel >= CGM_OUTACT_MAX_GROUP_LEVEL )
418 return;
420 sal_uInt32 nFirstIndex = maGroupLevel[mnGroupLevel];
421 if ( nFirstIndex == 0xffffffff )
422 nFirstIndex = 0;
423 sal_uInt32 nCurrentCount = maXShapes->getCount();
424 if ( ( nCurrentCount - nFirstIndex ) <= 1 )
425 return;
427 uno::Reference< drawing::XShapeGrouper > aXShapeGrouper;
428 aXShapeGrouper.set( maXDrawPage, uno::UNO_QUERY );
429 if( !aXShapeGrouper.is() )
430 return;
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 ));
436 if (aXShape.is() )
438 aXShapes->add( aXShape );
441 aXShapeGrouper->group( aXShapes );
444 void CGMImpressOutAct::EndGrouping()
446 while ( mnGroupLevel )
448 EndGroup();
452 void CGMImpressOutAct::DrawRectangle( FloatRect const & rFloatRect )
454 if ( mnGroupActCount != ( mpCGM->mnActCount - 1 ) ) // POWERPOINT HACK !!!
456 if ( ImplCreateShape( "com.sun.star.drawing.RectangleShape" ) )
458 awt::Size aSize( static_cast<tools::Long>(rFloatRect.Right - rFloatRect.Left ), static_cast<tools::Long>(rFloatRect.Bottom-rFloatRect.Top ) );
459 maXShape->setSize( aSize );
460 maXShape->setPosition( awt::Point( static_cast<tools::Long>(rFloatRect.Left), static_cast<tools::Long>(rFloatRect.Top) ) );
461 ImplSetFillBundle();
466 void CGMImpressOutAct::DrawEllipse( FloatPoint const & rCenter, FloatPoint const & rSize, double& rOrientation )
468 if ( !ImplCreateShape( "com.sun.star.drawing.EllipseShape" ) )
469 return;
471 drawing::CircleKind eCircleKind = drawing::CircleKind_FULL;
472 uno::Any aAny( &eCircleKind, ::cppu::UnoType<drawing::CircleKind>::get() );
473 maXPropSet->setPropertyValue( "CircleKind", aAny );
475 tools::Long nXSize = static_cast<tools::Long>( rSize.X * 2.0 ); // strange behaviour with an awt::Size of 0
476 tools::Long nYSize = static_cast<tools::Long>( rSize.Y * 2.0 );
477 if ( nXSize < 1 )
478 nXSize = 1;
479 if ( nYSize < 1 )
480 nYSize = 1;
481 maXShape->setSize( awt::Size( nXSize, nYSize ) );
482 maXShape->setPosition( awt::Point( static_cast<tools::Long>( rCenter.X - rSize.X ), static_cast<tools::Long>( rCenter.Y - rSize.Y ) ) );
484 if ( rOrientation != 0 )
486 ImplSetOrientation( rCenter, rOrientation );
488 ImplSetFillBundle();
491 void CGMImpressOutAct::DrawEllipticalArc( FloatPoint const & rCenter, FloatPoint const & rSize, double& rOrientation,
492 sal_uInt32 nType, double& fStartAngle, double& fEndAngle )
494 if ( !ImplCreateShape( "com.sun.star.drawing.EllipseShape" ) )
495 return;
497 uno::Any aAny;
498 drawing::CircleKind eCircleKind;
501 tools::Long nXSize = static_cast<tools::Long>( rSize.X * 2.0 ); // strange behaviour with an awt::Size of 0
502 tools::Long nYSize = static_cast<tools::Long>( rSize.Y * 2.0 );
503 if ( nXSize < 1 )
504 nXSize = 1;
505 if ( nYSize < 1 )
506 nYSize = 1;
508 maXShape->setSize( awt::Size ( nXSize, nYSize ) );
510 if ( rOrientation != 0 )
512 fStartAngle = NormAngle360(fStartAngle + rOrientation);
513 fEndAngle = NormAngle360(fEndAngle + rOrientation);
515 switch( nType )
517 case 0 : eCircleKind = drawing::CircleKind_SECTION; break;
518 case 1 : eCircleKind = drawing::CircleKind_CUT; break;
519 case 2 : eCircleKind = drawing::CircleKind_ARC; break;
520 default : eCircleKind = drawing::CircleKind_FULL; break;
522 if ( static_cast<tools::Long>(fStartAngle) == static_cast<tools::Long>(fEndAngle) )
524 eCircleKind = drawing::CircleKind_FULL;
525 maXPropSet->setPropertyValue( "CircleKind", uno::Any(eCircleKind) );
527 else
529 maXPropSet->setPropertyValue( "CircleKind", uno::Any(eCircleKind) );
530 maXPropSet->setPropertyValue( "CircleStartAngle", uno::Any(static_cast<sal_Int32>( fStartAngle * 100 )) );
531 maXPropSet->setPropertyValue( "CircleEndAngle", uno::Any(static_cast<sal_Int32>( fEndAngle * 100 )) );
533 maXShape->setPosition( awt::Point( static_cast<tools::Long>( rCenter.X - rSize.X ), static_cast<tools::Long>( rCenter.Y - rSize.Y ) ) );
534 if ( rOrientation != 0 )
536 ImplSetOrientation( rCenter, rOrientation );
538 if ( eCircleKind == drawing::CircleKind_ARC )
540 ImplSetLineBundle();
542 else
544 ImplSetFillBundle();
545 if ( nType == 2 )
547 ImplSetLineBundle();
548 aAny <<= drawing::FillStyle_NONE;
549 maXPropSet->setPropertyValue( "FillStyle", aAny );
554 void CGMImpressOutAct::DrawBitmap( CGMBitmapDescriptor* pBmpDesc )
556 if ( !pBmpDesc->mbStatus || !pBmpDesc->mxBitmap )
557 return;
559 FloatPoint aOrigin = pBmpDesc->mnOrigin;
560 double fdx = pBmpDesc->mndx;
561 double fdy = pBmpDesc->mndy;
563 BmpMirrorFlags nMirr = BmpMirrorFlags::NONE;
564 if ( pBmpDesc->mbVMirror )
565 nMirr |= BmpMirrorFlags::Vertical;
566 if ( nMirr != BmpMirrorFlags::NONE )
567 pBmpDesc->mxBitmap.Mirror( nMirr );
569 mpCGM->ImplMapPoint( aOrigin );
570 mpCGM->ImplMapX( fdx );
571 mpCGM->ImplMapY( fdy );
573 if ( !ImplCreateShape( "com.sun.star.drawing.GraphicObjectShape" ) )
574 return;
576 maXShape->setSize( awt::Size( static_cast<tools::Long>(fdx), static_cast<tools::Long>(fdy) ) );
577 maXShape->setPosition( awt::Point( static_cast<tools::Long>(aOrigin.X), static_cast<tools::Long>(aOrigin.Y) ) );
579 if ( pBmpDesc->mnOrientation != 0 )
581 ImplSetOrientation( aOrigin, pBmpDesc->mnOrientation );
584 uno::Reference< awt::XBitmap > xBitmap( VCLUnoHelper::CreateBitmap( pBmpDesc->mxBitmap ) );
585 maXPropSet->setPropertyValue( "GraphicObjectFillBitmap", uno::Any(xBitmap) );
588 void CGMImpressOutAct::DrawPolygon( tools::Polygon& rPoly )
590 sal_uInt16 nPoints = rPoly.GetSize();
592 if ( !(( nPoints > 1 ) && ImplCreateShape( "com.sun.star.drawing.PolyPolygonShape" )) )
593 return;
595 drawing::PointSequenceSequence aRetval;
597 // prepare inside polygons
598 aRetval.realloc( 1 );
600 // get pointer to outside arrays
601 drawing::PointSequence* pOuterSequence = aRetval.getArray();
603 // make room in arrays
604 pOuterSequence->realloc(static_cast<sal_Int32>(nPoints));
606 // get pointer to arrays
607 awt::Point* pInnerSequence = pOuterSequence->getArray();
609 for( sal_uInt16 n = 0; n < nPoints; n++ )
610 *pInnerSequence++ = awt::Point( rPoly[ n ].X(), rPoly[n].Y() );
612 uno::Any aParam;
613 aParam <<= aRetval;
614 maXPropSet->setPropertyValue( "PolyPolygon", aParam );
615 ImplSetFillBundle();
618 void CGMImpressOutAct::DrawPolyLine( tools::Polygon& rPoly )
620 sal_uInt16 nPoints = rPoly.GetSize();
622 if ( !(( nPoints > 1 ) && ImplCreateShape( "com.sun.star.drawing.PolyLineShape" )) )
623 return;
625 drawing::PointSequenceSequence aRetval;
627 // prepare inside polygons
628 aRetval.realloc( 1 );
630 // get pointer to outside arrays
631 drawing::PointSequence* pOuterSequence = aRetval.getArray();
633 // make room in arrays
634 pOuterSequence->realloc(static_cast<sal_Int32>(nPoints));
636 // get pointer to arrays
637 awt::Point* pInnerSequence = pOuterSequence->getArray();
639 for( sal_uInt16 n = 0; n < nPoints; n++ )
640 *pInnerSequence++ = awt::Point( rPoly[ n ].X(), rPoly[n].Y() );
642 uno::Any aParam;
643 aParam <<= aRetval;
644 maXPropSet->setPropertyValue( "PolyPolygon", aParam );
645 ImplSetLineBundle();
648 void CGMImpressOutAct::DrawPolybezier( tools::Polygon& rPolygon )
650 sal_uInt16 nPoints = rPolygon.GetSize();
651 if ( !(( nPoints > 1 ) && ImplCreateShape( "com.sun.star.drawing.OpenBezierShape" )) )
652 return;
654 drawing::PolyPolygonBezierCoords aRetval;
656 aRetval.Coordinates.realloc( 1 );
657 aRetval.Flags.realloc( 1 );
659 // get pointer to outside arrays
660 drawing::PointSequence* pOuterSequence = aRetval.Coordinates.getArray();
661 drawing::FlagSequence* pOuterFlags = aRetval.Flags.getArray();
663 // make room in arrays
664 pOuterSequence->realloc( nPoints );
665 pOuterFlags->realloc( nPoints );
667 awt::Point* pInnerSequence = pOuterSequence->getArray();
668 drawing::PolygonFlags* pInnerFlags = pOuterFlags->getArray();
670 for( sal_uInt16 i = 0; i < nPoints; i++ )
672 *pInnerSequence++ = awt::Point( rPolygon[ i ].X(), rPolygon[ i ].Y() );
673 *pInnerFlags++ = static_cast<drawing::PolygonFlags>(rPolygon.GetFlags( i ));
675 uno::Any aParam;
676 aParam <<= aRetval;
677 maXPropSet->setPropertyValue( "PolyPolygonBezier", aParam );
678 ImplSetLineBundle();
681 void CGMImpressOutAct::DrawPolyPolygon( tools::PolyPolygon const & rPolyPolygon )
683 sal_uInt32 nNumPolys = rPolyPolygon.Count();
684 if ( !(nNumPolys && ImplCreateShape( "com.sun.star.drawing.ClosedBezierShape" )) )
685 return;
687 drawing::PolyPolygonBezierCoords aRetval;
689 // prepare inside polygons
690 aRetval.Coordinates.realloc(static_cast<sal_Int32>(nNumPolys));
691 aRetval.Flags.realloc(static_cast<sal_Int32>(nNumPolys));
693 // get pointer to outside arrays
694 drawing::PointSequence* pOuterSequence = aRetval.Coordinates.getArray();
695 drawing::FlagSequence* pOuterFlags = aRetval.Flags.getArray();
697 for( sal_uInt32 a = 0; a < nNumPolys; a++ )
699 const tools::Polygon& aPolygon( rPolyPolygon.GetObject( a ) );
700 sal_uInt32 nNumPoints = aPolygon.GetSize();
702 // make room in arrays
703 pOuterSequence->realloc(static_cast<sal_Int32>(nNumPoints));
704 pOuterFlags->realloc(static_cast<sal_Int32>(nNumPoints));
706 // get pointer to arrays
707 awt::Point* pInnerSequence = pOuterSequence->getArray();
708 drawing::PolygonFlags* pInnerFlags = pOuterFlags->getArray();
710 for( sal_uInt32 b = 0; b < nNumPoints; b++ )
712 *pInnerSequence++ = awt::Point( aPolygon.GetPoint( b ).X(), aPolygon.GetPoint( b ).Y() ) ;
713 *pInnerFlags++ = static_cast<drawing::PolygonFlags>(aPolygon.GetFlags( b ));
715 pOuterSequence++;
716 pOuterFlags++;
718 uno::Any aParam;
719 aParam <<= aRetval;
720 maXPropSet->setPropertyValue( "PolyPolygonBezier", aParam);
721 ImplSetFillBundle();
724 void CGMImpressOutAct::DrawText(awt::Point const & rTextPos, awt::Size const & rTextSize, const OUString& rString, FinalFlag eFlag)
726 if ( !ImplCreateShape( "com.sun.star.drawing.TextShape" ) )
727 return;
729 uno::Any aAny;
730 tools::Long nWidth = rTextSize.Width;
731 tools::Long nHeight = rTextSize.Height;
733 awt::Point aTextPos( rTextPos );
734 switch ( mpCGM->pElement->eTextAlignmentV )
736 case TAV_HALF :
738 aTextPos.Y = o3tl::saturating_add(aTextPos.X, static_cast<sal_Int32>((mpCGM->pElement->nCharacterHeight * -1.5) / 2));
740 break;
742 case TAV_BASE :
743 case TAV_BOTTOM :
744 case TAV_NORMAL :
745 aTextPos.Y = o3tl::saturating_add(aTextPos.Y, static_cast<sal_Int32>(mpCGM->pElement->nCharacterHeight * -1.5));
746 break;
747 case TAV_TOP :
748 break;
749 case TAV_CAP:
750 case TAV_CONT:
751 break; // -Wall these two were not here.
754 if ( nWidth < 0 )
756 nWidth = -nWidth;
758 else if ( nWidth == 0 )
760 nWidth = -1;
762 if ( nHeight < 0 )
764 nHeight = -nHeight;
766 else if ( nHeight == 0 )
768 nHeight = -1;
770 maXShape->setPosition( aTextPos );
771 maXShape->setSize( awt::Size( nWidth, nHeight ) );
772 double nX = mpCGM->pElement->nCharacterOrientation[ 2 ];
773 double nY = mpCGM->pElement->nCharacterOrientation[ 3 ];
774 double fSqrt = sqrt(nX * nX + nY * nY);
775 double nOrientation = fSqrt != 0.0 ? (acos(nX / fSqrt) * 57.29577951308) : 0.0;
776 if ( nY < 0 )
777 nOrientation = 360 - nOrientation;
779 if ( nOrientation )
781 maXPropSet->setPropertyValue( "RotationPointX", uno::Any(aTextPos.X) );
782 maXPropSet->setPropertyValue( "RotationPointY", uno::Any(static_cast<sal_Int32>( aTextPos.Y + nHeight )) );
783 maXPropSet->setPropertyValue( "RotateAngle", uno::Any(static_cast<sal_Int32>( nOrientation * 100 )) );
785 if ( nWidth == -1 )
787 aAny <<= true;
788 maXPropSet->setPropertyValue( "TextAutoGrowWidth", aAny );
790 drawing::TextAdjust eTextAdjust;
791 switch ( mpCGM->pElement->eTextAlignmentH )
793 case TAH_RIGHT :
794 eTextAdjust = drawing::TextAdjust_RIGHT;
795 break;
796 case TAH_LEFT :
797 case TAH_CONT :
798 case TAH_NORMAL :
799 eTextAdjust = drawing::TextAdjust_LEFT;
800 break;
801 case TAH_CENTER :
802 eTextAdjust = drawing::TextAdjust_CENTER;
803 break;
805 maXPropSet->setPropertyValue( "TextHorizontalAdjust", uno::Any(eTextAdjust) );
807 if ( nHeight == -1 )
809 maXPropSet->setPropertyValue( "TextAutoGrowHeight", uno::Any(true) );
811 uno::Reference< text::XText > xText;
812 uno::Any aFirstQuery( maXShape->queryInterface( cppu::UnoType<text::XText>::get()));
813 if( aFirstQuery >>= xText )
815 uno::Reference< text::XTextCursor > aXTextCursor( xText->createTextCursor() );
817 aXTextCursor->gotoEnd( false );
818 uno::Reference< text::XTextRange > aCursorText;
819 uno::Any aSecondQuery( aXTextCursor->queryInterface( cppu::UnoType<text::XTextRange>::get()));
820 if ( aSecondQuery >>= aCursorText )
822 uno::Reference< beans::XPropertySet > aCursorPropSet;
824 uno::Any aQuery( aCursorText->queryInterface( cppu::UnoType<beans::XPropertySet>::get()));
825 if( aQuery >>= aCursorPropSet )
827 if ( nWidth != -1 ) // paragraph adjusting in a valid textbox ?
829 switch ( mpCGM->pElement->eTextAlignmentH )
831 case TAH_RIGHT :
832 aAny <<= sal_Int16(style::HorizontalAlignment_RIGHT);
833 break;
834 case TAH_LEFT :
835 case TAH_CONT :
836 case TAH_NORMAL :
837 aAny <<= sal_Int16(style::HorizontalAlignment_LEFT);
838 break;
839 case TAH_CENTER :
840 aAny <<= sal_Int16(style::HorizontalAlignment_CENTER);
841 break;
843 aCursorPropSet->setPropertyValue( "ParaAdjust", aAny );
845 if ( nWidth > 0 && nHeight > 0 ) // restricted text
847 aAny <<= true;
848 maXPropSet->setPropertyValue( "TextFitToSize", aAny );
850 aCursorText->setString(rString);
851 aXTextCursor->gotoEnd( true );
852 ImplSetTextBundle( aCursorPropSet );
857 if ( eFlag == FF_NOT_FINAL )
859 nFinalTextCount = maXShapes->getCount();
863 void CGMImpressOutAct::AppendText( const char* pString )
865 if ( !nFinalTextCount )
866 return;
868 uno::Reference< drawing::XShape > aShape = *o3tl::doAccess<uno::Reference<drawing::XShape>>(maXShapes->getByIndex( nFinalTextCount - 1 ));
869 if ( !aShape.is() )
870 return;
872 uno::Reference< text::XText > xText;
873 uno::Any aFirstQuery( aShape->queryInterface( cppu::UnoType<text::XText>::get()) );
874 if( !(aFirstQuery >>= xText) )
875 return;
877 OUString aStr(pString, strlen(pString), RTL_TEXTENCODING_ASCII_US);
879 uno::Reference< text::XTextCursor > aXTextCursor( xText->createTextCursor() );
880 if ( !aXTextCursor.is() )
881 return;
883 aXTextCursor->gotoEnd( false );
884 uno::Reference< text::XTextRange > aCursorText;
885 uno::Any aSecondQuery(aXTextCursor->queryInterface( cppu::UnoType<text::XTextRange>::get()));
886 if ( aSecondQuery >>= aCursorText )
888 uno::Reference< beans::XPropertySet > aPropSet;
889 uno::Any aQuery(aCursorText->queryInterface( cppu::UnoType<beans::XPropertySet>::get()));
890 if( aQuery >>= aPropSet )
892 aCursorText->setString( aStr );
893 aXTextCursor->gotoEnd( true );
894 ImplSetTextBundle( aPropSet );
900 void CGMImpressOutAct::BeginFigure()
902 if (!maPoints.empty())
903 EndFigure();
905 BeginGroup();
906 maPoints.clear();
907 maFlags.clear();
910 void CGMImpressOutAct::CloseRegion()
912 if (maPoints.size() > 2)
914 NewRegion();
915 DrawPolyPolygon( maPolyPolygon );
916 maPolyPolygon.Clear();
920 void CGMImpressOutAct::NewRegion()
922 if (maPoints.size() > 2)
924 tools::Polygon aPolygon(maPoints.size(), maPoints.data(), maFlags.data());
925 maPolyPolygon.Insert( aPolygon );
927 maPoints.clear();
928 maFlags.clear();
931 void CGMImpressOutAct::EndFigure()
933 NewRegion();
934 DrawPolyPolygon( maPolyPolygon );
935 maPolyPolygon.Clear();
936 EndGroup();
937 maPoints.clear();
938 maFlags.clear();
941 void CGMImpressOutAct::RegPolyLine( tools::Polygon const & rPolygon, bool bReverse )
943 sal_uInt16 nPoints = rPolygon.GetSize();
944 if ( !nPoints )
945 return;
947 if ( bReverse )
949 for ( sal_uInt16 i = 0; i < nPoints; i++ )
951 maPoints.push_back(rPolygon.GetPoint(nPoints - i - 1));
952 maFlags.push_back(rPolygon.GetFlags(nPoints - i - 1));
955 else
957 for ( sal_uInt16 i = 0; i < nPoints; i++ )
959 maPoints.push_back(rPolygon.GetPoint(i));
960 maFlags.push_back(rPolygon.GetFlags(i));
965 void CGMImpressOutAct::SetGradientOffset( tools::Long nHorzOfs, tools::Long nVertOfs )
967 if ( !mpGradient )
968 mpGradient.reset( new awt::Gradient );
969 mpGradient->XOffset = ( static_cast<sal_uInt16>(nHorzOfs) & 0x7f );
970 mpGradient->YOffset = ( static_cast<sal_uInt16>(nVertOfs) & 0x7f );
973 void CGMImpressOutAct::SetGradientAngle( tools::Long nAngle )
975 if ( !mpGradient )
976 mpGradient.reset( new awt::Gradient );
977 mpGradient->Angle = sal::static_int_cast< sal_Int16 >(nAngle);
980 void CGMImpressOutAct::SetGradientDescriptor( sal_uInt32 nColorFrom, sal_uInt32 nColorTo )
982 if ( !mpGradient )
983 mpGradient.reset( new awt::Gradient );
984 mpGradient->StartColor = nColorFrom;
985 mpGradient->EndColor = nColorTo;
988 void CGMImpressOutAct::SetGradientStyle( sal_uInt32 nStyle )
990 if ( !mpGradient )
991 mpGradient.reset( new awt::Gradient );
992 switch ( nStyle )
994 case 0xff :
996 mpGradient->Style = awt::GradientStyle_AXIAL;
998 break;
999 case 4 :
1001 mpGradient->Style = awt::GradientStyle_RADIAL; // CONICAL
1003 break;
1004 case 3 :
1006 mpGradient->Style = awt::GradientStyle_RECT;
1008 break;
1009 case 2 :
1011 mpGradient->Style = awt::GradientStyle_ELLIPTICAL;
1013 break;
1014 default :
1016 mpGradient->Style = awt::GradientStyle_LINEAR;
1021 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */