include/svx/annotation/Annotation.hxx          |    4 +
 include/vcl/filter/PDFiumLibrary.hxx           |    3 +
 include/vcl/pdf/PDFAnnotationMarker.hxx        |    7 ++
 sd/source/filter/pdf/sdpdffilter.cxx           |    8 +++
 sd/source/ui/annotations/annotationmanager.cxx |   13 +++++
 vcl/source/filter/ipdf/pdfread.cxx             |   21 +++++++-
 vcl/source/pdf/PDFiumLibrary.cxx               |   64 +++++++++++++++++++++++++
 7 files changed, 119 insertions(+), 1 deletion(-)

New commits:
commit 6490cf00f733d620a4f224197b478a6100df0fb7
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Thu Jun 13 14:25:21 2024 +0900
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Tue Jun 18 12:21:58 2024 +0200

    annot: add support to import Stamp annotation from PDF
    
    Stamp annotation shows an arbitrary bitmap in the document, where
    the most common bitmaps are stamps like "Approved", "Confidential",
    "Expired", "Sold",...
    
    Change-Id: I332e34cbb346a686ee16eac7ca437ec4048e65ed
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168760
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>
    (cherry picked from commit 66a68fcb5639c3f0e42385fcdb08f16b9c96f243)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168844
    Tested-by: Miklos Vajna <vmik...@collabora.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/include/svx/annotation/Annotation.hxx 
b/include/svx/annotation/Annotation.hxx
index 6464d96c8ce2..8ffaad3f0997 100644
--- a/include/svx/annotation/Annotation.hxx
+++ b/include/svx/annotation/Annotation.hxx
@@ -22,6 +22,7 @@
 #include <cppuhelper/basemutex.hxx>
 #include <svx/annotation/Annotation.hxx>
 #include <svx/annotation/TextAPI.hxx>
+#include <vcl/bitmapex.hxx>
 
 class SdrUndoAction;
 class SfxViewShell;
@@ -57,6 +58,7 @@ enum class AnnotationType
     Highlight,
     Line,
     FreeText,
+    Stamp
 };
 
 /** Annotation data that is used at annotation creation */
@@ -74,6 +76,8 @@ struct CreationInfo
 
     bool mbColor = false;
     Color maColor = COL_TRANSPARENT;
+
+    BitmapEx maBitmapEx;
 };
 
 /** Data of an annotation */
diff --git a/include/vcl/filter/PDFiumLibrary.hxx 
b/include/vcl/filter/PDFiumLibrary.hxx
index 3c087cf7b11c..d90da7286020 100644
--- a/include/vcl/filter/PDFiumLibrary.hxx
+++ b/include/vcl/filter/PDFiumLibrary.hxx
@@ -37,6 +37,7 @@
 #include <vcl/pdf/PDFAnnotAActionType.hxx>
 
 class SvMemoryStream;
+class BitmapEx;
 
 namespace vcl::pdf
 {
@@ -80,6 +81,8 @@ public:
     virtual int getWidth() = 0;
     virtual int getHeight() = 0;
     virtual PDFBitmapType getFormat() = 0;
+    /// Convert the bitmap buffer to a BitmapEx
+    virtual BitmapEx createBitmapFromBuffer() = 0;
 };
 
 class VCL_DLLPUBLIC PDFiumAnnotation
diff --git a/include/vcl/pdf/PDFAnnotationMarker.hxx 
b/include/vcl/pdf/PDFAnnotationMarker.hxx
index 3be2e6c8ca3d..d1217c65c3af 100644
--- a/include/vcl/pdf/PDFAnnotationMarker.hxx
+++ b/include/vcl/pdf/PDFAnnotationMarker.hxx
@@ -14,6 +14,7 @@
 #include <tools/color.hxx>
 #include <basegfx/polygon/b2dpolygon.hxx>
 #include <basegfx/point/b2dpoint.hxx>
+#include <vcl/bitmapex.hxx>
 
 namespace vcl::pdf
 {
@@ -27,6 +28,12 @@ struct VCL_DLLPUBLIC PDFAnnotationMarker
     Color maFillColor = COL_TRANSPARENT;
 };
 
+/** Stamp annotation marker - arbitrary bitmap as annotation */
+struct VCL_DLLPUBLIC PDFAnnotationMarkerStamp : public PDFAnnotationMarker
+{
+    BitmapEx maBitmapEx;
+};
+
 /** Free text annotation marker - showing text of the annotation in the 
document */
 struct VCL_DLLPUBLIC PDFAnnotationMarkerFreeText : public PDFAnnotationMarker
 {
diff --git a/sd/source/filter/pdf/sdpdffilter.cxx 
b/sd/source/filter/pdf/sdpdffilter.cxx
index 6b69530454c3..58e2dfead82f 100644
--- a/sd/source/filter/pdf/sdpdffilter.cxx
+++ b/sd/source/filter/pdf/sdpdffilter.cxx
@@ -210,6 +210,14 @@ bool SdPdfFilter::Import()
                 {
                     aInfo.meType = sdr::annotation::AnnotationType::FreeText;
                 }
+                else if (rPDFAnnotation.meSubType == 
vcl::pdf::PDFAnnotationSubType::Stamp)
+                {
+                    auto* pMarker = 
static_cast<vcl::pdf::PDFAnnotationMarkerStamp*>(
+                        rPDFAnnotation.mpMarker.get());
+
+                    aInfo.meType = sdr::annotation::AnnotationType::Stamp;
+                    aInfo.maBitmapEx = pMarker->maBitmapEx;
+                }
 
                 xAnnotation->setCreationInfo(aInfo);
             }
diff --git a/sd/source/ui/annotations/annotationmanager.cxx 
b/sd/source/ui/annotations/annotationmanager.cxx
index 98a79f902478..67f356884725 100644
--- a/sd/source/ui/annotations/annotationmanager.cxx
+++ b/sd/source/ui/annotations/annotationmanager.cxx
@@ -82,6 +82,7 @@
 #include <svx/svdorect.hxx>
 #include <svx/svdopath.hxx>
 #include <svx/svdotext.hxx>
+#include <svx/svdograf.hxx>
 
 #include <svx/xfillit0.hxx>
 #include <svx/xflclit.hxx>
@@ -1070,6 +1071,18 @@ void AnnotationManagerImpl::SyncAnnotationObjects()
             applyAnnotationCommon(*pNewObject, xAnnotation);
             applyAnnotationProperties(*pNewObject, rInfo);
         }
+        else if (rInfo.meType == sdr::annotation::AnnotationType::Stamp)
+        {
+            pNewObject = new SdrCircObj(rModel, SdrCircKind::Full, aRectangle);
+
+            rtl::Reference<SdrGrafObj> pGrafObject = new SdrGrafObj(rModel, 
Graphic(rInfo.maBitmapEx), aRectangle);
+            pNewObject = pGrafObject;
+
+            applyAnnotationCommon(*pNewObject, xAnnotation);
+
+            
pGrafObject->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
+            
pGrafObject->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
+        }
         else
         {
             SdrObjKind ekind = SdrObjKind::Polygon;
diff --git a/vcl/source/filter/ipdf/pdfread.cxx 
b/vcl/source/filter/ipdf/pdfread.cxx
index c19a6939b486..b2e97a519ed5 100644
--- a/vcl/source/filter/ipdf/pdfread.cxx
+++ b/vcl/source/filter/ipdf/pdfread.cxx
@@ -182,7 +182,8 @@ findAnnotations(const 
std::unique_ptr<vcl::pdf::PDFiumPage>& pPage, basegfx::B2D
                 || eSubtype == vcl::pdf::PDFAnnotationSubType::Square
                 || eSubtype == vcl::pdf::PDFAnnotationSubType::Ink
                 || eSubtype == vcl::pdf::PDFAnnotationSubType::Highlight
-                || eSubtype == vcl::pdf::PDFAnnotationSubType::Line)
+                || eSubtype == vcl::pdf::PDFAnnotationSubType::Line
+                || eSubtype == vcl::pdf::PDFAnnotationSubType::Stamp)
             {
                 OUString sAuthor = 
pAnnotation->getString(vcl::pdf::constDictionaryKeyTitle);
                 OUString sText = 
pAnnotation->getString(vcl::pdf::constDictionaryKeyContents);
@@ -330,6 +331,24 @@ findAnnotations(const 
std::unique_ptr<vcl::pdf::PDFiumPage>& pPage, basegfx::B2D
                     auto pMarker = 
std::make_shared<vcl::pdf::PDFAnnotationMarkerFreeText>();
                     rPDFGraphicAnnotation.mpMarker = pMarker;
                 }
+                else if (eSubtype == vcl::pdf::PDFAnnotationSubType::Stamp)
+                {
+                    auto pMarker = 
std::make_shared<vcl::pdf::PDFAnnotationMarkerStamp>();
+                    rPDFGraphicAnnotation.mpMarker = pMarker;
+
+                    auto nObjects = pAnnotation->getObjectCount();
+
+                    for (int nIndex = 0; nIndex < nObjects; nIndex++)
+                    {
+                        auto pPageObject = pAnnotation->getObject(nIndex);
+                        if (pPageObject->getType() == 
vcl::pdf::PDFPageObjectType::Image)
+                        {
+                            std::unique_ptr<vcl::pdf::PDFiumBitmap> pBitmap
+                                = pPageObject->getImageBitmap();
+                            pMarker->maBitmapEx = 
pBitmap->createBitmapFromBuffer();
+                        }
+                    }
+                }
             }
         }
     }
diff --git a/vcl/source/pdf/PDFiumLibrary.cxx b/vcl/source/pdf/PDFiumLibrary.cxx
index 553be738c8f5..4c3872979d1d 100644
--- a/vcl/source/pdf/PDFiumLibrary.cxx
+++ b/vcl/source/pdf/PDFiumLibrary.cxx
@@ -28,6 +28,8 @@
 #include <o3tl/string_view.hxx>
 
 #include <vcl/BitmapWriteAccess.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/dibtools.hxx>
 
 using namespace com::sun::star;
 
@@ -214,6 +216,7 @@ public:
     int getWidth() override;
     int getHeight() override;
     PDFBitmapType getFormat() override;
+    BitmapEx createBitmapFromBuffer() override;
 };
 
 class PDFiumPathSegmentImpl final : public PDFiumPathSegment
@@ -1097,6 +1100,67 @@ PDFBitmapType PDFiumBitmapImpl::getFormat()
     return static_cast<PDFBitmapType>(FPDFBitmap_GetFormat(mpBitmap));
 }
 
+BitmapEx PDFiumBitmapImpl::createBitmapFromBuffer()
+{
+    BitmapEx aBitmapEx;
+
+    const vcl::pdf::PDFBitmapType eFormat = getFormat();
+    if (eFormat == vcl::pdf::PDFBitmapType::Unknown)
+        return aBitmapEx;
+
+    const int nWidth = getWidth();
+    const int nHeight = getHeight();
+    const int nStride = getStride();
+
+    switch (eFormat)
+    {
+        case vcl::pdf::PDFBitmapType::BGR:
+        {
+            aBitmapEx = BitmapEx(Size(nWidth, nHeight), 
vcl::PixelFormat::N24_BPP);
+            ReadRawDIB(aBitmapEx, getBuffer(), ScanlineFormat::N24BitTcBgr, 
nHeight, nStride);
+        }
+        break;
+
+        case vcl::pdf::PDFBitmapType::BGRx:
+        {
+            aBitmapEx = BitmapEx(Size(nWidth, nHeight), 
vcl::PixelFormat::N24_BPP);
+            ReadRawDIB(aBitmapEx, getBuffer(), ScanlineFormat::N32BitTcRgba, 
nHeight, nStride);
+        }
+        break;
+
+        case vcl::pdf::PDFBitmapType::BGRA:
+        {
+            Bitmap aBitmap(Size(nWidth, nHeight), vcl::PixelFormat::N24_BPP);
+            AlphaMask aMask(Size(nWidth, nHeight));
+            {
+                BitmapScopedWriteAccess pWriteAccess(aBitmap);
+                BitmapScopedWriteAccess pMaskAccess(aMask);
+                ConstScanline pBuffer = getBuffer();
+                std::vector<sal_uInt8> aScanlineAlpha(nWidth);
+                for (int nRow = 0; nRow < nHeight; ++nRow)
+                {
+                    ConstScanline pLine = pBuffer + (nStride * nRow);
+                    pWriteAccess->CopyScanline(nRow, pLine, 
ScanlineFormat::N32BitTcBgra, nStride);
+                    for (int nCol = 0; nCol < nWidth; ++nCol)
+                    {
+                        aScanlineAlpha[nCol] = pLine[3];
+                        pLine += 4;
+                    }
+                    pMaskAccess->CopyScanline(nRow, aScanlineAlpha.data(), 
ScanlineFormat::N8BitPal,
+                                              nWidth);
+                }
+            }
+            aBitmapEx = BitmapEx(aBitmap, aMask);
+        }
+        break;
+
+        default:
+            break;
+    }
+
+    return aBitmapEx;
+}
+
 PDFiumAnnotationImpl::PDFiumAnnotationImpl(FPDF_ANNOTATION pAnnotation)
     : mpAnnotation(pAnnotation)
 {

Reply via email to