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

New commits:
commit 66a68fcb5639c3f0e42385fcdb08f16b9c96f243
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Thu Jun 13 14:25:21 2024 +0900
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Fri Jun 14 04:07:21 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>

diff --git a/include/svx/annotation/Annotation.hxx 
b/include/svx/annotation/Annotation.hxx
index 436827b13fc6..f7917b608e9c 100644
--- a/include/svx/annotation/Annotation.hxx
+++ b/include/svx/annotation/Annotation.hxx
@@ -21,6 +21,7 @@
 #include <cppuhelper/propertysetmixin.hxx>
 #include <svx/annotation/Annotation.hxx>
 #include <svx/annotation/TextAPI.hxx>
+#include <vcl/bitmapex.hxx>
 
 class SdrUndoAction;
 class SfxViewShell;
@@ -56,6 +57,7 @@ enum class AnnotationType
     Highlight,
     Line,
     FreeText,
+    Stamp
 };
 
 /** Annotation data that is used at annotation creation */
@@ -73,6 +75,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 28850c0dd57c..31292315787e 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>
@@ -1067,6 +1068,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 ebd6ea0dba10..c7cf5794dffa 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)
             {
                 basegfx::B2DRectangle rRectangle = pAnnotation->getRectangle();
                 basegfx::B2DRectangle rRectangleHMM(
@@ -329,6 +330,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)
 {
commit 0fb1e4e9a74b566fb075a58ae2c7632f2cc068de
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Thu Jun 13 14:19:44 2024 +0900
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Fri Jun 14 04:07:12 2024 +0200

    annot: add annotation marker for free text annotation
    
    Added new class PDFAnnotationMarkerFreeText as we need a marker to
    know if the annotation is a special one.
    
    Change-Id: Ica0e72dd6bf62b322676c8e87659a3850074522a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168759
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>

diff --git a/include/vcl/pdf/PDFAnnotationMarker.hxx 
b/include/vcl/pdf/PDFAnnotationMarker.hxx
index c643856375b5..3be2e6c8ca3d 100644
--- a/include/vcl/pdf/PDFAnnotationMarker.hxx
+++ b/include/vcl/pdf/PDFAnnotationMarker.hxx
@@ -27,6 +27,11 @@ struct VCL_DLLPUBLIC PDFAnnotationMarker
     Color maFillColor = COL_TRANSPARENT;
 };
 
+/** Free text annotation marker - showing text of the annotation in the 
document */
+struct VCL_DLLPUBLIC PDFAnnotationMarkerFreeText : public PDFAnnotationMarker
+{
+};
+
 struct VCL_DLLPUBLIC PDFAnnotationMarkerCircle : public PDFAnnotationMarker
 {
 };
diff --git a/vcl/source/filter/ipdf/pdfread.cxx 
b/vcl/source/filter/ipdf/pdfread.cxx
index b8a6687827cb..ebd6ea0dba10 100644
--- a/vcl/source/filter/ipdf/pdfread.cxx
+++ b/vcl/source/filter/ipdf/pdfread.cxx
@@ -324,6 +324,11 @@ findAnnotations(const 
std::unique_ptr<vcl::pdf::PDFiumPage>& pPage, basegfx::B2D
                         pMarker->mnWidth = convertPointToMm100(fWidth);
                     }
                 }
+                else if (eSubtype == vcl::pdf::PDFAnnotationSubType::FreeText)
+                {
+                    auto pMarker = 
std::make_shared<vcl::pdf::PDFAnnotationMarkerFreeText>();
+                    rPDFGraphicAnnotation.mpMarker = pMarker;
+                }
             }
         }
     }

Reply via email to