diff --git a/drawinglayer/CppunitTest_drawinglayer_processors.mk b/drawinglayer/CppunitTest_drawinglayer_processors.mk index 789f878f5bb9..94e2b575ccd2 100644 --- a/drawinglayer/CppunitTest_drawinglayer_processors.mk +++ b/drawinglayer/CppunitTest_drawinglayer_processors.mk @@ -37,6 +37,7 @@ $(eval $(call gb_CppunitTest_use_externals,drawinglayer_processors,\ )) $(eval $(call gb_CppunitTest_add_exception_objects,drawinglayer_processors, \ + drawinglayer/qa/unit/strokeattribute \ drawinglayer/qa/unit/vclmetafileprocessor2d \ drawinglayer/qa/unit/vclpixelprocessor2d \ )) diff --git a/drawinglayer/qa/unit/strokeattribute.cxx b/drawinglayer/qa/unit/strokeattribute.cxx new file mode 100644 index 000000000000..74d5b69c084d --- /dev/null +++ b/drawinglayer/qa/unit/strokeattribute.cxx @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include + +#include + +using namespace drawinglayer::attribute; + +namespace +{ +class StrokeAttributeTest : public test::BootstrapFixture +{ +}; + +CPPUNIT_TEST_FIXTURE(StrokeAttributeTest, tdf152997_odd_length_dash_array) +{ + std::vector aDashArray{ 6.0 }; + StrokeAttribute aStroke(std::move(aDashArray)); + + // Without the fix in place, this test would have failed with + // - Expected: 2 + // - Actual : 1 + // i.e. the odd-length array was not duplicated + const std::vector aExpected{ 6.0, 6.0 }; + CPPUNIT_ASSERT_EQUAL(aExpected.size(), aStroke.getDotDashArray().size()); + CPPUNIT_ASSERT_EQUAL(12.0, aStroke.getFullDotDashLen()); + for (size_t i = 0; i < aExpected.size(); ++i) + CPPUNIT_ASSERT_DOUBLES_EQUAL(aExpected[i], aStroke.getDotDashArray()[i], 1E-12); +} + +CPPUNIT_TEST_FIXTURE(StrokeAttributeTest, tdf152997_odd_length_dash_array_multiple_values) +{ + std::vector aDashArray{ 5.0, 3.0, 2.0 }; + StrokeAttribute aStroke(std::move(aDashArray)); + + // Without the fix in place, this test would have failed with + // - Expected: 6 + // - Actual : 3 + // i.e. the odd-length array was not duplicated + const std::vector aExpected{ 5.0, 3.0, 2.0, 5.0, 3.0, 2.0 }; + CPPUNIT_ASSERT_EQUAL(aExpected.size(), aStroke.getDotDashArray().size()); + for (size_t i = 0; i < aExpected.size(); ++i) + CPPUNIT_ASSERT_DOUBLES_EQUAL(aExpected[i], aStroke.getDotDashArray()[i], 1E-12); +} + +CPPUNIT_TEST_FIXTURE(StrokeAttributeTest, tdf152997_even_length_dash_array) +{ + std::vector aDashArray{ 4.0, 2.0 }; + StrokeAttribute aStroke(std::move(aDashArray), 6.0); + + // An even-length dash array should not be changed + const std::vector aExpected{ 4.0, 2.0 }; + CPPUNIT_ASSERT_EQUAL(aExpected.size(), aStroke.getDotDashArray().size()); + CPPUNIT_ASSERT_EQUAL(6.0, aStroke.getFullDotDashLen()); + for (size_t i = 0; i < aExpected.size(); ++i) + CPPUNIT_ASSERT_DOUBLES_EQUAL(aExpected[i], aStroke.getDotDashArray()[i], 1E-12); +} + +CPPUNIT_TEST_FIXTURE(StrokeAttributeTest, tdf152997_empty_dash_array) +{ + std::vector aDashArray; + StrokeAttribute aStroke(std::move(aDashArray)); + + // An empty dash array should not be changed + CPPUNIT_ASSERT(aStroke.getDotDashArray().empty()); +} + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/drawinglayer/source/attribute/strokeattribute.cxx b/drawinglayer/source/attribute/strokeattribute.cxx index d925eb65acbe..46ac8a70ccce 100644 --- a/drawinglayer/source/attribute/strokeattribute.cxx +++ b/drawinglayer/source/attribute/strokeattribute.cxx @@ -36,6 +36,21 @@ namespace drawinglayer::attribute : maDotDashArray(std::move(rDotDashArray)), mfFullDotDashLen(fFullDotDashLen) { + // tdf#152997 - duplicate an odd length dash array in order to meet the spec. + // An odd-length array will be drawn as one dash spanning the entire path. The + // specifications under https://www.w3.org/TR/svg-strokes/#StrokeDashing state: + // "If the list has an odd number of values, then it is repeated to yield an + // even number of values. Thus, the rendering behavior of stroke-dasharray: 5,3,2 + // is equivalent to stroke-dasharray: 5,3,2,5,3,2." + if (maDotDashArray.size() % 2 == 1) + { + const std::vector aOriginal(maDotDashArray); + maDotDashArray.insert(maDotDashArray.end(), aOriginal.begin(), aOriginal.end()); + + // Increase the length accordingly + if (0.0 != mfFullDotDashLen) + mfFullDotDashLen *= 2.0; + } } ImpStrokeAttribute()