[Libreoffice-commits] core.git: emfio/inc emfio/qa emfio/source filter/source include/vcl vcl/source

Miklos Vajna (via logerrit) logerrit at kemper.freedesktop.org
Tue Oct 27 10:21:42 UTC 2020


 emfio/inc/mtftools.hxx                 |    5 ++++-
 emfio/qa/cppunit/emf/EmfImportTest.cxx |   15 +++++++++++++++
 emfio/source/reader/emfreader.cxx      |    3 ++-
 emfio/source/reader/mtftools.cxx       |    9 ++++++++-
 filter/source/pdf/pdfdecomposer.cxx    |    2 +-
 include/vcl/pdfread.hxx                |    6 +++---
 vcl/source/filter/ipdf/pdfread.cxx     |   31 ++++++++++++++++++++++++++++---
 vcl/source/gdi/vectorgraphicdata.cxx   |    2 +-
 8 files changed, 62 insertions(+), 11 deletions(-)

New commits:
commit 4a35c118a3a6b954827953674cc9bad435c394ee
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Mon Oct 26 21:16:28 2020 +0100
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Tue Oct 27 11:20:46 2020 +0100

    tdf#137413 EMF import: fix transparency in the PDF fallback case
    
    Commit d75c5b38911557173c54a78f42ff220ab3918573 (tdf#136836 emfio: speed
    up import of EMF import when the orig PDF is available, 2020-09-17)
    improved both performance and correctness of the EMF import, in case it
    had a PDF fallback.
    
    It turns out that PDF fallback can be nominally non-transparent, and
    still the EMF equivalent supports transparency.
    
    Fix the problem by enabling transparency in the PDF-in-EMF case.
    
    Change-Id: I4d1585a5db6f28bd9c9cb380b5f193f4d5edcc8d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/104849
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>
    Tested-by: Jenkins

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;


More information about the Libreoffice-commits mailing list