summaryrefslogtreecommitdiff
path: root/drawinglayer
diff options
context:
space:
mode:
authorBartosz Kosiorek <gang65@poczta.onet.pl>2022-04-20 19:44:05 +0200
committerXisco Fauli <xiscofauli@libreoffice.org>2022-04-22 16:13:54 +0200
commit547ac0aa23a25f03a17014cb474eedc1fd88017f (patch)
tree50792210e32f51d12fa558830c53f8b8d2040e7b /drawinglayer
parentaf0955d600cd3d54d26a87b9ff30e3c402a226dd (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.cxx9
-rw-r--r--drawinglayer/source/tools/emfpcustomlinecap.hxx2
-rw-r--r--drawinglayer/source/tools/emfphelperdata.cxx62
-rw-r--r--drawinglayer/source/tools/emfppen.cxx70
-rw-r--r--drawinglayer/source/tools/emfppen.hxx5
-rw-r--r--drawinglayer/source/tools/primitive2dxmldump.cxx32
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();