summaryrefslogtreecommitdiff
path: root/filter/source/msfilter
diff options
context:
space:
mode:
authorRegina Henschel <rb.henschel@t-online.de>2019-09-01 19:26:40 +0200
committerRegina Henschel <rb.henschel@t-online.de>2019-09-05 12:36:56 +0200
commit57c9bdab377a00649299d1a4c9ed2f9e5e03b84e (patch)
tree680bb89ff0c2d11745702e1fdca149fe0ea3f20f /filter/source/msfilter
parent8590de9d8c3f155f23155d7500fd805c0e21a26b (diff)
tdf#127166, tdf#123903 improve import/export of line styles
I have added import and export of prstDash line styles, for OOXML and for binary MS Office formats. This includes: Corrected Dot <--> Dash confusion, corrected some wrong defaults, added support for hairlines tdf#127267, take care of treating length 0 as 100%. tdf#108064 has introduced some mapping from our standard line styles to OOXML prstDash. I have removed that and implemented to export our styles as custDash and recover them back on import. That way the dashing looks initially the same in MS Office. I have removed the now wrong test. Binary MS Office formats have no custom dash styles AFAIK, therefore I have not changed the export of our styles there, but only added support for prstDash styles. Change-Id: Ia8cc8f90df6fdbe42adfc0236cc52becc670b333 Reviewed-on: https://gerrit.libreoffice.org/78372 Tested-by: Jenkins Reviewed-by: Regina Henschel <rb.henschel@t-online.de>
Diffstat (limited to 'filter/source/msfilter')
-rw-r--r--filter/source/msfilter/escherex.cxx102
-rw-r--r--filter/source/msfilter/msdffimp.cxx88
2 files changed, 137 insertions, 53 deletions
diff --git a/filter/source/msfilter/escherex.cxx b/filter/source/msfilter/escherex.cxx
index 1324a23979cd..69bb2b92f257 100644
--- a/filter/source/msfilter/escherex.cxx
+++ b/filter/source/msfilter/escherex.cxx
@@ -1028,6 +1028,11 @@ void EscherPropertyContainer::CreateLineProperties(
}
}
+ sal_uInt32 nLineWidth = ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "LineWidth" ) )
+ ? *o3tl::doAccess<sal_uInt32>(aAny) : 0;
+ if ( nLineWidth > 1 )
+ AddOpt( ESCHER_Prop_lineWidth, nLineWidth * 360 ); // 100TH MM -> PT , 1PT = 12700 EMU
+
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "LineStyle" ) )
{
drawing::LineStyle eLS;
@@ -1045,7 +1050,6 @@ void EscherPropertyContainer::CreateLineProperties(
{
ESCHER_LineDashing eDash = ESCHER_LineSolid;
auto pLineDash = o3tl::doAccess<drawing::LineDash>(aAny);
- sal_Int32 nDistance = pLineDash->Distance << 1;
switch ( pLineDash->Style )
{
case drawing::DashStyle_ROUND :
@@ -1054,35 +1058,86 @@ void EscherPropertyContainer::CreateLineProperties(
break;
default : break;
}
- if ( ((!(pLineDash->Dots )) || (!(pLineDash->Dashes )) ) || ( pLineDash->DotLen == pLineDash->DashLen ) )
+ // Try to detect exact prstDash styles. Use a similar method as in oox export.
+ // Map it to a roughly fitting prstDash in outher cases.
+ bool bIsConverted = false;
+ bool bIsRelative = pLineDash->Style == drawing::DashStyle_RECTRELATIVE
+ || pLineDash->Style == drawing::DashStyle_ROUNDRELATIVE;
+ sal_Int16 nDashes = pLineDash->Dashes;
+ sal_Int16 nDots = pLineDash->Dots;
+ sal_Int32 nDashLen = pLineDash->DashLen;
+ sal_Int32 nDotLen = pLineDash->DotLen;
+ sal_Int32 nDistance = pLineDash->Distance;
+
+ // Caution! The names are misleading. "dot" is always the first dash and "dash"
+ // the second one, regardless of the actual length. All prstDash
+ // definitions start with the longer dash and have exact one longer dash.
+ // Preset line style definitions for binary format are the same as for OOXML.
+ if (bIsRelative && nDots == 1)
{
- sal_Int32 nLen = pLineDash->DotLen;
- if ( pLineDash->Dashes )
- nLen = pLineDash->DashLen;
-
- if ( nLen >= nDistance )
+ // I'm not sure that LO always uses 100%, because in case of absolute values, LO
+ // sets length to 0 but treats it as 100%, if the attribute is missing in ODF.
+ // So to be sure set 100% explicitly in case of relative too.
+ if (nDashes > 0 && nDashLen == 0)
+ nDashLen = 100;
+ if (nDotLen == 0)
+ nDotLen = 100;
+ bIsConverted = true;
+ if (nDotLen == 100 && nDashes == 0 && nDashLen == 0 && nDistance == 300)
+ eDash = ESCHER_LineDotGEL;
+ else if (nDotLen == 400 && nDashes == 0 && nDashLen == 0 && nDistance == 300)
+ eDash = ESCHER_LineDashGEL;
+ else if (nDotLen == 400 && nDashes == 1 && nDashLen == 100 && nDistance == 300)
+ eDash = ESCHER_LineDashDotGEL;
+ else if (nDotLen == 800 && nDashes == 0 && nDashLen == 0 && nDistance == 300)
eDash = ESCHER_LineLongDashGEL;
- else if ( pLineDash->Dots )
+ else if (nDotLen == 800 && nDashes == 1 && nDashLen == 100 && nDistance == 300)
+ eDash = ESCHER_LineLongDashDotGEL;
+ else if (nDotLen == 800 && nDashes == 2 && nDashLen == 100 && nDistance == 300)
+ eDash = ESCHER_LineLongDashDotDotGEL;
+ else if (nDotLen == 100 && nDashes == 0 && nDashLen == 0 && nDistance == 100)
eDash = ESCHER_LineDotSys;
+ else if (nDotLen == 300 && nDashes == 0 && nDashLen == 0 && nDistance == 100)
+ eDash = ESCHER_LineDashSys;
+ else if (nDotLen == 300 && nDashes == 1 && nDashLen == 100 && nDistance == 100)
+ eDash = ESCHER_LineDashDotSys;
+ else if (nDotLen == 300 && nDashes == 2 && nDashLen == 100 && nDistance == 100)
+ eDash = ESCHER_LineDashDotDotSys;
else
- eDash = ESCHER_LineDashGEL;
+ bIsConverted = false;
}
- else // X Y
- {
- if ( pLineDash->Dots != pLineDash->Dashes )
+
+ if (!bIsConverted)
+ { // Map the style roughly to preset line styles.
+ if (((!(pLineDash->Dots)) || (!(pLineDash->Dashes)))
+ || (pLineDash->DotLen == pLineDash->DashLen))
{
- if ( ( pLineDash->DashLen > nDistance ) || ( pLineDash->DotLen > nDistance ) )
- eDash = ESCHER_LineLongDashDotDotGEL;
+ sal_Int32 nLen = pLineDash->DotLen;
+ if (pLineDash->Dashes)
+ nLen = pLineDash->DashLen;
+ if (nLen >= nDistance)
+ eDash = ESCHER_LineLongDashGEL;
+ else if (pLineDash->Dots)
+ eDash = ESCHER_LineDotSys;
else
- eDash = ESCHER_LineDashDotDotSys;
+ eDash = ESCHER_LineDashGEL;
}
- else // X Y Y
+ else // X Y
{
- if ( ( pLineDash->DashLen > nDistance ) || ( pLineDash->DotLen > nDistance ) )
- eDash = ESCHER_LineLongDashDotGEL;
- else
- eDash = ESCHER_LineDashDotGEL;
-
+ if (pLineDash->Dots != pLineDash->Dashes)
+ {
+ if ((pLineDash->DashLen > nDistance) || (pLineDash->DotLen > nDistance))
+ eDash = ESCHER_LineLongDashDotDotGEL;
+ else
+ eDash = ESCHER_LineDashDotDotSys;
+ }
+ else // X Y Y
+ {
+ if ((pLineDash->DashLen > nDistance) || (pLineDash->DotLen > nDistance))
+ eDash = ESCHER_LineLongDashDotGEL;
+ else
+ eDash = ESCHER_LineDashDotGEL;
+ }
}
}
AddOpt( ESCHER_Prop_lineDashing, eDash );
@@ -1105,11 +1160,6 @@ void EscherPropertyContainer::CreateLineProperties(
}
}
- sal_uInt32 nLineSize = ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "LineWidth" ) )
- ? *o3tl::doAccess<sal_uInt32>(aAny) : 0;
- if ( nLineSize > 1 )
- AddOpt( ESCHER_Prop_lineWidth, nLineSize * 360 ); // 100TH MM -> PT , 1PT = 12700 EMU
-
ESCHER_LineJoin eLineJoin = ESCHER_LineJoinMiter;
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "LineJoint", true ) )
{
diff --git a/filter/source/msfilter/msdffimp.cxx b/filter/source/msfilter/msdffimp.cxx
index 17be716f50c8..3dc792e7674f 100644
--- a/filter/source/msfilter/msdffimp.cxx
+++ b/filter/source/msfilter/msdffimp.cxx
@@ -934,7 +934,7 @@ void DffPropertyReader::ApplyLineAttributes( SfxItemSet& rSet, const MSO_SPT eSh
sal_Int32 nLineWidth = static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_lineWidth, 9525 ));
// support LineCap
- const MSO_LineCap eLineCap(static_cast<MSO_LineCap>(GetPropertyValue(DFF_Prop_lineEndCapStyle, mso_lineEndCapSquare)));
+ const MSO_LineCap eLineCap(static_cast<MSO_LineCap>(GetPropertyValue(DFF_Prop_lineEndCapStyle, mso_lineEndCapFlat)));
switch(eLineCap)
{
@@ -961,63 +961,97 @@ void DffPropertyReader::ApplyLineAttributes( SfxItemSet& rSet, const MSO_SPT eSh
rSet.Put(XLineStyleItem( drawing::LineStyle_SOLID ) );
else
{
- sal_uInt16 nDots = 1;
- sal_uInt32 nDotLen = nLineWidth / 360;
+ // Despite of naming "dot" and "dash", that are all dashes and a "dot" can be longer
+ // than a "dash". The naming indicates the order, "dot" is always the first dash and
+ // "dash" is always the second dash. MS Office always starts with the longer dash, so
+ // set it here accordingly.
+ // The preset from binary is essentially the same as from OOXML. So here the same
+ // setting is used as in oox import. The comment corrensponds to
+ // "dots, dotLen, dashes, dashLen, distance" there.
+ // MS Office uses always relative length, so no need to consider nLineWidth
+ // here. Values are of kind 300 for 300% in css::drawing::DashStyle, for example.
+
+ sal_uInt16 nDots = 1; // in all cases, "solid" is treated above
+ // initalize, will be changened if necessary
+ sal_uInt32 nDotLen = 300;
sal_uInt16 nDashes = 0;
- const bool bHugeWidth = static_cast<sal_uInt32>(nLineWidth) >= SAL_MAX_UINT32/8U; //then rougher approx is fine
- sal_uInt32 nDashLen = bHugeWidth ? (nDotLen * 8U) : ((8U * nLineWidth) / 360);
- sal_uInt32 nDistance = bHugeWidth ? (nDotLen * 3U) : ((3U * nLineWidth) / 360);
-
+ sal_uInt32 nDashLen = 0;
+ sal_uInt32 nDistance = 300;
switch ( eLineDashing )
{
default:
- case mso_lineDotSys :
+ case mso_lineDotSys : // 1 1 0 0 1
{
- nDots = 1;
- nDashes = 0;
- nDistance = nDotLen;
+ nDotLen =100;
+ nDistance = 100;
}
break;
- case mso_lineDashGEL :
+ case mso_lineDashGEL : // 1 4 0 0 3
{
- nDots = 0;
- nDashes = 1;
- nDashLen = bHugeWidth ? (nDotLen * 4U) : ((4U * nLineWidth) / 360);
+ nDotLen = 400;
}
break;
- case mso_lineDashDotGEL :
+ case mso_lineDashDotGEL : // 1 4 1 1 3
{
- nDots = 1;
+ nDotLen = 400;
nDashes = 1;
- nDashLen = bHugeWidth ? (nDotLen * 4U) : ((4U * nLineWidth) / 360);
+ nDashLen = 100;
}
break;
- case mso_lineLongDashGEL :
+ case mso_lineLongDashGEL : // 1 8 0 0 3
{
- nDots = 0;
- nDashes = 1;
+ nDotLen = 800;
}
break;
- case mso_lineLongDashDotGEL :
+ case mso_lineLongDashDotGEL : // 1 8 1 1 3
{
- nDots = 1;
+ nDotLen = 800;
nDashes = 1;
+ nDashLen = 100;
+ }
+ break;
+
+ case mso_lineLongDashDotDotGEL: // 1 8 2 1 3
+ {
+ nDotLen = 800;
+ nDashes = 2;
+ nDashLen = 100;
+ }
+ break;
+
+ case mso_lineDotGEL: // 1 1 0 0 3
+ {
+ nDotLen = 100;
+ }
+ break;
+
+ case mso_lineDashSys: // 1 3 0 0 1
+ {
+ nDistance = 100;
}
break;
- case mso_lineLongDashDotDotGEL:
+ case mso_lineDashDotSys: // 1 3 1 1 1
{
- nDots = 2;
nDashes = 1;
+ nDashLen = 100;
+ nDistance = 100;
}
break;
- }
- rSet.Put( XLineDashItem( OUString(), XDash( css::drawing::DashStyle_RECT, nDots, nDotLen, nDashes, nDashLen, nDistance ) ) );
+ case mso_lineDashDotDotSys: // 1 3 2 1 1
+ {
+ nDashes = 2;
+ nDashLen = 100;
+ nDistance = 100;
+ }
+ break;
+ }
+ rSet.Put( XLineDashItem( OUString(), XDash( css::drawing::DashStyle_RECTRELATIVE, nDots, nDotLen, nDashes, nDashLen, nDistance ) ) );
rSet.Put( XLineStyleItem( drawing::LineStyle_DASH ) );
}
rSet.Put( XLineColorItem( OUString(), rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_lineColor, 0 ) ) ) );