sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx |   28 ++++++++++++++
 sw/qa/core/accessibilitycheck/data/ContrastTestFail.odt  |binary
 sw/qa/core/accessibilitycheck/data/ContrastTestOK.odt    |binary
 sw/source/core/access/AccessibilityCheck.cxx             |   29 ++++++++++++++-
 4 files changed, 56 insertions(+), 1 deletion(-)

New commits:
commit 99c04ba30e5dbc8bdc7a3e920536b0c432c39797
Author:     Michael Weghorn <m.wegh...@posteo.de>
AuthorDate: Mon Dec 9 10:11:59 2024 +0100
Commit:     Michael Weghorn <m.wegh...@posteo.de>
CommitDate: Thu Dec 12 09:52:15 2024 +0100

    tdf#164247 sw a11y check: Adhere to WCAG contrast threshold for large text
    
    Quoting WCAG 2.2 "Success Criterion 1.4.3 Contrast (Minimum)" [1]:
    
    > The visual presentation of text and images of text has a contrast
    > ratio of at least 4.5:1, except for the following:
    >
    > Large Text
    >
    >     Large-scale text and images of large-scale text have a contrast
    >     ratio of at least 3:1;
    
    Regarding large text, the corresponding "Understanding SC 1.4.3" [2]
    clarifies:
    
    > Text that is larger and has wider character strokes is easier to read at
    > lower contrast. The contrast requirement for larger text is therefore
    > lower. This allows authors to use a wider range of color choices for
    > large text, which is helpful for design of pages, particularly titles.
    > 18 point text or 14 point bold text is judged to be large enough to
    > require a lower contrast ratio.
    
    Therefore, lower the text contrast requirement in
    Writer's accessibility check from 4.5 to 3.0 for
    text that is considered large according to that
    specification.
    
    Add a unit test with 2 test documents:
    
    * one that adheres to the requirements and would have triggered false
      positives without this change in place
      (sw/qa/core/accessibilitycheck/data/ContrastTestOK.odt)
    * one that doesn't adhere to the requirements and still fails the
      check, as it should
      (sw/qa/core/accessibilitycheck/data/ContrastTestFail.odt)
    
    [1] https://www.w3.org/TR/WCAG22/#contrast-minimum
    [2] https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html
    
    Change-Id: I398f72aa5bdcd77c42834632575d6465a5ecd586
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/178127
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>
    Tested-by: Jenkins
    Reviewed-by: Balazs Varga <balazs.varga.ext...@allotropia.de>
    (cherry picked from commit a4b03fce93fce7672be40b57d30797ac36ca67c9)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/178169

diff --git a/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx 
b/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx
index d15eeaf70da9..fc0aa008f4b3 100644
--- a/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx
+++ b/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx
@@ -306,6 +306,34 @@ CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, 
testStylesWithHeader)
     CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::DIRECT_FORMATTING, 
aIssues[4]->m_eIssueID);
 }
 
+// Text contrast tests
+// see https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html
+CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, testCheckTextContrast)
+{
+    // first test doc has these issues:
+    // * normal text with contrast < 4.5
+    // * large text with contrast < 3.0
+    // * bold text with font size 13 (i.e. not considered large) with contrast 
< 4.5
+    createSwDoc("ContrastTestFail.odt");
+    SwDoc* pDoc = getSwDoc();
+    sw::AccessibilityCheck aCheck(pDoc);
+    aCheck.check();
+    auto& aIssues = aCheck.getIssueCollection().getIssues();
+    CPPUNIT_ASSERT_EQUAL(size_t(3), aIssues.size());
+
+    // second test doc has large text with contrast between 3.0 and 4.5,
+    // which is sufficient for large text
+    // both of these are considered large text according to the spec:
+    // * non-bold text font with size 18
+    // * bold text with font size 14
+    createSwDoc("ContrastTestOK.odt");
+    SwDoc* pDocOK = getSwDoc();
+    sw::AccessibilityCheck aCheckOK(pDocOK);
+    aCheckOK.check();
+    auto& aIssuesOK = aCheckOK.getIssueCollection().getIssues();
+    CPPUNIT_ASSERT_EQUAL(size_t(0), aIssuesOK.size());
+}
+
 namespace
 {
 std::vector<std::shared_ptr<sfx::AccessibilityIssue>>
diff --git a/sw/qa/core/accessibilitycheck/data/ContrastTestFail.odt 
b/sw/qa/core/accessibilitycheck/data/ContrastTestFail.odt
new file mode 100644
index 000000000000..4f898942e37f
Binary files /dev/null and 
b/sw/qa/core/accessibilitycheck/data/ContrastTestFail.odt differ
diff --git a/sw/qa/core/accessibilitycheck/data/ContrastTestOK.odt 
b/sw/qa/core/accessibilitycheck/data/ContrastTestOK.odt
new file mode 100644
index 000000000000..2f47148838a2
Binary files /dev/null and 
b/sw/qa/core/accessibilitycheck/data/ContrastTestOK.odt differ
diff --git a/sw/source/core/access/AccessibilityCheck.cxx 
b/sw/source/core/access/AccessibilityCheck.cxx
index 0d63ed192696..f54f348786f3 100644
--- a/sw/source/core/access/AccessibilityCheck.cxx
+++ b/sw/source/core/access/AccessibilityCheck.cxx
@@ -21,6 +21,7 @@
 #include <svx/svdpage.hxx>
 #include <sortedobjs.hxx>
 #include <swtable.hxx>
+#include <com/sun/star/awt/FontWeight.hpp>
 #include <com/sun/star/frame/XModel.hpp>
 #include <com/sun/star/text/XTextContent.hpp>
 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
@@ -490,6 +491,32 @@ double calculateContrastRatio(Color const& rColor1, Color 
const& rColor2)
     return (aMinMax.second + 0.05) / (aMinMax.first + 0.05);
 }
 
+// Determine required minimum contrast ratio for text with the given properties
+// according to 
https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html
+// * 3.0 for large text (font size >= 18 or bold and font size >= 14)
+// * 4.5 otherwise
+double minimumContrastRatio(const uno::Reference<beans::XPropertySet>& 
xProperties)
+{
+    double fMinimumContrastRatio = 4.5;
+    double fFontSize = 0;
+    if (xProperties->getPropertyValue(u"CharHeight"_ustr) >>= fFontSize)
+    {
+        if (fFontSize >= 18)
+            fMinimumContrastRatio = 3.0;
+        else if (fFontSize >= 14)
+        {
+            double fCharWeight = 0;
+            if (xProperties->getPropertyValue(u"CharWeight"_ustr) >>= 
fCharWeight)
+            {
+                if (fCharWeight == css::awt::FontWeight::BOLD
+                    || fCharWeight == css::awt::FontWeight::ULTRABOLD)
+                    fMinimumContrastRatio = 3.0;
+            }
+        }
+    }
+    return fMinimumContrastRatio;
+}
+
 class TextContrastCheck : public NodeCheck
 {
 private:
@@ -609,7 +636,7 @@ private:
             aBackgroundColor = COL_WHITE;
 
         double fContrastRatio = calculateContrastRatio(aForegroundColor, 
aBackgroundColor);
-        if (fContrastRatio < 4.5)
+        if (fContrastRatio < minimumContrastRatio(xProperties))
         {
             auto pIssue = lclAddIssue(m_rIssueCollection, 
SwResId(STR_TEXT_CONTRAST));
             pIssue->setIssueObject(IssueObject::TEXT);

Reply via email to