summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <michael.stahl@allotropia.de>2023-10-11 19:13:53 +0200
committerMichael Stahl <michael.stahl@allotropia.de>2023-10-12 11:54:51 +0200
commitd5c19ef9d30cde052e8cd2486ac9395e62d9c9a9 (patch)
treeaa143345d82cc29f47fd861ffc9ca854c6a00487
parent2e32aa1e9fc240c9cd9854655106d0decbd3694a (diff)
drawinglayer,svx: PDF/UA export: put Form SE into anchor paragraph SE
This is like commit d467f1aa3d028f399826c97e2eecedcd79efcf65 and commit 6e5d59c2ca6969e9491f97cd7a00d094fc62cfb3 but for the form controls, which have their own special ControlPrimitive2D. Change-Id: I4b4ac45e81f490a7b625acd9e8753300d10bf119 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157847 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
-rw-r--r--drawinglayer/source/primitive2d/controlprimitive2d.cxx4
-rw-r--r--drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx20
-rw-r--r--include/drawinglayer/primitive2d/controlprimitive2d.hxx8
-rw-r--r--svx/source/sdr/contact/viewcontactofunocontrol.cxx9
-rw-r--r--svx/source/sdr/contact/viewobjectcontactofunocontrol.cxx10
-rw-r--r--vcl/qa/cppunit/pdfexport/pdfexport.cxx63
6 files changed, 109 insertions, 5 deletions
diff --git a/drawinglayer/source/primitive2d/controlprimitive2d.cxx b/drawinglayer/source/primitive2d/controlprimitive2d.cxx
index 372fb61244a0..c8448efa981f 100644
--- a/drawinglayer/source/primitive2d/controlprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/controlprimitive2d.cxx
@@ -243,10 +243,12 @@ namespace drawinglayer::primitive2d
uno::Reference< awt::XControlModel > xControlModel,
uno::Reference<awt::XControl> xXControl,
::std::u16string_view const rTitle,
- ::std::u16string_view const rDescription)
+ ::std::u16string_view const rDescription,
+ void const*const pAnchorKey)
: maTransform(std::move(aTransform)),
mxControlModel(std::move(xControlModel)),
mxXControl(std::move(xXControl))
+ , m_pAnchorStructureElementKey(pAnchorKey)
{
::rtl::OUStringBuffer buf(rTitle);
if (!rTitle.empty() && !rDescription.empty())
diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
index d87c70c7e772..084cc0bef17e 100644
--- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
@@ -1102,6 +1102,18 @@ void VclMetafileProcessor2D::processControlPrimitive2D(
if (!bIsPrintableControl)
return;
+ ::std::optional<sal_Int32> oAnchorParent;
+ if (mpPDFExtOutDevData)
+ {
+ if (rControlPrimitive.GetAnchorStructureElementKey())
+ {
+ sal_Int32 const id = mpPDFExtOutDevData->EnsureStructureElement(
+ rControlPrimitive.GetAnchorStructureElementKey());
+ oAnchorParent.emplace(mpPDFExtOutDevData->GetCurrentStructureElement());
+ mpPDFExtOutDevData->SetCurrentStructureElement(id);
+ }
+ }
+
const bool bPDFExport(mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportFormFields());
bool bDoProcessRecursively(true);
@@ -1154,6 +1166,10 @@ void VclMetafileProcessor2D::processControlPrimitive2D(
}
mpPDFExtOutDevData->CreateControl(*pPDFControl);
mpPDFExtOutDevData->EndStructureElement();
+ if (oAnchorParent)
+ {
+ mpPDFExtOutDevData->SetCurrentStructureElement(*oAnchorParent);
+ }
// no normal paint needed (see original UnoControlPDFExportContact::do_PaintObject);
// do not process recursively
@@ -1236,6 +1252,10 @@ void VclMetafileProcessor2D::processControlPrimitive2D(
if (mpPDFExtOutDevData)
{
mpPDFExtOutDevData->EndStructureElement();
+ if (oAnchorParent)
+ {
+ mpPDFExtOutDevData->SetCurrentStructureElement(*oAnchorParent);
+ }
}
}
diff --git a/include/drawinglayer/primitive2d/controlprimitive2d.hxx b/include/drawinglayer/primitive2d/controlprimitive2d.hxx
index e33c26886cd9..a7128b7f7322 100644
--- a/include/drawinglayer/primitive2d/controlprimitive2d.hxx
+++ b/include/drawinglayer/primitive2d/controlprimitive2d.hxx
@@ -58,6 +58,9 @@ private:
/// yet another special snowflake way to generate PDF Alt text
OUString m_AltText;
+ /// anchor structure element (Writer)
+ void const* const m_pAnchorStructureElementKey;
+
/** used from getXControl() to create a local awt::XControl which is remembered in mxXControl
and from thereon always used and returned by getXControl()
*/
@@ -81,7 +84,8 @@ public:
ControlPrimitive2D(basegfx::B2DHomMatrix aTransform,
css::uno::Reference<css::awt::XControlModel> xControlModel,
css::uno::Reference<css::awt::XControl> xXControl,
- ::std::u16string_view rTitle, ::std::u16string_view rDescription);
+ ::std::u16string_view rTitle, ::std::u16string_view rDescription,
+ void const* pAnchorKey);
/// data read access
const basegfx::B2DHomMatrix& getTransform() const { return maTransform; }
@@ -98,6 +102,8 @@ public:
OUString const& GetAltText() const { return m_AltText; }
+ void const* GetAnchorStructureElementKey() const { return m_pAnchorStructureElementKey; }
+
/// compare operator
virtual bool operator==(const BasePrimitive2D& rPrimitive) const override;
diff --git a/svx/source/sdr/contact/viewcontactofunocontrol.cxx b/svx/source/sdr/contact/viewcontactofunocontrol.cxx
index cc14ae06ad5e..3018551d8175 100644
--- a/svx/source/sdr/contact/viewcontactofunocontrol.cxx
+++ b/svx/source/sdr/contact/viewcontactofunocontrol.cxx
@@ -106,6 +106,12 @@ namespace sdr::contact {
if(xControlModel.is())
{
+ void const* pAnchorKey(nullptr);
+ if (auto const pUserCall = GetSdrObject().GetUserCall())
+ {
+ pAnchorKey = pUserCall->GetPDFAnchorStructureElementKey(GetSdrObject());
+ }
+
// create control primitive WITHOUT possibly existing XControl; this would be done in
// the VOC in createPrimitive2DSequence()
const drawinglayer::primitive2d::Primitive2DReference xRetval(
@@ -114,7 +120,8 @@ namespace sdr::contact {
xControlModel,
nullptr,
GetSdrObject().GetTitle(),
- GetSdrObject().GetDescription()));
+ GetSdrObject().GetDescription(),
+ pAnchorKey));
rVisitor.visit(xRetval);
}
diff --git a/svx/source/sdr/contact/viewobjectcontactofunocontrol.cxx b/svx/source/sdr/contact/viewobjectcontactofunocontrol.cxx
index 27eddc715420..e5292b1515d5 100644
--- a/svx/source/sdr/contact/viewobjectcontactofunocontrol.cxx
+++ b/svx/source/sdr/contact/viewobjectcontactofunocontrol.cxx
@@ -1564,12 +1564,18 @@ namespace sdr::contact {
return;
}
+ SdrObject const& rSdrObj(m_pVOCImpl->getViewContact().GetSdrObject());
+ void const* pAnchorKey(nullptr);
+ if (auto const pUserCall = rSdrObj.GetUserCall())
+ {
+ pAnchorKey = pUserCall->GetPDFAnchorStructureElementKey(rSdrObj);
+ }
+
// create a primitive and hand over the existing xControl. This will
// allow the primitive to not need to create another one on demand.
rContainer.push_back( new ::drawinglayer::primitive2d::ControlPrimitive2D(
m_aTransformation, xControlModel, rControl.getControl(),
- m_pVOCImpl->getViewContact().GetSdrObject().GetTitle(),
- m_pVOCImpl->getViewContact().GetSdrObject().GetDescription()) );
+ rSdrObj.GetTitle(), rSdrObj.GetDescription(), pAnchorKey) );
}
sal_uInt32 LazyControlCreationPrimitive2D::getPrimitive2DID() const
diff --git a/vcl/qa/cppunit/pdfexport/pdfexport.cxx b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
index 801a890c6c0b..0cec8d4bdeee 100644
--- a/vcl/qa/cppunit/pdfexport/pdfexport.cxx
+++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
@@ -4604,6 +4604,69 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf157397)
CPPUNIT_ASSERT_EQUAL(static_cast<decltype(nMCID)>(1), nMCID);
CPPUNIT_ASSERT_EQUAL(static_cast<decltype(nRef)>(1), nRef);
}
+
+ auto pRefKid16 = dynamic_cast<vcl::filter::PDFReferenceElement*>(pKids1v[6]);
+ CPPUNIT_ASSERT(pRefKid16);
+ auto pObject16 = pRefKid16->LookupObject();
+ CPPUNIT_ASSERT(pObject16);
+ auto pType16 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject16->Lookup("Type"));
+ CPPUNIT_ASSERT_EQUAL(OString("StructElem"), pType16->GetValue());
+ auto pS16 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject16->Lookup("S"));
+ CPPUNIT_ASSERT_EQUAL(OString("Text#20body"), pS16->GetValue());
+
+ auto pKids16 = dynamic_cast<vcl::filter::PDFArrayElement*>(pObject16->Lookup("K"));
+ CPPUNIT_ASSERT(pKids16);
+ // assume there are no MCID ref at this level
+ auto pKids16v = pKids16->GetElements();
+ auto pRefKid160 = dynamic_cast<vcl::filter::PDFReferenceElement*>(pKids16v[0]);
+ CPPUNIT_ASSERT(pRefKid160);
+ auto pObject160 = pRefKid160->LookupObject();
+ CPPUNIT_ASSERT(pObject160);
+ auto pType160 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject160->Lookup("Type"));
+ CPPUNIT_ASSERT_EQUAL(OString("StructElem"), pType160->GetValue());
+ auto pS160 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject160->Lookup("S"));
+ CPPUNIT_ASSERT_EQUAL(OString("Form"), pS160->GetValue());
+ auto pA160 = dynamic_cast<vcl::filter::PDFReferenceElement*>(pObject160->Lookup("A"));
+ CPPUNIT_ASSERT(pA160);
+ auto pA160Obj = pA160->LookupObject();
+ auto pA160O = dynamic_cast<vcl::filter::PDFNameElement*>(pA160Obj->Lookup("O"));
+ CPPUNIT_ASSERT(pA160O);
+ CPPUNIT_ASSERT_EQUAL(OString("PrintField"), pA160O->GetValue());
+ auto pA160Role = dynamic_cast<vcl::filter::PDFNameElement*>(pA160Obj->Lookup("Role"));
+ CPPUNIT_ASSERT(pA160Role);
+ CPPUNIT_ASSERT_EQUAL(OString("tv"), pA160Role->GetValue());
+
+ {
+ auto pKids = dynamic_cast<vcl::filter::PDFArrayElement*>(pObject160->Lookup("K"));
+ auto nMCID(0);
+ auto nRef(0);
+ for (size_t i = 0; i < pKids->GetElements().size(); ++i)
+ {
+ auto pNum = dynamic_cast<vcl::filter::PDFNumberElement*>(pKids->GetElement(i));
+ auto pRef = dynamic_cast<vcl::filter::PDFReferenceElement*>(pKids->GetElement(i));
+ if (pNum)
+ {
+ ++nMCID;
+ }
+ if (pRef)
+ {
+ ++nRef;
+ auto pObjR = pRef->LookupObject();
+ auto pOType = dynamic_cast<vcl::filter::PDFNameElement*>(pObjR->Lookup("Type"));
+ CPPUNIT_ASSERT_EQUAL(OString("OBJR"), pOType->GetValue());
+ auto pAnnotRef
+ = dynamic_cast<vcl::filter::PDFReferenceElement*>(pObjR->Lookup("Obj"));
+ auto pAnnot = pAnnotRef->LookupObject();
+ auto pAType = dynamic_cast<vcl::filter::PDFNameElement*>(pAnnot->Lookup("Type"));
+ CPPUNIT_ASSERT_EQUAL(OString("Annot"), pAType->GetValue());
+ auto pASubtype
+ = dynamic_cast<vcl::filter::PDFNameElement*>(pAnnot->Lookup("Subtype"));
+ CPPUNIT_ASSERT_EQUAL(OString("Widget"), pASubtype->GetValue());
+ }
+ }
+ CPPUNIT_ASSERT_EQUAL(static_cast<decltype(nMCID)>(1), nMCID);
+ CPPUNIT_ASSERT_EQUAL(static_cast<decltype(nRef)>(1), nRef);
+ }
}
CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf135192)