Rebased ref, commits from common ancestor: commit 0ceb2321848d9adf6ed1839a1661ca89ddc46b53 Author: Samuel Mehrbrodt <samuel.mehrbr...@cib.de> AuthorDate: Wed Feb 13 08:59:01 2019 +0100 Commit: Samuel Mehrbrodt <samuel.mehrbr...@cib.de> CommitDate: Wed Mar 6 12:43:33 2019 +0100
tdf#123378 Prevent modifying doc when printing Just remove this update fields call, they are updated anyway. Reviewed-on: https://gerrit.libreoffice.org/67754 Tested-by: Jenkins Reviewed-by: Samuel Mehrbrodt <samuel.mehrbr...@cib.de> (cherry picked from commit ac1b2c9e1ab2f84de3a8856772e00302d237e82f) Change-Id: Iaed1b6e7e1be8138ecb48e7557cc09ec0eeebda3 diff --git a/sw/qa/uitest/writer_tests5/tdf123378.py b/sw/qa/uitest/writer_tests5/tdf123378.py new file mode 100644 index 000000000000..6c78e0ecf699 --- /dev/null +++ b/sw/qa/uitest/writer_tests5/tdf123378.py @@ -0,0 +1,25 @@ +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*- +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +from uitest.framework import UITestCase + +#Bug 123378 - Printing always sets "document modified" status + +class tdf123378(UITestCase): + def test_tdf123378_print_sets_modified(self): + self.ui_test.create_doc_in_start_center("writer") + document = self.ui_test.get_component() + xWriterDoc = self.xUITest.getTopFocusWindow() + + self.xUITest.executeCommand(".uno:Print") + xDialog = self.xUITest.getTopFocusWindow() + xOK = xDialog.getChild("cancel") + self.ui_test.close_dialog_through_button(xOK) + + self.assertEqual(document.isModified(), False) + + self.ui_test.close_doc() +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx index 805bbf81b108..b5d224209275 100644 --- a/sw/source/uibase/uno/unotxdoc.cxx +++ b/sw/source/uibase/uno/unotxdoc.cxx @@ -2630,8 +2630,6 @@ sal_Int32 SAL_CALL SwXTextDocument::getRendererCount( bStateChanged = true; } - // #122919# Force field update before PDF export - pViewShell->SwViewShell::UpdateFields(true); if( bStateChanged ) pRenderDocShell->EnableSetModified(); commit fdcedaeac252b188e2100b4d69aaef732627db85 Author: Samuel Mehrbrodt <samuel.mehrbr...@cib.de> AuthorDate: Thu Feb 7 11:17:21 2019 +0100 Commit: Samuel Mehrbrodt <samuel.mehrbr...@cib.de> CommitDate: Wed Mar 6 12:43:33 2019 +0100 tdf#122607 Fix layout invalidation in headless mode Layout was not invalidated correctly since the visible area is 0 in headless mode. So just reformat the whole doc when doing the pdf conversion headless. An attempt to fix this was already made with commit 1ecca673b40fedc53db125e332b087d1c120a254 but that didn't cover all cases. Reviewed-on: https://gerrit.libreoffice.org/67417 Tested-by: Jenkins Reviewed-by: Samuel Mehrbrodt <samuel.mehrbr...@cib.de> (cherry picked from commit e41b09d0126ecb28cff277c9b4b40eae7cc7c3f4) Change-Id: I3f620b2f2db2c4a6e5bf279b33e5c93697e4e2d4 diff --git a/sw/inc/viewsh.hxx b/sw/inc/viewsh.hxx index 832f4f9dd878..da9146bf12ea 100644 --- a/sw/inc/viewsh.hxx +++ b/sw/inc/viewsh.hxx @@ -152,7 +152,7 @@ class SW_DLLPUBLIC SwViewShell : public sw::Ring<SwViewShell> inline void ResetInvalidRect(); - SAL_DLLPRIVATE void Reformat(); // Invalidates complete Layout (ApplyViewOption). + SAL_DLLPRIVATE void PaintDesktop(vcl::RenderContext& rRenderContext, const SwRect&); // Collect values for painting of desktop // and calling. @@ -216,6 +216,9 @@ public: void InvalidateWindows( const SwRect &rRect ); + /// Invalidates complete Layout (ApplyViewOption). + void Reformat(); + // #i72754# set of Pre/PostPaints with lock counter and initial target OutDev protected: std::stack<vcl::Region> mPrePostPaintRegions; // acts also as a lock counter (empty == not locked) diff --git a/sw/qa/extras/layout/data/tdf122607.odt b/sw/qa/extras/layout/data/tdf122607.odt new file mode 100644 index 000000000000..123e04702ef8 Binary files /dev/null and b/sw/qa/extras/layout/data/tdf122607.odt differ diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx index 7d6eeccd18b8..b1ef14cbbad8 100755 --- a/sw/qa/extras/layout/layout.cxx +++ b/sw/qa/extras/layout/layout.cxx @@ -32,6 +32,7 @@ public: void testTdf117188(); void testTdf119875(); void testTdf116989(); + void testTdf122607(); CPPUNIT_TEST_SUITE(SwLayoutWriter); CPPUNIT_TEST(testTdf116830); @@ -49,6 +50,7 @@ public: CPPUNIT_TEST(testTdf117188); CPPUNIT_TEST(testTdf119875); CPPUNIT_TEST(testTdf116989); + CPPUNIT_TEST(testTdf122607); CPPUNIT_TEST_SUITE_END(); private: @@ -304,6 +306,20 @@ void SwLayoutWriter::testTdf116989() } } +void SwLayoutWriter::testTdf122607() +{ + createDoc("tdf122607.odt"); + xmlDocPtr pXmlDoc = parseLayoutDump(); + assertXPath(pXmlDoc, + "/root/page[1]/anchored/fly/txt[1]/anchored/fly/tab/row[2]/cell/txt[7]/anchored/" + "fly/txt/Text[1]", + "nHeight", "253"); + assertXPath(pXmlDoc, + "/root/page[1]/anchored/fly/txt[1]/anchored/fly/tab/row[2]/cell/txt[7]/anchored/" + "fly/txt/Text[1]", + "nWidth", "428"); +} + CPPUNIT_TEST_SUITE_REGISTRATION(SwLayoutWriter); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx index f33f5f033d9f..805bbf81b108 100644 --- a/sw/source/uibase/uno/unotxdoc.cxx +++ b/sw/source/uibase/uno/unotxdoc.cxx @@ -2635,6 +2635,9 @@ sal_Int32 SAL_CALL SwXTextDocument::getRendererCount( if( bStateChanged ) pRenderDocShell->EnableSetModified(); + // tdf#122607 Re-layout the doc. Calling CalcLayout here is not enough, as it depends + // on the currently visible area which is 0 when doing headless conversion. + pViewShell->Reformat(); pViewShell->CalcPagesForPrint( pViewShell->GetPageCount() ); pViewShell->SetPDFExportOption( false ); commit 922a919326abb0a33911d49fbccad2476998405a Author: Samuel Mehrbrodt <samuel.mehrbr...@cib.de> AuthorDate: Thu Jan 24 15:52:47 2019 +0100 Commit: Samuel Mehrbrodt <samuel.mehrbr...@cib.de> CommitDate: Wed Mar 6 12:43:33 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.mehrbr...@cib.de> (cherry picked from commit 1ecca673b40fedc53db125e332b087d1c120a254) Reviewed-on: https://gerrit.libreoffice.org/66897 Tested-by: Samuel Mehrbrodt <samuel.mehrbr...@cib.de> diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx index 1db55d3c5831..f33f5f033d9f 100644 --- a/sw/source/uibase/uno/unotxdoc.cxx +++ b/sw/source/uibase/uno/unotxdoc.cxx @@ -2635,10 +2635,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() ); pViewShell->SetPDFExportOption( false ); commit 966bfb55f5b7ebc4cfdec97dc22d339d06cf7683 Author: Noel Grandin <noel.gran...@collabora.co.uk> AuthorDate: Tue Jun 5 14:16:23 2018 +0200 Commit: Samuel Mehrbrodt <samuel.mehrbr...@cib.de> CommitDate: Wed Mar 6 12:43:33 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 <c...@libreoffice.org> Reviewed-by: Noel Grandin <noel.gran...@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 7dbb2995d9d3a711d72d6d0aed72ff48e115f794 Author: Noel Grandin <noel.gran...@collabora.co.uk> AuthorDate: Tue Jun 5 14:48:51 2018 +0200 Commit: Samuel Mehrbrodt <samuel.mehrbr...@cib.de> CommitDate: Wed Mar 6 12:43:33 2019 +0100 manage PhysicalFontFace by rtl::Reference Change-Id: I8f66b5afb066fe83abb83c56ebde6f21197f894b Reviewed-on: https://gerrit.libreoffice.org/55333 Tested-by: Jenkins <c...@libreoffice.org> Reviewed-by: Noel Grandin <noel.gran...@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 a1ec611ea740e56949cf9f80179a90591d4f9dfc Author: Samuel Mehrbrodt <samuel.mehrbr...@cib.de> AuthorDate: Tue Mar 5 13:47:10 2019 +0100 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Wed Mar 6 12:32:12 2019 +0100 tdf#123829 Respect CollapseEmptyCellPara setting when reading odf docs Commit 56b2cf0c10d9caa01ebae1d80465e342d046a85c introduced a "feature" which would hide an empty line after a table and only make it visible when the cursor is in it. So when loading an ODF doc, only enable this feature for which have the CollapseEmptyCellPara setting set. Change-Id: Ib4dfbbe8d45eb57547c51c7eee2f81331fc5300e Reviewed-on: https://gerrit.libreoffice.org/68742 Tested-by: Jenkins Reviewed-by: Samuel Mehrbrodt <samuel.mehrbr...@cib.de> (cherry picked from commit 0d2da0acfaa610c690bce552c0ed5df62d4c35cb) Reviewed-on: https://gerrit.libreoffice.org/68790 Reviewed-by: Michael Stahl <michael.st...@cib.de> diff --git a/sw/qa/extras/odfimport/data/tdf123829.odt b/sw/qa/extras/odfimport/data/tdf123829.odt new file mode 100644 index 000000000000..3219b4156182 Binary files /dev/null and b/sw/qa/extras/odfimport/data/tdf123829.odt differ diff --git a/sw/qa/extras/odfimport/odfimport.cxx b/sw/qa/extras/odfimport/odfimport.cxx index 88f3564e3be3..9ee4f206f5a5 100644 --- a/sw/qa/extras/odfimport/odfimport.cxx +++ b/sw/qa/extras/odfimport/odfimport.cxx @@ -22,6 +22,7 @@ #include <com/sun/star/text/PageNumberType.hpp> #include <com/sun/star/text/VertOrientation.hpp> +#include <IDocumentSettingAccess.hxx> #include <wrtsh.hxx> #include <ndtxt.hxx> #include <swdtflvr.hxx> @@ -915,5 +916,15 @@ DECLARE_ODFIMPORT_TEST(testTdf120677, "tdf120677.fodt") // The document used to hang the layout, consuming memory until OOM } +DECLARE_ODFIMPORT_TEST(testTdf123829, "tdf123829.odt") +{ + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + CPPUNIT_ASSERT(pTextDoc); + SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "Compatibility: collapse cell paras should not be set", false, + pDoc->getIDocumentSettingAccess().get(DocumentSettingId::COLLAPSE_EMPTY_CELL_PARA)); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/xml/xmlimp.cxx b/sw/source/filter/xml/xmlimp.cxx index e88f90e2c621..d838a8adb8a6 100644 --- a/sw/source/filter/xml/xmlimp.cxx +++ b/sw/source/filter/xml/xmlimp.cxx @@ -1393,6 +1393,7 @@ void SwXMLImport::SetConfigurationSettings(const Sequence < PropertyValue > & aC bool bPropLineSpacingShrinksFirstLine = false; bool bSubtractFlysAnchoredAtFlys = false; bool bDisableOffPagePositioning = false; + bool bCollapseEmptyCellPara = false; const PropertyValue* currentDatabaseDataSource = nullptr; const PropertyValue* currentDatabaseCommand = nullptr; @@ -1487,6 +1488,8 @@ void SwXMLImport::SetConfigurationSettings(const Sequence < PropertyValue > & aC bSubtractFlysAnchoredAtFlys = true; else if (pValues->Name == "DisableOffPagePositioning") bDisableOffPagePositioning = true; + else if (pValues->Name == "CollapseEmptyCellPara") + bCollapseEmptyCellPara = true; } catch( Exception& ) { @@ -1650,6 +1653,9 @@ void SwXMLImport::SetConfigurationSettings(const Sequence < PropertyValue > & aC if ( bDisableOffPagePositioning ) xProps->setPropertyValue("DisableOffPagePositioning", makeAny(true)); + if (!bCollapseEmptyCellPara) + xProps->setPropertyValue("CollapseEmptyCellPara", makeAny(false)); + SwDoc *pDoc = getDoc(); SfxPrinter *pPrinter = pDoc->getIDocumentDeviceAccess().getPrinter( false ); if( pPrinter ) commit cd376726cc8dad65d246493fee233c8018123bf1 Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Tue Mar 5 13:25:16 2019 +0000 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Wed Mar 6 11:31:36 2019 +0100 Resolves: tdf#123815 null terminator included in string regression from... commit 18d636063fd7be165e7888af49372a6e2b851776 Author: Caolán McNamara <caol...@redhat.com> Date: Mon Jun 19 09:46:31 2017 +0100 ofz: use OString instead of bare char* this is no use to the reporter though, as the document format is 10 and 11 is the oldest the filter will open Change-Id: I4cdfe92e37f047493a6eab95f0e8e9f5dced1a35 Reviewed-on: https://gerrit.libreoffice.org/68747 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@cib.de> diff --git a/lotuswordpro/source/filter/tocread.cxx b/lotuswordpro/source/filter/tocread.cxx index e6af6f42e8f1..b64eec71676f 100644 --- a/lotuswordpro/source/filter/tocread.cxx +++ b/lotuswordpro/source/filter/tocread.cxx @@ -296,7 +296,9 @@ CBenTOCReader::ReadTOC() return Err; } - OString sName(sBuffer, Length); + OString sName; + if (Length) + sName = OString(sBuffer, Length - 1); CUtListElmt * pPrevNamedObjectListElmt; if (FindNamedObject(&cpContainer->GetNamedObjects(), commit a02a160c8d5a70b30128c0880ba8853d0dbe0e7c Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Fri Feb 22 17:12:04 2019 +0100 Commit: Andras Timar <andras.ti...@collabora.com> CommitDate: Mon Mar 4 19:11:51 2019 +0100 Related: tdf#117761 oox smartart: backport fixes related to picture strip This is a combination of 7 commits. This is the 1st commit: oox smartart, picture strip: handle bitmap fill of pres nodes There were two problems here: 1) We did not import bitmap fill from presentation nodes. 2) Presentation nodes contained properties with reference semantics, so if you set a bitmap fill for a first and a second shape, then at the end both shapes contained the second bitmap. With this, both bitmaps are imported exactly once. (cherry picked from commit 333e9ea15bb57cf1c87ac2ea150de1e3fd79cfcb) This is the commit #2: oox smartart, picture strip: fetch # of children only once in snake algo No functional changes intended. (cherry picked from commit 90372d52fdcc378473b89f4e6f2de0e206c110ef) This is the commit #3: oox smartart, picture strip: expose aspect ratio of children for snake algo The aspect ratio request of the Shape is not yet used in AlgAtom::layoutShape(), though. The heavy-lifting is needed, because the number of cols/rows in the snake algorithm depends on the aspect ratio request from the child algorithm, so need to transfer the aspect ratio from child algorithm -> layout node -> shape -> parent algorithm. Still no functional changes intended. (cherry picked from commit a1e10b7968fbf4dba962349be8a6dfb0cb1d3176) This is the commit #4: oox smartart, picture strip: fix too many columns with aspect ratio request The bugdoc has 3 items in the picture strip and PowerPoint laid this out as a single column with 3 rows (as a snake algorithm). We used to put the first two items to the first row and the third item to the second row. Improve out layout by taking into account what aspect ratio the child algorithms request: this way it's obvious that we should use a single column in case we have a large enough aspect ratio and few enough items. (PowerPoint also uses multiple columns without the aspect ratio request.) (cherry picked from commit 159e33ec661b2ce038b2642b2f30600ce7901d1b) This is the commit #5: oox smartart, picture strip: fix lack of spacing around the picture list The snake algorithm in PowerPoint seem to interpret spacing as follows: if you have N elements, then there should be the requested amount of spacing between the elements, and also double amount of spacing around the actual list of elements. With this, the SmartArt and the title shape in the bugdoc no longer overlaps. (cherry picked from commit 0a29c928afa74123bca05dc089c751603d368467) This is the commit #6: oox smartart, picture strip: fix lack of margin in text shapes Shape text has two kind of spacing inside the shape's bounding box: the shape-level margin and the paragraph-level one. Only the second was handled in the tx algorithm so far, add support for the first. The margins taken from constraints were way large by default: the only explanation I found for that is that SmartArt layout sometimes calculates in MMs, sometimes in Points, and the ratio between the two is exactly the Impress / PowerPoint margin. So assume that indeed that unit difference is the reason for the smaller in-PowerPoint margin values and do the same on our side. (cherry picked from commit 279c7f83a57c4d3991930ee80e9d9c287c21270a) This is the commit #7: oox smartart, picture strip: fix too wide child shapes Once the constraints determine the size, the aspect ratio may shrink one dimension to achieve the requested ratio. Implement the case where a >1 ratio shrinks the width, so the container of the image-text shape pair has correct aspect ratio. (cherry picked from commit f4fbb127897ea6afe27055d3b6cfcb0441080902) Change-Id: I7bac764c031e80bac532c4f97ebd5b5096401096 Reviewed-on: https://gerrit.libreoffice.org/68687 Tested-by: Jenkins Reviewed-by: Andras Timar <andras.ti...@collabora.com> diff --git a/include/oox/drawingml/drawingmltypes.hxx b/include/oox/drawingml/drawingmltypes.hxx index c4f05fcdd84e..2abe05767d6a 100644 --- a/include/oox/drawingml/drawingmltypes.hxx +++ b/include/oox/drawingml/drawingmltypes.hxx @@ -190,6 +190,13 @@ inline float convertEmuToPoints( sal_Int64 nValue ) return static_cast<float>(nValue) / EMU_PER_PT; } +/** Converts the passed double value from points to mm. */ +inline double convertPointToMms(double fValue) +{ + constexpr double fFactor = static_cast<double>(EMU_PER_PT) / (EMU_PER_HMM * 100); + return fValue * fFactor; +} + /** A structure for a point with 64-bit integer components. */ struct EmuPoint { diff --git a/include/oox/drawingml/shape.hxx b/include/oox/drawingml/shape.hxx index 4a571213a090..40a80ae113dc 100644 --- a/include/oox/drawingml/shape.hxx +++ b/include/oox/drawingml/shape.hxx @@ -226,6 +226,13 @@ public: sal_Int32 getDataNodeType() const { return mnDataNodeType; } + void setAspectRatio(double fAspectRatio) { mfAspectRatio = fAspectRatio; } + + double getAspectRatio() const { return mfAspectRatio; } + + /// Changes reference semantics to value semantics for fill properties. + void cloneFillProperties(); + protected: css::uno::Reference< css::drawing::XShape > const & @@ -348,6 +355,9 @@ private: /// Type of data node for an in-diagram shape. sal_Int32 mnDataNodeType = 0; + + /// Aspect ratio for an in-diagram shape. + double mfAspectRatio = 0; }; } } diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx index 09edf0022259..247b99d0baad 100644 --- a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx +++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx @@ -65,6 +65,24 @@ bool isFontUnit(sal_Int32 nUnit) return nUnit == oox::XML_primFontSz || nUnit == oox::XML_secFontSz; } +/// Determines which UNO property should be set for a given constraint type. +sal_Int32 getPropertyFromConstraint(sal_Int32 nConstraint) +{ + switch (nConstraint) + { + case oox::XML_lMarg: + return oox::PROP_TextLeftDistance; + case oox::XML_rMarg: + return oox::PROP_TextRightDistance; + case oox::XML_tMarg: + return oox::PROP_TextUpperDistance; + case oox::XML_bMarg: + return oox::PROP_TextLowerDistance; + } + + return 0; +} + /// Determines the connector shape type from a linear alg. sal_Int32 getConnectorType(const oox::drawingml::LayoutNode* pNode) { @@ -246,7 +264,7 @@ void LayoutAtom::dump(int level) pAtom->dump(level + 1); } -ForEachAtom::ForEachAtom(const LayoutNode& rLayoutNode, const Reference< XFastAttributeList >& xAttributes) : +ForEachAtom::ForEachAtom(LayoutNode& rLayoutNode, const Reference< XFastAttributeList >& xAttributes) : LayoutAtom(rLayoutNode) { maIter.loadFromXAttr(xAttributes); @@ -273,7 +291,7 @@ const std::vector<LayoutAtomPtr>& ChooseAtom::getChildren() const return maEmptyChildren; } -ConditionAtom::ConditionAtom(const LayoutNode& rLayoutNode, bool isElse, const Reference< XFastAttributeList >& xAttributes) : +ConditionAtom::ConditionAtom(LayoutNode& rLayoutNode, bool isElse, const Reference< XFastAttributeList >& xAttributes) : LayoutAtom(rLayoutNode), mIsElse(isElse) { @@ -447,6 +465,21 @@ void ConstraintAtom::accept( LayoutAtomVisitor& rVisitor ) void ConstraintAtom::parseConstraint(std::vector<Constraint>& rConstraints, bool bRequireForName) const { + // Whitelist for cases where empty forName is handled. + if (bRequireForName) + { + switch (maConstraint.mnType) + { + case XML_sp: + case XML_lMarg: + case XML_rMarg: + case XML_tMarg: + case XML_bMarg: + bRequireForName = false; + break; + } + } + if (bRequireForName && maConstraint.msForName.isEmpty()) return; @@ -464,7 +497,7 @@ void AlgAtom::accept( LayoutAtomVisitor& rVisitor ) } void AlgAtom::layoutShape( const ShapePtr& rShape, - const std::vector<Constraint>& rOwnConstraints ) const + const std::vector<Constraint>& rOwnConstraints ) { // Algorithm result may depend on the parent constraints as well. std::vector<Constraint> aMergedConstraints; @@ -860,6 +893,18 @@ void AlgAtom::layoutShape( const ShapePtr& rShape, if (rShape->getChildren().empty() || rShape->getSize().Width == 0 || rShape->getSize().Height == 0) break; + // Parse constraints, only self spacing from height as a start. + double fSpaceFromConstraint = 0; + for (const auto& rConstr : rConstraints) + { + if (rConstr.mnRefType == XML_h) + { + if (rConstr.mnType == XML_sp && rConstr.msForName.isEmpty()) + fSpaceFromConstraint = rConstr.mfFactor; + } + } + bool bSpaceFromConstraints = fSpaceFromConstraint != 0; + const sal_Int32 nDir = maMap.count(XML_grDir) ? maMap.find(XML_grDir)->second : XML_tL; sal_Int32 nIncX = 1; sal_Int32 nIncY = 1; @@ -871,38 +916,67 @@ void AlgAtom::layoutShape( const ShapePtr& rShape, case XML_bR: nIncX = -1; nIncY = -1; break; } - // TODO: get values from constraints sal_Int32 nCount = rShape->getChildren().size(); - double fSpace = 0.3; + // Defaults in case not provided by constraints. + double fSpace = bSpaceFromConstraints ? fSpaceFromConstraint : 0.3; double fAspectRatio = 0.54; // diagram should not spill outside, earlier it was 0.6 sal_Int32 nCol = 1; sal_Int32 nRow = 1; - for ( ; nRow<nCount; nRow++) + double fChildAspectRatio = rShape->getChildren()[0]->getAspectRatio(); + if (nCount <= fChildAspectRatio) + // Child aspect ratio request (width/height) is N, and we have at most N shapes. + // This means we don't need multiple columns. + nRow = nCount; + else { - nCol = (nCount+nRow-1) / nRow; - const double fShapeHeight = rShape->getSize().Height; - const double fShapeWidth = rShape->getSize().Width; - if ((fShapeHeight / nCol) / (fShapeWidth / nRow) >= fAspectRatio) - break; + for ( ; nRow<nCount; nRow++) + { + nCol = (nCount+nRow-1) / nRow; + const double fShapeHeight = rShape->getSize().Height; + const double fShapeWidth = rShape->getSize().Width; + if ((fShapeHeight / nCol) / (fShapeWidth / nRow) >= fAspectRatio) + break; + } } SAL_INFO("oox.drawingml", "Snake layout grid: " << nCol << "x" << nRow); sal_Int32 nWidth = rShape->getSize().Width / (nCol + (nCol-1)*fSpace); - const awt::Size aChildSize(nWidth, nWidth * fAspectRatio); + awt::Size aChildSize(nWidth, nWidth * fAspectRatio); + if (nCol == 1 && nRow > 1) + { + // We have a single column, so count the height based on the parent height, not + // based on width. + // Space occurs inside children; also double amount of space is needed outside (on + // both sides), if the factor comes from a constraint. + sal_Int32 nNumSpaces = -1; + if (bSpaceFromConstraints) + nNumSpaces += 4; + sal_Int32 nHeight + = rShape->getSize().Height / (nRow + (nRow + nNumSpaces) * fSpace); + + if (fChildAspectRatio > 1) + { + // Shrink width if the aspect ratio requires it. + nWidth = std::min(rShape->getSize().Width, + static_cast<sal_Int32>(nHeight * fChildAspectRatio)); + aChildSize = awt::Size(nWidth, nHeight); + } + } awt::Point aCurrPos(0, 0); if (nIncX == -1) aCurrPos.X = rShape->getSize().Width - aChildSize.Width; if (nIncY == -1) aCurrPos.Y = rShape->getSize().Height - aChildSize.Height; + else if (bSpaceFromConstraints) + // Initial vertical offset to have upper spacing (outside, so double amount). + aCurrPos.Y = aChildSize.Height * fSpace * 2; sal_Int32 nStartX = aCurrPos.X; sal_Int32 nColIdx = 0,index = 0; - sal_Int32 num = rShape->getChildren().size(); - const sal_Int32 aContDir = maMap.count(XML_contDir) ? maMap.find(XML_contDir)->second : XML_sameDir; switch(aContDir) @@ -922,7 +996,7 @@ void AlgAtom::layoutShape( const ShapePtr& rShape, if(++nColIdx == nCol) // condition for next row { // if last row, then position children according to number of shapes. - if((index+1)%nCol!=0 && (index+1)>=3 && ((index+1)/nCol+1)==nRow && num!=nRow*nCol) + if((index+1)%nCol!=0 && (index+1)>=3 && ((index+1)/nCol+1)==nRow && nCount!=nRow*nCol) // position first child of last row aCurrPos.X = nStartX + (nIncX * (aChildSize.Width + fSpace*aChildSize.Width))/2; else @@ -961,10 +1035,10 @@ void AlgAtom::layoutShape( const ShapePtr& rShape, if(++nColIdx == nCol) // condition for next row { // if last row, then position children according to number of shapes. - if((index+1)%nCol!=0 && (index+1)>=4 && ((index+1)/nCol+1)==nRow && num!=nRow*nCol && ((index/nCol)+1)%2==0) + if((index+1)%nCol!=0 && (index+1)>=4 && ((index+1)/nCol+1)==nRow && nCount!=nRow*nCol && ((index/nCol)+1)%2==0) // position first child of last row aCurrPos.X -= aChildSize.Width*3/2; - else if((index+1)%nCol!=0 && (index+1)>=4 && ((index+1)/nCol+1)==nRow && num!=nRow*nCol && ((index/nCol)+1)%2!=0) + else if((index+1)%nCol!=0 && (index+1)>=4 && ((index+1)/nCol+1)==nRow && nCount!=nRow*nCol && ((index/nCol)+1)%2!=0) aCurrPos.X = nStartX + (nIncX * (aChildSize.Width + fSpace*aChildSize.Width))/2; else if(((index/nCol)+1)%2!=0) aCurrPos.X = nStartX; @@ -997,6 +1071,29 @@ void AlgAtom::layoutShape( const ShapePtr& rShape, case XML_tx: { // adjust text alignment + + // Parse constraints, only self margins as a start. + for (const auto& rConstr : rConstraints) + { + if (rConstr.mnRefType == XML_w) + { + if (!rConstr.msForName.isEmpty()) + continue; + + sal_Int32 nProperty = getPropertyFromConstraint(rConstr.mnType); + if (!nProperty) + continue; + + // PowerPoint takes size as points, but gives margin as MMs. + double fFactor = convertPointToMms(rConstr.mfFactor); + + // DrawingML works in EMUs, UNO API works in MM100s. + sal_Int32 nValue = rShape->getSize().Width * fFactor / EMU_PER_HMM; + + rShape->getShapeProperties().setProperty(nProperty, nValue); + } + } + // TODO: adjust text size to fit shape TextBodyPtr pTextBody = rShape->getTextBody(); if (!pTextBody || @@ -1220,6 +1317,8 @@ bool LayoutNode::setupShape( const ShapePtr& rShape, const dgm::Point* pPresNode " processing shape type " << rShape->getCustomShapeProperties()->getShapePresetType() << " for layout node named \"" << msName << "\""); + if (pPresNode->mpShape) + rShape->getFillProperties().assignUsed(pPresNode->mpShape->getFillProperties()); } // TODO(Q1): apply styling & coloring - take presentation diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx index 75149a5cbecd..9b184f917f17 100644 --- a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx +++ b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx @@ -91,10 +91,10 @@ typedef std::shared_ptr< LayoutAtom > LayoutAtomPtr; class LayoutAtom { public: - LayoutAtom(const LayoutNode& rLayoutNode) : mrLayoutNode(rLayoutNode) {} + LayoutAtom(LayoutNode& rLayoutNode) : mrLayoutNode(rLayoutNode) {} virtual ~LayoutAtom() { } - const LayoutNode& getLayoutNode() const + LayoutNode& getLayoutNode() { return mrLayoutNode; } /** visitor acceptance @@ -127,7 +127,7 @@ public: void dump(int level = 0); protected: - const LayoutNode& mrLayoutNode; + LayoutNode& mrLayoutNode; std::vector< LayoutAtomPtr > mpChildNodes; std::weak_ptr<LayoutAtom> mpParent; OUString msName; @@ -137,7 +137,7 @@ class ConstraintAtom : public LayoutAtom { public: - ConstraintAtom(const LayoutNode& rLayoutNode) : LayoutAtom(rLayoutNode) {} + ConstraintAtom(LayoutNode& rLayoutNode) : LayoutAtom(rLayoutNode) {} virtual void accept( LayoutAtomVisitor& ) override; Constraint& getConstraint() { return maConstraint; } @@ -150,7 +150,7 @@ class AlgAtom : public LayoutAtom { public: - AlgAtom(const LayoutNode& rLayoutNode) : LayoutAtom(rLayoutNode), mnType(0), maMap() {} + AlgAtom(LayoutNode& rLayoutNode) : LayoutAtom(rLayoutNode), mnType(0), maMap() {} typedef std::map<sal_Int32,sal_Int32> ParamMap; @@ -161,7 +161,7 @@ public: void addParam( sal_Int32 nType, sal_Int32 nVal ) { maMap[nType]=nVal; } void layoutShape( const ShapePtr& rShape, - const std::vector<Constraint>& rConstraints ) const; + const std::vector<Constraint>& rConstraints ); /// Gives access to <dgm:alg type="..."/>. sal_Int32 getType() const { return mnType; } @@ -171,6 +171,8 @@ public: void setAspectRatio(double fAspectRatio) { mfAspectRatio = fAspectRatio; } + double getAspectRatio() const { return mfAspectRatio; } + private: sal_Int32 mnType; ParamMap maMap; @@ -184,7 +186,7 @@ class ForEachAtom : public LayoutAtom { public: - explicit ForEachAtom(const LayoutNode& rLayoutNode, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttributes); + explicit ForEachAtom(LayoutNode& rLayoutNode, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttributes); IteratorAttr & iterator() { return maIter; } @@ -200,7 +202,7 @@ class ConditionAtom : public LayoutAtom { public: - explicit ConditionAtom(const LayoutNode& rLayoutNode, bool isElse, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttributes); + explicit ConditionAtom(LayoutNode& rLayoutNode, bool isElse, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttributes); virtual void accept( LayoutAtomVisitor& ) override; bool getDecision() const; private: @@ -220,7 +222,7 @@ class ChooseAtom : public LayoutAtom { public: - ChooseAtom(const LayoutNode& rLayoutNode) + ChooseAtom(LayoutNode& rLayoutNode) : LayoutAtom(rLayoutNode) #if defined __clang__ && __clang_major__ == 3 && __clang_minor__ == 8 , maEmptyChildren() @@ -264,6 +266,10 @@ public: const LayoutNode* getParentLayoutNode() const; ... etc. - the rest is truncated _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits