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>
36#include <oox/token/properties.hxx>
49void lclSetDashData( LineDash& orLineDash, sal_Int16 nDots, sal_Int32 nDotLen,
50 sal_Int16 nDashes, sal_Int32 nDashLen, sal_Int32 nDistance )
52 orLineDash.Dots = nDots;
53 orLineDash.DotLen = nDotLen;
54 orLineDash.Dashes = nDashes;
55 orLineDash.DashLen = nDashLen;
56 orLineDash.Distance = nDistance;
61void lclConvertPresetDash(LineDash& orLineDash, sal_Int32 nPresetDash)
65 case XML_dot: lclSetDashData( orLineDash, 1, 1, 0, 0, 3 );
break;
66 case XML_dash: lclSetDashData( orLineDash, 1, 4, 0, 0, 3 );
break;
67 case XML_dashDot: lclSetDashData( orLineDash, 1, 4, 1, 1, 3 );
break;
69 case XML_lgDash: lclSetDashData( orLineDash, 1, 8, 0, 0, 3 );
break;
70 case XML_lgDashDot: lclSetDashData( orLineDash, 1, 8, 1, 1, 3 );
break;
71 case XML_lgDashDotDot: lclSetDashData( orLineDash, 1, 8, 2, 1, 3 );
break;
73 case XML_sysDot: lclSetDashData( orLineDash, 1, 1, 0, 0, 1 );
break;
74 case XML_sysDash: lclSetDashData( orLineDash, 1, 3, 0, 0, 1 );
break;
75 case XML_sysDashDot: lclSetDashData( orLineDash, 1, 3, 1, 1, 1 );
break;
76 case XML_sysDashDotDot: lclSetDashData( orLineDash, 1, 3, 2, 1, 1 );
break;
79 OSL_FAIL(
"lclConvertPresetDash - unsupported preset dash" );
80 lclSetDashData( orLineDash, 1, 4, 0, 0, 3 );
82 orLineDash.DotLen *= 100;
83 orLineDash.DashLen *= 100;
84 orLineDash.Distance *= 100;
94 OSL_ASSERT(!rCustomDash.empty());
96 orLineDash.Distance = rCustomDash[0].second;
98 orLineDash.DotLen = rCustomDash[0].first;
100 for(
const auto& rIt : rCustomDash)
102 if (rIt.first != orLineDash.DotLen)
107 orLineDash.Dashes = rCustomDash.size() - orLineDash.Dots;
108 if (orLineDash.Dashes > 0)
109 orLineDash.DashLen = rCustomDash[orLineDash.Dots].first;
111 orLineDash.DashLen = 0;
114 orLineDash.DotLen = orLineDash.DotLen / 1000;
115 orLineDash.DashLen = orLineDash.DashLen / 1000;
116 orLineDash.Distance = orLineDash.Distance / 1000;
124void lclRecoverStandardDashStyles(LineDash& orLineDash, sal_Int32 nLineWidth)
126 sal_uInt16 nDots = orLineDash.Dots;
127 sal_uInt16 nDashes = orLineDash.Dashes;
128 sal_uInt32 nDotLen = orLineDash.DotLen;
129 sal_uInt32 nDashLen = orLineDash.DashLen;
130 sal_uInt32 nDistance = orLineDash.Distance;
135 if (nDots == 3 && nDotLen == 197 &&nDashes == 3 && nDashLen == 100 && nDistance == 100)
137 orLineDash.DashLen = 0;
139 else if (nDots == 1 && nDotLen == 100 && nDashes == 0 && nDistance == 50)
141 orLineDash.DotLen = 0;
143 else if (nDots == 2 && nDashes == 0 && nDotLen == nDistance
144 && std::abs(nDistance * fWidthHelp - 51.0) < fWidthHelp)
147 orLineDash.DotLen = 51;
148 orLineDash.Dashes = 1;
149 orLineDash.DashLen = 51;
150 orLineDash.Distance = 51;
151 orLineDash.Style = orLineDash.Style == DashStyle_ROUNDRELATIVE ? DashStyle_ROUND : DashStyle_RECT;
153 else if (nDots == 2 && nDashes == 3 && std::abs(nDotLen * fWidthHelp - 51.0) < fWidthHelp
154 && std::abs(nDashLen * fWidthHelp - 254.0) < fWidthHelp
155 && std::abs(nDistance * fWidthHelp - 127.0) < fWidthHelp)
157 orLineDash.DotLen = 51;
158 orLineDash.DashLen = 254;
159 orLineDash.Distance = 127;
160 orLineDash.Style = orLineDash.Style == DashStyle_ROUNDRELATIVE ? DashStyle_ROUND : DashStyle_RECT;
162 else if (nDots == 1 && nDotLen == 100 && nDashes == 0
163 && std::abs(nDistance * fWidthHelp - 457.0) < fWidthHelp)
165 orLineDash.DotLen = 0;
166 orLineDash.Distance = 457;
167 orLineDash.Style = orLineDash.Style == DashStyle_ROUNDRELATIVE ? DashStyle_ROUND : DashStyle_RECT;
169 else if (nDots == 1 && nDashes == 10 && nDashLen == 100
170 && std::abs(nDistance * fWidthHelp - 152.0) < fWidthHelp)
172 orLineDash.DotLen = 2007;
173 orLineDash.DashLen = 0;
174 orLineDash.Distance = 152;
175 orLineDash.Style = orLineDash.Style == DashStyle_ROUNDRELATIVE ? DashStyle_ROUND : DashStyle_RECT;
177 else if (nDots == 2 && nDotLen == 100 && nDashes == 1 && nDashLen == nDistance
178 && std::abs(nDistance * fWidthHelp - 203.0) < fWidthHelp)
180 orLineDash.DotLen = 0;
181 orLineDash.DashLen = 203;
182 orLineDash.Distance = 203;
183 orLineDash.Style = orLineDash.Style == DashStyle_ROUNDRELATIVE ? DashStyle_ROUND : DashStyle_RECT;
187DashStyle lclGetDashStyle( sal_Int32 nToken )
189 OSL_ASSERT((nToken & sal_Int32(0xFFFF0000))==0);
193 case XML_rnd:
return DashStyle_ROUNDRELATIVE;
194 case XML_sq:
return DashStyle_RECTRELATIVE;
195 case XML_flat:
return DashStyle_RECTRELATIVE;
197 return DashStyle_RECTRELATIVE;
200LineCap lclGetLineCap( sal_Int32 nToken )
202 OSL_ASSERT((nToken & sal_Int32(0xFFFF0000))==0);
205 case XML_rnd:
return LineCap_ROUND;
206 case XML_sq:
return LineCap_SQUARE;
207 case XML_flat:
return LineCap_BUTT;
212LineJoint lclGetLineJoint( sal_Int32 nToken )
214 OSL_ASSERT((nToken & sal_Int32(0xFFFF0000))==0);
217 case XML_round:
return LineJoint_ROUND;
218 case XML_bevel:
return LineJoint_BEVEL;
219 case XML_miter:
return LineJoint_MITER;
221 return LineJoint_ROUND;
224const sal_Int32 OOX_ARROWSIZE_SMALL = 0;
225const sal_Int32 OOX_ARROWSIZE_MEDIUM = 1;
226const sal_Int32 OOX_ARROWSIZE_LARGE = 2;
228sal_Int32 lclGetArrowSize( sal_Int32 nToken )
230 OSL_ASSERT((nToken & sal_Int32(0xFFFF0000))==0);
233 case XML_sm:
return OOX_ARROWSIZE_SMALL;
234 case XML_med:
return OOX_ARROWSIZE_MEDIUM;
235 case XML_lg:
return OOX_ARROWSIZE_LARGE;
237 return OOX_ARROWSIZE_MEDIUM;
240void lclPushMarkerProperties( ShapePropertyMap& rPropMap,
241 const LineArrowProperties& rArrowProps, sal_Int32 nLineWidth,
bool bLineEnd )
245 NamedValue aNamedMarker;
248 sal_Int32 nMarkerWidth = 0;
249 bool bMarkerCenter =
false;
250 sal_Int32 nArrowType = rArrowProps.moArrowType.value_or( XML_none );
251 OSL_ASSERT((nArrowType & sal_Int32(0xFFFF0000))==0);
255 aBuffer.append(
"msArrowEnd" );
258 aBuffer.append(
"msArrowOpenEnd" );
261 aBuffer.append(
"msArrowStealthEnd" );
264 aBuffer.append(
"msArrowDiamondEnd" );
265 bMarkerCenter =
true;
268 aBuffer.append(
"msArrowOvalEnd" );
269 bMarkerCenter =
true;
275 bool bIsArrow = nArrowType == XML_arrow;
276 sal_Int32
nLength = lclGetArrowSize( rArrowProps.moArrowLength.value_or( XML_med ) );
277 sal_Int32 nWidth = lclGetArrowSize( rArrowProps.moArrowWidth.value_or( XML_med ) );
279 sal_Int32 nNameIndex = nWidth * 3 +
nLength + 1;
280 aBuffer.append(
" " + OUString::number( nNameIndex ));
284 aBuffer.append(
" " + OUString::number(nLineWidth));
286 OUString aMarkerName =
aBuffer.makeStringAndClear();
288 double fArrowLength = 1.0;
291 case OOX_ARROWSIZE_SMALL: fArrowLength = (bIsArrow ? 2.5 : 2.0);
break;
292 case OOX_ARROWSIZE_MEDIUM: fArrowLength = (bIsArrow ? 3.5 : 3.0);
break;
293 case OOX_ARROWSIZE_LARGE: fArrowLength = (bIsArrow ? 5.5 : 5.0);
break;
295 double fArrowWidth = 1.0;
298 case OOX_ARROWSIZE_SMALL: fArrowWidth = (bIsArrow ? 2.5 : 2.0);
break;
299 case OOX_ARROWSIZE_MEDIUM: fArrowWidth = (bIsArrow ? 3.5 : 3.0);
break;
300 case OOX_ARROWSIZE_LARGE: fArrowWidth = (bIsArrow ? 5.5 : 5.0);
break;
303 sal_Int32 nBaseLineWidth = ::std::max< sal_Int32 >( nLineWidth, 70 );
304 nMarkerWidth =
static_cast<sal_Int32
>( fArrowWidth * nBaseLineWidth );
310 if( !rPropMap.hasNamedLineMarkerInTable( aMarkerName ) )
313 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 ) ); };
317 const double fArrowLineHalfWidth = ::std::max< double >( 100.0 * 0.5 * nLineWidth / nMarkerWidth, 1 );
319 ::std::vector< awt::Point > aPoints;
320 OSL_ASSERT((rArrowProps.moArrowType.value() & sal_Int32(0xFFFF0000))==0);
321 switch( rArrowProps.moArrowType.value() )
324 aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) );
325 aPoints.push_back( OOX_ARROW_POINT( 100, 100 ) );
326 aPoints.push_back( OOX_ARROW_POINT( 0, 100 ) );
327 aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) );
330 aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) );
331 aPoints.push_back( OOX_ARROW_POINT( 100, 100 - fArrowLineHalfWidth * 1.5) );
332 aPoints.push_back( OOX_ARROW_POINT( 100 - fArrowLineHalfWidth * 1.5, 100 ) );
333 aPoints.push_back( OOX_ARROW_POINT( 50.0 + fArrowLineHalfWidth, 5.5 * fArrowLineHalfWidth) );
334 aPoints.push_back( OOX_ARROW_POINT( 50.0 + fArrowLineHalfWidth, 100 ) );
335 aPoints.push_back( OOX_ARROW_POINT( 50.0 - fArrowLineHalfWidth, 100 ) );
336 aPoints.push_back( OOX_ARROW_POINT( 50.0 - fArrowLineHalfWidth, 5.5 * fArrowLineHalfWidth) );
337 aPoints.push_back( OOX_ARROW_POINT( fArrowLineHalfWidth * 1.5, 100 ) );
338 aPoints.push_back( OOX_ARROW_POINT( 0, 100 - fArrowLineHalfWidth * 1.5) );
339 aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) );
342 aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) );
343 aPoints.push_back( OOX_ARROW_POINT( 100, 100 ) );
344 aPoints.push_back( OOX_ARROW_POINT( 50, 60 ) );
345 aPoints.push_back( OOX_ARROW_POINT( 0, 100 ) );
346 aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) );
349 aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) );
350 aPoints.push_back( OOX_ARROW_POINT( 100, 50 ) );
351 aPoints.push_back( OOX_ARROW_POINT( 50, 100 ) );
352 aPoints.push_back( OOX_ARROW_POINT( 0, 50 ) );
353 aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) );
356 aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) );
357 aPoints.push_back( OOX_ARROW_POINT( 75, 7 ) );
358 aPoints.push_back( OOX_ARROW_POINT( 93, 25 ) );
359 aPoints.push_back( OOX_ARROW_POINT( 100, 50 ) );
360 aPoints.push_back( OOX_ARROW_POINT( 93, 75 ) );
361 aPoints.push_back( OOX_ARROW_POINT( 75, 93 ) );
362 aPoints.push_back( OOX_ARROW_POINT( 50, 100 ) );
363 aPoints.push_back( OOX_ARROW_POINT( 25, 93 ) );
364 aPoints.push_back( OOX_ARROW_POINT( 7, 75 ) );
365 aPoints.push_back( OOX_ARROW_POINT( 0, 50 ) );
366 aPoints.push_back( OOX_ARROW_POINT( 7, 25 ) );
367 aPoints.push_back( OOX_ARROW_POINT( 25, 7 ) );
368 aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) );
372 OSL_ENSURE( !aPoints.empty(),
"lclPushMarkerProperties - missing arrow coordinates" );
373 if( !aPoints.empty() )
375 PolyPolygonBezierCoords aMarkerCoords;
378 ::std::vector< PolygonFlags > aFlags( aPoints.size(), PolygonFlags_NORMAL );
381 aNamedMarker.Name = aMarkerName;
382 aNamedMarker.Value <<= aMarkerCoords;
390 aNamedMarker.Name = aMarkerName;
395 if( aNamedMarker.Name.isEmpty() )
443 drawing::LineStyle eLineStyle = (
maLineFill.
moFillType.value() == XML_noFill) ? drawing::LineStyle_NONE : drawing::LineStyle_SOLID;
455 if( (eLineStyle != drawing::LineStyle_NONE) &&
459 aLineDash.Style = lclGetDashStyle(
moLineCap.value_or( XML_flat ) );
462 lclConvertPresetDash(aLineDash,
moPresetDash.value_or(XML_dash));
466 lclRecoverStandardDashStyles(aLineDash,
nLineWidth);
472 if (eLineCap == LineCap_ROUND || (eLineCap == LineCap_SQUARE &&
maCustomDash.empty()))
476 if (aLineDash.DotLen >= 100 || aLineDash.DashLen >= 100)
477 aLineDash.Distance += 99;
478 if (aLineDash.DotLen >= 100)
479 aLineDash.DotLen -= 99;
480 if (aLineDash.DashLen >= 100)
481 aLineDash.DashLen -= 99;
485 eLineStyle = drawing::LineStyle_DASH;
506 if (aColor == nPhClr)
522 sal_Int16 nShade = o3tl::narrowing<sal_Int16>(-aLineColor.
getTintOrShade());
538 return drawing::LineStyle_NONE;
541 return drawing::LineStyle_DASH;
542 return drawing::LineStyle_SOLID;
548 return lclGetLineCap(
moLineCap.value() );
550 return drawing::LineCap_BUTT;
558 return drawing::LineJoint_NONE;
void addTransformation(Transformation const &rTransform)
void setType(ThemeColorType eType)
Provides helper functions for colors, device measurement conversion, graphics, and graphic objects ha...
sal_Int16 getTintOrShade() const
sal_Int16 getLumMod() const
sal_Int16 getTransparency() const
Returns the transparency of the color (0 = opaque, 100 = full transparent).
sal_Int16 getLumOff() const
bool isUsed() const
Returns true, if the color is initialized.
bool hasTransparency() const
Returns true, if the color is transparent.
sal_Int16 getSchemeColorIndex() const
::Color getColor(const GraphicHelper &rGraphicHelper, ::Color nPhClr=API_RGB_TRANSPARENT) const
Returns the final RGB color value.
bool setProperty(ShapeProperty ePropId, const Type &rValue)
Sets the specified shape property to the passed value.
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
uno::Reference< util::XThemeColor > createXThemeColor(model::ThemeColor const &rThemeColor)
constexpr ThemeColorType convertToThemeColorType(sal_Int32 nIndex)
@ LineStart
Explicit line start marker or name of a line marker stored in a global container.
@ LineEnd
Explicit line end marker or name of a line marker stored in a global container.
@ LineDash
Explicit line dash or name of a line dash stored in a global container.
sal_Int32 convertEmuToHmm(sal_Int64 nValue)
Converts the passed 64-bit integer value from EMUs to 1/100 mm.
void assignIfUsed(std::optional< Type > &rDestValue, const std::optional< Type > &rSourceValue)
void assignUsed(const FillProperties &rSourceProps)
Properties for bitmap fills.
Color getBestSolidColor() const
Tries to resolve current settings to a solid color, e.g.
std::optional< sal_Int32 > moFillType
std::optional< sal_Int32 > moArrowLength
std::optional< sal_Int32 > moArrowType
void assignUsed(const LineArrowProperties &rSourceProps)
Overwrites all members that are explicitly set in rSourceProps.
std::optional< sal_Int32 > moArrowWidth
void assignUsed(const LineProperties &rSourceProps)
Line joint type (OOXML token).
FillProperties maLineFill
End line arrow style.
std::optional< sal_Int32 > moLineCompound
Preset dash (OOXML token).
sal_Int32 getLineWidth() const
Calculates the line width attribute from the internal state of the object.
std::optional< sal_Int32 > moLineCap
Line compound type (OOXML token).
std::optional< sal_Int32 > moLineWidth
User-defined line dash style.
LineArrowProperties maStartArrow
void pushToPropMap(ShapePropertyMap &rPropMap, const GraphicHelper &rGraphicHelper, ::Color nPhClr=API_RGB_TRANSPARENT, sal_Int16 nPhClrTheme=-1) const
Writes the properties to the passed property map.
css::drawing::LineStyle getLineStyle() const
Calculates the line style attribute from the internal state of the object.
::std::vector< DashStop > DashStopVector
std::optional< sal_Int32 > moLineJoint
Line cap (OOXML token).
LineArrowProperties maEndArrow
Start line arrow style.
std::optional< sal_Int32 > moPresetDash
Line width (EMUs).
DashStopVector maCustomDash
Line fill (solid, gradient, ...).
css::drawing::LineCap getLineCap() const
Calculates the line cap attribute from the internal state of the object.
css::drawing::LineJoint getLineJoint() const
Calculates the line joint attribute from the internal state of the object.
std::unique_ptr< char[]> aBuffer