24 #include <rtl/ustrbuf.hxx>
25 #include <osl/diagnose.h>
26 #include <com/sun/star/beans/NamedValue.hpp>
27 #include <com/sun/star/drawing/LineCap.hpp>
28 #include <com/sun/star/drawing/LineDash.hpp>
29 #include <com/sun/star/drawing/LineJoint.hpp>
30 #include <com/sun/star/drawing/LineStyle.hpp>
31 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
35 #include <oox/token/tokens.hxx>
46 void lclSetDashData( LineDash& orLineDash, sal_Int16 nDots, sal_Int32 nDotLen,
47 sal_Int16 nDashes, sal_Int32 nDashLen, sal_Int32 nDistance )
49 orLineDash.Dots = nDots;
50 orLineDash.DotLen = nDotLen;
51 orLineDash.Dashes = nDashes;
52 orLineDash.DashLen = nDashLen;
53 orLineDash.Distance = nDistance;
58 void lclConvertPresetDash(LineDash& orLineDash, sal_Int32 nPresetDash)
62 case XML_dot: lclSetDashData( orLineDash, 1, 1, 0, 0, 3 );
break;
63 case XML_dash: lclSetDashData( orLineDash, 1, 4, 0, 0, 3 );
break;
64 case XML_dashDot: lclSetDashData( orLineDash, 1, 4, 1, 1, 3 );
break;
66 case XML_lgDash: lclSetDashData( orLineDash, 1, 8, 0, 0, 3 );
break;
67 case XML_lgDashDot: lclSetDashData( orLineDash, 1, 8, 1, 1, 3 );
break;
68 case XML_lgDashDotDot: lclSetDashData( orLineDash, 1, 8, 2, 1, 3 );
break;
70 case XML_sysDot: lclSetDashData( orLineDash, 1, 1, 0, 0, 1 );
break;
71 case XML_sysDash: lclSetDashData( orLineDash, 1, 3, 0, 0, 1 );
break;
72 case XML_sysDashDot: lclSetDashData( orLineDash, 1, 3, 1, 1, 1 );
break;
73 case XML_sysDashDotDot: lclSetDashData( orLineDash, 1, 3, 2, 1, 1 );
break;
76 OSL_FAIL(
"lclConvertPresetDash - unsupported preset dash" );
77 lclSetDashData( orLineDash, 1, 4, 0, 0, 3 );
79 orLineDash.DotLen *= 100;
80 orLineDash.DashLen *= 100;
81 orLineDash.Distance *= 100;
91 OSL_ASSERT(!rCustomDash.empty());
93 orLineDash.Distance = rCustomDash[0].second;
95 orLineDash.DotLen = rCustomDash[0].first;
97 for(
const auto& rIt : rCustomDash)
99 if (rIt.first != orLineDash.DotLen)
104 orLineDash.Dashes = rCustomDash.size() - orLineDash.Dots;
105 if (orLineDash.Dashes > 0)
106 orLineDash.DashLen = rCustomDash[orLineDash.Dots].first;
108 orLineDash.DashLen = 0;
111 orLineDash.DotLen = orLineDash.DotLen / 1000;
112 orLineDash.DashLen = orLineDash.DashLen / 1000;
113 orLineDash.Distance = orLineDash.Distance / 1000;
121 void lclRecoverStandardDashStyles(LineDash& orLineDash, sal_Int32 nLineWidth)
123 sal_uInt16 nDots = orLineDash.Dots;
124 sal_uInt16 nDashes = orLineDash.Dashes;
125 sal_uInt32 nDotLen = orLineDash.DotLen;
126 sal_uInt32 nDashLen = orLineDash.DashLen;
127 sal_uInt32 nDistance = orLineDash.Distance;
129 double fWidthHelp = nLineWidth == 0 ? 26.95/100.0 : nLineWidth / 100.0;
132 if (nDots == 3 && nDotLen == 197 &&nDashes == 3 && nDashLen == 100 && nDistance == 100)
134 orLineDash.DashLen = 0;
136 else if (nDots == 1 && nDotLen == 100 && nDashes == 0 && nDistance == 50)
138 orLineDash.DotLen = 0;
140 else if (nDots == 2 && nDashes == 0 && nDotLen == nDistance
141 && std::abs(nDistance * fWidthHelp - 51.0) < fWidthHelp)
144 orLineDash.DotLen = 51;
145 orLineDash.Dashes = 1;
146 orLineDash.DashLen = 51;
147 orLineDash.Distance = 51;
148 orLineDash.Style = orLineDash.Style == DashStyle_ROUNDRELATIVE ? DashStyle_ROUND : DashStyle_RECT;
150 else if (nDots == 2 && nDashes == 3 && std::abs(nDotLen * fWidthHelp - 51.0) < fWidthHelp
151 && std::abs(nDashLen * fWidthHelp - 254.0) < fWidthHelp
152 && std::abs(nDistance * fWidthHelp - 127.0) < fWidthHelp)
154 orLineDash.DotLen = 51;
155 orLineDash.DashLen = 254;
156 orLineDash.Distance = 127;
157 orLineDash.Style = orLineDash.Style == DashStyle_ROUNDRELATIVE ? DashStyle_ROUND : DashStyle_RECT;
159 else if (nDots == 1 && nDotLen == 100 && nDashes == 0
160 && std::abs(nDistance * fWidthHelp - 457.0) < fWidthHelp)
162 orLineDash.DotLen = 0;
163 orLineDash.Distance = 457;
164 orLineDash.Style = orLineDash.Style == DashStyle_ROUNDRELATIVE ? DashStyle_ROUND : DashStyle_RECT;
166 else if (nDots == 1 && nDashes == 10 && nDashLen == 100
167 && std::abs(nDistance * fWidthHelp - 152.0) < fWidthHelp)
169 orLineDash.DotLen = 2007;
170 orLineDash.DashLen = 0;
171 orLineDash.Distance = 152;
172 orLineDash.Style = orLineDash.Style == DashStyle_ROUNDRELATIVE ? DashStyle_ROUND : DashStyle_RECT;
174 else if (nDots == 2 && nDotLen == 100 && nDashes == 1 && nDashLen == nDistance
175 && std::abs(nDistance * fWidthHelp - 203.0) < fWidthHelp)
177 orLineDash.DotLen = 0;
178 orLineDash.DashLen = 203;
179 orLineDash.Distance = 203;
180 orLineDash.Style = orLineDash.Style == DashStyle_ROUNDRELATIVE ? DashStyle_ROUND : DashStyle_RECT;
184 DashStyle lclGetDashStyle( sal_Int32 nToken )
186 OSL_ASSERT((nToken & sal_Int32(0xFFFF0000))==0);
190 case XML_rnd:
return DashStyle_ROUNDRELATIVE;
191 case XML_sq:
return DashStyle_RECTRELATIVE;
192 case XML_flat:
return DashStyle_RECTRELATIVE;
194 return DashStyle_RECTRELATIVE;
197 LineCap lclGetLineCap( sal_Int32 nToken )
199 OSL_ASSERT((nToken & sal_Int32(0xFFFF0000))==0);
202 case XML_rnd:
return LineCap_ROUND;
203 case XML_sq:
return LineCap_SQUARE;
204 case XML_flat:
return LineCap_BUTT;
209 LineJoint lclGetLineJoint( sal_Int32 nToken )
211 OSL_ASSERT((nToken & sal_Int32(0xFFFF0000))==0);
214 case XML_round:
return LineJoint_ROUND;
215 case XML_bevel:
return LineJoint_BEVEL;
216 case XML_miter:
return LineJoint_MITER;
218 return LineJoint_ROUND;
221 const sal_Int32 OOX_ARROWSIZE_SMALL = 0;
222 const sal_Int32 OOX_ARROWSIZE_MEDIUM = 1;
223 const sal_Int32 OOX_ARROWSIZE_LARGE = 2;
225 sal_Int32 lclGetArrowSize( sal_Int32 nToken )
227 OSL_ASSERT((nToken & sal_Int32(0xFFFF0000))==0);
230 case XML_sm:
return OOX_ARROWSIZE_SMALL;
231 case XML_med:
return OOX_ARROWSIZE_MEDIUM;
232 case XML_lg:
return OOX_ARROWSIZE_LARGE;
234 return OOX_ARROWSIZE_MEDIUM;
237 void lclPushMarkerProperties( ShapePropertyMap& rPropMap,
238 const LineArrowProperties& rArrowProps, sal_Int32 nLineWidth,
bool bLineEnd )
242 NamedValue aNamedMarker;
245 sal_Int32 nMarkerWidth = 0;
246 bool bMarkerCenter =
false;
247 sal_Int32 nArrowType = rArrowProps.moArrowType.get( XML_none );
248 OSL_ASSERT((nArrowType & sal_Int32(0xFFFF0000))==0);
252 aBuffer.append(
"msArrowEnd" );
255 aBuffer.append(
"msArrowOpenEnd" );
258 aBuffer.append(
"msArrowStealthEnd" );
261 aBuffer.append(
"msArrowDiamondEnd" );
262 bMarkerCenter =
true;
265 aBuffer.append(
"msArrowOvalEnd" );
266 bMarkerCenter =
true;
270 if( !aBuffer.isEmpty() )
272 bool bIsArrow = nArrowType == XML_arrow;
273 sal_Int32
nLength = lclGetArrowSize( rArrowProps.moArrowLength.get( XML_med ) );
274 sal_Int32 nWidth = lclGetArrowSize( rArrowProps.moArrowWidth.get( XML_med ) );
276 sal_Int32 nNameIndex = nWidth * 3 + nLength + 1;
277 aBuffer.append(
' ' ).append( nNameIndex );
281 aBuffer.append(
' ').append(nLineWidth);
283 OUString aMarkerName = aBuffer.makeStringAndClear();
285 double fArrowLength = 1.0;
288 case OOX_ARROWSIZE_SMALL: fArrowLength = (bIsArrow ? 2.5 : 2.0);
break;
289 case OOX_ARROWSIZE_MEDIUM: fArrowLength = (bIsArrow ? 3.5 : 3.0);
break;
290 case OOX_ARROWSIZE_LARGE: fArrowLength = (bIsArrow ? 5.5 : 5.0);
break;
292 double fArrowWidth = 1.0;
295 case OOX_ARROWSIZE_SMALL: fArrowWidth = (bIsArrow ? 2.5 : 2.0);
break;
296 case OOX_ARROWSIZE_MEDIUM: fArrowWidth = (bIsArrow ? 3.5 : 3.0);
break;
297 case OOX_ARROWSIZE_LARGE: fArrowWidth = (bIsArrow ? 5.5 : 5.0);
break;
300 sal_Int32 nBaseLineWidth = ::std::max< sal_Int32 >( nLineWidth, 70 );
301 nMarkerWidth =
static_cast<sal_Int32
>( fArrowWidth * nBaseLineWidth );
307 if( !rPropMap.hasNamedLineMarkerInTable( aMarkerName ) )
310 auto OOX_ARROW_POINT = [fArrowLength, fArrowWidth](
double x,
double y ) {
return awt::Point( static_cast< sal_Int32 >( fArrowWidth * x ), static_cast< sal_Int32 >( fArrowLength * y ) ); };
314 const double fArrowLineHalfWidth = ::std::max< double >( 100.0 * 0.5 * nLineWidth / nMarkerWidth, 1 );
316 ::std::vector< awt::Point > aPoints;
317 OSL_ASSERT((rArrowProps.moArrowType.get() & sal_Int32(0xFFFF0000))==0);
318 switch( rArrowProps.moArrowType.get() )
321 aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) );
322 aPoints.push_back( OOX_ARROW_POINT( 100, 100 ) );
323 aPoints.push_back( OOX_ARROW_POINT( 0, 100 ) );
324 aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) );
327 aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) );
328 aPoints.push_back( OOX_ARROW_POINT( 100, 100 - fArrowLineHalfWidth * 1.5) );
329 aPoints.push_back( OOX_ARROW_POINT( 100 - fArrowLineHalfWidth * 1.5, 100 ) );
330 aPoints.push_back( OOX_ARROW_POINT( 50.0 + fArrowLineHalfWidth, 5.5 * fArrowLineHalfWidth) );
331 aPoints.push_back( OOX_ARROW_POINT( 50.0 + fArrowLineHalfWidth, 100 ) );
332 aPoints.push_back( OOX_ARROW_POINT( 50.0 - fArrowLineHalfWidth, 100 ) );
333 aPoints.push_back( OOX_ARROW_POINT( 50.0 - fArrowLineHalfWidth, 5.5 * fArrowLineHalfWidth) );
334 aPoints.push_back( OOX_ARROW_POINT( fArrowLineHalfWidth * 1.5, 100 ) );
335 aPoints.push_back( OOX_ARROW_POINT( 0, 100 - fArrowLineHalfWidth * 1.5) );
336 aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) );
339 aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) );
340 aPoints.push_back( OOX_ARROW_POINT( 100, 100 ) );
341 aPoints.push_back( OOX_ARROW_POINT( 50, 60 ) );
342 aPoints.push_back( OOX_ARROW_POINT( 0, 100 ) );
343 aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) );
346 aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) );
347 aPoints.push_back( OOX_ARROW_POINT( 100, 50 ) );
348 aPoints.push_back( OOX_ARROW_POINT( 50, 100 ) );
349 aPoints.push_back( OOX_ARROW_POINT( 0, 50 ) );
350 aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) );
353 aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) );
354 aPoints.push_back( OOX_ARROW_POINT( 75, 7 ) );
355 aPoints.push_back( OOX_ARROW_POINT( 93, 25 ) );
356 aPoints.push_back( OOX_ARROW_POINT( 100, 50 ) );
357 aPoints.push_back( OOX_ARROW_POINT( 93, 75 ) );
358 aPoints.push_back( OOX_ARROW_POINT( 75, 93 ) );
359 aPoints.push_back( OOX_ARROW_POINT( 50, 100 ) );
360 aPoints.push_back( OOX_ARROW_POINT( 25, 93 ) );
361 aPoints.push_back( OOX_ARROW_POINT( 7, 75 ) );
362 aPoints.push_back( OOX_ARROW_POINT( 0, 50 ) );
363 aPoints.push_back( OOX_ARROW_POINT( 7, 25 ) );
364 aPoints.push_back( OOX_ARROW_POINT( 25, 7 ) );
365 aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) );
369 OSL_ENSURE( !aPoints.empty(),
"lclPushMarkerProperties - missing arrow coordinates" );
370 if( !aPoints.empty() )
372 PolyPolygonBezierCoords aMarkerCoords;
375 ::std::vector< PolygonFlags > aFlags( aPoints.size(), PolygonFlags_NORMAL );
378 aNamedMarker.Name = aMarkerName;
379 aNamedMarker.Value <<= aMarkerCoords;
387 aNamedMarker.Name = aMarkerName;
392 if( aNamedMarker.Name.isEmpty() )
452 if( (eLineStyle != drawing::LineStyle_NONE) &&
456 aLineDash.Style = lclGetDashStyle(
moLineCap.
get( XML_flat ) );
463 lclRecoverStandardDashStyles(aLineDash, nLineWidth);
469 if (eLineCap == LineCap_ROUND || (eLineCap == LineCap_SQUARE &&
maCustomDash.empty()))
473 if (aLineDash.DotLen >= 100 || aLineDash.DashLen >= 100)
474 aLineDash.Distance += 99;
475 if (aLineDash.DotLen >= 100)
476 aLineDash.DotLen -= 99;
477 if (aLineDash.DashLen >= 100)
478 aLineDash.DashLen -= 99;
482 eLineStyle = drawing::LineStyle_DASH;
502 lclPushMarkerProperties( rPropMap,
maStartArrow, nLineWidth,
false );
503 lclPushMarkerProperties( rPropMap,
maEndArrow, nLineWidth,
true );
510 return drawing::LineStyle_NONE;
513 return drawing::LineStyle_DASH;
514 return drawing::LineStyle_SOLID;
522 return drawing::LineCap_BUTT;
530 return drawing::LineJoint_NONE;
Provides helper functions for colors, device measurement conversion, graphics, and graphic objects ha...
bool hasTransparency() const
Returns true, if the color is transparent.
sal_Int32 convertEmuToHmm(sal_Int64 nValue)
Converts the passed 64-bit integer value from EMUs to 1/100 mm.
bool setProperty(ShapeProperty ePropId, const Type &rValue)
Sets the specified shape property to the passed value.
OptValue< sal_Int32 > moFillType
OptValue< sal_Int32 > moLineCompound
Preset dash (OOXML token).
Color getBestSolidColor() const
Tries to resolve current settings to a solid color, e.g.
sal_Int32 getLineWidth() const
Calculates the line width attribute from the internal state of the object.
OptValue< sal_Int32 > moPresetDash
Line width (EMUs).
css::drawing::LineJoint getLineJoint() const
Calculates the line joint attribute from the internal state of the object.
OptValue< sal_Int32 > moLineCap
Line compound type (OOXML token).
void assignUsed(const LineArrowProperties &rSourceProps)
Overwrites all members that are explicitly set in rSourceProps.
LineArrowProperties maStartArrow
LineArrowProperties maEndArrow
Start line arrow style.
OptValue< sal_Int32 > moArrowWidth
OptValue< sal_Int32 > moLineJoint
Line cap (OOXML token).
css::drawing::LineStyle getLineStyle() const
Calculates the line style attribute from the internal state of the object.
void pushToPropMap(ShapePropertyMap &rPropMap, const GraphicHelper &rGraphicHelper,::Color nPhClr=API_RGB_TRANSPARENT) const
Writes the properties to the passed property map.
::Color getColor(const GraphicHelper &rGraphicHelper,::Color nPhClr=API_RGB_TRANSPARENT) const
Returns the final RGB color value.
bool isUsed() const
Returns true, if the color is initialized.
void assignIfUsed(const OptValue &rValue)
::std::vector< DashStop > DashStopVector
OptValue< sal_Int32 > moArrowLength
std::unique_ptr< char[]> aBuffer
FillProperties maLineFill
End line arrow style.
OptValue< sal_Int32 > moArrowType
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
css::drawing::LineCap getLineCap() const
Calculates the line cap attribute from the internal state of the object.
sal_Int16 getTransparency() const
Returns the transparency of the color (0 = opaque, 100 = full transparent).
void assignUsed(const FillProperties &rSourceProps)
Properties for bitmap fills.
Explicit line dash or name of a line dash stored in a global container.
Explicit line start marker or name of a line marker stored in a global container. ...
void assignUsed(const LineProperties &rSourceProps)
Line joint type (OOXML token).
OptValue< sal_Int32 > moLineWidth
User-defined line dash style.
DashStopVector maCustomDash
Line fill (solid, gradient, ...).
Explicit line end marker or name of a line marker stored in a global container.