diff options
author | Armin Le Grand <Armin.Le.Grand@cib.de> | 2018-12-20 17:31:32 +0100 |
---|---|---|
committer | Thorsten Behrens <Thorsten.Behrens@CIB.de> | 2019-02-06 16:46:08 +0100 |
commit | 2840352ba56a212d191cc16e08378c87672d7b73 (patch) | |
tree | b61423212519ebc9e2afc0e780aca1661f42403f /svx | |
parent | cdfa8b27f28328612b6734533981c1b363ced0a0 (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 'svx')
-rw-r--r-- | svx/source/svdraw/svdotextdecomposition.cxx | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/svx/source/svdraw/svdotextdecomposition.cxx b/svx/source/svdraw/svdotextdecomposition.cxx index e5e0ee273e11..fb02ac86b79a 100644 --- a/svx/source/svdraw/svdotextdecomposition.cxx +++ b/svx/source/svdraw/svdotextdecomposition.cxx @@ -93,7 +93,7 @@ namespace void impCreateTextPortionPrimitive(const DrawPortionInfo& rInfo); static drawinglayer::primitive2d::BasePrimitive2D* impCheckFieldPrimitive(drawinglayer::primitive2d::BasePrimitive2D* pPrimitive, const DrawPortionInfo& rInfo); void impFlushTextPortionPrimitivesToLinePrimitives(); - void impFlushLinePrimitivesToParagraphPrimitives(); + void impFlushLinePrimitivesToParagraphPrimitives(sal_Int32 nPara); void impHandleDrawPortionInfo(const DrawPortionInfo& rInfo); void impHandleDrawBulletInfo(const DrawBulletInfo& rInfo); @@ -482,12 +482,21 @@ namespace } } - void impTextBreakupHandler::impFlushLinePrimitivesToParagraphPrimitives() + void impTextBreakupHandler::impFlushLinePrimitivesToParagraphPrimitives(sal_Int32 nPara) { // ALWAYS create a paragraph primitive, even when no content was added. This is done to // have the correct paragraph count even with empty paragraphs. Those paragraphs will // have an empty sub-PrimitiveSequence. - maParagraphPrimitives.push_back(new drawinglayer::primitive2d::TextHierarchyParagraphPrimitive2D(maLinePrimitives)); + const sal_Int16 nOutlineLevel(nPara >= 0 && nPara < mrOutliner.GetParagraphCount() + ? mrOutliner.GetParaAttribs(nPara).Get(EE_PARA_OUTLLEVEL).GetValue() + : -1); + + //Z This basically makes OutlineLevel information available in VclMetafileProcessor2D, + //Z so may be used similar to 'SetAlternateText' in processGraphicPrimitive2D for PDF export + maParagraphPrimitives.push_back( + new drawinglayer::primitive2d::TextHierarchyParagraphPrimitive2D( + maLinePrimitives, + nOutlineLevel)); maLinePrimitives.clear(); } @@ -502,7 +511,7 @@ namespace if(rInfo.mbEndOfParagraph) { - impFlushLinePrimitivesToParagraphPrimitives(); + impFlushLinePrimitivesToParagraphPrimitives(rInfo.mnPara); } } @@ -637,7 +646,7 @@ namespace if(!maLinePrimitives.empty()) { // collect non-closed paragraphs - impFlushLinePrimitivesToParagraphPrimitives(); + impFlushLinePrimitivesToParagraphPrimitives(mrOutliner.GetParagraphCount() - 1); } return maParagraphPrimitives; |