merge the formfield patch from ooo-build
[ooovba.git] / slideshow / source / engine / tools.cxx
blob95f09d4c26033446c5899c503cad9f27f898ff28
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: tools.cxx,v $
10 * $Revision: 1.14 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_slideshow.hxx"
34 #include <canvas/debug.hxx>
35 #include <tools/diagnose_ex.h>
36 #include <canvas/canvastools.hxx>
38 #include <math.h>
40 #include <com/sun/star/beans/NamedValue.hpp>
41 #include <com/sun/star/awt/Rectangle.hpp>
42 #include <com/sun/star/animations/ValuePair.hpp>
43 #include <com/sun/star/drawing/FillStyle.hpp>
44 #include <com/sun/star/drawing/LineStyle.hpp>
45 #include <com/sun/star/awt/FontSlant.hpp>
47 #include <basegfx/polygon/b2dpolygon.hxx>
48 #include <basegfx/polygon/b2dpolygontools.hxx>
49 #include <basegfx/range/b2drange.hxx>
50 #include <basegfx/vector/b2dvector.hxx>
51 #include <basegfx/vector/b2ivector.hxx>
52 #include <basegfx/matrix/b2dhommatrix.hxx>
53 #include <basegfx/numeric/ftools.hxx>
55 #include <cppcanvas/basegfxfactory.hxx>
57 #include "lerp.hxx"
58 #include "unoview.hxx"
59 #include "smilfunctionparser.hxx"
60 #include "tools.hxx"
62 #include <limits>
65 using namespace ::com::sun::star;
67 namespace slideshow
69 namespace internal
71 namespace
73 class NamedValueStringComparator
75 public:
76 NamedValueStringComparator( const ::rtl::OUString& rSearchString ) :
77 mrSearchString( rSearchString )
81 bool operator()( const beans::NamedValue& rValue )
83 return rValue.Name == mrSearchString;
86 private:
87 const ::rtl::OUString& mrSearchString;
90 class NamedValueComparator
92 public:
93 NamedValueComparator( const beans::NamedValue& rKey ) :
94 mrKey( rKey )
98 bool operator()( const beans::NamedValue& rValue )
100 return rValue.Name == mrKey.Name && rValue.Value == mrKey.Value;
103 private:
104 const beans::NamedValue& mrKey;
107 ::basegfx::B2DHomMatrix getAttributedShapeTransformation( const ::basegfx::B2DRectangle& rShapeBounds,
108 const ShapeAttributeLayerSharedPtr& pAttr )
110 ::basegfx::B2DHomMatrix aTransform;
111 const ::basegfx::B2DSize& rSize( rShapeBounds.getRange() );
113 const double nShearX( pAttr->isShearXAngleValid() ?
114 pAttr->getShearXAngle() :
115 0.0 );
116 const double nShearY( pAttr->isShearYAngleValid() ?
117 pAttr->getShearYAngle() :
118 0.0 );
119 const double nRotation( pAttr->isRotationAngleValid() ?
120 pAttr->getRotationAngle()*M_PI/180.0 :
121 0.0 );
123 // scale, shear and rotation pivot point is the shape
124 // center - adapt origin accordingly
125 aTransform.translate( -0.5, -0.5 );
127 // ensure valid size (zero size will inevitably lead
128 // to a singular transformation matrix)
129 aTransform.scale( ::basegfx::pruneScaleValue(
130 rSize.getX() ),
131 ::basegfx::pruneScaleValue(
132 rSize.getY() ) );
134 const bool bNeedShearX( !::basegfx::fTools::equalZero(nShearX) );
135 const bool bNeedShearY( !::basegfx::fTools::equalZero(nShearY) );
136 const bool bNeedRotation( !::basegfx::fTools::equalZero(nRotation) );
138 if( bNeedRotation || bNeedShearX || bNeedShearY )
140 if( bNeedShearX )
141 aTransform.shearX( nShearX );
143 if( bNeedShearY )
144 aTransform.shearY( nShearY );
146 if( bNeedRotation )
147 aTransform.rotate( nRotation );
150 // move left, top corner back to position of the
151 // shape. Since we've already translated the
152 // center of the shape to the origin (the
153 // translate( -0.5, -0.5 ) above), translate to
154 // center of final shape position here.
155 aTransform.translate( rShapeBounds.getCenterX(),
156 rShapeBounds.getCenterY() );
158 return aTransform;
162 // Value extraction from Any
163 // =========================
165 /// extract unary double value from Any
166 bool extractValue( double& o_rValue,
167 const uno::Any& rSourceAny,
168 const ShapeSharedPtr& rShape,
169 const ::basegfx::B2DVector& rSlideBounds )
171 // try to extract numeric value (double, or smaller POD, like float or int)
172 if( (rSourceAny >>= o_rValue) )
174 // succeeded
175 return true;
178 // try to extract string
179 ::rtl::OUString aString;
180 if( !(rSourceAny >>= aString) )
181 return false; // nothing left to try
183 // parse the string into an ExpressionNode
186 // Parse string into ExpressionNode, eval node at time 0.0
187 o_rValue = (*SmilFunctionParser::parseSmilValue(
188 aString,
189 calcRelativeShapeBounds(rSlideBounds,
190 rShape->getBounds()) ))(0.0);
192 catch( ParseError& )
194 return false;
197 return true;
200 /// extract enum/constant group value from Any
201 bool extractValue( sal_Int32& o_rValue,
202 const uno::Any& rSourceAny,
203 const ShapeSharedPtr& /*rShape*/,
204 const ::basegfx::B2DVector& /*rSlideBounds*/ )
206 // try to extract numeric value (int, or smaller POD, like byte)
207 if( (rSourceAny >>= o_rValue) )
209 // succeeded
210 return true;
213 // okay, no plain int. Maybe one of the domain-specific enums?
214 drawing::FillStyle eFillStyle;
215 if( (rSourceAny >>= eFillStyle) )
217 o_rValue = sal::static_int_cast<sal_Int16>(eFillStyle);
219 // succeeded
220 return true;
223 drawing::LineStyle eLineStyle;
224 if( (rSourceAny >>= eLineStyle) )
226 o_rValue = sal::static_int_cast<sal_Int16>(eLineStyle);
228 // succeeded
229 return true;
232 awt::FontSlant eFontSlant;
233 if( (rSourceAny >>= eFontSlant) )
235 o_rValue = sal::static_int_cast<sal_Int16>(eFontSlant);
237 // succeeded
238 return true;
241 // nothing left to try. Failure
242 return false;
245 /// extract enum/constant group value from Any
246 bool extractValue( sal_Int16& o_rValue,
247 const uno::Any& rSourceAny,
248 const ShapeSharedPtr& rShape,
249 const ::basegfx::B2DVector& rSlideBounds )
251 sal_Int32 aValue;
252 if( !extractValue(aValue,rSourceAny,rShape,rSlideBounds) )
253 return false;
255 if( std::numeric_limits<sal_Int16>::max() < aValue ||
256 std::numeric_limits<sal_Int16>::min() > aValue )
258 return false;
261 o_rValue = static_cast<sal_Int16>(aValue);
263 return true;
266 /// extract color value from Any
267 bool extractValue( RGBColor& o_rValue,
268 const uno::Any& rSourceAny,
269 const ShapeSharedPtr& /*rShape*/,
270 const ::basegfx::B2DVector& /*rSlideBounds*/ )
272 // try to extract numeric value (double, or smaller POD, like float or int)
274 double nTmp = 0;
275 if( (rSourceAny >>= nTmp) )
277 sal_uInt32 aIntColor( static_cast< sal_uInt32 >(nTmp) );
279 // TODO(F2): Handle color values correctly, here
280 o_rValue = unoColor2RGBColor( aIntColor );
282 // succeeded
283 return true;
287 // try double sequence
289 uno::Sequence< double > aTmp;
290 if( (rSourceAny >>= aTmp) )
292 ENSURE_OR_THROW( aTmp.getLength() == 3,
293 "extractValue(): inappropriate length for RGB color value" );
295 o_rValue = RGBColor( aTmp[0], aTmp[1], aTmp[2] );
297 // succeeded
298 return true;
302 // try sal_Int32 sequence
304 uno::Sequence< sal_Int32 > aTmp;
305 if( (rSourceAny >>= aTmp) )
307 ENSURE_OR_THROW( aTmp.getLength() == 3,
308 "extractValue(): inappropriate length for RGB color value" );
310 // truncate to byte
311 o_rValue = RGBColor( ::cppcanvas::makeColor(
312 static_cast<sal_uInt8>(aTmp[0]),
313 static_cast<sal_uInt8>(aTmp[1]),
314 static_cast<sal_uInt8>(aTmp[2]),
315 255 ) );
317 // succeeded
318 return true;
322 // try sal_Int8 sequence
324 uno::Sequence< sal_Int8 > aTmp;
325 if( (rSourceAny >>= aTmp) )
327 ENSURE_OR_THROW( aTmp.getLength() == 3,
328 "extractValue(): inappropriate length for RGB color value" );
330 o_rValue = RGBColor( ::cppcanvas::makeColor( aTmp[0], aTmp[1], aTmp[2], 255 ) );
332 // succeeded
333 return true;
337 // try to extract string
338 ::rtl::OUString aString;
339 if( !(rSourceAny >>= aString) )
340 return false; // nothing left to try
342 // TODO(F2): Provide symbolic color values here
343 o_rValue = RGBColor( 0.5, 0.5, 0.5 );
345 return true;
348 /// extract color value from Any
349 bool extractValue( HSLColor& o_rValue,
350 const uno::Any& rSourceAny,
351 const ShapeSharedPtr& /*rShape*/,
352 const ::basegfx::B2DVector& /*rSlideBounds*/ )
354 // try double sequence
356 uno::Sequence< double > aTmp;
357 if( (rSourceAny >>= aTmp) )
359 ENSURE_OR_THROW( aTmp.getLength() == 3,
360 "extractValue(): inappropriate length for HSL color value" );
362 o_rValue = HSLColor( aTmp[0], aTmp[1], aTmp[2] );
364 // succeeded
365 return true;
369 // try sal_Int8 sequence
371 uno::Sequence< sal_Int8 > aTmp;
372 if( (rSourceAny >>= aTmp) )
374 ENSURE_OR_THROW( aTmp.getLength() == 3,
375 "extractValue(): inappropriate length for HSL color value" );
377 o_rValue = HSLColor( aTmp[0]*360.0/255.0, aTmp[1]/255.0, aTmp[2]/255.0 );
379 // succeeded
380 return true;
384 return false; // nothing left to try
387 /// extract plain string from Any
388 bool extractValue( ::rtl::OUString& o_rValue,
389 const uno::Any& rSourceAny,
390 const ShapeSharedPtr& /*rShape*/,
391 const ::basegfx::B2DVector& /*rSlideBounds*/ )
393 // try to extract string
394 if( !(rSourceAny >>= o_rValue) )
395 return false; // nothing left to try
397 return true;
400 /// extract bool value from Any
401 bool extractValue( bool& o_rValue,
402 const uno::Any& rSourceAny,
403 const ShapeSharedPtr& /*rShape*/,
404 const ::basegfx::B2DVector& /*rSlideBounds*/ )
406 sal_Bool nTmp = sal_Bool();
407 // try to extract bool value
408 if( (rSourceAny >>= nTmp) )
410 o_rValue = nTmp;
412 // succeeded
413 return true;
416 // try to extract string
417 ::rtl::OUString aString;
418 if( !(rSourceAny >>= aString) )
419 return false; // nothing left to try
421 // we also take the strings "true" and "false",
422 // as well as "on" and "off" here
423 if( aString.equalsIgnoreAsciiCaseAscii("true") ||
424 aString.equalsIgnoreAsciiCaseAscii("on") )
426 o_rValue = true;
427 return true;
429 if( aString.equalsIgnoreAsciiCaseAscii("false") ||
430 aString.equalsIgnoreAsciiCaseAscii("off") )
432 o_rValue = false;
433 return true;
436 // ultimately failed.
437 return false;
440 /// extract double 2-tuple from Any
441 bool extractValue( ::basegfx::B2DTuple& o_rPair,
442 const uno::Any& rSourceAny,
443 const ShapeSharedPtr& rShape,
444 const ::basegfx::B2DVector& rSlideBounds )
446 animations::ValuePair aPair;
448 if( !(rSourceAny >>= aPair) )
449 return false;
451 double nFirst;
452 if( !extractValue( nFirst, aPair.First, rShape, rSlideBounds ) )
453 return false;
455 double nSecond;
456 if( !extractValue( nSecond, aPair.Second, rShape, rSlideBounds ) )
457 return false;
459 o_rPair.setX( nFirst );
460 o_rPair.setY( nSecond );
462 return true;
465 bool findNamedValue( uno::Sequence< beans::NamedValue > const& rSequence,
466 const beans::NamedValue& rSearchKey )
468 const beans::NamedValue* pArray = rSequence.getConstArray();
469 const size_t nLen( rSequence.getLength() );
471 if( nLen == 0 )
472 return false;
474 const beans::NamedValue* pFound = ::std::find_if( pArray,
475 pArray + nLen,
476 NamedValueComparator( rSearchKey ) );
478 if( pFound == pArray + nLen )
479 return false;
481 return true;
484 bool findNamedValue( beans::NamedValue* o_pRet,
485 const uno::Sequence< beans::NamedValue >& rSequence,
486 const ::rtl::OUString& rSearchString )
488 const beans::NamedValue* pArray = rSequence.getConstArray();
489 const size_t nLen( rSequence.getLength() );
491 if( nLen == 0 )
492 return false;
494 const beans::NamedValue* pFound = ::std::find_if( pArray,
495 pArray + nLen,
496 NamedValueStringComparator( rSearchString ) );
497 if( pFound == pArray + nLen )
498 return false;
500 if( o_pRet )
501 *o_pRet = *pFound;
503 return true;
506 basegfx::B2DRange calcRelativeShapeBounds( const basegfx::B2DVector& rPageSize,
507 const basegfx::B2DRange& rShapeBounds )
509 return basegfx::B2DRange( rShapeBounds.getMinX() / rPageSize.getX(),
510 rShapeBounds.getMinY() / rPageSize.getY(),
511 rShapeBounds.getMaxX() / rPageSize.getX(),
512 rShapeBounds.getMaxY() / rPageSize.getY() );
515 // TODO(F2): Currently, the positional attributes DO NOT mirror the XShape properties.
516 // First and foremost, this is because we must operate with the shape boundrect,
517 // not position and size (the conversion between logic rect, snap rect and boundrect
518 // are non-trivial for draw shapes, and I won't duplicate them here). Thus, shapes
519 // rotated on the page will still have 0.0 rotation angle, as the metafile
520 // representation fetched over the API is our default zero case.
522 ::basegfx::B2DHomMatrix getShapeTransformation( const ::basegfx::B2DRectangle& rShapeBounds,
523 const ShapeAttributeLayerSharedPtr& pAttr )
525 if( !pAttr )
527 ::basegfx::B2DHomMatrix aTransform;
529 aTransform.scale( rShapeBounds.getWidth(), rShapeBounds.getHeight() );
530 aTransform.translate( rShapeBounds.getMinX(), rShapeBounds.getMinY() );
532 return aTransform;
534 else
536 return getAttributedShapeTransformation( rShapeBounds,
537 pAttr );
541 ::basegfx::B2DHomMatrix getSpriteTransformation( const ::basegfx::B2DVector& rPixelSize,
542 const ::basegfx::B2DVector& rOrigSize,
543 const ShapeAttributeLayerSharedPtr& pAttr )
545 ::basegfx::B2DHomMatrix aTransform;
547 if( pAttr )
549 const double nShearX( pAttr->isShearXAngleValid() ?
550 pAttr->getShearXAngle() :
551 0.0 );
552 const double nShearY( pAttr->isShearYAngleValid() ?
553 pAttr->getShearYAngle() :
554 0.0 );
555 const double nRotation( pAttr->isRotationAngleValid() ?
556 pAttr->getRotationAngle()*M_PI/180.0 :
557 0.0 );
559 // scale, shear and rotation pivot point is the
560 // sprite's pixel center - adapt origin accordingly
561 aTransform.translate( -0.5*rPixelSize.getX(),
562 -0.5*rPixelSize.getY() );
564 const ::basegfx::B2DSize aSize(
565 pAttr->isWidthValid() ? pAttr->getWidth() : rOrigSize.getX(),
566 pAttr->isHeightValid() ? pAttr->getHeight() : rOrigSize.getY() );
568 // ensure valid size (zero size will inevitably lead
569 // to a singular transformation matrix).
570 aTransform.scale( ::basegfx::pruneScaleValue(
571 aSize.getX() /
572 ::basegfx::pruneScaleValue(
573 rOrigSize.getX() ) ),
574 ::basegfx::pruneScaleValue(
575 aSize.getY() /
576 ::basegfx::pruneScaleValue(
577 rOrigSize.getY() ) ) );
579 const bool bNeedShearX( !::basegfx::fTools::equalZero(nShearX) );
580 const bool bNeedShearY( !::basegfx::fTools::equalZero(nShearY) );
581 const bool bNeedRotation( !::basegfx::fTools::equalZero(nRotation) );
583 if( bNeedRotation || bNeedShearX || bNeedShearY )
585 if( bNeedShearX )
586 aTransform.shearX( nShearX );
588 if( bNeedShearY )
589 aTransform.shearY( nShearY );
591 if( bNeedRotation )
592 aTransform.rotate( nRotation );
595 // move left, top corner back to original position of
596 // the sprite (we've translated the center of the
597 // sprite to the origin above).
598 aTransform.translate( 0.5*rPixelSize.getX(),
599 0.5*rPixelSize.getY() );
602 // return identity transform for un-attributed
603 // shapes. This renders the sprite as-is, in it's
604 // document-supplied size.
605 return aTransform;
608 ::basegfx::B2DRectangle getShapeUpdateArea( const ::basegfx::B2DRectangle& rUnitBounds,
609 const ::basegfx::B2DHomMatrix& rShapeTransform,
610 const ShapeAttributeLayerSharedPtr& pAttr )
612 ::basegfx::B2DHomMatrix aTransform;
614 if( pAttr &&
615 pAttr->isCharScaleValid() &&
616 fabs(pAttr->getCharScale()) > 1.0 )
618 // enlarge shape bounds. Have to consider the worst
619 // case here (the text fully fills the shape)
621 const double nCharScale( pAttr->getCharScale() );
623 // center of scaling is the middle of the shape
624 aTransform.translate( -0.5, -0.5 );
625 aTransform.scale( nCharScale, nCharScale );
626 aTransform.translate( 0.5, 0.5 );
629 aTransform *= rShapeTransform;
631 ::basegfx::B2DRectangle aRes;
633 // apply shape transformation to unit rect
634 return ::canvas::tools::calcTransformedRectBounds(
635 aRes,
636 rUnitBounds,
637 aTransform );
640 ::basegfx::B2DRange getShapeUpdateArea( const ::basegfx::B2DRange& rUnitBounds,
641 const ::basegfx::B2DRange& rShapeBounds )
643 return ::basegfx::B2DRectangle(
644 lerp( rShapeBounds.getMinX(),
645 rShapeBounds.getMaxX(),
646 rUnitBounds.getMinX() ),
647 lerp( rShapeBounds.getMinY(),
648 rShapeBounds.getMaxY(),
649 rUnitBounds.getMinY() ),
650 lerp( rShapeBounds.getMinX(),
651 rShapeBounds.getMaxX(),
652 rUnitBounds.getMaxX() ),
653 lerp( rShapeBounds.getMinY(),
654 rShapeBounds.getMaxY(),
655 rUnitBounds.getMaxY() ) );
658 ::basegfx::B2DRectangle getShapePosSize( const ::basegfx::B2DRectangle& rOrigBounds,
659 const ShapeAttributeLayerSharedPtr& pAttr )
661 // an already empty shape bound need no further
662 // treatment. In fact, any changes applied below would
663 // actually remove the special empty state, thus, don't
664 // change!
665 if( !pAttr ||
666 rOrigBounds.isEmpty() )
668 return rOrigBounds;
670 else
672 // cannot use maBounds anymore, attributes might have been
673 // changed by now.
674 // Have to use absolute values here, as negative sizes
675 // (aka mirrored shapes) _still_ have the same bounds,
676 // only with mirrored content.
677 ::basegfx::B2DSize aSize;
678 aSize.setX( fabs( pAttr->isWidthValid() ?
679 pAttr->getWidth() :
680 rOrigBounds.getWidth() ) );
681 aSize.setY( fabs( pAttr->isHeightValid() ?
682 pAttr->getHeight() :
683 rOrigBounds.getHeight() ) );
685 ::basegfx::B2DPoint aPos;
686 aPos.setX( pAttr->isPosXValid() ?
687 pAttr->getPosX() :
688 rOrigBounds.getCenterX() );
689 aPos.setY( pAttr->isPosYValid() ?
690 pAttr->getPosY() :
691 rOrigBounds.getCenterY() );
693 // the positional attribute retrieved from the
694 // ShapeAttributeLayer actually denotes the _middle_
695 // of the shape (do it as the PPTs do...)
696 return ::basegfx::B2DRectangle( aPos - 0.5*aSize,
697 aPos + 0.5*aSize );
701 RGBColor unoColor2RGBColor( sal_Int32 nColor )
703 return RGBColor(
704 ::cppcanvas::makeColor(
705 // convert from API color to IntSRGBA color
706 // (0xAARRGGBB -> 0xRRGGBBAA)
707 static_cast< sal_uInt8 >( nColor >> 16U ),
708 static_cast< sal_uInt8 >( nColor >> 8U ),
709 static_cast< sal_uInt8 >( nColor ),
710 static_cast< sal_uInt8 >( nColor >> 24U ) ) );
713 void fillRect( const ::cppcanvas::CanvasSharedPtr& rCanvas,
714 const ::basegfx::B2DRectangle& rRect,
715 ::cppcanvas::Color::IntSRGBA aFillColor )
717 const ::basegfx::B2DPolygon aPoly(
718 ::basegfx::tools::createPolygonFromRect( rRect ));
720 ::cppcanvas::PolyPolygonSharedPtr pPolyPoly(
721 ::cppcanvas::BaseGfxFactory::getInstance().createPolyPolygon( rCanvas,
722 aPoly ) );
724 if( pPolyPoly )
726 pPolyPoly->setRGBAFillColor( aFillColor );
727 pPolyPoly->draw();
731 void initSlideBackground( const ::cppcanvas::CanvasSharedPtr& rCanvas,
732 const ::basegfx::B2ISize& rSize )
734 ::cppcanvas::CanvasSharedPtr pCanvas( rCanvas->clone() );
736 // set transformation to identitiy (->device pixel)
737 pCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
739 // #i42440# Fill the _full_ background in
740 // black. Since we had to extend the bitmap by one
741 // pixel, and the bitmap is initialized white,
742 // depending on the slide content a one pixel wide
743 // line will show to the bottom and the right.
744 fillRect( pCanvas,
745 ::basegfx::B2DRectangle( 0.0, 0.0,
746 rSize.getX(),
747 rSize.getY() ),
748 0x000000FFU );
750 // fill the bounds rectangle in white. Subtract one pixel
751 // from both width and height, because the slide size is
752 // chosen one pixel larger than given by the drawing
753 // layer. This is because shapes with line style, that
754 // have the size of the slide would otherwise be cut
755 // off. OTOH, every other slide background (solid fill,
756 // gradient, bitmap) render one pixel less, thus revealing
757 // ugly white pixel to the right and the bottom.
758 fillRect( pCanvas,
759 ::basegfx::B2DRectangle( 0.0, 0.0,
760 rSize.getX()-1,
761 rSize.getY()-1 ),
762 0xFFFFFFFFU );
765 ::basegfx::B2DRectangle getAPIShapeBounds( const uno::Reference< drawing::XShape >& xShape )
767 uno::Reference< beans::XPropertySet > xPropSet( xShape,
768 uno::UNO_QUERY_THROW );
769 // read bound rect
770 awt::Rectangle aTmpRect;
771 if( !(xPropSet->getPropertyValue(
772 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("BoundRect") ) ) >>= aTmpRect) )
774 ENSURE_OR_THROW( false,
775 "getAPIShapeBounds(): Could not get \"BoundRect\" property from shape" );
778 return ::basegfx::B2DRectangle( aTmpRect.X,
779 aTmpRect.Y,
780 aTmpRect.X+aTmpRect.Width,
781 aTmpRect.Y+aTmpRect.Height );
784 double getAPIShapePrio( const uno::Reference< drawing::XShape >& xShape )
786 uno::Reference< beans::XPropertySet > xPropSet( xShape,
787 uno::UNO_QUERY_THROW );
788 // read prio
789 sal_Int32 nPrio(0);
790 if( !(xPropSet->getPropertyValue(
791 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ZOrder") ) ) >>= nPrio) )
793 ENSURE_OR_THROW( false,
794 "getAPIShapePrio(): Could not get \"ZOrder\" property from shape" );
797 // TODO(F2): Check and adapt the range of possible values here.
798 // Maybe we can also take the total number of shapes here
799 return nPrio / 65535.0;
802 basegfx::B2IVector getSlideSizePixel( const basegfx::B2DVector& rSlideSize,
803 const UnoViewSharedPtr& pView )
805 ENSURE_OR_THROW(pView, "getSlideSizePixel(): invalid view");
807 // determine transformed page bounds
808 const basegfx::B2DRange aRect( 0,0,
809 rSlideSize.getX(),
810 rSlideSize.getY() );
811 basegfx::B2DRange aTmpRect;
812 canvas::tools::calcTransformedRectBounds( aTmpRect,
813 aRect,
814 pView->getTransformation() );
816 // #i42440# Returned slide size is one pixel too small, as
817 // rendering happens one pixel to the right and below the
818 // actual bound rect.
819 return basegfx::B2IVector(
820 basegfx::fround( aTmpRect.getRange().getX() ) + 1,
821 basegfx::fround( aTmpRect.getRange().getY() ) + 1 );