sw/qa/extras/ooxmlexport/data/tdf118947_tableStyle.docx |binary
 sw/qa/extras/ooxmlexport/ooxmlexport13.cxx              |   29 +++
 sw/source/core/unocore/unotbl.cxx                       |  128 ++++++++++++++--
 3 files changed, 141 insertions(+), 16 deletions(-)

New commits:
commit 6bced3c6a1bf8d4652dd6ba75e41b128ce1bfc5c
Author:     Justin Luth <justin.l...@collabora.com>
AuthorDate: Fri Oct 11 11:06:02 2019 +0300
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Nov 27 11:57:10 2019 +0100

    tdf#118947 sw tablestyle: manually scan parents for ::SET
    
    ...since we do not want to find DocDefaults or pool defaults.
    
    This patch mainly does two things.
    1.) Since DocDefaults get merged into root-level styles,
    this patch identifies these DocDefaults as values that
    can be overwritten by table style properties.
    
    2.) Some properties (like left/right margins) are paired
    together, so if one is SET, the other is also initialized
    and reported as SET. These are identified, and
    followed to see if they actually inherit from pool defaults.
    
    Change-Id: I4291c77073858ae23360a9f34d3650bfd5df86ca
    Reviewed-on: https://gerrit.libreoffice.org/81413
    Tested-by: Jenkins
    Reviewed-by: Justin Luth <justin_l...@sil.org>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sw/qa/extras/ooxmlexport/data/tdf118947_tableStyle.docx 
b/sw/qa/extras/ooxmlexport/data/tdf118947_tableStyle.docx
new file mode 100644
index 000000000000..0b40aab5b95b
Binary files /dev/null and 
b/sw/qa/extras/ooxmlexport/data/tdf118947_tableStyle.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
index 64c1fc6cc10a..0d6cdb8b37ae 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
@@ -10,6 +10,7 @@
 #include <swmodeltestbase.hxx>
 
 #include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/style/LineSpacing.hpp>
 #include <com/sun/star/text/WritingMode2.hpp>
 #include <com/sun/star/text/XTextFrame.hpp>
 #include <com/sun/star/drawing/XControlShape.hpp>
@@ -311,6 +312,34 @@ DECLARE_OOXMLEXPORT_TEST(testTdf123636_newlinePageBreak4, 
"tdf123636_newlinePage
     assertXPath(pDump, "/root/page[2]/body/txt[1]/Text", 0);
 }
 
+DECLARE_OOXMLEXPORT_TEST(testTdf118947_tableStyle, "tdf118947_tableStyle.docx")
+{
+    uno::Reference<text::XTextTable> xTable(getParagraphOrTable(1), 
uno::UNO_QUERY);
+    uno::Reference<text::XTextRange> xCell(xTable->getCellByName("A1"), 
uno::UNO_QUERY);
+    uno::Reference<container::XEnumerationAccess> 
xParaEnumAccess(xCell->getText(), uno::UNO_QUERY);
+    uno::Reference<container::XEnumeration> xParaEnum = 
xParaEnumAccess->createEnumeration();
+    uno::Reference<text::XTextRange> xPara(xParaEnum->nextElement(), 
uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(OUString("Table grid settings set line-spacing to 
250% instead of single-spacing, which is set as a document default."), 
xPara->getString());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("TextBody has 10pt font size", 10.f, 
getProperty<float>(xPara, "CharHeight"));
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("TextBody has 1pt space below paragraph", 
sal_Int32(35), getProperty<sal_Int32>(xPara, "ParaBottomMargin"));
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("Table has 10pt space above paragraph", 
sal_Int32(353), getProperty<sal_Int32>(xPara, "ParaTopMargin"));
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("Table style sets 0 right margin", 
sal_Int32(0), getProperty<sal_Int32>(xPara, "ParaRightMargin"));
+    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("TextBody has 1.07 line-spacing", 
sal_Int16(107), getProperty<style::LineSpacing>(xPara, 
"ParaLineSpacing").Height, 1);
+
+    xCell.set(xTable->getCellByName("A2"), uno::UNO_QUERY);
+    xParaEnumAccess.set(xCell->getText(), uno::UNO_QUERY);
+    xParaEnum = xParaEnumAccess->createEnumeration();
+    xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(OUString("Notice that this is 8pt font in 
compatibility mode."), xPara->getString());
+    // Even though not specified, Table-Style distributes the DocDefault 
font/justification unless overrideTableStyleFontSizeAndJustification.
+    // DocDefault is 8pt.
+    //CPPUNIT_ASSERT_EQUAL_MESSAGE("Compat mode has 8pt font size", 8.f, 
getProperty<float>(xPara, "CharHeight"));
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("Normal has 0pt space below paragraph", 
sal_Int32(0), getProperty<sal_Int32>(xPara, "ParaBottomMargin"));
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("Table sets 10pt space above paragraph", 
sal_Int32(353), getProperty<sal_Int32>(xPara, "ParaTopMargin"));
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("Table style sets 0 right margin", 
sal_Int32(0), getProperty<sal_Int32>(xPara, "ParaRightMargin"));
+    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Table sets 2.5 line-spacing", 
sal_Int16(250), getProperty<style::LineSpacing>(xPara, 
"ParaLineSpacing").Height, 1);
+}
+
 DECLARE_OOXMLEXPORT_TEST(tdf123912_protectedForm, 
"tdf123912_protectedForm.odt")
 {
     SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument 
*>(mxComponent.get());
diff --git a/sw/source/core/unocore/unotbl.cxx 
b/sw/source/core/unocore/unotbl.cxx
index 77330375aebf..34c2b1bfb2ca 100644
--- a/sw/source/core/unocore/unotbl.cxx
+++ b/sw/source/core/unocore/unotbl.cxx
@@ -982,6 +982,67 @@ uno::Reference< beans::XPropertySetInfo >  
SwXCell::getPropertySetInfo()
     return xRef;
 }
 
+// If the current property matches the previous parent's property (i.e. no 
reason for it to be set),
+// then it may be a ::DEFAULT value, even if it is marked as ::SET
+static bool lcl_mayBeDefault( const sal_uInt16 nWhich, sal_uInt8 nMemberId,
+                       const SfxPoolItem* pPrevItem, const SfxPoolItem& 
rCurrItem,
+                       const bool bDirect )
+{
+    bool bMayBeDefault = false;
+    // These are the paragraph/character pairs that I found running unit tests.
+    // UNFORTUNATELY there is no way to see if a property has multiple members.
+    // Since valid members can be nMemberId == 0, we can't do something like 
"if (nMemberId & ~CONVERT_TWIPS) != 0"
+    // Perhaps the full list can be found in editeng/memberids.h???
+    switch ( nWhich )
+    {
+        case RES_BOX:
+        case RES_UL_SPACE:
+        case RES_LR_SPACE:
+        case RES_CHRATR_ESCAPEMENT:
+        case RES_CHRATR_FONT:
+        case RES_CHRATR_CJK_FONT:
+        case RES_CHRATR_CTL_FONT:
+        case RES_CHRATR_FONTSIZE:
+        case RES_CHRATR_CJK_FONTSIZE:
+        case RES_CHRATR_CTL_FONTSIZE:
+        case RES_CHRATR_WEIGHT:
+        case RES_CHRATR_CJK_WEIGHT:
+        case RES_CHRATR_CTL_WEIGHT:
+        case RES_CHRATR_LANGUAGE:
+        case RES_CHRATR_CJK_LANGUAGE:
+        case RES_CHRATR_CTL_LANGUAGE:
+        case RES_CHRATR_POSTURE:
+        case RES_CHRATR_CJK_POSTURE:
+        case RES_CHRATR_CTL_POSTURE:
+        case RES_PARATR_ADJUST:
+        {
+            // These properties are paired up, containing multiple properties 
in one nWhich.
+            // If one is ::SET, they all report ::SET, even if only 
initialized with the default value.
+            // Assume created automatically by another MemberId.
+            bMayBeDefault = true;
+            if ( pPrevItem )
+            {
+                uno::Any aPrev;
+                uno::Any aCurr;
+                (*pPrevItem).QueryValue(aPrev, nMemberId);
+                rCurrItem.QueryValue(aCurr, nMemberId);
+                // If different, it overrides a parent value, so can't be 
considered a default.
+                bMayBeDefault = aPrev == aCurr;
+            }
+            break;
+        }
+        default:
+        {
+            // Since DocDefaults are copied into root-level stylesheets 
(tdf#103961),
+            // identify the duplicated properties as DocDefault values.
+            // Assume any style information could have been inherited/copied.
+            if ( !bDirect )
+                bMayBeDefault = !pPrevItem || *pPrevItem == rCurrItem;
+        }
+    }
+    return bMayBeDefault;
+}
+
 void SwXCell::setPropertyValue(const OUString& rPropertyName, const uno::Any& 
aValue)
 {
     SolarMutexGuard aGuard;
@@ -1024,26 +1085,61 @@ void SwXCell::setPropertyValue(const OUString& 
rPropertyName, const uno::Any& aV
                 while ( &aIdx.GetNode() != pEndNd )
                 {
                     const SwTextNode* pNd = aIdx.GetNode().GetTextNode();
-                    if ( pNd )
+                    ++aIdx;
+                    if ( !pNd )
+                        continue;
+
+                    const SfxPoolItem* pPrevItem = nullptr;
+                    const SfxPoolItem* pCurrItem = nullptr;
+                    // Table-styles don't override direct formatting
+                    if ( pNd->HasSwAttrSet() && SfxItemState::SET == 
pNd->GetSwAttrSet().GetItemState(pEntry->nWID, false, &pCurrItem) )
                     {
-                        //point and mark selecting the whole paragraph
-                        SwPaM aPaM(*pNd, 0, *pNd, pNd->GetText().getLength());
-                        const bool bHasAttrSet = pNd->HasSwAttrSet();
-                        const SfxItemSet& aSet = pNd->GetSwAttrSet();
-                        // isPARATR: replace DEFAULT_VALUE properties only
-                        // Require that the property is default in the 
paragraph style as well,
-                        // unless the style is the default style.
-                        // isCHRATR: change the base/auto SwAttr property, but 
don't remove the DIRECT hints
-                        bool bCustomParent = false;
-                        if (const SwFormatColl* pFormatColl = 
pNd->GetFormatColl())
+                        // Some WIDs have several MIDs, so perhaps ::SET 
refers to another MID and this property was copied from parents?
+                        if ( lcl_mayBeDefault(pEntry->nWID, pEntry->nMemberId, 
pPrevItem, *pCurrItem, /*bDirect=*/true) )
+                            pPrevItem = pCurrItem;
+                        else
+                            continue; //don't override direct formatting
+                    }
+
+                    bool bSet = false;
+                    // HACK: don't check styles if numbering/bullets are 
turned on. Table-styles don't override numbering formatting
+                    SwFormat* pFormatColl = pNd->GetNumRule() ? nullptr : 
pNd->GetFormatColl();
+                    // Manually walk through the parent properties in order to 
avoid the default properties.
+                    // Table-styles don't override paragraph-style formatting.
+                    //    TODO: ?except for fontsize/justification if 
compat:overrideTableStyleFontSizeAndJustification?
+                    while ( pFormatColl )
+                    {
+                        if ( SfxItemState::SET == 
pFormatColl->GetItemState(pEntry->nWID, /*bSrchInParent=*/false, &pCurrItem) )
                         {
-                            bCustomParent = pFormatColl->GetPoolFormatId() != 
RES_POOLCOLL_STANDARD;
+                            if ( lcl_mayBeDefault(pEntry->nWID, 
pEntry->nMemberId, pPrevItem, *pCurrItem, false) )
+                            {
+                                // if the property matches DocDefaults, then 
table-style needs to override it
+                                pPrevItem = pFormatColl->IsDefault() ? nullptr 
: pCurrItem;
+                            }
+                            else
+                            {
+                                bSet = true; //don't override style formatting
+                                break;
+                            }
                         }
-                        bool bSearchInParent = bCustomParent && 
!pNd->GetNumRule();
-                        if ( !bHasAttrSet || SfxItemState::DEFAULT == 
aSet.GetItemState(pEntry->nWID, bSearchInParent) )
-                            SwUnoCursorHelper::SetPropertyValue(aPaM, 
rParaPropSet, rPropertyName, aValue, SetAttrMode::DONTREPLACE);
+                        pFormatColl = pFormatColl->DerivedFrom();
                     }
-                    ++aIdx;
+                    if ( bSet )
+                        continue;
+
+                    // Check if previous ::SET came from the pool defaults.
+                    if ( pPrevItem && pNd->GetSwAttrSet().GetPool() )
+                    {
+                        pCurrItem = 
&pNd->GetSwAttrSet().GetPool()->GetDefaultItem(pEntry->nWID);
+                        if ( !lcl_mayBeDefault(pEntry->nWID, 
pEntry->nMemberId, pPrevItem, *pCurrItem, false) )
+                            continue;
+                    }
+
+                    // Apply table-style property
+                    // point and mark selecting the whole paragraph
+                    SwPaM aPaM(*pNd, 0, *pNd, pNd->GetText().getLength());
+                    // for isCHRATR: change the base/auto SwAttr property, but 
don't remove the DIRECT hints
+                    SwUnoCursorHelper::SetPropertyValue(aPaM, rParaPropSet, 
rPropertyName, aValue, SetAttrMode::DONTREPLACE);
                 }
                 return;
             }
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to