vcl/inc/pdf/pdfwriter_impl.hxx | 2 ++ vcl/source/gdi/pdfextoutdevdata.cxx | 14 +++++++++++++- vcl/source/gdi/pdfwriter_impl.cxx | 19 +++++++++++++++++-- 3 files changed, 32 insertions(+), 3 deletions(-)
New commits: commit d4d471fc88fe4fd14f44dfccdfe360dec327d4f0 Author: Michael Stahl <[email protected]> AuthorDate: Fri Mar 24 20:29:06 2023 +0100 Commit: Caolán McNamara <[email protected]> CommitDate: Tue Mar 28 12:29:42 2023 +0000 tdf#152234 vcl: PDF/UA export: StructElem<->Annot for form controls veraPDF complains: Specification: ISO 14289-1:2014, Clause: 7.18.4, Test number: 1 A Widget annotation shall be nested within a Form tag per ISO 32000-1:2008, 14.8.4.5, Table 340. This is a little simpler than for Link and Screen annotations, because the form control StructElem and Annot are exported at the same time from VclMetafileProcessor2D::processControlPrimitive2D(). So PDFExtOutDevData can just make up the mapping on playback. Change-Id: Idacb84a3e414f45a2598ccb33b252205cb2bcde9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149556 Tested-by: Jenkins Reviewed-by: Michael Stahl <[email protected]> (cherry picked from commit d9031bd83ffe718a80da9ecbdbeb485e35fbabee) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149603 Reviewed-by: Caolán McNamara <[email protected]> diff --git a/vcl/inc/pdf/pdfwriter_impl.hxx b/vcl/inc/pdf/pdfwriter_impl.hxx index e46088bca912..ece9fa3ac6df 100644 --- a/vcl/inc/pdf/pdfwriter_impl.hxx +++ b/vcl/inc/pdf/pdfwriter_impl.hxx @@ -525,6 +525,8 @@ struct PDFWidget : public PDFAnnotation std::vector<sal_Int32> m_aSelectedEntries; typedef std::unordered_map<OString, SvMemoryStream*> PDFAppearanceStreams; std::unordered_map<OString, PDFAppearanceStreams> m_aAppearances; + sal_Int32 m_nStructParent = -1; + PDFWidget() : m_eType( PDFWriter::PushButton ), m_nTextStyle( DrawTextFlags::NONE ), diff --git a/vcl/source/gdi/pdfextoutdevdata.cxx b/vcl/source/gdi/pdfextoutdevdata.cxx index 5dfcc5b19d6e..21f340fc2107 100644 --- a/vcl/source/gdi/pdfextoutdevdata.cxx +++ b/vcl/source/gdi/pdfextoutdevdata.cxx @@ -97,6 +97,10 @@ struct GlobalSyncData sal_Int32 GetMappedId(); sal_Int32 GetMappedStructId( sal_Int32 ); + /** the way this appears to work: (only) everything that increments mCurId + at recording time must put an item into mParaIds at playback time, + so that the mCurId becomes the eventual index into mParaIds. + */ sal_Int32 mCurId; std::vector< sal_Int32 > mParaIds; std::vector< sal_Int32 > mStructIdMap; @@ -410,7 +414,14 @@ bool PageSyncData::PlaySyncPageAct( PDFWriter& rWriter, sal_uInt32& rCurGDIMtfAc std::shared_ptr< PDFWriter::AnyWidget > pControl( mControls.front() ); SAL_WARN_IF( !pControl, "vcl", "PageSyncData::PlaySyncPageAct: invalid widget!" ); if ( pControl ) - rWriter.CreateControl( *pControl ); + { + sal_Int32 const n = rWriter.CreateControl(*pControl); + // resolve AnnotIds structural attribute + ::std::vector<sal_Int32> const annotIds{ sal_Int32(mpGlobalData->mParaIds.size()) }; + rWriter.SetStructureAnnotIds(annotIds); + rWriter.SetLinkPropertyID(n, sal_Int32(mpGlobalData->mParaIds.size())); + mpGlobalData->mParaIds.push_back(n); + } mControls.pop_front(); } break; @@ -849,6 +860,7 @@ void PDFExtOutDevData::CreateControl( const PDFWriter::AnyWidget& rControlType ) std::shared_ptr< PDFWriter::AnyWidget > pClone( rControlType.Clone() ); mpPageSyncData->mControls.push_back( pClone ); + mpGlobalSyncData->mCurId++; } void PDFExtOutDevData::BeginGroup() diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index 8cf4b34b6519..3ce03d88f734 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -2247,8 +2247,16 @@ sal_Int32 PDFWriterImpl::emitStructure( PDFStructureElement& rEle ) auto const it(m_aLinkPropertyMap.find(id)); assert(it != m_aLinkPropertyMap.end()); - assert(0 <= it->second && o3tl::make_unsigned(it->second) < m_aScreens.size()); - AppendAnnotKid(rEle, m_aScreens[it->second]); + if (rEle.m_eType == PDFWriter::Form) + { + assert(0 <= it->second && o3tl::make_unsigned(it->second) < m_aWidgets.size()); + AppendAnnotKid(rEle, m_aWidgets[it->second]); + } + else + { + assert(0 <= it->second && o3tl::make_unsigned(it->second) < m_aScreens.size()); + AppendAnnotKid(rEle, m_aScreens[it->second]); + } } } if( ! rEle.m_aKids.empty() ) @@ -4649,6 +4657,13 @@ bool PDFWriterImpl::emitWidgetAnnotations() iRectMargin = 1; } + if (0 < rWidget.m_nStructParent) + { + aLine.append("/StructParent "); + aLine.append(rWidget.m_nStructParent); + aLine.append("\n"); + } + aLine.append("/Rect[" ); appendFixedInt( rWidget.m_aRect.Left()-iRectMargin, aLine ); aLine.append( ' ' );
