DOCX import: fix interaction between the crop and the wrap polygon of images

Word first applies the crop, then applies the wrap polygon on the
remaining visible part of the image.

Writer applies the crop on the original bitmap, and even has explicit
code to make sure the uncropped bitmap is used for the wrap polygon, see
how SwFlyFrame::GetContour() calls SwNoTextFrame::GetGrfArea(), which
will extend the resulting size based on cropping.

Fix the problem by moving and scaling the wrap polygon, so it ends up
where it would in Word.

Also adapt testFdo76803, which had a similar crop+wrap polygon case, but
the different there is quite small.

Change-Id: Iab2adaa81a33eb04e1806b17ed129ac50f5d2aa3
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/94149
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
This commit is contained in:
Miklos Vajna 2020-05-13 17:59:34 +02:00
parent cbc9c1ef72
commit 2abe9837de
7 changed files with 75 additions and 8 deletions

View file

@ -981,17 +981,17 @@ DECLARE_OOXMLIMPORT_TEST(testFdo76803, "fdo76803.docx")
CPPUNIT_ASSERT_EQUAL(sal_uInt32(4), aPolygon.count());
CPPUNIT_ASSERT_EQUAL(double(-163), aPolygon.getB2DPoint(0).getX());
CPPUNIT_ASSERT_EQUAL(double(0), aPolygon.getB2DPoint(0).getY());
CPPUNIT_ASSERT_EQUAL(double(-162), aPolygon.getB2DPoint(0).getX());
CPPUNIT_ASSERT_EQUAL(double(-35), aPolygon.getB2DPoint(0).getY());
CPPUNIT_ASSERT_EQUAL(double(-163), aPolygon.getB2DPoint(1).getX());
CPPUNIT_ASSERT_EQUAL(double(3661), aPolygon.getB2DPoint(1).getY());
CPPUNIT_ASSERT_EQUAL(double(-162), aPolygon.getB2DPoint(1).getX());
CPPUNIT_ASSERT_EQUAL(double(3510), aPolygon.getB2DPoint(1).getY());
CPPUNIT_ASSERT_EQUAL(double(16987), aPolygon.getB2DPoint(2).getX());
CPPUNIT_ASSERT_EQUAL(double(3661), aPolygon.getB2DPoint(2).getY());
CPPUNIT_ASSERT_EQUAL(double(16892), aPolygon.getB2DPoint(2).getX());
CPPUNIT_ASSERT_EQUAL(double(3510), aPolygon.getB2DPoint(2).getY());
CPPUNIT_ASSERT_EQUAL(double(16987), aPolygon.getB2DPoint(3).getX());
CPPUNIT_ASSERT_EQUAL(double(0), aPolygon.getB2DPoint(3).getY());
CPPUNIT_ASSERT_EQUAL(double(16892), aPolygon.getB2DPoint(3).getX());
CPPUNIT_ASSERT_EQUAL(double(-35), aPolygon.getB2DPoint(3).getY());
}
DECLARE_OOXMLIMPORT_TEST(testUnbalancedColumnsCompat, "unbalanced-columns-compat.docx")

View file

@ -25,6 +25,7 @@ $(eval $(call gb_CppunitTest_add_exception_objects,writerfilter_dmapper, \
))
$(eval $(call gb_CppunitTest_use_libraries,writerfilter_dmapper, \
basegfx \
comphelper \
cppu \
oox \

View file

@ -15,6 +15,9 @@
#include <com/sun/star/frame/Desktop.hpp>
#include <com/sun/star/container/XNamed.hpp>
#include <com/sun/star/text/RelOrientation.hpp>
#include <com/sun/star/drawing/PointSequenceSequence.hpp>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
using namespace ::com::sun::star;
@ -134,6 +137,33 @@ CPPUNIT_TEST_FIXTURE(Test, testRelfromhInsidemargin)
xShape->getPropertyValue("PageToggle") >>= bPageToggle;
CPPUNIT_ASSERT(bPageToggle);
}
CPPUNIT_TEST_FIXTURE(Test, testWrapPolyCrop)
{
OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "wrap-poly-crop.docx";
getComponent() = loadFromDesktop(aURL);
uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(getComponent(), uno::UNO_QUERY);
uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
uno::Reference<beans::XPropertySet> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY);
drawing::PointSequenceSequence aContour;
xShape->getPropertyValue("ContourPolyPolygon") >>= aContour;
auto aPolyPolygon = basegfx::utils::UnoPointSequenceSequenceToB2DPolyPolygon(aContour);
CPPUNIT_ASSERT_EQUAL(sal_uInt32(1), aPolyPolygon.count());
auto aPolygon = aPolyPolygon.getB2DPolygon(0);
CPPUNIT_ASSERT_EQUAL(sal_uInt32(4), aPolygon.count());
// Ideally this would be 2352, because the graphic size in mm100, using the graphic's DPI is
// 10582, the lower 33% of the graphic is cropped, and the wrap polygon covers the middle third
// of the area vertically. Which means 10582*2/3 = 7054.67 is the cropped height, and the top of
// the middle third is 2351.55.
//
// Without the accompanying fix in place, this test would have failed with:
// - Expected: 2361
// - Actual : 3542
// i.e. the wrap polygon covered a larger-than-correct area, which end the end means 3 lines
// were wrapping around the image, not only 2 as Word does it.
CPPUNIT_ASSERT_EQUAL(2361., aPolygon.getB2DPoint(0).getY());
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View file

@ -1404,6 +1404,17 @@ uno::Reference<text::XTextContent> GraphicImport::createGraphicObject(uno::Refer
pCorrected = m_pImpl->mpWrapPolygon->correctWordWrapPolygonPixel(aGraphicSize);
}
}
text::GraphicCrop aGraphicCrop;
xShapeProps->getPropertyValue("GraphicCrop") >>= aGraphicCrop;
if (aGraphicCrop.Top != 0 || aGraphicCrop.Bottom != 0 || aGraphicCrop.Left != 0
|| aGraphicCrop.Right != 0)
{
// Word's wrap polygon deals with a canvas which has the size of the already
// cropped graphic, correct our polygon to have the same render result.
pCorrected = pCorrected->correctCrop(aGraphicSize, aGraphicCrop);
}
if (pCorrected)
{
aContourPolyPolygon <<= pCorrected->getPointSequenceSequence();

View file

@ -18,6 +18,7 @@
*/
#include <com/sun/star/drawing/PointSequence.hpp>
#include <com/sun/star/text/GraphicCrop.hpp>
#include <comphelper/sequence.hxx>
#include <ooxml/resourceids.hxx>
@ -135,6 +136,23 @@ WrapPolygon::Pointer_t WrapPolygon::correctWordWrapPolygonPixel(const awt::Size
return pResult;
}
WrapPolygon::Pointer_t WrapPolygon::correctCrop(const awt::Size& rGraphicSize,
const text::GraphicCrop& rGraphicCrop)
{
WrapPolygon::Pointer_t pResult;
Fraction aScaleX(rGraphicSize.Width - rGraphicCrop.Left - rGraphicCrop.Right,
rGraphicSize.Width);
Fraction aScaleY(rGraphicSize.Height - rGraphicCrop.Top - rGraphicCrop.Bottom,
rGraphicSize.Height);
pResult = scale(aScaleX, aScaleY);
awt::Point aMove(rGraphicCrop.Left, rGraphicCrop.Top);
pResult = pResult->move(aMove);
return pResult;
}
drawing::PointSequenceSequence WrapPolygon::getPointSequenceSequence() const
{
drawing::PointSequenceSequence aPolyPolygon(1);

View file

@ -25,6 +25,11 @@
#include <tools/fract.hxx>
#include <vector>
namespace com::sun::star::text
{
struct GraphicCrop;
}
namespace writerfilter {
namespace dmapper {
@ -51,6 +56,8 @@ public:
WrapPolygon::Pointer_t scale(const Fraction & rFractionX, const Fraction & rFractionY);
WrapPolygon::Pointer_t correctWordWrapPolygon(const css::awt::Size & rSrcSize);
WrapPolygon::Pointer_t correctWordWrapPolygonPixel(const css::awt::Size & rSrcSize);
WrapPolygon::Pointer_t correctCrop(const css::awt::Size& rGraphicSize,
const css::text::GraphicCrop& rGraphicCrop);
css::drawing::PointSequenceSequence getPointSequenceSequence() const;
};