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>
diff --git a/drawinglayer/source/primitive2d/structuretagprimitive2d.cxx b/drawinglayer/source/primitive2d/structuretagprimitive2d.cxx
index 01d09d8..7e4de87 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 09ee03b..e771d24 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 0393039..730b7aa 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 07f9868..e1d56f4 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 b7d0c65..d2f0a69 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 bf8a48f..40ad422 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