drawinglayer,svx: PDF/UA export: put Form SE into anchor paragraph SE
This is like commitd467f1aa3d
and commit6e5d59c2ca
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>
This commit is contained in:
@@ -243,10 +243,12 @@ namespace drawinglayer::primitive2d
|
|||||||
uno::Reference< awt::XControlModel > xControlModel,
|
uno::Reference< awt::XControlModel > xControlModel,
|
||||||
uno::Reference<awt::XControl> xXControl,
|
uno::Reference<awt::XControl> xXControl,
|
||||||
::std::u16string_view const rTitle,
|
::std::u16string_view const rTitle,
|
||||||
::std::u16string_view const rDescription)
|
::std::u16string_view const rDescription,
|
||||||
|
void const*const pAnchorKey)
|
||||||
: maTransform(std::move(aTransform)),
|
: maTransform(std::move(aTransform)),
|
||||||
mxControlModel(std::move(xControlModel)),
|
mxControlModel(std::move(xControlModel)),
|
||||||
mxXControl(std::move(xXControl))
|
mxXControl(std::move(xXControl))
|
||||||
|
, m_pAnchorStructureElementKey(pAnchorKey)
|
||||||
{
|
{
|
||||||
::rtl::OUStringBuffer buf(rTitle);
|
::rtl::OUStringBuffer buf(rTitle);
|
||||||
if (!rTitle.empty() && !rDescription.empty())
|
if (!rTitle.empty() && !rDescription.empty())
|
||||||
|
@@ -1102,6 +1102,18 @@ void VclMetafileProcessor2D::processControlPrimitive2D(
|
|||||||
if (!bIsPrintableControl)
|
if (!bIsPrintableControl)
|
||||||
return;
|
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());
|
const bool bPDFExport(mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportFormFields());
|
||||||
bool bDoProcessRecursively(true);
|
bool bDoProcessRecursively(true);
|
||||||
|
|
||||||
@@ -1154,6 +1166,10 @@ void VclMetafileProcessor2D::processControlPrimitive2D(
|
|||||||
}
|
}
|
||||||
mpPDFExtOutDevData->CreateControl(*pPDFControl);
|
mpPDFExtOutDevData->CreateControl(*pPDFControl);
|
||||||
mpPDFExtOutDevData->EndStructureElement();
|
mpPDFExtOutDevData->EndStructureElement();
|
||||||
|
if (oAnchorParent)
|
||||||
|
{
|
||||||
|
mpPDFExtOutDevData->SetCurrentStructureElement(*oAnchorParent);
|
||||||
|
}
|
||||||
|
|
||||||
// no normal paint needed (see original UnoControlPDFExportContact::do_PaintObject);
|
// no normal paint needed (see original UnoControlPDFExportContact::do_PaintObject);
|
||||||
// do not process recursively
|
// do not process recursively
|
||||||
@@ -1236,6 +1252,10 @@ void VclMetafileProcessor2D::processControlPrimitive2D(
|
|||||||
if (mpPDFExtOutDevData)
|
if (mpPDFExtOutDevData)
|
||||||
{
|
{
|
||||||
mpPDFExtOutDevData->EndStructureElement();
|
mpPDFExtOutDevData->EndStructureElement();
|
||||||
|
if (oAnchorParent)
|
||||||
|
{
|
||||||
|
mpPDFExtOutDevData->SetCurrentStructureElement(*oAnchorParent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -58,6 +58,9 @@ private:
|
|||||||
/// yet another special snowflake way to generate PDF Alt text
|
/// yet another special snowflake way to generate PDF Alt text
|
||||||
OUString m_AltText;
|
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
|
/** used from getXControl() to create a local awt::XControl which is remembered in mxXControl
|
||||||
and from thereon always used and returned by getXControl()
|
and from thereon always used and returned by getXControl()
|
||||||
*/
|
*/
|
||||||
@@ -81,7 +84,8 @@ public:
|
|||||||
ControlPrimitive2D(basegfx::B2DHomMatrix aTransform,
|
ControlPrimitive2D(basegfx::B2DHomMatrix aTransform,
|
||||||
css::uno::Reference<css::awt::XControlModel> xControlModel,
|
css::uno::Reference<css::awt::XControlModel> xControlModel,
|
||||||
css::uno::Reference<css::awt::XControl> xXControl,
|
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
|
/// data read access
|
||||||
const basegfx::B2DHomMatrix& getTransform() const { return maTransform; }
|
const basegfx::B2DHomMatrix& getTransform() const { return maTransform; }
|
||||||
@@ -98,6 +102,8 @@ public:
|
|||||||
|
|
||||||
OUString const& GetAltText() const { return m_AltText; }
|
OUString const& GetAltText() const { return m_AltText; }
|
||||||
|
|
||||||
|
void const* GetAnchorStructureElementKey() const { return m_pAnchorStructureElementKey; }
|
||||||
|
|
||||||
/// compare operator
|
/// compare operator
|
||||||
virtual bool operator==(const BasePrimitive2D& rPrimitive) const override;
|
virtual bool operator==(const BasePrimitive2D& rPrimitive) const override;
|
||||||
|
|
||||||
|
@@ -106,6 +106,12 @@ namespace sdr::contact {
|
|||||||
|
|
||||||
if(xControlModel.is())
|
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
|
// create control primitive WITHOUT possibly existing XControl; this would be done in
|
||||||
// the VOC in createPrimitive2DSequence()
|
// the VOC in createPrimitive2DSequence()
|
||||||
const drawinglayer::primitive2d::Primitive2DReference xRetval(
|
const drawinglayer::primitive2d::Primitive2DReference xRetval(
|
||||||
@@ -114,7 +120,8 @@ namespace sdr::contact {
|
|||||||
xControlModel,
|
xControlModel,
|
||||||
nullptr,
|
nullptr,
|
||||||
GetSdrObject().GetTitle(),
|
GetSdrObject().GetTitle(),
|
||||||
GetSdrObject().GetDescription()));
|
GetSdrObject().GetDescription(),
|
||||||
|
pAnchorKey));
|
||||||
|
|
||||||
rVisitor.visit(xRetval);
|
rVisitor.visit(xRetval);
|
||||||
}
|
}
|
||||||
|
@@ -1564,12 +1564,18 @@ namespace sdr::contact {
|
|||||||
return;
|
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
|
// create a primitive and hand over the existing xControl. This will
|
||||||
// allow the primitive to not need to create another one on demand.
|
// allow the primitive to not need to create another one on demand.
|
||||||
rContainer.push_back( new ::drawinglayer::primitive2d::ControlPrimitive2D(
|
rContainer.push_back( new ::drawinglayer::primitive2d::ControlPrimitive2D(
|
||||||
m_aTransformation, xControlModel, rControl.getControl(),
|
m_aTransformation, xControlModel, rControl.getControl(),
|
||||||
m_pVOCImpl->getViewContact().GetSdrObject().GetTitle(),
|
rSdrObj.GetTitle(), rSdrObj.GetDescription(), pAnchorKey) );
|
||||||
m_pVOCImpl->getViewContact().GetSdrObject().GetDescription()) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sal_uInt32 LazyControlCreationPrimitive2D::getPrimitive2DID() const
|
sal_uInt32 LazyControlCreationPrimitive2D::getPrimitive2DID() const
|
||||||
|
@@ -4604,6 +4604,69 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf157397)
|
|||||||
CPPUNIT_ASSERT_EQUAL(static_cast<decltype(nMCID)>(1), nMCID);
|
CPPUNIT_ASSERT_EQUAL(static_cast<decltype(nMCID)>(1), nMCID);
|
||||||
CPPUNIT_ASSERT_EQUAL(static_cast<decltype(nRef)>(1), nRef);
|
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)
|
CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf135192)
|
||||||
|
Reference in New Issue
Block a user