summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2022-09-20 08:30:53 +0200
committerMiklos Vajna <vmiklos@collabora.com>2022-09-20 09:22:28 +0200
commitaddfb3cce0f7ce8fbd0b169d467b6956ed95dbb5 (patch)
tree44ad218bf4ee32be4b77003c0deea853ad60e41e
parent6754b647c145cded1f54b49d53d37ad35ace211c (diff)
sw content controls: add a11y description for PDF export
Acrobat Reader shows these descriptions on mouse hovering on a form widget. Change-Id: I8614222e46c992baca8a57b13a948f88973e8911 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/140215 Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Tested-by: Jenkins
-rw-r--r--external/pdfium/UnpackedTarball_pdfium.mk1
-rw-r--r--external/pdfium/annot-alternate-name.patch.140
-rw-r--r--include/vcl/filter/PDFiumLibrary.hxx1
-rw-r--r--sw/qa/core/text/text.cxx13
-rw-r--r--sw/source/core/text/itrform2.cxx14
-rw-r--r--vcl/source/pdf/PDFiumLibrary.cxx31
6 files changed, 100 insertions, 0 deletions
diff --git a/external/pdfium/UnpackedTarball_pdfium.mk b/external/pdfium/UnpackedTarball_pdfium.mk
index 272fa5cb606f..4c9f483f8ed7 100644
--- a/external/pdfium/UnpackedTarball_pdfium.mk
+++ b/external/pdfium/UnpackedTarball_pdfium.mk
@@ -29,6 +29,7 @@ pdfium_patches += include.patch
pdfium_patches += abseil-trivial.patch
pdfium_patches += annot.patch.1
+pdfium_patches += annot-alternate-name.patch.1
$(eval $(call gb_UnpackedTarball_UnpackedTarball,pdfium))
diff --git a/external/pdfium/annot-alternate-name.patch.1 b/external/pdfium/annot-alternate-name.patch.1
new file mode 100644
index 000000000000..6ed619c8ec45
--- /dev/null
+++ b/external/pdfium/annot-alternate-name.patch.1
@@ -0,0 +1,40 @@
+diff --git a/fpdfsdk/fpdf_annot.cpp b/fpdfsdk/fpdf_annot.cpp
+index 05ec46f01..2aa1ce912 100644
+--- a/fpdfsdk/fpdf_annot.cpp
++++ b/fpdfsdk/fpdf_annot.cpp
+@@ -1289,6 +1289,18 @@ FPDFAnnot_GetFormFieldName(FPDF_FORMHANDLE hHandle,
+ buflen);
+ }
+
++FPDF_EXPORT unsigned long FPDF_CALLCONV
++FPDFAnnot_GetFormFieldAlternateName(FPDF_FORMHANDLE hHandle,
++ FPDF_ANNOTATION annot,
++ FPDF_WCHAR* buffer,
++ unsigned long buflen) {
++ const CPDF_FormField* pFormField = GetFormField(hHandle, annot);
++ if (!pFormField)
++ return 0;
++ return Utf16EncodeMaybeCopyAndReturnLength(pFormField->GetAlternateName(), buffer,
++ buflen);
++}
++
+ FPDF_EXPORT int FPDF_CALLCONV
+ FPDFAnnot_GetFormFieldType(FPDF_FORMHANDLE hHandle, FPDF_ANNOTATION annot) {
+ const CPDF_FormField* pFormField = GetFormField(hHandle, annot);
+diff --git a/public/fpdf_annot.h b/public/fpdf_annot.h
+index e4217056b..7ce6f3caf 100644
+--- a/public/fpdf_annot.h
++++ b/public/fpdf_annot.h
+@@ -735,6 +735,12 @@ FPDFAnnot_GetFormFieldName(FPDF_FORMHANDLE hHandle,
+ FPDF_WCHAR* buffer,
+ unsigned long buflen);
+
++FPDF_EXPORT unsigned long FPDF_CALLCONV
++FPDFAnnot_GetFormFieldAlternateName(FPDF_FORMHANDLE hHandle,
++ FPDF_ANNOTATION annot,
++ FPDF_WCHAR* buffer,
++ unsigned long buflen);
++
+ // Experimental API.
+ // Gets the form field type of |annot|, which is an interactive form annotation.
+ //
diff --git a/include/vcl/filter/PDFiumLibrary.hxx b/include/vcl/filter/PDFiumLibrary.hxx
index 390c826cd57b..1dc1382643d0 100644
--- a/include/vcl/filter/PDFiumLibrary.hxx
+++ b/include/vcl/filter/PDFiumLibrary.hxx
@@ -103,6 +103,7 @@ public:
virtual std::vector<basegfx::B2DPoint> getLineGeometry() = 0;
virtual PDFFormFieldType getFormFieldType(PDFiumDocument* pDoc) = 0;
virtual float getFormFontSize(PDFiumDocument* pDoc) = 0;
+ virtual OUString getFormFieldAlternateName(PDFiumDocument* pDoc) = 0;
};
class PDFiumTextPage;
diff --git a/sw/qa/core/text/text.cxx b/sw/qa/core/text/text.cxx
index 12dc50884f23..245f8c230ca6 100644
--- a/sw/qa/core/text/text.cxx
+++ b/sw/qa/core/text/text.cxx
@@ -35,6 +35,7 @@
#include <fmtfsize.hxx>
#include <IDocumentRedlineAccess.hxx>
#include <formatcontentcontrol.hxx>
+#include <strings.hrc>
constexpr OUStringLiteral DATA_DIRECTORY = u"/sw/qa/core/text/data/";
@@ -623,6 +624,12 @@ CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testContentControlPDF)
SwDoc* pDoc = createSwDoc();
SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
pWrtShell->InsertContentControl(SwContentControlType::RICH_TEXT);
+ pWrtShell->SttEndDoc(/*bStt=*/true);
+ pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
+ sal_Int32 nPlaceHolderLen = SwResId(STR_CONTENT_CONTROL_PLACEHOLDER).getLength();
+ pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, nPlaceHolderLen,
+ /*bBasicCall=*/false);
+ pWrtShell->Insert("mydesc");
// When exporting to PDF:
StoreToTempFile("writer_pdf_Export");
@@ -635,6 +642,12 @@ CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testContentControlPDF)
// - Actual : 0
// i.e. the content control was just exported as normal text.
CPPUNIT_ASSERT_EQUAL(1, pPage->getAnnotationCount());
+ std::unique_ptr<vcl::pdf::PDFiumAnnotation> pAnnotation = pPage->getAnnotation(0);
+ CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Widget, pAnnotation->getSubType());
+
+ // Also verify that the widget description is correct, it was empty:
+ CPPUNIT_ASSERT_EQUAL(OUString("mydesc"),
+ pAnnotation->getFormFieldAlternateName(pPdfDocument.get()));
}
CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testCheckboxContentControlPDF)
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index 320133b0ffce..f07ea0bc1de7 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -56,6 +56,7 @@
#include <IDocumentMarkAccess.hxx>
#include <comphelper/processfactory.hxx>
#include <vcl/pdfextoutdevdata.hxx>
+#include <comphelper/string.hxx>
#include <docsh.hxx>
#include <unocrsrhelper.hxx>
#include <textcontentcontrol.hxx>
@@ -984,6 +985,19 @@ bool SwContentControlPortion::DescribePDFControl(const SwTextPaintInfo& rInf) co
pDescriptor->TextFont = pFont->GetActualFont();
}
+ // Description for accessibility purposes.
+ SwTextContentControl* pTextAttr = pContentControl->GetTextAttr();
+ SwTextNode* pTextNode = pContentControl->GetTextNode();
+ SwPosition aPoint(*pTextNode, pTextAttr->GetStart());
+ SwPosition aMark(*pTextNode, *pTextAttr->GetEnd());
+ SwPaM aPam(aMark, aPoint);
+ OUString aDescription = aPam.GetText();
+ static sal_Unicode const aForbidden[] = {
+ CH_TXTATR_BREAKWORD,
+ 0
+ };
+ pDescriptor->Description = comphelper::string::removeAny(aDescription, aForbidden);
+
SwRect aLocation;
rInf.CalcRect(*this, &aLocation);
pDescriptor->Location = aLocation.SVRect();
diff --git a/vcl/source/pdf/PDFiumLibrary.cxx b/vcl/source/pdf/PDFiumLibrary.cxx
index bb371ca930dc..e64aa2f5e3e5 100644
--- a/vcl/source/pdf/PDFiumLibrary.cxx
+++ b/vcl/source/pdf/PDFiumLibrary.cxx
@@ -251,6 +251,7 @@ public:
std::vector<basegfx::B2DPoint> getLineGeometry() override;
PDFFormFieldType getFormFieldType(PDFiumDocument* pDoc) override;
float getFormFontSize(PDFiumDocument* pDoc) override;
+ OUString getFormFieldAlternateName(PDFiumDocument* pDoc) override;
};
class PDFiumPageObjectImpl final : public PDFiumPageObject
@@ -1148,6 +1149,36 @@ float PDFiumAnnotationImpl::getFormFontSize(PDFiumDocument* pDoc)
return fRet;
}
+OUString PDFiumAnnotationImpl::getFormFieldAlternateName(PDFiumDocument* pDoc)
+{
+ auto pDocImpl = static_cast<PDFiumDocumentImpl*>(pDoc);
+ OUString aString;
+ unsigned long nSize = FPDFAnnot_GetFormFieldAlternateName(pDocImpl->getFormHandlePointer(),
+ mpAnnotation, nullptr, 0);
+ assert(nSize % 2 == 0);
+ nSize /= 2;
+ if (nSize > 1)
+ {
+ std::unique_ptr<sal_Unicode[]> pText(new sal_Unicode[nSize]);
+ unsigned long nStringSize = FPDFAnnot_GetFormFieldAlternateName(
+ pDocImpl->getFormHandlePointer(), mpAnnotation,
+ reinterpret_cast<FPDF_WCHAR*>(pText.get()), nSize * 2);
+ assert(nStringSize % 2 == 0);
+ nStringSize /= 2;
+ if (nStringSize > 0)
+ {
+#if defined OSL_BIGENDIAN
+ for (unsigned long i = 0; i != nStringSize; ++i)
+ {
+ pText[i] = OSL_SWAPWORD(pText[i]);
+ }
+#endif
+ aString = OUString(pText.get());
+ }
+ }
+ return aString;
+}
+
namespace
{
bool getBorderProperties(FPDF_ANNOTATION mpAnnotation, float& rHorizontalCornerRadius,