take into account clipping for pdf graphics

at least for graphics that are entirely clipped out.

Change-Id: I2e8b15209a8a0e2e6777601b8d853ad323e5828e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193116
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
This commit is contained in:
Caolán McNamara
2025-10-29 16:13:16 +01:00
parent c995322f64
commit 68c5c606bc
4 changed files with 91 additions and 0 deletions
Binary file not shown.
+30
View File
@@ -1185,6 +1185,36 @@ CPPUNIT_TEST_FIXTURE(SdExportTest, testExplodedPdfGrayscaleImageUnderInvisibleTe
CPPUNIT_ASSERT_MESSAGE("Shape should be Invisible", !bVisible);
}
CPPUNIT_TEST_FIXTURE(SdExportTest, testExplodedPdfClippedImages)
{
auto pPdfium = vcl::pdf::PDFiumLibrary::get();
if (!pPdfium)
return;
UsePdfium aGuard;
loadFromFile(u"pdf/ClippedImages.pdf");
setFilterOptions("{\"DecomposePDF\":{\"type\":\"boolean\",\"value\":\"true\"}}");
setImportFilterName(u"OpenDocument Drawing Flat XML"_ustr);
saveAndReload(u"OpenDocument Drawing Flat XML"_ustr);
uno::Reference<drawing::XShapes> xGroupShape(getShapeFromPage(0, 0), uno::UNO_QUERY);
CPPUNIT_ASSERT(xGroupShape.is());
uno::Reference<beans::XPropertySet> xGraphicShape1(xGroupShape->getByIndex(0), uno::UNO_QUERY);
CPPUNIT_ASSERT(xGraphicShape1.is());
bool bVisible(true);
xGraphicShape1->getPropertyValue(u"Visible"_ustr) >>= bVisible;
CPPUNIT_ASSERT_MESSAGE("1st Graphic should be Visible", bVisible);
// before the fix the clip for this graphic wasn't taken into account so it was visiblem
// not it is detected as entirely clipped out and toggled to invisible
uno::Reference<beans::XPropertySet> xGraphicShape2(xGroupShape->getByIndex(1), uno::UNO_QUERY);
CPPUNIT_ASSERT(xGraphicShape2.is());
xGraphicShape2->getPropertyValue(u"Visible"_ustr) >>= bVisible;
CPPUNIT_ASSERT_MESSAGE("2nd Graphic should be Invisible", !bVisible);
}
CPPUNIT_TEST_FIXTURE(SdExportTest, testExplodedPdfMissingFontVersion)
{
auto pPdfium = vcl::pdf::PDFiumLibrary::get();
+4
View File
@@ -162,6 +162,10 @@ class ImpSdrPdfImport final
const std::vector<std::unique_ptr<vcl::pdf::PDFiumPathSegment>>& rPathSegments,
const basegfx::B2DHomMatrix& rPathMatrix);
basegfx::B2DPolyPolygon GetClip(const std::unique_ptr<vcl::pdf::PDFiumClipPath>& rClipPath,
const basegfx::B2DHomMatrix& rPathMatrix,
const basegfx::B2DHomMatrix& rTransform);
// #i73407# reformulation to use new B2DPolygon classes
bool CheckLastPolyLineAndFillMerge(const basegfx::B2DPolyPolygon& rPolyPolygon);
+57
View File
@@ -20,6 +20,7 @@
#include <svdpdf.hxx>
#include <tools/UnitConversion.hxx>
#include <vcl/canvastools.hxx>
#include <vcl/embeddedfontsmanager.hxx>
#include <vcl/graph.hxx>
#include <vcl/vectorgraphicdata.hxx>
@@ -55,6 +56,7 @@
#include <svx/svdetc.hxx>
#include <svl/itemset.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <tools/helpers.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
@@ -1950,6 +1952,29 @@ void ImpSdrPdfImport::MapScaling()
mnMapScalingOfs = nCount;
}
basegfx::B2DPolyPolygon
ImpSdrPdfImport::GetClip(const std::unique_ptr<vcl::pdf::PDFiumClipPath>& pClipPath,
const basegfx::B2DHomMatrix& rPathMatrix,
const basegfx::B2DHomMatrix& rTransform)
{
basegfx::B2DPolyPolygon aClipPolyPoly;
int nClipPathCount = pClipPath->getPathCount();
for (int i = 0; i < nClipPathCount; ++i)
{
std::vector<std::unique_ptr<vcl::pdf::PDFiumPathSegment>> aPathSegments;
const int nSegments = pClipPath->getPathSegmentCount(i);
for (int nSegmentIndex = 0; nSegmentIndex < nSegments; ++nSegmentIndex)
aPathSegments.push_back(pClipPath->getPathSegment(i, nSegmentIndex));
appendSegmentsToPolyPoly(aClipPolyPoly, aPathSegments, rPathMatrix);
}
aClipPolyPoly.transform(rTransform);
return aClipPolyPoly;
}
void ImpSdrPdfImport::ImportImage(std::unique_ptr<vcl::pdf::PDFiumPageObject> const& pPageObject,
int /*nPageObjectIndex*/)
{
@@ -1974,6 +1999,34 @@ void ImpSdrPdfImport::ImportImage(std::unique_ptr<vcl::pdf::PDFiumPageObject> co
float right = aBounds.getMaxX();
// Upside down.
float top = aBounds.getMaxY();
bool bEntirelyClippedOut = false;
auto aPathMatrix = pPageObject->getMatrix();
aPathMatrix *= maCurrentMatrix;
const basegfx::B2DHomMatrix aTransform(
basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
basegfx::B2DPolyPolygon aClipPolyPoly
= GetClip(pPageObject->getClipPath(), aPathMatrix, aTransform);
if (aClipPolyPoly.count())
{
// Clip against ClipRegion, use same conversions and transformation on
// the graphic bounds as were applied to the clipping polypolygon
const tools::Rectangle aRect = PointsToLogic(aBounds.getMinX(), aBounds.getMaxX(),
aBounds.getMinY(), aBounds.getMaxY());
basegfx::B2DPolyPolygon aGraphicBounds(
basegfx::utils::createPolygonFromRect(vcl::unotools::b2DRectangleFromRectangle(aRect)));
aGraphicBounds.transform(aTransform);
const basegfx::B2DPolyPolygon aClippedBounds(basegfx::utils::clipPolyPolygonOnPolyPolygon(
aGraphicBounds, aClipPolyPoly, true, false));
// completely clipped out
bEntirelyClippedOut = aClippedBounds.getB2DRange().isEmpty();
}
tools::Rectangle aRect = PointsToLogic(left, right, top, bottom);
aRect.AdjustRight(1);
aRect.AdjustBottom(1);
@@ -1984,6 +2037,10 @@ void ImpSdrPdfImport::ImportImage(std::unique_ptr<vcl::pdf::PDFiumPageObject> co
// This action is not creating line and fill, set directly, do not use SetAttributes(..)
pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
if (bEntirelyClippedOut)
pGraf->SetVisible(false);
InsertObj(pGraf.get());
}