diff options
author | Bartosz Kosiorek <gang65@poczta.onet.pl> | 2022-04-20 19:44:05 +0200 |
---|---|---|
committer | Xisco Fauli <xiscofauli@libreoffice.org> | 2022-04-22 16:13:54 +0200 |
commit | 547ac0aa23a25f03a17014cb474eedc1fd88017f (patch) | |
tree | 50792210e32f51d12fa558830c53f8b8d2040e7b /drawinglayer | |
parent | af0955d600cd3d54d26a87b9ff30e3c402a226dd (diff) |
tdf#55058 tdf#143875 EMF+ Fix display of dashed lines and line joints
With previous implementation, empty spaces between dashes
were too long.
Additionally line joints were not working correctly, after
EMF+ reworking: tdf#111486
This commit fixes all these issues and additionally it is
covering it with tests.
Change-Id: I9404e566d2d7d3405ab817268ad9b1f538c200eb
Change-Id: I523f92a928ab592ff175d0d01c1ad1a3bc22e324
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133207
Tested-by: Jenkins
Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
(cherry picked from commit 80c856336668e35837667323957fa3ad4172f3c0)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133152
Diffstat (limited to 'drawinglayer')
-rw-r--r-- | drawinglayer/source/tools/emfpcustomlinecap.cxx | 9 | ||||
-rw-r--r-- | drawinglayer/source/tools/emfpcustomlinecap.hxx | 2 | ||||
-rw-r--r-- | drawinglayer/source/tools/emfphelperdata.cxx | 62 | ||||
-rw-r--r-- | drawinglayer/source/tools/emfppen.cxx | 70 | ||||
-rw-r--r-- | drawinglayer/source/tools/emfppen.hxx | 5 | ||||
-rw-r--r-- | drawinglayer/source/tools/primitive2dxmldump.cxx | 32 |
6 files changed, 88 insertions, 92 deletions
diff --git a/drawinglayer/source/tools/emfpcustomlinecap.cxx b/drawinglayer/source/tools/emfpcustomlinecap.cxx index e24cbcc32cb1..49cc912ed33c 100644 --- a/drawinglayer/source/tools/emfpcustomlinecap.cxx +++ b/drawinglayer/source/tools/emfpcustomlinecap.cxx @@ -43,15 +43,6 @@ namespace emfplushelper { } - void EMFPCustomLineCap::SetAttributes(rendering::StrokeAttributes& aAttributes) - { - aAttributes.StartCapType = EMFPPen::lcl_convertStrokeCap(strokeStartCap); - aAttributes.EndCapType = EMFPPen::lcl_convertStrokeCap(strokeEndCap); - aAttributes.JoinType = EMFPPen::lcl_convertLineJoinType(strokeJoin); - - aAttributes.MiterLimit = miterLimit; - } - void EMFPCustomLineCap::ReadPath(SvStream& s, EmfPlusHelperData const & rR, bool bFill) { sal_Int32 pathLength; diff --git a/drawinglayer/source/tools/emfpcustomlinecap.hxx b/drawinglayer/source/tools/emfpcustomlinecap.hxx index a42e0ab4ef46..e6202ae98179 100644 --- a/drawinglayer/source/tools/emfpcustomlinecap.hxx +++ b/drawinglayer/source/tools/emfpcustomlinecap.hxx @@ -19,7 +19,6 @@ #pragma once -#include <com/sun/star/rendering/StrokeAttributes.hpp> #include "emfphelperdata.hxx" namespace emfplushelper @@ -34,7 +33,6 @@ namespace emfplushelper EMFPCustomLineCap(); - void SetAttributes(com::sun::star::rendering::StrokeAttributes& aAttributes); void ReadPath(SvStream& s, EmfPlusHelperData const & rR, bool bFill); void Read(SvStream& s, EmfPlusHelperData const & rR); }; diff --git a/drawinglayer/source/tools/emfphelperdata.cxx b/drawinglayer/source/tools/emfphelperdata.cxx index 447686167837..79ced761e8a2 100644 --- a/drawinglayer/source/tools/emfphelperdata.cxx +++ b/drawinglayer/source/tools/emfphelperdata.cxx @@ -509,13 +509,6 @@ namespace emfplushelper if (!(pen && polygon.count())) return; - // we need a line join attribute - basegfx::B2DLineJoin lineJoin = basegfx::B2DLineJoin::Round; - if (pen->penDataFlags & EmfPlusPenDataJoin) // additional line join information - { - lineJoin = static_cast<basegfx::B2DLineJoin>(EMFPPen::lcl_convertLineJoinType(pen->lineJoin)); - } - // we need a line cap attribute css::drawing::LineCap lineCap = css::drawing::LineCap_BUTT; if (pen->penDataFlags & EmfPlusPenDataStartCap) // additional line cap information @@ -527,57 +520,16 @@ namespace emfplushelper const double transformedPenWidth = maMapTransform.get(0, 0) * pen->penWidth; drawinglayer::attribute::LineAttribute lineAttribute(pen->GetColor().getBColor(), transformedPenWidth, - lineJoin, - lineCap); - - drawinglayer::attribute::StrokeAttribute aStrokeAttribute; - if (pen->penDataFlags & EmfPlusPenDataLineStyle && pen->dashStyle != EmfPlusLineStyleCustom) // pen has a predefined line style - { - // short writing - const double pw = maMapTransform.get(1, 1) * pen->penWidth; - // taken from the old cppcanvas implementation and multiplied with pen width - const std::vector<double> dash = { 3*pw, 3*pw }; - const std::vector<double> dot = { pw, 3*pw }; - const std::vector<double> dashdot = { 3*pw, 3*pw, pw, 3*pw }; - const std::vector<double> dashdotdot = { 3*pw, 3*pw, pw, 3*pw, pw, 3*pw }; - - switch (pen->dashStyle) - { - case EmfPlusLineStyleSolid: // do nothing special, use default stroke attribute - break; - case EmfPlusLineStyleDash: - aStrokeAttribute = drawinglayer::attribute::StrokeAttribute(std::vector(dash)); - break; - case EmfPlusLineStyleDot: - aStrokeAttribute = drawinglayer::attribute::StrokeAttribute(std::vector(dot)); - break; - case EmfPlusLineStyleDashDot: - aStrokeAttribute = drawinglayer::attribute::StrokeAttribute(std::vector(dashdot)); - break; - case EmfPlusLineStyleDashDotDot: - aStrokeAttribute = drawinglayer::attribute::StrokeAttribute(std::vector(dashdotdot)); - break; - } - } - else if (pen->penDataFlags & EmfPlusPenDataDashedLine) // pen has a custom dash line - { - // StrokeAttribute needs a double vector while the pen provides a float vector - std::vector<double> aPattern(pen->dashPattern.size()); - for (size_t i=0; i<aPattern.size(); i++) - { - // convert from float to double and multiply with the adjusted pen width - aPattern[i] = maMapTransform.get(1, 1) * pen->penWidth * pen->dashPattern[i]; - } - aStrokeAttribute = drawinglayer::attribute::StrokeAttribute(std::move(aPattern)); - } - + pen->GetLineJoinType(), + lineCap, + basegfx::deg2rad(15.0)); // TODO Add MiterLimit support if (!pen->GetColor().IsTransparent()) { mrTargetHolders.Current().append( new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D( polygon, lineAttribute, - aStrokeAttribute)); + pen->GetStrokeAttribute(maMapTransform.get(1, 1)))); } else { @@ -585,7 +537,7 @@ namespace emfplushelper new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D( polygon, lineAttribute, - aStrokeAttribute)); + pen->GetStrokeAttribute(maMapTransform.get(1, 1)))); mrTargetHolders.Current().append( new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D( @@ -634,7 +586,7 @@ namespace emfplushelper new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D( startCapPolygon, lineAttribute, - aStrokeAttribute)); + pen->GetStrokeAttribute(maMapTransform.get(1, 1)))); } } @@ -679,7 +631,7 @@ namespace emfplushelper new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D( endCapPolygon, lineAttribute, - aStrokeAttribute)); + pen->GetStrokeAttribute(maMapTransform.get(1, 1)))); } } diff --git a/drawinglayer/source/tools/emfppen.cxx b/drawinglayer/source/tools/emfppen.cxx index d41dca676d4e..f348391b0519 100644 --- a/drawinglayer/source/tools/emfppen.cxx +++ b/drawinglayer/source/tools/emfppen.cxx @@ -18,7 +18,6 @@ */ #include <com/sun/star/rendering/PathCapType.hpp> -#include <com/sun/star/rendering/PathJoinType.hpp> #include <o3tl/safeint.hxx> #include <sal/log.hxx> #include <rtl/ustrbuf.hxx> @@ -179,27 +178,70 @@ namespace emfplushelper { switch (nEmfStroke) { - case EmfPlusLineCapTypeSquare: return rendering::PathCapType::SQUARE; - case EmfPlusLineCapTypeRound: return rendering::PathCapType::ROUND; + case EmfPlusLineCapTypeSquare: + return rendering::PathCapType::SQUARE; + // we have no mapping for EmfPlusLineCapTypeTriangle, + // but it is similar to Round + case EmfPlusLineCapTypeTriangle: // fall-through + case EmfPlusLineCapTypeRound: + return rendering::PathCapType::ROUND; } - // we have no mapping for EmfPlusLineCapTypeTriangle = 0x00000003, - // so return BUTT always return rendering::PathCapType::BUTT; } - sal_Int8 EMFPPen::lcl_convertLineJoinType(sal_uInt32 nEmfLineJoin) + basegfx::B2DLineJoin EMFPPen::GetLineJoinType() const { - switch (nEmfLineJoin) + if (penDataFlags & EmfPlusPenDataJoin) // additional line join information { - case EmfPlusLineJoinTypeMiter: // fall-through - case EmfPlusLineJoinTypeMiterClipped: return rendering::PathJoinType::MITER; - case EmfPlusLineJoinTypeBevel: return rendering::PathJoinType::BEVEL; - case EmfPlusLineJoinTypeRound: return rendering::PathJoinType::ROUND; + switch (lineJoin) + { + case EmfPlusLineJoinTypeMiter: // fall-through + case EmfPlusLineJoinTypeMiterClipped: + return basegfx::B2DLineJoin::Miter; + case EmfPlusLineJoinTypeBevel: + return basegfx::B2DLineJoin::Bevel; + case EmfPlusLineJoinTypeRound: + return basegfx::B2DLineJoin::Round; + } } + // If nothing set, then miter applied with no limit + return basegfx::B2DLineJoin::Miter; + } - assert(false); // Line Join type isn't in specification. - return 0; + drawinglayer::attribute::StrokeAttribute + EMFPPen::GetStrokeAttribute(const double aTransformation) const + { + if (penDataFlags & EmfPlusPenDataLineStyle // pen has a predefined line style + && dashStyle != EmfPlusLineStyleCustom) + { + const double pw = aTransformation * penWidth; + switch (dashStyle) + { + case EmfPlusLineStyleDash: + return drawinglayer::attribute::StrokeAttribute({ 3 * pw, pw }); + case EmfPlusLineStyleDot: + return drawinglayer::attribute::StrokeAttribute({ pw, pw }); + case EmfPlusLineStyleDashDot: + return drawinglayer::attribute::StrokeAttribute({ 3 * pw, pw, pw, pw }); + case EmfPlusLineStyleDashDotDot: + return drawinglayer::attribute::StrokeAttribute({ 3 * pw, pw, pw, pw, pw, pw }); + } + } + else if (penDataFlags & EmfPlusPenDataDashedLine) // pen has a custom dash line + { + const double pw = aTransformation * penWidth; + // StrokeAttribute needs a double vector while the pen provides a float vector + std::vector<double> aPattern(dashPattern.size()); + for (size_t i = 0; i < aPattern.size(); i++) + { + // convert from float to double and multiply with the adjusted pen width + aPattern[i] = pw * dashPattern[i]; + } + return drawinglayer::attribute::StrokeAttribute(std::move(aPattern)); + } + // EmfPlusLineStyleSolid: - do nothing special, use default stroke attribute + return drawinglayer::attribute::StrokeAttribute(); } void EMFPPen::Read(SvStream& s, EmfPlusHelperData const & rR) @@ -249,7 +291,7 @@ namespace emfplushelper if (penDataFlags & PenDataJoin) { s.ReadInt32(lineJoin); - SAL_WARN("drawinglayer.emf", "EMF+\t\tTODO PenDataJoin: " << LineJoinTypeToString(lineJoin) << " (0x" << std::hex << lineJoin << ")"); + SAL_WARN("drawinglayer.emf", "EMF+\t\t LineJoin: " << LineJoinTypeToString(lineJoin) << " (0x" << std::hex << lineJoin << ")"); } else { diff --git a/drawinglayer/source/tools/emfppen.hxx b/drawinglayer/source/tools/emfppen.hxx index 05b2fc376d7d..29ece63ecf5d 100644 --- a/drawinglayer/source/tools/emfppen.hxx +++ b/drawinglayer/source/tools/emfppen.hxx @@ -19,6 +19,7 @@ #pragma once +#include <drawinglayer/attribute/strokeattribute.hxx> #include "emfpbrush.hxx" #include <vector> @@ -26,6 +27,7 @@ namespace emfplushelper { const sal_uInt32 EmfPlusLineCapTypeSquare = 0x00000001; const sal_uInt32 EmfPlusLineCapTypeRound = 0x00000002; + const sal_uInt32 EmfPlusLineCapTypeTriangle = 0x00000003; const sal_uInt32 EmfPlusLineJoinTypeMiter = 0x00000000; const sal_uInt32 EmfPlusLineJoinTypeBevel = 0x00000001; @@ -122,7 +124,8 @@ namespace emfplushelper void Read(SvStream& s, EmfPlusHelperData const & rR); static sal_Int8 lcl_convertStrokeCap(sal_uInt32 nEmfStroke); - static sal_Int8 lcl_convertLineJoinType(sal_uInt32 nEmfLineJoin); + drawinglayer::attribute::StrokeAttribute GetStrokeAttribute(const double aTransformation) const; + basegfx::B2DLineJoin GetLineJoinType() const; }; } diff --git a/drawinglayer/source/tools/primitive2dxmldump.cxx b/drawinglayer/source/tools/primitive2dxmldump.cxx index 2e2bb887a3d4..a1fddf900543 100644 --- a/drawinglayer/source/tools/primitive2dxmldump.cxx +++ b/drawinglayer/source/tools/primitive2dxmldump.cxx @@ -13,6 +13,7 @@ #include <tools/stream.hxx> #include <tools/XmlWriter.hxx> +#include <math.h> #include <memory> #include <sal/log.hxx> @@ -132,6 +133,24 @@ void writePolyPolygon(::tools::XmlWriter& rWriter, const basegfx::B2DPolyPolygon rWriter.endElement(); } +void writeStrokeAttribute(::tools::XmlWriter& rWriter, + const drawinglayer::attribute::StrokeAttribute& rStrokeAttribute) +{ + if (!rStrokeAttribute.getDotDashArray().empty()) + { + rWriter.startElement("stroke"); + + OUString sDotDash; + for (double fDotDash : rStrokeAttribute.getDotDashArray()) + { + sDotDash += OUString::number(round(100.0 * fDotDash)) + " "; + } + rWriter.attribute("dotDashArray", sDotDash); + rWriter.attribute("fullDotDashLength", rStrokeAttribute.getFullDotDashLen()); + rWriter.endElement(); + } +} + void writeLineAttribute(::tools::XmlWriter& rWriter, const drawinglayer::attribute::LineAttribute& rLineAttribute) { @@ -718,14 +737,7 @@ void Primitive2dXmlDump::decomposeAndWrite( rWriter.endElement(); writeLineAttribute(rWriter, rPolygonStrokePrimitive2D.getLineAttribute()); - - rWriter.startElement("stroke"); - const drawinglayer::attribute::StrokeAttribute& aStrokeAttribute - = rPolygonStrokePrimitive2D.getStrokeAttribute(); - rWriter.attribute("fulldotdashlen", aStrokeAttribute.getFullDotDashLen()); - //rWriter.attribute("dotdasharray", aStrokeAttribute.getDotDashArray()); - rWriter.endElement(); - + writeStrokeAttribute(rWriter, rPolygonStrokePrimitive2D.getStrokeAttribute()); rWriter.endElement(); } break; @@ -736,9 +748,7 @@ void Primitive2dXmlDump::decomposeAndWrite( rWriter.startElement("polypolygonstroke"); writeLineAttribute(rWriter, rPolyPolygonStrokePrimitive2D.getLineAttribute()); - - //getStrokeAttribute() - + writeStrokeAttribute(rWriter, rPolyPolygonStrokePrimitive2D.getStrokeAttribute()); writePolyPolygon(rWriter, rPolyPolygonStrokePrimitive2D.getB2DPolyPolygon()); rWriter.endElement(); |