related: tdf#162601 UNIQUE function is case-insensitive also for non ASCII
[LibreOffice.git] / filter / source / graphicfilter / icgm / class4.cxx
blob4c0f204f08fd3956bbbf99f41c0dfec82e287f3b
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 .
21 #include "bitmap.hxx"
22 #include "cgm.hxx"
23 #include "chart.hxx"
24 #include "elements.hxx"
25 #include "outact.hxx"
27 #include <o3tl/float_int_conversion.hxx>
28 #include <o3tl/safeint.hxx>
30 #include <memory>
32 using namespace ::com::sun::star;
34 double CGM::ImplGetOrientation( FloatPoint const & rCenter, FloatPoint const & rPoint )
36 double nX = rPoint.X - rCenter.X;
37 double nY = rPoint.Y - rCenter.Y;
39 double fSqrt = std::hypot(nX, nY);
40 double fOrientation = fSqrt != 0.0 ? basegfx::rad2deg(acos(nX / fSqrt)) : 0.0;
41 if (nY > 0)
42 fOrientation = 360 - fOrientation;
44 return fOrientation;
48 void CGM::ImplSwitchStartEndAngle( double& rStartAngle, double& rEndAngle )
50 double nTemp;
51 nTemp = rStartAngle;
52 rStartAngle = rEndAngle;
53 rEndAngle = nTemp;
57 void CGM::ImplGetVector( double* pVector )
59 if ( pElement->eVDCType == VDC_REAL )
61 for ( sal_uInt32 i = 0; i < 4; i++ )
63 pVector[ i ] = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
66 else
68 for ( sal_uInt32 i = 0; i < 4; i++ )
70 pVector[ i ] = static_cast<double>(ImplGetI( pElement->nVDCIntegerPrecision ));
73 pVector[ 0 ] *= mnVDCXmul;
74 pVector[ 2 ] *= mnVDCXmul;
75 pVector[ 1 ] *= mnVDCYmul;
76 pVector[ 3 ] *= mnVDCYmul;
80 bool CGM::ImplGetEllipse( FloatPoint& rCenter, FloatPoint& rRadius, double& rAngle )
82 FloatPoint aPoint1, aPoint2;
83 double fRot1, fRot2;
84 ImplGetPoint( rCenter, true );
85 ImplGetPoint( aPoint1, true );
86 ImplGetPoint( aPoint2, true );
87 fRot1 = ImplGetOrientation( rCenter, aPoint1 );
88 fRot2 = ImplGetOrientation( rCenter, aPoint2 );
89 rAngle = ImplGetOrientation( rCenter, aPoint1 );
90 aPoint1.X -= rCenter.X;
91 aPoint1.Y -= rCenter.Y;
92 rRadius.X = std::hypot(aPoint1.X, aPoint1.Y);
93 aPoint2.X -= rCenter.X;
94 aPoint2.Y -= rCenter.Y;
95 rRadius.Y = std::hypot(aPoint2.X, aPoint2.Y);
97 if ( fRot1 > fRot2 )
99 if ( ( fRot1 - fRot2 ) < 180 )
100 return false;
102 else
104 if ( ( fRot2 - fRot1 ) > 180 )
105 return false;
107 return true;
110 void CGM::ImplDoClass4()
112 if ( mbFirstOutPut )
113 mpOutAct->FirstOutPut();
115 if ( mpBitmapInUse && ( mnElementID != 9 ) ) // process existed graphic
116 { // because there are now no pending bitmap actions
117 CGMBitmapDescriptor* pBmpDesc = mpBitmapInUse->GetBitmap();
118 // do anything with the bitmap
119 mpOutAct->DrawBitmap( pBmpDesc );
120 mpBitmapInUse.reset();
123 if ( ( mpChart == nullptr ) || mpChart->IsAnnotation() )
125 switch ( mnElementID )
127 case 0x01 : /*PolyLine*/
129 sal_uInt32 nPoints = mnElementSize / ImplGetPointSize();
130 tools::Polygon aPolygon( static_cast<sal_uInt16>(nPoints) );
131 for ( sal_uInt32 i = 0; i < nPoints; i++)
133 FloatPoint aFloatPoint;
134 ImplGetPoint( aFloatPoint, true );
135 aPolygon.SetPoint( Point( static_cast<tools::Long>(aFloatPoint.X), static_cast<tools::Long>(aFloatPoint.Y) ), i );
137 if ( mbFigure )
138 mpOutAct->RegPolyLine( aPolygon );
139 else
140 mpOutAct->DrawPolyLine( aPolygon );
142 break;
144 case 0x02 : /*Disjoint PolyLine*/
146 sal_uInt16 nPoints = sal::static_int_cast< sal_uInt16 >(
147 mnElementSize / ImplGetPointSize());
148 if ( ! ( nPoints & 1 ) )
150 nPoints >>= 1;
151 FloatPoint aFloatPoint;
152 if ( mbFigure )
154 tools::Polygon aPolygon( nPoints );
155 for ( sal_uInt16 i = 0; i < nPoints; i++ )
157 ImplGetPoint( aFloatPoint, true );
158 aPolygon.SetPoint( Point( static_cast<tools::Long>(aFloatPoint.X), static_cast<tools::Long>(aFloatPoint.Y) ), 0 );
160 mpOutAct->RegPolyLine( aPolygon );
162 else
164 mpOutAct->BeginGroup();
165 tools::Polygon aPolygon( sal_uInt16(2) );
166 for ( sal_uInt16 i = 0; i < nPoints; i++ )
168 ImplGetPoint( aFloatPoint, true );
169 aPolygon.SetPoint( Point( static_cast<tools::Long>(aFloatPoint.X), static_cast<tools::Long>(aFloatPoint.Y) ), 0 );
170 ImplGetPoint( aFloatPoint, true );
171 aPolygon.SetPoint( Point( static_cast<tools::Long>(aFloatPoint.X), static_cast<tools::Long>(aFloatPoint.Y) ), 1);
172 mpOutAct->DrawPolyLine( aPolygon );
174 mpOutAct->EndGroup();
178 break;
180 case 0x03 : /*PolyMarker*/ break;
181 case 0x04 : /*Text*/
183 FloatPoint aFloatPoint;
185 if ( mbFigure )
186 mpOutAct->CloseRegion();
188 ImplGetPoint ( aFloatPoint, true );
189 sal_uInt32 nType = ImplGetUI16();
190 sal_uInt32 nSize = ImplGetUI( 1 );
192 if (o3tl::make_unsigned(mpEndValidSource - (mpSource + mnParaSize)) < nSize)
193 throw css::uno::Exception(u"attempt to read past end of input"_ustr, nullptr);
195 OUString aStr(reinterpret_cast<char*>(mpSource) + mnParaSize, nSize, RTL_TEXTENCODING_ASCII_US);
197 awt::Size aSize;
198 awt::Point aPoint( static_cast<tools::Long>(aFloatPoint.X), static_cast<tools::Long>(aFloatPoint.Y) );
199 mpOutAct->DrawText(aPoint, aSize, aStr, static_cast<FinalFlag>(nType));
200 mnParaSize = mnElementSize;
202 break;
204 case 0x05 : /*Restricted Text*/
206 double dx, dy;
207 FloatPoint aFloatPoint;
209 if ( mbFigure )
210 mpOutAct->CloseRegion();
212 if ( pElement->eVDCType == VDC_REAL )
214 dx = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
215 dy = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
217 else
219 dx = static_cast<double>(ImplGetI( pElement->nVDCIntegerPrecision ));
220 dy = static_cast<double>(ImplGetI( pElement->nVDCIntegerPrecision ));
222 ImplMapDouble( dx );
223 ImplMapDouble( dy );
225 ImplGetPoint ( aFloatPoint, true );
226 sal_uInt32 nType = ImplGetUI16();
227 sal_uInt32 nSize = ImplGetUI(1);
229 if (o3tl::make_unsigned(mpEndValidSource - (mpSource + mnParaSize)) < nSize)
230 throw css::uno::Exception(u"attempt to read past end of input"_ustr, nullptr);
232 OUString aStr(reinterpret_cast<char*>(mpSource) + mnParaSize, nSize, RTL_TEXTENCODING_ASCII_US);
234 awt::Point aPoint( static_cast<tools::Long>(aFloatPoint.X), static_cast<tools::Long>(aFloatPoint.Y) );
235 awt::Size aSize(static_cast<tools::Long>(dx), static_cast<tools::Long>(dy));
236 mpOutAct->DrawText(aPoint, aSize , aStr, static_cast<FinalFlag>(nType));
237 mnParaSize = mnElementSize;
239 break;
241 case 0x06 : /*Append Text*/
243 (void)ImplGetUI16(); // nType
244 sal_uInt32 nSize = ImplGetUI( 1 );
246 if (o3tl::make_unsigned(mpEndValidSource - (mpSource + mnParaSize)) <= nSize)
247 throw css::uno::Exception(u"attempt to read past end of input"_ustr, nullptr);
249 mpSource[ mnParaSize + nSize ] = 0;
251 mpOutAct->AppendText( reinterpret_cast<char*>(mpSource) + mnParaSize );
252 mnParaSize = mnElementSize;
254 break;
256 case 0x07 : /*Polygon*/
258 if ( mbFigure )
259 mpOutAct->CloseRegion();
261 sal_uInt16 nPoints = sal::static_int_cast< sal_uInt16 >(
262 mnElementSize / ImplGetPointSize());
263 tools::Polygon aPolygon( nPoints );
264 for ( sal_uInt16 i = 0; i < nPoints; i++)
266 FloatPoint aFloatPoint;
267 ImplGetPoint( aFloatPoint, true );
268 aPolygon.SetPoint( Point ( static_cast<tools::Long>( aFloatPoint.X ), static_cast<tools::Long>( aFloatPoint.Y ) ), i );
270 mpOutAct->DrawPolygon( aPolygon );
272 break;
274 case 0x08 : /*Polygon Set*/
276 if ( mbFigure )
277 mpOutAct->CloseRegion();
279 std::vector<Point> aPoints;
280 tools::PolyPolygon aPolyPolygon;
281 FloatPoint aFloatPoint;
283 while ( mnParaSize < mnElementSize )
285 ImplGetPoint( aFloatPoint, true );
286 sal_uInt32 nEdgeFlag = ImplGetUI16();
287 aPoints.push_back(Point(static_cast<tools::Long>(aFloatPoint.X), static_cast<tools::Long>(aFloatPoint.Y)));
288 if ( ( nEdgeFlag & 2 ) || ( mnParaSize == mnElementSize ) )
290 aPolyPolygon.Insert(tools::Polygon(aPoints.size(), aPoints.data()));
291 aPoints.clear();
294 mpOutAct->DrawPolyPolygon( aPolyPolygon );
296 break;
298 case 0x09 : /*Cell Array*/
300 if ( mbFigure )
301 mpOutAct->CloseRegion();
303 if ( mpBitmapInUse )
305 std::unique_ptr<CGMBitmap> xBmpDesc(mpBitmapInUse->GetNext());
306 if (xBmpDesc) // we possibly get a bitmap back which does not fit to
307 { // to the previous -> we need to delete this one too
308 mpOutAct->DrawBitmap(xBmpDesc->GetBitmap());
311 else
313 mpBitmapInUse.reset( new CGMBitmap( *this ) );
316 break;
318 case 0x0a : /*Generalized Drawing Primitive*/
320 ImplGetI( pElement->nIntegerPrecision ); //-Wall is this needed
321 ImplGetUI( pElement->nIntegerPrecision ); //-Wall is this needed
322 mnParaSize = mnElementSize;
324 break;
326 case 0x0b : /*Rectangle*/
328 if ( mbFigure )
329 mpOutAct->CloseRegion();
331 FloatRect aFloatRect;
332 ImplGetRectangle( aFloatRect, true );
333 mpOutAct->DrawRectangle( aFloatRect );
335 break;
337 case 0x0c : /*Circle*/
339 if ( mbFigure )
340 mpOutAct->CloseRegion();
342 double fRotation = 0;
343 FloatPoint aCenter, aRadius;
344 ImplGetPoint( aCenter, true );
345 if ( pElement->eVDCType == VDC_REAL )
346 aRadius.X = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
347 else
348 aRadius.X = static_cast<double>(ImplGetI( pElement->nVDCIntegerPrecision ));
349 ImplMapDouble( aRadius.X );
350 aRadius.Y = aRadius.X;
351 mpOutAct->DrawEllipse( aCenter, aRadius, fRotation );
353 break;
355 case 0x0d : /*Circular Arc 3 Point*/
357 FloatPoint aStartingPoint, aIntermediatePoint, aEndingPoint;
358 ImplGetPoint( aStartingPoint, true );
359 ImplGetPoint( aIntermediatePoint, true );
360 ImplGetPoint( aEndingPoint, true );
362 double fA = aIntermediatePoint.X - aStartingPoint.X;
363 double fB = aIntermediatePoint.Y - aStartingPoint.Y;
364 double fC = aEndingPoint.X - aStartingPoint.X;
365 double fD = aEndingPoint.Y - aStartingPoint.Y;
367 double fE = fA * ( aStartingPoint.X + aIntermediatePoint.X ) + fB * ( aStartingPoint.Y + aIntermediatePoint.Y );
368 double fF = fC * ( aStartingPoint.X + aEndingPoint.X ) + fD * ( aStartingPoint.Y + aEndingPoint.Y );
370 double fG = 2.0 * ( fA * ( aEndingPoint.Y - aIntermediatePoint.Y ) - fB * ( aEndingPoint.X - aIntermediatePoint.X ) );
372 bool bUseless = fG == 0;
374 FloatPoint aCenterPoint;
375 if (!bUseless)
377 aCenterPoint.X = ( fD * fE - fB * fF ) / fG;
378 aCenterPoint.Y = ( fA * fF - fC * fE ) / fG;
379 bUseless = useless(aCenterPoint.X) || useless(aCenterPoint.Y);
382 if (!bUseless)
383 bUseless = useless(aStartingPoint.X) || useless(aStartingPoint.Y);
385 if (!bUseless)
387 double fStartAngle = ImplGetOrientation( aCenterPoint, aStartingPoint );
388 double fInterAngle = ImplGetOrientation( aCenterPoint, aIntermediatePoint );
389 double fEndAngle = ImplGetOrientation( aCenterPoint, aEndingPoint );
391 int nSwitch = 0;
393 if ( fStartAngle > fEndAngle )
395 nSwitch ^=1;
396 aIntermediatePoint = aEndingPoint;
397 aEndingPoint = aStartingPoint;
398 aStartingPoint = aIntermediatePoint;
399 fG = fStartAngle;
400 fStartAngle = fEndAngle;
401 fEndAngle = fG;
403 if ( ! ( fInterAngle > fStartAngle ) && ( fInterAngle < fEndAngle ) )
405 nSwitch ^=1;
406 aIntermediatePoint = aEndingPoint;
407 aEndingPoint = aStartingPoint;
408 aStartingPoint = aIntermediatePoint;
409 fG = fStartAngle;
410 fStartAngle = fEndAngle;
411 fEndAngle = fG;
413 double fRadius = std::hypot(aStartingPoint.X - aCenterPoint.X, aStartingPoint.Y - aCenterPoint.Y);
415 if ( mbFigure )
417 double fLeft = aCenterPoint.X - fRadius;
418 double fTop = aCenterPoint.Y - fRadius;
419 double fRight = fLeft + (2 * fRadius);
420 double fBottom = fTop + (2 * fRadius);
421 bUseless = useless(fLeft) || useless(fTop) || useless(2 * fRadius) || useless(fRight) || useless(fBottom);
422 if (!bUseless)
424 double fCenterCalc = fLeft + fRight;
425 bUseless = !o3tl::convertsToAtLeast(fCenterCalc, std::numeric_limits<tools::Long>::min()) ||
426 !o3tl::convertsToAtMost(fCenterCalc, std::numeric_limits<tools::Long>::max());
428 if (!bUseless)
430 double fCenterCalc = fTop + fBottom;
431 bUseless = !o3tl::convertsToAtLeast(fCenterCalc, std::numeric_limits<tools::Long>::min()) ||
432 !o3tl::convertsToAtMost(fCenterCalc, std::numeric_limits<tools::Long>::max());
434 if (!bUseless)
436 tools::Rectangle aBoundingBox(Point(fLeft, fTop), Size(2 * fRadius, 2 * fRadius));
437 tools::Polygon aPolygon( aBoundingBox, Point( static_cast<tools::Long>(aStartingPoint.X), static_cast<tools::Long>(aStartingPoint.Y) ) ,Point( static_cast<tools::Long>(aEndingPoint.X), static_cast<tools::Long>(aEndingPoint.Y) ), PolyStyle::Arc );
438 if ( nSwitch )
439 mpOutAct->RegPolyLine( aPolygon, true );
440 else
441 mpOutAct->RegPolyLine( aPolygon );
444 else
446 fG = 0;
447 FloatPoint aRadius;
448 aRadius.X = aRadius.Y = fRadius;
449 mpOutAct->DrawEllipticalArc( aCenterPoint, aRadius, fG, 2, fStartAngle, fEndAngle );
453 break;
455 case 0x0e : /*Circular Arc 3 Point Close*/
457 if ( mbFigure )
458 mpOutAct->CloseRegion();
460 FloatPoint aStartingPoint, aIntermediatePoint, aEndingPoint;
461 ImplGetPoint( aStartingPoint );
462 ImplGetPoint( aIntermediatePoint );
463 ImplGetPoint( aEndingPoint );
465 double fA = aIntermediatePoint.X - aStartingPoint.X;
466 double fB = aIntermediatePoint.Y - aStartingPoint.Y;
467 double fC = aEndingPoint.X - aStartingPoint.X;
468 double fD = aEndingPoint.Y - aStartingPoint.Y;
470 double fE = fA * ( aStartingPoint.X + aIntermediatePoint.X ) + fB * ( aStartingPoint.Y + aIntermediatePoint.Y );
471 double fF = fC * ( aStartingPoint.X + aEndingPoint.X ) + fD * ( aStartingPoint.Y + aEndingPoint.Y );
473 double fG = 2.0 * ( fA * ( aEndingPoint.Y - aIntermediatePoint.Y ) - fB * ( aEndingPoint.X - aIntermediatePoint.X ) );
475 if ( fG != 0 )
477 FloatPoint aCenterPoint;
478 aCenterPoint.X = ( fD * fE - fB * fF ) / fG;
479 aCenterPoint.Y = ( fA * fF - fC * fE ) / fG;
480 double fStartAngle = ImplGetOrientation( aCenterPoint, aStartingPoint );
481 double fInterAngle = ImplGetOrientation( aCenterPoint, aIntermediatePoint );
482 double fEndAngle = ImplGetOrientation( aCenterPoint, aEndingPoint );
484 if ( fStartAngle > fEndAngle )
486 aIntermediatePoint = aEndingPoint;
487 aEndingPoint = aStartingPoint;
488 aStartingPoint = aIntermediatePoint;
489 fG = fStartAngle;
490 fStartAngle = fEndAngle;
491 fEndAngle = fG;
493 if ( ! ( fInterAngle > fStartAngle ) && ( fInterAngle < fEndAngle ) )
495 aIntermediatePoint = aEndingPoint;
496 aEndingPoint = aStartingPoint;
497 aStartingPoint = aIntermediatePoint;
498 fG = fStartAngle;
499 fStartAngle = fEndAngle;
500 fEndAngle = fG;
502 FloatPoint fRadius;
503 fRadius.Y = fRadius.X = std::hypot(aStartingPoint.X - aCenterPoint.X, aStartingPoint.Y - aCenterPoint.Y);
505 sal_uInt32 nType = ImplGetUI16();
506 if ( nType == 0 )
507 nType = 0; // is PIE
508 else
509 nType = 1; // is CHORD
511 double fOrientation = 0;
512 mpOutAct->DrawEllipticalArc( aCenterPoint, fRadius, fOrientation, nType, fStartAngle, fEndAngle );
515 break;
517 case 0x0f : /*Circular Arc Centre*/
519 double fStartAngle, fEndAngle, vector[ 4 ];
520 FloatPoint aCenter, aRadius;
522 if ( mbFigure )
523 mpOutAct->CloseRegion();
525 ImplGetPoint( aCenter, true );
526 ImplGetVector( &vector[ 0 ] );
528 if ( pElement->eVDCType == VDC_REAL )
530 aRadius.X = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
532 else
534 aRadius.X = static_cast<double>(ImplGetI( pElement->nVDCIntegerPrecision ));
537 ImplMapDouble( aRadius.X );
538 aRadius.Y = aRadius.X;
540 bool bUseless = useless(vector[0]) || useless(vector[1]) || useless(vector[2]) || useless(vector[3]);
541 if (!bUseless)
543 const double fStartSqrt = std::hypot(vector[0], vector[1]);
544 fStartAngle = fStartSqrt != 0.0 ? basegfx::rad2deg(acos(vector[0] / fStartSqrt)) : 0.0;
545 const double fEndSqrt = std::hypot(vector[2], vector[3]);
546 fEndAngle = fEndSqrt != 0.0 ? basegfx::rad2deg(acos(vector[ 2 ] / fEndSqrt)) : 0.0;
548 if ( vector[ 1 ] > 0 )
549 fStartAngle = 360 - fStartAngle;
550 if ( vector[ 3 ] > 0 )
551 fEndAngle = 360 - fEndAngle;
553 if ( mbAngReverse )
554 ImplSwitchStartEndAngle( fStartAngle, fEndAngle );
556 if ( mbFigure )
558 double fLeft = aCenter.X - aRadius.X;
559 double fTop = aCenter.Y - aRadius.X;
560 double fRight = fLeft + (2 * aRadius.X);
561 double fBottom = fTop + (2 * aRadius.X);
562 bUseless = useless(fLeft) || useless(fTop) || useless(2 * aRadius.X) || useless(fRight) || useless(fBottom);
563 if (!bUseless)
565 double fCenterCalc = fLeft + fRight;
566 bUseless = !o3tl::convertsToAtLeast(fCenterCalc, std::numeric_limits<tools::Long>::min()) ||
567 !o3tl::convertsToAtMost(fCenterCalc, std::numeric_limits<tools::Long>::max());
569 if (!bUseless)
571 double fCenterCalc = fTop + fBottom;
572 bUseless = !o3tl::convertsToAtLeast(fCenterCalc, std::numeric_limits<tools::Long>::min()) ||
573 !o3tl::convertsToAtMost(fCenterCalc, std::numeric_limits<tools::Long>::max());
575 if (!bUseless)
577 tools::Rectangle aBoundingBox(Point(fLeft, fTop), Size(2 * aRadius.X, 2 * aRadius.X));
578 tools::Polygon aPolygon( aBoundingBox,
579 Point( static_cast<tools::Long>(vector[ 0 ]), static_cast<tools::Long>(vector[ 1 ]) ),
580 Point( static_cast<tools::Long>(vector[ 2 ]), static_cast<tools::Long>(vector[ 3 ]) ), PolyStyle::Arc );
581 mpOutAct->RegPolyLine( aPolygon );
584 else
586 double fOrientation = 0;
587 mpOutAct->DrawEllipticalArc( aCenter, aRadius, fOrientation, 2, fStartAngle, fEndAngle );
591 mnParaSize = mnElementSize;
593 break;
595 case 0x10 : /*Circular Arc Centre Close*/
597 double fOrientation, vector[ 4 ];
598 FloatPoint aCenter, aRadius;
600 if ( mbFigure )
601 mpOutAct->CloseRegion();
603 ImplGetPoint( aCenter, true );
604 ImplGetVector( &vector[ 0 ] );
605 if ( pElement->eVDCType == VDC_REAL )
607 aRadius.X = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
609 else
611 aRadius.X = static_cast<double>(ImplGetI( pElement->nVDCIntegerPrecision ));
613 ImplMapDouble( aRadius.X );
614 aRadius.Y = aRadius.X;
616 sal_uInt32 nType = ImplGetUI16();
618 bool bUseless = useless(vector[0]) || useless(vector[1]) || useless(vector[2]) || useless(vector[3]);
619 if (!bUseless)
621 const double fStartSqrt = std::hypot(vector[0], vector[1]);
622 double fStartAngle = fStartSqrt ? basegfx::rad2deg(acos(vector[0] / fStartSqrt)) : 0.0;
623 const double fEndSqrt = std::hypot(vector[2], vector[3]);
624 double fEndAngle = fEndSqrt ? basegfx::rad2deg(acos(vector[2] / fEndSqrt)) : 0.0;
626 if ( vector[ 1 ] > 0 )
627 fStartAngle = 360 - fStartAngle;
628 if ( vector[ 3 ] > 0 )
629 fEndAngle = 360 - fEndAngle;
631 if ( mbAngReverse )
632 ImplSwitchStartEndAngle( fStartAngle, fEndAngle );
634 if ( nType == 0 )
635 nType = 0; // is PIE
636 else
637 nType = 1; // is CHORD
638 fOrientation = 0;
640 mpOutAct->DrawEllipticalArc( aCenter, aRadius, fOrientation,
641 nType, fStartAngle, fEndAngle );
644 mnParaSize = mnElementSize;
646 break;
648 case 0x11 : /*Ellipse*/
650 double fOrientation;
651 FloatPoint aCenter, aRadius;
653 if ( mbFigure )
654 mpOutAct->CloseRegion();
656 ImplGetEllipse( aCenter, aRadius, fOrientation ) ;
657 mpOutAct->DrawEllipse( aCenter, aRadius, fOrientation ) ;
659 break;
661 case 0x12 : /*Elliptical Arc*/
663 if ( mbFigure )
664 mpOutAct->CloseRegion();
666 double fOrientation, fStartAngle, fEndAngle, vector[ 4 ];
667 FloatPoint aCenter, aRadius;
669 if ( mbFigure )
670 mpOutAct->CloseRegion();
672 bool bDirection = ImplGetEllipse( aCenter, aRadius, fOrientation );
673 ImplGetVector( &vector[ 0 ] );
675 bool bUseless = useless(vector[0]) || useless(vector[1]) || useless(vector[2]) || useless(vector[3]);
676 if (!bUseless)
678 double fStartSqrt = std::hypot(vector[0], vector[1]);
679 fStartAngle = fStartSqrt ? basegfx::rad2deg(acos(vector[0] / fStartSqrt)) : 0.0;
680 double fEndSqrt = std::hypot(vector[2], vector[3]);
681 fEndAngle = fEndSqrt ? basegfx::rad2deg(acos(vector[2] / fEndSqrt)) : 0.0;
683 if ( vector[ 1 ] > 0 )
684 fStartAngle = 360 - fStartAngle;
685 if ( vector[ 3 ] > 0 )
686 fEndAngle = 360 - fEndAngle;
688 if ( bDirection )
689 mpOutAct->DrawEllipticalArc( aCenter, aRadius, fOrientation,
690 2, fStartAngle, fEndAngle );
691 else
692 mpOutAct->DrawEllipticalArc( aCenter, aRadius, fOrientation,
693 2, fEndAngle, fStartAngle);
696 break;
698 case 0x13 : /*Elliptical Arc Close*/
700 double fOrientation, fStartAngle, fEndAngle, vector[ 4 ];
701 FloatPoint aCenter, aRadius;
703 if ( mbFigure )
704 mpOutAct->CloseRegion();
706 bool bDirection = ImplGetEllipse( aCenter, aRadius, fOrientation );
707 ImplGetVector( &vector[ 0 ] );
709 sal_uInt32 nType = ImplGetUI16();
711 bool bUseless = useless(vector[0]) || useless(vector[1]) || useless(vector[2]) || useless(vector[3]);
712 if (!bUseless)
714 double fStartSqrt = std::hypot(vector[0], vector[1]);
715 fStartAngle = fStartSqrt ? basegfx::rad2deg(acos(vector[0] / fStartSqrt)) : 0.0;
716 double fEndSqrt = std::hypot(vector[2], vector[3]);
717 fEndAngle = fEndSqrt ? basegfx::rad2deg(acos(vector[2] / fEndSqrt)) : 0.0;
719 if ( vector[ 1 ] > 0 )
720 fStartAngle = 360 - fStartAngle;
721 if ( vector[ 3 ] > 0 )
722 fEndAngle = 360 - fEndAngle;
724 if ( nType == 0 )
725 nType = 0; // is PIE
726 else
727 nType = 1; // is CHORD
729 if ( bDirection )
730 mpOutAct->DrawEllipticalArc( aCenter, aRadius, fOrientation,
731 nType, fStartAngle, fEndAngle );
732 else
733 mpOutAct->DrawEllipticalArc( aCenter, aRadius, fOrientation,
734 nType, fEndAngle, fStartAngle);
737 break;
738 case 0x14 : /*Circular Arc Centre Reversed*/
740 if ( mbFigure )
741 mpOutAct->CloseRegion();
743 break;
744 case 0x15 : /*Connection Edge */ // NS
746 // if ( mbFigure )
747 // mpOutAct->CloseRegion();
749 break;
750 case 0x16 : /*Hyperbolic Arc */ // NS
752 if ( mbFigure )
753 mpOutAct->CloseRegion();
755 break;
756 case 0x17 : /*Parabolic Arc */ // NS
758 if ( mbFigure )
759 mpOutAct->CloseRegion();
761 break;
762 case 0x18 : /*Non Uniform B-Spline */ // NS
764 if ( mbFigure )
765 mpOutAct->CloseRegion();
767 break;
768 case 0x19 : /*Non Uniform Rational B-Spline */ // NS
770 if ( mbFigure )
771 mpOutAct->CloseRegion();
773 break;
774 case 0x1a : /*Polybezier*/
776 sal_uInt32 nOrder = ImplGetI( pElement->nIntegerPrecision );
778 sal_uInt16 nNumberOfPoints = sal::static_int_cast< sal_uInt16 >(( mnElementSize - pElement->nIntegerPrecision ) / ImplGetPointSize());
780 tools::Polygon aPolygon( nNumberOfPoints );
782 for ( sal_uInt16 i = 0; i < nNumberOfPoints; i++)
784 FloatPoint aFloatPoint;
785 ImplGetPoint( aFloatPoint, true );
786 aPolygon.SetPoint( Point ( static_cast<tools::Long>( aFloatPoint.X ), static_cast<tools::Long>( aFloatPoint.Y ) ), i );
788 if ( nOrder & 4 )
790 for ( sal_uInt16 i = 0; i < nNumberOfPoints; i++ )
792 if ( ( i % 3 ) == 0 )
793 aPolygon.SetFlags( i, PolyFlags::Normal );
794 else
795 aPolygon.SetFlags( i, PolyFlags::Control );
798 else
800 for ( sal_uInt16 i = 0; i < nNumberOfPoints; i++ )
802 switch ( i & 3 )
804 case 0 :
805 case 3 : aPolygon.SetFlags( i, PolyFlags::Normal ); break;
806 default : aPolygon.SetFlags( i, PolyFlags::Control ); break;
810 if ( mbFigure )
811 mpOutAct->RegPolyLine( aPolygon );
812 else
813 mpOutAct->DrawPolybezier( aPolygon );
814 mnParaSize = mnElementSize;
816 break;
818 case 0x1b : /*Polysymbol */ // NS
820 if ( mbFigure )
821 mpOutAct->CloseRegion();
823 break;
824 case 0x1c : /*Bitonal Tile */ // NS
826 if ( mbFigure )
827 mpOutAct->CloseRegion();
829 break;
830 case 0x1d : /*Tile */ // NS
832 if ( mbFigure )
833 mpOutAct->CloseRegion();
835 break;
836 case 0x1e : /*Insert Object*/
838 if ( mbFigure )
839 mpOutAct->CloseRegion();
841 break;
842 case 0xff : /*Polybezier*/
844 if ( mbFigure )
845 mpOutAct->CloseRegion();
847 break;
848 case 0xfe : /*Sharp Polybezier*/
850 if ( mbFigure )
851 mpOutAct->CloseRegion();
853 break;
854 case 0xfd : /*Polyspline*/
856 if ( mbFigure )
857 mpOutAct->CloseRegion();
859 break;
860 case 0xfc : /*Rounded Rectangle*/
862 if ( mbFigure )
863 mpOutAct->CloseRegion();
865 break;
866 case 0xfb : /*Begin Cell Array*/
868 if ( mbFigure )
869 mpOutAct->CloseRegion();
871 break;
872 case 0xfa : /*End Cell Array*/
874 if ( mbFigure )
875 mpOutAct->CloseRegion();
877 break;
878 case 0xf9 : /*Insert File*/
880 if ( mbFigure )
881 mpOutAct->CloseRegion();
883 break;
884 case 0xf8 : /*Block Text*/
886 if ( mbFigure )
887 mpOutAct->CloseRegion();
889 break;
890 case 0xf7 : /*Variable Width Polyline*/
892 if ( mbFigure )
893 mpOutAct->CloseRegion();
895 break;
896 case 0xf6 : /*Elliptical Arc 3 Point*/
898 if ( mbFigure )
899 mpOutAct->CloseRegion();
901 break;
902 case 0xf1 : /*Hyperlink Definition */break;
903 default: break;
906 else
907 mnParaSize = mnElementSize;
911 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */