sw/qa/extras/layout/data/tdf153136.docx |binary
 sw/qa/extras/layout/layout2.cxx         |  171 ++++++++++++++++++++++++++++++++
 sw/source/core/text/porlay.cxx          |   19 ++-
 3 files changed, 183 insertions(+), 7 deletions(-)

New commits:
commit 339ab1b2e198a91673352110f54def2a1de90d64
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Mon Jan 23 11:38:52 2023 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Tue Jan 24 11:10:44 2023 +0000

    tdf#153136: fix IgnoreTabsAndBlanksForLineCalculation compat flag
    
    It should handle SPACE, EN SPACE, EM SPACE, FOUR-PER-EM SPACE ,and
    IDEOGRAPHIC SPACE, but not SIX-PER-EM SPACE. The latter was mistakenly
    added in commit 9ee96273a2090b63e0f579a1e9c9cef780756e6d "tdf#123703
    strip six-em-space (U+2006) at line break" (2019-08-24).
    
    Change-Id: I857f303eb19e19f067ad47933fa4b7eb96ce5ca0
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145995
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    (cherry picked from commit 23555ec4058521262860d48d976eba8563d9ba98)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/146029
    Tested-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/sw/qa/extras/layout/data/tdf153136.docx 
b/sw/qa/extras/layout/data/tdf153136.docx
new file mode 100644
index 000000000000..357f64f9a940
Binary files /dev/null and b/sw/qa/extras/layout/data/tdf153136.docx differ
diff --git a/sw/qa/extras/layout/layout2.cxx b/sw/qa/extras/layout/layout2.cxx
index 434bf6376ebc..1e72bd335227 100644
--- a/sw/qa/extras/layout/layout2.cxx
+++ b/sw/qa/extras/layout/layout2.cxx
@@ -2573,6 +2573,177 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf152031)
                                  nLeft_Row2);
 }
 
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf153136)
+{
+    createSwDoc("tdf153136.docx");
+    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+
+    const sal_Int32 small = 300; // Small-height lines are around 276 twip
+    const sal_Int32 large = 1000; // Large-height lines are 1104 twip or more
+
+    // Page 1: standalone paragraphs
+
+    // U+0009 CHARACTER TABULATION: height is ignored
+    sal_Int32 height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[1]", 
"height").toInt32();
+    CPPUNIT_ASSERT_LESS(small, height);
+
+    // U+0020 SPACE: height is ignored
+    height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[2]", 
"height").toInt32();
+    CPPUNIT_ASSERT_LESS(small, height);
+
+    // U+00A0 NO-BREAK SPACE: height is considered
+    height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[3]", 
"height").toInt32();
+    CPPUNIT_ASSERT_GREATER(large, height);
+
+    // U+1680 OGHAM SPACE MARK: height is considered; not tested, because 
Liberation Serif lacks it
+
+    // U+2000 EN QUAD: height is considered
+    height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[4]", 
"height").toInt32();
+    CPPUNIT_ASSERT_GREATER(large, height);
+
+    // U+2001 EM QUAD: height is considered
+    height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[5]", 
"height").toInt32();
+    CPPUNIT_ASSERT_GREATER(large, height);
+
+    // U+2002 EN SPACE: height is ignored
+    height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[6]", 
"height").toInt32();
+    CPPUNIT_ASSERT_LESS(small, height);
+
+    // U+2003 EM SPACE: height is ignored
+    height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[7]", 
"height").toInt32();
+    CPPUNIT_ASSERT_LESS(small, height);
+
+    // U+2004 THREE-PER-EM SPACE: height is considered
+    height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[8]", 
"height").toInt32();
+    CPPUNIT_ASSERT_GREATER(large, height);
+
+    // U+2005 FOUR-PER-EM SPACE: height is ignored
+    height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[9]", 
"height").toInt32();
+    CPPUNIT_ASSERT_LESS(small, height);
+
+    // U+2006 SIX-PER-EM SPACE: height is considered
+    height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[10]", 
"height").toInt32();
+    CPPUNIT_ASSERT_GREATER(large, height);
+
+    // U+2007 FIGURE SPACE: height is considered
+    height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[11]", 
"height").toInt32();
+    CPPUNIT_ASSERT_GREATER(large, height);
+
+    // U+2008 PUNCTUATION SPACE: height is considered
+    height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[12]", 
"height").toInt32();
+    CPPUNIT_ASSERT_GREATER(large, height);
+
+    // U+2009 THIN SPACE: height is considered
+    height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[13]", 
"height").toInt32();
+    CPPUNIT_ASSERT_GREATER(large, height);
+
+    // U+200A HAIR SPACE: height is considered
+    height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[14]", 
"height").toInt32();
+    CPPUNIT_ASSERT_GREATER(large, height);
+
+    // U+202F NARROW NO-BREAK SPACE: height is considered
+    height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[15]", 
"height").toInt32();
+    CPPUNIT_ASSERT_GREATER(large, height);
+
+    // U+205F MEDIUM MATHEMATICAL SPACE: height is considered; not tested, 
because Liberation Serif lacks it
+    // U+3000 IDEOGRAPHIC SPACE: height is ignored; not tested, because 
Liberation Serif lacks it
+
+    // Page 2: table rows (no paragraph-level size DF)
+
+    // U+0020 SPACE: height is ignored
+    height = getXPath(pXmlDoc, "(/root/page[2]//row)[1]/infos/bounds", 
"height").toInt32();
+    CPPUNIT_ASSERT_LESS(small, height);
+
+    // U+00A0 NO-BREAK SPACE: height is considered (1104 or so)
+    height = getXPath(pXmlDoc, "(/root/page[2]//row)[2]/infos/bounds", 
"height").toInt32();
+    CPPUNIT_ASSERT_GREATER(large, height);
+
+    // U+1680 OGHAM SPACE MARK: height is considered; not tested, because 
Liberation Serif lacks it
+
+    // U+2000 EN QUAD: height is considered
+    height = getXPath(pXmlDoc, "(/root/page[2]//row)[3]/infos/bounds", 
"height").toInt32();
+    CPPUNIT_ASSERT_GREATER(large, height);
+
+    // U+2001 EM QUAD: height is considered
+    height = getXPath(pXmlDoc, "(/root/page[2]//row)[4]/infos/bounds", 
"height").toInt32();
+    CPPUNIT_ASSERT_GREATER(large, height);
+
+    // U+2002 EN SPACE: height is ignored
+    height = getXPath(pXmlDoc, "(/root/page[2]//row)[5]/infos/bounds", 
"height").toInt32();
+    CPPUNIT_ASSERT_LESS(small, height);
+
+    // U+2003 EM SPACE: height is ignored
+    height = getXPath(pXmlDoc, "(/root/page[2]//row)[6]/infos/bounds", 
"height").toInt32();
+    CPPUNIT_ASSERT_LESS(small, height);
+
+    // U+2004 THREE-PER-EM SPACE: height is considered
+    height = getXPath(pXmlDoc, "(/root/page[2]//row)[7]/infos/bounds", 
"height").toInt32();
+    CPPUNIT_ASSERT_GREATER(large, height);
+
+    // U+2005 FOUR-PER-EM SPACE: height is ignored
+    height = getXPath(pXmlDoc, "(/root/page[2]//row)[8]/infos/bounds", 
"height").toInt32();
+    CPPUNIT_ASSERT_LESS(small, height);
+
+    // U+2006 SIX-PER-EM SPACE: height is considered
+    height = getXPath(pXmlDoc, "(/root/page[2]//row)[9]/infos/bounds", 
"height").toInt32();
+    CPPUNIT_ASSERT_GREATER(large, height);
+
+    // U+2007 FIGURE SPACE: height is considered
+    height = getXPath(pXmlDoc, "(/root/page[2]//row)[10]/infos/bounds", 
"height").toInt32();
+    CPPUNIT_ASSERT_GREATER(large, height);
+
+    // U+2008 PUNCTUATION SPACE: height is considered
+    height = getXPath(pXmlDoc, "(/root/page[2]//row)[11]/infos/bounds", 
"height").toInt32();
+    CPPUNIT_ASSERT_GREATER(large, height);
+
+    // U+2009 THIN SPACE: height is considered
+    height = getXPath(pXmlDoc, "(/root/page[2]//row)[12]/infos/bounds", 
"height").toInt32();
+    CPPUNIT_ASSERT_GREATER(large, height);
+
+    // U+200A HAIR SPACE: height is considered
+    height = getXPath(pXmlDoc, "(/root/page[2]//row)[13]/infos/bounds", 
"height").toInt32();
+    CPPUNIT_ASSERT_GREATER(large, height);
+
+    // U+202F NARROW NO-BREAK SPACE: height is considered
+    height = getXPath(pXmlDoc, "(/root/page[2]//row)[14]/infos/bounds", 
"height").toInt32();
+    CPPUNIT_ASSERT_GREATER(large, height);
+
+    // U+205F MEDIUM MATHEMATICAL SPACE: height is considered; not tested, 
because Liberation Serif lacks it
+    // U+3000 IDEOGRAPHIC SPACE: height is ignored; not tested, because 
Liberation Serif lacks it
+
+    // TODO: page 3, with table having paragraphs with paragraph-level size DF;
+    // all rows should have large height
+
+    // height = getXPath(pXmlDoc, "(/root/page[3]//row)[1]/infos/bounds", 
"height").toInt32();
+    // CPPUNIT_ASSERT_GREATER(large, height);
+    // height = getXPath(pXmlDoc, "(/root/page[3]//row)[2]/infos/bounds", 
"height").toInt32();
+    // CPPUNIT_ASSERT_GREATER(large, height);
+    // height = getXPath(pXmlDoc, "(/root/page[3]//row)[3]/infos/bounds", 
"height").toInt32();
+    // CPPUNIT_ASSERT_GREATER(large, height);
+    // height = getXPath(pXmlDoc, "(/root/page[3]//row)[4]/infos/bounds", 
"height").toInt32();
+    // CPPUNIT_ASSERT_GREATER(large, height);
+    // height = getXPath(pXmlDoc, "(/root/page[3]//row)[5]/infos/bounds", 
"height").toInt32();
+    // CPPUNIT_ASSERT_GREATER(large, height);
+    // height = getXPath(pXmlDoc, "(/root/page[3]//row)[6]/infos/bounds", 
"height").toInt32();
+    // CPPUNIT_ASSERT_GREATER(large, height);
+    // height = getXPath(pXmlDoc, "(/root/page[3]//row)[7]/infos/bounds", 
"height").toInt32();
+    // CPPUNIT_ASSERT_GREATER(large, height);
+    // height = getXPath(pXmlDoc, "(/root/page[3]//row)[8]/infos/bounds", 
"height").toInt32();
+    // CPPUNIT_ASSERT_GREATER(large, height);
+    // height = getXPath(pXmlDoc, "(/root/page[3]//row)[9]/infos/bounds", 
"height").toInt32();
+    // CPPUNIT_ASSERT_GREATER(large, height);
+    // height = getXPath(pXmlDoc, "(/root/page[3]//row)[10]/infos/bounds", 
"height").toInt32();
+    // CPPUNIT_ASSERT_GREATER(large, height);
+    // height = getXPath(pXmlDoc, "(/root/page[3]//row)[11]/infos/bounds", 
"height").toInt32();
+    // CPPUNIT_ASSERT_GREATER(large, height);
+    // height = getXPath(pXmlDoc, "(/root/page[3]//row)[12]/infos/bounds", 
"height").toInt32();
+    // CPPUNIT_ASSERT_GREATER(large, height);
+    // height = getXPath(pXmlDoc, "(/root/page[3]//row)[13]/infos/bounds", 
"height").toInt32();
+    // CPPUNIT_ASSERT_GREATER(large, height);
+    // height = getXPath(pXmlDoc, "(/root/page[3]//row)[14]/infos/bounds", 
"height").toInt32();
+    // CPPUNIT_ASSERT_GREATER(large, height);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/porlay.cxx b/sw/source/core/text/porlay.cxx
index 65f2b4de3bae..5e50f7ad5873 100644
--- a/sw/source/core/text/porlay.cxx
+++ b/sw/source/core/text/porlay.cxx
@@ -355,20 +355,25 @@ void SwLineLayout::CreateSpaceAdd( const tools::Long 
nInit )
     SetLLSpaceAdd( nInit, 0 );
 }
 
-// Returns true if there are only blanks in [nStt, nEnd[
+// #i3952# Returns true if there are only blanks in [nStt, nEnd[
+// Used to implement IgnoreTabsAndBlanksForLineCalculation compat flag
 static bool lcl_HasOnlyBlanks(std::u16string_view rText, TextFrameIndex nStt, 
TextFrameIndex nEnd)
 {
-    bool bBlankOnly = true;
     while ( nStt < nEnd )
     {
-        const sal_Unicode cChar = rText[ sal_Int32(nStt++) ];
-        if ( ' ' != cChar && CH_FULL_BLANK != cChar && CH_SIX_PER_EM != cChar )
+        switch (rText[sal_Int32(nStt++)])
         {
-            bBlankOnly = false;
-            break;
+        case 0x0020: // SPACE
+        case 0x2002: // EN SPACE
+        case 0x2003: // EM SPACE
+        case 0x2005: // FOUR-PER-EM SPACE
+        case 0x3000: // IDEOGRAPHIC SPACE
+            continue;
+        default:
+            return false;
         }
     }
-    return bBlankOnly;
+    return true;
 }
 
 // Swapped out from FormatLine()

Reply via email to