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 #include <oox/drawingml/shapepropertymap.hxx>
21 
22 #include <com/sun/star/awt/Gradient.hpp>
23 #include <com/sun/star/beans/NamedValue.hpp>
24 #include <com/sun/star/drawing/LineDash.hpp>
25 #include <com/sun/star/drawing/Hatch.hpp>
26 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
27 #include <com/sun/star/graphic/XGraphic.hpp>
28 
29 #include <oox/helper/modelobjecthelper.hxx>
30 #include <oox/token/properties.hxx>
31 
32 namespace oox {
33 namespace drawingml {
34 
35 using namespace ::com::sun::star;
36 using namespace ::com::sun::star::beans;
37 using namespace ::com::sun::star::drawing;
38 using namespace ::com::sun::star::uno;
39 
40 namespace {
41 
42 static const ShapePropertyIds spnDefaultShapeIds =
43 {
44     PROP_LineStyle, PROP_LineWidth, PROP_LineColor, PROP_LineTransparence, PROP_LineDash, PROP_LineCap, PROP_LineJoint,
45     PROP_LineStartName, PROP_LineStartWidth, PROP_LineStartCenter, PROP_LineEndName, PROP_LineEndWidth, PROP_LineEndCenter,
46     PROP_FillStyle, PROP_FillColor, PROP_FillTransparence, PROP_FillTransparenceGradientName, PROP_FillGradient,
47     PROP_FillBitmap, PROP_FillBitmapMode, PROP_FillBitmapSizeX, PROP_FillBitmapSizeY,
48     PROP_FillBitmapPositionOffsetX, PROP_FillBitmapPositionOffsetY, PROP_FillBitmapRectanglePoint,
49     PROP_FillHatch,
50     PROP_FillBackground,
51     PROP_FillBitmapName,
52     PROP_ShadowXDistance
53 };
54 
55 } // namespace
56 
57 ShapePropertyInfo ShapePropertyInfo::DEFAULT( spnDefaultShapeIds, true, false, false, false, false );
58 
ShapePropertyInfo(const ShapePropertyIds & rnPropertyIds,bool bNamedLineMarker,bool bNamedLineDash,bool bNamedFillGradient,bool bNamedFillBitmap,bool bNamedFillHatch)59 ShapePropertyInfo::ShapePropertyInfo( const ShapePropertyIds& rnPropertyIds,
60         bool bNamedLineMarker, bool bNamedLineDash, bool bNamedFillGradient, bool bNamedFillBitmap, bool bNamedFillHatch ) :
61     mrPropertyIds(rnPropertyIds),
62     mbNamedLineMarker( bNamedLineMarker ),
63     mbNamedLineDash( bNamedLineDash ),
64     mbNamedFillGradient( bNamedFillGradient ),
65     mbNamedFillBitmap( bNamedFillBitmap ),
66     mbNamedFillHatch( bNamedFillHatch )
67 {
68 }
69 
ShapePropertyMap(ModelObjectHelper & rModelObjHelper,const ShapePropertyInfo & rShapePropInfo)70 ShapePropertyMap::ShapePropertyMap( ModelObjectHelper& rModelObjHelper, const ShapePropertyInfo& rShapePropInfo ) :
71     mrModelObjHelper( rModelObjHelper ),
72     maShapePropInfo( rShapePropInfo )
73 {
74 }
75 
supportsProperty(ShapeProperty ePropId) const76 bool ShapePropertyMap::supportsProperty( ShapeProperty ePropId ) const
77 {
78     return maShapePropInfo.has( ePropId );
79 }
80 
hasNamedLineMarkerInTable(const OUString & rMarkerName) const81 bool ShapePropertyMap::hasNamedLineMarkerInTable( const OUString& rMarkerName ) const
82 {
83     return maShapePropInfo.mbNamedLineMarker && mrModelObjHelper.hasLineMarker( rMarkerName );
84 }
85 
setAnyProperty(ShapeProperty ePropId,const Any & rValue)86 bool ShapePropertyMap::setAnyProperty( ShapeProperty ePropId, const Any& rValue )
87 {
88     // get current property identifier for the specified property
89     sal_Int32 nPropId = maShapePropInfo[ ePropId ];
90     if( nPropId < 0 ) return false;
91 
92     // special handling for properties supporting named objects in tables
93     switch( ePropId )
94     {
95         case ShapeProperty::LineStart:
96         case ShapeProperty::LineEnd:
97             return setLineMarker( nPropId, rValue );
98 
99         case ShapeProperty::LineDash:
100             return setLineDash( nPropId, rValue );
101 
102         case ShapeProperty::FillGradient:
103             return setFillGradient( nPropId, rValue );
104 
105         case ShapeProperty::GradientTransparency:
106             return setGradientTrans( nPropId, rValue );
107 
108         case ShapeProperty::FillBitmap:
109             return setFillBitmap(nPropId, rValue);
110 
111         case ShapeProperty::FillBitmapName:
112             return setFillBitmapName(rValue);
113 
114         case ShapeProperty::FillHatch:
115             return setFillHatch( nPropId, rValue );
116 
117         default:;   // suppress compiler warnings
118     }
119 
120     // set plain property value
121     setAnyProperty( nPropId, rValue );
122     return true;
123 }
124 
125 // private --------------------------------------------------------------------
126 
setLineMarker(sal_Int32 nPropId,const Any & rValue)127 bool ShapePropertyMap::setLineMarker( sal_Int32 nPropId, const Any& rValue )
128 {
129     NamedValue aNamedMarker;
130     if( (rValue >>= aNamedMarker) && !aNamedMarker.Name.isEmpty() )
131     {
132         // push line marker explicitly
133         if( !maShapePropInfo.mbNamedLineMarker )
134             return setAnyProperty( nPropId, aNamedMarker.Value );
135 
136         // create named line marker (if coordinates have been passed) and push its name
137         bool bInserted = !aNamedMarker.Value.has< PolyPolygonBezierCoords >() ||
138             mrModelObjHelper.insertLineMarker( aNamedMarker.Name, aNamedMarker.Value.get< PolyPolygonBezierCoords >() );
139         return bInserted && setProperty( nPropId, aNamedMarker.Name );
140     }
141     return false;
142 }
143 
setLineDash(sal_Int32 nPropId,const Any & rValue)144 bool ShapePropertyMap::setLineDash( sal_Int32 nPropId, const Any& rValue )
145 {
146     // push line dash explicitly
147     if( !maShapePropInfo.mbNamedLineDash )
148         return setAnyProperty( nPropId, rValue );
149 
150     // create named line dash and push its name
151     if( rValue.has< LineDash >() )
152     {
153         OUString aDashName = mrModelObjHelper.insertLineDash( rValue.get< LineDash >() );
154         return !aDashName.isEmpty() && setProperty( nPropId, aDashName );
155     }
156 
157     return false;
158 }
159 
setFillGradient(sal_Int32 nPropId,const Any & rValue)160 bool ShapePropertyMap::setFillGradient( sal_Int32 nPropId, const Any& rValue )
161 {
162     // push gradient explicitly
163     if( !maShapePropInfo.mbNamedFillGradient )
164         return setAnyProperty( nPropId, rValue );
165 
166     // create named gradient and push its name
167     if( rValue.has< awt::Gradient >() )
168     {
169         OUString aGradientName = mrModelObjHelper.insertFillGradient( rValue.get< awt::Gradient >() );
170         return !aGradientName.isEmpty() && setProperty( nPropId, aGradientName );
171     }
172 
173     return false;
174 }
175 
setFillHatch(sal_Int32 nPropId,const Any & rValue)176 bool ShapePropertyMap::setFillHatch( sal_Int32 nPropId, const Any& rValue )
177 {
178     // push hatch explicitly
179     if( !maShapePropInfo.mbNamedFillHatch )
180         return setAnyProperty( nPropId, rValue );
181 
182     // create named hatch and push its name
183     if( rValue.has< Hatch >() )
184     {
185         OUString aHatchName = mrModelObjHelper.insertFillHatch( rValue.get< Hatch >() );
186         return !aHatchName.isEmpty() && setProperty( nPropId, aHatchName );
187     }
188 
189     return false;
190 }
191 
setGradientTrans(sal_Int32 nPropId,const Any & rValue)192 bool ShapePropertyMap::setGradientTrans( sal_Int32 nPropId, const Any& rValue )
193 {
194     // create named gradient and push its name
195     if( rValue.has< awt::Gradient >() )
196     {
197         OUString aGradientName = mrModelObjHelper.insertTransGrandient( rValue.get< awt::Gradient >() );
198         return !aGradientName.isEmpty()  && setProperty( nPropId, aGradientName );
199     }
200 
201     return false;
202 }
203 
setFillBitmap(sal_Int32 nPropId,const Any & rValue)204 bool ShapePropertyMap::setFillBitmap(sal_Int32 nPropId, const Any& rValue)
205 {
206     // push bitmap explicitly
207     if (!maShapePropInfo.mbNamedFillBitmap)
208     {
209         return setAnyProperty(nPropId, rValue);
210     }
211 
212     // create named bitmap URL and push its name
213     if (rValue.has<uno::Reference<graphic::XGraphic>>())
214     {
215         auto xGraphic = rValue.get<uno::Reference<graphic::XGraphic>>();
216         OUString aBitmapName = mrModelObjHelper.insertFillBitmapXGraphic(xGraphic);
217         return !aBitmapName.isEmpty() && setProperty(nPropId, aBitmapName);
218     }
219 
220     return false;
221 }
222 
setFillBitmapName(const Any & rValue)223 bool ShapePropertyMap::setFillBitmapName(const Any& rValue)
224 {
225     if (rValue.has<uno::Reference<graphic::XGraphic>>())
226     {
227         auto xGraphic = rValue.get<uno::Reference<graphic::XGraphic>>();
228         OUString aBitmapUrlName = mrModelObjHelper.insertFillBitmapXGraphic(xGraphic);
229         return !aBitmapUrlName.isEmpty() && setProperty(PROP_FillBitmapName, aBitmapUrlName);
230     }
231     return false;
232 }
233 
234 } // namespace drawingml
235 } // namespace oox
236 
237 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
238