1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_slideshow.hxx"
30 
31 // must be first
32 #include <canvas/debug.hxx>
33 #include <tools/diagnose_ex.h>
34 #include <shapeattributelayer.hxx>
35 
36 #include <canvas/verbosetrace.hxx>
37 
38 
39 #include <com/sun/star/awt/Rectangle.hpp>
40 #include <com/sun/star/awt/FontUnderline.hpp>
41 #include <com/sun/star/awt/FontWeight.hpp>
42 #include <com/sun/star/beans/XPropertySet.hpp>
43 #include <com/sun/star/animations/AnimationAdditiveMode.hpp>
44 
45 #include <basegfx/numeric/ftools.hxx>
46 #include <basegfx/polygon/b2dpolygon.hxx>
47 #include <rtl/math.hxx>
48 
49 
50 using namespace ::com::sun::star;
51 
52 
53 namespace slideshow
54 {
55     namespace internal
56     {
57         /** Update state ids
58 
59         	This method updates all state IDs from possible
60         	children. Whenever a child's state ID changed, we
61         	increment ours.
62         */
63         void ShapeAttributeLayer::updateStateIds()
64         {
65             if( haveChild() )
66             {
67                 if( mnTransformationState != mpChild->getTransformationState() )
68                     ++mnTransformationState;
69                 if( mnClipState != mpChild->getClipState() )
70                     ++mnClipState;
71                 if( mnAlphaState != mpChild->getAlphaState() )
72                     ++mnAlphaState;
73                 if( mnPositionState != mpChild->getPositionState() )
74                     ++mnPositionState;
75                 if( mnContentState != mpChild->getContentState() )
76                     ++mnContentState;
77                 if( mnVisibilityState != mpChild->getVisibilityState() )
78                     ++mnVisibilityState;
79             }
80         }
81 
82         /** Calc attribute value.
83 
84         	This method determines the current attribute value,
85         	appropriately combining it with children values (by
86         	evaluating the mnAdditiveMode member).
87          */
88         template< typename T > T ShapeAttributeLayer::calcValue( const T& 					rCurrValue,
89                                                                  bool						bThisInstanceValid,
90                                                                  bool (ShapeAttributeLayer::*pIsValid)() const,
91                                                                  T 	 (ShapeAttributeLayer::*pGetValue)() const ) const
92         {
93             // deviated from the (*shared_ptr).*mpFuncPtr notation
94             // here, since gcc does not seem to parse that as a member
95             // function call anymore.
96             const bool bChildInstanceValueValid( haveChild() ? (mpChild.get()->*pIsValid)() : false );
97 
98             if( bThisInstanceValid )
99             {
100                 if( bChildInstanceValueValid )
101                 {
102                     // merge with child value
103                     switch( mnAdditiveMode )
104                     {
105                         default:
106                             // FALTHROUGH intended
107                         case animations::AnimationAdditiveMode::NONE:
108                             // FALTHROUGH intended
109                         case animations::AnimationAdditiveMode::BASE:
110                             // FALTHROUGH intended
111                         case animations::AnimationAdditiveMode::REPLACE:
112                             // TODO(F2): reverse-engineer the semantics of these
113                             // values
114 
115                             // currently, treat them the same and replace
116                             // the child value by our own
117                             return rCurrValue;
118 
119                         case animations::AnimationAdditiveMode::SUM:
120                             return rCurrValue + ((*mpChild).*pGetValue)();
121 
122                         case animations::AnimationAdditiveMode::MULTIPLY:
123                             return rCurrValue * ((*mpChild).*pGetValue)();
124                     }
125                 }
126                 else
127                 {
128                     // this object is the only one defining
129                     // the value, so take it
130                     return rCurrValue;
131                 }
132             }
133             else
134             {
135                 return bChildInstanceValueValid ?
136                     ((*mpChild).*pGetValue)() :
137                     T(); 			// pass on child value, regardless
138                 					// if it's valid or not. If not, it's
139                 					// a default anyway
140             }
141         }
142 
143         ShapeAttributeLayer::ShapeAttributeLayer( const ShapeAttributeLayerSharedPtr& rChildLayer ) :
144             mpChild( rChildLayer ),
145 
146             maSize(),
147             maPosition(),
148             maClip(),
149 
150             maFontFamily(),
151 
152             mnRotationAngle(),
153             mnShearXAngle(),
154             mnShearYAngle(),
155             mnAlpha(),
156             mnCharRotationAngle(),
157             mnCharScale(),
158             mnCharWeight(),
159 
160             meFillStyle( drawing::FillStyle_NONE ),
161             meLineStyle( drawing::LineStyle_NONE ),
162             meCharPosture( awt::FontSlant_NONE ),
163             mnUnderlineMode(),
164 
165             maDimColor(),
166             maFillColor(),
167             maLineColor(),
168             maCharColor(),
169 
170             mnTransformationState( rChildLayer ? rChildLayer->getTransformationState() : 0 ),
171             mnClipState( rChildLayer ? rChildLayer->getClipState() : 0),
172             mnAlphaState( rChildLayer ? rChildLayer->getAlphaState() : 0),
173             mnPositionState( rChildLayer ? rChildLayer->getPositionState() : 0 ),
174             mnContentState( rChildLayer ? rChildLayer->getContentState() : 0 ),
175             mnVisibilityState( rChildLayer ? rChildLayer->getVisibilityState() : 0 ),
176 
177             mnAdditiveMode( animations::AnimationAdditiveMode::BASE ),
178 
179             mbVisibility( false ),
180 
181             mbWidthValid( false ),
182             mbHeightValid( false ),
183             mbPosXValid( false ),
184             mbPosYValid( false ),
185             mbClipValid( false ),
186 
187             mbFontFamilyValid( false ),
188 
189             mbRotationAngleValid( false ),
190             mbShearXAngleValid( false ),
191             mbShearYAngleValid( false ),
192 
193             mbAlphaValid( false ),
194 
195             mbCharRotationAngleValid( false ),
196             mbCharScaleValid( false ),
197 
198             mbDimColorValid( false ),
199             mbFillColorValid( false ),
200             mbLineColorValid( false ),
201             mbCharColorValid( false ),
202 
203             mbFillStyleValid( false ),
204             mbLineStyleValid( false ),
205             mbCharWeightValid( false ),
206             mbUnderlineModeValid( false ),
207             mbCharPostureValid( false ),
208             mbVisibilityValid( false )
209         {
210         }
211 
212         bool ShapeAttributeLayer::revokeChildLayer( const ShapeAttributeLayerSharedPtr& rChildLayer )
213         {
214             ENSURE_OR_RETURN_FALSE( rChildLayer,
215                                "ShapeAttributeLayer::revokeChildLayer(): Will not remove NULL child" );
216 
217             if( !haveChild() )
218                 return false; // no children, nothing to revoke.
219 
220             if( mpChild == rChildLayer )
221             {
222                 // we have it - replace by removed child's sibling.
223                 mpChild = rChildLayer->getChildLayer();
224 
225                 // if we're now the first one, defensively increment _all_
226                 // state ids: possibly all underlying attributes have now
227                 // changed to default
228                 if( !haveChild() )
229                 {
230                     // TODO(P1): Check whether it pays off to check more
231                     // detailed, which attributes really change
232                     ++mnTransformationState;
233                     ++mnClipState;
234                     ++mnAlphaState;
235                     ++mnPositionState;
236                     ++mnContentState;
237                     ++mnVisibilityState;
238                 }
239             }
240             else
241             {
242                 // we don't have it - pass on the request
243                 if( !mpChild->revokeChildLayer( rChildLayer ) )
244                     return false; // nobody has it - bail out
245             }
246 
247             // something might have changed - update ids.
248             updateStateIds();
249 
250             return true;
251         }
252 
253         ShapeAttributeLayerSharedPtr  ShapeAttributeLayer::getChildLayer() const
254         {
255             return mpChild;
256         }
257 
258         void ShapeAttributeLayer::setAdditiveMode( sal_Int16 nMode )
259         {
260             if( mnAdditiveMode != nMode )
261             {
262                 // TODO(P1): Check whether it pays off to check more
263                 // detailed, which attributes really change
264 
265                 // defensively increment all states - possibly each of them
266                 // will change with different additive mode
267                 ++mnTransformationState;
268                 ++mnClipState;
269                 ++mnAlphaState;
270                 ++mnPositionState;
271                 ++mnContentState;
272                 ++mnVisibilityState;
273             }
274 
275             mnAdditiveMode = nMode;
276         }
277 
278         bool ShapeAttributeLayer::isWidthValid() const
279         {
280             return mbWidthValid ? true : haveChild() ? mpChild->isWidthValid() : false;
281         }
282 
283         double ShapeAttributeLayer::getWidth() const
284         {
285             return calcValue< double >(
286                 maSize.getX(),
287                 mbWidthValid,
288                 &ShapeAttributeLayer::isWidthValid,
289                 &ShapeAttributeLayer::getWidth );
290         }
291 
292         void ShapeAttributeLayer::setWidth( const double& rNewWidth )
293         {
294             ENSURE_OR_THROW( ::rtl::math::isFinite(rNewWidth),
295                               "ShapeAttributeLayer::setWidth(): Invalid width" );
296 
297             maSize.setX( rNewWidth );
298             mbWidthValid = true;
299             ++mnTransformationState;
300         }
301 
302         bool ShapeAttributeLayer::isHeightValid() const
303         {
304             return mbHeightValid ? true : haveChild() ? mpChild->isHeightValid() : false;
305         }
306 
307         double ShapeAttributeLayer::getHeight() const
308         {
309             return calcValue< double >(
310                 maSize.getY(),
311                 mbHeightValid,
312                 &ShapeAttributeLayer::isHeightValid,
313                 &ShapeAttributeLayer::getHeight );
314         }
315 
316         void ShapeAttributeLayer::setHeight( const double& rNewHeight )
317         {
318             ENSURE_OR_THROW( ::rtl::math::isFinite(rNewHeight),
319                               "ShapeAttributeLayer::setHeight(): Invalid height" );
320 
321             maSize.setY( rNewHeight );
322             mbHeightValid = true;
323             ++mnTransformationState;
324         }
325 
326         void ShapeAttributeLayer::setSize( const ::basegfx::B2DSize& rNewSize )
327         {
328             ENSURE_OR_THROW( ::rtl::math::isFinite(rNewSize.getX()) &&
329                               ::rtl::math::isFinite(rNewSize.getY()),
330                               "ShapeAttributeLayer::setSize(): Invalid size" );
331 
332             maSize = rNewSize;
333             mbWidthValid = mbHeightValid = true;
334             ++mnTransformationState;
335         }
336 
337         bool ShapeAttributeLayer::isPosXValid() const
338         {
339             return mbPosXValid ? true : haveChild() ? mpChild->isPosXValid() : false;
340         }
341 
342         double ShapeAttributeLayer::getPosX() const
343         {
344             return calcValue< double >(
345                 maPosition.getX(),
346                 mbPosXValid,
347                 &ShapeAttributeLayer::isPosXValid,
348                 &ShapeAttributeLayer::getPosX );
349         }
350 
351         void ShapeAttributeLayer::setPosX( const double& rNewX )
352         {
353             ENSURE_OR_THROW( ::rtl::math::isFinite(rNewX),
354                               "ShapeAttributeLayer::setPosX(): Invalid position" );
355 
356             maPosition.setX( rNewX );
357             mbPosXValid = true;
358             ++mnPositionState;
359         }
360 
361         bool ShapeAttributeLayer::isPosYValid() const
362         {
363             return mbPosYValid ? true : haveChild() ? mpChild->isPosYValid() : false;
364         }
365 
366         double ShapeAttributeLayer::getPosY() const
367         {
368             return calcValue< double >(
369                 maPosition.getY(),
370                 mbPosYValid,
371                 &ShapeAttributeLayer::isPosYValid,
372                 &ShapeAttributeLayer::getPosY );
373         }
374 
375         void ShapeAttributeLayer::setPosY( const double& rNewY )
376         {
377             ENSURE_OR_THROW( ::rtl::math::isFinite(rNewY),
378                               "ShapeAttributeLayer::setPosY(): Invalid position" );
379 
380             maPosition.setY( rNewY );
381             mbPosYValid = true;
382             ++mnPositionState;
383         }
384 
385         void ShapeAttributeLayer::setPosition( const ::basegfx::B2DPoint& rNewPos )
386         {
387             maPosition = rNewPos;
388             mbPosXValid = mbPosYValid = true;
389             ++mnPositionState;
390         }
391 
392         bool ShapeAttributeLayer::isRotationAngleValid() const
393         {
394             return mbRotationAngleValid ? true : haveChild() ? mpChild->isRotationAngleValid() : false;
395         }
396 
397         double ShapeAttributeLayer::getRotationAngle() const
398         {
399             return calcValue< double >(
400                 mnRotationAngle,
401                 mbRotationAngleValid,
402                 &ShapeAttributeLayer::isRotationAngleValid,
403                 &ShapeAttributeLayer::getRotationAngle );
404         }
405 
406         void ShapeAttributeLayer::setRotationAngle( const double& rNewAngle )
407         {
408             ENSURE_OR_THROW( ::rtl::math::isFinite(rNewAngle),
409                               "ShapeAttributeLayer::setRotationAngle(): Invalid angle" );
410 
411             mnRotationAngle = rNewAngle;
412             mbRotationAngleValid = true;
413             ++mnTransformationState;
414         }
415 
416         bool ShapeAttributeLayer::isShearXAngleValid() const
417         {
418             return mbShearXAngleValid ? true : haveChild() ? mpChild->isShearXAngleValid() : false;
419         }
420 
421         double ShapeAttributeLayer::getShearXAngle() const
422         {
423             return calcValue( mnShearXAngle,
424                               mbShearXAngleValid,
425                               &ShapeAttributeLayer::isShearXAngleValid,
426                               &ShapeAttributeLayer::getShearXAngle );
427         }
428 
429         void ShapeAttributeLayer::setShearXAngle( const double& rNewAngle )
430         {
431             ENSURE_OR_THROW( ::rtl::math::isFinite(rNewAngle),
432                               "ShapeAttributeLayer::setShearXAngle(): Invalid angle" );
433 
434             mnShearXAngle = rNewAngle;
435             mbShearXAngleValid = true;
436             ++mnTransformationState;
437         }
438 
439         bool ShapeAttributeLayer::isShearYAngleValid() const
440         {
441             return mbShearYAngleValid ? true : haveChild() ? mpChild->isShearYAngleValid() : false;
442         }
443 
444         double ShapeAttributeLayer::getShearYAngle() const
445         {
446             return calcValue( mnShearYAngle,
447                               mbShearYAngleValid,
448                               &ShapeAttributeLayer::isShearYAngleValid,
449                               &ShapeAttributeLayer::getShearYAngle );
450         }
451 
452         void ShapeAttributeLayer::setShearYAngle( const double& rNewAngle )
453         {
454             ENSURE_OR_THROW( ::rtl::math::isFinite(rNewAngle),
455                               "ShapeAttributeLayer::setShearYAngle(): Invalid angle" );
456 
457             mnShearYAngle = rNewAngle;
458             mbShearYAngleValid = true;
459             ++mnTransformationState;
460         }
461 
462         bool ShapeAttributeLayer::isAlphaValid() const
463         {
464             return mbAlphaValid ? true : haveChild() ? mpChild->isAlphaValid() : false;
465         }
466 
467         double ShapeAttributeLayer::getAlpha() const
468         {
469             return calcValue( mnAlpha,
470                               mbAlphaValid,
471                               &ShapeAttributeLayer::isAlphaValid,
472                               &ShapeAttributeLayer::getAlpha );
473         }
474 
475         void ShapeAttributeLayer::setAlpha( const double& rNewValue )
476         {
477             ENSURE_OR_THROW( ::rtl::math::isFinite(rNewValue),
478                               "ShapeAttributeLayer::setAlpha(): Invalid alpha" );
479 
480             mnAlpha = rNewValue;
481             mbAlphaValid = true;
482             ++mnAlphaState;
483         }
484 
485         bool ShapeAttributeLayer::isClipValid() const
486         {
487             return mbClipValid ? true : haveChild() ? mpChild->isClipValid() : false;
488         }
489 
490         ::basegfx::B2DPolyPolygon ShapeAttributeLayer::getClip() const
491         {
492             // TODO(F1): Implement polygon algebra for additive modes
493             if( mbClipValid )
494                 return maClip;
495             else if( haveChild() )
496                 return mpChild->getClip();
497             else
498                 return ::basegfx::B2DPolyPolygon();
499         }
500 
501         void ShapeAttributeLayer::setClip( const ::basegfx::B2DPolyPolygon& rNewClip )
502         {
503             maClip = rNewClip;
504             mbClipValid = true;
505             ++mnClipState;
506         }
507 
508         bool ShapeAttributeLayer::isDimColorValid() const
509         {
510             return mbDimColorValid ? true : haveChild() ? mpChild->isDimColorValid() : false;
511         }
512 
513         RGBColor ShapeAttributeLayer::getDimColor() const
514         {
515             return calcValue( maDimColor,
516                               mbDimColorValid,
517                               &ShapeAttributeLayer::isDimColorValid,
518                               &ShapeAttributeLayer::getDimColor );
519         }
520 
521         void ShapeAttributeLayer::setDimColor( const RGBColor& nNewColor )
522         {
523             maDimColor = nNewColor;
524             mbDimColorValid = true;
525             ++mnContentState;
526         }
527 
528         bool ShapeAttributeLayer::isFillColorValid() const
529         {
530             return mbFillColorValid ? true : haveChild() ? mpChild->isFillColorValid() : false;
531         }
532 
533         RGBColor ShapeAttributeLayer::getFillColor() const
534         {
535             return calcValue( maFillColor,
536                               mbFillColorValid,
537                               &ShapeAttributeLayer::isFillColorValid,
538                               &ShapeAttributeLayer::getFillColor );
539         }
540 
541         void ShapeAttributeLayer::setFillColor( const RGBColor& nNewColor )
542         {
543             maFillColor = nNewColor;
544             mbFillColorValid = true;
545             ++mnContentState;
546         }
547 
548         bool ShapeAttributeLayer::isLineColorValid() const
549         {
550             return mbLineColorValid ? true : haveChild() ? mpChild->isLineColorValid() : false;
551         }
552 
553         RGBColor  ShapeAttributeLayer::getLineColor() const
554         {
555             return calcValue( maLineColor,
556                               mbLineColorValid,
557                               &ShapeAttributeLayer::isLineColorValid,
558                               &ShapeAttributeLayer::getLineColor );
559         }
560 
561         void ShapeAttributeLayer::setLineColor( const RGBColor& nNewColor )
562         {
563             maLineColor = nNewColor;
564             mbLineColorValid = true;
565             ++mnContentState;
566         }
567 
568         bool ShapeAttributeLayer::isFillStyleValid() const
569         {
570             return mbFillStyleValid ? true : haveChild() ? mpChild->isFillStyleValid() : false;
571         }
572 
573         sal_Int16 ShapeAttributeLayer::getFillStyle() const
574         {
575             // mnAdditiveMode is ignored, cannot combine strings in
576             // any sensible way
577             if( mbFillStyleValid )
578                 return sal::static_int_cast<sal_Int16>(meFillStyle);
579             else if( haveChild() )
580                 return sal::static_int_cast<sal_Int16>(mpChild->getFillStyle());
581             else
582                 return sal::static_int_cast<sal_Int16>(drawing::FillStyle_SOLID);
583         }
584 
585         void ShapeAttributeLayer::setFillStyle( const sal_Int16& rStyle )
586         {
587             // TODO(Q1): Check range here.
588             meFillStyle = (drawing::FillStyle)rStyle;
589             mbFillStyleValid = true;
590             ++mnContentState;
591         }
592 
593         bool ShapeAttributeLayer::isLineStyleValid() const
594         {
595             return mbLineStyleValid ? true : haveChild() ? mpChild->isLineStyleValid() : false;
596         }
597 
598         sal_Int16 ShapeAttributeLayer::getLineStyle() const
599         {
600             // mnAdditiveMode is ignored, cannot combine strings in
601             // any sensible way
602             if( mbLineStyleValid )
603                 return sal::static_int_cast<sal_Int16>(meLineStyle);
604             else if( haveChild() )
605                 return sal::static_int_cast<sal_Int16>(mpChild->getLineStyle());
606             else
607                 return sal::static_int_cast<sal_Int16>(drawing::LineStyle_SOLID);
608         }
609 
610         void ShapeAttributeLayer::setLineStyle( const sal_Int16& rStyle )
611         {
612             // TODO(Q1): Check range here.
613             meLineStyle = (drawing::LineStyle)rStyle;
614             mbLineStyleValid = true;
615             ++mnContentState;
616         }
617 
618         bool ShapeAttributeLayer::isVisibilityValid() const
619         {
620             return mbVisibilityValid ? true : haveChild() ? mpChild->isVisibilityValid() : false;
621         }
622 
623         bool ShapeAttributeLayer::getVisibility() const
624         {
625             // mnAdditiveMode is ignored, SMIL spec requires to not combine
626             // bools in any sensible way
627             if( mbVisibilityValid )
628                 return mbVisibility;
629             else if( haveChild() )
630                 return mpChild->getVisibility();
631             else
632                 return true; // default is always visible
633         }
634 
635         void ShapeAttributeLayer::setVisibility( const bool& bVisible )
636         {
637             mbVisibility = bVisible;
638             mbVisibilityValid = true;
639             ++mnVisibilityState;
640         }
641 
642         bool ShapeAttributeLayer::isCharColorValid() const
643         {
644             return mbCharColorValid ? true : haveChild() ? mpChild->isCharColorValid() : false;
645         }
646 
647         RGBColor ShapeAttributeLayer::getCharColor() const
648         {
649             return calcValue( maCharColor,
650                               mbCharColorValid,
651                               &ShapeAttributeLayer::isCharColorValid,
652                               &ShapeAttributeLayer::getCharColor );
653         }
654 
655         void ShapeAttributeLayer::setCharColor( const RGBColor& nNewColor )
656         {
657             maCharColor = nNewColor;
658             mbCharColorValid = true;
659             ++mnContentState;
660         }
661 
662         bool ShapeAttributeLayer::isCharRotationAngleValid() const
663         {
664             return mbCharRotationAngleValid ? true : haveChild() ? mpChild->isCharRotationAngleValid() : false;
665         }
666 
667         double ShapeAttributeLayer::getCharRotationAngle() const
668         {
669             return calcValue( mnCharRotationAngle,
670                               mbCharRotationAngleValid,
671                               &ShapeAttributeLayer::isCharRotationAngleValid,
672                               &ShapeAttributeLayer::getCharRotationAngle );
673         }
674 
675         void ShapeAttributeLayer::setCharRotationAngle( const double& rNewAngle )
676         {
677             ENSURE_OR_THROW( ::rtl::math::isFinite(rNewAngle),
678                               "ShapeAttributeLayer::setCharRotationAngle(): Invalid angle" );
679 
680             mnCharRotationAngle = rNewAngle;
681             mbCharRotationAngleValid = true;
682             ++mnContentState;
683         }
684 
685         bool ShapeAttributeLayer::isCharWeightValid() const
686         {
687             return mbCharWeightValid ? true : haveChild() ? mpChild->isCharWeightValid() : false;
688         }
689 
690         double ShapeAttributeLayer::getCharWeight() const
691         {
692             // mnAdditiveMode is ignored, cannot combine strings in
693             // any sensible way
694             if( mbCharWeightValid )
695                 return mnCharWeight;
696             else if( haveChild() )
697                 return mpChild->getCharWeight();
698             else
699                 return awt::FontWeight::NORMAL;
700         }
701 
702         void ShapeAttributeLayer::setCharWeight( const double& rValue )
703         {
704             // TODO(Q1): Check range here.
705             mnCharWeight = rValue;
706             mbCharWeightValid = true;
707             ++mnContentState;
708         }
709 
710         bool ShapeAttributeLayer::isUnderlineModeValid() const
711         {
712             return mbUnderlineModeValid ? true : haveChild() ? mpChild->isUnderlineModeValid() : false;
713         }
714 
715         sal_Int16 ShapeAttributeLayer::getUnderlineMode() const
716         {
717             // mnAdditiveMode is ignored, SMIL spec requires to not combine
718             // bools in any sensible way
719             if( mbUnderlineModeValid )
720                 return mnUnderlineMode;
721             else if( haveChild() )
722                 return mpChild->getUnderlineMode();
723             else
724                 return awt::FontUnderline::NONE; // default is no underline
725         }
726 
727         void ShapeAttributeLayer::setUnderlineMode( const sal_Int16& rUnderlineMode )
728         {
729             // TODO(Q1): Check range here.
730             mnUnderlineMode = rUnderlineMode;
731             mbUnderlineModeValid = true;
732             ++mnContentState;
733         }
734 
735         bool ShapeAttributeLayer::isFontFamilyValid() const
736         {
737             return mbFontFamilyValid ? true : haveChild() ? mpChild->isFontFamilyValid() : false;
738         }
739 
740         ::rtl::OUString ShapeAttributeLayer::getFontFamily() const
741         {
742             // mnAdditiveMode is ignored, cannot combine strings in
743             // any sensible way
744             if( mbFontFamilyValid )
745                 return maFontFamily;
746             else if( haveChild() )
747                 return mpChild->getFontFamily();
748             else
749                 return ::rtl::OUString();
750         }
751 
752         void ShapeAttributeLayer::setFontFamily( const ::rtl::OUString& rName )
753         {
754             maFontFamily = rName;
755             mbFontFamilyValid = true;
756             ++mnContentState;
757         }
758 
759         bool ShapeAttributeLayer::isCharPostureValid() const
760         {
761             return mbCharPostureValid ? true : haveChild() ? mpChild->isCharPostureValid() : false;
762         }
763 
764         sal_Int16 ShapeAttributeLayer::getCharPosture() const
765         {
766             // mnAdditiveMode is ignored, cannot combine strings in
767             // any sensible way
768             if( mbCharPostureValid )
769                 return sal::static_int_cast<sal_Int16>(meCharPosture);
770             else if( haveChild() )
771                 return sal::static_int_cast<sal_Int16>(mpChild->getCharPosture());
772             else
773                 return sal::static_int_cast<sal_Int16>(awt::FontSlant_NONE);
774         }
775 
776         void ShapeAttributeLayer::setCharPosture( const sal_Int16& rStyle )
777         {
778             // TODO(Q1): Check range here.
779             meCharPosture = (awt::FontSlant)rStyle;
780             mbCharPostureValid = true;
781             ++mnContentState;
782         }
783 
784         bool ShapeAttributeLayer::isCharScaleValid() const
785         {
786             return mbCharScaleValid ? true : haveChild() ? mpChild->isCharScaleValid() : false;
787         }
788 
789         double ShapeAttributeLayer::getCharScale() const
790         {
791             return calcValue( mnCharScale,
792                               mbCharScaleValid,
793                               &ShapeAttributeLayer::isCharScaleValid,
794                               &ShapeAttributeLayer::getCharScale );
795         }
796 
797         void ShapeAttributeLayer::setCharScale( const double& rNewHeight )
798         {
799             ENSURE_OR_THROW( ::rtl::math::isFinite(rNewHeight),
800                               "ShapeAttributeLayer::setCharScale(): Invalid height" );
801 
802             mnCharScale = rNewHeight;
803             mbCharScaleValid = true;
804             ++mnContentState;
805         }
806 
807         State::StateId ShapeAttributeLayer::getTransformationState() const
808         {
809             return haveChild() ?
810                 ::std::max( mnTransformationState,
811                             mpChild->getTransformationState() ) :
812                 mnTransformationState;
813         }
814 
815         State::StateId ShapeAttributeLayer::getClipState() const
816         {
817             return haveChild() ?
818                 ::std::max( mnClipState,
819                             mpChild->getClipState() ) :
820                 mnClipState;
821         }
822 
823         State::StateId ShapeAttributeLayer::getAlphaState() const
824         {
825             return haveChild() ?
826                 ::std::max( mnAlphaState,
827                             mpChild->getAlphaState() ) :
828                 mnAlphaState;
829         }
830 
831         State::StateId ShapeAttributeLayer::getPositionState() const
832  		{
833             return haveChild() ?
834                 ::std::max( mnPositionState,
835                             mpChild->getPositionState() ) :
836                 mnPositionState;
837         }
838 
839         State::StateId ShapeAttributeLayer::getContentState() const
840         {
841             return haveChild() ?
842                 ::std::max( mnContentState,
843                             mpChild->getContentState() ) :
844                 mnContentState;
845         }
846 
847         State::StateId ShapeAttributeLayer::getVisibilityState() const
848         {
849             return haveChild() ?
850                 ::std::max( mnVisibilityState,
851                             mpChild->getVisibilityState() ) :
852                 mnVisibilityState;
853         }
854 
855     }
856 }
857