external/pdfium/UnpackedTarball_pdfium.mk    |    1 
 external/pdfium/annot-alternate-name.patch.1 |   40 +++++++++++++++++++++++++++
 include/vcl/filter/PDFiumLibrary.hxx         |    1 
 sw/qa/core/text/text.cxx                     |   13 ++++++++
 sw/source/core/text/itrform2.cxx             |   14 +++++++++
 vcl/source/pdf/PDFiumLibrary.cxx             |   31 ++++++++++++++++++++
 6 files changed, 100 insertions(+)

New commits:
commit addfb3cce0f7ce8fbd0b169d467b6956ed95dbb5
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Tue Sep 20 08:30:53 2022 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Tue Sep 20 09:22:28 2022 +0200

    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 <vmik...@collabora.com>
    Tested-by: Jenkins

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,

Reply via email to