include/svx/sdr/overlay/overlaypolypolygon.hxx | 19 +++++++++- include/vcl/pdf/PDFAnnotationMarker.hxx | 37 ++++++++++++++++++++ include/vcl/pdfread.hxx | 5 ++ sd/inc/Annotation.hxx | 31 ++++++++++++++++ sd/source/filter/pdf/sdpdffilter.cxx | 24 +++++++++++++ sd/source/ui/annotations/annotationtag.cxx | 37 ++++++++++++++++---- svx/source/sdr/overlay/overlaypolypolygon.cxx | 46 +++++++++++++++++++++++++ vcl/source/filter/ipdf/pdfread.cxx | 41 +++++++++++++++++----- 8 files changed, 224 insertions(+), 16 deletions(-)
New commits: commit 52c2b0fefcd3743c266cccb321ae194fd00720a4 Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Thu Oct 15 09:38:56 2020 +0200 Commit: Tomaž Vajngerl <qui...@gmail.com> CommitDate: Sun Oct 18 21:20:40 2020 +0200 sd: custom annotation marker and draw polygon annotation from PDF This implements custom annotation marker, which overrides the default marker drawing of comments in Draw/Impress. The polygon is transported from the import of PDF to SdPdfFilter, then the sd::Annotation is set-up, by settuing up the new class CustomAnnotationMarker. CustomAnnotationMarker also supports setting of the line color, line width and fill color. The OverlayPolyPolygon is the new class that is responsible for the marker overlay, mainly to create the Primitive2D of the marker, that will be shown on the screen. This only implements Polygon PDF annotation sub-type. Change-Id: Ic663c31c5b3db5c13179dde63c1a0b81159f4b80 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/104365 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> diff --git a/include/svx/sdr/overlay/overlaypolypolygon.hxx b/include/svx/sdr/overlay/overlaypolypolygon.hxx index 4cb5c4610a00..d3aa2074d48f 100644 --- a/include/svx/sdr/overlay/overlaypolypolygon.hxx +++ b/include/svx/sdr/overlay/overlaypolypolygon.hxx @@ -25,7 +25,24 @@ namespace sdr::overlay - { +{ + class SVXCORE_DLLPUBLIC OverlayPolyPolygon final : public OverlayObject + { + private: + basegfx::B2DPolyPolygon maLinePolyPolygon; + double mfLineWidth; + Color maFillColor; + + virtual drawinglayer::primitive2d::Primitive2DContainer createOverlayObjectPrimitive2DSequence() override; + + public: + explicit OverlayPolyPolygon(const basegfx::B2DPolyPolygon& rLinePolyPolygon, + Color const & rLineColor, + double mfLineWidth, + Color const & rFillColor); + virtual ~OverlayPolyPolygon() override; + }; + class SVXCORE_DLLPUBLIC OverlayPolyPolygonStripedAndFilled final : public OverlayObject { // geometry diff --git a/include/vcl/pdf/PDFAnnotationMarker.hxx b/include/vcl/pdf/PDFAnnotationMarker.hxx new file mode 100644 index 000000000000..2cfbeaa31111 --- /dev/null +++ b/include/vcl/pdf/PDFAnnotationMarker.hxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#pragma once + +#include <tools/color.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> + +namespace vcl::pdf +{ +struct VCL_DLLPUBLIC PDFAnnotationMarker +{ + PDFAnnotationMarker() + : mnWidth(0.0f) + , maFillColor(COL_TRANSPARENT) + { + } + + float mnWidth; + Color maFillColor; +}; + +struct VCL_DLLPUBLIC PDFAnnotationMarkerPolygon : public PDFAnnotationMarker +{ + basegfx::B2DPolygon maPolygon; +}; + +} // namespace vcl::pdf + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vcl/pdfread.hxx b/include/vcl/pdfread.hxx index bffdb104da42..78bc4a305aed 100644 --- a/include/vcl/pdfread.hxx +++ b/include/vcl/pdfread.hxx @@ -13,11 +13,13 @@ #include <vector> #include <tools/gen.hxx> #include <tools/stream.hxx> +#include <tools/color.hxx> #include <vcl/graph.hxx> #include <basegfx/range/b2drectangle.hxx> #include <com/sun/star/util/DateTime.hpp> #include <vcl/pdf/PDFAnnotationSubType.hxx> +#include <vcl/pdf/PDFAnnotationMarker.hxx> namespace com::sun::star::uno { @@ -43,7 +45,10 @@ struct PDFGraphicAnnotation basegfx::B2DRectangle maRectangle; // In HMM css::util::DateTime maDateTime; + Color maColor; + pdf::PDFAnnotationSubType meSubType; + std::shared_ptr<pdf::PDFAnnotationMarker> mpMarker; }; class PDFGraphicResult diff --git a/sd/inc/Annotation.hxx b/sd/inc/Annotation.hxx index 24eb09989aca..883512506c78 100644 --- a/sd/inc/Annotation.hxx +++ b/sd/inc/Annotation.hxx @@ -31,6 +31,10 @@ #include "drawdoc.hxx" #include "sdpage.hxx" #include "textapi.hxx" +#include "sddllapi.h" + +#include <basegfx/polygon/b2dpolygon.hxx> +#include <tools/color.hxx> class SdrUndoAction; @@ -62,7 +66,15 @@ void LOKCommentNotify(CommentNotificationType nType, const SfxViewShell* pViewSh void LOKCommentNotifyAll(CommentNotificationType nType, css::uno::Reference<css::office::XAnnotation> const & rxAnnotation); -class Annotation : private ::cppu::BaseMutex, +struct SD_DLLPUBLIC CustomAnnotationMarker +{ + Color maLineColor; + Color maFillColor; + float mnLineWidth; + std::vector<basegfx::B2DPolygon> maPolygons; +}; + +class SD_DLLPUBLIC Annotation : private ::cppu::BaseMutex, public ::cppu::WeakComponentImplHelper<css::office::XAnnotation>, public ::cppu::PropertySetMixin<css::office::XAnnotation> { @@ -107,6 +119,21 @@ public: void createChangeUndo(); + void createCustomAnnotationMarker() + { + m_pCustomAnnotationMarker = std::make_unique<CustomAnnotationMarker>(); + } + + CustomAnnotationMarker& getCustomAnnotationMarker() + { + return *m_pCustomAnnotationMarker; + } + + bool hasCustomAnnotationMarker() + { + return bool(m_pCustomAnnotationMarker); + } + private: // destructor is private and will be called indirectly by the release call virtual ~Annotation() {} @@ -124,6 +151,8 @@ private: OUString m_Initials; css::util::DateTime m_DateTime; rtl::Reference<TextApiObject> m_TextRange; + + std::unique_ptr<CustomAnnotationMarker> m_pCustomAnnotationMarker; }; } diff --git a/sd/source/filter/pdf/sdpdffilter.cxx b/sd/source/filter/pdf/sdpdffilter.cxx index 07b6cd08ff9f..a1f6100cfd19 100644 --- a/sd/source/filter/pdf/sdpdffilter.cxx +++ b/sd/source/filter/pdf/sdpdffilter.cxx @@ -19,6 +19,7 @@ #include <sal/config.h> +#include <svx/svxids.hrc> #include <sfx2/docfile.hxx> #include <svx/svdograf.hxx> @@ -29,9 +30,13 @@ #include <vcl/graph.hxx> #include <vcl/pdfread.hxx> +#include <Annotation.hxx> + #include <com/sun/star/office/XAnnotation.hpp> #include <com/sun/star/text/XText.hpp> +#include <basegfx/polygon/b2dpolygontools.hxx> + using namespace css; SdPdfFilter::SdPdfFilter(SfxMedium& rMedium, sd::DrawDocShell& rDocShell) @@ -97,6 +102,25 @@ bool SdPdfFilter::Import() xAnnotation->setPosition(aUnoPosition); xAnnotation->setSize(aUnoSize); xAnnotation->setDateTime(rPDFAnnotation.maDateTime); + + if (rPDFAnnotation.mpMarker) + { + auto* pAnnotation = static_cast<sd::Annotation*>(xAnnotation.get()); + pAnnotation->createCustomAnnotationMarker(); + sd::CustomAnnotationMarker& rCustomAnnotationMarker + = pAnnotation->getCustomAnnotationMarker(); + + rCustomAnnotationMarker.maLineColor = rPDFAnnotation.maColor; + + if (rPDFAnnotation.meSubType == vcl::pdf::PDFAnnotationSubType::Polygon) + { + auto* pMarker = static_cast<vcl::pdf::PDFAnnotationMarkerPolygon*>( + rPDFAnnotation.mpMarker.get()); + rCustomAnnotationMarker.mnLineWidth = pMarker->mnWidth; + rCustomAnnotationMarker.maFillColor = pMarker->maFillColor; + rCustomAnnotationMarker.maPolygons.push_back(pMarker->maPolygon); + } + } } } mrDocument.setLock(bWasLocked); diff --git a/sd/source/ui/annotations/annotationtag.cxx b/sd/source/ui/annotations/annotationtag.cxx index 6d918775f73d..61c8ac8b2a3d 100644 --- a/sd/source/ui/annotations/annotationtag.cxx +++ b/sd/source/ui/annotations/annotationtag.cxx @@ -28,6 +28,7 @@ #include <svx/sdr/overlay/overlayanimatedbitmapex.hxx> #include <svx/sdr/overlay/overlaybitmapex.hxx> +#include <svx/sdr/overlay/overlaypolypolygon.hxx> #include <svx/svdpagv.hxx> #include <svx/sdrpagewindow.hxx> #include <svx/sdrpaintwindow.hxx> @@ -40,6 +41,7 @@ #include "annotationmanagerimpl.hxx" #include "annotationwindow.hxx" #include "annotationtag.hxx" +#include <Annotation.hxx> #include <ViewShell.hxx> #include <Window.hxx> #include <drawdoc.hxx> @@ -182,7 +184,7 @@ void AnnotationHdl::CreateB2dIAObject() // first throw away old one GetRidOfIAObject(); - if( !mxAnnotation.is() ) + if (!mxAnnotation.is()) return; const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); @@ -221,16 +223,39 @@ void AnnotationHdl::CreateB2dIAObject() { std::unique_ptr<sdr::overlay::OverlayObject> pOverlayObject; - // animate focused handles - if(bFocused) + auto* pAnnotation = dynamic_cast<sd::Annotation*>(mxAnnotation.get()); + + if (pAnnotation && pAnnotation->hasCustomAnnotationMarker()) { - const sal_uInt64 nBlinkTime = rStyleSettings.GetCursorBlinkTime(); + CustomAnnotationMarker& rCustomAnnotationMarker = pAnnotation->getCustomAnnotationMarker(); - pOverlayObject.reset(new sdr::overlay::OverlayAnimatedBitmapEx(aPosition, aBitmapEx, aBitmapEx2, nBlinkTime, 0, 0, 0, 0 )); + auto& rPolygons = rCustomAnnotationMarker.maPolygons; + if (!rPolygons.empty()) + { + basegfx::B2DPolyPolygon aPolyPolygon; + for (auto const & rPolygon : rPolygons) + aPolyPolygon.append(rPolygon); + + pOverlayObject.reset(new sdr::overlay::OverlayPolyPolygon( + aPolyPolygon, + rCustomAnnotationMarker.maLineColor, + rCustomAnnotationMarker.mnLineWidth, + rCustomAnnotationMarker.maFillColor)); + } } else { - pOverlayObject.reset(new sdr::overlay::OverlayBitmapEx( aPosition, aBitmapEx, 0, 0 )); + // animate focused handles + if(bFocused) + { + const sal_uInt64 nBlinkTime = rStyleSettings.GetCursorBlinkTime(); + + pOverlayObject.reset(new sdr::overlay::OverlayAnimatedBitmapEx(aPosition, aBitmapEx, aBitmapEx2, nBlinkTime, 0, 0, 0, 0 )); + } + else + { + pOverlayObject.reset(new sdr::overlay::OverlayBitmapEx( aPosition, aBitmapEx, 0, 0 )); + } } // OVERLAYMANAGER diff --git a/svx/source/sdr/overlay/overlaypolypolygon.cxx b/svx/source/sdr/overlay/overlaypolypolygon.cxx index 650b6420794e..b338d171e551 100644 --- a/svx/source/sdr/overlay/overlaypolypolygon.cxx +++ b/svx/source/sdr/overlay/overlaypolypolygon.cxx @@ -21,10 +21,56 @@ #include <svx/sdr/overlay/overlaymanager.hxx> #include <drawinglayer/primitive2d/PolyPolygonMarkerPrimitive2D.hxx> #include <drawinglayer/primitive2d/PolyPolygonSelectionPrimitive2D.hxx> +#include <drawinglayer/primitive2d/PolyPolygonStrokePrimitive2D.hxx> +#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx> +#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx> namespace sdr::overlay { + OverlayPolyPolygon::OverlayPolyPolygon( + const basegfx::B2DPolyPolygon& rLinePolyPolygon, + Color const & rLineColor, + double fLineWidth, + Color const & rFillColor) + : OverlayObject(rLineColor) + , maLinePolyPolygon(rLinePolyPolygon) + , mfLineWidth(fLineWidth) + , maFillColor(rFillColor) + { + } + + OverlayPolyPolygon::~OverlayPolyPolygon() = default; + + drawinglayer::primitive2d::Primitive2DContainer OverlayPolyPolygon::createOverlayObjectPrimitive2DSequence() + { + drawinglayer::primitive2d::Primitive2DContainer aReturnContainer; + + if (getOverlayManager()) + { + const drawinglayer::attribute::LineAttribute aLineAttribute(getBaseColor().getBColor(), mfLineWidth); + + auto aLine(new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D(maLinePolyPolygon, aLineAttribute)); + + aReturnContainer = drawinglayer::primitive2d::Primitive2DContainer { aLine }; + if (maFillColor.GetTransparency() != 255) + { + auto aFill(new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(maLinePolyPolygon, maFillColor.getBColor())); + aReturnContainer.push_back(aFill); + } + + sal_Int8 nTransparency = getBaseColor().GetTransparency(); + if (nTransparency != 0) + { + const drawinglayer::primitive2d::Primitive2DReference aTransparencePrimitive( + new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(aReturnContainer, nTransparency / 255.0)); + aReturnContainer = drawinglayer::primitive2d::Primitive2DContainer{ aTransparencePrimitive }; + } + } + + return aReturnContainer; + } + drawinglayer::primitive2d::Primitive2DContainer OverlayPolyPolygonStripedAndFilled::createOverlayObjectPrimitive2DSequence() { drawinglayer::primitive2d::Primitive2DContainer aRetval; diff --git a/vcl/source/filter/ipdf/pdfread.cxx b/vcl/source/filter/ipdf/pdfread.cxx index 605ea45f8c23..856cc7864d77 100644 --- a/vcl/source/filter/ipdf/pdfread.cxx +++ b/vcl/source/filter/ipdf/pdfread.cxx @@ -254,7 +254,8 @@ findAnnotations(const std::unique_ptr<vcl::pdf::PDFiumPage>& pPage, basegfx::B2D { auto eSubtype = pAnnotation->getSubType(); - if (eSubtype == vcl::pdf::PDFAnnotationSubType::Text) + if (eSubtype == vcl::pdf::PDFAnnotationSubType::Text + || eSubtype == vcl::pdf::PDFAnnotationSubType::Polygon) { OUString sAuthor = pAnnotation->getString(vcl::pdf::constDictionaryKeyTitle); OUString sText = pAnnotation->getString(vcl::pdf::constDictionaryKeyContents); @@ -276,13 +277,37 @@ findAnnotations(const std::unique_ptr<vcl::pdf::PDFiumPage>& pPage, basegfx::B2D utl::ISO8601parseDateTime(sISO8601String, aDateTime); } - PDFGraphicAnnotation aPDFGraphicAnnotation; - aPDFGraphicAnnotation.maRectangle = rRectangleHMM; - aPDFGraphicAnnotation.maAuthor = sAuthor; - aPDFGraphicAnnotation.maText = sText; - aPDFGraphicAnnotation.maDateTime = aDateTime; - aPDFGraphicAnnotation.meSubType = eSubtype; - aPDFGraphicAnnotations.push_back(aPDFGraphicAnnotation); + Color aColor = pAnnotation->getColor(); + + aPDFGraphicAnnotations.emplace_back(); + + auto& rPDFGraphicAnnotation = aPDFGraphicAnnotations.back(); + rPDFGraphicAnnotation.maRectangle = rRectangleHMM; + rPDFGraphicAnnotation.maAuthor = sAuthor; + rPDFGraphicAnnotation.maText = sText; + rPDFGraphicAnnotation.maDateTime = aDateTime; + rPDFGraphicAnnotation.meSubType = eSubtype; + rPDFGraphicAnnotation.maColor = aColor; + + if (eSubtype == vcl::pdf::PDFAnnotationSubType::Polygon) + { + auto const& rVertices = pAnnotation->getVertices(); + if (!rVertices.empty()) + { + auto pMarker = std::make_shared<vcl::pdf::PDFAnnotationMarkerPolygon>(); + rPDFGraphicAnnotation.mpMarker = pMarker; + for (auto const& rVertex : rVertices) + { + double x = convertPointToMm100(rVertex.getX()); + double y = convertPointToMm100(aPageSize.getY() - rVertex.getY()); + pMarker->maPolygon.append({ x, y }); + } + pMarker->maPolygon.setClosed(true); + pMarker->mnWidth = convertPointToMm100(pAnnotation->getBorderWidth()); + if (pAnnotation->hasKey(vcl::pdf::constDictionaryKeyInteriorColor)) + pMarker->maFillColor = pAnnotation->getInteriorColor(); + } + } } } } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits