oox/source/shape/WpsContext.cxx                                    |   86 
++++------
 sw/qa/extras/ooxmlimport/data/tdf153791-shd_overrides_fontRef.docx |binary
 sw/qa/extras/ooxmlimport/ooxmlimport2.cxx                          |   74 
++++++++
 3 files changed, 114 insertions(+), 46 deletions(-)

New commits:
commit e8c46d0067d88832896798678993dc77edd9c493
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Fri Feb 24 15:27:07 2023 +0300
Commit:     Christian Lohmaier <lohmaier+libreoff...@googlemail.com>
CommitDate: Thu Mar 9 12:44:43 2023 +0000

    tdf#153791: paragraph's/character's shd overrides shape style's fontRef
    
    I couldn't find any references to this in documentation (ECMA-376, MS-OE376)
    regarding this, but Word ignores the font properties (including color) 
defined
    in the shape style's fontRef for txbxContent's paragraphs / runs that have 
shd
    elements with non-auto fill color.
    
    Change-Id: Ice634a5eed7b51379649462303300f55358a566f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147630
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    (cherry picked from commit c15412eb96bda1037c12811f5818ed8ce1e603bd)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147844
    Reviewed-by: Christian Lohmaier <lohmaier+libreoff...@googlemail.com>

diff --git a/oox/source/shape/WpsContext.cxx b/oox/source/shape/WpsContext.cxx
index 99656195075b..1d0ecfe95519 100644
--- a/oox/source/shape/WpsContext.cxx
+++ b/oox/source/shape/WpsContext.cxx
@@ -169,62 +169,56 @@ oox::core::ContextHandlerRef 
WpsContext::onCreateContext(sal_Int32 nElementToken
 
                 // Apply character color of the shape to the shape's textbox.
                 uno::Reference<text::XText> xText(mxShape, uno::UNO_QUERY);
-                uno::Reference<text::XTextCursor> xTextCursor = 
xText->createTextCursor();
-                xTextCursor->gotoStart(false);
-                xTextCursor->gotoEnd(true);
-                uno::Reference<beans::XPropertySet> 
xTextBoxPropertySet(xTextCursor,
-                                                                        
uno::UNO_QUERY);
                 uno::Any xCharColor = 
xPropertySet->getPropertyValue("CharColor");
                 Color aColor = COL_AUTO;
                 if ((xCharColor >>= aColor) && aColor != COL_AUTO)
                 {
-                    const uno::Reference<beans::XPropertyState> 
xPropertyState(xTextCursor,
-                                                                               
uno::UNO_QUERY);
-                    const beans::PropertyState ePropertyState
-                        = xPropertyState->getPropertyState("CharColor");
-                    if (ePropertyState == beans::PropertyState_DEFAULT_VALUE)
-                    {
-                        xTextBoxPropertySet->setPropertyValue("CharColor", 
xCharColor);
-                    }
-                    else
+                    // tdf#135923 Apply character color of the shape to the 
textrun
+                    //            when the character color of the textrun is 
default.
+                    // tdf#153791 But only if the run has no background color 
(shd element in OOXML)
+                    if (uno::Reference<container::XEnumerationAccess> 
paraEnumAccess{
+                            xText, uno::UNO_QUERY })
                     {
-                        // tdf#135923 Apply character color of the shape to 
the textrun
-                        //            when the character color of the textrun 
is default.
-                        uno::Reference<container::XEnumerationAccess> 
paraEnumAccess(
-                            xText, uno::UNO_QUERY);
-                        if (paraEnumAccess.is())
-                        {
-                            uno::Reference<container::XEnumeration> paraEnum(
-                                paraEnumAccess->createEnumeration());
+                        uno::Reference<container::XEnumeration> paraEnum(
+                            paraEnumAccess->createEnumeration());
 
-                            while (paraEnum->hasMoreElements())
-                            {
-                                uno::Reference<text::XTextRange> 
xParagraph(paraEnum->nextElement(),
-                                                                            
uno::UNO_QUERY);
-                                uno::Reference<container::XEnumerationAccess> 
runEnumAccess(
-                                    xParagraph, uno::UNO_QUERY);
-                                if (!runEnumAccess.is())
+                        while (paraEnum->hasMoreElements())
+                        {
+                            uno::Reference<text::XTextRange> 
xParagraph(paraEnum->nextElement(),
+                                                                        
uno::UNO_QUERY);
+                            uno::Reference<container::XEnumerationAccess> 
runEnumAccess(
+                                xParagraph, uno::UNO_QUERY);
+                            if (!runEnumAccess.is())
+                                continue;
+                            if (uno::Reference<beans::XPropertySet> 
xParaPropSet{ xParagraph,
+                                                                               
   uno::UNO_QUERY })
+                                if 
((xParaPropSet->getPropertyValue("ParaBackColor") >>= aColor)
+                                    && aColor != COL_AUTO)
                                     continue;
 
-                                uno::Reference<container::XEnumeration> runEnum
-                                    = runEnumAccess->createEnumeration();
+                            uno::Reference<container::XEnumeration> runEnum
+                                = runEnumAccess->createEnumeration();
 
-                                while (runEnum->hasMoreElements())
+                            while (runEnum->hasMoreElements())
+                            {
+                                uno::Reference<text::XTextRange> 
xRun(runEnum->nextElement(),
+                                                                      
uno::UNO_QUERY);
+                                const uno::Reference<beans::XPropertyState> 
xRunState(
+                                    xRun, uno::UNO_QUERY);
+                                if (!xRunState
+                                    || xRunState->getPropertyState("CharColor")
+                                           == 
beans::PropertyState_DEFAULT_VALUE)
                                 {
-                                    uno::Reference<text::XTextRange> 
xRun(runEnum->nextElement(),
-                                                                          
uno::UNO_QUERY);
-                                    const 
uno::Reference<beans::XPropertyState> xRunState(
-                                        xRun, uno::UNO_QUERY);
-                                    if 
(xRunState->getPropertyState("CharColor")
-                                        == beans::PropertyState_DEFAULT_VALUE)
-                                    {
-                                        uno::Reference<beans::XPropertySet> 
xRunPropSet(
-                                            xRun, uno::UNO_QUERY);
-                                        Color aRunColor = COL_AUTO;
-                                        
xRunPropSet->getPropertyValue("CharColor") >>= aRunColor;
-                                        if (aRunColor == COL_AUTO)
-                                            
xRunPropSet->setPropertyValue("CharColor", xCharColor);
-                                    }
+                                    uno::Reference<beans::XPropertySet> 
xRunPropSet(xRun,
+                                                                               
     uno::UNO_QUERY);
+                                    if (!xRunPropSet)
+                                        continue;
+                                    if 
((xRunPropSet->getPropertyValue("CharBackColor") >>= aColor)
+                                        && aColor != COL_AUTO)
+                                        continue;
+                                    if 
(!(xRunPropSet->getPropertyValue("CharColor") >>= aColor)
+                                        || aColor == COL_AUTO)
+                                        
xRunPropSet->setPropertyValue("CharColor", xCharColor);
                                 }
                             }
                         }
diff --git a/sw/qa/extras/ooxmlimport/data/tdf153791-shd_overrides_fontRef.docx 
b/sw/qa/extras/ooxmlimport/data/tdf153791-shd_overrides_fontRef.docx
new file mode 100644
index 000000000000..3706b456ca8e
Binary files /dev/null and 
b/sw/qa/extras/ooxmlimport/data/tdf153791-shd_overrides_fontRef.docx differ
diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx 
b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
index a1110d0d287e..26ad31df3a78 100644
--- a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
+++ b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
@@ -947,6 +947,80 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf152200)
     // Should not crash/hang because of wrong placement of ending fldChar
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testTdf153791)
+{
+    createSwDoc("tdf153791-shd_overrides_fontRef.docx");
+
+    // the first shape (a paragraph with no background)
+    auto xTextBox(getShape(1));
+    CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getProperty<Color>(xTextBox, 
"CharColor"));
+    uno::Reference<text::XTextRange> xRange(xTextBox, uno::UNO_QUERY_THROW);
+    CPPUNIT_ASSERT_EQUAL(OUString("Lorem ipsum"), xRange->getString());
+
+    uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xRange, 
uno::UNO_QUERY_THROW);
+    uno::Reference<container::XEnumeration> xParaEnum = 
xParaEnumAccess->createEnumeration();
+
+    uno::Reference<text::XTextRange> xPara(xParaEnum->nextElement(), 
uno::UNO_QUERY_THROW);
+    CPPUNIT_ASSERT_EQUAL(COL_AUTO, getProperty<Color>(xPara, "ParaBackColor"));
+
+    uno::Reference<container::XEnumerationAccess> xRunEnumAccess(xPara, 
uno::UNO_QUERY_THROW);
+    uno::Reference<container::XEnumeration> xRunEnum = 
xRunEnumAccess->createEnumeration();
+
+    uno::Reference<text::XTextRange> xRun(xRunEnum->nextElement(), 
uno::UNO_QUERY_THROW);
+    CPPUNIT_ASSERT_EQUAL(OUString("Lorem ipsum"), xRun->getString());
+    CPPUNIT_ASSERT_EQUAL(COL_AUTO, getProperty<Color>(xRun, "CharBackColor"));
+    // In the absence of paragraph/character background, the whole paragraph 
is red.
+    CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getProperty<Color>(xRun, "CharColor"));
+
+    // the second shape: two paragraphs
+    xTextBox.set(getShape(2));
+    CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getProperty<Color>(xTextBox, 
"CharColor"));
+    xRange.set(xTextBox, uno::UNO_QUERY_THROW);
+    CPPUNIT_ASSERT_EQUAL(OUString("Lorem ipsum" SAL_NEWLINE_STRING "Lorem 
ipsum"),
+                         xRange->getString());
+
+    xParaEnumAccess.set(xRange, uno::UNO_QUERY_THROW);
+    xParaEnum = xParaEnumAccess->createEnumeration();
+
+    // the first one has paragraph background
+    xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY_THROW);
+    CPPUNIT_ASSERT_EQUAL(Color(0xF0F0F0), getProperty<Color>(xPara, 
"ParaBackColor"));
+
+    xRunEnumAccess.set(xPara, uno::UNO_QUERY_THROW);
+    xRunEnum = xRunEnumAccess->createEnumeration();
+
+    xRun.set(xRunEnum->nextElement(), uno::UNO_QUERY_THROW);
+    CPPUNIT_ASSERT_EQUAL(OUString("Lorem ipsum"), xRun->getString());
+    CPPUNIT_ASSERT_EQUAL(COL_AUTO, getProperty<Color>(xRun, "CharBackColor"));
+    // With paragraph background, the whole paragraph is auto.
+    // Without the fix, this would fail with:
+    // - Expected: rgba[ffffff00]
+    // - Actual  : rgba[ff0000ff]
+    CPPUNIT_ASSERT_EQUAL(COL_AUTO, getProperty<Color>(xRun, "CharColor"));
+
+    // the second paragraph has two runs, the last one with character 
background
+    xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY_THROW);
+    CPPUNIT_ASSERT_EQUAL(COL_AUTO, getProperty<Color>(xPara, "ParaBackColor"));
+
+    xRunEnumAccess.set(xPara, uno::UNO_QUERY_THROW);
+    xRunEnum = xRunEnumAccess->createEnumeration();
+
+    xRun.set(xRunEnum->nextElement(), uno::UNO_QUERY_THROW);
+    CPPUNIT_ASSERT_EQUAL(OUString("Lorem "), xRun->getString());
+    CPPUNIT_ASSERT_EQUAL(COL_AUTO, getProperty<Color>(xRun, "CharBackColor"));
+    // In the absence of paragraph/character background, the run is red
+    CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getProperty<Color>(xRun, "CharColor"));
+
+    xRun.set(xRunEnum->nextElement(), uno::UNO_QUERY_THROW);
+    CPPUNIT_ASSERT_EQUAL(OUString("ipsum"), xRun->getString());
+    CPPUNIT_ASSERT_EQUAL(Color(0xF0F0F0), getProperty<Color>(xRun, 
"CharBackColor"));
+    // With character background, the run is auto.
+    // Without the fix, this would fail with:
+    // - Expected: rgba[ffffff00]
+    // - Actual  : rgba[ff0000ff]
+    CPPUNIT_ASSERT_EQUAL(COL_AUTO, getProperty<Color>(xRun, "CharColor"));
+}
+
 // tests should only be added to ooxmlIMPORT *if* they fail round-tripping in 
ooxmlEXPORT
 
 CPPUNIT_PLUGIN_IMPLEMENT();

Reply via email to