diff options
author | Michael Stahl <michael.stahl@allotropia.de> | 2022-11-23 19:08:14 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2022-12-03 21:01:50 +0000 |
commit | 2b3fc2a2603f54e60ad16e81d112d30b204e9796 (patch) | |
tree | c93edc5fff60d3a5d1400dbc32872c037eb9d11f /drawinglayer | |
parent | 1df094470ddf3c9c46dbc289e1582814acf6159d (diff) |
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.stahl@allotropia.de>
(cherry picked from commit 78681cd0829dcb6a73690e1a63ae3808d297677a)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143291
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'drawinglayer')
5 files changed, 67 insertions, 61 deletions
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 1dcc486021c1..1bb8bb9ca646 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 <tools/diagnose_ex.h> +#include <comphelper/flagguard.hxx> #include <comphelper/processfactory.hxx> #include <config_global.h> #include <basegfx/polygon/b2dpolygonclipper.hxx> @@ -924,7 +925,7 @@ void VclMetafileProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimi } case PRIMITIVE2D_ID_OBJECTINFOPRIMITIVE2D: { - RenderObjectInfoPrimitive2D( + processObjectInfoPrimitive2D( static_cast<const primitive2d::ObjectInfoPrimitive2D&>(rCandidate)); break; } @@ -944,6 +945,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) { @@ -1035,38 +1081,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 @@ -2344,11 +2358,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 @@ -2421,7 +2442,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 06fd61e18309..6b66a160bdc4 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); void processPrimitive2DOnPixelProcessor(const primitive2d::BasePrimitive2D& rCandidate); @@ -195,6 +198,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 da34cd558a81..b77c1d9c0182 100644 --- a/drawinglayer/source/processor2d/vclprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx @@ -1262,20 +1262,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) { @@ -1482,7 +1468,6 @@ VclProcessor2D::VclProcessor2D(const geometry::ViewInformation2D& rViewInformati , mpOutputDevice(&rOutDev) , maBColorModifierStack(rInitStack) , 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 7e251aa0ca13..1506f481e2e7 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); @@ -119,12 +113,6 @@ public: VclProcessor2D(const geometry::ViewInformation2D& rViewInformation, OutputDevice& rOutDev, const basegfx::BColorModifierStack& rInitStack = basegfx::BColorModifierStack()); virtual ~VclProcessor2D() override; - - // access to currently used ObjectInfoPrimitive2D - const primitive2d::ObjectInfoPrimitive2D* getObjectInfoPrimitive2D() const - { - return mpObjectInfoPrimitive2D; - } }; } // end of namespace drawinglayer::processor2d |