From a4b03fce93fce7672be40b57d30797ac36ca67c9 Mon Sep 17 00:00:00 2001 From: Michael Weghorn Date: Mon, 9 Dec 2024 10:11:59 +0100 Subject: [PATCH] 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 Tested-by: Jenkins Reviewed-by: Balazs Varga --- .../AccessibilityCheckTest.cxx | 31 ++++++++++++++++++ .../data/ContrastTestFail.odt | Bin 0 -> 13771 bytes .../data/ContrastTestOK.odt | Bin 0 -> 13560 bytes sw/source/core/access/AccessibilityCheck.cxx | 29 +++++++++++++++- 4 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 sw/qa/core/accessibilitycheck/data/ContrastTestFail.odt create mode 100644 sw/qa/core/accessibilitycheck/data/ContrastTestOK.odt diff --git a/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx b/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx index 1f820b47ed02..981cf03cd26b 100644 --- a/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx +++ b/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx @@ -318,6 +318,37 @@ 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()); + CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_CONTRAST, aIssues[0]->m_eIssueID); + CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_CONTRAST, aIssues[1]->m_eIssueID); + CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_CONTRAST, aIssues[2]->m_eIssueID); + + // 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> diff --git a/sw/qa/core/accessibilitycheck/data/ContrastTestFail.odt b/sw/qa/core/accessibilitycheck/data/ContrastTestFail.odt new file mode 100644 index 0000000000000000000000000000000000000000..4f898942e37f71a9004fb6cfbcaad91775bc3d5e GIT binary patch literal 13771 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 literal 0 HcmV?d00001 diff --git a/sw/qa/core/accessibilitycheck/data/ContrastTestOK.odt b/sw/qa/core/accessibilitycheck/data/ContrastTestOK.odt new file mode 100644 index 0000000000000000000000000000000000000000..2f47148838a2464f647a1ef21d343b7c138d4b6a GIT binary patch literal 13560 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 #include #include +#include #include #include #include @@ -716,6 +717,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& 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: @@ -836,7 +863,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), sfx::AccessibilityIssueID::TEXT_CONTRAST,