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; + } } } }