summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBartosz Kosiorek <gang65@poczta.onet.pl>2022-06-12 21:51:52 +0200
committerXisco Fauli <xiscofauli@libreoffice.org>2022-06-15 08:41:31 +0200
commit8419e2909aef8916111e4dce9c0a070464a06e66 (patch)
tree8bd8bc3d5bb49574d3df14c927518d09805463af
parent45d400ec42a59b03aca00cf1e08e3a9be2488537 (diff)
tdf#131506 tdf#143031 EMF+ Fix displaying PathGradient fill
With previous implementation, the EMF+ import is calculating gradient positions wrongly. It is causing warning: SvgGradientHelper got invalid SvgGradientEntries outside [0.0 .. 1.0] and the gradient was not displayed at all. This patch fixes that and gradient is displayed correctly Change-Id: I6229c516165436d0c7ae187d9eb69b5494da396f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135607 Tested-by: Jenkins Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl> (cherry picked from commit 7b12c659842eb53b96dd98ecea65c6071506dfbb) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135746 Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org> Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135858
-rw-r--r--drawinglayer/source/tools/emfpbrush.cxx12
-rw-r--r--drawinglayer/source/tools/emfphelperdata.cxx55
-rw-r--r--drawinglayer/source/tools/primitive2dxmldump.cxx42
-rw-r--r--emfio/qa/cppunit/emf/EmfImportTest.cxx24
-rw-r--r--emfio/qa/cppunit/emf/data/TestEmfPlusBrushPathGradientWithBlendColors.emfbin0 -> 2404 bytes
-rw-r--r--svgio/qa/cppunit/SvgImportTest.cxx14
6 files changed, 99 insertions, 48 deletions
diff --git a/drawinglayer/source/tools/emfpbrush.cxx b/drawinglayer/source/tools/emfpbrush.cxx
index 4acc311345a8..493b6eafc613 100644
--- a/drawinglayer/source/tools/emfpbrush.cxx
+++ b/drawinglayer/source/tools/emfpbrush.cxx
@@ -187,6 +187,12 @@ namespace emfplushelper
SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tUse brush transformation: " << brush_transformation);
}
+ // BrushDataPresetColors and BrushDataBlendFactorsH
+ if ((additionalFlags & 0x04) && (additionalFlags & 0x08))
+ {
+ SAL_WARN("drawinglayer.emf", "EMF+\t Brush must not contain both BrushDataPresetColors and BrushDataBlendFactorsH");
+ return;
+ }
if (additionalFlags & 0x08)
{
s.ReadInt32(blendPoints);
@@ -268,6 +274,12 @@ namespace emfplushelper
hasTransformation = true;
SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tUse brush transformation: " << brush_transformation);
}
+ // BrushDataPresetColors and BrushDataBlendFactorsH
+ if ((additionalFlags & 0x04) && (additionalFlags & 0x08))
+ {
+ SAL_WARN("drawinglayer.emf", "EMF+\t Brush must not contain both BrushDataPresetColors and BrushDataBlendFactorsH");
+ return;
+ }
if (additionalFlags & 0x08)
{
diff --git a/drawinglayer/source/tools/emfphelperdata.cxx b/drawinglayer/source/tools/emfphelperdata.cxx
index 7a64f8ad4dac..df3c4293a87f 100644
--- a/drawinglayer/source/tools/emfphelperdata.cxx
+++ b/drawinglayer/source/tools/emfphelperdata.cxx
@@ -784,21 +784,12 @@ namespace emfplushelper
// store the blendpoints in the vector
for (int i = 0; i < brush->blendPoints; i++)
{
- double aBlendPoint;
+ const double aBlendPoint = brush->blendPositions[i];
basegfx::BColor aColor;
- if (brush->type == BrushTypeLinearGradient)
- {
- aBlendPoint = brush->blendPositions [i];
- }
- else
- {
- // seems like SvgRadialGradientPrimitive2D needs doubled, inverted radius
- aBlendPoint = 2. * ( 1. - brush->blendPositions [i] );
- }
- aColor.setGreen( aStartColor.getGreen() + brush->blendFactors[i] * ( aEndColor.getGreen() - aStartColor.getGreen() ) );
- aColor.setBlue ( aStartColor.getBlue() + brush->blendFactors[i] * ( aEndColor.getBlue() - aStartColor.getBlue() ) );
- aColor.setRed ( aStartColor.getRed() + brush->blendFactors[i] * ( aEndColor.getRed() - aStartColor.getRed() ) );
- const double aAlpha = brush->solidColor.GetAlpha() + brush->blendFactors[i] * ( brush->secondColor.GetAlpha() - brush->solidColor.GetAlpha() );
+ aColor.setGreen(aStartColor.getGreen() + brush->blendFactors[i] * (aEndColor.getGreen() - aStartColor.getGreen()));
+ aColor.setBlue (aStartColor.getBlue() + brush->blendFactors[i] * (aEndColor.getBlue() - aStartColor.getBlue()));
+ aColor.setRed (aStartColor.getRed() + brush->blendFactors[i] * (aEndColor.getRed() - aStartColor.getRed()));
+ const double aAlpha = brush->solidColor.GetAlpha() + brush->blendFactors[i] * (brush->secondColor.GetAlpha() - brush->solidColor.GetAlpha());
aVector.emplace_back(aBlendPoint, aColor, aAlpha / 255.0);
}
}
@@ -809,33 +800,15 @@ namespace emfplushelper
// store the colorBlends in the vector
for (int i = 0; i < brush->colorblendPoints; i++)
{
- double aBlendPoint;
- basegfx::BColor aColor;
- if (brush->type == BrushTypeLinearGradient)
- {
- aBlendPoint = brush->colorblendPositions [i];
- }
- else
- {
- // seems like SvgRadialGradientPrimitive2D needs doubled, inverted radius
- aBlendPoint = 2. * ( 1. - brush->colorblendPositions [i] );
- }
- aColor = brush->colorblendColors[i].getBColor();
- aVector.emplace_back(aBlendPoint, aColor, brush->colorblendColors[i].GetAlpha() / 255.0 );
+ const double aBlendPoint = brush->colorblendPositions[i];
+ const basegfx::BColor aColor = brush->colorblendColors[i].getBColor();
+ aVector.emplace_back(aBlendPoint, aColor, brush->colorblendColors[i].GetAlpha() / 255.0);
}
}
else // ok, no extra points: just start and end
{
- if (brush->type == BrushTypeLinearGradient)
- {
- aVector.emplace_back(0.0, aStartColor, brush->solidColor.GetAlpha() / 255.0);
- aVector.emplace_back(1.0, aEndColor, brush->secondColor.GetAlpha() / 255.0);
- }
- else // again, here reverse
- {
- aVector.emplace_back(0.0, aEndColor, brush->secondColor.GetAlpha() / 255.0);
- aVector.emplace_back(1.0, aStartColor, brush->solidColor.GetAlpha() / 255.0);
- }
+ aVector.emplace_back(0.0, aStartColor, brush->solidColor.GetAlpha() / 255.0);
+ aVector.emplace_back(1.0, aEndColor, brush->secondColor.GetAlpha() / 255.0);
}
// get the polygon range to be able to map the start/end/center point correctly
@@ -886,7 +859,7 @@ namespace emfplushelper
aSpreadMethod));
}
else // BrushTypePathGradient
- {
+ { // TODO The PathGradient is not implemented, and Radial Gradient is used instead
basegfx::B2DPoint aCenterPoint = Map(brush->firstPointX, brush->firstPointY);
aCenterPoint = aPolygonTransformation * aCenterPoint;
@@ -897,9 +870,9 @@ namespace emfplushelper
polygon,
std::move(aVector),
aCenterPoint,
- 0.5, // relative radius
- true, // use UnitCoordinates to stretch the gradient
- drawinglayer::primitive2d::SpreadMethod::Repeat,
+ 0.7, // relative radius little bigger to cover all elements
+ true, // use UnitCoordinates to stretch the gradient
+ drawinglayer::primitive2d::SpreadMethod::Pad,
nullptr));
}
}
diff --git a/drawinglayer/source/tools/primitive2dxmldump.cxx b/drawinglayer/source/tools/primitive2dxmldump.cxx
index 27a8adf1b5e3..fcad3a03bbac 100644
--- a/drawinglayer/source/tools/primitive2dxmldump.cxx
+++ b/drawinglayer/source/tools/primitive2dxmldump.cxx
@@ -458,6 +458,25 @@ void writeMaterialAttribute(::tools::XmlWriter& rWriter,
rWriter.endElement();
}
+void writeSpreadMethod(::tools::XmlWriter& rWriter,
+ const drawinglayer::primitive2d::SpreadMethod& rSpreadMethod)
+{
+ switch (rSpreadMethod)
+ {
+ case drawinglayer::primitive2d::SpreadMethod::Pad:
+ rWriter.attribute("spreadmethod", "pad");
+ break;
+ case drawinglayer::primitive2d::SpreadMethod::Reflect:
+ rWriter.attribute("spreadmethod", "reflect");
+ break;
+ case drawinglayer::primitive2d::SpreadMethod::Repeat:
+ rWriter.attribute("spreadmethod", "repeat");
+ break;
+ default:
+ rWriter.attribute("spreadmethod", "unknown");
+ }
+}
+
} // end anonymous namespace
Primitive2dXmlDump::Primitive2dXmlDump()
@@ -887,13 +906,28 @@ void Primitive2dXmlDump::decomposeAndWrite(
const SvgRadialGradientPrimitive2D& rSvgRadialGradientPrimitive2D
= dynamic_cast<const SvgRadialGradientPrimitive2D&>(*pBasePrimitive);
rWriter.startElement("svgradialgradient");
- basegfx::B2DPoint aFocusAttribute = rSvgRadialGradientPrimitive2D.getFocal();
+ if (rSvgRadialGradientPrimitive2D.isFocalSet())
+ {
+ basegfx::B2DPoint aFocalAttribute = rSvgRadialGradientPrimitive2D.getFocal();
+ rWriter.attribute("focalx", aFocalAttribute.getX());
+ rWriter.attribute("focaly", aFocalAttribute.getY());
+ }
+ basegfx::B2DPoint aStartPoint = rSvgRadialGradientPrimitive2D.getStart();
+ rWriter.attribute("startx", aStartPoint.getX());
+ rWriter.attribute("starty", aStartPoint.getY());
rWriter.attribute("radius",
OString::number(rSvgRadialGradientPrimitive2D.getRadius()));
- rWriter.attribute("focusx", aFocusAttribute.getX());
- rWriter.attribute("focusy", aFocusAttribute.getY());
+ writeSpreadMethod(rWriter, rSvgRadialGradientPrimitive2D.getSpreadMethod());
+ rWriter.attributeDouble(
+ "opacity",
+ rSvgRadialGradientPrimitive2D.getGradientEntries().front().getOpacity());
+
+ rWriter.startElement("transform");
+ writeMatrix(rWriter, rSvgRadialGradientPrimitive2D.getGradientTransform());
+ rWriter.endElement();
+ writePolyPolygon(rWriter, rSvgRadialGradientPrimitive2D.getPolyPolygon());
rWriter.endElement();
}
break;
@@ -910,7 +944,7 @@ void Primitive2dXmlDump::decomposeAndWrite(
rWriter.attribute("starty", aStartAttribute.getY());
rWriter.attribute("endx", aEndAttribute.getX());
rWriter.attribute("endy", aEndAttribute.getY());
- //rWriter.attribute("spreadmethod", (int)rSvgLinearGradientPrimitive2D.getSpreadMethod());
+ writeSpreadMethod(rWriter, rSvgLinearGradientPrimitive2D.getSpreadMethod());
rWriter.attributeDouble(
"opacity",
rSvgLinearGradientPrimitive2D.getGradientEntries().front().getOpacity());
diff --git a/emfio/qa/cppunit/emf/EmfImportTest.cxx b/emfio/qa/cppunit/emf/EmfImportTest.cxx
index a734010e0dac..112ea0926596 100644
--- a/emfio/qa/cppunit/emf/EmfImportTest.cxx
+++ b/emfio/qa/cppunit/emf/EmfImportTest.cxx
@@ -65,6 +65,7 @@ class Test : public test::BootstrapFixture, public XmlTestTools, public unotest:
void TestSetArcDirection();
void TestDrawPolyLine16WithClip();
void TestFillRegion();
+ void TestEmfPlusBrushPathGradientWithBlendColors();
void TestExtTextOutOpaqueAndClipTransform();
void TestBitBltStretchBltWMF();
@@ -109,6 +110,7 @@ public:
CPPUNIT_TEST(TestSetArcDirection);
CPPUNIT_TEST(TestDrawPolyLine16WithClip);
CPPUNIT_TEST(TestFillRegion);
+ CPPUNIT_TEST(TestEmfPlusBrushPathGradientWithBlendColors);
CPPUNIT_TEST(TestExtTextOutOpaqueAndClipTransform);
CPPUNIT_TEST(TestBitBltStretchBltWMF);
@@ -452,6 +454,7 @@ void Test::TestLinearGradient()
assertXPath(pDocument, aXPathPrefix + "mask/polypolygon", "width", "15232");
assertXPath(pDocument, aXPathPrefix + "mask/polypolygon", "path", "m0 0h15232v7610h-15232z");
+ assertXPath(pDocument, aXPathPrefix + "mask/svglineargradient[1]", "spreadmethod", "repeat");
assertXPath(pDocument, aXPathPrefix + "mask/svglineargradient[1]", "startx", "0");
assertXPath(pDocument, aXPathPrefix + "mask/svglineargradient[1]", "starty", "-1");
assertXPath(pDocument, aXPathPrefix + "mask/svglineargradient[1]", "endx", "0");
@@ -460,6 +463,8 @@ void Test::TestLinearGradient()
"0.392156862745098");
assertXPath(pDocument, aXPathPrefix + "mask/svglineargradient[1]/polypolygon", "path",
"m0 0.216110019646294h7615.75822989746v7610.21611001965h-7615.75822989746z");
+
+ assertXPath(pDocument, aXPathPrefix + "mask/svglineargradient[2]", "spreadmethod", "repeat");
assertXPath(pDocument, aXPathPrefix + "mask/svglineargradient[2]", "startx", "-1");
assertXPath(pDocument, aXPathPrefix + "mask/svglineargradient[2]", "starty", "-1");
assertXPath(pDocument, aXPathPrefix + "mask/svglineargradient[2]", "endx", "0");
@@ -890,6 +895,25 @@ void Test::TestPolylinetoCloseStroke()
assertXPath(pDocument, aXPathPrefix + "polygonhairline[2]", "color", "#000000");
}
+void Test::TestEmfPlusBrushPathGradientWithBlendColors()
+{
+ // tdf#131506 EMF+ records: FillRects, Brush with PathGradient and BlendColor, FillRects
+ Primitive2DSequence aSequence
+ = parseEmf(u"emfio/qa/cppunit/emf/data/TestEmfPlusBrushPathGradientWithBlendColors.emf");
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(aSequence.getLength()));
+ drawinglayer::Primitive2dXmlDump dumper;
+ xmlDocUniquePtr pDocument
+ = dumper.dumpAndParse(comphelper::sequenceToContainer<Primitive2DContainer>(aSequence));
+ CPPUNIT_ASSERT(pDocument);
+
+ assertXPath(pDocument, aXPathPrefix + "svgradialgradient", "radius", "0.7");
+ assertXPath(pDocument, aXPathPrefix + "svgradialgradient/focalx", 0);
+ assertXPath(pDocument, aXPathPrefix + "svgradialgradient/focaly", 0);
+ assertXPath(pDocument, aXPathPrefix + "svgradialgradient", "startx", "0");
+ assertXPath(pDocument, aXPathPrefix + "svgradialgradient", "starty", "0");
+ assertXPath(pDocument, aXPathPrefix + "svgradialgradient", "spreadmethod", "pad");
+}
+
void Test::TestExtTextOutOpaqueAndClipTransform()
{
// tdf#142495 EMF records: SETBKCOLOR, SELECTOBJECT, EXTTEXTOUTW, MODIFYWORLDTRANSFORM, CREATEFONTINDIRECT.
diff --git a/emfio/qa/cppunit/emf/data/TestEmfPlusBrushPathGradientWithBlendColors.emf b/emfio/qa/cppunit/emf/data/TestEmfPlusBrushPathGradientWithBlendColors.emf
new file mode 100644
index 000000000000..caa9876bd449
--- /dev/null
+++ b/emfio/qa/cppunit/emf/data/TestEmfPlusBrushPathGradientWithBlendColors.emf
Binary files differ
diff --git a/svgio/qa/cppunit/SvgImportTest.cxx b/svgio/qa/cppunit/SvgImportTest.cxx
index 3034c997015e..c563e7b296fd 100644
--- a/svgio/qa/cppunit/SvgImportTest.cxx
+++ b/svgio/qa/cppunit/SvgImportTest.cxx
@@ -412,9 +412,13 @@ void Test::testTdf97542_2()
CPPUNIT_ASSERT (pDocument);
- assertXPath(pDocument, "/primitive2D/transform/objectinfo/svgradialgradient[1]", "focusx", "1");
- assertXPath(pDocument, "/primitive2D/transform/objectinfo/svgradialgradient[1]", "focusy", "1");
- assertXPath(pDocument, "/primitive2D/transform/objectinfo/svgradialgradient[1]", "radius", "3");
+ assertXPath(pDocument, "/primitive2D/transform/objectinfo/svgradialgradient", "startx", "1");
+ assertXPath(pDocument, "/primitive2D/transform/objectinfo/svgradialgradient", "starty", "1");
+ assertXPath(pDocument, "/primitive2D/transform/objectinfo/svgradialgradient/focalx", 0);
+ assertXPath(pDocument, "/primitive2D/transform/objectinfo/svgradialgradient/focaly", 0);
+ assertXPath(pDocument, "/primitive2D/transform/objectinfo/svgradialgradient", "radius", "3");
+ assertXPath(pDocument, "/primitive2D/transform/objectinfo/svgradialgradient", "spreadmethod", "pad");
+ assertXPath(pDocument, "/primitive2D/transform/objectinfo/svgradialgradient", "opacity", "1");
}
void Test::testTdf97543()
@@ -738,8 +742,12 @@ void Test::testTdf94765()
CPPUNIT_ASSERT (pDocument);
//Check that both rectangles use the gradient as fill
+ assertXPath(pDocument, "/primitive2D/transform/transform/svglineargradient[1]", "startx", "1");
+ assertXPath(pDocument, "/primitive2D/transform/transform/svglineargradient[1]", "starty", "1");
assertXPath(pDocument, "/primitive2D/transform/transform/svglineargradient[1]", "endx", "2");
assertXPath(pDocument, "/primitive2D/transform/transform/svglineargradient[1]", "endy", "1");
+ assertXPath(pDocument, "/primitive2D/transform/transform/svglineargradient[2]", "startx", "0");
+ assertXPath(pDocument, "/primitive2D/transform/transform/svglineargradient[2]", "starty", "0");
assertXPath(pDocument, "/primitive2D/transform/transform/svglineargradient[2]", "endx", "0");
assertXPath(pDocument, "/primitive2D/transform/transform/svglineargradient[2]", "endy", "0");
}