diff options
author | Regina Henschel <rb.henschel@t-online.de> | 2019-09-01 19:26:40 +0200 |
---|---|---|
committer | Regina Henschel <rb.henschel@t-online.de> | 2019-09-05 12:36:56 +0200 |
commit | 57c9bdab377a00649299d1a4c9ed2f9e5e03b84e (patch) | |
tree | 680bb89ff0c2d11745702e1fdca149fe0ea3f20f /filter | |
parent | 8590de9d8c3f155f23155d7500fd805c0e21a26b (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')
-rw-r--r-- | filter/source/msfilter/escherex.cxx | 102 | ||||
-rw-r--r-- | filter/source/msfilter/msdffimp.cxx | 88 |
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 ) ) ) ); |