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.kaganski@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 0000000..357f64f
--- /dev/null
+++ b/sw/qa/extras/layout/data/tdf153136.docx
Binary files differ
diff --git a/sw/qa/extras/layout/layout2.cxx b/sw/qa/extras/layout/layout2.cxx
index 0fa9f99..6ff56e5 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 65f2b4d..5e50f7a 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()