sw/inc/AccessibilityCheckStrings.hrc                       |    1 
 sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx   |   12 +
 sw/qa/core/accessibilitycheck/data/AccessibilityTests1.odt |binary
 sw/qa/core/accessibilitycheck/data/NewlineTest.odt         |binary
 sw/source/core/access/AccessibilityCheck.cxx               |   87 +++++++++++++
 5 files changed, 100 insertions(+)

New commits:
commit f03d285d51ba5d5b30e9f8a2b1165270140d5a20
Author:     Paris Oplopoios <paris.oplopo...@collabora.com>
AuthorDate: Mon Oct 17 12:37:30 2022 +0300
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Mon Oct 17 16:32:13 2022 +0200

    a11y: Add check for spacing newlines
    
    Add accessibility check and relevant test for a document that uses
    newlines for spacing
    
    Change-Id: I14f14db5c51cbad1ee184e58eec8ff28563ba92a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141252
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>

diff --git a/sw/inc/AccessibilityCheckStrings.hrc 
b/sw/inc/AccessibilityCheckStrings.hrc
index 858de1a47d93..4d65bd095f51 100644
--- a/sw/inc/AccessibilityCheckStrings.hrc
+++ b/sw/inc/AccessibilityCheckStrings.hrc
@@ -22,6 +22,7 @@
 #define STR_AVOID_FOOTNOTES             NC_("STR_AVOID_FOOTNOTES", "Avoid 
footnotes.")
 #define STR_AVOID_ENDNOTES              NC_("STR_AVOID_ENDNOTES", "Avoid 
endnotes.")
 #define STR_AVOID_BACKGROUND_IMAGES     NC_("STR_AVOID_BACKGROUND_IMAGES", 
"Avoid background images.")
+#define STR_AVOID_NEWLINES_SPACE        NC_("STR_AVOID_NEWLINES_SPACE", "Avoid 
newlines to create space.")
 #define STR_HEADINGS_NOT_IN_ORDER       NC_("STR_HEADINGS_NOT_IN_ORDER", 
"Headings not in order.")
 #define STR_TEXT_FORMATTING_CONVEYS_MEANING 
NC_("STR_TEXT_FORMATTING_CONVEYS_MEANING", "The text formatting conveys 
additional meaning.")
 #define STR_NON_INTERACTIVE_FORMS       NC_("STR_NON_INTERACTIVE_FORMS", "An 
input form is not interactive.")
diff --git a/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx 
b/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx
index 2c36d2b5d4e7..7a60b1578e21 100644
--- a/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx
+++ b/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx
@@ -70,6 +70,18 @@ CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, 
testCheckBackgroundImage)
     CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::DOCUMENT_BACKGROUND, 
aIssues[0]->m_eIssueID);
 }
 
+CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, testCheckNewlineSpace)
+{
+    SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "NewlineTest.odt");
+    CPPUNIT_ASSERT(pDoc);
+    sw::AccessibilityCheck aCheck(pDoc);
+    aCheck.check();
+    auto& aIssues = aCheck.getIssueCollection().getIssues();
+    CPPUNIT_ASSERT_EQUAL(size_t(2), aIssues.size());
+    CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, 
aIssues[0]->m_eIssueID);
+    CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, 
aIssues[1]->m_eIssueID);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/core/accessibilitycheck/data/AccessibilityTests1.odt 
b/sw/qa/core/accessibilitycheck/data/AccessibilityTests1.odt
index 2e319f58e7a2..6b55335e773d 100644
Binary files a/sw/qa/core/accessibilitycheck/data/AccessibilityTests1.odt and 
b/sw/qa/core/accessibilitycheck/data/AccessibilityTests1.odt differ
diff --git a/sw/qa/core/accessibilitycheck/data/NewlineTest.odt 
b/sw/qa/core/accessibilitycheck/data/NewlineTest.odt
new file mode 100644
index 000000000000..9ff715916fc2
Binary files /dev/null and b/sw/qa/core/accessibilitycheck/data/NewlineTest.odt 
differ
diff --git a/sw/source/core/access/AccessibilityCheck.cxx 
b/sw/source/core/access/AccessibilityCheck.cxx
index de0a5bf63472..f56bdf3e0c7b 100644
--- a/sw/source/core/access/AccessibilityCheck.cxx
+++ b/sw/source/core/access/AccessibilityCheck.cxx
@@ -584,6 +584,92 @@ public:
     }
 };
 
+class NewlineSpacingCheck : public NodeCheck
+{
+private:
+    static SwTextNode* getNextTextNode(SwNode* pCurrent)
+    {
+        SwTextNode* pTextNode = nullptr;
+
+        auto nIndex = pCurrent->GetIndex();
+        auto nCount = pCurrent->GetNodes().Count();
+
+        nIndex++; // go to next node
+
+        while (pTextNode == nullptr && nIndex < nCount)
+        {
+            auto pNode = pCurrent->GetNodes()[nIndex];
+            if (pNode->IsTextNode())
+                pTextNode = pNode->GetTextNode();
+            nIndex++;
+        }
+
+        return pTextNode;
+    }
+
+public:
+    NewlineSpacingCheck(sfx::AccessibilityIssueCollection& rIssueCollection)
+        : NodeCheck(rIssueCollection)
+    {
+    }
+    void check(SwNode* pCurrent) override
+    {
+        if (!pCurrent->IsTextNode())
+            return;
+
+        SwTextNode* pTextNode = pCurrent->GetTextNode();
+        auto nParagraphLength = pTextNode->GetText().getLength();
+        if (nParagraphLength == 0)
+        {
+            SwTextNode* pNextTextNode = getNextTextNode(pCurrent);
+            if (!pNextTextNode)
+                return;
+            if (pNextTextNode->GetText().getLength() == 0)
+            {
+                auto pIssue = lclAddIssue(m_rIssueCollection, 
SwResId(STR_AVOID_NEWLINES_SPACE),
+                                          
sfx::AccessibilityIssueID::TEXT_FORMATTING);
+                pIssue->setIssueObject(IssueObject::TEXT);
+                pIssue->setNode(pNextTextNode);
+                SwDoc& rDocument = pNextTextNode->GetDoc();
+                pIssue->setDoc(rDocument);
+            }
+        }
+        else
+        {
+            // Check for excess lines inside this paragraph
+            const OUString& sParagraphText = pTextNode->GetText();
+            int nLineCount = 0;
+            for (sal_Int32 i = 0; i < nParagraphLength; i++)
+            {
+                auto aChar = sParagraphText[i];
+                if (aChar == '\n')
+                {
+                    nLineCount++;
+                    // Looking for 2 newline characters and above as one can 
be part of the line
+                    // break after a sentence
+                    if (nLineCount > 2)
+                    {
+                        auto pIssue
+                            = lclAddIssue(m_rIssueCollection, 
SwResId(STR_AVOID_NEWLINES_SPACE),
+                                          
sfx::AccessibilityIssueID::TEXT_FORMATTING);
+                        pIssue->setIssueObject(IssueObject::TEXT);
+                        pIssue->setNode(pTextNode);
+                        SwDoc& rDocument = pTextNode->GetDoc();
+                        pIssue->setDoc(rDocument);
+                        pIssue->setStart(i);
+                        pIssue->setEnd(i);
+                    }
+                }
+                // Don't count carriage return as normal character
+                else if (aChar != '\r')
+                {
+                    nLineCount = 0;
+                }
+            }
+        }
+    }
+};
+
 class BlinkingTextCheck : public NodeCheck
 {
 private:
@@ -1006,6 +1092,7 @@ void AccessibilityCheck::check()
     
aNodeChecks.push_back(std::make_unique<FloatingTextCheck>(m_aIssueCollection));
     
aNodeChecks.push_back(std::make_unique<TableHeadingCheck>(m_aIssueCollection));
     
aNodeChecks.push_back(std::make_unique<HeadingOrderCheck>(m_aIssueCollection));
+    
aNodeChecks.push_back(std::make_unique<NewlineSpacingCheck>(m_aIssueCollection));
 
     auto const& pNodes = m_pDoc->GetNodes();
     SwNode* pNode = nullptr;

Reply via email to