1*ca5ec200SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*ca5ec200SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*ca5ec200SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*ca5ec200SAndrew Rist  * distributed with this work for additional information
6*ca5ec200SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*ca5ec200SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*ca5ec200SAndrew Rist  * "License"); you may not use this file except in compliance
9*ca5ec200SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*ca5ec200SAndrew Rist  *
11*ca5ec200SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*ca5ec200SAndrew Rist  *
13*ca5ec200SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*ca5ec200SAndrew Rist  * software distributed under the License is distributed on an
15*ca5ec200SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*ca5ec200SAndrew Rist  * KIND, either express or implied.  See the License for the
17*ca5ec200SAndrew Rist  * specific language governing permissions and limitations
18*ca5ec200SAndrew Rist  * under the License.
19*ca5ec200SAndrew Rist  *
20*ca5ec200SAndrew Rist  *************************************************************/
21*ca5ec200SAndrew Rist 
22*ca5ec200SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #include "oox/drawingml/lineproperties.hxx"
25cdf0e10cSrcweir #include <vector>
26cdf0e10cSrcweir #include <rtl/ustrbuf.hxx>
27cdf0e10cSrcweir #include <com/sun/star/beans/NamedValue.hpp>
28cdf0e10cSrcweir #include <com/sun/star/container/XNameContainer.hpp>
29cdf0e10cSrcweir #include <com/sun/star/drawing/FlagSequence.hpp>
30cdf0e10cSrcweir #include <com/sun/star/drawing/LineDash.hpp>
31cdf0e10cSrcweir #include <com/sun/star/drawing/LineJoint.hpp>
32cdf0e10cSrcweir #include <com/sun/star/drawing/LineStyle.hpp>
33cdf0e10cSrcweir #include <com/sun/star/drawing/PointSequence.hpp>
34cdf0e10cSrcweir #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
35cdf0e10cSrcweir #include "oox/drawingml/drawingmltypes.hxx"
36cdf0e10cSrcweir #include "oox/drawingml/shapepropertymap.hxx"
37cdf0e10cSrcweir #include "oox/helper/containerhelper.hxx"
38cdf0e10cSrcweir #include "oox/helper/graphichelper.hxx"
39cdf0e10cSrcweir #include "oox/token/tokens.hxx"
40cdf0e10cSrcweir 
41cdf0e10cSrcweir using namespace ::com::sun::star::beans;
42cdf0e10cSrcweir using namespace ::com::sun::star::drawing;
43cdf0e10cSrcweir 
44cdf0e10cSrcweir using ::rtl::OUString;
45cdf0e10cSrcweir using ::rtl::OUStringBuffer;
46cdf0e10cSrcweir using ::com::sun::star::uno::Any;
47cdf0e10cSrcweir using ::com::sun::star::uno::Reference;
48cdf0e10cSrcweir using ::com::sun::star::awt::Point;
49cdf0e10cSrcweir using ::com::sun::star::container::XNameContainer;
50cdf0e10cSrcweir 
51cdf0e10cSrcweir namespace oox {
52cdf0e10cSrcweir namespace drawingml {
53cdf0e10cSrcweir 
54cdf0e10cSrcweir // ============================================================================
55cdf0e10cSrcweir 
56cdf0e10cSrcweir namespace {
57cdf0e10cSrcweir 
lclSetDashData(LineDash & orLineDash,sal_Int16 nDots,sal_Int32 nDotLen,sal_Int16 nDashes,sal_Int32 nDashLen,sal_Int32 nDistance)58cdf0e10cSrcweir void lclSetDashData( LineDash& orLineDash, sal_Int16 nDots, sal_Int32 nDotLen,
59cdf0e10cSrcweir         sal_Int16 nDashes, sal_Int32 nDashLen, sal_Int32 nDistance )
60cdf0e10cSrcweir {
61cdf0e10cSrcweir     orLineDash.Dots = nDots;
62cdf0e10cSrcweir     orLineDash.DotLen = nDotLen;
63cdf0e10cSrcweir     orLineDash.Dashes = nDashes;
64cdf0e10cSrcweir     orLineDash.DashLen = nDashLen;
65cdf0e10cSrcweir     orLineDash.Distance = nDistance;
66cdf0e10cSrcweir }
67cdf0e10cSrcweir 
68cdf0e10cSrcweir /** Converts the specified preset dash to API dash.
69cdf0e10cSrcweir 
70cdf0e10cSrcweir     Line length and dot length are set relative to line width and have to be
71cdf0e10cSrcweir     multiplied by the actual line width after this function.
72cdf0e10cSrcweir  */
lclConvertPresetDash(LineDash & orLineDash,sal_Int32 nPresetDash)73cdf0e10cSrcweir void lclConvertPresetDash( LineDash& orLineDash, sal_Int32 nPresetDash )
74cdf0e10cSrcweir {
75cdf0e10cSrcweir     switch( nPresetDash )
76cdf0e10cSrcweir     {
77cdf0e10cSrcweir         case XML_dot:           lclSetDashData( orLineDash, 1, 1, 0, 0, 3 );    break;
78cdf0e10cSrcweir         case XML_dash:          lclSetDashData( orLineDash, 0, 0, 1, 4, 3 );    break;
79cdf0e10cSrcweir         case XML_dashDot:       lclSetDashData( orLineDash, 1, 1, 1, 4, 3 );    break;
80cdf0e10cSrcweir 
81cdf0e10cSrcweir         case XML_lgDash:        lclSetDashData( orLineDash, 0, 0, 1, 8, 3 );    break;
82cdf0e10cSrcweir         case XML_lgDashDot:     lclSetDashData( orLineDash, 1, 1, 1, 8, 3 );    break;
83cdf0e10cSrcweir         case XML_lgDashDotDot:  lclSetDashData( orLineDash, 2, 1, 1, 8, 3 );    break;
84cdf0e10cSrcweir 
85cdf0e10cSrcweir         case XML_sysDot:        lclSetDashData( orLineDash, 1, 1, 0, 0, 1 );    break;
86cdf0e10cSrcweir         case XML_sysDash:       lclSetDashData( orLineDash, 0, 0, 1, 3, 1 );    break;
87cdf0e10cSrcweir         case XML_sysDashDot:    lclSetDashData( orLineDash, 1, 1, 1, 3, 1 );    break;
88cdf0e10cSrcweir         case XML_sysDashDotDot: lclSetDashData( orLineDash, 2, 1, 1, 3, 1 );    break;
89cdf0e10cSrcweir 
90cdf0e10cSrcweir         default:
91cdf0e10cSrcweir             OSL_ENSURE( false, "lclConvertPresetDash - unsupported preset dash" );
92cdf0e10cSrcweir             lclSetDashData( orLineDash, 0, 0, 1, 4, 3 );
93cdf0e10cSrcweir     }
94cdf0e10cSrcweir }
95cdf0e10cSrcweir 
96cdf0e10cSrcweir /** Converts the passed custom dash to API dash.
97cdf0e10cSrcweir 
98cdf0e10cSrcweir     Line length and dot length are set relative to line width and have to be
99cdf0e10cSrcweir     multiplied by the actual line width after this function.
100cdf0e10cSrcweir  */
lclConvertCustomDash(LineDash & orLineDash,const LineProperties::DashStopVector & rCustomDash)101cdf0e10cSrcweir void lclConvertCustomDash( LineDash& orLineDash, const LineProperties::DashStopVector& rCustomDash )
102cdf0e10cSrcweir {
103cdf0e10cSrcweir     if( rCustomDash.empty() )
104cdf0e10cSrcweir     {
105cdf0e10cSrcweir         OSL_ENSURE( false, "lclConvertCustomDash - unexpected empty custom dash" );
106cdf0e10cSrcweir         lclSetDashData( orLineDash, 0, 0, 1, 4, 3 );
107cdf0e10cSrcweir         return;
108cdf0e10cSrcweir     }
109cdf0e10cSrcweir 
110cdf0e10cSrcweir     // count dashes and dots (stops equal or less than 2 are assumed to be dots)
111cdf0e10cSrcweir     sal_Int16 nDots = 0;
112cdf0e10cSrcweir     sal_Int32 nDotLen = 0;
113cdf0e10cSrcweir     sal_Int16 nDashes = 0;
114cdf0e10cSrcweir     sal_Int32 nDashLen = 0;
115cdf0e10cSrcweir     sal_Int32 nDistance = 0;
116cdf0e10cSrcweir     for( LineProperties::DashStopVector::const_iterator aIt = rCustomDash.begin(), aEnd = rCustomDash.end(); aIt != aEnd; ++aIt )
117cdf0e10cSrcweir     {
118cdf0e10cSrcweir         if( aIt->first <= 2 )
119cdf0e10cSrcweir         {
120cdf0e10cSrcweir             ++nDots;
121cdf0e10cSrcweir             nDotLen += aIt->first;
122cdf0e10cSrcweir         }
123cdf0e10cSrcweir         else
124cdf0e10cSrcweir         {
125cdf0e10cSrcweir             ++nDashes;
126cdf0e10cSrcweir             nDashLen += aIt->first;
127cdf0e10cSrcweir         }
128cdf0e10cSrcweir         nDistance += aIt->second;
129cdf0e10cSrcweir     }
130cdf0e10cSrcweir     orLineDash.DotLen = (nDots > 0) ? ::std::max< sal_Int32 >( nDotLen / nDots, 1 ) : 0;
131cdf0e10cSrcweir     orLineDash.Dots = nDots;
132cdf0e10cSrcweir     orLineDash.DashLen = (nDashes > 0) ? ::std::max< sal_Int32 >( nDashLen / nDashes, 1 ) : 0;
133cdf0e10cSrcweir     orLineDash.Dashes = nDashes;
134cdf0e10cSrcweir     orLineDash.Distance = ::std::max< sal_Int32 >( nDistance / rCustomDash.size(), 1 );
135cdf0e10cSrcweir }
136cdf0e10cSrcweir 
lclGetDashStyle(sal_Int32 nToken)137cdf0e10cSrcweir DashStyle lclGetDashStyle( sal_Int32 nToken )
138cdf0e10cSrcweir {
139cdf0e10cSrcweir     switch( nToken )
140cdf0e10cSrcweir     {
141cdf0e10cSrcweir         case XML_rnd:   return DashStyle_ROUNDRELATIVE;
142cdf0e10cSrcweir         case XML_sq:    return DashStyle_RECTRELATIVE;
143cdf0e10cSrcweir         case XML_flat:  return DashStyle_RECT;
144cdf0e10cSrcweir     }
145cdf0e10cSrcweir     return DashStyle_ROUNDRELATIVE;
146cdf0e10cSrcweir }
147cdf0e10cSrcweir 
lclGetLineJoint(sal_Int32 nToken)148cdf0e10cSrcweir LineJoint lclGetLineJoint( sal_Int32 nToken )
149cdf0e10cSrcweir {
150cdf0e10cSrcweir     switch( nToken )
151cdf0e10cSrcweir     {
152cdf0e10cSrcweir         case XML_round: return LineJoint_ROUND;
153cdf0e10cSrcweir         case XML_bevel: return LineJoint_BEVEL;
154cdf0e10cSrcweir         case XML_miter: return LineJoint_MITER;
155cdf0e10cSrcweir     }
156cdf0e10cSrcweir     return LineJoint_ROUND;
157cdf0e10cSrcweir }
158cdf0e10cSrcweir 
159cdf0e10cSrcweir const sal_Int32 OOX_ARROWSIZE_SMALL     = 0;
160cdf0e10cSrcweir const sal_Int32 OOX_ARROWSIZE_MEDIUM    = 1;
161cdf0e10cSrcweir const sal_Int32 OOX_ARROWSIZE_LARGE     = 2;
162cdf0e10cSrcweir 
lclGetArrowSize(sal_Int32 nToken)163cdf0e10cSrcweir sal_Int32 lclGetArrowSize( sal_Int32 nToken )
164cdf0e10cSrcweir {
165cdf0e10cSrcweir     switch( nToken )
166cdf0e10cSrcweir     {
167cdf0e10cSrcweir         case XML_sm:    return OOX_ARROWSIZE_SMALL;
168cdf0e10cSrcweir         case XML_med:   return OOX_ARROWSIZE_MEDIUM;
169cdf0e10cSrcweir         case XML_lg:    return OOX_ARROWSIZE_LARGE;
170cdf0e10cSrcweir     }
171cdf0e10cSrcweir     return OOX_ARROWSIZE_MEDIUM;
172cdf0e10cSrcweir }
173cdf0e10cSrcweir 
174cdf0e10cSrcweir // ----------------------------------------------------------------------------
175cdf0e10cSrcweir 
lclPushMarkerProperties(ShapePropertyMap & rPropMap,const LineArrowProperties & rArrowProps,sal_Int32 nLineWidth,bool bLineEnd)176cdf0e10cSrcweir void lclPushMarkerProperties( ShapePropertyMap& rPropMap,
177cdf0e10cSrcweir         const LineArrowProperties& rArrowProps, sal_Int32 nLineWidth, bool bLineEnd )
178cdf0e10cSrcweir {
179cdf0e10cSrcweir     /*  Store the marker polygon and the marker name in a single value, to be
180cdf0e10cSrcweir         able to pass both to the ShapePropertyMap::setProperty() function. */
181cdf0e10cSrcweir     NamedValue aNamedMarker;
182cdf0e10cSrcweir 
183cdf0e10cSrcweir     OUStringBuffer aBuffer;
184cdf0e10cSrcweir     sal_Int32 nMarkerWidth = 0;
185cdf0e10cSrcweir     bool bMarkerCenter = false;
186cdf0e10cSrcweir     sal_Int32 nArrowType = rArrowProps.moArrowType.get( XML_none );
187cdf0e10cSrcweir     switch( nArrowType )
188cdf0e10cSrcweir     {
189cdf0e10cSrcweir         case XML_triangle:
190cdf0e10cSrcweir             aBuffer.append( CREATE_OUSTRING( "msArrowEnd" ) );
191cdf0e10cSrcweir         break;
192cdf0e10cSrcweir         case XML_arrow:
193cdf0e10cSrcweir             aBuffer.append( CREATE_OUSTRING( "msArrowOpenEnd" ) );
194cdf0e10cSrcweir         break;
195cdf0e10cSrcweir         case XML_stealth:
196cdf0e10cSrcweir             aBuffer.append( CREATE_OUSTRING( "msArrowStealthEnd" ) );
197cdf0e10cSrcweir         break;
198cdf0e10cSrcweir         case XML_diamond:
199cdf0e10cSrcweir             aBuffer.append( CREATE_OUSTRING( "msArrowDiamondEnd" ) );
200cdf0e10cSrcweir             bMarkerCenter = true;
201cdf0e10cSrcweir         break;
202cdf0e10cSrcweir         case XML_oval:
203cdf0e10cSrcweir             aBuffer.append( CREATE_OUSTRING( "msArrowOvalEnd" ) );
204cdf0e10cSrcweir             bMarkerCenter = true;
205cdf0e10cSrcweir         break;
206cdf0e10cSrcweir     }
207cdf0e10cSrcweir 
208cdf0e10cSrcweir     if( aBuffer.getLength() > 0 )
209cdf0e10cSrcweir     {
210cdf0e10cSrcweir         sal_Int32 nLength = lclGetArrowSize( rArrowProps.moArrowLength.get( XML_med ) );
211cdf0e10cSrcweir         sal_Int32 nWidth  = lclGetArrowSize( rArrowProps.moArrowWidth.get( XML_med ) );
212cdf0e10cSrcweir 
213cdf0e10cSrcweir         sal_Int32 nNameIndex = nWidth * 3 + nLength + 1;
214cdf0e10cSrcweir         aBuffer.append( sal_Unicode( ' ' ) ).append( nNameIndex );
215cdf0e10cSrcweir         OUString aMarkerName = aBuffer.makeStringAndClear();
216cdf0e10cSrcweir 
217cdf0e10cSrcweir         bool bIsArrow = nArrowType == XML_arrow;
218cdf0e10cSrcweir         double fArrowLength = 1.0;
219cdf0e10cSrcweir         switch( nLength )
220cdf0e10cSrcweir         {
221cdf0e10cSrcweir             case OOX_ARROWSIZE_SMALL:   fArrowLength = (bIsArrow ? 3.5 : 2.0); break;
222cdf0e10cSrcweir             case OOX_ARROWSIZE_MEDIUM:  fArrowLength = (bIsArrow ? 4.5 : 3.0); break;
223cdf0e10cSrcweir             case OOX_ARROWSIZE_LARGE:   fArrowLength = (bIsArrow ? 6.0 : 5.0); break;
224cdf0e10cSrcweir         }
225cdf0e10cSrcweir         double fArrowWidth = 1.0;
226cdf0e10cSrcweir         switch( nWidth )
227cdf0e10cSrcweir         {
228cdf0e10cSrcweir             case OOX_ARROWSIZE_SMALL:   fArrowWidth = (bIsArrow ? 3.5 : 2.0);  break;
229cdf0e10cSrcweir             case OOX_ARROWSIZE_MEDIUM:  fArrowWidth = (bIsArrow ? 4.5 : 3.0);  break;
230cdf0e10cSrcweir             case OOX_ARROWSIZE_LARGE:   fArrowWidth = (bIsArrow ? 6.0 : 5.0);  break;
231cdf0e10cSrcweir         }
232cdf0e10cSrcweir         // set arrow width relative to line width
233cdf0e10cSrcweir         sal_Int32 nBaseLineWidth = ::std::max< sal_Int32 >( nLineWidth, 70 );
234cdf0e10cSrcweir         nMarkerWidth = static_cast< sal_Int32 >( fArrowWidth * nBaseLineWidth );
235cdf0e10cSrcweir 
236cdf0e10cSrcweir         /*  Test if the marker already exists in the marker table, do not
237cdf0e10cSrcweir             create it again in this case. If markers are inserted explicitly
238cdf0e10cSrcweir             instead by their name, the polygon will be created always.
239cdf0e10cSrcweir             TODO: this can be optimized by using a map. */
240cdf0e10cSrcweir         if( !rPropMap.hasNamedLineMarkerInTable( aMarkerName ) )
241cdf0e10cSrcweir         {
242cdf0e10cSrcweir // pass X and Y as percentage to OOX_ARROW_POINT
243cdf0e10cSrcweir #define OOX_ARROW_POINT( x, y ) Point( static_cast< sal_Int32 >( fArrowWidth * x ), static_cast< sal_Int32 >( fArrowLength * y ) )
244cdf0e10cSrcweir 
245cdf0e10cSrcweir             ::std::vector< Point > aPoints;
246cdf0e10cSrcweir             switch( rArrowProps.moArrowType.get() )
247cdf0e10cSrcweir             {
248cdf0e10cSrcweir                 case XML_triangle:
249cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(  50,   0 ) );
250cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT( 100, 100 ) );
251cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(   0, 100 ) );
252cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(  50,   0 ) );
253cdf0e10cSrcweir                 break;
254cdf0e10cSrcweir                 case XML_arrow:
255cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(  50,   0 ) );
256cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT( 100,  91 ) );
257cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(  85, 100 ) );
258cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(  50,  36 ) );
259cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(  15, 100 ) );
260cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(   0,  91 ) );
261cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(  50,   0 ) );
262cdf0e10cSrcweir                 break;
263cdf0e10cSrcweir                 case XML_stealth:
264cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(  50,   0 ) );
265cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT( 100, 100 ) );
266cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(  50,  60 ) );
267cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(   0, 100 ) );
268cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(  50,   0 ) );
269cdf0e10cSrcweir                 break;
270cdf0e10cSrcweir                 case XML_diamond:
271cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(  50,   0 ) );
272cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT( 100,  50 ) );
273cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(  50, 100 ) );
274cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(   0,  50 ) );
275cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(  50,   0 ) );
276cdf0e10cSrcweir                 break;
277cdf0e10cSrcweir                 case XML_oval:
278cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(  50,   0 ) );
279cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(  75,   7 ) );
280cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(  93,  25 ) );
281cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT( 100,  50 ) );
282cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(  93,  75 ) );
283cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(  75,  93 ) );
284cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(  50, 100 ) );
285cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(  25,  93 ) );
286cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(   7,  75 ) );
287cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(   0,  50 ) );
288cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(   7,  25 ) );
289cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(  25,   7 ) );
290cdf0e10cSrcweir                     aPoints.push_back( OOX_ARROW_POINT(  50,   0 ) );
291cdf0e10cSrcweir                 break;
292cdf0e10cSrcweir             }
293cdf0e10cSrcweir #undef OOX_ARROW_POINT
294cdf0e10cSrcweir 
295cdf0e10cSrcweir             OSL_ENSURE( !aPoints.empty(), "lclPushMarkerProperties - missing arrow coordinates" );
296cdf0e10cSrcweir             if( !aPoints.empty() )
297cdf0e10cSrcweir             {
298cdf0e10cSrcweir                 PolyPolygonBezierCoords aMarkerCoords;
299cdf0e10cSrcweir                 aMarkerCoords.Coordinates.realloc( 1 );
300cdf0e10cSrcweir                 aMarkerCoords.Coordinates[ 0 ] = ContainerHelper::vectorToSequence( aPoints );
301cdf0e10cSrcweir 
302cdf0e10cSrcweir                 ::std::vector< PolygonFlags > aFlags( aPoints.size(), PolygonFlags_NORMAL );
303cdf0e10cSrcweir                 aMarkerCoords.Flags.realloc( 1 );
304cdf0e10cSrcweir                 aMarkerCoords.Flags[ 0 ] = ContainerHelper::vectorToSequence( aFlags );
305cdf0e10cSrcweir 
306cdf0e10cSrcweir                 aNamedMarker.Name = aMarkerName;
307cdf0e10cSrcweir                 aNamedMarker.Value <<= aMarkerCoords;
308cdf0e10cSrcweir             }
309cdf0e10cSrcweir         }
310cdf0e10cSrcweir         else
311cdf0e10cSrcweir         {
312cdf0e10cSrcweir             /*  Named marker object exists already in the marker table, pass
313cdf0e10cSrcweir                 its name only. This will set the name as property value, but
314cdf0e10cSrcweir                 does not create a new object in the marker table. */
315cdf0e10cSrcweir             aNamedMarker.Name = aMarkerName;
316cdf0e10cSrcweir         }
317cdf0e10cSrcweir     }
318cdf0e10cSrcweir 
319cdf0e10cSrcweir     // push the properties (filled aNamedMarker.Name indicates valid marker)
320cdf0e10cSrcweir     if( aNamedMarker.Name.getLength() > 0 )
321cdf0e10cSrcweir     {
322cdf0e10cSrcweir         if( bLineEnd )
323cdf0e10cSrcweir         {
324cdf0e10cSrcweir             rPropMap.setProperty( SHAPEPROP_LineEnd, aNamedMarker );
325cdf0e10cSrcweir             rPropMap.setProperty( SHAPEPROP_LineEndWidth, nMarkerWidth );
326cdf0e10cSrcweir             rPropMap.setProperty( SHAPEPROP_LineEndCenter, bMarkerCenter );
327cdf0e10cSrcweir         }
328cdf0e10cSrcweir         else
329cdf0e10cSrcweir         {
330cdf0e10cSrcweir             rPropMap.setProperty( SHAPEPROP_LineStart, aNamedMarker );
331cdf0e10cSrcweir             rPropMap.setProperty( SHAPEPROP_LineStartWidth, nMarkerWidth );
332cdf0e10cSrcweir             rPropMap.setProperty( SHAPEPROP_LineStartCenter, bMarkerCenter );
333cdf0e10cSrcweir         }
334cdf0e10cSrcweir     }
335cdf0e10cSrcweir }
336cdf0e10cSrcweir 
337cdf0e10cSrcweir } // namespace
338cdf0e10cSrcweir 
339cdf0e10cSrcweir // ============================================================================
340cdf0e10cSrcweir 
assignUsed(const LineArrowProperties & rSourceProps)341cdf0e10cSrcweir void LineArrowProperties::assignUsed( const LineArrowProperties& rSourceProps )
342cdf0e10cSrcweir {
343cdf0e10cSrcweir     moArrowType.assignIfUsed( rSourceProps.moArrowType );
344cdf0e10cSrcweir     moArrowWidth.assignIfUsed( rSourceProps.moArrowWidth );
345cdf0e10cSrcweir     moArrowLength.assignIfUsed( rSourceProps.moArrowLength );
346cdf0e10cSrcweir }
347cdf0e10cSrcweir 
348cdf0e10cSrcweir // ============================================================================
349cdf0e10cSrcweir 
assignUsed(const LineProperties & rSourceProps)350cdf0e10cSrcweir void LineProperties::assignUsed( const LineProperties& rSourceProps )
351cdf0e10cSrcweir {
352cdf0e10cSrcweir     maStartArrow.assignUsed( rSourceProps.maStartArrow );
353cdf0e10cSrcweir     maEndArrow.assignUsed( rSourceProps.maEndArrow );
354cdf0e10cSrcweir     maLineFill.assignUsed( rSourceProps.maLineFill );
355cdf0e10cSrcweir     if( !rSourceProps.maCustomDash.empty() )
356cdf0e10cSrcweir         maCustomDash = rSourceProps.maCustomDash;
357cdf0e10cSrcweir     moLineWidth.assignIfUsed( rSourceProps.moLineWidth );
358cdf0e10cSrcweir     moPresetDash.assignIfUsed( rSourceProps.moPresetDash );
359cdf0e10cSrcweir     moLineCompound.assignIfUsed( rSourceProps.moLineCompound );
360cdf0e10cSrcweir     moLineCap.assignIfUsed( rSourceProps.moLineCap );
361cdf0e10cSrcweir     moLineJoint.assignIfUsed( rSourceProps.moLineJoint );
362cdf0e10cSrcweir }
363cdf0e10cSrcweir 
pushToPropMap(ShapePropertyMap & rPropMap,const GraphicHelper & rGraphicHelper,sal_Int32 nPhClr) const364cdf0e10cSrcweir void LineProperties::pushToPropMap( ShapePropertyMap& rPropMap,
365cdf0e10cSrcweir         const GraphicHelper& rGraphicHelper, sal_Int32 nPhClr ) const
366cdf0e10cSrcweir {
367cdf0e10cSrcweir     // line fill type must exist, otherwise ignore other properties
368cdf0e10cSrcweir     if( maLineFill.moFillType.has() )
369cdf0e10cSrcweir     {
370cdf0e10cSrcweir         // line style (our core only supports none and solid)
371cdf0e10cSrcweir         LineStyle eLineStyle = (maLineFill.moFillType.get() == XML_noFill) ? LineStyle_NONE : LineStyle_SOLID;
372cdf0e10cSrcweir 
373cdf0e10cSrcweir         // convert line width from EMUs to 1/100mm
374cdf0e10cSrcweir         sal_Int32 nLineWidth = convertEmuToHmm( moLineWidth.get( 0 ) );
375cdf0e10cSrcweir 
376cdf0e10cSrcweir         // create line dash from preset dash token (not for invisible line)
377cdf0e10cSrcweir         if( (eLineStyle != LineStyle_NONE) && (moPresetDash.differsFrom( XML_solid ) || (!moPresetDash && !maCustomDash.empty())) )
378cdf0e10cSrcweir         {
379cdf0e10cSrcweir             LineDash aLineDash;
380cdf0e10cSrcweir             aLineDash.Style = lclGetDashStyle( moLineCap.get( XML_rnd ) );
381cdf0e10cSrcweir 
382cdf0e10cSrcweir             // convert preset dash or custom dash
383cdf0e10cSrcweir             if( moPresetDash.has() )
384cdf0e10cSrcweir                 lclConvertPresetDash( aLineDash, moPresetDash.get() );
385cdf0e10cSrcweir             else
386cdf0e10cSrcweir                 lclConvertCustomDash( aLineDash, maCustomDash );
387cdf0e10cSrcweir 
388cdf0e10cSrcweir             // convert relative dash/dot length to absolute length
389cdf0e10cSrcweir             sal_Int32 nBaseLineWidth = ::std::max< sal_Int32 >( nLineWidth, 35 );
390cdf0e10cSrcweir             aLineDash.DotLen *= nBaseLineWidth;
391cdf0e10cSrcweir             aLineDash.DashLen *= nBaseLineWidth;
392cdf0e10cSrcweir             aLineDash.Distance *= nBaseLineWidth;
393cdf0e10cSrcweir 
394cdf0e10cSrcweir             if( rPropMap.setProperty( SHAPEPROP_LineDash, aLineDash ) )
395cdf0e10cSrcweir                 eLineStyle = LineStyle_DASH;
396cdf0e10cSrcweir         }
397cdf0e10cSrcweir 
398cdf0e10cSrcweir         // set final line style property
399cdf0e10cSrcweir         rPropMap.setProperty( SHAPEPROP_LineStyle, eLineStyle );
400cdf0e10cSrcweir 
401cdf0e10cSrcweir         // line joint type
402cdf0e10cSrcweir         if( moLineJoint.has() )
403cdf0e10cSrcweir             rPropMap.setProperty( SHAPEPROP_LineJoint, lclGetLineJoint( moLineJoint.get() ) );
404cdf0e10cSrcweir 
405cdf0e10cSrcweir         // line width in 1/100mm
406cdf0e10cSrcweir         rPropMap.setProperty( SHAPEPROP_LineWidth, nLineWidth );
407cdf0e10cSrcweir 
408cdf0e10cSrcweir         // line color and transparence
409cdf0e10cSrcweir         Color aLineColor = maLineFill.getBestSolidColor();
410cdf0e10cSrcweir         if( aLineColor.isUsed() )
411cdf0e10cSrcweir         {
412cdf0e10cSrcweir             rPropMap.setProperty( SHAPEPROP_LineColor, aLineColor.getColor( rGraphicHelper, nPhClr ) );
413cdf0e10cSrcweir             if( aLineColor.hasTransparency() )
414cdf0e10cSrcweir                 rPropMap.setProperty( SHAPEPROP_LineTransparency, aLineColor.getTransparency() );
415cdf0e10cSrcweir         }
416cdf0e10cSrcweir 
417cdf0e10cSrcweir         // line markers
418cdf0e10cSrcweir         lclPushMarkerProperties( rPropMap, maStartArrow, nLineWidth, false );
419cdf0e10cSrcweir         lclPushMarkerProperties( rPropMap, maEndArrow,   nLineWidth, true );
420cdf0e10cSrcweir     }
421cdf0e10cSrcweir }
422cdf0e10cSrcweir 
423cdf0e10cSrcweir // ============================================================================
424cdf0e10cSrcweir 
425cdf0e10cSrcweir } // namespace drawingml
426cdf0e10cSrcweir } // namespace oox
427cdf0e10cSrcweir 
428