drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx |    1 
 include/vcl/pdfwriter.hxx                                  |   16 +++--
 sw/source/core/text/EnhancedPDFExportHelper.cxx            |   11 +++
 vcl/source/gdi/pdfwriter_impl.cxx                          |   37 ++++++++++---
 4 files changed, 51 insertions(+), 14 deletions(-)

New commits:
commit daae11a2ce060ee370ca98850ed1c69dfc32f5ce
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Fri Jan 10 13:19:09 2025 +0900
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Thu Feb 6 13:05:56 2025 +0100

    pdf: add PDF 2.0 support for /Title structure element
    
    Add support to PDF export to handle /Title structure element and
    fallback to /P (paragraph) if the PDF version is not PDF 2.0.
    Then add /Title structure element in writer if the style name of
    the paragraph is "Title".
    
    Change-Id: Ia8faab09bf3c97423d154deb7f1eb69860ce857a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180122
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180878
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>

diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx 
b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
index e2129f53f654..ccfcfdc136fb 100644
--- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
@@ -2580,6 +2580,7 @@ void 
VclMetafileProcessor2D::processStructureTagPrimitive2D(
                 case vcl::pdf::StructElement::H6:
                 case vcl::pdf::StructElement::Paragraph:
                 case vcl::pdf::StructElement::Heading:
+                case vcl::pdf::StructElement::Title:
                 case vcl::pdf::StructElement::Caption:
                 case vcl::pdf::StructElement::BlockQuote:
                 case vcl::pdf::StructElement::Table:
diff --git a/include/vcl/pdfwriter.hxx b/include/vcl/pdfwriter.hxx
index dc72cb5c44e8..92c3fa28ad39 100644
--- a/include/vcl/pdfwriter.hxx
+++ b/include/vcl/pdfwriter.hxx
@@ -155,26 +155,30 @@ struct PDFEncryptionProperties
 
 namespace pdf
 {
-// for a definition of structural element types please refer to
-// PDF Reference, 3rd ed. section 9.7.4
+// For a definition of structural element types please refer to
+// PDF Reference, 3rd ed. section 9.7.4.
+//
+// In PDF 2.0 specification (ISO 32000-2) refer to section 14.8.4
 enum class StructElement
 {
-    // special element to place outside the structure hierarchy
+    // Special element to place outside the structure hierarchy
     NonStructElement,
+
     // Grouping elements
     Document, Part, Article, Section, Division, BlockQuote,
     Caption, TOC, TOCI, Index,
 
-    // block level elements
+    // Block level elements
     Paragraph, Heading, H1, H2, H3, H4, H5, H6,
     List, ListItem, LILabel, LIBody,
     Table, TableRow, TableHeader, TableData,
+    Title, // PDF 2.0
 
-    // inline level elements
+    // Inline level elements
     Span, Quote, Note, Reference, BibEntry, Code, Link, Annot,
     Ruby, RB, RT, RP, Warichu, WT, WP,
 
-    // illustration elements
+    // Illustration elements
     Figure, Formula, Form
 };
 
diff --git a/sw/source/core/text/EnhancedPDFExportHelper.cxx 
b/sw/source/core/text/EnhancedPDFExportHelper.cxx
index d95a26bc1941..58be893db3af 100644
--- a/sw/source/core/text/EnhancedPDFExportHelper.cxx
+++ b/sw/source/core/text/EnhancedPDFExportHelper.cxx
@@ -175,6 +175,7 @@ const char aCaption[]           = "Caption";
 const char aHeading[]           = "Heading";
 const char aQuotation[]         = "Quotation";
 const char aSourceText[]        = "Source Text";
+constexpr OUString constTitleStyleName = u"Title"_ustr;
 
 // PDF Tag Names:
 constexpr OUStringLiteral aDocumentString = u"Document";
@@ -717,7 +718,7 @@ void 
SwTaggedPDFHelper::SetAttributes(vcl::pdf::StructElement eType)
             case vcl::pdf::StructElement::Paragraph:
             case vcl::pdf::StructElement::Heading:
             case vcl::pdf::StructElement::BlockQuote:
-
+            case vcl::pdf::StructElement::Title:
                 bPlacement =
                 bWritingMode =
                 bSpaceBefore =
@@ -1424,6 +1425,14 @@ void SwTaggedPDFHelper::BeginBlockStructureElements()
                 nPDFType = sal_uInt16(vcl::pdf::StructElement::Paragraph);
                 aPDFType = sStyleName;
 
+                // Title
+
+                if (sStyleName == constTitleStyleName)
+                {
+                    nPDFType = sal_uInt16(vcl::pdf::StructElement::Title);
+                    aPDFType = constTitleStyleName;
+                }
+
                 // Quotations: BlockQuote
 
                 if (sStyleName == aQuotations)
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx 
b/vcl/source/gdi/pdfwriter_impl.cxx
index 264d4ed6d5da..5e632421eeb5 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -10698,7 +10698,7 @@ void PDFWriterImpl::setOutlineItemDest( sal_Int32 
nItem, sal_Int32 nDestID )
     m_aOutline[nItem].m_nDestID = nDestID;
 }
 
-const char* PDFWriterImpl::getStructureTag(vcl::pdf::StructElement eType )
+const char* PDFWriterImpl::getStructureTag(vcl::pdf::StructElement eType)
 {
     using namespace vcl::pdf;
 
@@ -10747,18 +10747,35 @@ const char* 
PDFWriterImpl::getStructureTag(vcl::pdf::StructElement eType )
         { StructElement::WP,          "WP" },
         { StructElement::Figure,      "Figure" },
         { StructElement::Formula,     "Formula"},
-        { StructElement::Form,        "Form" }
+        { StructElement::Form,        "Form" },
+        { StructElement::Title,       "Title" },
     });
 
-    if (eType == StructElement::Annot
-        && m_aContext.Version < PDFWriter::PDFVersion::PDF_1_5)
+    // First handle fallbacks for elements that were added in a certain PDF 
version
+
+    // PDF 1.5 fallbacks
+    if (m_aContext.Version < PDFWriter::PDFVersion::PDF_1_5 && eType == 
StructElement::Annot)
+        eType = StructElement::Figure;
+
+    // PDF 2.0 fallbacks
+    if (m_aContext.Version < PDFWriter::PDFVersion::PDF_2_0)
     {
-        return "Figure"; // fallback
+        switch(eType)
+        {
+            case StructElement::Title:
+                eType = StructElement::Paragraph;
+                break;
+            default:
+                break;
+        }
     }
 
-    auto it = aTagStrings.find( eType );
+    auto it = aTagStrings.find(eType);
+
+    if (it == aTagStrings.end())
+        return "Div";
 
-    return it != aTagStrings.end() ? it->second : "Div";
+    return it->second;
 }
 
 void PDFWriterImpl::addRoleMap(OString aAlias, vcl::pdf::StructElement eType)
@@ -11260,6 +11277,7 @@ bool PDFWriterImpl::setStructureAttribute( enum 
PDFWriter::StructAttribute eAttr
                     eVal == PDFWriter::Justify )
                 {
                     if (eType == vcl::pdf::StructElement::Paragraph   ||
+                        eType == vcl::pdf::StructElement::Title ||
                         eType == vcl::pdf::StructElement::Heading     ||
                         eType == vcl::pdf::StructElement::H1          ||
                         eType == vcl::pdf::StructElement::H2          ||
@@ -11326,6 +11344,7 @@ bool PDFWriterImpl::setStructureAttribute( enum 
PDFWriter::StructAttribute eAttr
                 {
                     // only for ILSE and BLSE
                     if (eType == vcl::pdf::StructElement::Paragraph   ||
+                        eType == vcl::pdf::StructElement::Title ||
                         eType == vcl::pdf::StructElement::Heading     ||
                         eType == vcl::pdf::StructElement::H1          ||
                         eType == vcl::pdf::StructElement::H2          ||
@@ -11361,6 +11380,7 @@ bool PDFWriterImpl::setStructureAttribute( enum 
PDFWriter::StructAttribute eAttr
                 {
                     // only for ILSE and BLSE
                     if (eType == vcl::pdf::StructElement::Paragraph   ||
+                        eType == vcl::pdf::StructElement::Title ||
                         eType == vcl::pdf::StructElement::Heading     ||
                         eType == vcl::pdf::StructElement::H1          ||
                         eType == vcl::pdf::StructElement::H2          ||
@@ -11504,6 +11524,7 @@ bool PDFWriterImpl::setStructureAttributeNumerical( 
enum PDFWriter::StructAttrib
             case PDFWriter::EndIndent:
                 // just for BLSE
                 if (eType == vcl::pdf::StructElement::Paragraph   ||
+                    eType == vcl::pdf::StructElement::Title ||
                     eType == vcl::pdf::StructElement::Heading     ||
                     eType == vcl::pdf::StructElement::H1          ||
                     eType == vcl::pdf::StructElement::H2          ||
@@ -11526,6 +11547,7 @@ bool PDFWriterImpl::setStructureAttributeNumerical( 
enum PDFWriter::StructAttrib
             case PDFWriter::TextIndent:
                 // paragraph like BLSE and additional elements
                 if (eType == vcl::pdf::StructElement::Paragraph   ||
+                    eType == vcl::pdf::StructElement::Title ||
                     eType == vcl::pdf::StructElement::Heading     ||
                     eType == vcl::pdf::StructElement::H1          ||
                     eType == vcl::pdf::StructElement::H2          ||
@@ -11557,6 +11579,7 @@ bool PDFWriterImpl::setStructureAttributeNumerical( 
enum PDFWriter::StructAttrib
             case PDFWriter::BaselineShift:
                 // only for ILSE and BLSE
                 if (eType == vcl::pdf::StructElement::Paragraph   ||
+                    eType == vcl::pdf::StructElement::Title ||
                     eType == vcl::pdf::StructElement::Heading     ||
                     eType == vcl::pdf::StructElement::H1          ||
                     eType == vcl::pdf::StructElement::H2          ||

Reply via email to