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