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