diff options
-rw-r--r-- | emfio/inc/mtftools.hxx | 5 | ||||
-rw-r--r-- | emfio/qa/cppunit/emf/EmfImportTest.cxx | 15 | ||||
-rw-r--r-- | emfio/source/reader/emfreader.cxx | 3 | ||||
-rw-r--r-- | emfio/source/reader/mtftools.cxx | 9 | ||||
-rw-r--r-- | filter/source/pdf/pdfdecomposer.cxx | 2 | ||||
-rw-r--r-- | include/vcl/pdfread.hxx | 6 | ||||
-rw-r--r-- | vcl/source/filter/ipdf/pdfread.cxx | 31 | ||||
-rw-r--r-- | vcl/source/gdi/vectorgraphicdata.cxx | 2 |
8 files changed, 62 insertions, 11 deletions
diff --git a/emfio/inc/mtftools.hxx b/emfio/inc/mtftools.hxx index 5c0c60973350..70471b66ea21 100644 --- a/emfio/inc/mtftools.hxx +++ b/emfio/inc/mtftools.hxx @@ -441,6 +441,7 @@ namespace emfio BitmapEx aBmpEx; tools::Rectangle aOutRect; sal_uInt32 nWinRop; + bool m_bForceAlpha = false; BSaveStruct(const Bitmap& rBmp, const tools::Rectangle& rOutRect, sal_uInt32 nRop) : aBmpEx(rBmp) @@ -448,10 +449,12 @@ namespace emfio , nWinRop(nRop) {} - BSaveStruct(const BitmapEx& rBmpEx, const tools::Rectangle& rOutRect, sal_uInt32 nRop) + BSaveStruct(const BitmapEx& rBmpEx, const tools::Rectangle& rOutRect, sal_uInt32 nRop, + bool bForceAlpha = false) : aBmpEx(rBmpEx) , aOutRect(rOutRect) , nWinRop(nRop) + , m_bForceAlpha(bForceAlpha) {} }; diff --git a/emfio/qa/cppunit/emf/EmfImportTest.cxx b/emfio/qa/cppunit/emf/EmfImportTest.cxx index 9d3364693530..45894455141e 100644 --- a/emfio/qa/cppunit/emf/EmfImportTest.cxx +++ b/emfio/qa/cppunit/emf/EmfImportTest.cxx @@ -26,6 +26,7 @@ #include <drawinglayer/primitive2d/baseprimitive2d.hxx> #include <drawinglayer/tools/primitive2dxmldump.hxx> +#include <vcl/bitmapaccess.hxx> #include <memory> @@ -243,6 +244,20 @@ void Test::TestPdfInEmf() // i.e. there was no size hint, the shape with 14cm height had a bitmap-from-PDF fill, the PDF // height was only 5cm, so it looked blurry. CPPUNIT_ASSERT_EQUAL(14321.0, pVectorGraphicData->getSizeHint().getY()); + +#if !defined(WNT) && !defined(MACOSX) + // Hmm, manual testing on Windows looks OK. + BitmapEx aBitmapEx = aGraphic.GetBitmapEx(); + AlphaMask aMask = aBitmapEx.GetAlpha(); + Bitmap::ScopedReadAccess pAccess(aMask); + Color aColor(pAccess->GetPixel(0, 0)); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 220 + // - Actual : 0 + // i.e. the pixel at the top left corner was entirely opaque, while it should be mostly + // transparent. + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(220), aColor.GetBlue()); +#endif } CPPUNIT_TEST_SUITE_REGISTRATION(Test); diff --git a/emfio/source/reader/emfreader.cxx b/emfio/source/reader/emfreader.cxx index b47d0c86496f..1bc6339ff897 100644 --- a/emfio/source/reader/emfreader.cxx +++ b/emfio/source/reader/emfreader.cxx @@ -507,7 +507,8 @@ namespace emfio // ours. aGraphic.getVectorGraphicData()->setSizeHint(maSizeHint); - maBmpSaveList.emplace_back(new BSaveStruct(aGraphic.GetBitmapEx(), aOutputRect, SRCCOPY)); + maBmpSaveList.emplace_back( + new BSaveStruct(aGraphic.GetBitmapEx(), aOutputRect, SRCCOPY, /*bForceAlpha=*/true)); const std::shared_ptr<VectorGraphicData> pVectorGraphicData = aGraphic.getVectorGraphicData(); if (!pVectorGraphicData) diff --git a/emfio/source/reader/mtftools.cxx b/emfio/source/reader/mtftools.cxx index e32b0f2be502..7cd1ff58093d 100644 --- a/emfio/source/reader/mtftools.cxx +++ b/emfio/source/reader/mtftools.cxx @@ -1837,7 +1837,14 @@ namespace emfio { if ( nRasterOperation == 0x33 ) aBitmap.Invert(); - ImplDrawBitmap( aPos, aSize, BitmapEx(aBitmap) ); + if (pSave->m_bForceAlpha) + { + ImplDrawBitmap(aPos, aSize, pSave->aBmpEx); + } + else + { + ImplDrawBitmap(aPos, aSize, BitmapEx(aBitmap)); + } } break; diff --git a/filter/source/pdf/pdfdecomposer.cxx b/filter/source/pdf/pdfdecomposer.cxx index a7f11cc6588e..d1e89ccdc7b4 100644 --- a/filter/source/pdf/pdfdecomposer.cxx +++ b/filter/source/pdf/pdfdecomposer.cxx @@ -67,7 +67,7 @@ uno::Sequence<uno::Reference<graphic::XPrimitive2D>> SAL_CALL XPdfDecomposer::ge if (nPageIndex < 0) nPageIndex = 0; - std::vector<Bitmap> aBitmaps; + std::vector<BitmapEx> aBitmaps; int rv = vcl::RenderPDFBitmaps(xPdfData.getConstArray(), xPdfData.getLength(), aBitmaps, nPageIndex, 1); if (rv == 0) diff --git a/include/vcl/pdfread.hxx b/include/vcl/pdfread.hxx index 78bc4a305aed..b693c432302b 100644 --- a/include/vcl/pdfread.hxx +++ b/include/vcl/pdfread.hxx @@ -30,9 +30,9 @@ class Bitmap; namespace vcl { /// Fills the rBitmaps vector with rendered pages. -VCL_DLLPUBLIC size_t RenderPDFBitmaps(const void* pBuffer, int nSize, std::vector<Bitmap>& rBitmaps, - size_t nFirstPage = 0, int nPages = 1, - const basegfx::B2DTuple* pSizeHint = nullptr); +VCL_DLLPUBLIC size_t RenderPDFBitmaps(const void* pBuffer, int nSize, + std::vector<BitmapEx>& rBitmaps, size_t nFirstPage = 0, + int nPages = 1, const basegfx::B2DTuple* pSizeHint = nullptr); /// Imports a PDF stream into rGraphic as VectorGraphicData. VCL_DLLPUBLIC bool ImportPDF(SvStream& rStream, Graphic& rGraphic); diff --git a/vcl/source/filter/ipdf/pdfread.cxx b/vcl/source/filter/ipdf/pdfread.cxx index bb9b91e97702..f9d367002f2e 100644 --- a/vcl/source/filter/ipdf/pdfread.cxx +++ b/vcl/source/filter/ipdf/pdfread.cxx @@ -130,7 +130,7 @@ VectorGraphicDataArray createVectorGraphicDataArray(SvStream& rStream) namespace vcl { -size_t RenderPDFBitmaps(const void* pBuffer, int nSize, std::vector<Bitmap>& rBitmaps, +size_t RenderPDFBitmaps(const void* pBuffer, int nSize, std::vector<BitmapEx>& rBitmaps, const size_t nFirstPage, int nPages, const basegfx::B2DTuple* pSizeHint) { #if HAVE_FEATURE_PDFIUM @@ -171,27 +171,52 @@ size_t RenderPDFBitmaps(const void* pBuffer, int nSize, std::vector<Bitmap>& rBi if (!pPdfBitmap) break; - const FPDF_DWORD nColor = pPdfPage->hasTransparency() ? 0x00000000 : 0xFFFFFFFF; + bool bTransparent = pPdfPage->hasTransparency(); + if (pSizeHint) + { + // This is the PDF-in-EMF case: force transparency, even in case pdfium would tell us + // the PDF is not transparent. + bTransparent = true; + } + const FPDF_DWORD nColor = bTransparent ? 0x00000000 : 0xFFFFFFFF; FPDFBitmap_FillRect(pPdfBitmap->getPointer(), 0, 0, nPageWidth, nPageHeight, nColor); FPDF_RenderPageBitmap(pPdfBitmap->getPointer(), pPdfPage->getPointer(), /*start_x=*/0, /*start_y=*/0, nPageWidth, nPageHeight, /*rotate=*/0, /*flags=*/0); // Save the buffer as a bitmap. Bitmap aBitmap(Size(nPageWidth, nPageHeight), 24); + AlphaMask aMask(Size(nPageWidth, nPageHeight)); { BitmapScopedWriteAccess pWriteAccess(aBitmap); + AlphaScopedWriteAccess pMaskAccess(aMask); const auto pPdfBuffer = static_cast<ConstScanline>(FPDFBitmap_GetBuffer(pPdfBitmap->getPointer())); const int nStride = FPDFBitmap_GetStride(pPdfBitmap->getPointer()); + std::vector<sal_uInt8> aScanlineAlpha(nPageWidth); for (size_t nRow = 0; nRow < nPageHeight; ++nRow) { ConstScanline pPdfLine = pPdfBuffer + (nStride * nRow); // pdfium byte order is BGRA. pWriteAccess->CopyScanline(nRow, pPdfLine, ScanlineFormat::N32BitTcBgra, nStride); + for (size_t nCol = 0; nCol < nPageWidth; ++nCol) + { + // Invert alpha (source is alpha, target is opacity). + aScanlineAlpha[nCol] = ~pPdfLine[3]; + pPdfLine += 4; + } + pMaskAccess->CopyScanline(nRow, aScanlineAlpha.data(), ScanlineFormat::N8BitPal, + nPageWidth); } } - rBitmaps.emplace_back(std::move(aBitmap)); + if (bTransparent) + { + rBitmaps.emplace_back(aBitmap, aMask); + } + else + { + rBitmaps.emplace_back(std::move(aBitmap)); + } } return rBitmaps.size(); diff --git a/vcl/source/gdi/vectorgraphicdata.cxx b/vcl/source/gdi/vectorgraphicdata.cxx index d0d1e3ca6412..6d5dc6e87768 100644 --- a/vcl/source/gdi/vectorgraphicdata.cxx +++ b/vcl/source/gdi/vectorgraphicdata.cxx @@ -146,7 +146,7 @@ void VectorGraphicData::ensurePdfReplacement() return; // nothing to do // use PDFium directly - std::vector<Bitmap> aBitmaps; + std::vector<BitmapEx> aBitmaps; sal_Int32 nUsePageIndex = 0; if (mnPageIndex >= 0) nUsePageIndex = mnPageIndex; |