1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: shapeattributelayer.cxx,v $
10 * $Revision: 1.10.16.1 $
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"
35 #include <canvas/debug.hxx>
36 #include <tools/diagnose_ex.h>
37 #include <shapeattributelayer.hxx>
39 #include <canvas/verbosetrace.hxx>
42 #include <com/sun/star/awt/Rectangle.hpp>
43 #include <com/sun/star/awt/FontUnderline.hpp>
44 #include <com/sun/star/awt/FontWeight.hpp>
45 #include <com/sun/star/beans/XPropertySet.hpp>
46 #include <com/sun/star/animations/AnimationAdditiveMode.hpp>
48 #include <basegfx/numeric/ftools.hxx>
49 #include <basegfx/polygon/b2dpolygon.hxx>
50 #include <rtl/math.hxx>
53 using namespace ::com::sun::star
;
62 This method updates all state IDs from possible
63 children. Whenever a child's state ID changed, we
66 void ShapeAttributeLayer::updateStateIds()
70 if( mnTransformationState
!= mpChild
->getTransformationState() )
71 ++mnTransformationState
;
72 if( mnClipState
!= mpChild
->getClipState() )
74 if( mnAlphaState
!= mpChild
->getAlphaState() )
76 if( mnPositionState
!= mpChild
->getPositionState() )
78 if( mnContentState
!= mpChild
->getContentState() )
80 if( mnVisibilityState
!= mpChild
->getVisibilityState() )
85 /** Calc attribute value.
87 This method determines the current attribute value,
88 appropriately combining it with children values (by
89 evaluating the mnAdditiveMode member).
91 template< typename T
> T
ShapeAttributeLayer::calcValue( const T
& rCurrValue
,
92 bool bThisInstanceValid
,
93 bool (ShapeAttributeLayer::*pIsValid
)() const,
94 T (ShapeAttributeLayer::*pGetValue
)() const ) const
96 // deviated from the (*shared_ptr).*mpFuncPtr notation
97 // here, since gcc does not seem to parse that as a member
98 // function call anymore.
99 const bool bChildInstanceValueValid( haveChild() ? (mpChild
.get()->*pIsValid
)() : false );
101 if( bThisInstanceValid
)
103 if( bChildInstanceValueValid
)
105 // merge with child value
106 switch( mnAdditiveMode
)
109 // FALTHROUGH intended
110 case animations::AnimationAdditiveMode::NONE
:
111 // FALTHROUGH intended
112 case animations::AnimationAdditiveMode::BASE
:
113 // FALTHROUGH intended
114 case animations::AnimationAdditiveMode::REPLACE
:
115 // TODO(F2): reverse-engineer the semantics of these
118 // currently, treat them the same and replace
119 // the child value by our own
122 case animations::AnimationAdditiveMode::SUM
:
123 return rCurrValue
+ ((*mpChild
).*pGetValue
)();
125 case animations::AnimationAdditiveMode::MULTIPLY
:
126 return rCurrValue
* ((*mpChild
).*pGetValue
)();
131 // this object is the only one defining
132 // the value, so take it
138 return bChildInstanceValueValid
?
139 ((*mpChild
).*pGetValue
)() :
140 T(); // pass on child value, regardless
141 // if it's valid or not. If not, it's
146 ShapeAttributeLayer::ShapeAttributeLayer( const ShapeAttributeLayerSharedPtr
& rChildLayer
) :
147 mpChild( rChildLayer
),
159 mnCharRotationAngle(),
163 meFillStyle( drawing::FillStyle_NONE
),
164 meLineStyle( drawing::LineStyle_NONE
),
165 meCharPosture( awt::FontSlant_NONE
),
173 mnTransformationState( rChildLayer
? rChildLayer
->getTransformationState() : 0 ),
174 mnClipState( rChildLayer
? rChildLayer
->getClipState() : 0),
175 mnAlphaState( rChildLayer
? rChildLayer
->getAlphaState() : 0),
176 mnPositionState( rChildLayer
? rChildLayer
->getPositionState() : 0 ),
177 mnContentState( rChildLayer
? rChildLayer
->getContentState() : 0 ),
178 mnVisibilityState( rChildLayer
? rChildLayer
->getVisibilityState() : 0 ),
180 mnAdditiveMode( animations::AnimationAdditiveMode::BASE
),
182 mbVisibility( false ),
184 mbWidthValid( false ),
185 mbHeightValid( false ),
186 mbPosXValid( false ),
187 mbPosYValid( false ),
188 mbClipValid( false ),
190 mbFontFamilyValid( false ),
192 mbRotationAngleValid( false ),
193 mbShearXAngleValid( false ),
194 mbShearYAngleValid( false ),
196 mbAlphaValid( false ),
198 mbCharRotationAngleValid( false ),
199 mbCharScaleValid( false ),
201 mbDimColorValid( false ),
202 mbFillColorValid( false ),
203 mbLineColorValid( false ),
204 mbCharColorValid( false ),
206 mbFillStyleValid( false ),
207 mbLineStyleValid( false ),
208 mbCharWeightValid( false ),
209 mbUnderlineModeValid( false ),
210 mbCharPostureValid( false ),
211 mbVisibilityValid( false )
215 bool ShapeAttributeLayer::revokeChildLayer( const ShapeAttributeLayerSharedPtr
& rChildLayer
)
217 ENSURE_OR_RETURN( rChildLayer
,
218 "ShapeAttributeLayer::revokeChildLayer(): Will not remove NULL child" );
221 return false; // no children, nothing to revoke.
223 if( mpChild
== rChildLayer
)
225 // we have it - replace by removed child's sibling.
226 mpChild
= rChildLayer
->getChildLayer();
228 // if we're now the first one, defensively increment _all_
229 // state ids: possibly all underlying attributes have now
230 // changed to default
233 // TODO(P1): Check whether it pays off to check more
234 // detailed, which attributes really change
235 ++mnTransformationState
;
245 // we don't have it - pass on the request
246 if( !mpChild
->revokeChildLayer( rChildLayer
) )
247 return false; // nobody has it - bail out
250 // something might have changed - update ids.
256 ShapeAttributeLayerSharedPtr
ShapeAttributeLayer::getChildLayer() const
261 void ShapeAttributeLayer::setAdditiveMode( sal_Int16 nMode
)
263 if( mnAdditiveMode
!= nMode
)
265 // TODO(P1): Check whether it pays off to check more
266 // detailed, which attributes really change
268 // defensively increment all states - possibly each of them
269 // will change with different additive mode
270 ++mnTransformationState
;
278 mnAdditiveMode
= nMode
;
281 bool ShapeAttributeLayer::isWidthValid() const
283 return mbWidthValid
? true : haveChild() ? mpChild
->isWidthValid() : false;
286 double ShapeAttributeLayer::getWidth() const
288 return calcValue
< double >(
291 &ShapeAttributeLayer::isWidthValid
,
292 &ShapeAttributeLayer::getWidth
);
295 void ShapeAttributeLayer::setWidth( const double& rNewWidth
)
297 ENSURE_OR_THROW( ::rtl::math::isFinite(rNewWidth
),
298 "ShapeAttributeLayer::setWidth(): Invalid width" );
300 maSize
.setX( rNewWidth
);
302 ++mnTransformationState
;
305 bool ShapeAttributeLayer::isHeightValid() const
307 return mbHeightValid
? true : haveChild() ? mpChild
->isHeightValid() : false;
310 double ShapeAttributeLayer::getHeight() const
312 return calcValue
< double >(
315 &ShapeAttributeLayer::isHeightValid
,
316 &ShapeAttributeLayer::getHeight
);
319 void ShapeAttributeLayer::setHeight( const double& rNewHeight
)
321 ENSURE_OR_THROW( ::rtl::math::isFinite(rNewHeight
),
322 "ShapeAttributeLayer::setHeight(): Invalid height" );
324 maSize
.setY( rNewHeight
);
325 mbHeightValid
= true;
326 ++mnTransformationState
;
329 void ShapeAttributeLayer::setSize( const ::basegfx::B2DSize
& rNewSize
)
331 ENSURE_OR_THROW( ::rtl::math::isFinite(rNewSize
.getX()) &&
332 ::rtl::math::isFinite(rNewSize
.getY()),
333 "ShapeAttributeLayer::setSize(): Invalid size" );
336 mbWidthValid
= mbHeightValid
= true;
337 ++mnTransformationState
;
340 bool ShapeAttributeLayer::isPosXValid() const
342 return mbPosXValid
? true : haveChild() ? mpChild
->isPosXValid() : false;
345 double ShapeAttributeLayer::getPosX() const
347 return calcValue
< double >(
350 &ShapeAttributeLayer::isPosXValid
,
351 &ShapeAttributeLayer::getPosX
);
354 void ShapeAttributeLayer::setPosX( const double& rNewX
)
356 ENSURE_OR_THROW( ::rtl::math::isFinite(rNewX
),
357 "ShapeAttributeLayer::setPosX(): Invalid position" );
359 maPosition
.setX( rNewX
);
364 bool ShapeAttributeLayer::isPosYValid() const
366 return mbPosYValid
? true : haveChild() ? mpChild
->isPosYValid() : false;
369 double ShapeAttributeLayer::getPosY() const
371 return calcValue
< double >(
374 &ShapeAttributeLayer::isPosYValid
,
375 &ShapeAttributeLayer::getPosY
);
378 void ShapeAttributeLayer::setPosY( const double& rNewY
)
380 ENSURE_OR_THROW( ::rtl::math::isFinite(rNewY
),
381 "ShapeAttributeLayer::setPosY(): Invalid position" );
383 maPosition
.setY( rNewY
);
388 void ShapeAttributeLayer::setPosition( const ::basegfx::B2DPoint
& rNewPos
)
390 maPosition
= rNewPos
;
391 mbPosXValid
= mbPosYValid
= true;
395 bool ShapeAttributeLayer::isRotationAngleValid() const
397 return mbRotationAngleValid
? true : haveChild() ? mpChild
->isRotationAngleValid() : false;
400 double ShapeAttributeLayer::getRotationAngle() const
402 return calcValue
< double >(
404 mbRotationAngleValid
,
405 &ShapeAttributeLayer::isRotationAngleValid
,
406 &ShapeAttributeLayer::getRotationAngle
);
409 void ShapeAttributeLayer::setRotationAngle( const double& rNewAngle
)
411 ENSURE_OR_THROW( ::rtl::math::isFinite(rNewAngle
),
412 "ShapeAttributeLayer::setRotationAngle(): Invalid angle" );
414 mnRotationAngle
= rNewAngle
;
415 mbRotationAngleValid
= true;
416 ++mnTransformationState
;
419 bool ShapeAttributeLayer::isShearXAngleValid() const
421 return mbShearXAngleValid
? true : haveChild() ? mpChild
->isShearXAngleValid() : false;
424 double ShapeAttributeLayer::getShearXAngle() const
426 return calcValue( mnShearXAngle
,
428 &ShapeAttributeLayer::isShearXAngleValid
,
429 &ShapeAttributeLayer::getShearXAngle
);
432 void ShapeAttributeLayer::setShearXAngle( const double& rNewAngle
)
434 ENSURE_OR_THROW( ::rtl::math::isFinite(rNewAngle
),
435 "ShapeAttributeLayer::setShearXAngle(): Invalid angle" );
437 mnShearXAngle
= rNewAngle
;
438 mbShearXAngleValid
= true;
439 ++mnTransformationState
;
442 bool ShapeAttributeLayer::isShearYAngleValid() const
444 return mbShearYAngleValid
? true : haveChild() ? mpChild
->isShearYAngleValid() : false;
447 double ShapeAttributeLayer::getShearYAngle() const
449 return calcValue( mnShearYAngle
,
451 &ShapeAttributeLayer::isShearYAngleValid
,
452 &ShapeAttributeLayer::getShearYAngle
);
455 void ShapeAttributeLayer::setShearYAngle( const double& rNewAngle
)
457 ENSURE_OR_THROW( ::rtl::math::isFinite(rNewAngle
),
458 "ShapeAttributeLayer::setShearYAngle(): Invalid angle" );
460 mnShearYAngle
= rNewAngle
;
461 mbShearYAngleValid
= true;
462 ++mnTransformationState
;
465 bool ShapeAttributeLayer::isAlphaValid() const
467 return mbAlphaValid
? true : haveChild() ? mpChild
->isAlphaValid() : false;
470 double ShapeAttributeLayer::getAlpha() const
472 return calcValue( mnAlpha
,
474 &ShapeAttributeLayer::isAlphaValid
,
475 &ShapeAttributeLayer::getAlpha
);
478 void ShapeAttributeLayer::setAlpha( const double& rNewValue
)
480 ENSURE_OR_THROW( ::rtl::math::isFinite(rNewValue
),
481 "ShapeAttributeLayer::setAlpha(): Invalid alpha" );
488 bool ShapeAttributeLayer::isClipValid() const
490 return mbClipValid
? true : haveChild() ? mpChild
->isClipValid() : false;
493 ::basegfx::B2DPolyPolygon
ShapeAttributeLayer::getClip() const
495 // TODO(F1): Implement polygon algebra for additive modes
498 else if( haveChild() )
499 return mpChild
->getClip();
501 return ::basegfx::B2DPolyPolygon();
504 void ShapeAttributeLayer::setClip( const ::basegfx::B2DPolyPolygon
& rNewClip
)
511 bool ShapeAttributeLayer::isDimColorValid() const
513 return mbDimColorValid
? true : haveChild() ? mpChild
->isDimColorValid() : false;
516 RGBColor
ShapeAttributeLayer::getDimColor() const
518 return calcValue( maDimColor
,
520 &ShapeAttributeLayer::isDimColorValid
,
521 &ShapeAttributeLayer::getDimColor
);
524 void ShapeAttributeLayer::setDimColor( const RGBColor
& nNewColor
)
526 maDimColor
= nNewColor
;
527 mbDimColorValid
= true;
531 bool ShapeAttributeLayer::isFillColorValid() const
533 return mbFillColorValid
? true : haveChild() ? mpChild
->isFillColorValid() : false;
536 RGBColor
ShapeAttributeLayer::getFillColor() const
538 return calcValue( maFillColor
,
540 &ShapeAttributeLayer::isFillColorValid
,
541 &ShapeAttributeLayer::getFillColor
);
544 void ShapeAttributeLayer::setFillColor( const RGBColor
& nNewColor
)
546 maFillColor
= nNewColor
;
547 mbFillColorValid
= true;
551 bool ShapeAttributeLayer::isLineColorValid() const
553 return mbLineColorValid
? true : haveChild() ? mpChild
->isLineColorValid() : false;
556 RGBColor
ShapeAttributeLayer::getLineColor() const
558 return calcValue( maLineColor
,
560 &ShapeAttributeLayer::isLineColorValid
,
561 &ShapeAttributeLayer::getLineColor
);
564 void ShapeAttributeLayer::setLineColor( const RGBColor
& nNewColor
)
566 maLineColor
= nNewColor
;
567 mbLineColorValid
= true;
571 bool ShapeAttributeLayer::isFillStyleValid() const
573 return mbFillStyleValid
? true : haveChild() ? mpChild
->isFillStyleValid() : false;
576 sal_Int16
ShapeAttributeLayer::getFillStyle() const
578 // mnAdditiveMode is ignored, cannot combine strings in
580 if( mbFillStyleValid
)
581 return sal::static_int_cast
<sal_Int16
>(meFillStyle
);
582 else if( haveChild() )
583 return sal::static_int_cast
<sal_Int16
>(mpChild
->getFillStyle());
585 return sal::static_int_cast
<sal_Int16
>(drawing::FillStyle_SOLID
);
588 void ShapeAttributeLayer::setFillStyle( const sal_Int16
& rStyle
)
590 // TODO(Q1): Check range here.
591 meFillStyle
= (drawing::FillStyle
)rStyle
;
592 mbFillStyleValid
= true;
596 bool ShapeAttributeLayer::isLineStyleValid() const
598 return mbLineStyleValid
? true : haveChild() ? mpChild
->isLineStyleValid() : false;
601 sal_Int16
ShapeAttributeLayer::getLineStyle() const
603 // mnAdditiveMode is ignored, cannot combine strings in
605 if( mbLineStyleValid
)
606 return sal::static_int_cast
<sal_Int16
>(meLineStyle
);
607 else if( haveChild() )
608 return sal::static_int_cast
<sal_Int16
>(mpChild
->getLineStyle());
610 return sal::static_int_cast
<sal_Int16
>(drawing::LineStyle_SOLID
);
613 void ShapeAttributeLayer::setLineStyle( const sal_Int16
& rStyle
)
615 // TODO(Q1): Check range here.
616 meLineStyle
= (drawing::LineStyle
)rStyle
;
617 mbLineStyleValid
= true;
621 bool ShapeAttributeLayer::isVisibilityValid() const
623 return mbVisibilityValid
? true : haveChild() ? mpChild
->isVisibilityValid() : false;
626 bool ShapeAttributeLayer::getVisibility() const
628 // mnAdditiveMode is ignored, SMIL spec requires to not combine
629 // bools in any sensible way
630 if( mbVisibilityValid
)
632 else if( haveChild() )
633 return mpChild
->getVisibility();
635 return true; // default is always visible
638 void ShapeAttributeLayer::setVisibility( const bool& bVisible
)
640 mbVisibility
= bVisible
;
641 mbVisibilityValid
= true;
645 bool ShapeAttributeLayer::isCharColorValid() const
647 return mbCharColorValid
? true : haveChild() ? mpChild
->isCharColorValid() : false;
650 RGBColor
ShapeAttributeLayer::getCharColor() const
652 return calcValue( maCharColor
,
654 &ShapeAttributeLayer::isCharColorValid
,
655 &ShapeAttributeLayer::getCharColor
);
658 void ShapeAttributeLayer::setCharColor( const RGBColor
& nNewColor
)
660 maCharColor
= nNewColor
;
661 mbCharColorValid
= true;
665 bool ShapeAttributeLayer::isCharRotationAngleValid() const
667 return mbCharRotationAngleValid
? true : haveChild() ? mpChild
->isCharRotationAngleValid() : false;
670 double ShapeAttributeLayer::getCharRotationAngle() const
672 return calcValue( mnCharRotationAngle
,
673 mbCharRotationAngleValid
,
674 &ShapeAttributeLayer::isCharRotationAngleValid
,
675 &ShapeAttributeLayer::getCharRotationAngle
);
678 void ShapeAttributeLayer::setCharRotationAngle( const double& rNewAngle
)
680 ENSURE_OR_THROW( ::rtl::math::isFinite(rNewAngle
),
681 "ShapeAttributeLayer::setCharRotationAngle(): Invalid angle" );
683 mnCharRotationAngle
= rNewAngle
;
684 mbCharRotationAngleValid
= true;
688 bool ShapeAttributeLayer::isCharWeightValid() const
690 return mbCharWeightValid
? true : haveChild() ? mpChild
->isCharWeightValid() : false;
693 double ShapeAttributeLayer::getCharWeight() const
695 // mnAdditiveMode is ignored, cannot combine strings in
697 if( mbCharWeightValid
)
699 else if( haveChild() )
700 return mpChild
->getCharWeight();
702 return awt::FontWeight::NORMAL
;
705 void ShapeAttributeLayer::setCharWeight( const double& rValue
)
707 // TODO(Q1): Check range here.
708 mnCharWeight
= rValue
;
709 mbCharWeightValid
= true;
713 bool ShapeAttributeLayer::isUnderlineModeValid() const
715 return mbUnderlineModeValid
? true : haveChild() ? mpChild
->isUnderlineModeValid() : false;
718 sal_Int16
ShapeAttributeLayer::getUnderlineMode() const
720 // mnAdditiveMode is ignored, SMIL spec requires to not combine
721 // bools in any sensible way
722 if( mbUnderlineModeValid
)
723 return mnUnderlineMode
;
724 else if( haveChild() )
725 return mpChild
->getUnderlineMode();
727 return awt::FontUnderline::NONE
; // default is no underline
730 void ShapeAttributeLayer::setUnderlineMode( const sal_Int16
& rUnderlineMode
)
732 // TODO(Q1): Check range here.
733 mnUnderlineMode
= rUnderlineMode
;
734 mbUnderlineModeValid
= true;
738 bool ShapeAttributeLayer::isFontFamilyValid() const
740 return mbFontFamilyValid
? true : haveChild() ? mpChild
->isFontFamilyValid() : false;
743 ::rtl::OUString
ShapeAttributeLayer::getFontFamily() const
745 // mnAdditiveMode is ignored, cannot combine strings in
747 if( mbFontFamilyValid
)
749 else if( haveChild() )
750 return mpChild
->getFontFamily();
752 return ::rtl::OUString();
755 void ShapeAttributeLayer::setFontFamily( const ::rtl::OUString
& rName
)
757 maFontFamily
= rName
;
758 mbFontFamilyValid
= true;
762 bool ShapeAttributeLayer::isCharPostureValid() const
764 return mbCharPostureValid
? true : haveChild() ? mpChild
->isCharPostureValid() : false;
767 sal_Int16
ShapeAttributeLayer::getCharPosture() const
769 // mnAdditiveMode is ignored, cannot combine strings in
771 if( mbCharPostureValid
)
772 return sal::static_int_cast
<sal_Int16
>(meCharPosture
);
773 else if( haveChild() )
774 return sal::static_int_cast
<sal_Int16
>(mpChild
->getCharPosture());
776 return sal::static_int_cast
<sal_Int16
>(awt::FontSlant_NONE
);
779 void ShapeAttributeLayer::setCharPosture( const sal_Int16
& rStyle
)
781 // TODO(Q1): Check range here.
782 meCharPosture
= (awt::FontSlant
)rStyle
;
783 mbCharPostureValid
= true;
787 bool ShapeAttributeLayer::isCharScaleValid() const
789 return mbCharScaleValid
? true : haveChild() ? mpChild
->isCharScaleValid() : false;
792 double ShapeAttributeLayer::getCharScale() const
794 return calcValue( mnCharScale
,
796 &ShapeAttributeLayer::isCharScaleValid
,
797 &ShapeAttributeLayer::getCharScale
);
800 void ShapeAttributeLayer::setCharScale( const double& rNewHeight
)
802 ENSURE_OR_THROW( ::rtl::math::isFinite(rNewHeight
),
803 "ShapeAttributeLayer::setCharScale(): Invalid height" );
805 mnCharScale
= rNewHeight
;
806 mbCharScaleValid
= true;
810 State::StateId
ShapeAttributeLayer::getTransformationState() const
813 ::std::max( mnTransformationState
,
814 mpChild
->getTransformationState() ) :
815 mnTransformationState
;
818 State::StateId
ShapeAttributeLayer::getClipState() const
821 ::std::max( mnClipState
,
822 mpChild
->getClipState() ) :
826 State::StateId
ShapeAttributeLayer::getAlphaState() const
829 ::std::max( mnAlphaState
,
830 mpChild
->getAlphaState() ) :
834 State::StateId
ShapeAttributeLayer::getPositionState() const
837 ::std::max( mnPositionState
,
838 mpChild
->getPositionState() ) :
842 State::StateId
ShapeAttributeLayer::getContentState() const
845 ::std::max( mnContentState
,
846 mpChild
->getContentState() ) :
850 State::StateId
ShapeAttributeLayer::getVisibilityState() const
853 ::std::max( mnVisibilityState
,
854 mpChild
->getVisibilityState() ) :