[Libreoffice-commits] core.git: sw/qa sw/source writerfilter/source

Mike Kaganski mike.kaganski at collabora.com
Tue Sep 12 12:28:45 UTC 2017


 sw/qa/extras/ww8import/data/tdf112346.doc   |binary
 sw/qa/extras/ww8import/ww8import.cxx        |    8 ++
 sw/source/filter/ww8/ww8par.cxx             |  103 +++++++++++++++++++++-------
 sw/source/filter/ww8/ww8par.hxx             |    1 
 sw/source/filter/ww8/ww8par6.cxx            |   15 ----
 writerfilter/source/dmapper/PropertyMap.cxx |   11 ++
 6 files changed, 97 insertions(+), 41 deletions(-)

New commits:
commit a952d1f59f4f84380b82f1eb9e550b8f69c4be5d
Author: Mike Kaganski <mike.kaganski at collabora.com>
Date:   Tue Sep 12 13:54:26 2017 +0300

    tdf#112346: take Word no-wrap limit into account also for ww8
    
    This also makes ww8 floating-table conversion decision heuristics
    somewhat closer to OOXML code.
    
    Change-Id: I29ca2ebabd1758ad98e02aaf560cf2f44daec3a8
    Reviewed-on: https://gerrit.libreoffice.org/42196
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>

diff --git a/sw/qa/extras/ww8import/data/tdf112346.doc b/sw/qa/extras/ww8import/data/tdf112346.doc
new file mode 100644
index 000000000000..af0cca219acf
Binary files /dev/null and b/sw/qa/extras/ww8import/data/tdf112346.doc differ
diff --git a/sw/qa/extras/ww8import/ww8import.cxx b/sw/qa/extras/ww8import/ww8import.cxx
index 5ea85cc7360b..907fe47ebcff 100644
--- a/sw/qa/extras/ww8import/ww8import.cxx
+++ b/sw/qa/extras/ww8import/ww8import.cxx
@@ -131,6 +131,14 @@ DECLARE_WW8IMPORT_TEST(testTdf106799, "tdf106799.doc")
         }
 }
 
+DECLARE_WW8IMPORT_TEST(testTdf112346, "tdf112346.doc")
+{
+    uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY);
+    uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+    // This was 1, multi-page table was imported as a floating one.
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), xDrawPage->getCount());
+}
+
 // tests should only be added to ww8IMPORT *if* they fail round-tripping in ww8EXPORT
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/filter/ww8/ww8par.cxx b/sw/source/filter/ww8/ww8par.cxx
index a135234ee669..196e8c7fcad8 100644
--- a/sw/source/filter/ww8/ww8par.cxx
+++ b/sw/source/filter/ww8/ww8par.cxx
@@ -93,6 +93,7 @@
 #include <charfmt.hxx>
 #include <unocrsr.hxx>
 #include <IDocumentSettingAccess.hxx>
+#include <sprmids.hxx>
 
 #include <fltini.hxx>
 
@@ -2501,6 +2502,83 @@ void SwWW8ImplReader::EndSpecial()
     OSL_ENSURE(!m_nInTable, "unclosed table!");
 }
 
+bool SwWW8ImplReader::FloatingTableConversion(WW8PLCFx_Cp_FKP* pPap)
+{
+    // This is ww8 version of the code deciding if the table needs to be
+    // in a floating frame.
+    // For OOXML code, see SectionPropertyMap::FloatingTableConversion in
+    // writerfilter/source/dmapper/PropertyMap.cxx
+    // The two should do ~same, so if you make changes here, please check
+    // that the other is in sync.
+
+    // Note that this is just a list of heuristics till sw core can have a
+    // table that is floating and can span over multiple pages at the same
+    // time.
+
+    bool bResult = true;
+
+    SprmResult aRes = pPap->HasSprm(NS_sprm::sprmTDefTable);
+    if (nullptr != aRes.pSprm)
+    {
+        bResult = false;
+        WW8TabBandDesc aDesc;
+        aDesc.ReadDef(false, aRes.pSprm);
+        int nTextAreaWidth = m_aSectionManager.GetTextAreaWidth();
+        int nTableWidth = aDesc.nCenter[aDesc.nWwCols] - aDesc.nCenter[0];
+
+        // It seems Word has a limit here, so that in case the table width is quite
+        // close to the text area width, then it won't perform a wrapping, even in
+        // case the content (e.g. an empty paragraph) would fit. The magic constant
+        // here represents this limit.
+        const int nMagicNumber = 469;
+
+        // If the table is wider than the text area, then don't create a fly
+        // for the table: no wrapping will be performed anyway, but multi-page
+        // tables will be broken.
+        if ((nTableWidth + nMagicNumber) < nTextAreaWidth)
+            bResult = true;
+
+        // If there are columns, do create a fly, as the flow of the columns
+        // would otherwise restrict the table.
+        if (!bResult && (m_aSectionManager.CurrentSectionColCount() >= 2))
+            bResult = true;
+    }
+
+    if (bResult)
+    {
+        WW8PLCFxSave1 aSave;
+        pPap->Save(aSave);
+        if (SearchTableEnd(pPap))
+        {
+            // Table is considered to be imported into a fly frame and we
+            // know where the end of the table is.
+            bool bIsUnicode;
+            WW8_FC nFc = m_xSBase->WW8Cp2Fc(pPap->Where(), &bIsUnicode);
+            sal_uInt64 nPos = m_pStrm->Tell();
+            m_pStrm->Seek(nFc);
+            sal_uInt16 nUChar = 0;
+            if (bIsUnicode)
+                m_pStrm->ReadUInt16(nUChar);
+            else
+            {
+                sal_uInt8 nChar = 0;
+                m_pStrm->ReadUChar(nChar);
+                nUChar = nChar;
+            }
+            m_pStrm->Seek(nPos);
+            if (nUChar == 0xc)
+                // The pap after the table starts with a page break, so
+                // there will be no wrapping around the float-table.
+                // Request no fly in this case, so the table can properly
+                // be a multi-page one if necessary.
+                bResult = false;
+        }
+        pPap->Restore(aSave);
+    }
+
+    return bResult;
+}
+
 bool SwWW8ImplReader::ProcessSpecial(bool &rbReSync, WW8_CP nStartCp)
 {
     // Frame/Table/Anl
@@ -2575,31 +2653,6 @@ bool SwWW8ImplReader::ProcessSpecial(bool &rbReSync, WW8_CP nStartCp)
             if (bHasRowEnd && ParseTabPos(&aTabPos,pPap))
                 pTabPos = &aTabPos;
 
-            if (pTabPos && !pTabPos->bNoFly && SearchTableEnd(pPap))
-            {
-                // Table is considered to be imported into a fly frame and we
-                // know where the end of the table is.
-                bool bIsUnicode;
-                WW8_FC nFc = m_xSBase->WW8Cp2Fc(pPap->Where(), &bIsUnicode);
-                sal_uInt64 nPos = m_pStrm->Tell();
-                m_pStrm->Seek(nFc);
-                sal_uInt16 nUChar = 0;
-                if (bIsUnicode)
-                    m_pStrm->ReadUInt16(nUChar);
-                else
-                {
-                    sal_uInt8 nChar = 0;
-                    m_pStrm->ReadUChar(nChar);
-                    nUChar = nChar;
-                }
-                m_pStrm->Seek(nPos);
-                if (nUChar == 0xc)
-                    // The pap after the table starts with a page break, so
-                    // there will be no wrapping around the float-table.
-                    // Request no fly in this case, so the table can properly
-                    // be a multi-page one if necessary.
-                    pTabPos->bNoFly = true;
-            }
             m_xPlcxMan->GetPap()->Restore( aSave );
         }
 
diff --git a/sw/source/filter/ww8/ww8par.hxx b/sw/source/filter/ww8/ww8par.hxx
index a0d54fcdbbfd..cfb3ed81ad89 100644
--- a/sw/source/filter/ww8/ww8par.hxx
+++ b/sw/source/filter/ww8/ww8par.hxx
@@ -1867,6 +1867,7 @@ public:     // really private, but can only be done public
     bool SearchRowEnd(WW8PLCFx_Cp_FKP* pPap,WW8_CP &rStartCp, int nLevel) const;
     /// Seek to the end of the table with pPap, returns true on success.
     bool SearchTableEnd(WW8PLCFx_Cp_FKP* pPap) const;
+    bool FloatingTableConversion(WW8PLCFx_Cp_FKP* pPap);
 
     const WW8Fib& GetFib() const    { return *m_xWwFib; }
     SwDoc& GetDoc() const           { return m_rDoc; }
diff --git a/sw/source/filter/ww8/ww8par6.cxx b/sw/source/filter/ww8/ww8par6.cxx
index 6be1868af08a..2130cdc25f39 100644
--- a/sw/source/filter/ww8/ww8par6.cxx
+++ b/sw/source/filter/ww8/ww8par6.cxx
@@ -5099,22 +5099,9 @@ bool SwWW8ImplReader::ParseTabPos(WW8_TablePos *pTabPos, WW8PLCFx_Cp_FKP* pPap)
         aRes = pPap->HasSprm(0x941F);
         if (aRes.pSprm && aRes.nRemainingData >= 2)
             pTabPos->nLoMgn = SVBT16ToShort(aRes.pSprm);
+        pTabPos->bNoFly = !FloatingTableConversion(pPap);
         bRet = true;
     }
-    aRes = pPap->HasSprm(NS_sprm::sprmTDefTable);
-    if (nullptr != aRes.pSprm)
-    {
-        WW8TabBandDesc aDesc;
-        aDesc.ReadDef(false, aRes.pSprm);
-        int nTableWidth = aDesc.nCenter[aDesc.nWwCols] - aDesc.nCenter[0];
-        int nTextAreaWidth = m_aSectionManager.GetTextAreaWidth();
-        // If the table is wider than the text area, then don't create a fly
-        // for the table: no wrapping will be performed anyway, but multi-page
-        // tables will be broken.
-        // If there are columns, do create a fly, as the flow of the columns
-        // would otherwise restrict the table.
-        pTabPos->bNoFly = nTableWidth >= nTextAreaWidth  && m_aSectionManager.CurrentSectionColCount() < 2;
-    }
     return bRet;
 }
 
diff --git a/writerfilter/source/dmapper/PropertyMap.cxx b/writerfilter/source/dmapper/PropertyMap.cxx
index 6ba8e6c20084..36fd67761a4b 100644
--- a/writerfilter/source/dmapper/PropertyMap.cxx
+++ b/writerfilter/source/dmapper/PropertyMap.cxx
@@ -1010,6 +1010,13 @@ void SectionPropertyMap::HandleMarginsHeaderFooter( bool bFirstPage, DomainMappe
 
 bool SectionPropertyMap::FloatingTableConversion( DomainMapper_Impl& rDM_Impl, FloatingTableInfo& rInfo )
 {
+    // This is OOXML version of the code deciding if the table needs to be
+    // in a floating frame.
+    // For ww8 code, see SwWW8ImplReader::FloatingTableConversion in
+    // sw/source/filter/ww8/ww8par.cxx
+    // The two should do the same, so if you make changes here, please check
+    // that the other is in sync.
+
     // Note that this is just a list of heuristics till sw core can have a
     // table that is floating and can span over multiple pages at the same
     // time.
@@ -1063,9 +1070,9 @@ bool SectionPropertyMap::FloatingTableConversion( DomainMapper_Impl& rDM_Impl, F
 
     // If the position is relative to the edge of the page, then we need to check the whole
     // page width to see whether text can fit next to the table.
-    if ( rInfo.getPropertyValue( "HoriOrientRelation" ) == text::RelOrientation::PAGE_FRAME )
+    if ( nHoriOrientRelation == text::RelOrientation::PAGE_FRAME )
     {
-        // If the table is wide enough to that no text fits next to it, then don't create a fly
+        // If the table is wide enough so that no text fits next to it, then don't create a fly
         // for the table: no wrapping will be performed anyway, but multi-page
         // tables will be broken.
         if ((nTableWidth + nMagicNumber) < (nPageWidth - std::min(GetLeftMargin(), GetRightMargin())))


More information about the Libreoffice-commits mailing list