summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--editeng/source/items/textitem.cxx48
-rw-r--r--embeddedobj/source/commonembedding/miscobj.cxx46
-rw-r--r--embeddedobj/source/commonembedding/specialobject.cxx18
-rw-r--r--embeddedobj/source/general/dummyobject.cxx16
-rw-r--r--embeddedobj/source/inc/commonembobj.hxx12
-rw-r--r--embeddedobj/source/inc/dummyobject.hxx8
-rw-r--r--embeddedobj/source/inc/oleembobj.hxx9
-rw-r--r--embeddedobj/source/inc/specialobject.hxx5
-rw-r--r--embeddedobj/source/msole/olemisc.cxx16
-rw-r--r--include/editeng/fontitem.hxx1
-rw-r--r--sfx2/source/doc/sfxbasemodel.cxx11
-rw-r--r--sw/qa/extras/htmlexport/data/transparent.pngbin0 -> 2950 bytes
-rw-r--r--sw/qa/extras/htmlexport/htmlexport.cxx48
-rw-r--r--sw/source/filter/html/htmlreqifreader.cxx8
-rw-r--r--sw/source/filter/xml/xmlfonte.cxx18
-rw-r--r--xmloff/qa/unit/style.cxx53
16 files changed, 300 insertions, 17 deletions
diff --git a/editeng/source/items/textitem.cxx b/editeng/source/items/textitem.cxx
index 2e2cf4fe7604..e6817adb9a8d 100644
--- a/editeng/source/items/textitem.cxx
+++ b/editeng/source/items/textitem.cxx
@@ -153,6 +153,24 @@ bool SvxFontListItem::GetPresentation
// class SvxFontItem -----------------------------------------------------
+namespace
+{
+sal_Int32 CompareTo(sal_Int32 nA, sal_Int32 nB)
+{
+ if (nA < nB)
+ {
+ return -1;
+ }
+
+ if (nA > nB)
+ {
+ return 1;
+ }
+
+ return 0;
+}
+}
+
SvxFontItem::SvxFontItem( const sal_uInt16 nId ) :
SfxPoolItem( nId )
{
@@ -290,6 +308,36 @@ bool SvxFontItem::operator==( const SfxPoolItem& rAttr ) const
return bRet;
}
+bool SvxFontItem::operator<(const SfxPoolItem& rCmp) const
+{
+ const auto& rOther = static_cast<const SvxFontItem&>(rCmp);
+ sal_Int32 nRet = GetFamilyName().compareTo(rOther.GetFamilyName());
+ if (nRet != 0)
+ {
+ return nRet < 0;
+ }
+
+ nRet = GetStyleName().compareTo(rOther.GetStyleName());
+ if (nRet != 0)
+ {
+ return nRet < 0;
+ }
+
+ nRet = CompareTo(GetFamily(), rOther.GetFamily());
+ if (nRet != 0)
+ {
+ return nRet < 0;
+ }
+
+ nRet = CompareTo(GetPitch(), rOther.GetPitch());
+ if (nRet != 0)
+ {
+ return nRet < 0;
+ }
+
+ return GetCharSet() < rOther.GetCharSet();
+}
+
SvxFontItem* SvxFontItem::Clone( SfxItemPool * ) const
{
return new SvxFontItem( *this );
diff --git a/embeddedobj/source/commonembedding/miscobj.cxx b/embeddedobj/source/commonembedding/miscobj.cxx
index ea2a3cb3c110..8a1dd801f6ea 100644
--- a/embeddedobj/source/commonembedding/miscobj.cxx
+++ b/embeddedobj/source/commonembedding/miscobj.cxx
@@ -32,6 +32,7 @@
#include <comphelper/mimeconfighelper.hxx>
#include <vcl/svapp.hxx>
+#include <cppuhelper/supportsservice.hxx>
#include "persistence.hxx"
@@ -341,6 +342,16 @@ uno::Any SAL_CALL OCommonEmbeddedObject::queryInterface( const uno::Type& rType
void* p = static_cast<embed::XEmbedPersist2*>(this);
return uno::Any(&p, rType);
}
+ else if (rType == cppu::UnoType<lang::XServiceInfo>::get())
+ {
+ void* p = static_cast<lang::XServiceInfo*>(this);
+ return uno::Any(&p, rType);
+ }
+ else if (rType == cppu::UnoType<lang::XTypeProvider>::get())
+ {
+ void* p = static_cast<lang::XTypeProvider*>(this);
+ return uno::Any(&p, rType);
+ }
else
aReturn = ::cppu::queryInterface(
rType,
@@ -583,4 +594,39 @@ void SAL_CALL OCommonEmbeddedObject::removeEventListener( const uno::Reference<
xListener );
}
+OUString SAL_CALL OCommonEmbeddedObject::getImplementationName()
+{
+ return "com.sun.star.comp.embed.OCommonEmbeddedObject";
+}
+
+sal_Bool SAL_CALL OCommonEmbeddedObject::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+uno::Sequence<OUString> SAL_CALL OCommonEmbeddedObject::getSupportedServiceNames()
+{
+ return { "com.sun.star.comp.embed.OCommonEmbeddedObject" };
+}
+
+uno::Sequence<uno::Type> SAL_CALL OCommonEmbeddedObject::getTypes()
+{
+ static const uno::Sequence<uno::Type> aTypes{
+ cppu::UnoType<embed::XEmbeddedObject>::get(),
+ cppu::UnoType<embed::XEmbedPersist2>::get(),
+ cppu::UnoType<embed::XLinkageSupport>::get(),
+ cppu::UnoType<embed::XInplaceObject>::get(),
+ cppu::UnoType<container::XChild>::get(),
+ cppu::UnoType<chart2::XDefaultSizeTransmitter>::get(),
+ cppu::UnoType<lang::XServiceInfo>::get(),
+ cppu::UnoType<lang::XTypeProvider>::get(),
+ };
+ return aTypes;
+}
+
+uno::Sequence<sal_Int8> SAL_CALL OCommonEmbeddedObject::getImplementationId()
+{
+ return uno::Sequence<sal_Int8>();
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/embeddedobj/source/commonembedding/specialobject.cxx b/embeddedobj/source/commonembedding/specialobject.cxx
index 683fe0aab3f2..809ffce1f2c4 100644
--- a/embeddedobj/source/commonembedding/specialobject.cxx
+++ b/embeddedobj/source/commonembedding/specialobject.cxx
@@ -28,6 +28,7 @@
#include <cppuhelper/queryinterface.hxx>
#include <osl/diagnose.h>
+#include <cppuhelper/supportsservice.hxx>
#include <specialobject.hxx>
@@ -51,6 +52,8 @@ uno::Any SAL_CALL OSpecialEmbeddedObject::queryInterface( const uno::Type& rType
static_cast< embed::XClassifiedObject* >( this ),
static_cast< embed::XComponentSupplier* >( this ),
static_cast< util::XCloseable* >( this ),
+ static_cast< lang::XServiceInfo* >( this ),
+ static_cast< lang::XTypeProvider* >( this ),
static_cast< document::XEventBroadcaster* >( this ) );
if ( aReturn.hasValue() )
return aReturn;
@@ -160,4 +163,19 @@ void SAL_CALL OSpecialEmbeddedObject::doVerb( sal_Int32 nVerbID )
OCommonEmbeddedObject::doVerb( nVerbID );
}
+OUString SAL_CALL OSpecialEmbeddedObject::getImplementationName()
+{
+ return "com.sun.star.comp.embed.OSpecialEmbeddedObject";
+}
+
+sal_Bool SAL_CALL OSpecialEmbeddedObject::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+uno::Sequence<OUString> SAL_CALL OSpecialEmbeddedObject::getSupportedServiceNames()
+{
+ return { "com.sun.star.comp.embed.OSpecialEmbeddedObject" };
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/embeddedobj/source/general/dummyobject.cxx b/embeddedobj/source/general/dummyobject.cxx
index e37aca939b9b..cb251571222b 100644
--- a/embeddedobj/source/general/dummyobject.cxx
+++ b/embeddedobj/source/general/dummyobject.cxx
@@ -30,6 +30,7 @@
#include <com/sun/star/lang/IllegalArgumentException.hpp>
#include <com/sun/star/lang/NoSupportException.hpp>
+#include <cppuhelper/supportsservice.hxx>
#include <dummyobject.hxx>
@@ -620,4 +621,19 @@ void SAL_CALL ODummyEmbeddedObject::removeEventListener( const uno::Reference< d
xListener );
}
+OUString SAL_CALL ODummyEmbeddedObject::getImplementationName()
+{
+ return "com.sun.star.comp.embed.ODummyEmbeddedObject";
+}
+
+sal_Bool SAL_CALL ODummyEmbeddedObject::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+uno::Sequence<OUString> SAL_CALL ODummyEmbeddedObject::getSupportedServiceNames()
+{
+ return { "com.sun.star.comp.embed.ODummyEmbeddedObject" };
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/embeddedobj/source/inc/commonembobj.hxx b/embeddedobj/source/inc/commonembobj.hxx
index 61e939a0c62f..922ecf50d59f 100644
--- a/embeddedobj/source/inc/commonembobj.hxx
+++ b/embeddedobj/source/inc/commonembobj.hxx
@@ -33,6 +33,7 @@
#include <com/sun/star/awt/Rectangle.hpp>
#include <com/sun/star/util/XCloseable.hpp>
#include <com/sun/star/chart2/XDefaultSizeTransmitter.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
#include <cppuhelper/weak.hxx>
#include <rtl/ref.hxx>
#include <map>
@@ -78,6 +79,8 @@ class OCommonEmbeddedObject : public css::embed::XEmbeddedObject
, public css::embed::XInplaceObject
, public css::container::XChild
, public css::chart2::XDefaultSizeTransmitter
+ , public css::lang::XServiceInfo
+ , public css::lang::XTypeProvider
, public ::cppu::OWeakObject
{
protected:
@@ -394,6 +397,15 @@ public:
// XDefaultSizeTransmitter
//#i103460# charts do not necessarily have an own size within ODF files, in this case they need to use the size settings from the surrounding frame, which is made available with this method
virtual void SAL_CALL setDefaultSize( const css::awt::Size& rSize_100TH_MM ) override;
+
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+ sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // XTypeProvider
+ css::uno::Sequence<css::uno::Type> SAL_CALL getTypes() override;
+ css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId() override;
};
#endif
diff --git a/embeddedobj/source/inc/dummyobject.hxx b/embeddedobj/source/inc/dummyobject.hxx
index 60bca914b636..e8004cbcf28e 100644
--- a/embeddedobj/source/inc/dummyobject.hxx
+++ b/embeddedobj/source/inc/dummyobject.hxx
@@ -28,6 +28,7 @@
#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/embed/XEmbeddedObject.hpp>
#include <com/sun/star/embed/XEmbedPersist.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
#include <cppuhelper/implbase.hxx>
#include <cppuhelper/interfacecontainer.hxx>
@@ -54,7 +55,8 @@ namespace cppu {
*/
class ODummyEmbeddedObject : public ::cppu::WeakImplHelper
< css::embed::XEmbeddedObject
- , css::embed::XEmbedPersist >
+ , css::embed::XEmbedPersist
+ , css::lang::XServiceInfo >
{
::osl::Mutex m_aMutex;
std::unique_ptr<cppu::OMultiTypeInterfaceContainerHelper>
@@ -199,6 +201,10 @@ public:
virtual void SAL_CALL removeEventListener(
const css::uno::Reference< css::document::XEventListener >& Listener ) override;
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+ sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
};
#endif
diff --git a/embeddedobj/source/inc/oleembobj.hxx b/embeddedobj/source/inc/oleembobj.hxx
index 051d63294af4..f1480e08d71e 100644
--- a/embeddedobj/source/inc/oleembobj.hxx
+++ b/embeddedobj/source/inc/oleembobj.hxx
@@ -34,6 +34,7 @@
#include <com/sun/star/util/XCloseListener.hpp>
#include <com/sun/star/io/XActiveDataStreamer.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
#include <cppuhelper/implbase.hxx>
#include <rtl/ref.hxx>
@@ -115,7 +116,8 @@ class OleEmbeddedObject : public ::cppu::WeakImplHelper
, css::embed::XInplaceObject
, css::container::XChild
, css::io::XActiveDataStreamer
- , css::lang::XInitialization >
+ , css::lang::XInitialization
+ , css::lang::XServiceInfo >
{
friend class OleComponent;
@@ -445,6 +447,11 @@ public:
// XInitialization
void SAL_CALL initialize(const css::uno::Sequence<css::uno::Any>& rArguments) override;
+
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+ sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
};
#endif
diff --git a/embeddedobj/source/inc/specialobject.hxx b/embeddedobj/source/inc/specialobject.hxx
index 32ad61a7a582..695aad730cd9 100644
--- a/embeddedobj/source/inc/specialobject.hxx
+++ b/embeddedobj/source/inc/specialobject.hxx
@@ -48,6 +48,11 @@ public:
virtual void SAL_CALL changeState( sal_Int32 nNewState ) override;
virtual void SAL_CALL doVerb( sal_Int32 nVerbID ) override;
+
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+ sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
};
#endif
diff --git a/embeddedobj/source/msole/olemisc.cxx b/embeddedobj/source/msole/olemisc.cxx
index 6de6a9cdca75..c87812fc73fc 100644
--- a/embeddedobj/source/msole/olemisc.cxx
+++ b/embeddedobj/source/msole/olemisc.cxx
@@ -30,6 +30,7 @@
#include <cppuhelper/interfacecontainer.h>
#include <comphelper/sequenceashashmap.hxx>
+#include <cppuhelper/supportsservice.hxx>
#include <oleembobj.hxx>
#include "olepersist.hxx"
@@ -688,4 +689,19 @@ void OleEmbeddedObject::initialize(const uno::Sequence<uno::Any>& rArguments)
}
}
+OUString SAL_CALL OleEmbeddedObject::getImplementationName()
+{
+ return "com.sun.star.comp.embed.OleEmbeddedObject";
+}
+
+sal_Bool SAL_CALL OleEmbeddedObject::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+uno::Sequence<OUString> SAL_CALL OleEmbeddedObject::getSupportedServiceNames()
+{
+ return { "com.sun.star.comp.embed.OleEmbeddedObject" };
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/editeng/fontitem.hxx b/include/editeng/fontitem.hxx
index 9a73a051f79e..2ccaade20121 100644
--- a/include/editeng/fontitem.hxx
+++ b/include/editeng/fontitem.hxx
@@ -46,6 +46,7 @@ public:
// "pure virtual Methods" from SfxPoolItem
virtual bool operator==(const SfxPoolItem& rItem) const override;
+ bool operator<(const SfxPoolItem& rCmp) const override;
virtual SvxFontItem* Clone(SfxItemPool *pPool = nullptr) const override;
virtual bool QueryValue(css::uno::Any& rVal, sal_uInt8 nMemberId = 0) const override;
virtual bool PutValue(const css::uno::Any& rVal, sal_uInt8 nMemberId) override;
diff --git a/sfx2/source/doc/sfxbasemodel.cxx b/sfx2/source/doc/sfxbasemodel.cxx
index 533650751d75..adcea5aaf752 100644
--- a/sfx2/source/doc/sfxbasemodel.cxx
+++ b/sfx2/source/doc/sfxbasemodel.cxx
@@ -1680,7 +1680,16 @@ void SAL_CALL SfxBaseModel::storeAsURL( const OUString& rURL
SfxSaveGuard aSaveGuard(this, m_pData.get());
- impl_store( rURL, rArgs, false );
+ utl::MediaDescriptor aDescriptor(rArgs);
+ bool bOnMainThread = aDescriptor.getUnpackedValueOrDefault("OnMainThread", false);
+ if (bOnMainThread)
+ {
+ vcl::solarthread::syncExecute([this, rURL, rArgs]() { impl_store(rURL, rArgs, false); });
+ }
+ else
+ {
+ impl_store(rURL, rArgs, false);
+ }
Sequence< beans::PropertyValue > aSequence ;
TransformItems( SID_OPENDOC, *m_pData->m_pObjectShell->GetMedium()->GetItemSet(), aSequence );
diff --git a/sw/qa/extras/htmlexport/data/transparent.png b/sw/qa/extras/htmlexport/data/transparent.png
new file mode 100644
index 000000000000..936980b0a19b
--- /dev/null
+++ b/sw/qa/extras/htmlexport/data/transparent.png
Binary files differ
diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx
index 50e001c72890..fd9e4ee06583 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -38,6 +38,7 @@
#include <filter/msfilter/rtfutil.hxx>
#include <sot/storage.hxx>
#include <svl/eitem.hxx>
+#include <vcl/dibtools.hxx>
namespace
{
@@ -129,6 +130,7 @@ bool TestReqIfRtfReader::WriteObjectData(SvStream& rOLE)
struct OLE1Reader
{
sal_uInt32 m_nNativeDataSize;
+ std::vector<char> m_aNativeData;
sal_uInt32 m_nPresentationDataSize;
OLE1Reader(SvStream& rStream);
@@ -150,7 +152,8 @@ OLE1Reader::OLE1Reader(SvStream& rStream)
rStream.SeekRel(nData);
rStream.ReadUInt32(m_nNativeDataSize);
- rStream.SeekRel(m_nNativeDataSize);
+ m_aNativeData.resize(m_nNativeDataSize);
+ rStream.ReadBytes(m_aNativeData.data(), m_aNativeData.size());
rStream.ReadUInt32(nData); // OLEVersion for presentation data
CPPUNIT_ASSERT(rStream.good());
@@ -1494,6 +1497,49 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifImageToOle)
CPPUNIT_ASSERT(aOle1Reader.m_nPresentationDataSize);
}
+CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifOleBmpTransparent)
+{
+ // Given a document with a transparent image:
+ loadURL("private:factory/swriter", nullptr);
+ OUString aImageURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "transparent.png";
+ uno::Sequence<beans::PropertyValue> aArgs = {
+ comphelper::makePropertyValue("FileName", aImageURL),
+ };
+ dispatchCommand(mxComponent, ".uno:InsertGraphic", aArgs);
+
+ // When exporting to reqif with ExportImagesAsOLE=true:
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ uno::Sequence<beans::PropertyValue> aStoreProperties = {
+ comphelper::makePropertyValue("FilterName", OUString("HTML (StarWriter)")),
+ comphelper::makePropertyValue("FilterOptions", OUString("xhtmlns=reqif-xhtml")),
+ comphelper::makePropertyValue("ExportImagesAsOLE", true),
+ };
+ xStorable->storeToURL(maTempFile.GetURL(), aStoreProperties);
+
+ // Then make sure the transparent pixel turns into white:
+ OUString aRtfUrl = GetOlePath();
+ SvMemoryStream aRtf;
+ HtmlExportTest::wrapRtfFragment(aRtfUrl, aRtf);
+ tools::SvRef<TestReqIfRtfReader> xReader(new TestReqIfRtfReader(aRtf));
+ CPPUNIT_ASSERT(xReader->CallParser() != SvParserState::Error);
+ SvMemoryStream aOle1;
+ CPPUNIT_ASSERT(xReader->WriteObjectData(aOle1));
+ OLE1Reader aOle1Reader(aOle1);
+ SvMemoryStream aBitmapStream(aOle1Reader.m_aNativeData.data(), aOle1Reader.m_aNativeData.size(),
+ StreamMode::READ);
+ Bitmap aBitmap;
+ ReadDIB(aBitmap, aBitmapStream, /*bFileHeader=*/true);
+ Size aBitmapSize = aBitmap.GetSizePixel();
+ BitmapEx aBitmapEx(aBitmap);
+ Color nActualColor
+ = aBitmapEx.GetPixelColor(aBitmapSize.getWidth() - 1, aBitmapSize.getHeight() - 1);
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: Color: R:255 G:255 B:255 A:0
+ // - Actual : Color: R:0 G:0 B:0 A:0
+ // i.e. the bitmap without an alpha channel was black, not white.
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, nActualColor);
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/html/htmlreqifreader.cxx b/sw/source/filter/html/htmlreqifreader.cxx
index 8a6101fa93ee..a091183b9f69 100644
--- a/sw/source/filter/html/htmlreqifreader.cxx
+++ b/sw/source/filter/html/htmlreqifreader.cxx
@@ -545,7 +545,13 @@ bool WrapGraphicInRtf(const Graphic& rGraphic, const SwFrameFormat& rFormat, SvS
// NativeDataSize
SvMemoryStream aNativeData;
- if (GraphicConverter::Export(aNativeData, rGraphic, ConvertDataFormat::BMP) != ERRCODE_NONE)
+
+ // Set white background for the semi-transparent pixels.
+ BitmapEx aBitmapEx = rGraphic.GetBitmapEx();
+ Bitmap aBitmap = aBitmapEx.GetBitmap(/*aTransparentReplaceColor=*/COL_WHITE);
+
+ if (GraphicConverter::Export(aNativeData, BitmapEx(aBitmap), ConvertDataFormat::BMP)
+ != ERRCODE_NONE)
{
SAL_WARN("sw.html", "WrapGraphicInRtf: bmp conversion failed");
}
diff --git a/sw/source/filter/xml/xmlfonte.cxx b/sw/source/filter/xml/xmlfonte.cxx
index 9b90f94fd419..79207700c204 100644
--- a/sw/source/filter/xml/xmlfonte.cxx
+++ b/sw/source/filter/xml/xmlfonte.cxx
@@ -46,21 +46,27 @@ SwXMLFontAutoStylePool_Impl::SwXMLFontAutoStylePool_Impl(SwXMLExport& _rExport,
RES_CHRATR_CTL_FONT };
const SfxItemPool& rPool = _rExport.getDoc()->GetAttrPool();
+ std::vector<const SvxFontItem *> aFonts;
for(sal_uInt16 nWhichId : aWhichIds)
{
const SvxFontItem& rFont =
static_cast<const SvxFontItem&>(rPool.GetDefaultItem( nWhichId ));
- Add( rFont.GetFamilyName(), rFont.GetStyleName(),
- rFont.GetFamily(), rFont.GetPitch(),
- rFont.GetCharSet() );
+ aFonts.push_back(&rFont);
for (const SfxPoolItem* pItem : rPool.GetItemSurrogates(nWhichId))
{
auto pFont = static_cast<const SvxFontItem *>(pItem);
- Add( pFont->GetFamilyName(), pFont->GetStyleName(),
- pFont->GetFamily(), pFont->GetPitch(),
- pFont->GetCharSet() );
+ aFonts.push_back(pFont);
}
}
+
+ std::sort(aFonts.begin(), aFonts.end(),
+ [](const SvxFontItem* pA, const SvxFontItem* pB) -> bool { return *pA < *pB; });
+ for (const auto& pFont : aFonts)
+ {
+ Add(pFont->GetFamilyName(), pFont->GetStyleName(), pFont->GetFamily(), pFont->GetPitch(),
+ pFont->GetCharSet());
+ }
+
auto const & pDocument = _rExport.getDoc();
m_bEmbedUsedOnly = pDocument->getIDocumentSettingAccess().get(DocumentSettingId::EMBED_USED_FONTS);
diff --git a/xmloff/qa/unit/style.cxx b/xmloff/qa/unit/style.cxx
index f859c3619837..1ccffa8a039c 100644
--- a/xmloff/qa/unit/style.cxx
+++ b/xmloff/qa/unit/style.cxx
@@ -19,6 +19,7 @@
#include <comphelper/propertysequence.hxx>
#include <unotools/tempfile.hxx>
#include <unotools/ucbstreamhelper.hxx>
+#include <rtl/character.hxx>
using namespace ::com::sun::star;
@@ -82,6 +83,25 @@ CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testFillImageBase64)
CPPUNIT_ASSERT(xBitmaps->hasByName("libreoffice_0"));
}
+namespace
+{
+struct XmlFont
+{
+ OString aName;
+ OString aFontFamilyGeneric;
+ bool operator<(const XmlFont& rOther) const
+ {
+ sal_Int32 nRet = aName.compareTo(rOther.aName);
+ if (nRet != 0)
+ {
+ return nRet < 0;
+ }
+
+ return aFontFamilyGeneric.compareTo(rOther.aFontFamilyGeneric) < 0;
+ }
+};
+}
+
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testFontSorting)
{
// Given an empty document with default fonts (Liberation Sans, Lucida Sans, etc):
@@ -107,25 +127,46 @@ CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testFontSorting)
= getXPathNode(pXmlDoc, "/office:document-content/office:font-face-decls/style:font-face");
xmlNodeSetPtr pXmlNodes = pXPath->nodesetval;
int nNodeCount = xmlXPathNodeSetGetLength(pXmlNodes);
- std::vector<OString> aXMLNames;
- std::set<OString> aSortedNames;
+ std::vector<XmlFont> aXMLFonts;
+ std::vector<XmlFont> aSortedFonts;
for (int i = 0; i < nNodeCount; ++i)
{
xmlNodePtr pXmlNode = pXmlNodes->nodeTab[i];
xmlChar* pName = xmlGetProp(pXmlNode, BAD_CAST("name"));
OString aName(reinterpret_cast<char const*>(pName));
- aXMLNames.push_back(aName);
- aSortedNames.insert(aName);
+
+ // Ignore numbers at the end, those are just appended to make all names unique.
+ while (rtl::isAsciiDigit(static_cast<sal_uInt32>(aName[aName.getLength() - 1])))
+ {
+ aName = aName.copy(0, aName.getLength() - 1);
+ }
+
+ xmlChar* pFontFamilyGeneric = xmlGetProp(pXmlNode, BAD_CAST("font-family-generic"));
+ OString aFontFamilyGeneric;
+ if (pFontFamilyGeneric)
+ {
+ aFontFamilyGeneric = OString(reinterpret_cast<char const*>(pFontFamilyGeneric));
+ }
+
+ aXMLFonts.push_back(XmlFont{ aName, aFontFamilyGeneric });
+ aSortedFonts.push_back(XmlFont{ aName, aFontFamilyGeneric });
xmlFree(pName);
}
+ std::sort(aSortedFonts.begin(), aSortedFonts.end());
size_t nIndex = 0;
- for (const auto& rName : aSortedNames)
+ for (const auto& rFont : aSortedFonts)
{
// Without the accompanying fix in place, this test would have failed with:
// - Expected: Liberation Sans
// - Actual : Lucida Sans1
// i.e. the output was not lexicographically sorted, "u" was before "i".
- CPPUNIT_ASSERT_EQUAL(rName, aXMLNames[nIndex]);
+ CPPUNIT_ASSERT_EQUAL(rFont.aName, aXMLFonts[nIndex].aName);
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: swiss
+ // - Actual : system
+ // i.e. the output was not lexicographically sorted when style:name was the same, but
+ // style:font-family-generic was not the same.
+ CPPUNIT_ASSERT_EQUAL(rFont.aFontFamilyGeneric, aXMLFonts[nIndex].aFontFamilyGeneric);
++nIndex;
}
xmlXPathFreeObject(pXPath);