sw/qa/filter/ww8/ww8.cxx                     |   30 ++++++++++++++++++++++++
 sw/source/filter/ww8/attributeoutputbase.hxx |    2 -
 sw/source/filter/ww8/docxattributeoutput.cxx |   33 ++++++++++++++++++---------
 sw/source/filter/ww8/docxattributeoutput.hxx |    2 -
 sw/source/filter/ww8/rtfattributeoutput.cxx  |    3 +-
 sw/source/filter/ww8/rtfattributeoutput.hxx  |    3 +-
 sw/source/filter/ww8/wrtw8nds.cxx            |   31 ++++++++++++++++++++++---
 sw/source/filter/ww8/ww8atr.cxx              |    2 -
 sw/source/filter/ww8/ww8attributeoutput.hxx  |    2 -
 9 files changed, 89 insertions(+), 19 deletions(-)

New commits:
commit ae1e1d0910f4724d661cb6be26773ae51fac33e2
Author:     Szymon Kłos <szymon.k...@collabora.com>
AuthorDate: Tue Nov 29 10:09:10 2022 +0100
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Mon Jan 9 16:45:50 2023 +0000

    docx: export symbol characters correctly
    
    Previously we had:
    after save: <w:t></w:t>
    original content: <w:sym w:font="Wingdings" w:char="F0E0"/>
    
    This patch checks if paragraph has symbol font used and exports
    content using w:sym mark in that case
    
    Change-Id: I74f4bb0d249cbf5dfc930e931f7d91bd0d2e9821
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143455
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144949
    Tested-by: Jenkins
    Reviewed-by: Szymon Kłos <szymon.k...@collabora.com>
    (cherry picked from commit 87e82f80e87bb4a216ea83383864d494f3e92eea)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145219
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/sw/qa/filter/ww8/ww8.cxx b/sw/qa/filter/ww8/ww8.cxx
index 8a2f97438d7b..611d63259ae8 100644
--- a/sw/qa/filter/ww8/ww8.cxx
+++ b/sw/qa/filter/ww8/ww8.cxx
@@ -9,6 +9,7 @@
 
 #include <swmodeltestbase.hxx>
 
+#include <com/sun/star/awt/CharSet.hpp>
 #include <com/sun/star/text/XTextDocument.hpp>
 
 #include <docsh.hxx>
@@ -159,6 +160,35 @@ CPPUNIT_TEST_FIXTURE(Test, 
testDocxContentControlDropdownEmptyDisplayText)
     // i.e. we wrote an empty attribute instead of omitting it.
     assertXPathNoAttribute(pXmlDoc, 
"//w:sdt/w:sdtPr/w:dropDownList/w:listItem", "displayText");
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testDocxSymbolFontExport)
+{
+    // Create document with symbol character and font Wingdings
+    mxComponent = loadFromDesktop("private:factory/swriter");
+    uno::Reference<lang::XMultiServiceFactory> xMSF(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<text::XTextDocument> xTextDocument(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<text::XText> xText = xTextDocument->getText();
+    uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
+
+    xText->insertString(xCursor, u"", true);
+
+    uno::Reference<text::XTextRange> xRange = xCursor;
+    uno::Reference<beans::XPropertySet> xTextProps(xRange, uno::UNO_QUERY);
+    xTextProps->setPropertyValue("CharFontName", 
uno::Any(OUString("Wingdings")));
+    xTextProps->setPropertyValue("CharFontNameAsian", 
uno::Any(OUString("Wingdings")));
+    xTextProps->setPropertyValue("CharFontNameComplex", 
uno::Any(OUString("Wingdings")));
+    xTextProps->setPropertyValue("CharFontCharSet", 
uno::Any(awt::CharSet::SYMBOL));
+
+    // When exporting to DOCX:
+    save("Office Open XML Text");
+
+    // Then make sure the expected markup is used:
+    xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml");
+
+    assertXPath(pXmlDoc, "//w:p/w:r/w:sym", 1);
+    assertXPath(pXmlDoc, "//w:p/w:r/w:sym[1]", "font", "Wingdings");
+    assertXPath(pXmlDoc, "//w:p/w:r/w:sym[1]", "char", "f0e0");
+}
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/filter/ww8/attributeoutputbase.hxx 
b/sw/source/filter/ww8/attributeoutputbase.hxx
index ac3164ae2de6..99cae10812cc 100644
--- a/sw/source/filter/ww8/attributeoutputbase.hxx
+++ b/sw/source/filter/ww8/attributeoutputbase.hxx
@@ -191,7 +191,7 @@ public:
     virtual void WritePostitFieldReference() {};
 
     /// Output text (inside a run).
-    virtual void RunText( const OUString& rText, rtl_TextEncoding eCharSet = 
RTL_TEXTENCODING_UTF8 ) = 0;
+    virtual void RunText( const OUString& rText, rtl_TextEncoding eCharSet = 
RTL_TEXTENCODING_UTF8, const OUString& rSymbolFont = OUString() ) = 0;
 
     /// Output text (without markup).
     virtual void RawText(const OUString& rText, rtl_TextEncoding eCharSet) = 0;
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx 
b/sw/source/filter/ww8/docxattributeoutput.cxx
index 4f527862bf0a..80f09a85562f 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -3425,7 +3425,8 @@ bool DocxAttributeOutput::FootnoteEndnoteRefTag()
     the switch in DocxAttributeOutput::RunText() nicer ;-)
  */
 static bool impl_WriteRunText( FSHelperPtr const & pSerializer, sal_Int32 
nTextToken,
-        const sal_Unicode* &rBegin, const sal_Unicode* pEnd, bool bMove = true 
)
+        const sal_Unicode* &rBegin, const sal_Unicode* pEnd, bool bMove = true,
+        const OUString& rSymbolFont = OUString() )
 {
     const sal_Unicode *pBegin = rBegin;
 
@@ -3436,22 +3437,34 @@ static bool impl_WriteRunText( FSHelperPtr const & 
pSerializer, sal_Int32 nTextT
     if ( pBegin >= pEnd )
         return false; // we want to write at least one character
 
-    // we have to add 'preserve' when starting/ending with space
-    if ( *pBegin == ' ' || *( pEnd - 1 ) == ' ' )
+    bool bIsSymbol = !rSymbolFont.isEmpty();
+
+    std::u16string_view aView( pBegin, pEnd - pBegin );
+    if (bIsSymbol)
     {
-        pSerializer->startElementNS(XML_w, nTextToken, FSNS(XML_xml, 
XML_space), "preserve");
+        for (char16_t aChar : aView)
+        {
+            pSerializer->singleElementNS(XML_w, XML_sym,
+                FSNS(XML_w, XML_font), rSymbolFont,
+                FSNS(XML_w, XML_char), OString::number(aChar, 16));
+        }
     }
     else
-        pSerializer->startElementNS(XML_w, nTextToken);
-
-    pSerializer->writeEscaped( std::u16string_view( pBegin, pEnd - pBegin ) );
+    {
+        // we have to add 'preserve' when starting/ending with space
+        if ( *pBegin == ' ' || *( pEnd - 1 ) == ' ' )
+            pSerializer->startElementNS(XML_w, nTextToken, FSNS(XML_xml, 
XML_space), "preserve");
+        else
+            pSerializer->startElementNS(XML_w, nTextToken);
 
-    pSerializer->endElementNS( XML_w, nTextToken );
+        pSerializer->writeEscaped( aView );
+        pSerializer->endElementNS( XML_w, nTextToken );
+    }
 
     return true;
 }
 
-void DocxAttributeOutput::RunText( const OUString& rText, rtl_TextEncoding 
/*eCharSet*/ )
+void DocxAttributeOutput::RunText( const OUString& rText, rtl_TextEncoding 
/*eCharSet*/, const OUString& rSymbolFont )
 {
     if( m_closeHyperlinkInThisRun )
     {
@@ -3516,7 +3529,7 @@ void DocxAttributeOutput::RunText( const OUString& rText, 
rtl_TextEncoding /*eCh
         }
     }
 
-    impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pEnd, false );
+    impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pEnd, false, 
rSymbolFont );
 }
 
 void DocxAttributeOutput::RawText(const OUString& rText, rtl_TextEncoding 
/*eCharSet*/)
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx 
b/sw/source/filter/ww8/docxattributeoutput.hxx
index f8da5a4bd32d..b8614169c954 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -203,7 +203,7 @@ public:
     virtual void WritePostitFieldReference() override;
 
     /// Output text (inside a run).
-    virtual void RunText( const OUString& rText, rtl_TextEncoding eCharSet = 
RTL_TEXTENCODING_UTF8 ) override;
+    virtual void RunText( const OUString& rText, rtl_TextEncoding eCharSet = 
RTL_TEXTENCODING_UTF8, const OUString& rSymbolFont = OUString() ) override;
 
     /// Output text (without markup).
     virtual void RawText(const OUString& rText, rtl_TextEncoding eCharSet) 
override;
diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx 
b/sw/source/filter/ww8/rtfattributeoutput.cxx
index cd2f81a2463e..c1221069936b 100644
--- a/sw/source/filter/ww8/rtfattributeoutput.cxx
+++ b/sw/source/filter/ww8/rtfattributeoutput.cxx
@@ -515,7 +515,8 @@ OString RtfAttributeOutput::MoveCharacterProperties(bool 
aAutoWriteRtlLtr)
     return aBuf.makeStringAndClear();
 }
 
-void RtfAttributeOutput::RunText(const OUString& rText, rtl_TextEncoding 
/*eCharSet*/)
+void RtfAttributeOutput::RunText(const OUString& rText, rtl_TextEncoding 
/*eCharSet*/,
+                                 const OUString& /*rSymbolFont*/)
 {
     SAL_INFO("sw.rtf", __func__ << ", rText: " << rText);
     RawText(rText, m_rExport.GetCurrentEncoding());
diff --git a/sw/source/filter/ww8/rtfattributeoutput.hxx 
b/sw/source/filter/ww8/rtfattributeoutput.hxx
index 0ecf103a74fb..5042b523ba1a 100644
--- a/sw/source/filter/ww8/rtfattributeoutput.hxx
+++ b/sw/source/filter/ww8/rtfattributeoutput.hxx
@@ -85,7 +85,8 @@ public:
     void EndRunProperties(const SwRedlineData* pRedlineData) override;
 
     /// Output text (inside a run).
-    void RunText(const OUString& rText, rtl_TextEncoding eCharSet = 
RTL_TEXTENCODING_UTF8) override;
+    void RunText(const OUString& rText, rtl_TextEncoding eCharSet = 
RTL_TEXTENCODING_UTF8,
+                 const OUString& rSymbolFont = OUString()) override;
 
     // Access to (anyway) private buffers, used by the sdr exporter
     OStringBuffer& RunText();
diff --git a/sw/source/filter/ww8/wrtw8nds.cxx 
b/sw/source/filter/ww8/wrtw8nds.cxx
index 8b2f09d88023..3b6f4c2b47ed 100644
--- a/sw/source/filter/ww8/wrtw8nds.cxx
+++ b/sw/source/filter/ww8/wrtw8nds.cxx
@@ -2224,6 +2224,25 @@ bool MSWordExportBase::NeedTextNodeSplit( const 
SwTextNode& rNd, SwSoftPageBreak
     return pList.size() > 2 && NeedSectionBreak( rNd );
 }
 
+namespace {
+OUString lcl_GetSymbolFont(SwAttrPool& rPool, const SwTextNode* pTextNode, int 
nStart, int nEnd)
+{
+    SfxItemSetFixed<RES_CHRATR_FONT, RES_CHRATR_FONT> aSet( rPool );
+    if ( pTextNode && pTextNode->GetParaAttr(aSet, nStart, nEnd) )
+    {
+        SfxPoolItem const* pPoolItem = aSet.GetItem(RES_CHRATR_FONT);
+        if (pPoolItem)
+        {
+            const SvxFontItem* pFontItem = static_cast<const 
SvxFontItem*>(pPoolItem);
+            if (pFontItem->GetCharSet() == RTL_TEXTENCODING_SYMBOL)
+                return pFontItem->GetFamilyName();
+        }
+    }
+
+    return OUString();
+}
+}
+
 void MSWordExportBase::OutputTextNode( SwTextNode& rNode )
 {
     SAL_INFO( "sw.ww8", "<OutWW8_SwTextNode>" );
@@ -2447,6 +2466,7 @@ void MSWordExportBase::OutputTextNode( SwTextNode& rNode )
             bool bTextAtr = aAttrIter.IsTextAttr( nCurrentPos );
             nOpenAttrWithRange += aAttrIter.OutAttrWithRange( rNode, 
nCurrentPos );
 
+            OUString aSymbolFont;
             sal_Int32 nLen = nNextAttr - nCurrentPos;
             if ( !bTextAtr && nLen )
             {
@@ -2613,12 +2633,13 @@ void MSWordExportBase::OutputTextNode( SwTextNode& 
rNode )
                 assert(0 <= nLen);
 
                 OUString aSnippet( aAttrIter.GetSnippet( aStr, nCurrentPos + 
ofs, nLen ) );
+                const SwTextNode* pTextNode( rNode.GetTextNode() );
                 if ( ( m_nTextTyp == TXT_EDN || m_nTextTyp == TXT_FTN ) && 
nCurrentPos == 0 && nLen > 0 )
                 {
                     // Allow MSO to emulate LO footnote text starting at left 
margin - only meaningful with hanging indent
                     sal_Int32 nFirstLineIndent=0;
                     SfxItemSetFixed<RES_LR_SPACE, RES_LR_SPACE> aSet( 
m_rDoc.GetAttrPool() );
-                    const SwTextNode* pTextNode( rNode.GetTextNode() );
+
                     if ( pTextNode && pTextNode->GetAttr(aSet) )
                     {
                         const SvxLRSpaceItem* pLRSpace = 
aSet.GetItem<SvxLRSpaceItem>(RES_LR_SPACE);
@@ -2632,6 +2653,8 @@ void MSWordExportBase::OutputTextNode( SwTextNode& rNode )
                     m_bAddFootnoteTab = false;
                 }
 
+                aSymbolFont = lcl_GetSymbolFont(m_rDoc.GetAttrPool(), 
pTextNode, nCurrentPos + ofs, nCurrentPos + ofs + nLen);
+
                 if ( bPostponeWritingText && ( FLY_POSTPONED != 
nStateOfFlyFrame ) )
                 {
                     aSavedSnippet = aSnippet ;
@@ -2639,7 +2662,7 @@ void MSWordExportBase::OutputTextNode( SwTextNode& rNode )
                 else
                 {
                     bPostponeWritingText = false ;
-                    AttrOutput().RunText( aSnippet, eChrSet );
+                    AttrOutput().RunText( aSnippet, eChrSet, aSymbolFont );
                 }
 
                 if (ofs == 1 && nNextAttr == nEnd)
@@ -2764,6 +2787,8 @@ void MSWordExportBase::OutputTextNode( SwTextNode& rNode )
 
             AttrOutput().WritePostitFieldReference();
 
+            aSymbolFont = lcl_GetSymbolFont(m_rDoc.GetAttrPool(), &rNode, 
nCurrentPos, nCurrentPos + nLen);
+
             if (bPostponeWritingText)
             {
                 if (FLY_PROCESSED == nStateOfFlyFrame || FLY_NONE == 
nStateOfFlyFrame)
@@ -2785,7 +2810,7 @@ void MSWordExportBase::OutputTextNode( SwTextNode& rNode )
                     // OutAttr may have introduced new comments, so write them 
out now
                     AttrOutput().WritePostitFieldReference();
                 }
-                AttrOutput().RunText( aSavedSnippet, eChrSet );
+                AttrOutput().RunText( aSavedSnippet, eChrSet, aSymbolFont );
                 AttrOutput().EndRun(&rNode, nCurrentPos, nLen, nNextAttr == 
nEnd);
             }
             else
diff --git a/sw/source/filter/ww8/ww8atr.cxx b/sw/source/filter/ww8/ww8atr.cxx
index 70ce371185f8..d0bed9c5c5bf 100644
--- a/sw/source/filter/ww8/ww8atr.cxx
+++ b/sw/source/filter/ww8/ww8atr.cxx
@@ -1136,7 +1136,7 @@ void WW8AttributeOutput::EndRunProperties( const 
SwRedlineData* pRedlineData )
     m_rWW8Export.m_pO->clear();
 }
 
-void WW8AttributeOutput::RunText( const OUString& rText, rtl_TextEncoding 
eCharSet )
+void WW8AttributeOutput::RunText( const OUString& rText, rtl_TextEncoding 
eCharSet, const OUString& /*rSymbolFont*/ )
 {
     RawText(rText, eCharSet);
 }
diff --git a/sw/source/filter/ww8/ww8attributeoutput.hxx 
b/sw/source/filter/ww8/ww8attributeoutput.hxx
index 3b78c33317d7..e139ae71f906 100644
--- a/sw/source/filter/ww8/ww8attributeoutput.hxx
+++ b/sw/source/filter/ww8/ww8attributeoutput.hxx
@@ -67,7 +67,7 @@ public:
     virtual void EndRunProperties( const SwRedlineData* pRedlineData ) 
override;
 
     /// Output text.
-    virtual void RunText( const OUString& rText, rtl_TextEncoding eCharSet = 
RTL_TEXTENCODING_UTF8 ) override;
+    virtual void RunText( const OUString& rText, rtl_TextEncoding eCharSet = 
RTL_TEXTENCODING_UTF8, const OUString& rSymbolFont = OUString() ) override;
 
     /// Output text (without markup).
     virtual void RawText(const OUString& rText, rtl_TextEncoding eCharSet) 
override;

Reply via email to