summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorArmin Le Grand <Armin.Le.Grand@cib.de>2018-12-20 17:31:32 +0100
committerThorsten Behrens <Thorsten.Behrens@CIB.de>2019-02-06 16:46:08 +0100
commit2840352ba56a212d191cc16e08378c87672d7b73 (patch)
treeb61423212519ebc9e2afc0e780aca1661f42403f /sw
parentcdfa8b27f28328612b6734533981c1b363ced0a0 (diff)
Enhance tagged PDF export for a11y
The current tagged PDF export does not well support quite some internal structures. This includes all apps (Draw/Impress/Writer/Calc) and some areas. -= AlternativeText ('/Alt'): Only writer currently at least adds Title information, but we also have Description (MS does add) and Name. Target is to add this information when available to content frames. Writer did that by manually adding that tag using PDFExtOutDevData::SetAlternateText, but only used Title so far. To make this work as broad as possible, better add this to primitives. There is already a primitive called ObjectInfoPrimitive2D that encapsulates any content adding Name/Title/Description using GroupPrimitive functionality. Changed Writer to use that way. Draw/Impress already uses it, all apps now use graphic paint using primitives, so we have a natural target to encapsulate. Add support to VclMetafileProcessor2D to interpret it and add - if mpPDFExtOutDevData->GetIsExportTaggedPDF() - that data using a combination of Name/Title/Description and add using mpPDFExtOutDevData->SetAlternateText. This works for Draw/Impress/Writer, but not for Calc because Calc does not create more complex data structures, so SetAlternateText does not work (see PDFWriterImpl::setAlternateText for more infos). -= Area tagged ListContent (use 'L', 'LI', 'LBody' PDF tags): To support this in Draw/Impress, we can also use a similar way to support in primitives. For this I evaluated how to add needed OutlineLevel information to the existing (and already used to write 'P') TextHierarchyParagraphPrimitive2D. Added this and now ready to use in VclMetafileProcessor2D ::processTextHierarchyParagraphPrimitive2D. Added now using the OutlineLevel information at the TextHierarchyParagraphPrimitive2D. Made sure there are fallbacks to unchanged old behaviour when no PDF export or no Tagged-PDF used. Creating now '/L', '/LI' and '/LBody' statements as tagged PDF wants us to do. Exported PDF still works well while additionally a verifier as 'PAC 3' shows the expected and wanted structure. This will work now for any text in Draw/Impress and for Draw-Objects using Lists in Calc. Need to check for direct text in Calc cells and Writer - and guess how big the effort would be for these to make it work there, too. -= Area '/Artifact': Target is to avoid too much ScreenReader hassle when Impress uses Pictures/FillPatterns etc. in Background - what means on MasterPage in Impress. Experimented with different possibilities. Decided to use existing StructureTagPrimitive2D and extend for info if encapsulated data is 'Background' data -> on MasterPage. Can be created in ImplRenderPaintProc in method createRedirectedPrimitive2DSeque as needed by checking for MasterPage member (remember: primitives need to be as independent from model data as possible, never include e.g. a SdrObject reference in any way). Tried different ways to use this in VclMetafileProcessor2D processStructureTagPrimitive2D, see comments there. Current best solution is to just *not* create StuctureTag information for these objects. Change-Id: Ib2a578b02c1256758cda6d15ce37799803d8205c
Diffstat (limited to 'sw')
-rw-r--r--sw/source/core/doc/notxtfrm.cxx27
-rw-r--r--sw/source/core/inc/frmtool.hxx5
-rw-r--r--sw/source/core/layout/paintfrm.cxx5
-rw-r--r--sw/source/core/text/EnhancedPDFExportHelper.cxx18
4 files changed, 35 insertions, 20 deletions
diff --git a/sw/source/core/doc/notxtfrm.cxx b/sw/source/core/doc/notxtfrm.cxx
index c64c0388b2c1..b2fb0f388bac 100644
--- a/sw/source/core/doc/notxtfrm.cxx
+++ b/sw/source/core/doc/notxtfrm.cxx
@@ -80,6 +80,7 @@
#include <vcl/pdfextoutdevdata.hxx>
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx>
using namespace com::sun::star;
@@ -928,7 +929,10 @@ void paintGraphicUsingPrimitivesHelper(
vcl::RenderContext & rOutputDevice,
GraphicObject const& rGrfObj,
GraphicAttr const& rGraphicAttr,
- const basegfx::B2DHomMatrix& rGraphicTransform)
+ const basegfx::B2DHomMatrix& rGraphicTransform,
+ const OUString& rName,
+ const OUString& rTitle,
+ const OUString& rDescription)
{
// RotGrfFlyFrame: unify using GraphicPrimitive2D
// -> the primitive handles all crop and mirror stuff
@@ -988,6 +992,17 @@ void paintGraphicUsingPrimitivesHelper(
}
}
+ if(!rName.isEmpty() || !rTitle.isEmpty() || !rDescription.isEmpty())
+ {
+ // Embed to ObjectInfoPrimitive2D when we have Name/Title/Description
+ // information available
+ aContent[0] = new drawinglayer::primitive2d::ObjectInfoPrimitive2D(
+ aContent,
+ rName,
+ rTitle,
+ rDescription);
+ }
+
basegfx::B2DRange aTargetRange(0.0, 0.0, 1.0, 1.0);
aTargetRange.transform(rGraphicTransform);
@@ -1129,7 +1144,10 @@ void SwNoTextFrame::PaintPicture( vcl::RenderContext* pOut, const SwRect &rGrfAr
*pOut,
rGrfObj,
aGrfAttr,
- aGraphicTransform);
+ aGraphicTransform,
+ nullptr == pGrfNd->GetFlyFormat() ? OUString() : pGrfNd->GetFlyFormat()->GetName(),
+ rNoTNd.GetTitle(),
+ rNoTNd.GetDescription());
}
}
else
@@ -1217,7 +1235,10 @@ void SwNoTextFrame::PaintPicture( vcl::RenderContext* pOut, const SwRect &rGrfAr
*pOut,
aTempGraphicObject,
aGrfAttr,
- aGraphicTransform);
+ aGraphicTransform,
+ nullptr == pOLENd->GetFlyFormat() ? OUString() : pOLENd->GetFlyFormat()->GetName(),
+ rNoTNd.GetTitle(),
+ rNoTNd.GetDescription());
// shade the representation if the object is activated outplace
uno::Reference < embed::XEmbeddedObject > xObj = pOLENd->GetOLEObj().GetOleRef();
diff --git a/sw/source/core/inc/frmtool.hxx b/sw/source/core/inc/frmtool.hxx
index bb006d56520e..507dca39313d 100644
--- a/sw/source/core/inc/frmtool.hxx
+++ b/sw/source/core/inc/frmtool.hxx
@@ -92,7 +92,10 @@ void paintGraphicUsingPrimitivesHelper(
OutputDevice & rOutputDevice,
GraphicObject const& rGraphicObj,
GraphicAttr const& rGraphicAttr,
- const basegfx::B2DHomMatrix& rGraphicTransform);
+ const basegfx::B2DHomMatrix& rGraphicTransform,
+ const OUString& rName,
+ const OUString& rTitle,
+ const OUString& rDescription);
// method to align rectangle.
// Created declaration here to avoid <extern> declarations
diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx
index dafc00ec4d34..213ce01e7797 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -1675,7 +1675,10 @@ static void lcl_DrawGraphic( const SvxBrushItem& rBrush, vcl::RenderContext *pOu
*pOut,
*pGrf,
pGrf->GetAttr(),
- aGraphicTransform);
+ aGraphicTransform,
+ OUString(),
+ OUString(),
+ OUString());
if ( bNotInside )
pOut->Pop();
diff --git a/sw/source/core/text/EnhancedPDFExportHelper.cxx b/sw/source/core/text/EnhancedPDFExportHelper.cxx
index 69395167a38f..290c69867b47 100644
--- a/sw/source/core/text/EnhancedPDFExportHelper.cxx
+++ b/sw/source/core/text/EnhancedPDFExportHelper.cxx
@@ -486,7 +486,6 @@ void SwTaggedPDFHelper::SetAttributes( vcl::PDFWriter::StructElement eType )
bool bEndIndent = false;
bool bTextIndent = false;
bool bTextAlign = false;
- bool bAlternateText = false;
bool bWidth = false;
bool bHeight = false;
bool bBox = false;
@@ -550,7 +549,6 @@ void SwTaggedPDFHelper::SetAttributes( vcl::PDFWriter::StructElement eType )
case vcl::PDFWriter::Formula :
case vcl::PDFWriter::Figure :
bPlacement =
- bAlternateText =
bWidth =
bHeight =
bBox = true;
@@ -640,19 +638,9 @@ void SwTaggedPDFHelper::SetAttributes( vcl::PDFWriter::StructElement eType )
}
}
- if ( bAlternateText )
- {
- OSL_ENSURE( pFrame->IsFlyFrame(), "Frame type <-> tag attribute mismatch" );
- const SwFlyFrame* pFly = static_cast<const SwFlyFrame*>(pFrame);
- if ( pFly->Lower() && pFly->Lower()->IsNoTextFrame() )
- {
- const SwNoTextFrame* pNoTextFrame = static_cast<const SwNoTextFrame*>(pFly->Lower());
- const SwNoTextNode* pNoTextNode = static_cast<const SwNoTextNode*>(pNoTextFrame->GetNode());
-
- const OUString aAlternateText( pNoTextNode->GetTitle() );
- mpPDFExtOutDevData->SetAlternateText( aAlternateText );
- }
- }
+ // Formally here bAlternateText was triggered for PDF export, but this
+ // was moved for more general use to primitives and usage in
+ // VclMetafileProcessor2D (see processGraphicPrimitive2D).
if ( bWidth )
{