diff options
author | Miklos Vajna <vmiklos@collabora.co.uk> | 2016-04-18 16:53:48 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2016-04-18 19:06:39 +0000 |
commit | 422f10c5d7ebe6f4b778636c9c1eb6dbdf708a27 (patch) | |
tree | 48cc1010c22ba6113fc70ae79ef6ed086331c981 /drawinglayer | |
parent | tdf#99371 fix for DDE link update via Function Wizard (diff) | |
download | core-422f10c5d7ebe6f4b778636c9c1eb6dbdf708a27.tar.gz core-422f10c5d7ebe6f4b778636c9c1eb6dbdf708a27.zip |
tdf#99315 VclPixelProcessor2D: fix double border line width
Regression from commit 2c91cb08d65cd35fa8ef6eaca3677aa82fb58cbe (better
drawing support for borders of different width, fdo#33634, 2012-04-04),
the problem is that previously the width of inner/outer double border
lines got rounded to integer values quite early, but after the commit
they are kept at a double precision for much longer, which needs pixel
correction in VclPixelProcessor2D.
Example: if the border with is 1.47, and the line gets moved by 0.2
pixels, then the inner and outer edge of the line will be 0.2 and 1.67,
which gets rounded to 0 -> 2 in the pixel processor. Previously the
input was rounded to 1, so moving by 0.2 resulted in 0.2 -> 1.2, which
got rounded to 0 -> 1. The result is that sometimes the line width is 1
pixel wider than expected.
Fix the problem by allowing VclPixelProcessor2D to request pixel
correction from BorderLinePrimitive2D. It wouldn't be possible to do
pixel correction only in VclPixelProcessor2D, as it has no idea what to
correct: it only gets polygons, so it has no idea if e.g. the top of a
polygon is the outer edge of a top border line or an inner edge of a
bottom border line.
Change-Id: I1971f3a952fbcdc598ab46c659e12d976c13cbe6
Reviewed-on: https://gerrit.libreoffice.org/24221
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
Diffstat (limited to 'drawinglayer')
-rw-r--r-- | drawinglayer/CppunitTest_drawinglayer_border.mk | 16 | ||||
-rw-r--r-- | drawinglayer/qa/unit/border.cxx | 71 | ||||
-rw-r--r-- | drawinglayer/source/primitive2d/borderlineprimitive2d.cxx | 15 | ||||
-rw-r--r-- | drawinglayer/source/processor2d/vclpixelprocessor2d.cxx | 7 |
4 files changed, 104 insertions, 5 deletions
diff --git a/drawinglayer/CppunitTest_drawinglayer_border.mk b/drawinglayer/CppunitTest_drawinglayer_border.mk index 65f8cf6b65d9..ea72b8cee602 100644 --- a/drawinglayer/CppunitTest_drawinglayer_border.mk +++ b/drawinglayer/CppunitTest_drawinglayer_border.mk @@ -21,6 +21,9 @@ $(eval $(call gb_CppunitTest_use_libraries,drawinglayer_border, \ sal \ salhelper \ drawinglayer \ + vcl \ + test \ + tl \ $(gb_UWINAPI) \ )) @@ -33,4 +36,17 @@ $(eval $(call gb_CppunitTest_add_exception_objects,drawinglayer_border, \ drawinglayer/qa/unit/border \ )) +$(eval $(call gb_CppunitTest_use_ure,drawinglayer_border)) + +$(eval $(call gb_CppunitTest_use_vcl,drawinglayer_border)) + +$(eval $(call gb_CppunitTest_use_components,drawinglayer_border,\ + configmgr/source/configmgr \ + i18npool/util/i18npool \ + ucb/source/core/ucb1 \ + ucb/source/ucp/file/ucpfile1 \ +)) + +$(eval $(call gb_CppunitTest_use_configuration,drawinglayer_border)) + # vim: set noet sw=4 ts=4: diff --git a/drawinglayer/qa/unit/border.cxx b/drawinglayer/qa/unit/border.cxx index 6f49a2447b77..9f0c62187801 100644 --- a/drawinglayer/qa/unit/border.cxx +++ b/drawinglayer/qa/unit/border.cxx @@ -8,7 +8,6 @@ */ #include <cppunit/TestAssert.h> -#include <cppunit/TestFixture.h> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/plugin/TestPlugIn.h> @@ -17,20 +16,27 @@ #include <drawinglayer/geometry/viewinformation2d.hxx> #include <drawinglayer/primitive2d/borderlineprimitive2d.hxx> #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <drawinglayer/processor2d/baseprocessor2d.hxx> +#include <drawinglayer/processor2d/processorfromoutputdevice.hxx> #include <rtl/ref.hxx> +#include <test/bootstrapfixture.hxx> +#include <vcl/vclptr.hxx> +#include <vcl/virdev.hxx> using namespace com::sun::star; namespace { -class DrawinglayerBorderTest : public CppUnit::TestFixture +class DrawinglayerBorderTest : public test::BootstrapFixture { public: void testDoubleDecompositionSolid(); + void testDoublePixelProcessing(); CPPUNIT_TEST_SUITE(DrawinglayerBorderTest); CPPUNIT_TEST(testDoubleDecompositionSolid); + CPPUNIT_TEST(testDoublePixelProcessing); CPPUNIT_TEST_SUITE_END(); }; @@ -74,6 +80,67 @@ void DrawinglayerBorderTest::testDoubleDecompositionSolid() CPPUNIT_ASSERT_DOUBLES_EQUAL(fLeftWidth, rRange.getHeight(), basegfx::fTools::getSmallValue()); } +void DrawinglayerBorderTest::testDoublePixelProcessing() +{ + // Create a pixel processor. + ScopedVclPtrInstance<VirtualDevice> pDev; + drawinglayer::geometry::ViewInformation2D aView; + std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(*pDev, aView)); + CPPUNIT_ASSERT(pProcessor); + GDIMetaFile aMetaFile; + // Start recording after the processor is created, so we can test the pixel processor. + aMetaFile.Record(pDev); + + // Create a border line primitive that's similar to the one from the bugdoc: + // 1.47 pixels is 0.03cm at 130% zoom and 96 DPI. + basegfx::B2DPoint aStart(0, 20); + basegfx::B2DPoint aEnd(100, 20); + double fLeftWidth = 1.47; + double fDistance = 1.47; + double fRightWidth = 1.47; + double fExtendLeftStart = 0; + double fExtendLeftEnd = 0; + double fExtendRightStart = 0; + double fExtendRightEnd = 0; + basegfx::BColor aColorRight; + basegfx::BColor aColorLeft; + basegfx::BColor aColorGap; + bool bHasGapColor = false; + sal_Int16 nStyle = table::BorderLineStyle::DOUBLE; + rtl::Reference<drawinglayer::primitive2d::BorderLinePrimitive2D> xBorder(new drawinglayer::primitive2d::BorderLinePrimitive2D(aStart, aEnd, fLeftWidth, fDistance, fRightWidth, fExtendLeftStart, fExtendLeftEnd, fExtendRightStart, fExtendRightEnd, aColorRight, aColorLeft, aColorGap, bHasGapColor, nStyle)); + drawinglayer::primitive2d::Primitive2DContainer aPrimitives; + aPrimitives.push_back(drawinglayer::primitive2d::Primitive2DReference(xBorder.get())); + + // Process the primitives. + pProcessor->process(aPrimitives); + + // Now assert the height of the outer (second) border polygon. + aMetaFile.Stop(); + aMetaFile.WindStart(); + bool bFirst = true; + sal_Int32 nHeight = 0; + for(std::size_t nAction = 0; nAction < aMetaFile.GetActionSize(); ++nAction) + { + MetaAction* pAction = aMetaFile.GetAction(nAction); + if (pAction->GetType() == MetaActionType::POLYPOLYGON) + { + if (bFirst) + { + bFirst = false; + continue; + } + + auto pMPPAction = static_cast<MetaPolyPolygonAction*>(pAction); + const tools::PolyPolygon& rPolyPolygon = pMPPAction->GetPolyPolygon(); + nHeight = rPolyPolygon.GetBoundRect().getHeight(); + } + } + sal_Int32 nExpectedHeight = std::round(fRightWidth); + // This was 2, and should be 1: if the logical requested width is 1.47, + // then that must be 1 px on the screen, not 2. + CPPUNIT_ASSERT_EQUAL(nExpectedHeight, nHeight); +} + CPPUNIT_TEST_SUITE_REGISTRATION(DrawinglayerBorderTest); } diff --git a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx index 4a6a15018715..8ed0a9caf420 100644 --- a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx @@ -163,6 +163,11 @@ primitive2d::Primitive2DReference makeSolidLinePrimitive( Primitive2DContainer BorderLinePrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const { + return createDecomposition(rViewInformation, false); + } + + Primitive2DContainer BorderLinePrimitive2D::createDecomposition(const geometry::ViewInformation2D& rViewInformation, bool bPixelCorrection) const + { Primitive2DContainer xRetval; if(!getStart().equal(getEnd()) && ( isInsideUsed() || isOutsideUsed() ) ) @@ -199,8 +204,11 @@ primitive2d::Primitive2DReference makeSolidLinePrimitive( xRetval[0] = makeHairLinePrimitive( getStart(), getEnd(), aVector, getRGBColorLeft(), 0.0); else + { + double fWidth = bPixelCorrection ? std::round(fLeftWidth) : fLeftWidth; xRetval[0] = makeSolidLinePrimitive( - aClipRegion, aTmpStart, aTmpEnd, aVector, getRGBColorLeft(), fLeftWidth, -fLeftWidth/2.0); + aClipRegion, aTmpStart, aTmpEnd, aVector, getRGBColorLeft(), fWidth, -fLeftWidth/2.0); + } // "outside" line @@ -208,8 +216,11 @@ primitive2d::Primitive2DReference makeSolidLinePrimitive( xRetval[1] = makeHairLinePrimitive( getStart(), getEnd(), aVector, getRGBColorRight(), fLeftWidth+mfDistance); else + { + double fWidth = bPixelCorrection ? std::round(fRightWidth) : fRightWidth; xRetval[1] = makeSolidLinePrimitive( - aClipRegion, aTmpStart, aTmpEnd, aVector, getRGBColorRight(), fRightWidth, mfDistance+fRightWidth/2.0); + aClipRegion, aTmpStart, aTmpEnd, aVector, getRGBColorRight(), fWidth, mfDistance+fRightWidth/2.0); + } } else { diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx index 6d7832f66ef8..7b18c5900068 100644 --- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx @@ -1232,7 +1232,12 @@ namespace drawinglayer static_cast<const drawinglayer::primitive2d::BorderLinePrimitive2D&>(rCandidate); if (!tryDrawBorderLinePrimitive2DDirect(rBorder)) - process(rCandidate.get2DDecomposition(getViewInformation2D())); + { + if (rBorder.getStyle() == table::BorderLineStyle::DOUBLE) + process(rBorder.createDecomposition(getViewInformation2D(), true)); + else + process(rCandidate.get2DDecomposition(getViewInformation2D())); + } mpOutputDevice->SetAntialiasing(nAntiAliasing); break; |