Insert blank page when first page number is even

When the page number is explicitly changed at a page break,
LibreOffice will insert a blank page if necessary to ensure that
even page numbers appear on "left" pages.

This commit fixes a case that was missed: the case where the page
number of the very first page in the document is explicitly set to
be an even number.

Also:

 - adjust a couple of unit tests which were referring to specific
   physical page numbers, that were not expecting this blank page to be
   there

 - enhance SwModelTestBase::parseDump to support xpath expressions
   evaluating to simple values rather than nodes, for use in a
   test case for this change

Change-Id: I1f41760c3bb17bdffb868cf32a1331de87d1d0e1
Reviewed-on: https://gerrit.libreoffice.org/39858
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
This commit is contained in:
Luke Deller
2017-07-12 20:39:50 +10:00
committed by Miklos Vajna
parent feb463e93f
commit 14bb680949
6 changed files with 64 additions and 12 deletions

View File

@@ -405,15 +405,35 @@ protected:
xmlXPathContextPtr pXmlXpathCtx = xmlXPathNewContext(pXmlDoc);
xmlXPathObjectPtr pXmlXpathObj = xmlXPathEvalExpression(BAD_CAST(aXPath.getStr()), pXmlXpathCtx);
xmlNodeSetPtr pXmlNodes = pXmlXpathObj->nodesetval;
CPPUNIT_ASSERT_EQUAL_MESSAGE("parsing dump failed", 1, xmlXPathNodeSetGetLength(pXmlNodes));
xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0];
OUString aRet;
if (aAttribute.getLength())
aRet = OUString::createFromAscii(reinterpret_cast<char*>(xmlGetProp(pXmlNode, BAD_CAST(aAttribute.getStr()))));
CPPUNIT_ASSERT_MESSAGE("xpath evaluation failed", pXmlXpathObj);
xmlChar *pXpathStrResult;
if (pXmlXpathObj->type == XPATH_NODESET)
{
xmlNodeSetPtr pXmlNodes = pXmlXpathObj->nodesetval;
CPPUNIT_ASSERT_EQUAL_MESSAGE("xpath should match exactly 1 node",
1, xmlXPathNodeSetGetLength(pXmlNodes));
xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0];
if (aAttribute.getLength())
pXpathStrResult = xmlGetProp(pXmlNode, BAD_CAST(aAttribute.getStr()));
else
pXpathStrResult = xmlNodeGetContent(pXmlNode);
}
else
aRet = OUString::createFromAscii(reinterpret_cast<char*>(xmlNodeGetContent(pXmlNode)));
{
// the xpath expression evaluated to a value, not a node
CPPUNIT_ASSERT_EQUAL_MESSAGE(
"attr name should not be supplied when xpath evals to a value",
aAttribute.getLength(), sal_Int32(0));
pXpathStrResult = xmlXPathCastToString(pXmlXpathObj);
CPPUNIT_ASSERT_MESSAGE("xpath result cannot be cast to string",
pXpathStrResult);
}
OUString aRet = OUString(reinterpret_cast<char*>(pXpathStrResult),
xmlStrlen(pXpathStrResult), RTL_TEXTENCODING_UTF8);
xmlFree(pXpathStrResult);
xmlFree(pXmlXpathObj);
xmlFree(pXmlXpathCtx);
xmlFreeDoc(pXmlDoc);
return aRet;

View File

@@ -857,5 +857,18 @@ DECLARE_ODFIMPORT_TEST(testTdf94882, "tdf94882.odt")
CPPUNIT_ASSERT_EQUAL(OUString("This is the first page header"), headertext);
}
DECLARE_ODFIMPORT_TEST(testBlankBeforeFirstPage, "tdf94882.odt")
{
// This document starts on page 50, which is even, so it should have a
// blank page inserted before it to make it a left page
CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be 2 pages output",
OUString("2"), parseDump("count(/root/page)")
);
CPPUNIT_ASSERT_EQUAL_MESSAGE("The first page should be blank",
OUString("0"), parseDump("count(/root/page[1]/body)")
);
}
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@@ -249,7 +249,7 @@ DECLARE_OOXMLEXPORT_TEST(testRelSizeRound, "rel-size-round.docx")
DECLARE_OOXMLEXPORT_TEST(testTestTitlePage, "testTitlePage.docx")
{
CPPUNIT_ASSERT_EQUAL(OUString("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), parseDump("/root/page[2]/footer/txt/text()"));
CPPUNIT_ASSERT_EQUAL(OUString("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), parseDump("/root/page[last()]/footer/txt/text()"));
}
DECLARE_OOXMLEXPORT_TEST(testTableRowDataDisplayedTwice,"table-row-data-displayed-twice.docx")

View File

@@ -591,7 +591,12 @@ DECLARE_WW8EXPORT_TEST(testFdo81102, "fdo81102.doc")
DECLARE_WW8EXPORT_TEST(testBnc787942, "bnc787942.doc")
{
// The frame ended up on the second page instead of first.
parseDump("/root/page[1]/body/txt[4]/anchored");
// Ensure that the anchor is on the same page as the text "Zelva Mana"
// (Note that this can actually be the second physical page, since the
// page number is set to 0 which is even so LO will insert a blank page
// before it to make it a left page)
parseDump("/root/page[body/txt/text()='Zelva Mana']/body/txt[4]/anchored");
}
DECLARE_WW8EXPORT_TEST(testLayoutHanging, "fdo68967.doc")

View File

@@ -537,11 +537,16 @@ void SwRootFrame::Init( SwFrameFormat* pFormat )
mbIsVirtPageNum = false;
if ( !pDesc )
pDesc = &pDoc->GetPageDesc( 0 );
const bool bOdd = !oPgNum || 0 != ( oPgNum.get() % 2 );
const bool bFirst = true;
// Even page numbers are supposed to be printed as left pages. So if a
// page number has been explicitly set for this first page, then we must
// insert a blank page before it to make it a left page.
const bool bInsertEmpty = !bOdd;
// Create a page and put it in the layout
SwPageFrame *pPage = ::InsertNewPage( *pDesc, this, bOdd, bFirst, false, false, nullptr );
SwPageFrame *pPage = ::InsertNewPage( *pDesc, this, bOdd, bFirst, bInsertEmpty, false, nullptr );
// Find the first page in the Bodytext section.
SwLayoutFrame *pLay = pPage->FindBodyCont();

View File

@@ -1745,8 +1745,17 @@ bool SwFrame::OnFirstPage() const
const SwPageFrame* pPrevFrame = dynamic_cast<const SwPageFrame*>(pPage->GetPrev());
if (pPrevFrame)
{
const SwPageDesc* pDesc = pPage->GetPageDesc();
bRet = pPrevFrame->GetPageDesc() != pDesc;
if (pPrevFrame->IsEmptyPage() && pPrevFrame->GetPhyPageNum()==1)
{
// This was the first page of the document, but its page number
// was set to an even number, so a blank page was automatically
// inserted before it to make this be a "left" page.
// We still use the first page format of the page style here.
bRet = true;
} else {
const SwPageDesc* pDesc = pPage->GetPageDesc();
bRet = pPrevFrame->GetPageDesc() != pDesc;
}
}
else
bRet = true;