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