[Libreoffice-commits] core.git: Branch 'feature/cib_contract57c' - 46 commits - basic/source configure.ac cui/source dbaccess/source desktop/source dictionaries download.lst embeddedobj/source extensions/inc extensions/uiconfig external/lcms2 external/libxml2 external/poppler external/python3 fpicker/Library_fps.mk fpicker/source icon-themes/breeze icon-themes/breeze_dark icon-themes/breeze_svg icon-themes/colibre icon-themes/colibre_svg icon-themes/elementary icon-themes/elementary_svg icon-themes/karasa_jaga icon-themes/tango include/oox include/vcl jvmfwk/distributions jvmfwk/plugins oox/source sc/inc sc/qa sc/source sdext/source sd/qa sfx2/source solenv/flatpak-manifest.in svl/source svx/source sw/inc sw/qa sw/source toolkit/source translations vcl/inc vcl/Library_vcl.mk vcl/qt5 vcl/quartz vcl/source vcl/unx vcl/win writerfilter/source xmloff/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Fri Jan 25 07:39:23 UTC 2019


Rebased ref, commits from common ancestor:
commit a331973da8e84dd93c38e3f97389e6a620b07c2d
Author:     Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
AuthorDate: Thu Jan 24 15:52:47 2019 +0100
Commit:     Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
CommitDate: Fri Jan 25 08:38:24 2019 +0100

    tdf#122607 Don't unnecessarily redo the layout
    
    Brings weird issues like out of place textboxes as described in the bug.
    
    Change-Id: I19341efc48188f0b52069401dc39ba05f4fcc7f6
    Reviewed-on: https://gerrit.libreoffice.org/66874
    Tested-by: Jenkins
    Reviewed-by: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
    (cherry picked from commit 1ecca673b40fedc53db125e332b087d1c120a254)
    Reviewed-on: https://gerrit.libreoffice.org/66897
    Tested-by: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>

diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx
index 6e9701c765eb..066907bea12e 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -2633,10 +2633,6 @@ sal_Int32 SAL_CALL SwXTextDocument::getRendererCount(
             if( bStateChanged )
                 pRenderDocShell->EnableSetModified();
 
-            // there is some redundancy between those two function calls, but right now
-            // there is no time to sort this out.
-            //TODO: check what exactly needs to be done and make just one function for that
-            pViewShell->CalcLayout();
             pViewShell->CalcPagesForPrint( pViewShell->GetPageCount() );
 
             // #122919# Force field update before PDF export, but after layout init (tdf#121962)
commit 5d76f9bf66d6f8883a1658e134b546d9448e1c2a
Author:     Noel Grandin <noel.grandin at collabora.co.uk>
AuthorDate: Tue Jun 5 14:16:23 2018 +0200
Commit:     Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
CommitDate: Fri Jan 25 08:38:23 2019 +0100

    hold LogicalFontInstance with rtl::Reference
    
    instead of manual reference counting.
    
    Also the releasing of not-currently-in-use LogicalFontInstance objects
    from the cache is made less aggressive - we now only flush entries until
    we have less than CACHE_SIZE instances, instead of flushing the whole
    cache.
    
    Reviewed-on: https://gerrit.libreoffice.org/55384
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Noel Grandin <noel.grandin at collabora.co.uk>
    (cherry picked from commit c4c56de1b0e62ec866b519b2b24c5e805f0a86d3)
    
    Change-Id: Ib235b132776b5f09ae8ae93a933c2eebe5fa9610

diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx
index 174987e51757..93a3ce610c32 100644
--- a/include/vcl/outdev.hxx
+++ b/include/vcl/outdev.hxx
@@ -332,7 +332,7 @@ private:
     mutable VclPtr<OutputDevice>    mpPrevGraphics;     ///< Previous output device in list
     mutable VclPtr<OutputDevice>    mpNextGraphics;     ///< Next output device in list
     GDIMetaFile*                    mpMetaFile;
-    mutable LogicalFontInstance*    mpFontInstance;
+    mutable rtl::Reference<LogicalFontInstance> mpFontInstance;
     mutable ImplFontCache*          mpFontCache;
     mutable PhysicalFontCollection* mpFontCollection;
     mutable std::unique_ptr<ImplDeviceFontList>     mpDeviceFontList;
diff --git a/vcl/inc/PhysicalFontFace.hxx b/vcl/inc/PhysicalFontFace.hxx
index 2406b6cf41da..e289345716ca 100644
--- a/vcl/inc/PhysicalFontFace.hxx
+++ b/vcl/inc/PhysicalFontFace.hxx
@@ -54,7 +54,7 @@ public:
 class VCL_PLUGIN_PUBLIC PhysicalFontFace : public FontAttributes, public salhelper::SimpleReferenceObject
 {
 public:
-    virtual LogicalFontInstance* CreateFontInstance(const FontSelectPattern&) const;
+    virtual rtl::Reference<LogicalFontInstance> CreateFontInstance(const FontSelectPattern&) const;
     virtual rtl::Reference<PhysicalFontFace> Clone() const = 0;
 
     int                     GetHeight() const           { return mnHeight; }
diff --git a/vcl/inc/fontinstance.hxx b/vcl/inc/fontinstance.hxx
index 317b7181198d..149bb553c3eb 100644
--- a/vcl/inc/fontinstance.hxx
+++ b/vcl/inc/fontinstance.hxx
@@ -24,6 +24,7 @@
 #include "impfontmetricdata.hxx"
 
 #include <rtl/ref.hxx>
+#include <salhelper/simplereferenceobject.hxx>
 #include <unordered_map>
 #include <memory>
 
@@ -35,7 +36,7 @@ class PhysicalFontFace;
 
 // TODO: allow sharing of metrics for related fonts
 
-class VCL_PLUGIN_PUBLIC LogicalFontInstance
+class VCL_PLUGIN_PUBLIC LogicalFontInstance : public salhelper::SimpleReferenceObject
 {
     // just declaring the factory function doesn't work AKA
     // friend LogicalFontInstance* PhysicalFontFace::CreateFontInstance(const FontSelectPattern&) const;
@@ -43,7 +44,7 @@ class VCL_PLUGIN_PUBLIC LogicalFontInstance
     friend class ImplFontCache;
 
 public: // TODO: make data members private
-    virtual ~LogicalFontInstance();
+    virtual ~LogicalFontInstance() override;
 
     ImplFontMetricDataRef mxFontMetric;        // Font attributes
     const ConvertChar* mpConversion;        // used e.g. for StarBats->StarSymbol
@@ -57,9 +58,6 @@ public: // TODO: make data members private
     bool            GetFallbackForUnicode( sal_UCS4, FontWeight eWeight, OUString* pFontName ) const;
     void            IgnoreFallbackForUnicode( sal_UCS4, FontWeight eWeight, const OUString& rFontName );
 
-    void            Acquire();
-    void            Release();
-
     inline hb_font_t* GetHbFont();
     void SetAverageWidthFactor(double nFactor) { m_nAveWidthFactor = nFactor; }
     double GetAverageWidthFactor() const { return m_nAveWidthFactor; }
@@ -88,7 +86,6 @@ private:
     typedef ::std::unordered_map< ::std::pair<sal_UCS4,FontWeight>, OUString > UnicodeFallbackList;
     std::unique_ptr<UnicodeFallbackList> mpUnicodeFallbackList;
     ImplFontCache * mpFontCache;
-    sal_uInt32      mnRefCount;
     const FontSelectPattern m_aFontSelData;
     hb_font_t* m_pHbFont;
     double m_nAveWidthFactor;
diff --git a/vcl/inc/fontselect.hxx b/vcl/inc/fontselect.hxx
index 389077270758..efb88ad74ae1 100644
--- a/vcl/inc/fontselect.hxx
+++ b/vcl/inc/fontselect.hxx
@@ -21,6 +21,7 @@
 #define INCLUDED_VCL_INC_FONTSELECT_HXX
 
 #include <i18nlangtag/lang.h>
+#include <rtl/ref.hxx>
 
 #include "fontattributes.hxx"
 
@@ -80,7 +81,7 @@ public:
 #endif
 
 public: // TODO: change to private
-    LogicalFontInstance*  mpFontInstance;                // pointer to the resulting FontCache entry
+    rtl::Reference<LogicalFontInstance> mpFontInstance;                // pointer to the resulting FontCache entry
 
     void            copyAttributes(const FontSelectPatternAttributes &rAttributes);
 };
diff --git a/vcl/inc/impfontcache.hxx b/vcl/inc/impfontcache.hxx
index a99283fb300e..6cb05b39d9b3 100644
--- a/vcl/inc/impfontcache.hxx
+++ b/vcl/inc/impfontcache.hxx
@@ -33,36 +33,24 @@ class PhysicalFontCollection;
 
 class ImplFontCache
 {
-    // For access to Acquire and Release
-    friend class LogicalFontInstance;
-
 private:
     LogicalFontInstance* mpLastHitCacheEntry; ///< keeps the last hit cache entry
-    int mnRef0Count; ///< number of unreferenced LogicalFontInstances
 
     // cache of recently used font instances
     struct IFSD_Equal { bool operator()( const FontSelectPattern&, const FontSelectPattern& ) const; };
     struct IFSD_Hash { size_t operator()( const FontSelectPattern& ) const; };
-    typedef std::unordered_map<FontSelectPattern,LogicalFontInstance*,IFSD_Hash,IFSD_Equal > FontInstanceList;
+    typedef std::unordered_map<FontSelectPattern, rtl::Reference<LogicalFontInstance>, IFSD_Hash, IFSD_Equal> FontInstanceList;
     FontInstanceList    maFontInstanceList;
 
-    int                 CountUnreferencedEntries() const;
-    bool                IsFontInList(const LogicalFontInstance* pFont) const;
-
-    /// Increase the refcount of the given LogicalFontInstance.
-    void                Acquire(LogicalFontInstance*);
-    /// Decrease the refcount and potentially cleanup the entries with zero refcount from the cache.
-    void                Release(LogicalFontInstance*);
-
-    LogicalFontInstance* GetFontInstance(PhysicalFontCollection const*, FontSelectPattern&);
+    rtl::Reference<LogicalFontInstance> GetFontInstance(PhysicalFontCollection const*, FontSelectPattern&);
 
 public:
                         ImplFontCache();
                         ~ImplFontCache();
 
-    LogicalFontInstance* GetFontInstance( PhysicalFontCollection const *,
+    rtl::Reference<LogicalFontInstance> GetFontInstance( PhysicalFontCollection const *,
                              const vcl::Font&, const Size& rPixelSize, float fExactHeight);
-    LogicalFontInstance* GetGlyphFallbackFont( PhysicalFontCollection const *, FontSelectPattern&,
+    rtl::Reference<LogicalFontInstance> GetGlyphFallbackFont( PhysicalFontCollection const *, FontSelectPattern&,
                             int nFallbackLevel, OUString& rMissingCodes );
 
     void                Invalidate();
diff --git a/vcl/inc/quartz/salgdi.h b/vcl/inc/quartz/salgdi.h
index 2f53a44d694e..1dd896058890 100644
--- a/vcl/inc/quartz/salgdi.h
+++ b/vcl/inc/quartz/salgdi.h
@@ -71,7 +71,7 @@ public:
     bool                            GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const;
     bool                            HasChar( sal_uInt32 cChar ) const;
 
-    LogicalFontInstance*            CreateFontInstance(const FontSelectPattern&) const override;
+    rtl::Reference<LogicalFontInstance> CreateFontInstance(const FontSelectPattern&) const override;
 
 protected:
                                     CoreTextFontFace( const CoreTextFontFace& );
@@ -85,7 +85,7 @@ private:
 
 class CoreTextStyle : public LogicalFontInstance
 {
-    friend LogicalFontInstance* CoreTextFontFace::CreateFontInstance(const FontSelectPattern&) const;
+    friend rtl::Reference<LogicalFontInstance> CoreTextFontFace::CreateFontInstance(const FontSelectPattern&) const;
 
 public:
     ~CoreTextStyle();
@@ -159,7 +159,7 @@ class AquaSalGraphics : public SalGraphics
     RGBAColor                               maFillColor;
 
     // Device Font settings
-    CoreTextStyle*                          mpTextStyle[MAX_FALLBACK];
+    rtl::Reference<CoreTextStyle>           mpTextStyle[MAX_FALLBACK];
     RGBAColor                               maTextColor;
     /// allows text to be rendered without antialiasing
     bool                                    mbNonAntialiasedText;
diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx
index 62cda5832906..8daed9a01d09 100644
--- a/vcl/inc/sallayout.hxx
+++ b/vcl/inc/sallayout.hxx
@@ -352,7 +352,7 @@ private:
 
     void            ParseFeatures(const OUString& name);
 
-    LogicalFontInstance* const mpFont;
+    rtl::Reference<LogicalFontInstance> const mpFont;
     css::uno::Reference<css::i18n::XBreakIterator> mxBreak;
 
     std::vector<GlyphItem> m_GlyphItems;
diff --git a/vcl/inc/salwtype.hxx b/vcl/inc/salwtype.hxx
index 34ca43664a25..29cbaf00c3a6 100644
--- a/vcl/inc/salwtype.hxx
+++ b/vcl/inc/salwtype.hxx
@@ -21,6 +21,7 @@
 #define INCLUDED_VCL_INC_SALWTYPE_HXX
 
 #include <i18nlangtag/lang.h>
+#include <rtl/ref.hxx>
 #include <rtl/ustring.hxx>
 #include <tools/solar.h>
 
@@ -238,7 +239,7 @@ struct SalFrameState
 
 struct SalInputContext
 {
-    LogicalFontInstance* mpFont;
+    rtl::Reference<LogicalFontInstance> mpFont;
     LanguageType           meLanguage;
     InputContextFlags      mnOptions;
 };
diff --git a/vcl/inc/unx/freetype_glyphcache.hxx b/vcl/inc/unx/freetype_glyphcache.hxx
index d6b87b7ab7a9..bf00935b15a1 100644
--- a/vcl/inc/unx/freetype_glyphcache.hxx
+++ b/vcl/inc/unx/freetype_glyphcache.hxx
@@ -114,7 +114,7 @@ private:
 public:
                             FreetypeFontFace( FreetypeFontInfo*, const FontAttributes& );
 
-    virtual LogicalFontInstance* CreateFontInstance( const FontSelectPattern& ) const override;
+    virtual rtl::Reference<LogicalFontInstance> CreateFontInstance( const FontSelectPattern& ) const override;
     virtual rtl::Reference<PhysicalFontFace> Clone() const override   { return new FreetypeFontFace( *this ); }
     virtual sal_IntPtr      GetFontId() const override { return mpFreetypeFontInfo->GetFontId(); }
 };
@@ -122,7 +122,7 @@ public:
 // a class for cache entries for physical font instances that are based on serverfonts
 class VCL_DLLPUBLIC FreetypeFontInstance : public LogicalFontInstance
 {
-    friend LogicalFontInstance* FreetypeFontFace::CreateFontInstance(const FontSelectPattern&) const;
+    friend rtl::Reference<LogicalFontInstance> FreetypeFontFace::CreateFontInstance(const FontSelectPattern&) const;
 
     FreetypeFont* mpFreetypeFont;
 
diff --git a/vcl/inc/unx/glyphcache.hxx b/vcl/inc/unx/glyphcache.hxx
index 5e515db564b5..50d1f071d44f 100644
--- a/vcl/inc/unx/glyphcache.hxx
+++ b/vcl/inc/unx/glyphcache.hxx
@@ -39,6 +39,7 @@
 #include <unordered_map>
 
 class FreetypeManager;
+class FreetypeFontInstance;
 class FreetypeFontInfo;
 class GlyphData;
 class FontConfigFontOptions;
@@ -139,7 +140,7 @@ public:
     bool                    GetGlyphOutline(const GlyphItem& rGlyph, basegfx::B2DPolyPolygon&) const;
     bool                    GetAntialiasAdvice() const;
 
-    LogicalFontInstance* GetFontInstance() const { return mpFontInstance; }
+    FreetypeFontInstance*   GetFontInstance() const { return mpFontInstance.get(); }
 
 private:
     friend class GlyphCache;
@@ -161,7 +162,7 @@ private:
     typedef std::unordered_map<int,GlyphData> GlyphList;
     mutable GlyphList       maGlyphList;
 
-    LogicalFontInstance* const mpFontInstance;
+    rtl::Reference<FreetypeFontInstance> mpFontInstance;
 
     // used by GlyphCache for cache LRU algorithm
     mutable long            mnRefCount;
diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h
index dc7bc7510229..0f175ebe75c2 100644
--- a/vcl/inc/win/salgdi.h
+++ b/vcl/inc/win/salgdi.h
@@ -64,7 +64,7 @@ public:
     virtual                 ~WinFontFace() override;
 
     virtual rtl::Reference<PhysicalFontFace> Clone() const override;
-    virtual LogicalFontInstance* CreateFontInstance( const FontSelectPattern& ) const override;
+    virtual rtl::Reference<LogicalFontInstance> CreateFontInstance( const FontSelectPattern& ) const override;
     virtual sal_IntPtr      GetFontId() const override;
     void                    SetFontId( sal_IntPtr nId ) { mnId = nId; }
     void                    UpdateFromHDC( HDC ) const;
@@ -170,7 +170,8 @@ private:
      **/
 
     HFONT                   mhFonts[ MAX_FALLBACK ];        // Font + Fallbacks
-    WinFontInstance*       mpWinFontEntry[ MAX_FALLBACK ]; // pointer to the most recent font instance
+    rtl::Reference<WinFontInstance>
+                            mpWinFontEntry[ MAX_FALLBACK ]; // pointer to the most recent font instance
     float                   mfFontScale[ MAX_FALLBACK ];        // allows metrics emulation of huge font sizes
     HRGN                    mhRegion;           // vcl::Region Handle
     HPEN                    mhDefPen;           // DefaultPen
@@ -182,8 +183,6 @@ private:
     RGNDATA*                mpStdClipRgnData;   // Cache Standard-ClipRegion-Data
     int                     mnPenWidth;         // line width
 
-    LogicalFontInstance* GetWinFontEntry(int nFallbackLevel);
-
     bool CacheGlyphs(const GenericSalLayout& rLayout);
     bool DrawCachedGlyphs(const GenericSalLayout& rLayout);
     HFONT ImplDoSetFont(FontSelectPattern const * i_pFont, const PhysicalFontFace * i_pFontFace, float& o_rFontScale, HFONT& o_rOldFont);
diff --git a/vcl/inc/win/winlayout.hxx b/vcl/inc/win/winlayout.hxx
index 0c447153c800..07ae1a7d03c1 100644
--- a/vcl/inc/win/winlayout.hxx
+++ b/vcl/inc/win/winlayout.hxx
@@ -145,7 +145,7 @@ public:
 // win32 specific physical font instance
 class WinFontInstance : public LogicalFontInstance
 {
-    friend LogicalFontInstance* WinFontFace::CreateFontInstance(const FontSelectPattern&) const;
+    friend rtl::Reference<LogicalFontInstance> WinFontFace::CreateFontInstance(const FontSelectPattern&) const;
 
 public:
     virtual ~WinFontInstance() override;
diff --git a/vcl/quartz/ctfonts.cxx b/vcl/quartz/ctfonts.cxx
index 1d72f601eafa..dc372325e9e8 100644
--- a/vcl/quartz/ctfonts.cxx
+++ b/vcl/quartz/ctfonts.cxx
@@ -288,7 +288,7 @@ rtl::Reference<PhysicalFontFace> CoreTextFontFace::Clone() const
     return new CoreTextFontFace( *this);
 }
 
-LogicalFontInstance* CoreTextFontFace::CreateFontInstance(const FontSelectPattern& rFSD) const
+rtl::Reference<LogicalFontInstance> CoreTextFontFace::CreateFontInstance(const FontSelectPattern& rFSD) const
 {
     return new CoreTextStyle(*this, rFSD);
 }
diff --git a/vcl/quartz/salgdi.cxx b/vcl/quartz/salgdi.cxx
index 7154bd672e0f..48e40f3d0895 100644
--- a/vcl/quartz/salgdi.cxx
+++ b/vcl/quartz/salgdi.cxx
@@ -66,7 +66,7 @@ bool CoreTextGlyphFallbackSubstititution::FindFontSubstitute(FontSelectPattern&
     OUString& rMissingChars) const
 {
     bool bFound = false;
-    CoreTextStyle* pStyle = static_cast<CoreTextStyle*>(rPattern.mpFontInstance);
+    CoreTextStyle* pStyle = static_cast<CoreTextStyle*>(rPattern.mpFontInstance.get());
     CTFontRef pFont = static_cast<CTFontRef>(CFDictionaryGetValue(pStyle->GetStyleDict(), kCTFontAttributeName));
     CFStringRef pStr = CreateCFString(rMissingChars);
     if (pStr)
@@ -243,7 +243,7 @@ AquaSalGraphics::~AquaSalGraphics()
     {
         if (!mpTextStyle[i])
             break;
-        mpTextStyle[i]->Release();
+        mpTextStyle[i].clear();
     }
 
     if( mpXorEmulation )
@@ -488,8 +488,7 @@ void AquaSalGraphics::SetFont(const FontSelectPattern* pReqFont, int nFallbackLe
     {
         if (!mpTextStyle[i])
             break;
-        mpTextStyle[i]->Release();
-        mpTextStyle[i] = nullptr;
+        mpTextStyle[i].clear();
     }
 
     if (!pReqFont)
@@ -499,8 +498,7 @@ void AquaSalGraphics::SetFont(const FontSelectPattern* pReqFont, int nFallbackLe
         return;
 
     // update the text style
-    mpTextStyle[nFallbackLevel] = static_cast<CoreTextStyle*>(pReqFont->mpFontInstance);
-    mpTextStyle[nFallbackLevel]->Acquire();
+    mpTextStyle[nFallbackLevel] = static_cast<CoreTextStyle*>(pReqFont->mpFontInstance.get());
 
     SAL_INFO("vcl.ct",
             "SetFont"
diff --git a/vcl/source/font/PhysicalFontFace.cxx b/vcl/source/font/PhysicalFontFace.cxx
index 690fd1fdc401..d356438e43a1 100644
--- a/vcl/source/font/PhysicalFontFace.cxx
+++ b/vcl/source/font/PhysicalFontFace.cxx
@@ -45,7 +45,7 @@ PhysicalFontFace::PhysicalFontFace( const PhysicalFontFace& other )
 {
 }
 
-LogicalFontInstance* PhysicalFontFace::CreateFontInstance(const FontSelectPattern& rFSD) const
+rtl::Reference<LogicalFontInstance> PhysicalFontFace::CreateFontInstance(const FontSelectPattern& rFSD) const
 {
     return new LogicalFontInstance(*this, rFSD);
 }
diff --git a/vcl/source/font/fontcache.cxx b/vcl/source/font/fontcache.cxx
index 205b49ada4e0..a58d9b6931f2 100644
--- a/vcl/source/font/fontcache.cxx
+++ b/vcl/source/font/fontcache.cxx
@@ -83,23 +83,14 @@ bool ImplFontCache::IFSD_Equal::operator()(const FontSelectPattern& rA, const Fo
 }
 
 ImplFontCache::ImplFontCache()
-:   mpLastHitCacheEntry( nullptr ),
-    mnRef0Count( 0 )
+:   mpLastHitCacheEntry( nullptr )
 {}
 
 ImplFontCache::~ImplFontCache()
 {
-    for (auto const& fontInstance : maFontInstanceList)
-    {
-        LogicalFontInstance* pFontInstance = fontInstance.second;
-        if (pFontInstance->mnRefCount)
-            pFontInstance->mpFontCache = nullptr;
-        else
-            delete pFontInstance;
-    }
 }
 
-LogicalFontInstance* ImplFontCache::GetFontInstance( PhysicalFontCollection const * pFontList,
+rtl::Reference<LogicalFontInstance> ImplFontCache::GetFontInstance( PhysicalFontCollection const * pFontList,
     const vcl::Font& rFont, const Size& rSize, float fExactHeight )
 {
     // initialize internal font request object
@@ -107,10 +98,10 @@ LogicalFontInstance* ImplFontCache::GetFontInstance( PhysicalFontCollection cons
     return GetFontInstance( pFontList, aFontSelData );
 }
 
-LogicalFontInstance* ImplFontCache::GetFontInstance( PhysicalFontCollection const * pFontList,
+rtl::Reference<LogicalFontInstance> ImplFontCache::GetFontInstance( PhysicalFontCollection const * pFontList,
     FontSelectPattern& aFontSelData )
 {
-    LogicalFontInstance *pFontInstance = nullptr;
+    rtl::Reference<LogicalFontInstance> pFontInstance;
     PhysicalFontFamily* pFontFamily = nullptr;
 
     // check if a directly matching logical font instance is already cached,
@@ -140,12 +131,7 @@ LogicalFontInstance* ImplFontCache::GetFontInstance( PhysicalFontCollection cons
         }
     }
 
-    if( pFontInstance ) // cache hit => use existing font instance
-    {
-        // increase the font instance's reference count
-        pFontInstance->Acquire();
-    }
-    else if (pFontFamily) // still no cache hit => create a new font instance
+    if( !pFontInstance && pFontFamily) // still no cache hit => create a new font instance
     {
         PhysicalFontFace* pFontData = pFontFamily->FindBestFontFace(aFontSelData);
 
@@ -173,19 +159,38 @@ LogicalFontInstance* ImplFontCache::GetFontInstance( PhysicalFontCollection cons
         }
 #endif
 
+        static const size_t FONTCACHE_MAX = getenv("LO_TESTNAME") ? 1 : 50;
+
+        if (maFontInstanceList.size() >= FONTCACHE_MAX)
+        {
+            // remove entries from font instance cache that are only referenced by the cache
+            FontInstanceList::iterator it_next = maFontInstanceList.begin();
+            while( it_next != maFontInstanceList.end() )
+            {
+                LogicalFontInstance* pFontEntry = (*it_next).second.get();
+                if( pFontEntry->m_nCount > 1 )
+                {
+                    ++it_next;
+                    continue;
+                }
+                maFontInstanceList.erase(it_next);
+                if (mpLastHitCacheEntry == pFontEntry)
+                    mpLastHitCacheEntry = nullptr;
+                // just remove one entry, which will bring us back under FONTCACHE_MAX size again
+                break;
+            }
+        }
+
+        assert(pFontInstance);
         // add the new entry to the cache
-#ifndef NDEBUG
-        auto aResult =
-#endif
-        maFontInstanceList.insert({aFontSelData, pFontInstance});
-        assert(aResult.second);
+        maFontInstanceList.insert({aFontSelData, pFontInstance.get()});
     }
 
-    mpLastHitCacheEntry = pFontInstance;
+    mpLastHitCacheEntry = pFontInstance.get();
     return pFontInstance;
 }
 
-LogicalFontInstance* ImplFontCache::GetGlyphFallbackFont( PhysicalFontCollection const * pFontCollection,
+rtl::Reference<LogicalFontInstance> ImplFontCache::GetGlyphFallbackFont( PhysicalFontCollection const * pFontCollection,
     FontSelectPattern& rFontSelData, int nFallbackLevel, OUString& rMissingCodes )
 {
     // get a candidate font for glyph fallback
@@ -216,102 +221,17 @@ LogicalFontInstance* ImplFontCache::GetGlyphFallbackFont( PhysicalFontCollection
         rFontSelData.maSearchName.clear();
     }
 
-    LogicalFontInstance* pFallbackFont = GetFontInstance( pFontCollection, rFontSelData );
+    rtl::Reference<LogicalFontInstance> pFallbackFont = GetFontInstance( pFontCollection, rFontSelData );
     return pFallbackFont;
 }
 
-void ImplFontCache::Acquire(LogicalFontInstance* pFontInstance)
-{
-    assert(pFontInstance->mpFontCache == this);
-    assert(IsFontInList(pFontInstance) && "ImplFontCache::Acquire() - font absent in the cache");
-
-    if (0 == pFontInstance->mnRefCount++)
-        --mnRef0Count;
-}
-
-void ImplFontCache::Release(LogicalFontInstance* pFontInstance)
-{
-    static const int FONTCACHE_MAX = getenv("LO_TESTNAME") ? 1 : 50;
-
-    assert(pFontInstance->mpFontCache == this);
-    assert(IsFontInList(pFontInstance) && "ImplFontCache::Release() - font absent in the cache");
-    assert(pFontInstance->mnRefCount > 0 && "ImplFontCache::Release() - font refcount underflow");
-    if( --pFontInstance->mnRefCount > 0 )
-        return;
-
-    if (++mnRef0Count < FONTCACHE_MAX)
-        return;
-
-    assert(CountUnreferencedEntries() == mnRef0Count);
-
-    // remove unused entries from font instance cache
-    FontInstanceList::iterator it_next = maFontInstanceList.begin();
-    while( it_next != maFontInstanceList.end() )
-    {
-        LogicalFontInstance* pFontEntry = (*it_next).second;
-        if( pFontEntry->mnRefCount > 0 )
-        {
-            ++it_next;
-            continue;
-        }
-
-        it_next = maFontInstanceList.erase(it_next);
-        delete pFontEntry;
-        --mnRef0Count;
-        assert(mnRef0Count>=0 && "ImplFontCache::Release() - refcount0 underflow");
-
-        if (mpLastHitCacheEntry == pFontEntry)
-            mpLastHitCacheEntry = nullptr;
-    }
-
-    assert(mnRef0Count==0 && "ImplFontCache::Release() - refcount0 mismatch");
-}
-
-bool ImplFontCache::IsFontInList(const LogicalFontInstance* pFont) const
-{
-    auto Pred = [pFont](const FontInstanceList::value_type& el) -> bool { return el.second == pFont; };
-    return std::find_if(maFontInstanceList.begin(), maFontInstanceList.end(), Pred) != maFontInstanceList.end();
-}
-
-int ImplFontCache::CountUnreferencedEntries() const
-{
-    size_t nCount = 0;
-    // count unreferenced entries
-    for (auto const& fontInstance : maFontInstanceList)
-    {
-        const LogicalFontInstance* pFontEntry = fontInstance.second;
-        if (pFontEntry->mnRefCount > 0)
-            continue;
-        ++nCount;
-    }
-    return nCount;
-}
-
 void ImplFontCache::Invalidate()
 {
-    assert(CountUnreferencedEntries() == mnRef0Count);
-
-    // delete unreferenced entries
-    for (auto const& fontInstance : maFontInstanceList)
-    {
-        LogicalFontInstance* pFontEntry = fontInstance.second;
-        if( pFontEntry->mnRefCount > 0 )
-        {
-            // These fonts will become orphans after clearing the list below;
-            // allow them to control their life from now on and wish good luck :)
-            pFontEntry->mpFontCache = nullptr;
-            continue;
-        }
-
-        delete pFontEntry;
-        --mnRef0Count;
-    }
-
     // #112304# make sure the font cache is really clean
     mpLastHitCacheEntry = nullptr;
+    for (auto const & pair : maFontInstanceList)
+        pair.second->mpFontCache = nullptr;
     maFontInstanceList.clear();
-
-    assert(mnRef0Count==0 && "ImplFontCache::Invalidate() - mnRef0Count non-zero");
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/font/fontinstance.cxx b/vcl/source/font/fontinstance.cxx
index fca20fd03ca3..e5fac6c6a67b 100644
--- a/vcl/source/font/fontinstance.cxx
+++ b/vcl/source/font/fontinstance.cxx
@@ -48,7 +48,6 @@ LogicalFontInstance::LogicalFontInstance(const PhysicalFontFace& rFontFace, cons
     , mnOrientation( 0 )
     , mbInit( false )
     , mpFontCache( nullptr )
-    , mnRefCount( 1 )
     , m_aFontSelData(rFontSelData)
     , m_pHbFont(nullptr)
     , m_nAveWidthFactor(1.0f)
@@ -115,27 +114,6 @@ void LogicalFontInstance::GetScale(double* nXScale, double* nYScale)
         *nXScale = nWidth / nUPEM;
 }
 
-void LogicalFontInstance::Acquire()
-{
-    assert(mnRefCount < std::numeric_limits<decltype(mnRefCount)>::max()
-        && "LogicalFontInstance::Release() - refcount overflow");
-    if (mpFontCache)
-        mpFontCache->Acquire(this);
-    else
-        ++mnRefCount;
-}
-
-void LogicalFontInstance::Release()
-{
-    assert(mnRefCount > 0 && "LogicalFontInstance::Release() - refcount underflow");
-
-    if (mpFontCache)
-        mpFontCache->Release(this);
-    else
-        if (--mnRefCount == 0)
-            delete this;
-}
-
 void LogicalFontInstance::AddFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, const OUString& rFontName )
 {
     if( !mpUnicodeFallbackList )
diff --git a/vcl/source/font/fontselect.cxx b/vcl/source/font/fontselect.cxx
index 80b9ba78ce6b..563c6ebcbc54 100644
--- a/vcl/source/font/fontselect.cxx
+++ b/vcl/source/font/fontselect.cxx
@@ -21,6 +21,7 @@
 #include <o3tl/safeint.hxx>
 
 #include <fontselect.hxx>
+#include <fontinstance.hxx>
 
 #include <PhysicalFontFace.hxx>
 #include <svdata.hxx>
diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx
index 8dcdc06a1ce8..22b5ea460d8e 100644
--- a/vcl/source/gdi/CommonSalLayout.cxx
+++ b/vcl/source/gdi/CommonSalLayout.cxx
@@ -58,12 +58,10 @@ GenericSalLayout::GenericSalLayout(LogicalFontInstance &rFont)
     , mpVertGlyphs(nullptr)
     , mbFuzzing(utl::ConfigManager::IsFuzzing())
 {
-    mpFont->Acquire();
 }
 
 GenericSalLayout::~GenericSalLayout()
 {
-    mpFont->Release();
 }
 
 void GenericSalLayout::ParseFeatures(const OUString& aName)
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index d9411779fb34..181d2003f3e4 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -6779,7 +6779,7 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool
         // This includes ascent / descent.
         aRectangle.setHeight(aRefDevFontMetric.GetLineHeight());
 
-        LogicalFontInstance* pFontInstance = m_pReferenceDevice->mpFontInstance;
+        LogicalFontInstance* pFontInstance = m_pReferenceDevice->mpFontInstance.get();
         if (pFontInstance->mnOrientation)
         {
             // Adapt rectangle for rotated text.
@@ -7269,7 +7269,7 @@ void PDFWriterImpl::drawLine( const Point& rStart, const Point& rStop, const Lin
 void PDFWriterImpl::drawWaveTextLine( OStringBuffer& aLine, long nWidth, FontLineStyle eTextLine, Color aColor, bool bIsAbove )
 {
     // note: units in pFontInstance are ref device pixel
-    LogicalFontInstance*  pFontInstance = m_pReferenceDevice->mpFontInstance;
+    LogicalFontInstance*  pFontInstance = m_pReferenceDevice->mpFontInstance.get();
     long            nLineHeight = 0;
     long            nLinePos = 0;
 
@@ -7339,7 +7339,7 @@ void PDFWriterImpl::drawWaveTextLine( OStringBuffer& aLine, long nWidth, FontLin
 void PDFWriterImpl::drawStraightTextLine( OStringBuffer& aLine, long nWidth, FontLineStyle eTextLine, Color aColor, bool bIsAbove )
 {
     // note: units in pFontInstance are ref device pixel
-    LogicalFontInstance*  pFontInstance = m_pReferenceDevice->mpFontInstance;
+    LogicalFontInstance*  pFontInstance = m_pReferenceDevice->mpFontInstance.get();
     long            nLineHeight = 0;
     long            nLinePos  = 0;
     long            nLinePos2 = 0;
@@ -7510,7 +7510,7 @@ void PDFWriterImpl::drawStraightTextLine( OStringBuffer& aLine, long nWidth, Fon
 void PDFWriterImpl::drawStrikeoutLine( OStringBuffer& aLine, long nWidth, FontStrikeout eStrikeout, Color aColor )
 {
     // note: units in pFontInstance are ref device pixel
-    LogicalFontInstance*  pFontInstance = m_pReferenceDevice->mpFontInstance;
+    LogicalFontInstance*  pFontInstance = m_pReferenceDevice->mpFontInstance.get();
     long            nLineHeight = 0;
     long            nLinePos  = 0;
     long            nLinePos2 = 0;
@@ -7607,7 +7607,7 @@ void PDFWriterImpl::drawStrikeoutChar( const Point& rPos, long nWidth, FontStrik
     aRect.SetBottom( rPos.Y()+aRefDevFontMetric.GetDescent() );
     aRect.SetTop( rPos.Y()-aRefDevFontMetric.GetAscent() );
 
-    LogicalFontInstance* pFontInstance = m_pReferenceDevice->mpFontInstance;
+    LogicalFontInstance* pFontInstance = m_pReferenceDevice->mpFontInstance.get();
     if (pFontInstance->mnOrientation)
     {
         tools::Polygon aPoly( aRect );
@@ -7642,7 +7642,7 @@ void PDFWriterImpl::drawTextLine( const Point& rPos, long nWidth, FontStrikeout
     updateGraphicsState();
 
     // note: units in pFontInstance are ref device pixel
-    LogicalFontInstance* pFontInstance = m_pReferenceDevice->mpFontInstance;
+    LogicalFontInstance* pFontInstance = m_pReferenceDevice->mpFontInstance.get();
     Color           aUnderlineColor = m_aCurrentPDFState.m_aTextLineColor;
     Color           aOverlineColor  = m_aCurrentPDFState.m_aOverlineColor;
     Color           aStrikeoutColor = m_aCurrentPDFState.m_aFont.GetColor();
diff --git a/vcl/source/gdi/print.cxx b/vcl/source/gdi/print.cxx
index a5fe96a76db0..ac44dcbbaf18 100644
--- a/vcl/source/gdi/print.cxx
+++ b/vcl/source/gdi/print.cxx
@@ -580,12 +580,7 @@ void Printer::ImplReleaseFonts()
     mbNewFont = true;
     mbInitFont = true;
 
-    if ( mpFontInstance )
-    {
-        mpFontInstance->Release();
-        mpFontInstance = nullptr;
-    }
-
+    mpFontInstance.clear();
     mpDeviceFontList.reset();
     mpDeviceFontSizeList.reset();
 }
@@ -946,11 +941,7 @@ void Printer::dispose()
         // OutputDevice Dtor is trying the same thing; that why we need to set
         // the FontEntry to NULL here
         // TODO: consolidate duplicate cleanup by Printer and OutputDevice
-        if ( mpFontInstance )
-        {
-            mpFontInstance->Release();
-            mpFontInstance = nullptr;
-        }
+        mpFontInstance.clear();
         mpDeviceFontList.reset();
         mpDeviceFontSizeList.reset();
         delete mpFontCache;
@@ -1087,11 +1078,7 @@ bool Printer::SetPrinterProps( const Printer* pPrinter )
         {
             ReleaseGraphics();
             pSVData->mpDefInst->DestroyInfoPrinter( mpInfoPrinter );
-            if ( mpFontInstance )
-            {
-                mpFontInstance->Release();
-                mpFontInstance = nullptr;
-            }
+            mpFontInstance.clear();
             mpDeviceFontList.reset();
             mpDeviceFontSizeList.reset();
             // clean up font list
@@ -1122,11 +1109,7 @@ bool Printer::SetPrinterProps( const Printer* pPrinter )
         {
             pSVData->mpDefInst->DestroyInfoPrinter( mpInfoPrinter );
 
-            if ( mpFontInstance )
-            {
-                mpFontInstance->Release();
-                mpFontInstance = nullptr;
-            }
+            mpFontInstance.clear();
             mpDeviceFontList.reset();
             mpDeviceFontSizeList.reset();
             delete mpFontCache;
diff --git a/vcl/source/gdi/virdev.cxx b/vcl/source/gdi/virdev.cxx
index 8972d83c23c8..dad14458705c 100644
--- a/vcl/source/gdi/virdev.cxx
+++ b/vcl/source/gdi/virdev.cxx
@@ -487,11 +487,7 @@ void VirtualDevice::ImplSetReferenceDevice( RefDevMode i_eRefDevMode, sal_Int32
 
     // the reference device should have only scalable fonts
     // => clean up the original font lists before getting new ones
-    if ( mpFontInstance )
-    {
-        mpFontInstance->Release();
-        mpFontInstance = nullptr;
-    }
+    mpFontInstance.clear();
     mpDeviceFontList.reset();
     mpDeviceFontSizeList.reset();
 
diff --git a/vcl/source/outdev/font.cxx b/vcl/source/outdev/font.cxx
index c65dd0d5cce9..439a3df75c5b 100644
--- a/vcl/source/outdev/font.cxx
+++ b/vcl/source/outdev/font.cxx
@@ -168,7 +168,7 @@ FontMetric OutputDevice::GetFontMetric() const
     if( mbNewFont && !ImplNewFont() )
         return aMetric;
 
-    LogicalFontInstance* pFontInstance = mpFontInstance;
+    LogicalFontInstance* pFontInstance = mpFontInstance.get();
     ImplFontMetricDataRef xFontMetric = pFontInstance->mxFontMetric;
 
     // prepare metric
@@ -475,11 +475,7 @@ long OutputDevice::GetFontExtLeading() const
 void OutputDevice::ImplClearFontData( const bool bNewFontLists )
 {
     // the currently selected logical font is no longer needed
-    if ( mpFontInstance )
-    {
-        mpFontInstance->Release();
-        mpFontInstance = nullptr;
-    }
+    mpFontInstance.clear();
 
     mbInitFont = true;
     mbNewFont = true;
@@ -884,12 +880,11 @@ vcl::Font OutputDevice::GetDefaultFont( DefaultFontType nType, LanguageType eLan
 
                     // get the name of the first available font
                     float fExactHeight = static_cast<float>(aSize.Height());
-                    LogicalFontInstance* pFontInstance = pOutDev->mpFontCache->GetFontInstance( pOutDev->mpFontCollection, aFont, aSize, fExactHeight );
+                    rtl::Reference<LogicalFontInstance> pFontInstance = pOutDev->mpFontCache->GetFontInstance( pOutDev->mpFontCollection, aFont, aSize, fExactHeight );
                     if (pFontInstance)
                     {
                         assert(pFontInstance->GetFontFace());
                         aFont.SetFamilyName(pFontInstance->GetFontFace()->GetFamilyName());
-                        pFontInstance->Release();
                     }
                 }
             }
@@ -1034,12 +1029,12 @@ bool OutputDevice::ImplNewFont() const
         aSize.setWidth( 1 );
 
     // get font entry
-    LogicalFontInstance* pOldFontInstance = mpFontInstance;
+    rtl::Reference<LogicalFontInstance> pOldFontInstance = mpFontInstance;
     mpFontInstance = mpFontCache->GetFontInstance( mpFontCollection, maFont, aSize, fExactHeight );
-    if( pOldFontInstance )
-        pOldFontInstance->Release();
+    bool bNewFontInstance = pOldFontInstance.get() != mpFontInstance.get();
+    pOldFontInstance.clear();
 
-    LogicalFontInstance* pFontInstance = mpFontInstance;
+    LogicalFontInstance* pFontInstance = mpFontInstance.get();
 
     if (!pFontInstance)
     {
@@ -1049,7 +1044,7 @@ bool OutputDevice::ImplNewFont() const
 
     // mark when lower layers need to get involved
     mbNewFont = false;
-    if( pFontInstance != pOldFontInstance )
+    if( bNewFontInstance )
         mbInitFont = true;
 
     // select font when it has not been initialized yet
@@ -1350,7 +1345,7 @@ std::unique_ptr<SalLayout> OutputDevice::ImplGlyphFallbackLayout( std::unique_pt
         // if the system-specific glyph fallback is active
         aFontSelData.mpFontInstance = mpFontInstance; // reset the fontinstance to base-level
 
-        LogicalFontInstance* pFallbackFont = mpFontCache->GetGlyphFallbackFont( mpFontCollection,
+        rtl::Reference<LogicalFontInstance> pFallbackFont = mpFontCache->GetGlyphFallbackFont( mpFontCollection,
             aFontSelData, nFallbackLevel, aMissingCodes );
         if( !pFallbackFont )
             break;
@@ -1364,7 +1359,6 @@ std::unique_ptr<SalLayout> OutputDevice::ImplGlyphFallbackLayout( std::unique_pt
             if( mpFontInstance->GetFontFace() == pFallbackFont->GetFontFace() &&
                 aMissingCodes.indexOf(0x202F) == -1 )
             {
-                pFallbackFont->Release();
                 continue;
             }
         }
@@ -1382,8 +1376,6 @@ std::unique_ptr<SalLayout> OutputDevice::ImplGlyphFallbackLayout( std::unique_pt
                 pMultiSalLayout->SetIncomplete(true);
         }
 
-        pFallbackFont->Release();
-
         // break when this fallback was sufficient
         if( !rLayoutArgs.PrepareFallback() )
             break;
diff --git a/vcl/source/outdev/outdev.cxx b/vcl/source/outdev/outdev.cxx
index 82833c72d819..1ecdcca86411 100644
--- a/vcl/source/outdev/outdev.cxx
+++ b/vcl/source/outdev/outdev.cxx
@@ -172,8 +172,7 @@ void OutputDevice::dispose()
     mpOutDevStateStack.reset();
 
     // release the active font instance
-    if( mpFontInstance )
-        mpFontInstance->Release();
+    mpFontInstance.clear();
 
     // remove cached results of GetDevFontList/GetDevSizeList
     mpDeviceFontList.reset();
diff --git a/vcl/source/outdev/outdevstate.cxx b/vcl/source/outdev/outdevstate.cxx
index 6713f6481369..24e0b75e3c3e 100644
--- a/vcl/source/outdev/outdevstate.cxx
+++ b/vcl/source/outdev/outdevstate.cxx
@@ -615,12 +615,7 @@ void OutputDevice::ImplReleaseFonts()
     mbNewFont = true;
     mbInitFont = true;
 
-    if ( mpFontInstance )
-    {
-        mpFontInstance->Release();
-        mpFontInstance = nullptr;
-    }
-
+    mpFontInstance.clear();
     mpDeviceFontList.reset();
     mpDeviceFontSizeList.reset();
 }
diff --git a/vcl/source/outdev/textline.cxx b/vcl/source/outdev/textline.cxx
index 22e7db6230a1..2034a54beb8a 100644
--- a/vcl/source/outdev/textline.cxx
+++ b/vcl/source/outdev/textline.cxx
@@ -211,7 +211,7 @@ void OutputDevice::ImplDrawWaveTextLine( long nBaseX, long nBaseY,
                                          Color aColor,
                                          bool bIsAbove )
 {
-    LogicalFontInstance* pFontInstance = mpFontInstance;
+    LogicalFontInstance* pFontInstance = mpFontInstance.get();
     long            nLineHeight;
     long            nLinePos;
 
@@ -279,7 +279,7 @@ void OutputDevice::ImplDrawStraightTextLine( long nBaseX, long nBaseY,
                                              Color aColor,
                                              bool bIsAbove )
 {
-    LogicalFontInstance*  pFontInstance = mpFontInstance;
+    LogicalFontInstance*  pFontInstance = mpFontInstance.get();
     long            nLineHeight = 0;
     long            nLinePos  = 0;
     long            nLinePos2 = 0;
@@ -521,7 +521,7 @@ void OutputDevice::ImplDrawStrikeoutLine( long nBaseX, long nBaseY,
                                           FontStrikeout eStrikeout,
                                           Color aColor )
 {
-    LogicalFontInstance*  pFontInstance = mpFontInstance;
+    LogicalFontInstance*  pFontInstance = mpFontInstance.get();
     long            nLineHeight = 0;
     long            nLinePos  = 0;
     long            nLinePos2 = 0;
@@ -1030,7 +1030,7 @@ void OutputDevice::DrawWaveLine( const Point& rStartPos, const Point& rEndPos )
     }
 
     // #109280# make sure the waveline does not exceed the descent to avoid paint problems
-    LogicalFontInstance* pFontInstance = mpFontInstance;
+    LogicalFontInstance* pFontInstance = mpFontInstance.get();
     if( nWaveHeight > pFontInstance->mxFontMetric->GetWavelineUnderlineSize() )
     {
         nWaveHeight = pFontInstance->mxFontMetric->GetWavelineUnderlineSize();
diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx
index ce0be303d2e8..12182b2c3f1f 100644
--- a/vcl/source/window/window.cxx
+++ b/vcl/source/window/window.cxx
@@ -1738,7 +1738,7 @@ void Window::ImplNewInputContext()
     SalInputContext         aNewContext;
     const vcl::Font&        rFont = rInputContext.GetFont();
     const OUString&         rFontName = rFont.GetFamilyName();
-    LogicalFontInstance*    pFontInstance = nullptr;
+    rtl::Reference<LogicalFontInstance> pFontInstance;
     aNewContext.mpFont = nullptr;
     if (!rFontName.isEmpty())
     {
@@ -1761,9 +1761,6 @@ void Window::ImplNewInputContext()
     aNewContext.meLanguage  = rFont.GetLanguage();
     aNewContext.mnOptions   = rInputContext.GetOptions();
     pFocusWin->ImplGetFrame()->SetInputContext( &aNewContext );
-
-    if ( pFontInstance )
-        pFontInstance->Release();
 }
 
 void Window::doLazyDelete()
diff --git a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx
index 5d7b9ff064ac..d17f02db69ff 100644
--- a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx
+++ b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx
@@ -357,7 +357,7 @@ FreetypeFontFace::FreetypeFontFace( FreetypeFontInfo* pFI, const FontAttributes&
 {
 }
 
-LogicalFontInstance* FreetypeFontFace::CreateFontInstance(const FontSelectPattern& rFSD) const
+rtl::Reference<LogicalFontInstance> FreetypeFontFace::CreateFontInstance(const FontSelectPattern& rFSD) const
 {
     return new FreetypeFontInstance(*this, rFSD);
 }
@@ -366,7 +366,7 @@ LogicalFontInstance* FreetypeFontFace::CreateFontInstance(const FontSelectPatter
 
 FreetypeFont::FreetypeFont( const FontSelectPattern& rFSD, FreetypeFontInfo* pFI )
 :   maGlyphList( 0),
-    mpFontInstance(rFSD.mpFontInstance),
+    mpFontInstance(static_cast<FreetypeFontInstance*>(rFSD.mpFontInstance.get())),
     mnRefCount(1),
     mnBytesUsed( sizeof(FreetypeFont) ),
     mpPrevGCFont( nullptr ),
@@ -385,8 +385,7 @@ FreetypeFont::FreetypeFont( const FontSelectPattern& rFSD, FreetypeFontInfo* pFI
     int nPrioEmbedded = nDefaultPrioEmbedded;
     // TODO: move update of mpFontInstance into FontEntry class when
     // it becomes responsible for the FreetypeFont instantiation
-    static_cast<FreetypeFontInstance*>(mpFontInstance)->SetFreetypeFont( this );
-    mpFontInstance->Acquire();
+    mpFontInstance->SetFreetypeFont( this );
 
     maFaceFT = pFI->GetFaceFT();
 
@@ -485,7 +484,7 @@ FreetypeFont::~FreetypeFont()
 
     mpFontInfo->ReleaseFaceFT();
 
-    mpFontInstance->Release();
+    mpFontInstance.clear();
 
     ReleaseFromGarbageCollect();
 }
diff --git a/vcl/win/gdi/salfont.cxx b/vcl/win/gdi/salfont.cxx
index 11957c7043dc..b0158f9154d5 100644
--- a/vcl/win/gdi/salfont.cxx
+++ b/vcl/win/gdi/salfont.cxx
@@ -658,7 +658,7 @@ rtl::Reference<PhysicalFontFace> WinFontFace::Clone() const
     return new WinFontFace(*this);
 }
 
-LogicalFontInstance* WinFontFace::CreateFontInstance(const FontSelectPattern& rFSD) const
+rtl::Reference<LogicalFontInstance> WinFontFace::CreateFontInstance(const FontSelectPattern& rFSD) const
 {
     return new WinFontInstance(*this, rFSD);
 }
@@ -922,33 +922,16 @@ void WinSalGraphics::SetFont( const FontSelectPattern* pFont, int nFallbackLevel
         for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i )
         {
             if( mhFonts[i] )
-            {
                 ::DeleteFont( mhFonts[i] );
-                mhFonts[ i ] = nullptr;
-            }
-            if (mpWinFontEntry[i])
-            {
-                GetWinFontEntry(i)->Release();
-                mpWinFontEntry[i] = nullptr;
-            }
-            mfFontScale[i] = 1.0;
+            mhFonts[ i ] = nullptr;
+            mpWinFontEntry[i] = nullptr;
         }
         return;
     }
 
-    if (mpWinFontEntry[nFallbackLevel])
-    {
-        GetWinFontEntry(nFallbackLevel)->Release();
-    }
     // WinSalGraphics::GetEmbedFontData does not set mpFontInstance
     // since it is interested in font file data only.
-    if (pFont->mpFontInstance)
-    {
-        pFont->mpFontInstance->Acquire();
-    }
-
-    WinFontInstance *pFontInstance = static_cast<WinFontInstance*>(pFont->mpFontInstance);
-    mpWinFontEntry[ nFallbackLevel ] = pFontInstance;
+    mpWinFontEntry[ nFallbackLevel ] = reinterpret_cast<WinFontInstance*>( pFont->mpFontInstance.get() );
 
     HFONT hOldFont = nullptr;
     HFONT hNewFont = pFontInstance ? pFontInstance->GetHFONT() : nullptr;
diff --git a/vcl/win/gdi/salgdi.cxx b/vcl/win/gdi/salgdi.cxx
index aba0d6e6589e..57dd4ed37efd 100644
--- a/vcl/win/gdi/salgdi.cxx
+++ b/vcl/win/gdi/salgdi.cxx
@@ -29,6 +29,7 @@
 #include <win/salgdi.h>
 #include <win/salframe.h>
 #include <win/salvd.h>
+#include <win/winlayout.hxx>
 #include <basegfx/matrix/b2dhommatrixtools.hxx>
 
 #include <salgdiimpl.hxx>
diff --git a/vcl/win/gdi/winlayout.cxx b/vcl/win/gdi/winlayout.cxx
index 392a6abef02a..fa0c2b683387 100644
--- a/vcl/win/gdi/winlayout.cxx
+++ b/vcl/win/gdi/winlayout.cxx
@@ -310,11 +310,6 @@ std::unique_ptr<SalLayout> WinSalGraphics::GetTextLayout(ImplLayoutArgs& /*rArgs
     return std::unique_ptr<SalLayout>(aLayout);
 }
 
-LogicalFontInstance * WinSalGraphics::GetWinFontEntry(int const nFallbackLevel)
-{
-    return mpWinFontEntry[nFallbackLevel];
-}
-
 WinFontInstance::WinFontInstance(const PhysicalFontFace& rPFF, const FontSelectPattern& rFSP)
     : LogicalFontInstance(rPFF, rFSP)
     , m_hFont(nullptr)
commit ed1570ab5474264971d6d60d81142085b69174cf
Author:     Noel Grandin <noel.grandin at collabora.co.uk>
AuthorDate: Tue Jun 5 14:48:51 2018 +0200
Commit:     Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
CommitDate: Fri Jan 25 08:38:23 2019 +0100

    manage PhysicalFontFace by rtl::Reference
    
    Change-Id: I8f66b5afb066fe83abb83c56ebde6f21197f894b
    Reviewed-on: https://gerrit.libreoffice.org/55333
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Noel Grandin <noel.grandin at collabora.co.uk>
    (cherry picked from commit 77a01802d1a0452814718789bb0c76adeeb747c0)

diff --git a/vcl/inc/PhysicalFontFace.hxx b/vcl/inc/PhysicalFontFace.hxx
index 39237ff46f89..2406b6cf41da 100644
--- a/vcl/inc/PhysicalFontFace.hxx
+++ b/vcl/inc/PhysicalFontFace.hxx
@@ -20,6 +20,8 @@
 #ifndef INCLUDED_VCL_INC_PHYSICALFONTFACE_HXX
 #define INCLUDED_VCL_INC_PHYSICALFONTFACE_HXX
 
+#include <salhelper/simplereferenceobject.hxx>
+#include <rtl/ref.hxx>
 #include <vcl/dllapi.h>
 
 #include "fontattributes.hxx"
@@ -40,7 +42,6 @@ public:
 
 
 // TODO: no more direct access to members
-// TODO: add reference counting
 // TODO: get rid of height/width for scalable fonts
 // TODO: make cloning cheaper
 
@@ -50,13 +51,11 @@ public:
  * It acts as a factory for its corresponding LogicalFontInstances and
  * can be extended to cache device and font instance specific data.
  */
-class VCL_PLUGIN_PUBLIC PhysicalFontFace : public FontAttributes
+class VCL_PLUGIN_PUBLIC PhysicalFontFace : public FontAttributes, public salhelper::SimpleReferenceObject
 {
 public:
-    virtual                ~PhysicalFontFace() {}
-
     virtual LogicalFontInstance* CreateFontInstance(const FontSelectPattern&) const;
-    virtual PhysicalFontFace* Clone() const = 0;
+    virtual rtl::Reference<PhysicalFontFace> Clone() const = 0;
 
     int                     GetHeight() const           { return mnHeight; }
     int                     GetWidth() const            { return mnWidth; }
@@ -68,6 +67,7 @@ public:
 
 protected:
     explicit PhysicalFontFace(const FontAttributes&);
+    PhysicalFontFace(const PhysicalFontFace&);
     void                    SetBitmapSize( int nW, int nH ) { mnWidth=nW; mnHeight=nH; }
 
     long                    mnWidth;    // Width (in pixels)
diff --git a/vcl/inc/PhysicalFontFamily.hxx b/vcl/inc/PhysicalFontFamily.hxx
index e88db8203809..990256590c88 100644
--- a/vcl/inc/PhysicalFontFamily.hxx
+++ b/vcl/inc/PhysicalFontFamily.hxx
@@ -67,7 +67,7 @@ public:
     void                InitMatchData( const utl::FontSubstConfiguration&,
                                        const OUString& rSearchName );
 
-    bool                AddFontFace( PhysicalFontFace* );
+    void                AddFontFace( PhysicalFontFace* );
 
     PhysicalFontFace*   FindBestFontFace( const FontSelectPattern& rFSD ) const;
 
@@ -78,7 +78,7 @@ static void             CalcType( ImplFontAttrs& rType, FontWeight& rWeight, Fon
                                   FontFamily eFamily, const utl::FontNameAttr* pFontAttr );
 
 private:
-    std::vector< std::unique_ptr<PhysicalFontFace> > maFontFaces;
+    std::vector< rtl::Reference<PhysicalFontFace> > maFontFaces;
 
     OUString            maFamilyName;       // original font family name
     OUString            maSearchName;       // normalized font family name
diff --git a/vcl/inc/fontinstance.hxx b/vcl/inc/fontinstance.hxx
index 90ed83d3ab33..317b7181198d 100644
--- a/vcl/inc/fontinstance.hxx
+++ b/vcl/inc/fontinstance.hxx
@@ -23,6 +23,7 @@
 #include "fontselect.hxx"
 #include "impfontmetricdata.hxx"
 
+#include <rtl/ref.hxx>
 #include <unordered_map>
 #include <memory>
 
@@ -64,7 +65,7 @@ public: // TODO: make data members private
     double GetAverageWidthFactor() const { return m_nAveWidthFactor; }
     const FontSelectPattern& GetFontSelectPattern() const { return m_aFontSelData; }
 
-    const PhysicalFontFace* GetFontFace() const { return m_pFontFace; }
+    const PhysicalFontFace* GetFontFace() const { return m_pFontFace.get(); }
     const ImplFontCache* GetFontCache() const { return mpFontCache; }
 
     int GetKashidaWidth();
@@ -91,7 +92,7 @@ private:
     const FontSelectPattern m_aFontSelData;
     hb_font_t* m_pHbFont;
     double m_nAveWidthFactor;
-    const PhysicalFontFace* m_pFontFace;
+    rtl::Reference<PhysicalFontFace> m_pFontFace;
 };
 
 inline hb_font_t* LogicalFontInstance::GetHbFont()
diff --git a/vcl/inc/outdev.h b/vcl/inc/outdev.h
index 3b626f3b0d8e..2aabdfa93acf 100644
--- a/vcl/inc/outdev.h
+++ b/vcl/inc/outdev.h
@@ -41,12 +41,12 @@ enum class AddFontSubstituteFlags;
 class ImplDeviceFontList
 {
 private:
-    std::vector<PhysicalFontFace*> maDevFontVector;
+    std::vector<rtl::Reference<PhysicalFontFace>> maDevFontVector;
 
 public:
                         ImplDeviceFontList()        { maDevFontVector.reserve(1024); }
     void                Add( PhysicalFontFace* pFace )  { maDevFontVector.push_back( pFace ); }
-    PhysicalFontFace*   Get( int nIndex ) const     { return maDevFontVector[ nIndex ]; }
+    PhysicalFontFace*   Get( int nIndex ) const     { return maDevFontVector[ nIndex ].get(); }
     int                 Count() const               { return maDevFontVector.size(); }
 };
 
diff --git a/vcl/inc/quartz/salgdi.h b/vcl/inc/quartz/salgdi.h
index 064b2125e8be..2f53a44d694e 100644
--- a/vcl/inc/quartz/salgdi.h
+++ b/vcl/inc/quartz/salgdi.h
@@ -61,7 +61,7 @@ public:
                                     CoreTextFontFace( const FontAttributes&, sal_IntPtr nFontID );
     virtual                         ~CoreTextFontFace() override;
 
-    PhysicalFontFace*               Clone() const override;
+    rtl::Reference<PhysicalFontFace> Clone() const override;
     sal_IntPtr                      GetFontId() const override;
 
     int                             GetFontTable( uint32_t nTagCode, unsigned char* ) const;
@@ -128,7 +128,7 @@ private:
     CTFontCollectionRef mpCTFontCollection;
     CFArrayRef mpCTFontArray;
 
-    std::unordered_map<sal_IntPtr,CoreTextFontFace*> maFontContainer;
+    std::unordered_map<sal_IntPtr, rtl::Reference<CoreTextFontFace>> maFontContainer;
 };
 
 
diff --git a/vcl/inc/unx/freetype_glyphcache.hxx b/vcl/inc/unx/freetype_glyphcache.hxx
index 0a7b88887b24..d6b87b7ab7a9 100644
--- a/vcl/inc/unx/freetype_glyphcache.hxx
+++ b/vcl/inc/unx/freetype_glyphcache.hxx
@@ -115,7 +115,7 @@ public:
                             FreetypeFontFace( FreetypeFontInfo*, const FontAttributes& );
 
     virtual LogicalFontInstance* CreateFontInstance( const FontSelectPattern& ) const override;
-    virtual PhysicalFontFace* Clone() const override   { return new FreetypeFontFace( *this ); }
+    virtual rtl::Reference<PhysicalFontFace> Clone() const override   { return new FreetypeFontFace( *this ); }
     virtual sal_IntPtr      GetFontId() const override { return mpFreetypeFontInfo->GetFontId(); }
 };
 
diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h
index d43a1b28bef7..dc7bc7510229 100644
--- a/vcl/inc/win/salgdi.h
+++ b/vcl/inc/win/salgdi.h
@@ -63,7 +63,7 @@ public:
                                 BYTE nPitchAndFamily  );
     virtual                 ~WinFontFace() override;
 
-    virtual PhysicalFontFace* Clone() const override;
+    virtual rtl::Reference<PhysicalFontFace> Clone() const override;
     virtual LogicalFontInstance* CreateFontInstance( const FontSelectPattern& ) const override;
     virtual sal_IntPtr      GetFontId() const override;
     void                    SetFontId( sal_IntPtr nId ) { mnId = nId; }
diff --git a/vcl/qt5/Qt5FontFace.cxx b/vcl/qt5/Qt5FontFace.cxx
index 0cd071385aaa..df5273036bc4 100644
--- a/vcl/qt5/Qt5FontFace.cxx
+++ b/vcl/qt5/Qt5FontFace.cxx
@@ -114,6 +114,6 @@ bool Qt5FontFace::GetFontCapabilities(vcl::FontCapabilities& rFontCapabilities)
     return rFontCapabilities.oUnicodeRange || rFontCapabilities.oCodePageRange;
 }
 
-PhysicalFontFace* Qt5FontFace::Clone() const { return new Qt5FontFace(*this); }
+rtl::Reference<PhysicalFontFace> Qt5FontFace::Clone() const { return new Qt5FontFace(*this); }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qt5/Qt5FontFace.hxx b/vcl/qt5/Qt5FontFace.hxx
index 9468cf15b4e3..4cc21010a8b7 100644
--- a/vcl/qt5/Qt5FontFace.hxx
+++ b/vcl/qt5/Qt5FontFace.hxx
@@ -38,7 +38,7 @@ public:
 
     static Qt5FontFace* fromQFont(const QFont& rFont);
 
-    PhysicalFontFace* Clone() const override;
+    rtl::Reference<PhysicalFontFace> Clone() const override;
     sal_IntPtr GetFontId() const override;
 
     int GetFontTable(const char pTagName[5], unsigned char*) const;
diff --git a/vcl/quartz/ctfonts.cxx b/vcl/quartz/ctfonts.cxx
index ac20c1e9f4c5..1d72f601eafa 100644
--- a/vcl/quartz/ctfonts.cxx
+++ b/vcl/quartz/ctfonts.cxx
@@ -283,7 +283,7 @@ hb_font_t* CoreTextStyle::ImplInitHbFont()
     return InitHbFont(pHbFace);
 }
 
-PhysicalFontFace* CoreTextFontFace::Clone() const
+rtl::Reference<PhysicalFontFace> CoreTextFontFace::Clone() const
 {
     return new CoreTextFontFace( *this);
 }
@@ -504,9 +504,9 @@ static void fontEnumCallBack( const void* pValue, void* pContext )
     if( bFontEnabled)
     {
         const sal_IntPtr nFontId = reinterpret_cast<sal_IntPtr>(pValue);
-        CoreTextFontFace* pFontData = new CoreTextFontFace( rDFA, nFontId );
+        rtl::Reference<CoreTextFontFace> pFontData = new CoreTextFontFace( rDFA, nFontId );
         SystemFontList* pFontList = static_cast<SystemFontList*>(pContext);
-        pFontList->AddFont( pFontData );
+        pFontList->AddFont( pFontData.get() );
     }
 }
 
@@ -517,11 +517,6 @@ SystemFontList::SystemFontList()
 
 SystemFontList::~SystemFontList()
 {
-    auto it = maFontContainer.cbegin();
-    for(; it != maFontContainer.cend(); ++it )
-    {
-        delete (*it).second;
-    }
     maFontContainer.clear();
 
     if( mpCTFontArray )
@@ -545,7 +540,7 @@ void SystemFontList::AnnounceFonts( PhysicalFontCollection& rFontCollection ) co
     auto it = maFontContainer.cbegin();
     for(; it != maFontContainer.cend(); ++it )
     {
-        rFontCollection.Add( (*it).second->Clone() );
+        rFontCollection.Add( (*it).second->Clone().get() );
     }
 }
 
@@ -556,7 +551,7 @@ CoreTextFontFace* SystemFontList::GetFontDataFromId( sal_IntPtr nFontId ) const
     {
         return nullptr;
     }
-    return (*it).second;
+    return (*it).second.get();
 }
 
 bool SystemFontList::Init()
diff --git a/vcl/quartz/salgdi.cxx b/vcl/quartz/salgdi.cxx
index b0f074b61303..7154bd672e0f 100644
--- a/vcl/quartz/salgdi.cxx
+++ b/vcl/quartz/salgdi.cxx
@@ -801,8 +801,8 @@ void AquaSalGraphics::GetGlyphWidths( const PhysicalFontFace* pFontData, bool bV
             free( const_cast<TTSimpleGlyphMetrics *>(pGlyphMetrics) );
         }
 
-        CoreTextFontFace rCTFontData(*pFontData, pFontData->GetFontId());
-        FontCharMapRef xFCMap = rCTFontData.GetFontCharMap();
+        rtl::Reference<CoreTextFontFace> rCTFontData(new CoreTextFontFace(*pFontData, pFontData->GetFontId()));
+        FontCharMapRef xFCMap = rCTFontData->GetFontCharMap();
         SAL_WARN_IF( !xFCMap.is() || !xFCMap->GetCharCount(), "vcl", "no charmap" );
 
         // get unicode<->glyph encoding
diff --git a/vcl/source/font/PhysicalFontCollection.cxx b/vcl/source/font/PhysicalFontCollection.cxx
index fcdef005dfdd..9a87d8c0fbf3 100644
--- a/vcl/source/font/PhysicalFontCollection.cxx
+++ b/vcl/source/font/PhysicalFontCollection.cxx
@@ -283,10 +283,7 @@ void PhysicalFontCollection::Add( PhysicalFontFace* pNewData )
 
     PhysicalFontFamily* pFoundData = FindOrCreateFontFamily( aSearchName );
 
-    bool bKeepNewData = pFoundData->AddFontFace( pNewData );
-
-    if( !bKeepNewData )
-        delete pNewData;
+    pFoundData->AddFontFace( pNewData );
 }
 
 // find the font from the normalized font family name
diff --git a/vcl/source/font/PhysicalFontFace.cxx b/vcl/source/font/PhysicalFontFace.cxx
index 40948c41e77e..690fd1fdc401 100644
--- a/vcl/source/font/PhysicalFontFace.cxx
+++ b/vcl/source/font/PhysicalFontFace.cxx
@@ -37,6 +37,14 @@ PhysicalFontFace::PhysicalFontFace( const FontAttributes& rDFA )
             SetSymbolFlag( true );
 }
 
+PhysicalFontFace::PhysicalFontFace( const PhysicalFontFace& other )
+    : FontAttributes( other )
+    , salhelper::SimpleReferenceObject()
+    , mnWidth(other.mnWidth)
+    , mnHeight(other.mnWidth)
+{
+}
+
 LogicalFontInstance* PhysicalFontFace::CreateFontInstance(const FontSelectPattern& rFSD) const
 {
     return new LogicalFontInstance(*this, rFSD);
diff --git a/vcl/source/font/PhysicalFontFamily.cxx b/vcl/source/font/PhysicalFontFamily.cxx
index 34ad038a38a7..d0c1c2dad165 100644
--- a/vcl/source/font/PhysicalFontFamily.cxx
+++ b/vcl/source/font/PhysicalFontFamily.cxx
@@ -100,7 +100,7 @@ PhysicalFontFamily::~PhysicalFontFamily()
 {
 }
 
-bool PhysicalFontFamily::AddFontFace( PhysicalFontFace* pNewFontFace )
+void PhysicalFontFamily::AddFontFace( PhysicalFontFace* pNewFontFace )
 {
     if( maFontFaces.empty() )
     {
@@ -162,19 +162,18 @@ bool PhysicalFontFamily::AddFontFace( PhysicalFontFace* pNewFontFace )
 
         // ignore duplicate if its quality is worse
         if( pNewFontFace->GetQuality() < pFoundFontFace->GetQuality() )
-            return false;
+            return;
 
         // keep the device font if its quality is good enough
         if( pNewFontFace->GetQuality() == pFoundFontFace->GetQuality() )
-            return false;
+            return;
 
         // replace existing font face with a better one
-        it->reset(pNewFontFace); // insert at sort position
-        return true;
+        *it = pNewFontFace; // insert at sort position
+        return;
     }
 
     maFontFaces.emplace(it, pNewFontFace); // insert at sort position
-    return true;
 }
 
 // get font attributes using the normalized font family name
@@ -265,7 +264,7 @@ void PhysicalFontFamily::UpdateCloneFontList(PhysicalFontCollection& rFontCollec
             pFamily = rFontCollection.FindOrCreateFontFamily(aFamilyName);
         }
         assert(pFamily);
-        PhysicalFontFace* pClonedFace = pFoundFontFace->Clone();
+        rtl::Reference<PhysicalFontFace> pClonedFace = pFoundFontFace->Clone();
 
 #if OSL_DEBUG_LEVEL > 0
         OUString aClonedFamilyName = GetEnglishSearchFontName( pClonedFace->GetFamilyName() );
@@ -273,8 +272,7 @@ void PhysicalFontFamily::UpdateCloneFontList(PhysicalFontCollection& rFontCollec
         assert( rFontCollection.FindOrCreateFontFamily( aClonedFamilyName ) == pFamily );
 #endif
 
-        if (! pFamily->AddFontFace( pClonedFace ) )
-            delete pClonedFace;
+        pFamily->AddFontFace( pClonedFace.get() );
     }
 }
 
diff --git a/vcl/source/font/fontinstance.cxx b/vcl/source/font/fontinstance.cxx
index 6837329fbfaf..fca20fd03ca3 100644
--- a/vcl/source/font/fontinstance.cxx
+++ b/vcl/source/font/fontinstance.cxx
@@ -52,7 +52,7 @@ LogicalFontInstance::LogicalFontInstance(const PhysicalFontFace& rFontFace, cons
     , m_aFontSelData(rFontSelData)
     , m_pHbFont(nullptr)
     , m_nAveWidthFactor(1.0f)
-    , m_pFontFace(&rFontFace)
+    , m_pFontFace(&const_cast<PhysicalFontFace&>(rFontFace))
 {
     const_cast<FontSelectPattern*>(&m_aFontSelData)->mpFontInstance = this;
 }
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index acec33b4ec5c..d9411779fb34 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -3470,8 +3470,8 @@ bool PDFWriterImpl::emitFonts()
     // emit builtin font for widget appearances / variable text
     for (auto & item : m_aBuiltinFontToObjectMap)
     {
-        PdfBuiltinFontFace aData(m_aBuiltinFonts[item.first]);
-        item.second = emitBuiltinFont( &aData, item.second );
+        rtl::Reference<PdfBuiltinFontFace> aData(new PdfBuiltinFontFace(m_aBuiltinFonts[item.first]));
+        item.second = emitBuiltinFont( aData.get(), item.second );
     }
     appendBuiltinFontsToDict( aFontDict );
     aFontDict.append( "\n>>\nendobj\n\n" );
diff --git a/vcl/source/gdi/pdfwriter_impl.hxx b/vcl/source/gdi/pdfwriter_impl.hxx
index 23da7f6052cc..0aa63514b2c5 100644
--- a/vcl/source/gdi/pdfwriter_impl.hxx
+++ b/vcl/source/gdi/pdfwriter_impl.hxx
@@ -1291,7 +1291,7 @@ public:
     explicit                            PdfBuiltinFontFace( const PDFWriterImpl::BuiltinFont& );
     const PDFWriterImpl::BuiltinFont&   GetBuiltinFont() const  { return mrBuiltin; }
 
-    virtual PhysicalFontFace*           Clone() const override { return new PdfBuiltinFontFace(*this); }
+    virtual rtl::Reference<PhysicalFontFace> Clone() const override { return new PdfBuiltinFontFace(*this); }
     virtual sal_IntPtr                  GetFontId() const override { return reinterpret_cast<sal_IntPtr>(&mrBuiltin); }
 };
 
diff --git a/vcl/unx/generic/print/genpspgraphics.cxx b/vcl/unx/generic/print/genpspgraphics.cxx
index eb094f64b733..66d121b712fe 100644
--- a/vcl/unx/generic/print/genpspgraphics.cxx
+++ b/vcl/unx/generic/print/genpspgraphics.cxx
@@ -521,7 +521,7 @@ private:
 public:
     explicit ImplPspFontData( const psp::FastPrintFontInfo& );
     virtual sal_IntPtr      GetFontId() const override { return mnFontId; }
-    virtual PhysicalFontFace*   Clone() const override { return new ImplPspFontData( *this ); }
+    virtual rtl::Reference<PhysicalFontFace> Clone() const override { return new ImplPspFontData( *this ); }
 };
 
 ImplPspFontData::ImplPspFontData(const psp::FastPrintFontInfo& rInfo)
@@ -887,9 +887,9 @@ void GenPspGraphics::AnnounceFonts( PhysicalFontCollection* pFontCollection, con
                 nQuality += 10;
     }
 
-    ImplPspFontData* pFD = new ImplPspFontData( aInfo );
+    rtl::Reference<ImplPspFontData> pFD(new ImplPspFontData( aInfo ));
     pFD->IncreaseQualityBy( nQuality );
-    pFontCollection->Add( pFD );
+    pFontCollection->Add( pFD.get() );
 }
 
 bool GenPspGraphics::blendBitmap( const SalTwoRect&, const SalBitmap& )
diff --git a/vcl/win/gdi/salfont.cxx b/vcl/win/gdi/salfont.cxx
index a5e240afc480..11957c7043dc 100644
--- a/vcl/win/gdi/salfont.cxx
+++ b/vcl/win/gdi/salfont.cxx
@@ -554,7 +554,7 @@ static FontAttributes WinFont2DevFontAttributes( const ENUMLOGFONTEXW& rEnumFont
 }
 
 
-static WinFontFace* ImplLogMetricToDevFontDataW( const ENUMLOGFONTEXW* pLogFont,
+static rtl::Reference<WinFontFace> ImplLogMetricToDevFontDataW( const ENUMLOGFONTEXW* pLogFont,
                                          const NEWTEXTMETRICW* pMetric,
                                          DWORD nFontType )
 {
@@ -562,7 +562,7 @@ static WinFontFace* ImplLogMetricToDevFontDataW( const ENUMLOGFONTEXW* pLogFont,
     if ( nFontType & RASTER_FONTTYPE )
         nHeight = pMetric->tmHeight - pMetric->tmInternalLeading;
 
-    WinFontFace* pData = new WinFontFace(
+    rtl::Reference<WinFontFace> pData = new WinFontFace(
         WinFont2DevFontAttributes(*pLogFont, *pMetric),
         nHeight,
         pLogFont->elfLogFont.lfCharSet,
@@ -653,7 +653,7 @@ sal_IntPtr WinFontFace::GetFontId() const
     return mnId;
 }
 
-PhysicalFontFace* WinFontFace::Clone() const
+rtl::Reference<PhysicalFontFace> WinFontFace::Clone() const
 {
     return new WinFontFace(*this);
 }
@@ -1108,10 +1108,10 @@ int CALLBACK SalEnumFontsProcExW( const LOGFONTW* lpelfe,
             return 1;
         }
 
-        WinFontFace* pData = ImplLogMetricToDevFontDataW( pLogFont, &(pMetric->ntmTm), nFontType );
+        rtl::Reference<WinFontFace> pData = ImplLogMetricToDevFontDataW( pLogFont, &(pMetric->ntmTm), nFontType );
         pData->SetFontId( sal_IntPtr( pInfo->mnFontCount++ ) );
 
-        pInfo->mpList->Add( pData );
+        pInfo->mpList->Add( pData.get() );
     }
 
     return 1;
@@ -1312,11 +1312,11 @@ bool WinSalGraphics::AddTempDevFont( PhysicalFontCollection* pFontCollection,
         aDFS.maMapName = aFontName;
     */
 
-    WinFontFace* pFontData = new WinFontFace( aDFA, 0,
+    rtl::Reference<WinFontFace> pFontData = new WinFontFace( aDFA, 0,
         sal::static_int_cast<BYTE>(DEFAULT_CHARSET),
         sal::static_int_cast<BYTE>(TMPF_VECTOR|TMPF_TRUETYPE) );
-    pFontData->SetFontId( reinterpret_cast<sal_IntPtr>(pFontData) );
-    pFontCollection->Add( pFontData );
+    pFontData->SetFontId( reinterpret_cast<sal_IntPtr>(pFontData.get()) );
+    pFontCollection->Add( pFontData.get() );
     return true;
 }
 
commit 0e97e05d57a55d0825b321c0d0402dc619f089bf
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Fri Dec 21 17:51:17 2018 +0100
Commit:     Aron Budea <aron.budea at collabora.com>
CommitDate: Thu Jan 24 20:05:30 2019 +0100

    Related: tdf#117761 oox smartart: backport fixes related to org chart
    
    This is a combination of 10 commits.
    
    This is the 1st commit:
    
    oox smartart, org chart: add initial hierChild/Root algorithms
    
    hierChild is supposed to align and position its child layout nodes in a
    linear path under the hierRoot layout node, so initially just use a
    simple vertical layout algorithm.
    
    (cherry picked from commit 3103f9f9461f6eabb61a70be73862ef4be98010e)
    
    This is the commit #2:
    
    oox smartart, org chart: handle multiple elements in hierChild
    
    In case one manager has multiple employees, then we laid out only the
    first one. Recognize non-assistant type as the node type (as a start) to
    get the correct number of employees (when there are no assistants), and
    also render employees on a horizontal (and not on a vertical) path.
    
    With this, the 1 manager and multiple employees case looks reasonable.
    
    (cherry picked from commit dcd378bf614c99d705312259a0a0a25b40d88e2b)
    
    This is the commit #3:
    
    oox smartart, org chart: fix font color when defined with quick styles
    
    createStyleMatrixContext() assumed that <dgm:style> contains
    <dgm:fontRef>, but it contains <a:fontRef> instead.
    
    This resulted in a 0 mnThemedIdx, which meant that since commit
    89206c472ecf18bfde6824cea8004921cd404365 (bnc#862510: PPTX import: Wrong
    text color inside shape, 2014-12-21) we ignored the theme color in
    oox::drawingml::Shape::createAndInsert().
    
    (cherry picked from commit 5dfd5755c709e91d2903bd7be4582f7832e89780)
    
    This is the commit #4:
    
    oox smartart, org chart: fix vertical order of assistant nodes
    
    It seems the manager -> assistant -> employees ordering is not part of
    the file format. The order is stored twice in the file: the hierRoot
    algorithm has 3 layout nodes as a children, and also the data model has
    an order of the presentation nodes: both describe that employees go
    before assistant nodes.
    
    In contrast to that, PowerPoint orders XML_asst nodes before XML_node
    ones, so teach the hierRoot algorithm about this.
    
    This requires tracking the data model node type for each in-diagram
    drawingML shape, so that layout can determine if a hierRoot algorithm
    children has an assistant node or not.
    
    (cherry picked from commit 22086e70c4f3bb41620ff81ecaf57fd2af6ccbce)
    
    This is the commit #5:
    
    oox smartart, org chart: handle multiple paragraphs on data node
    
    This problem was similar to the one fixed in
    cfa76f538a44d4396574ece59e8a3953c22c6eb7 (oox smartart, accent process:
    handle multiple runs from a data point, 2018-11-21), but this there we
    handled multiple runs and this handles multiple paragraphs.
    
    It seems some smartart types allow multiple paragraphs in a diagram
    node, others only allow multiple runs. Org chart is in the former
    category.
    
    (cherry picked from commit dfc97dd381ef516ca4a7e99b29f9da1033a380f4)
    
    This is the commit #6:
    
    oox smartart, org chart: fix height of manager nodes without employees
    
    Employees and/or assistants reduce the height of managers -- this effect
    is wanted even if there are no employees/assistants.
    
    (cherry picked from commit 8638cc1b737195df16a160b148d2cd2c68131174)
    
    This is the commit #7:
    
    oox smartart, org chart: improve width of non-manager nodes
    
    The default case is that all managers have assistants/employees, so
    nodes under a manager can only use the horizontal space under the
    manager to avoid overlapping.
    
    But in case the previous / next sibling of the manager have no child
    nodes (assistant/employee) then we can use that space to make the child
    nodes larger. This improves readability of the chart's text a lot and
    brings the layout closer to what PowerPoint does for the same input.
    
    Handle all this in the hierChild algorithm, i.e. the container for a
    list of assistants or a list of employees, which means "parent" in this
    context always refers to a manager node.
    
    (cherry picked from commit 3a655975e5ea43417885513d0752da3627dd25ed)
    
    This is the commit #8:
    
    oox smartart, org chart: implement support for hierBranch conditions
    
    The relevant part of the layout is the <dgm:layoutNode
    name="hierChild2"> element that has a <dgm:choose> with two branches:
    
    <dgm:if name="Name34" func="var" arg="hierBranch" op="equ" val="std">
    <dgm:if name="Name36" func="var" arg="hierBranch" op="equ" val="init">
    
    The connectors were missing as we took the first branch
    (ConditionAtom::getDecision() returned true if the arg was hierBranch),
    even hierBranch on the parent layout node was set to "init".
    
    With this, the correct number of connectors are created, previously all
    employee connectors were missing. Their size / position is still
    incorrect, though.
    
    (cherry picked from commit ae34f471030869dfc0da1784597cae6f9131f8c5)
    
    This is the commit #9:
    
    oox smartart, org chart: fix shape type of connectors
    
    PowerPoint renders these as bent connectors, not as arrow shapes.
    
    Also add a bit of vertical spacing between the nodes, otherwise the
    connectors have no way to be visible. Their position is still incorrect,
    though.
    
    (cherry picked from commit 1791e08e9f27453ac5563ef400c715e30c791133)
    
    This is the commit #10:
    
    oox smartart, org chart: fix position and size of connector shapes
    
    Finally the bugdoc rendering result is reasonable and even looks like a
    tree as it should.
    
    (cherry picked from commit 2bfb9117b287a371066a157267614b9bdb367d71)
    
    Change-Id: I4e7a729afd3d2c5af2e7f41903737bd56be406fa
    Reviewed-on: https://gerrit.libreoffice.org/66718
    Tested-by: Jenkins
    Reviewed-by: Aron Budea <aron.budea at collabora.com>

diff --git a/include/oox/drawingml/shape.hxx b/include/oox/drawingml/shape.hxx
index e04a58beb4a6..4a571213a090 100644
--- a/include/oox/drawingml/shape.hxx
+++ b/include/oox/drawingml/shape.hxx
@@ -222,6 +222,10 @@ public:
 
     sal_Int32 getZOrderOff() const { return mnZOrderOff; }
 
+    void setDataNodeType(sal_Int32 nDataNodeType) { mnDataNodeType = nDataNodeType; }
+
+    sal_Int32 getDataNodeType() const { return mnDataNodeType; }
+
 protected:
 
     css::uno::Reference< css::drawing::XShape > const &
@@ -341,6 +345,9 @@ private:
 
     /// Z-Order offset.
     sal_Int32 mnZOrderOff = 0;
+
+    /// Type of data node for an in-diagram shape.
+    sal_Int32 mnDataNodeType = 0;
 };
 
 } }
diff --git a/oox/source/drawingml/diagram/datamodelcontext.cxx b/oox/source/drawingml/diagram/datamodelcontext.cxx
index 326b4f933ed6..b98d0ee87ccf 100644
--- a/oox/source/drawingml/diagram/datamodelcontext.cxx
+++ b/oox/source/drawingml/diagram/datamodelcontext.cxx
@@ -111,7 +111,7 @@ public:
                 mrPoint.mnDirection = rAttribs.getToken( XML_val, XML_norm );
                 break;
             case DGM_TOKEN( hierBranch ):
-                mrPoint.mnHierarchyBranch = rAttribs.getToken( XML_val, XML_std );
+                mrPoint.moHierarchyBranch = rAttribs.getToken( XML_val );
                 break;
             case DGM_TOKEN( orgChart ):
                 mrPoint.mbOrgChartEnabled = rAttribs.getBool( XML_val, false );
diff --git a/oox/source/drawingml/diagram/diagram.hxx b/oox/source/drawingml/diagram/diagram.hxx
index 1a981a858c29..242ff09fa152 100644
--- a/oox/source/drawingml/diagram/diagram.hxx
+++ b/oox/source/drawingml/diagram/diagram.hxx
@@ -73,7 +73,6 @@ struct Point
         mnMaxChildren(-1),
         mnPreferredChildren(-1),
         mnDirection(XML_norm),
-        mnHierarchyBranch(XML_std),
         mnResizeHandles(XML_rel),
         mnCustomAngle(-1),
         mnPercentageNeighbourWidth(-1),
@@ -118,7 +117,7 @@ struct Point
     sal_Int32     mnMaxChildren;
     sal_Int32     mnPreferredChildren;
     sal_Int32     mnDirection;
-    sal_Int32     mnHierarchyBranch;
+    OptValue<sal_Int32> moHierarchyBranch;
     sal_Int32     mnResizeHandles;
     sal_Int32     mnCustomAngle;
     sal_Int32     mnPercentageNeighbourWidth;
diff --git a/oox/source/drawingml/diagram/diagramfragmenthandler.cxx b/oox/source/drawingml/diagram/diagramfragmenthandler.cxx
index 836faa309eca..616f8eb1392d 100644
--- a/oox/source/drawingml/diagram/diagramfragmenthandler.cxx
+++ b/oox/source/drawingml/diagram/diagramfragmenthandler.cxx
@@ -111,7 +111,7 @@ DiagramQStylesFragmentHandler::DiagramQStylesFragmentHandler( XmlFilterBase& rFi
     const AttributeList& rAttribs,
     ShapeStyleRef& o_rStyle )
 {
-    o_rStyle.mnThemedIdx = (nElement == DGM_TOKEN(fontRef)) ?
+    o_rStyle.mnThemedIdx = (nElement == A_TOKEN(fontRef)) ?
         rAttribs.getToken( XML_idx, XML_none ) : rAttribs.getInteger( XML_idx, 0 );
     return new ColorContext( *this, o_rStyle.maPhClr );
 }
diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
index 502470933e8f..513dc9926e82 100644
--- a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
+++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
@@ -29,6 +29,7 @@
 #include <drawingml/textparagraph.hxx>
 #include <drawingml/textrun.hxx>
 #include <drawingml/customshapeproperties.hxx>
+#include <tools/gen.hxx>
 
 using namespace ::com::sun::star;
 using namespace ::com::sun::star::uno;
@@ -72,32 +73,130 @@ sal_Int32 getConnectorType(const oox::drawingml::LayoutNode* pNode)
     if (!pNode)
         return nType;
 
+    // This is cheaper than visiting the whole sub-tree.
+    if (pNode->getName().startsWith("hierChild"))
+        return oox::XML_bentConnector3;
+
     for (const auto& pChild : pNode->getChildren())
     {
         auto pAlgAtom = dynamic_cast<oox::drawingml::AlgAtom*>(pChild.get());
         if (!pAlgAtom)
             continue;
 
-        if (pAlgAtom->getType() != oox::XML_lin)
-            continue;
-
-        sal_Int32 nDir = oox::XML_fromL;
-        if (pAlgAtom->getMap().count(oox::XML_linDir))
-            nDir = pAlgAtom->getMap().find(oox::XML_linDir)->second;
-
-        switch (nDir)
+        switch (pAlgAtom->getType())
         {
-            case oox::XML_fromL:
-                nType = oox::XML_rightArrow;
+            case oox::XML_lin:
+            {
+                sal_Int32 nDir = oox::XML_fromL;
+                if (pAlgAtom->getMap().count(oox::XML_linDir))
+                    nDir = pAlgAtom->getMap().find(oox::XML_linDir)->second;
+
+                switch (nDir)
+                {
+                    case oox::XML_fromL:
+                        nType = oox::XML_rightArrow;
+                        break;
+                    case oox::XML_fromR:
+                        nType = oox::XML_leftArrow;
+                        break;
+                }
                 break;
-            case oox::XML_fromR:
-                nType = oox::XML_leftArrow;
+            }
+            case oox::XML_hierChild:
+            {
+                // TODO <dgm:param type="connRout" val="..."/> should be able
+                // to customize this.
+                nType = oox::XML_bentConnector3;
                 break;
+            }
         }
     }
 
     return nType;
 }
+
+/**
+ * Determines if pShape is (or contains) a presentation of a data node of type
+ * nType.
+ */
+bool containsDataNodeType(const oox::drawingml::ShapePtr& pShape, sal_Int32 nType)
+{
+    if (pShape->getDataNodeType() == nType)
+        return true;
+
+    for (const auto& pChild : pShape->getChildren())
+    {
+        if (containsDataNodeType(pChild, nType))
+            return true;
+    }
+
+    return false;
+}
+
+/**
+ * Calculates the offset and scaling for pShape (laid out with the hierChild
+ * algorithm) based on the siblings of pParent.
+ */
+void calculateHierChildOffsetScale(const oox::drawingml::ShapePtr& pShape,
+                                   const oox::drawingml::LayoutNode* pParent, sal_Int32& rXOffset,
+                                   double& rWidthScale)
+{
+    if (!pParent)
+        return;
+
+    const std::vector<oox::drawingml::ShapePtr>& rParents = pParent->getNodeShapes();
+    for (size_t nParent = 0; nParent < rParents.size(); ++nParent)
+    {
+        const oox::drawingml::ShapePtr& pParentShape = rParents[nParent];
+        const std::vector<oox::drawingml::ShapePtr>& rChildren = pParentShape->getChildren();
+        auto it = std::find_if(
+            rChildren.begin(), rChildren.end(),
+            [pShape](const oox::drawingml::ShapePtr& pChild) { return pChild == pShape; });
+        if (it == rChildren.end())
+            // This is not our parent.
+            continue;
+
+        if (nParent > 0)
+        {
+            if (rParents[nParent - 1]->getChildren().size() == 1)
+            {
+                // Previous sibling of our parent has no children: can use that
+                // space, so shift to the left and scale up.
+                rWidthScale += 1.0;
+                rXOffset -= pShape->getSize().Width;
+            }
+        }
+        if (nParent < rParents.size() - 1)
+        {
+            if (rParents[nParent + 1]->getChildren().size() == 1)
+                // Next sibling of our parent has no children: can use that
+                // space, so scale up.
+                rWidthScale += 1.0;
+        }
+    }
+}
+
+/// Sets the position and size of a connector inside a hierChild algorithm.
+void setHierChildConnPosSize(const oox::drawingml::ShapePtr& pShape)
+{
+    // Connect to the top center of the child.
+    awt::Point aShapePoint = pShape->getPosition();
+    awt::Size aShapeSize = pShape->getSize();
+    tools::Rectangle aRectangle(Point(aShapePoint.X, aShapePoint.Y),
+                                Size(aShapeSize.Width, aShapeSize.Height));
+    Point aTo = aRectangle.TopCenter();
+
+    // Connect from the bottom center of the parent.
+    Point aFrom = aTo;
+    aFrom.setY(aFrom.getY() - aRectangle.getHeight() * 0.3);
+
+    tools::Rectangle aRect(aFrom, aTo);
+    aRect.Justify();
+    aShapePoint = awt::Point(aRect.Left(), aRect.Top());
+    aShapeSize = awt::Size(aRect.getWidth(), aRect.getHeight());
+    pShape->setPosition(aShapePoint);
+    pShape->setSize(aShapeSize);
+}
 }
 
 namespace oox { namespace drawingml {
@@ -284,8 +383,32 @@ bool ConditionAtom::getDecision() const
     case XML_var:
     {
         const dgm::Point* pPoint = getPresNode();
-        if (pPoint && maCond.mnArg == XML_dir)
+        if (!pPoint)
+            break;
+
+        if (maCond.mnArg == XML_dir)
             return compareResult(maCond.mnOp, pPoint->mnDirection, maCond.mnVal);
+        else if (maCond.mnArg == XML_hierBranch)
+        {
+            sal_Int32 nHierarchyBranch = pPoint->moHierarchyBranch.get(XML_std);
+            if (!pPoint->moHierarchyBranch.has())
+            {
+                // If <dgm:hierBranch> is missing in the current presentation
+                // point, ask the parent.
+                OUString aParent = navigate(mrLayoutNode, XML_presParOf, pPoint->msModelId,
+                                            /*bSourceToDestination*/ false);
+                DiagramData::PointNameMap& rPointNameMap
+                    = mrLayoutNode.getDiagram().getData()->getPointNameMap();
+                auto it = rPointNameMap.find(aParent);
+                if (it != rPointNameMap.end())
+                {
+                    const dgm::Point* pParent = it->second;
+                    if (pParent->moHierarchyBranch.has())
+                        nHierarchyBranch = pParent->moHierarchyBranch.get();
+                }
+            }
+            return compareResult(maCond.mnOp, nHierarchyBranch, maCond.mnVal);
+        }
         break;
     }
 
@@ -445,6 +568,12 @@ void AlgAtom::layoutShape( const ShapePtr& rShape,
 
                 rShape->setSubType(nType);
                 rShape->getCustomShapeProperties()->setShapePresetType(nType);
+
+                if (nType == XML_bentConnector3)
+                {
+                    setHierChildConnPosSize(rShape);
+                    break;
+                }
             }
 
             // Parse constraints to adjust the size.
@@ -522,7 +651,81 @@ void AlgAtom::layoutShape( const ShapePtr& rShape,
 
         case XML_hierChild:
         case XML_hierRoot:
+        {
+            // hierRoot is the manager -> employees vertical linear path,
+            // hierChild is the first employee -> last employee horizontal
+            // linear path.
+            const sal_Int32 nDir = mnType == XML_hierRoot ? XML_fromT : XML_fromL;
+            if (rShape->getChildren().empty() || rShape->getSize().Width == 0
+                || rShape->getSize().Height == 0)
+                break;
+
+            sal_Int32 nCount = rShape->getChildren().size();
+
+            if (mnType == XML_hierChild)
+            {
+                // Connectors should not influence the size of non-connect
+                // shapes.
+                nCount = std::count_if(
+                    rShape->getChildren().begin(), rShape->getChildren().end(),
+                    [](const ShapePtr& pShape) { return pShape->getSubType() != XML_conn; });
+            }
+
+            // A manager node's height should be independent from if it has
+            // assistants and employees, compensate for that.
+            bool bTop = mnType == XML_hierRoot && rShape->getInternalName() == "hierRoot1";
+
+            // Add spacing, so connectors have a chance to be visible.
+            double fSpace = (nCount > 1 || bTop) ? 0.3 : 0;
+
+            double fHeightScale = 1.0;
+            if (mnType == XML_hierRoot && nCount < 3 && bTop)
+                fHeightScale = fHeightScale * nCount / 3;
+
+            if (mnType == XML_hierRoot && nCount == 3)
+            {
+                // Order assistant nodes above employee nodes.
+                std::vector<ShapePtr>& rChildren = rShape->getChildren();
+                if (!containsDataNodeType(rChildren[1], XML_asst)
+                    && containsDataNodeType(rChildren[2], XML_asst))
+                    std::swap(rChildren[1], rChildren[2]);
+            }
+
+            sal_Int32 nXOffset = 0;
+            double fWidthScale = 1.0;
+            if (mnType == XML_hierChild)
+                calculateHierChildOffsetScale(rShape, pParent, nXOffset, fWidthScale);
+
+            awt::Size aChildSize = rShape->getSize();
+            if (nDir == XML_fromT)
+            {
+                aChildSize.Height /= (nCount + nCount * fSpace);
+            }
+            else
+                aChildSize.Width /= nCount;
+            aChildSize.Height *= fHeightScale;
+            aChildSize.Width *= fWidthScale;
+
+            awt::Point aChildPos(nXOffset, 0);
+            for (auto& pChild : rShape->getChildren())
+            {
+                pChild->setPosition(aChildPos);
+                pChild->setSize(aChildSize);
+                pChild->setChildSize(aChildSize);
+
+                if (mnType == XML_hierChild && pChild->getSubType() == XML_conn)
+                    // Connectors should not influence the position of
+                    // non-connect shapes.
+                    continue;
+
+                if (nDir == XML_fromT)
+                    aChildPos.Y += aChildSize.Height + aChildSize.Height * fSpace;
+                else
+                    aChildPos.X += aChildSize.Width;
+            }
+
             break;
+        }
 
         case XML_lin:
         {
@@ -896,6 +1099,7 @@ bool LayoutNode::setupShape( const ShapePtr& rShape, const dgm::Point* pPresNode
         while( aVecIter != aVecEnd )
         {
             DiagramData::PointNameMap& rMap = mrDgm.getData()->getPointNameMap();
+            // pPresNode is the presentation node of the aDataNode2 data node.
             DiagramData::PointNameMap::const_iterator aDataNode2 = rMap.find(aVecIter->first);
             if (aDataNode2 == rMap.end())
             {
@@ -904,6 +1108,8 @@ bool LayoutNode::setupShape( const ShapePtr& rShape, const dgm::Point* pPresNode
                 continue;
             }
 
+            rShape->setDataNodeType(aDataNode2->second->mnType);
+
             if( aVecIter->second == 0 )
             {
                 // grab shape attr from topmost element(s)
@@ -941,16 +1147,19 @@ bool LayoutNode::setupShape( const ShapePtr& rShape, const dgm::Point* pPresNode
                     rShape->setTextBody(pTextBody);
                 }
 
-                TextParagraph& rPara=pTextBody->addParagraph();
-                if( aVecIter->second != -1 )
-                    rPara.getProperties().setLevel(aVecIter->second);
-
-                std::shared_ptr<TextParagraph> pSourceParagraph
-                    = aDataNode2->second->mpShape->getTextBody()->getParagraphs().front();
-                for (const auto& pRun : pSourceParagraph->getRuns())
-                    rPara.addRun(pRun);
-                rPara.getProperties().apply(
-                    aDataNode2->second->mpShape->getTextBody()->getParagraphs().front()->getProperties());
+                const TextParagraphVector& rSourceParagraphs
+                    = aDataNode2->second->mpShape->getTextBody()->getParagraphs();
+                for (const auto& pSourceParagraph : rSourceParagraphs)
+                {
+                    TextParagraph& rPara = pTextBody->addParagraph();
+                    if (aVecIter->second != -1)
+                        rPara.getProperties().setLevel(aVecIter->second);
+
+                    for (const auto& pRun : pSourceParagraph->getRuns())
+                        rPara.addRun(pRun);
+                    const TextBodyPtr& rBody = aDataNode2->second->mpShape->getTextBody();
+                    rPara.getProperties().apply(rBody->getParagraphs().front()->getProperties());
+                }
             }
 
             ++aVecIter;
diff --git a/oox/source/drawingml/diagram/layoutatomvisitors.cxx b/oox/source/drawingml/diagram/layoutatomvisitors.cxx
index 49a664c1e821..e2d6c4681b5c 100644
--- a/oox/source/drawingml/diagram/layoutatomvisitors.cxx
+++ b/oox/source/drawingml/diagram/layoutatomvisitors.cxx
@@ -57,7 +57,8 @@ void ShapeCreationVisitor::visit(ForEachAtom& rAtom)
     const std::vector<LayoutAtomPtr>& rChildren=rAtom.getChildren();
 
     sal_Int32 nChildren=1;
-    if( rAtom.iterator().mnPtType == XML_node )
+    // Approximate the non-assistant type with the node type.
+    if (rAtom.iterator().mnPtType == XML_node || rAtom.iterator().mnPtType == XML_nonAsst)
     {
         // count child data nodes - check all child Atoms for "name"
         // attribute that is contained in diagram's
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx
index 16bc511743b1..55d154642960 100644
--- a/oox/source/drawingml/shape.cxx
+++ b/oox/source/drawingml/shape.cxx
@@ -177,6 +177,7 @@ Shape::Shape( const ShapePtr& pSourceShape )
 , maDiagramDoms( pSourceShape->maDiagramDoms )
 , mnZOrder(pSourceShape->mnZOrder)
 , mnZOrderOff(pSourceShape->mnZOrderOff)
+, mnDataNodeType(pSourceShape->mnDataNodeType)
 {}
 
 Shape::~Shape()
diff --git a/sd/qa/unit/data/pptx/smartart-org-chart.pptx b/sd/qa/unit/data/pptx/smartart-org-chart.pptx
new file mode 100644
index 000000000000..08c9a4fc916d
Binary files /dev/null and b/sd/qa/unit/data/pptx/smartart-org-chart.pptx differ
diff --git a/sd/qa/unit/import-tests-smartart.cxx b/sd/qa/unit/import-tests-smartart.cxx
index b83de20890b1..9de4061a072b 100644
--- a/sd/qa/unit/import-tests-smartart.cxx
+++ b/sd/qa/unit/import-tests-smartart.cxx
@@ -18,6 +18,23 @@
 
 using namespace ::com::sun::star;
 
+namespace
+{
+/// Gets one child of xShape, which one is specified by nIndex.
+uno::Reference<drawing::XShape> getChildShape(const uno::Reference<drawing::XShape>& xShape, sal_Int32 nIndex)
+{
+    uno::Reference<container::XIndexAccess> xGroup(xShape, uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xGroup.is());
+
+    CPPUNIT_ASSERT(xGroup->getCount() > nIndex);
+
+    uno::Reference<drawing::XShape> xRet(xGroup->getByIndex(nIndex), uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xRet.is());
+
+    return xRet;
+}
+}
+
 class SdImportTestSmartArt : public SdModelTestBase
 {
 public:
@@ -33,6 +50,7 @@ public:
     void testTableList();
     void testAccentProcess();
     void testContinuousBlockProcess();
+    void testOrgChart();
 
     CPPUNIT_TEST_SUITE(SdImportTestSmartArt);
 
@@ -48,6 +66,7 @@ public:
     CPPUNIT_TEST(testTableList);
     CPPUNIT_TEST(testAccentProcess);
     CPPUNIT_TEST(testContinuousBlockProcess);
+    CPPUNIT_TEST(testOrgChart);
 
     CPPUNIT_TEST_SUITE_END();
 };
@@ -402,6 +421,132 @@ void SdImportTestSmartArt::testContinuousBlockProcess()
     xDocShRef->DoClose();
 }
 
+void SdImportTestSmartArt::testOrgChart()
+{
+    // Simple org chart with 1 manager and 1 employee only.
+    sd::DrawDocShellRef xDocShRef = loadURL(
+        m_directories.getURLFromSrc("/sd/qa/unit/data/pptx/smartart-org-chart.pptx"),
+        PPTX);
+    uno::Reference<drawing::XShape> xGroup(getShapeFromPage(0, 0, xDocShRef), uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xGroup.is());
+
+    uno::Reference<text::XText> xManager(
+        getChildShape(getChildShape(getChildShape(xGroup, 0), 0), 0), uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xManager.is());
+    // Without the accompanying fix in place, this test would have failed: this
+    // was just "Manager", and the second paragraph was lost.
+    OUString aExpected("Manager\nSecond para");
+    CPPUNIT_ASSERT_EQUAL(aExpected, xManager->getString());
+
+    uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xManager, uno::UNO_QUERY);
+    uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
+    uno::Reference<text::XTextRange> xPara(xParaEnum->nextElement(), uno::UNO_QUERY);
+    uno::Reference<container::XEnumerationAccess> xRunEnumAccess(xPara, uno::UNO_QUERY);
+    uno::Reference<container::XEnumeration> xRunEnum = xRunEnumAccess->createEnumeration();
+    uno::Reference<beans::XPropertySet> xRun(xRunEnum->nextElement(), uno::UNO_QUERY);
+    sal_Int32 nActualColor = xRun->getPropertyValue("CharColor").get<sal_Int32>();
+    // Without the accompanying fix in place, this test would have failed: the
+    // "Manager" font color was black, not white.
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0xffffff), nActualColor);
+
+    uno::Reference<drawing::XShape> xManagerShape(xManager, uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xManagerShape.is());
+
+    awt::Point aManagerPos = xManagerShape->getPosition();
+    awt::Size aManagerSize = xManagerShape->getSize();
+
+    // Make sure that the manager has 2 employees.
+    uno::Reference<drawing::XShapes> xEmployees(getChildShape(getChildShape(xGroup, 0), 2),
+                                                uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xEmployees.is());
+    // 4 children: connector, 1st employee, connector, 2nd employee.
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(4), xEmployees->getCount());
+
+    uno::Reference<text::XText> xEmployee(
+        getChildShape(
+            getChildShape(getChildShape(getChildShape(getChildShape(xGroup, 0), 2), 1), 0), 0),
+        uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xEmployee.is());
+    CPPUNIT_ASSERT_EQUAL(OUString("Employee"), xEmployee->getString());
+
+    uno::Reference<drawing::XShape> xEmployeeShape(xEmployee, uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xEmployeeShape.is());
+
+    awt::Point aEmployeePos = xEmployeeShape->getPosition();
+    awt::Size aEmployeeSize = xEmployeeShape->getSize();
+
+    CPPUNIT_ASSERT_EQUAL(aManagerPos.X, aEmployeePos.X);
+
+    // Without the accompanying fix in place, this test would have failed: the
+    // two shapes were overlapping, i.e. "manager" was not above "employee".
+    CPPUNIT_ASSERT_GREATER(aManagerPos.Y, aEmployeePos.Y);
+
+    // Make sure that the second employee is on the right of the first one.
+    // Without the accompanying fix in place, this test would have failed, as
+    // the second employee was below the first one.
+    uno::Reference<text::XText> xEmployee2(
+        getChildShape(
+            getChildShape(getChildShape(getChildShape(getChildShape(xGroup, 0), 2), 3), 0), 0),
+        uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xEmployee2.is());
+    CPPUNIT_ASSERT_EQUAL(OUString("Employee2"), xEmployee2->getString());
+
+    uno::Reference<drawing::XShape> xEmployee2Shape(xEmployee2, uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xEmployee2Shape.is());
+
+    awt::Point aEmployee2Pos = xEmployee2Shape->getPosition();
+    awt::Size aEmployee2Size = xEmployee2Shape->getSize();
+    CPPUNIT_ASSERT_GREATER(aEmployeePos.X, aEmployee2Pos.X);
+
+    // Make sure that assistant is above employees.
+    uno::Reference<text::XText> xAssistant(
+        getChildShape(
+            getChildShape(getChildShape(getChildShape(getChildShape(xGroup, 0), 1), 1), 0), 0),
+        uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(OUString("Assistant"), xAssistant->getString());
+
+    uno::Reference<drawing::XShape> xAssistantShape(xAssistant, uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xAssistantShape.is());
+
+    awt::Point aAssistantPos = xAssistantShape->getPosition();
+    // Without the accompanying fix in place, this test would have failed: the
+    // assistant shape was below the employee shape.
+    CPPUNIT_ASSERT_GREATER(aAssistantPos.Y, aEmployeePos.Y);
+
+    // Make sure the connector of the assistant is above the shape.
+    uno::Reference<drawing::XShape> xAssistantConnector(
+        getChildShape(getChildShape(getChildShape(xGroup, 0), 1), 0), uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xAssistantConnector.is());
+    awt::Point aAssistantConnectorPos = xAssistantConnector->getPosition();
+    // This failed, the vertical positions of the connector and the shape of
+    // the assistant were the same.
+    CPPUNIT_ASSERT_LESS(aAssistantPos.Y, aAssistantConnectorPos.Y);
+
+    // Make sure the height of xManager and xManager2 is the same.
+    uno::Reference<text::XText> xManager2(
+        getChildShape(getChildShape(getChildShape(xGroup, 1), 0), 0), uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xManager2.is());
+    CPPUNIT_ASSERT_EQUAL(OUString("Manager2"), xManager2->getString());
+
+    uno::Reference<drawing::XShape> xManager2Shape(xManager2, uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xManager2Shape.is());
+
+    awt::Size aManager2Size = xManager2Shape->getSize();
+    // Without the accompanying fix in place, this test would have failed:
+    // xManager2's height was 3 times larger than xManager's height.
+    CPPUNIT_ASSERT_EQUAL(aManagerSize.Height, aManager2Size.Height);
+
+    // Make sure the employee nodes use the free space on the right, since
+    // manager2 has no assistants / employees.
+    CPPUNIT_ASSERT_GREATER(aManagerSize.Width, aEmployeeSize.Width + aEmployee2Size.Width);
+
+    // Without the accompanying fix in place, this test would have failed: an
+    // employee was exactly the third of the total height, without any spacing.
+    CPPUNIT_ASSERT_LESS(xGroup->getSize().Height / 3, aEmployeeSize.Height);
+
+    xDocShRef->DoClose();
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SdImportTestSmartArt);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
commit 05a5037f489971676737808c37ad1cfb9dcd53d9
Author:     Serge Krot <Serge.Krot at cib.de>
AuthorDate: Fri Jan 18 12:51:33 2019 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Thu Jan 24 09:42:46 2019 +0100

    tdf#121561 sw DOCX: output toc-end inside last toc paragraph
    
    During export of the TOC into DOCX all TOC field parts
    should be placed inside one STD frame: field start-begin,
    field-separate and field-end mark.
    
    Updated unit test.
    
    Change-Id: I10e37a48160e1dc4f0074c4e2e7621a59f79c2ee
    Reviewed-on: https://gerrit.libreoffice.org/66587
    Tested-by: Jenkins
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    (cherry picked from commit fd5599b9d23a2d9b13af6dd88bd2d38f438f7e00)
    Reviewed-on: https://gerrit.libreoffice.org/66810


... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list