vcl/qa/cppunit/pdfexport/pdfexport.cxx |   45 ++++++++++-----------------------
 vcl/source/gdi/pdfwriter_impl.cxx      |   35 ++++++++++---------------
 2 files changed, 28 insertions(+), 52 deletions(-)

New commits:
commit 049f458143cbd02ab915271418625cda1299f4b1
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Tue Oct 24 15:58:14 2023 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Tue Oct 24 18:46:50 2023 +0200

    tdf#157028 vcl: PDF export: inline attribute dictionaries
    
    There seems to be no reason why SE attribute dictionaries are separate
    objects, they could just be inline, which saves a little space (1%)
    and more importantly the PDF file is easier to read with less clutter.
    
    Change-Id: Iaaea2432313c0b710edabecae32545205f4f495e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158392
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/vcl/qa/cppunit/pdfexport/pdfexport.cxx 
b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
index 8dd1a9a71fbf..70da866889aa 100644
--- a/vcl/qa/cppunit/pdfexport/pdfexport.cxx
+++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
@@ -3475,11 +3475,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf149140)
                 CPPUNIT_ASSERT(pAttrs != nullptr);
                 for (const auto& rAttrRef : pAttrs->GetElements())
                 {
-                    auto pARef = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(rAttrRef);
-                    CPPUNIT_ASSERT(pARef != nullptr);
-                    auto pAttr = pARef->LookupObject();
-                    CPPUNIT_ASSERT(pAttr != nullptr);
-                    auto pAttrDict = pAttr->GetDictionary();
+                    auto pAttrDict = 
dynamic_cast<vcl::filter::PDFDictionaryElement*>(rAttrRef);
                     CPPUNIT_ASSERT(pAttrDict != nullptr);
                     auto pOwner
                         = 
dynamic_cast<vcl::filter::PDFNameElement*>(pAttrDict->LookupElement("O"));
@@ -3841,11 +3837,8 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf135638)
             auto pS = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("S"));
             if (pS && pS->GetValue() == "Figure")
             {
-                auto pARef = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(pObject->Lookup("A"));
-                CPPUNIT_ASSERT(pARef != nullptr);
-                auto pAttr = pARef->LookupObject();
-                CPPUNIT_ASSERT(pAttr != nullptr);
-                auto pAttrDict = pAttr->GetDictionary();
+                auto pAttrDict
+                    = 
dynamic_cast<vcl::filter::PDFDictionaryElement*>(pObject->Lookup("A"));
                 CPPUNIT_ASSERT(pAttrDict != nullptr);
                 auto pOwner
                     = 
dynamic_cast<vcl::filter::PDFNameElement*>(pAttrDict->LookupElement("O"));
@@ -4398,12 +4391,8 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testSpans)
                 auto pS103101
                     = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObject103101->Lookup("S"));
                 CPPUNIT_ASSERT_EQUAL(OString("Span"), pS103101->GetValue());
-                auto pA103101
-                    = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(pObject103101->Lookup("A"));
-                CPPUNIT_ASSERT(pA103101);
-                auto pObjectA103101 = pA103101->LookupObject();
-                CPPUNIT_ASSERT(pObjectA103101);
-                auto pDictA103101 = pObjectA103101->GetDictionary();
+                auto pDictA103101
+                    = 
dynamic_cast<vcl::filter::PDFDictionaryElement*>(pObject103101->Lookup("A"));
                 CPPUNIT_ASSERT(pDictA103101 != nullptr);
                 CPPUNIT_ASSERT_EQUAL(OString("Layout"), 
dynamic_cast<vcl::filter::PDFNameElement*>(
                                                             
pDictA103101->LookupElement("O"))
@@ -4963,13 +4952,12 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf157397)
     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"));
+    auto pA160Dict = 
dynamic_cast<vcl::filter::PDFDictionaryElement*>(pObject160->Lookup("A"));
+    CPPUNIT_ASSERT(pA160Dict);
+    auto pA160O = 
dynamic_cast<vcl::filter::PDFNameElement*>(pA160Dict->LookupElement("O"));
     CPPUNIT_ASSERT(pA160O);
     CPPUNIT_ASSERT_EQUAL(OString("PrintField"), pA160O->GetValue());
-    auto pA160Role = 
dynamic_cast<vcl::filter::PDFNameElement*>(pA160Obj->Lookup("Role"));
+    auto pA160Role = 
dynamic_cast<vcl::filter::PDFNameElement*>(pA160Dict->LookupElement("Role"));
     CPPUNIT_ASSERT(pA160Role);
     CPPUNIT_ASSERT_EQUAL(OString("tv"), pA160Role->GetValue());
 
@@ -5088,13 +5076,9 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf135192)
                                                         for (const auto& 
rAttrRef :
                                                              
pAttrs->GetElements())
                                                         {
-                                                            auto pARef = 
dynamic_cast<
-                                                                
vcl::filter::PDFReferenceElement*>(
+                                                            auto pAttrDict = 
dynamic_cast<
+                                                                
vcl::filter::PDFDictionaryElement*>(
                                                                 rAttrRef);
-                                                            
CPPUNIT_ASSERT(pARef != nullptr);
-                                                            auto pAttr = 
pARef->LookupObject();
-                                                            
CPPUNIT_ASSERT(pAttr != nullptr);
-                                                            auto pAttrDict = 
pAttr->GetDictionary();
                                                             
CPPUNIT_ASSERT(pAttrDict != nullptr);
                                                             auto pOwner = 
dynamic_cast<
                                                                 
vcl::filter::PDFNameElement*>(
@@ -5726,13 +5710,12 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, 
testFormControlAnnot)
     auto pAlt = 
dynamic_cast<vcl::filter::PDFHexStringElement*>(pStructElem->Lookup("Alt"));
     CPPUNIT_ASSERT_EQUAL(OUString("textuelle alternative - a box to check"),
                          
::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAlt));
-    auto pA = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(pStructElem->Lookup("A"));
+    auto pA = 
dynamic_cast<vcl::filter::PDFDictionaryElement*>(pStructElem->Lookup("A"));
     CPPUNIT_ASSERT(pA);
-    auto pAObj = pA->LookupObject();
-    auto pO = dynamic_cast<vcl::filter::PDFNameElement*>(pAObj->Lookup("O"));
+    auto pO = 
dynamic_cast<vcl::filter::PDFNameElement*>(pA->LookupElement("O"));
     CPPUNIT_ASSERT(pO);
     CPPUNIT_ASSERT_EQUAL(OString("PrintField"), pO->GetValue());
-    auto pRole = 
dynamic_cast<vcl::filter::PDFNameElement*>(pAObj->Lookup("Role"));
+    auto pRole = 
dynamic_cast<vcl::filter::PDFNameElement*>(pA->LookupElement("Role"));
     CPPUNIT_ASSERT(pRole);
     CPPUNIT_ASSERT_EQUAL(OString("cb"), pRole->GetValue());
     auto pKids = 
dynamic_cast<vcl::filter::PDFArrayElement*>(pStructElem->Lookup("K"));
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx 
b/vcl/source/gdi/pdfwriter_impl.cxx
index 5699b2dc6ddc..677212e15d1a 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -2052,22 +2052,20 @@ OString PDFWriterImpl::emitStructureAttributes( 
PDFStructureElement& i_rEle )
         aLayout.append( "]\n" );
     }
 
-    std::vector< sal_Int32 > aAttribObjects;
+    OStringBuffer aRet(256);
+    bool isArray(false);
+    if (1 < (aLayout.isEmpty() ? 0 : 1) + (aList.isEmpty() ? 0 : 1)
+            + (aPrintField.isEmpty() ? 0 : 1) + (aTable.isEmpty() ? 0 : 1))
+    {
+        isArray = true;
+        aRet.append(" [");
+    }
     auto const WriteAttrs = [&](char const*const pName, OStringBuffer & rBuf)
     {
-        aAttribObjects.push_back( createObject() );
-        if (updateObject( aAttribObjects.back() ))
-        {
-            OStringBuffer aObj( 64 );
-            aObj.append( aAttribObjects.back() );
-            aObj.append( " 0 obj\n"
-                         "<</O");
-            aObj.append(pName);
-            aObj.append("\n");
-            rBuf.append(">>\nendobj\n\n");
-            writeBuffer(aObj);
-            writeBuffer(rBuf);
-        }
+        aRet.append(" <</O");
+        aRet.append(pName);
+        aRet.append(rBuf);
+        aRet.append(">>");
     };
     if( !aLayout.isEmpty() )
     {
@@ -2086,15 +2084,10 @@ OString PDFWriterImpl::emitStructureAttributes( 
PDFStructureElement& i_rEle )
         WriteAttrs("/Table", aTable);
     }
 
-    OStringBuffer aRet( 64 );
-    if( aAttribObjects.size() > 1 )
-        aRet.append( " [" );
-    for (auto const& attrib : aAttribObjects)
+    if (isArray)
     {
-        aRet.append( " "  + OString::number(attrib) + " 0 R" );
-    }
-    if( aAttribObjects.size() > 1 )
         aRet.append( " ]" );
+    }
     return aRet.makeStringAndClear();
 }
 

Reply via email to