drawinglayer/source/primitive2d/structuretagprimitive2d.cxx  |    7 
 drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx   |   89 ++++++-----
 drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx   |    5 
 drawinglayer/source/processor2d/vclprocessor2d.cxx           |   15 -
 drawinglayer/source/processor2d/vclprocessor2d.hxx           |   12 -
 include/drawinglayer/primitive2d/structuretagprimitive2d.hxx |    1 
 6 files changed, 68 insertions(+), 61 deletions(-)

New commits:
commit 78681cd0829dcb6a73690e1a63ae3808d297677a
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Wed Nov 23 19:08:14 2022 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Nov 25 11:47:13 2022 +0100

    tdf#57423 drawinglayer: PDF/UA export: more Alt texts for SdrObjects
    
    Currently /Alt texts are generated from ObjectInfoPrimitive2D, but this
    is only evaluated in VclMetafileProcessor2D::processGraphicPrimitive2D()
    so while it's created for every SdrObject, it's ignored in most cases.
    
    There doesn't appear to be a reason why this is done in
    processGraphicPrimitive2D() and not a more generic location, the special
    conditions that are checked there don't have anything to do with Alt
    texts, they effectively guard some optimisation done to bitmaps in
    PageSyncData::PlaySyncPageAct().
    
    There is another issue in that not every SdrObject gets a
    StructureTagPrimitive2D, and even if there is a StructureTagPrimitive2D
    it may be ignored if it's in the background.
    
    The Alt text must only be produced if there is a structure element for
    the same SdrObject, else it would end up on some unrelated structure
    element.
    
    Fix all this by moving processing to a new function which checks that
    there is a current StructureTagPrimitive2D for a SdrObject in effect.
    
    The only problem with this is that previously Writer images produced Alt
    text, and now they don't - but Writer needs some fixing anyway.
    
    Change-Id: I2a362e8a9cd93e5bc817c6eed546c46b46e14980
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143189
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/drawinglayer/source/primitive2d/structuretagprimitive2d.cxx 
b/drawinglayer/source/primitive2d/structuretagprimitive2d.cxx
index 01d09d8372d5..7e4de87ed64a 100644
--- a/drawinglayer/source/primitive2d/structuretagprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/structuretagprimitive2d.cxx
@@ -59,6 +59,13 @@ namespace drawinglayer::primitive2d
             return PRIMITIVE2D_ID_STRUCTURETAGPRIMITIVE2D;
         }
 
+        bool StructureTagPrimitive2D::isTaggedSdrObject() const
+        {
+            // note at the moment *all* StructureTagPrimitive2D are created for
+            // SdrObjects - if that ever changes, need another condition here
+            return !isBackground() || isImage();
+        }
+
 } // end of namespace
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx 
b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
index 09ee03bba126..e771d2466b1d 100644
--- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
@@ -25,6 +25,7 @@
 #include <tools/gen.hxx>
 #include <tools/stream.hxx>
 #include <comphelper/diagnose_ex.hxx>
+#include <comphelper/flagguard.hxx>
 #include <comphelper/processfactory.hxx>
 #include <config_global.h>
 #include <basegfx/polygon/b2dpolygonclipper.hxx>
@@ -947,7 +948,7 @@ void VclMetafileProcessor2D::processBasePrimitive2D(const 
primitive2d::BasePrimi
         }
         case PRIMITIVE2D_ID_OBJECTINFOPRIMITIVE2D:
         {
-            RenderObjectInfoPrimitive2D(
+            processObjectInfoPrimitive2D(
                 static_cast<const 
primitive2d::ObjectInfoPrimitive2D&>(rCandidate));
             break;
         }
@@ -960,6 +961,51 @@ void VclMetafileProcessor2D::processBasePrimitive2D(const 
primitive2d::BasePrimi
     }
 }
 
+void VclMetafileProcessor2D::processObjectInfoPrimitive2D(
+    primitive2d::ObjectInfoPrimitive2D const& rObjectInfoPrimitive2D)
+{
+    // currently StructureTagPrimitive2D is only used for SdrObjects - have to
+    // avoid adding Alt text if the SdrObject is not actually tagged, as it
+    // would then end up on an unrelated structure element.
+    if (mpCurrentStructureTag && mpCurrentStructureTag->isTaggedSdrObject())
+    {
+        // Create image alternative description from ObjectInfoPrimitive2D info
+        // for PDF export, for the currently active SdrObject's structure 
element
+        if (mpPDFExtOutDevData->GetIsExportTaggedPDF())
+        {
+            OUString aAlternateDescription;
+
+            if (!rObjectInfoPrimitive2D.getTitle().isEmpty())
+            {
+                aAlternateDescription += rObjectInfoPrimitive2D.getTitle();
+            }
+
+            if (!rObjectInfoPrimitive2D.getDesc().isEmpty())
+            {
+                if (!aAlternateDescription.isEmpty())
+                {
+                    aAlternateDescription += " - ";
+                }
+
+                aAlternateDescription += rObjectInfoPrimitive2D.getDesc();
+            }
+
+            // Use SetAlternateText to set it. This will work as long as some
+            // structure is used (see PDFWriterImpl::setAlternateText and
+            // m_nCurrentStructElement - tagged PDF export works with this in
+            // Draw/Impress/Writer, but not in Calc due to too less 
structure...)
+            //Z maybe add structure to Calc PDF export, may need some 
BeginGroup/EndGroup stuff ..?
+            if (!aAlternateDescription.isEmpty())
+            {
+                mpPDFExtOutDevData->SetAlternateText(aAlternateDescription);
+            }
+        }
+    }
+
+    // process content
+    process(rObjectInfoPrimitive2D.getChildren());
+}
+
 void VclMetafileProcessor2D::processGraphicPrimitive2D(
     const primitive2d::GraphicPrimitive2D& rGraphicPrimitive)
 {
@@ -1051,38 +1097,6 @@ void VclMetafileProcessor2D::processGraphicPrimitive2D(
             sal_Int32(ceil(aCropRange.getMaxX())), 
sal_Int32(ceil(aCropRange.getMaxY())));
     }
 
-    // Create image alternative description from ObjectInfoPrimitive2D info
-    // for PDF export
-    if (mpPDFExtOutDevData->GetIsExportTaggedPDF() && nullptr != 
getObjectInfoPrimitive2D())
-    {
-        OUString aAlternateDescription;
-
-        if (!getObjectInfoPrimitive2D()->getTitle().isEmpty())
-        {
-            aAlternateDescription += getObjectInfoPrimitive2D()->getTitle();
-        }
-
-        if (!getObjectInfoPrimitive2D()->getDesc().isEmpty())
-        {
-            if (!aAlternateDescription.isEmpty())
-            {
-                aAlternateDescription += " - ";
-            }
-
-            aAlternateDescription += getObjectInfoPrimitive2D()->getDesc();
-        }
-
-        // Use SetAlternateText to set it. This will work as long as some
-        // structure is used (see PDFWriterImpl::setAlternateText and
-        // m_nCurrentStructElement - tagged PDF export works with this in
-        // Draw/Impress/Writer, but not in Calc due to too less structure...)
-        //Z maybe add structure to Calc PDF export, may need some 
BeginGroup/EndGroup stuff ..?
-        if (!aAlternateDescription.isEmpty())
-        {
-            mpPDFExtOutDevData->SetAlternateText(aAlternateDescription);
-        }
-    }
-
     // #i123295# 3rd param is uncropped rect, 4th is cropped. The primitive 
has the cropped
     // object transformation, thus aCurrentRect *is* the clip region while 
aCropRect is the expanded,
     // uncropped region. Thus, correct order is aCropRect, aCurrentRect
@@ -2361,11 +2375,18 @@ void 
VclMetafileProcessor2D::processTransparencePrimitive2D(
 void VclMetafileProcessor2D::processStructureTagPrimitive2D(
     const primitive2d::StructureTagPrimitive2D& rStructureTagCandidate)
 {
+    ::comphelper::ValueRestorationGuard const g(mpCurrentStructureTag, 
&rStructureTagCandidate);
+
     // structured tag primitive
     const vcl::PDFWriter::StructElement& 
rTagElement(rStructureTagCandidate.getStructureElement());
     bool bTagUsed((vcl::PDFWriter::NonStructElement != rTagElement));
     sal_Int32 nPreviousElement(-1);
 
+    if (!rStructureTagCandidate.isTaggedSdrObject())
+    {
+        bTagUsed = false;
+    }
+
     if (mpPDFExtOutDevData && bTagUsed)
     {
         // foreground object: tag as regular structure element
@@ -2438,7 +2459,7 @@ void 
VclMetafileProcessor2D::processStructureTagPrimitive2D(
                 
mpPDFExtOutDevData->BeginStructureElement(vcl::PDFWriter::NonStructElement);
             // any other background object: do not tag
             else
-                bTagUsed = false;
+                assert(false);
         }
     }
 
diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx 
b/drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx
index 0393039f4455..730b7aac11f2 100644
--- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx
+++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx
@@ -63,6 +63,7 @@ class PolyPolygonColorPrimitive2D;
 class MaskPrimitive2D;
 class UnifiedTransparencePrimitive2D;
 class TransparencePrimitive2D;
+class ObjectInfoPrimitive2D;
 class StructureTagPrimitive2D;
 }
 
@@ -142,6 +143,8 @@ private:
         const primitive2d::UnifiedTransparencePrimitive2D& 
rUniTransparenceCandidate);
     void processTransparencePrimitive2D(
         const primitive2d::TransparencePrimitive2D& rTransparenceCandidate);
+    void
+    processObjectInfoPrimitive2D(const primitive2d::ObjectInfoPrimitive2D& 
rObjectInfoPrimitive2D);
     void processStructureTagPrimitive2D(
         const primitive2d::StructureTagPrimitive2D& rStructureTagCandidate);
 
@@ -191,6 +194,8 @@ private:
 
     std::stack<vcl::PDFWriter::StructElement> maListElements;
 
+    primitive2d::StructureTagPrimitive2D const* mpCurrentStructureTag = 
nullptr;
+
 protected:
     /*  the local processor for BasePrimitive2D-Implementation based 
primitives,
         called from the common process()-implementation
diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx 
b/drawinglayer/source/processor2d/vclprocessor2d.cxx
index 07f9868a798c..e1d56f4da9b1 100644
--- a/drawinglayer/source/processor2d/vclprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx
@@ -1302,20 +1302,6 @@ void VclProcessor2D::RenderEpsPrimitive2D(const 
primitive2d::EpsPrimitive2D& rEp
     }
 }
 
-void VclProcessor2D::RenderObjectInfoPrimitive2D(
-    const primitive2d::ObjectInfoPrimitive2D& rObjectInfoPrimitive2D)
-{
-    // remember current ObjectInfoPrimitive2D and set new current one (build a 
stack - push)
-    const primitive2d::ObjectInfoPrimitive2D* 
pLast(getObjectInfoPrimitive2D());
-    mpObjectInfoPrimitive2D = &rObjectInfoPrimitive2D;
-
-    // process content
-    process(rObjectInfoPrimitive2D.getChildren());
-
-    // restore current ObjectInfoPrimitive2D (pop)
-    mpObjectInfoPrimitive2D = pLast;
-}
-
 void VclProcessor2D::RenderSvgLinearAtomPrimitive2D(
     const primitive2d::SvgLinearAtomPrimitive2D& rCandidate)
 {
@@ -1521,7 +1507,6 @@ VclProcessor2D::VclProcessor2D(const 
geometry::ViewInformation2D& rViewInformati
     , mpOutputDevice(&rOutDev)
     , maBColorModifierStack(std::move(aInitStack))
     , mnPolygonStrokePrimitive2D(0)
-    , mpObjectInfoPrimitive2D(nullptr)
 {
     // set digit language, derived from SvtCTLOptions to have the correct
     // number display for arabic/hindi numerals
diff --git a/drawinglayer/source/processor2d/vclprocessor2d.hxx 
b/drawinglayer/source/processor2d/vclprocessor2d.hxx
index b7d0c65e9437..d2f0a69157fb 100644
--- a/drawinglayer/source/processor2d/vclprocessor2d.hxx
+++ b/drawinglayer/source/processor2d/vclprocessor2d.hxx
@@ -46,7 +46,6 @@ class PolygonStrokePrimitive2D;
 class ControlPrimitive2D;
 class PagePreviewPrimitive2D;
 class EpsPrimitive2D;
-class ObjectInfoPrimitive2D;
 class SvgLinearAtomPrimitive2D;
 class SvgRadialAtomPrimitive2D;
 }
@@ -76,9 +75,6 @@ protected:
     // PolygonStrokePrimitive2D's decompositions (normally only one)
     sal_uInt32 mnPolygonStrokePrimitive2D;
 
-    // currently used ObjectInfoPrimitive2D
-    const primitive2d::ObjectInfoPrimitive2D* mpObjectInfoPrimitive2D;
-
     // common VCL rendering support
     void RenderTextSimpleOrDecoratedPortionPrimitive2D(
         const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate);
@@ -105,8 +101,6 @@ protected:
     void RenderPolygonStrokePrimitive2D(
         const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokeCandidate);
     void RenderEpsPrimitive2D(const primitive2d::EpsPrimitive2D& 
rEpsPrimitive2D);
-    void
-    RenderObjectInfoPrimitive2D(const primitive2d::ObjectInfoPrimitive2D& 
rObjectInfoPrimitive2D);
     void RenderSvgLinearAtomPrimitive2D(const 
primitive2d::SvgLinearAtomPrimitive2D& rCandidate);
     void RenderSvgRadialAtomPrimitive2D(const 
primitive2d::SvgRadialAtomPrimitive2D& rCandidate);
 
@@ -120,12 +114,6 @@ public:
                    basegfx::BColorModifierStack aInitStack = 
basegfx::BColorModifierStack());
     virtual ~VclProcessor2D() override;
 
-    // access to currently used ObjectInfoPrimitive2D
-    const primitive2d::ObjectInfoPrimitive2D* getObjectInfoPrimitive2D() const
-    {
-        return mpObjectInfoPrimitive2D;
-    }
-
 private:
     bool RenderFillGraphicPrimitive2DImpl(
         const primitive2d::FillGraphicPrimitive2D& rFillBitmapCandidate);
diff --git a/include/drawinglayer/primitive2d/structuretagprimitive2d.hxx 
b/include/drawinglayer/primitive2d/structuretagprimitive2d.hxx
index bf8a48f98748..40ad422c2b9a 100644
--- a/include/drawinglayer/primitive2d/structuretagprimitive2d.hxx
+++ b/include/drawinglayer/primitive2d/structuretagprimitive2d.hxx
@@ -65,6 +65,7 @@ namespace drawinglayer::primitive2d
             const vcl::PDFWriter::StructElement& getStructureElement() const { 
return maStructureElement; }
             bool isBackground() const { return mbBackground; }
             bool isImage() const { return mbIsImage; }
+            bool isTaggedSdrObject() const;
             sal_Int32 GetAnchorStructureElementId() const { return 
m_nAnchorStructureElementId; }
 
             /// compare operator

Reply via email to