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