diff options
author | Michael Weghorn <m.weghorn@posteo.de> | 2024-12-09 10:11:59 +0100 |
---|---|---|
committer | Michael Weghorn <m.weghorn@posteo.de> | 2024-12-12 09:52:15 +0100 |
commit | 99c04ba30e5dbc8bdc7a3e920536b0c432c39797 (patch) | |
tree | cff2b223d16523da3eddc357d740a3f87e009e8f | |
parent | 22487a3d991b899e541c3abe6f718a57f3384be4 (diff) |
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.weghorn@posteo.de>
Tested-by: Jenkins
Reviewed-by: Balazs Varga <balazs.varga.extern@allotropia.de>
(cherry picked from commit a4b03fce93fce7672be40b57d30797ac36ca67c9)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/178169
-rw-r--r-- | sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx | 28 | ||||
-rw-r--r-- | sw/qa/core/accessibilitycheck/data/ContrastTestFail.odt | bin | 0 -> 13771 bytes | |||
-rw-r--r-- | sw/qa/core/accessibilitycheck/data/ContrastTestOK.odt | bin | 0 -> 13560 bytes | |||
-rw-r--r-- | sw/source/core/access/AccessibilityCheck.cxx | 29 |
4 files changed, 56 insertions, 1 deletions
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 Binary files differnew file mode 100644 index 000000000000..4f898942e37f --- /dev/null +++ b/sw/qa/core/accessibilitycheck/data/ContrastTestFail.odt diff --git a/sw/qa/core/accessibilitycheck/data/ContrastTestOK.odt b/sw/qa/core/accessibilitycheck/data/ContrastTestOK.odt Binary files differnew file mode 100644 index 000000000000..2f47148838a2 --- /dev/null +++ b/sw/qa/core/accessibilitycheck/data/ContrastTestOK.odt 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); |