[Libreoffice-commits] core.git: Branch 'feature/cib_contract57c' - 37 commits - configure.ac desktop/source download.lst external/libxslt filter/source filter/uiconfig framework/source include/vcl jvmfwk/inc jvmfwk/plugins jvmfwk/source officecfg/registry readlicense_oo/license sc/source shell/source solenv/clang-format svx/source sw/inc sw/qa sw/source translations vcl/inc vcl/qt5 vcl/quartz vcl/source vcl/unx vcl/win

Samuel Mehrbrodt (via logerrit) logerrit at kemper.freedesktop.org
Mon May 13 17:52:54 UTC 2019


Rebased ref, commits from common ancestor:
commit ca35a204bb19ccba00648418ac1bdc11eb56183b
Author:     Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
AuthorDate: Tue Apr 30 12:47:00 2019 +0200
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon May 13 19:51:51 2019 +0200

    Load explorerframe.dll at startup
    
    Change-Id: I8d129a4af589cd2b6af446e56309b51b79f6fb68

diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx
index c83d424f8a30..5d7a629453b6 100644
--- a/desktop/source/app/app.cxx
+++ b/desktop/source/app/app.cxx
@@ -119,6 +119,7 @@
 #include <svtools/accessibilityoptions.hxx>
 #include <svtools/apearcfg.hxx>
 #include <vcl/graphicfilter.hxx>
+#include <osl/module.hxx>
 
 #include "langselect.hxx"
 
@@ -439,6 +440,13 @@ Desktop::Desktop()
     m_firstRunTimer.SetTimeout(3000); // 3 sec.
     m_firstRunTimer.SetInvokeHandler(LINK(this, Desktop, AsyncInitFirstRun));
     m_firstRunTimer.SetDebugName( "desktop::Desktop m_firstRunTimer" );
+
+    static ::osl::Module aMod;
+    aMod.load("explorerframe.dll");
+    if (aMod.is())
+        SAL_WARN("desktop.app", "loading explorerframe.dll successful");
+    else
+        SAL_WARN("desktop.app", "loading explorerframe.dll failed");
 }
 
 Desktop::~Desktop()
commit 871eeb3b99d32564ff5266d4fe588c0652db7d00
Author:     Katarina Behrens <Katarina.Behrens at cib.de>
AuthorDate: Tue May 7 16:27:22 2019 +0200
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon May 13 19:51:05 2019 +0200

    tdf#83722: don't recycle frame with unmodified template
    
    a frame that contained valid but unmodified document opened from
    template or explicitly opened by the user (File > New) was treated
    the same as blank document i.e. it was reused and the content was
    overwritten by newly opened document (even if it already had
    non-empty content provided by the template).
    
    So let's not do that and let's open a new document in a new frame
    instead
    
    Change-Id: I10252d114e8cc5fcad3c98194ef07fd59873d6da
    Reviewed-on: https://gerrit.libreoffice.org/71919
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <Michael.Stahl at cib.de>
    Reviewed-by: Katarina Behrens <Katarina.Behrens at cib.de>

diff --git a/framework/source/loadenv/loadenv.cxx b/framework/source/loadenv/loadenv.cxx
index b527d0259e77..4f9cfe71d567 100644
--- a/framework/source/loadenv/loadenv.cxx
+++ b/framework/source/loadenv/loadenv.cxx
@@ -1072,7 +1072,7 @@ bool LoadEnv::impl_loadContent()
     // if it will be run out of scope.
 
     // Note further: ignore if this internal guard already contains a resource.
-    // Might impl_searchRecylcTarget() set it before. But in case this impl-method wasn't used
+    // Might impl_searchRecycleTarget() set it before. But in case this impl-method wasn't used
     // and the target frame was new created ... this lock here must be set!
     css::uno::Reference< css::document::XActionLockable > xTargetLock(xTargetFrame, css::uno::UNO_QUERY);
     m_aTargetLock.setResource(xTargetLock);
@@ -1512,6 +1512,15 @@ css::uno::Reference< css::frame::XFrame > LoadEnv::impl_searchRecycleTarget()
     css::uno::Reference< css::frame::XController > xOldDoc = xTask->getController();
     if (xOldDoc.is())
     {
+        utl::MediaDescriptor lOldDocDescriptor(xModel->getArgs());
+        bool bFromTemplate = lOldDocDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_ASTEMPLATE() , false);
+        OUString sReferrer = lOldDocDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_REFERRER(), OUString());
+
+        // tdf#83722: valid but unmodified document, either from template
+        // or opened by the user (File > New)
+        if (bFromTemplate || !sReferrer.isEmpty())
+            return css::uno::Reference< css::frame::XFrame >();
+
         bReactivateOldControllerOnError = xOldDoc->suspend(true);
         if (! bReactivateOldControllerOnError)
             return css::uno::Reference< css::frame::XFrame >();
commit 911c76ff790ecc8a3fd3cdeeff527ac5598375d8
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Apr 29 17:40:45 2019 +0200
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon May 13 19:51:05 2019 +0200

    tdf#122607 sw: restore CalcLayout() call in getRendererCount()
    
    Effectively revert commit 1ecca673b40fedc53db125e332b087d1c120a254.
    
    There are some documents that aren't formatted correctly.
    
    (cherry picked from commit 5879351aeb1935e2bf86fda59703f7d49fdeb6ed)
    
    Change-Id: I4b0cf6313c249a0ed916c2630cd5194d809bfb48

diff --git a/sw/qa/extras/layout/data/tdf122607_leerzeile.odt b/sw/qa/extras/layout/data/tdf122607_leerzeile.odt
new file mode 100644
index 000000000000..9819a229344a
Binary files /dev/null and b/sw/qa/extras/layout/data/tdf122607_leerzeile.odt differ
diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx
index 615061572ec1..a107d6472aa3 100755
--- a/sw/qa/extras/layout/layout.cxx
+++ b/sw/qa/extras/layout/layout.cxx
@@ -34,6 +34,7 @@ public:
     void testTdf119875();
     void testTdf116989();
     void testTdf122607();
+    void testTdf122607_regression();
     void testTdf123898();
 
     CPPUNIT_TEST_SUITE(SwLayoutWriter);
@@ -53,6 +54,7 @@ public:
     CPPUNIT_TEST(testTdf119875);
     CPPUNIT_TEST(testTdf116989);
     CPPUNIT_TEST(testTdf122607);
+    CPPUNIT_TEST(testTdf122607_regression);
     CPPUNIT_TEST(testTdf123898);
     CPPUNIT_TEST_SUITE_END();
 
@@ -323,6 +325,54 @@ void SwLayoutWriter::testTdf122607()
                 "nWidth", "428");
 }
 
+void SwLayoutWriter::testTdf122607_regression()
+{
+    discardDumpedLayout();
+    if (mxComponent.is())
+        mxComponent->dispose();
+
+    auto const pName("tdf122607_leerzeile.odt");
+
+    OUString const url(m_directories.getURLFromSrc(DATA_DIRECTORY)
+                       + OUString::createFromAscii(pName));
+
+    // note: must set Hidden property, so that SfxFrameViewWindow_Impl::Resize()
+    // does *not* forward initial VCL Window Resize and thereby triggers a
+    // layout which does not happen on soffice --convert-to pdf.
+    std::vector<beans::PropertyValue> aFilterOptions = {
+        { beans::PropertyValue("Hidden", -1, uno::Any(true), beans::PropertyState_DIRECT_VALUE) },
+    };
+
+    std::cout << pName << ":\n";
+
+    // inline the loading because currently properties can't be passed...
+    mxComponent = loadFromDesktop(url, "com.sun.star.text.TextDocument",
+                                  comphelper::containerToSequence(aFilterOptions));
+
+    CPPUNIT_ASSERT(mxComponent.is());
+
+    uno::Sequence<beans::PropertyValue> props(comphelper::InitPropertySequence({
+        { "FilterName", uno::Any(OUString("writer_pdf_Export")) },
+    }));
+    utl::TempFile aTempFile;
+    uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+    xStorable->storeToURL(aTempFile.GetURL(), props);
+
+    xmlDocPtr pXmlDoc = parseLayoutDump();
+    // somehow these 2 rows overlapped in the PDF unless CalcLayout() runs
+    assertXPath(pXmlDoc, "/root/page[1]/anchored/fly/tab[1]/row[1]/infos/bounds", "mbFixSize",
+                "false");
+    assertXPath(pXmlDoc, "/root/page[1]/anchored/fly/tab[1]/row[1]/infos/bounds", "top", "2977");
+    assertXPath(pXmlDoc, "/root/page[1]/anchored/fly/tab[1]/row[1]/infos/bounds", "height", "241");
+    assertXPath(pXmlDoc, "/root/page[1]/anchored/fly/tab[1]/row[2]/infos/bounds", "mbFixSize",
+                "true");
+    // this was 3034, causing the overlap
+    assertXPath(pXmlDoc, "/root/page[1]/anchored/fly/tab[1]/row[2]/infos/bounds", "top", "3218");
+    assertXPath(pXmlDoc, "/root/page[1]/anchored/fly/tab[1]/row[2]/infos/bounds", "height", "164");
+
+    aTempFile.EnableKillingFile();
+}
+
 void SwLayoutWriter::testTdf123898()
 {
     createDoc("tdf123898.odt");
diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx
index d2d512fd8c6f..f351dafdc4ec 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -2622,9 +2622,10 @@ sal_Int32 SAL_CALL SwXTextDocument::getRendererCount(
             // should be set for printing as well ...
             pViewShell->SetPDFExportOption( true );
 
-            // 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();
+            // 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() );
 
 
commit e8e60be122f354e59582687a6dba5beab76f4802
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Apr 29 17:21:18 2019 +0200
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon May 13 19:51:05 2019 +0200

    tdf#122607 sw: fix preservation of text frame cache entries
    
    SwSaveSetLRUOfst would leave only 50 cache entries available for the
    CalcLayout() to use; apparently it's not enough for this document.
    
    The difference between the 1st loading/layout and the 3rd loading/layout
    of the document is that in many paragraphs the cache entry is missing,
    because the entires of the previous loads were clogging up the cache
    and were preserved here, and the cache only has 50 available entries;
    if enough entries are available, everything is positioned properly.
    
    The idea with the 100 entries per visible shell actually comes from the
    CVS initial import, where there was a comment suggesting that; but the
    corresponding parameter was actually unused and removed in
    7c704c78d3c652504c064b4ac7af55a2c1ee49bb.
    
    Ideally we'd have time to investigate why a missing cache entry causes
    the wrong position...
    
    Reviewed-on: https://gerrit.libreoffice.org/71542
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <Michael.Stahl at cib.de>
    (cherry picked from commit 3d37463eec0c891243a8971a34903b2da01c9e24)
    
    Change-Id: I64a72a94361dbf5717bbc709fa3bc9abbe18a37c

diff --git a/sw/source/core/bastyp/swcache.cxx b/sw/source/core/bastyp/swcache.cxx
index ab82fe11ba74..e90f89b87612 100644
--- a/sw/source/core/bastyp/swcache.cxx
+++ b/sw/source/core/bastyp/swcache.cxx
@@ -440,6 +440,7 @@ bool SwCache::Insert( SwCacheObj *pNew )
 
 void SwCache::SetLRUOfst( const sal_uInt16 nOfst )
 {
+    assert(nOfst < m_nCurMax);
     if ( !m_pRealFirst || ((m_aCacheObjects.size() - m_aFreePositions.size()) < nOfst) )
         return;
 
diff --git a/sw/source/core/inc/swcache.hxx b/sw/source/core/inc/swcache.hxx
index a481bbff28ff..2cc6138cb2b1 100644
--- a/sw/source/core/inc/swcache.hxx
+++ b/sw/source/core/inc/swcache.hxx
@@ -117,15 +117,12 @@ public:
     sal_uInt16 size() { return m_aCacheObjects.size(); }
 };
 
-/// Safely manipulate the cache
+/// Try to prevent visible SwParaPortions from being deleted.
 class SwSaveSetLRUOfst
 {
-    SwCache &rCache;
 public:
-    SwSaveSetLRUOfst( SwCache &rC, const sal_uInt16 nOfst )
-        : rCache( rC )          { rCache.SetLRUOfst( nOfst );  }
-
-    ~SwSaveSetLRUOfst()         { rCache.ResetLRUOfst(); }
+    SwSaveSetLRUOfst();
+    ~SwSaveSetLRUOfst();
 };
 
 /**
diff --git a/sw/source/core/text/txtcache.cxx b/sw/source/core/text/txtcache.cxx
index b2f412b07c5b..20b992d9e275 100644
--- a/sw/source/core/text/txtcache.cxx
+++ b/sw/source/core/text/txtcache.cxx
@@ -21,6 +21,9 @@
 #include <txtfrm.hxx>
 #include "porlay.hxx"
 
+#include <sfx2/viewsh.hxx>
+#include <view.hxx>
+
 SwTextLine::SwTextLine( SwTextFrame const *pFrame, SwParaPortion *pNew ) :
     SwCacheObj( static_cast<void const *>(pFrame) ),
     pLine( pNew )
@@ -135,4 +138,37 @@ void SwTextFrame::SetPara( SwParaPortion *pNew, bool bDelete )
     }
 }
 
+/** Prevent the SwParaPortions of the *visible* paragraphs from being deleted;
+    they would just be recreated on the next paint.
+
+    Heuristic: 100 per view are visible
+
+    If the cache is too small, enlarge it to ensure there are sufficient free
+    entries for the layout so it doesn't have to throw away a node's
+    SwParaPortion when it starts formatting the next node.
+*/
+SwSaveSetLRUOfst::SwSaveSetLRUOfst()
+{
+    sal_uInt16 nVisibleShells(0);
+    for (auto pView = SfxViewShell::GetFirst(true, checkSfxViewShell<SwView>);
+         pView != nullptr;
+         pView = SfxViewShell::GetNext(*pView, true, checkSfxViewShell<SwView>))
+    {
+        ++nVisibleShells;
+    }
+
+    sal_uInt16 const nPreserved(100 * nVisibleShells);
+    SwCache & rCache(*SwTextFrame::GetTextCache());
+    if (rCache.GetCurMax() < nPreserved + 250)
+    {
+        rCache.IncreaseMax(nPreserved + 250 - rCache.GetCurMax());
+    }
+    rCache.SetLRUOfst(nPreserved);
+}
+
+SwSaveSetLRUOfst::~SwSaveSetLRUOfst()
+{
+    SwTextFrame::GetTextCache()->ResetLRUOfst();
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/view/viewsh.cxx b/sw/source/core/view/viewsh.cxx
index 76435e704cd9..640db966432e 100644
--- a/sw/source/core/view/viewsh.cxx
+++ b/sw/source/core/view/viewsh.cxx
@@ -700,9 +700,8 @@ void SwViewShell::LayoutIdle()
 #endif
 
     {
-        //Prepare and recover cache, so that it will not get fouled.
-        SwSaveSetLRUOfst aSave( *SwTextFrame::GetTextCache(),
-                             SwTextFrame::GetTextCache()->GetCurMax() - 50 );
+        // Preserve top of the text frame cache.
+        SwSaveSetLRUOfst aSaveLRU;
         // #125243# there are lots of stacktraces indicating that Imp() returns NULL
         // this SwViewShell seems to be invalid - but it's not clear why
         // this return is only a workaround!
@@ -978,9 +977,8 @@ void SwViewShell::CalcLayout()
     SET_CURR_SHELL( this );
     SwWait aWait( *GetDoc()->GetDocShell(), true );
 
-    //prepare and recover cache, so that it will not get fouled.
-    SwSaveSetLRUOfst aSaveLRU( *SwTextFrame::GetTextCache(),
-                                  SwTextFrame::GetTextCache()->GetCurMax() - 50 );
+    // Preserve top of the text frame cache.
+    SwSaveSetLRUOfst aSaveLRU;
 
     //switch on Progress when none is running yet.
     const bool bEndProgress = SfxProgress::GetActiveProgress( GetDoc()->GetDocShell() ) == nullptr;
commit 103915a477ead1e6d0f799c57bf27050cae1abf4
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Apr 29 17:14:42 2019 +0200
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon May 13 19:51:05 2019 +0200

    tdf#122607 sw: remove deleted SwTextFrame's cache entry
    
    Apparently nothing else would remove the entry, and without SwTextFrame
    it's not accessible any more.
    
    If the entry was recently used, then the SwSaveSetLRUOfst usage in
    SwViewShell::CalcLayout() will preserve it instead of giving the cache
    entry to a new frame.
    
    Change-Id: Id43fdbad2ac006853928e30a7b6768c3e3dc1667
    Reviewed-on: https://gerrit.libreoffice.org/71541
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <Michael.Stahl at cib.de>
    (cherry picked from commit 31ae7509003b1e650463ee1468c0b315ba13efe6)

diff --git a/sw/source/core/bastyp/swcache.cxx b/sw/source/core/bastyp/swcache.cxx
index 2019d7d0b3b5..ab82fe11ba74 100644
--- a/sw/source/core/bastyp/swcache.cxx
+++ b/sw/source/core/bastyp/swcache.cxx
@@ -326,6 +326,15 @@ void SwCache::DeleteObj( SwCacheObj *pObj )
     CHECK;
 }
 
+void SwCache::Delete(void const*const pOwner, sal_uInt16 const nIndex)
+{
+    INCREMENT( m_nDelete );
+    if (SwCacheObj *const pObj = Get(pOwner, nIndex, false))
+    {
+        DeleteObj(pObj);
+    }
+}
+
 void SwCache::Delete( const void *pOwner )
 {
     INCREMENT( m_nDelete );
diff --git a/sw/source/core/inc/swcache.hxx b/sw/source/core/inc/swcache.hxx
index 30410061b49f..a481bbff28ff 100644
--- a/sw/source/core/inc/swcache.hxx
+++ b/sw/source/core/inc/swcache.hxx
@@ -102,6 +102,7 @@ public:
     void ToTop( SwCacheObj *pObj );
 
     bool Insert( SwCacheObj *pNew );
+    void Delete(const void * pOwner, sal_uInt16 nIndex);
     void Delete( const void *pOwner );
 
     void SetLRUOfst( const sal_uInt16 nOfst );  /// nOfst determines how many are not to be touched
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index 62b281ae6974..c759be22aa02 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -693,6 +693,10 @@ void SwTextFrame::DestroyImpl()
 
 SwTextFrame::~SwTextFrame()
 {
+    if (GetCacheIdx() != USHRT_MAX)
+    {
+        s_pTextCache->Delete(this, GetCacheIdx());
+    }
 }
 
 namespace sw {
commit 63fd178941707bc6cf0bed91d2c21216e2747120
Author:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
AuthorDate: Thu Apr 11 09:47:27 2019 +0200
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon May 13 19:51:05 2019 +0200

    Fix appearance for checkboxes
    
    Conflicts:
            vcl/source/gdi/pdfwriter_impl.cxx
    
    (cherry picked from commit 49cb0dc7d70fdb12fa6eb91c98d63f9e0cf0067c)
    
    Change-Id: Id5028b0d062e0491b1cc9c36e2d9d4e4a7ab14a1

diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 1f8d1a1a31e9..fc734dc27d11 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -66,6 +66,7 @@
 #include <vcl/bitmapex.hxx>
 #include <vcl/bitmapaccess.hxx>
 #include <vcl/cvtgrf.hxx>
+#include <vcl/fontcharmap.hxx>
 #include <vcl/image.hxx>
 #include <vcl/lineinfo.hxx>
 #include <vcl/metric.hxx>
@@ -4384,45 +4385,75 @@ void PDFWriterImpl::createDefaultCheckBoxAppearance( PDFWidget& rBox, const PDFW
     pop();
 
     OStringBuffer aDA( 256 );
+
+    // tdf#93853 don't rely on Zapf (or any other 'standard' font)
+    // being present, but our own OpenSymbol - N.B. PDF/A for good
+    // reasons require even the standard PS fonts to be embedded!
+    getReferenceDevice()->Push();
+    getReferenceDevice()->SetFont(
+        Font( OUString( "OpenSymbol" ), Size( 0, 500 ) ) );
+    getReferenceDevice()->ImplNewFont();
+    FontCharMapRef pMap;
+    getReferenceDevice()->GetFontCharMap(pMap);
+    const PhysicalFontFace* pDevFont = m_pReferenceDevice->mpFontInstance->
+        GetFontFace();
+    getReferenceDevice()->Pop();
+
+    // make sure OpenSymbol is embedded, and includes our checkmark
+    const sal_Unicode cMark=0x2713;
+    const GlyphItem aItem(pMap->GetGlyphIndex(cMark), 0, 0,
+                          Point(), 0, 0, 0);
+    const std::vector<sal_Ucs> aCodeUnits={ cMark };
+    sal_uInt8 nMappedGlyph;
+    sal_Int32 nMappedFontObject;
+    registerGlyph(&aItem, pDevFont, aCodeUnits, nMappedGlyph, nMappedFontObject);
+
     appendNonStrokingColor( replaceColor( rWidget.TextColor, rSettings.GetRadioCheckTextColor() ), aDA );
-    sal_Int32 nBest = getBestBuiltinFont( Font( "ZapfDingbats", aFont.GetFontSize() ) );
     aDA.append( ' ' );
-    aDA.append( m_aBuiltinFonts[nBest].getNameObject() );
+    aDA.append( "/F" );
+    aDA.append( nMappedFontObject );
     aDA.append( " 0 Tf" );
+
+    OStringBuffer aDR( 32 );
+    aDR.append( "/Font " );
+    aDR.append( getFontDictObject() );
+    aDR.append( " 0 R" );
+    rBox.m_aDRDict = aDR.makeStringAndClear();
     rBox.m_aDAString = aDA.makeStringAndClear();
     rBox.m_aMKDict = "/CA";
     rBox.m_aMKDictCAString = "8";
     rBox.m_aRect = aCheckRect;
 
     // create appearance streams
-    sal_Char cMark = '8';
-    sal_Int32 nCharXOffset = 1000-m_aBuiltinFonts[13].m_aWidths[sal_Int32(cMark)];
+    sal_Int32 nCharXOffset = 1000;
     nCharXOffset *= aCheckRect.GetHeight();
     nCharXOffset /= 2000;
-    sal_Int32 nCharYOffset = 1000-
-        (m_aBuiltinFonts[13].m_nAscent+m_aBuiltinFonts[13].m_nDescent); // descent is negative
+    sal_Int32 nCharYOffset = 1000-(820-143); // metrics from Zapf
     nCharYOffset *= aCheckRect.GetHeight();
     nCharYOffset /= 2000;
 
+    // write 'checked' appearance stream
     SvMemoryStream* pCheckStream = new SvMemoryStream( 256, 256 );
     beginRedirect( pCheckStream, aCheckRect );
     aDA.append( "/Tx BMC\nq BT\n" );
     appendNonStrokingColor( replaceColor( rWidget.TextColor, rSettings.GetRadioCheckTextColor() ), aDA );
     aDA.append( ' ' );
-    aDA.append( m_aBuiltinFonts[nBest].getNameObject() );
+    aDA.append( "/F" );
+    aDA.append( nMappedFontObject );
     aDA.append( ' ' );
     m_aPages[ m_nCurrentPage ].appendMappedLength( sal_Int32( aCheckRect.GetHeight() ), aDA );
     aDA.append( " Tf\n" );
     m_aPages[ m_nCurrentPage ].appendMappedLength( nCharXOffset, aDA );
     aDA.append( " " );
     m_aPages[ m_nCurrentPage ].appendMappedLength( nCharYOffset, aDA );
-    aDA.append( " Td (" );
-    aDA.append( cMark );
-    aDA.append( ") Tj\nET\nQ\nEMC\n" );
+    aDA.append( " Td <" );
+    appendHex( nMappedGlyph, aDA );
+    aDA.append( "> Tj\nET\nQ\nEMC\n" );
     writeBuffer( aDA.getStr(), aDA.getLength() );
     endRedirect();
     rBox.m_aAppearances[ "N" ][ "Yes" ] = pCheckStream;
 
+    // write 'unchecked' appearance stream
     SvMemoryStream* pUncheckStream = new SvMemoryStream( 256, 256 );
     beginRedirect( pUncheckStream, aCheckRect );
     writeBuffer( "/Tx BMC\nEMC\n", 12 );
commit 269ee01ea6e03f9bbc89c4a09341599036d233b1
Author:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
AuthorDate: Mon Apr 8 00:32:09 2019 +0200
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon May 13 19:51:05 2019 +0200

    pdf: always write resource dict for content streams
    
    Take out:
    - revert i#42884 workaround for AR5: use implicit resources in
      transparency groups
    
    Since verapdf complains with FAIL 6.2.2-2 in this case - missing
    resource dict for content stream.
    
    Change-Id: Ic186d2b4b393ac34f991a6747667332cf8f4658b

diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 108f9199ce4f..1f8d1a1a31e9 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -8579,16 +8579,14 @@ void PDFWriterImpl::writeTransparentObject( TransparencyEmit& rObject )
     {
         if( ! m_bIsPDF_A1 )
         {
+            // 7.8.3 Resource dicts are required for content streams
+            aLine.append( "/Resources " );
+            aLine.append( getResourceDictObj() );
+            aLine.append( " 0 R\n" );
+
             aLine.append( "/Group<</S/Transparency/CS/DeviceRGB/K true>>\n" );
         }
     }
-    /* #i42884# the PDF reference recommends that each Form XObject
-    *  should have a resource dict; alas if that is the same object
-    *  as the one of the page it triggers an endless recursion in
-    *  acroread 5 (6 and up have that fixed). Since we have only one
-    *  resource dict anyway, let's use the one from the page by NOT
-    *  emitting a Resources entry.
-    */
 
     aLine.append( "/Length " );
     aLine.append( static_cast<sal_Int32>(nSize) );
@@ -8661,7 +8659,11 @@ void PDFWriterImpl::writeTransparentObject( TransparencyEmit& rObject )
             appendFixedInt( rObject.m_aBoundRect.Bottom()+1, aMask );
             aMask.append( "]\n" );
 
-            /* #i42884# see above */
+            // 7.8.3 Resource dicts are required for content streams
+            aMask.append( "/Resources " );
+            aMask.append( getResourceDictObj() );
+            aMask.append( " 0 R\n" );
+
             aMask.append( "/Group<</S/Transparency/CS/DeviceRGB>>\n" );
             aMask.append( "/Length " );
             aMask.append( nMaskSize );
commit ec6b6591cd9acf0c242bec8f10cfce5301f60a97
Author:     Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
AuthorDate: Tue Mar 26 15:08:12 2019 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon May 13 19:51:05 2019 +0200

    Fix windows build
    
    After 54ac2b203a6dd974c0153996ba67b26d585e98e1
    
    Change-Id: I805415dfa75568d843fceb5a79b637aac337ffd4

diff --git a/vcl/win/gdi/salfont.cxx b/vcl/win/gdi/salfont.cxx
index b0158f9154d5..f3d0cf97811e 100644
--- a/vcl/win/gdi/salfont.cxx
+++ b/vcl/win/gdi/salfont.cxx
@@ -932,6 +932,7 @@ void WinSalGraphics::SetFont( const FontSelectPattern* pFont, int nFallbackLevel
     // WinSalGraphics::GetEmbedFontData does not set mpFontInstance
     // since it is interested in font file data only.
     mpWinFontEntry[ nFallbackLevel ] = reinterpret_cast<WinFontInstance*>( pFont->mpFontInstance.get() );
+    WinFontInstance *pFontInstance = static_cast<WinFontInstance*>(pFont->mpFontInstance.get());
 
     HFONT hOldFont = nullptr;
     HFONT hNewFont = pFontInstance ? pFontInstance->GetHFONT() : nullptr;
@@ -970,7 +971,6 @@ void WinSalGraphics::SetFont( const FontSelectPattern* pFont, int nFallbackLevel
             }
             if (mpWinFontEntry[i])
             {
-                GetWinFontEntry(i)->Release();
                 mpWinFontEntry[i] = nullptr;
             }
             mfFontScale[i] = 1.0;
@@ -1363,7 +1363,7 @@ void WinSalGraphics::ClearDevFontCache()
 
 bool WinSalGraphics::GetGlyphBoundRect(const GlyphItem& rGlyph, tools::Rectangle& rRect)
 {
-    WinFontInstance* pFont = mpWinFontEntry[rGlyph.mnFallbackLevel];
+    rtl::Reference<WinFontInstance> pFont = mpWinFontEntry[rGlyph.mnFallbackLevel];
     HFONT hNewFont = pFont ? pFont->GetHFONT() : mhFonts[rGlyph.mnFallbackLevel];
     float fFontScale = pFont ? pFont->GetScale() : mfFontScale[rGlyph.mnFallbackLevel];
 
@@ -1572,7 +1572,7 @@ bool WinSalGraphics::GetGlyphOutline(const GlyphItem& rGlyph,
     // rescaling needed for the tools::PolyPolygon conversion
     if( rB2DPolyPoly.count() )
     {
-        WinFontInstance *pFont = mpWinFontEntry[rGlyph.mnFallbackLevel];
+        rtl::Reference<WinFontInstance> pFont = mpWinFontEntry[rGlyph.mnFallbackLevel];
         float fFontScale = pFont ? pFont->GetScale() : mfFontScale[rGlyph.mnFallbackLevel];
         const double fFactor(fFontScale/256);
         rB2DPolyPoly.transform(basegfx::utils::createScaleB2DHomMatrix(fFactor, fFactor));
commit 8e001487683d65b3e6765bc1b82cb77f3ca9426e
Author:     Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
AuthorDate: Tue Mar 26 12:27:38 2019 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon May 13 19:51:04 2019 +0200

    Add missing include
    
    Fallout from 7f9dfae2f83f11cc7799110435164a6bd2ba19d5
    
    Change-Id: If1f9ac47baf389c363f1fbda4158f4101ae2d50a

diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx
index 1e9047f855c2..615061572ec1 100755
--- a/sw/qa/extras/layout/layout.cxx
+++ b/sw/qa/extras/layout/layout.cxx
@@ -10,6 +10,7 @@
 #include <swmodeltestbase.hxx>
 #include <comphelper/propertysequence.hxx>
 #include <test/mtfxmldump.hxx>
+#include <vcl/scheduler.hxx>
 
 static char const DATA_DIRECTORY[] = "/sw/qa/extras/layout/data/";
 
commit d5f31e430b0d7970df997beedb1938e3a85a2560
Author:     Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
AuthorDate: Mon Mar 25 16:35:40 2019 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon May 13 19:51:04 2019 +0200

    tdf#124025 Update formula before printing
    
    Reintroduce the UpdateFields call, but guard it so that
    it does not modify the doc (as it was before)
    
    Change-Id: I23e814f0b5d900d145dc82272034f03e66c079ed
    Reviewed-on: https://gerrit.libreoffice.org/69696
    Tested-by: Jenkins
    Reviewed-by: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
    (cherry picked from commit 055480aac88e4688619e9a7815e0a8b0ab97a5a1)

diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx
index b5d224209275..d2d512fd8c6f 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -2621,23 +2621,25 @@ sal_Int32 SAL_CALL SwXTextDocument::getRendererCount(
             // since printing now also use the API for PDF export this option
             // should be set for printing as well ...
             pViewShell->SetPDFExportOption( true );
-            bool bOrigStatus = pRenderDocShell->IsEnableSetModified();
-            // check configuration: shall update of printing information in DocInfo set the document to "modified"?
+
+            // 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() );
+
+
+            // #122919# Force field update before PDF export, but after layout init (tdf#121962)
             bool bStateChanged = false;
-            if ( bOrigStatus && !SvtPrintWarningOptions().IsModifyDocumentOnPrintingAllowed() )
+            // check configuration: shall update of printing information in DocInfo set the document to "modified"?
+            if ( pRenderDocShell->IsEnableSetModified() && !SvtPrintWarningOptions().IsModifyDocumentOnPrintingAllowed() )
             {
                 pRenderDocShell->EnableSetModified( false );
                 bStateChanged = true;
             }
-
+            pViewShell->SwViewShell::UpdateFields(true);
             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 );
 
             // enable view again
commit 7d88468f3a877315fcaae85dc716e5207d62ff99
Author:     Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
AuthorDate: Mon Mar 18 09:46:52 2019 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon May 13 19:51:04 2019 +0200

    Add missing constraints for pdf versions
    
    Change-Id: I21008bf17641977b61b1735bb27bc54f24beda4a
    Reviewed-on: https://gerrit.libreoffice.org/69382
    Tested-by: Jenkins
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    (cherry picked from commit 6cbaee3d0522fa78383e3952c926d7f9310b123f)

diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs b/officecfg/registry/schema/org/openoffice/Office/Common.xcs
index 6b5729412f6e..e34a8c4f963d 100644
--- a/officecfg/registry/schema/org/openoffice/Office/Common.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/Common.xcs
@@ -5206,11 +5206,21 @@
                   <desc>PDF 1.5 (default selection).</desc>
                 </info>
               </enumeration>
+              <enumeration oor:value="16">
+                <info>
+                  <desc>PDF 1.6</desc>
+                </info>
+              </enumeration>
               <enumeration oor:value="1">
                 <info>
                   <desc>PDF/A-1 (ISO 19005-1:2005)</desc>
                 </info>
               </enumeration>
+              <enumeration oor:value="2">
+                <info>
+                  <desc>PDF/A-2 (ISO 19005-2:2011)</desc>
+                </info>
+              </enumeration>
             </constraints>
             <value>0</value>
           </prop>
commit c0a1b698fbe002f33712fe61f485032acaf50e5d
Author:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
AuthorDate: Fri Mar 15 09:47:45 2019 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon May 13 19:51:04 2019 +0200

    tdf#113448 fix PDF forms export
    
    This fixes verapdf A-2 validation error '6.3.3-2 annotation
    appearance dict is wrong'.
    
    Controls that use type /FT/Btn must have sub-dicts as /N content,
    instead of a direct stream reference.
    
    Change-Id: If985644fe3d583e98a0b3a703e4b33dbf652f165

diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index cd553e2fe7fe..108f9199ce4f 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -4555,6 +4555,19 @@ bool PDFWriterImpl::emitAppearances( PDFWidget& rWidget, OStringBuffer& rAnnotDi
             rAnnotDict.append( "/" );
             rAnnotDict.append( dict_item.first );
             bool bUseSubDict = (dict_item.second.size() > 1);
+
+            // PDF/A requires sub-dicts for /FT/Btn objects (clause
+            // 6.3.3)
+            if( m_bIsPDF_A1 || m_bIsPDF_A2 )
+            {
+                if( rWidget.m_eType == PDFWriter::RadioButton ||
+                    rWidget.m_eType == PDFWriter::CheckBox ||
+                    rWidget.m_eType == PDFWriter::PushButton )
+                {
+                    bUseSubDict = true;
+                }
+            }
+
             rAnnotDict.append( bUseSubDict ? "<<" : " " );
 
             for (auto const& stream_item : dict_item.second)
commit 32b3c868d863801efe7d9ed8a0a969d6f8503d6c
Author:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
AuthorDate: Thu Mar 14 00:36:37 2019 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon May 13 19:51:04 2019 +0200

    Fix pdf validation error 'glyph width in dict and font inconsistent'
    
    Previous code was writing hard-coded '1000' as glyph width for any type1
    font subsetting - since actual type2 width info only became available
    during subsequent convertOneTypeOp() parsing.
    
    Catch was, that loop sometimes already modifies the output buffer
    (whenever glyph path info was given), so we fix that by first padding
    out 5 bytes for the width (size of integers are sadly variable), then
    parsing Type2 glyph code, and in the end putting in the actual width
    value we then know.
    
    Can't put hsbw type1 op last, since standard requires that to be first
    (and can only be given _once_).
    
    Could be re-done nicer by buffering Type2 glyph data, then writing it.
    Left as an exercise for the reader.
    
    Change-Id: I64ffaa32ded2f0a7c06311d1e0426cf358308a0a

diff --git a/vcl/source/fontsubset/cff.cxx b/vcl/source/fontsubset/cff.cxx
index 13ed076d1ff6..c60e634143cc 100644
--- a/vcl/source/fontsubset/cff.cxx
+++ b/vcl/source/fontsubset/cff.cxx
@@ -1104,20 +1104,34 @@ int CffSubsetterContext::convert2Type1Ops( CffLocal* pCffLocal, const U8* const
     mpReadEnd = pT2Ops + nT2Len;
     // prepend "hsbw" or "sbw"
     // TODO: only emit hsbw when charwidth is known
-    // TODO: remove charwidth from T2 stack
-    writeType1Val( 0); // TODO: aSubsetterContext.getLeftSideBearing();
-    writeType1Val( 1000/*###getCharWidth()###*/);
-    writeTypeOp( TYPE1OP::HSBW);
-mbNeedClose = false;
-mbIgnoreHints = false;
-mnHintSize=mnHorzHintSize=mnStackIdx=0; maCharWidth=-1;//#######
-mnCntrMask = 0;
+    writeType1Val(0); // TODO: aSubsetterContext.getLeftSideBearing();
+    U8* pCharWidthPtr=mpWritePtr; // need to overwrite that later
+    // pad out 5 bytes for the char width with default val 1000 (to be
+    // filled with the actual value below)
+    *(mpWritePtr++) = 255;
+    *(mpWritePtr++) = static_cast<U8>(0);
+    *(mpWritePtr++) = static_cast<U8>(0);
+    *(mpWritePtr++) = static_cast<U8>(250);
+    *(mpWritePtr++) = static_cast<U8>(124);
+    writeTypeOp(TYPE1OP::HSBW);
+    mbNeedClose = false;
+    mbIgnoreHints = false;
+    mnHintSize=mnHorzHintSize=mnStackIdx=0; maCharWidth=-1;//#######
+    mnCntrMask = 0;
     while( mpReadPtr < mpReadEnd)
         convertOneTypeOp();
-//  if( bActivePath)
-//      writeTypeOp( TYPE1OP::CLOSEPATH);
-//  if( bSubRoutine)
-//      writeTypeOp( TYPE1OP::RETURN);
+    if( maCharWidth != -1 )
+    {
+        // overwrite earlier charWidth value, which we only now have
+        // parsed out of mpReadPtr buffer (by way of
+        // convertOneTypeOp()s above)
+        const int nInt = static_cast<int>(maCharWidth);
+        *(pCharWidthPtr++) = 255;
+        *(pCharWidthPtr++) = static_cast<U8>(nInt >> 24);
+        *(pCharWidthPtr++) = static_cast<U8>(nInt >> 16);
+        *(pCharWidthPtr++) = static_cast<U8>(nInt >> 8);
+        *(pCharWidthPtr++) = static_cast<U8>(nInt);
+    }
 #else // useful for manually encoding charstrings
     mpWritePtr = pT1Ops;
     mpWritePtr += sprintf( (char*)mpWritePtr, "OOo_\x8b\x8c\x0c\x10\x0b");
commit a663c7beae8f0900285bd9a6c9f1dd9566522975
Author:     Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
AuthorDate: Fri Mar 8 16:38:49 2019 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon May 13 19:51:04 2019 +0200

    tdf#123898 Fix frame content misaligned
    
    Frame was correctly formatted until spellchecker comes and
    calls GetCharRect which somehow reformats the frame causes the misalignment.
    
    So instead of calling GetCharRect, just call GetPaintArea as the frame is already
    formatted at this point.
    
    Reviewed-on: https://gerrit.libreoffice.org/68927
    Tested-by: Jenkins
    Reviewed-by: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
    (cherry picked from commit 86567ebde2d38c44aae93064b8c102f365641f81)
    
    Change-Id: I31df9140174c40cf4cf39891490301cbe4c5806a

diff --git a/sw/qa/extras/layout/data/tdf123898.odt b/sw/qa/extras/layout/data/tdf123898.odt
new file mode 100644
index 000000000000..31800aadb18b
Binary files /dev/null and b/sw/qa/extras/layout/data/tdf123898.odt differ
diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx
index b1ef14cbbad8..1e9047f855c2 100755
--- a/sw/qa/extras/layout/layout.cxx
+++ b/sw/qa/extras/layout/layout.cxx
@@ -33,6 +33,7 @@ public:
     void testTdf119875();
     void testTdf116989();
     void testTdf122607();
+    void testTdf123898();
 
     CPPUNIT_TEST_SUITE(SwLayoutWriter);
     CPPUNIT_TEST(testTdf116830);
@@ -51,6 +52,7 @@ public:
     CPPUNIT_TEST(testTdf119875);
     CPPUNIT_TEST(testTdf116989);
     CPPUNIT_TEST(testTdf122607);
+    CPPUNIT_TEST(testTdf123898);
     CPPUNIT_TEST_SUITE_END();
 
 private:
@@ -320,6 +322,18 @@ void SwLayoutWriter::testTdf122607()
                 "nWidth", "428");
 }
 
+void SwLayoutWriter::testTdf123898()
+{
+    createDoc("tdf123898.odt");
+
+    // Make sure spellchecker has done its job already
+    Scheduler::ProcessEventsToIdle();
+
+    xmlDocPtr pXmlDoc = parseLayoutDump();
+    // Make sure that the arrow on the left is not there (there are 43 children if it's there)
+    assertXPathChildren(pXmlDoc, "/root/page/body/txt/anchored/fly/txt", 42);
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SwLayoutWriter);
 CPPUNIT_PLUGIN_IMPLEMENT();
 
diff --git a/sw/source/core/txtnode/txtedt.cxx b/sw/source/core/txtnode/txtedt.cxx
index 7a646fc2b8ed..7b88b14ff5b9 100644
--- a/sw/source/core/txtnode/txtedt.cxx
+++ b/sw/source/core/txtnode/txtedt.cxx
@@ -204,71 +204,21 @@ static SwRect lcl_CalculateRepaintRect(
         SwTextFrame & rTextFrame, SwTextNode & rNode,
         sal_Int32 const nChgStart, sal_Int32 const nChgEnd)
 {
-    SwRect aRect;
-
     TextFrameIndex const iChgStart(rTextFrame.MapModelToView(&rNode, nChgStart));
     TextFrameIndex const iChgEnd(rTextFrame.MapModelToView(&rNode, nChgEnd));
 
-    SwPosition aPos( rNode, nChgEnd );
-    SwCursorMoveState aTmpState( MV_NONE );
-    aTmpState.m_b2Lines = true;
-    rTextFrame.GetCharRect( aRect, aPos, &aTmpState );
-    // information about end of repaint area
-    Sw2LinesPos* pEnd2Pos = aTmpState.m_p2Lines;
-
-    const SwTextFrame *pEndFrame = &rTextFrame;
+    SwRect aRect = rTextFrame.GetPaintArea();
+    SwRect aTmp = rTextFrame.GetPaintArea();
 
-    while( pEndFrame->HasFollow() &&
-           iChgEnd >= pEndFrame->GetFollow()->GetOfst())
-        pEndFrame = pEndFrame->GetFollow();
-
-    if ( pEnd2Pos )
-    {
-        // we are inside a special portion, take left border
-        SwRectFnSet aRectFnSet(pEndFrame);
-        aRectFnSet.SetTop( aRect, aRectFnSet.GetTop(pEnd2Pos->aLine) );
-        if ( pEndFrame->IsRightToLeft() )
-            aRectFnSet.SetLeft( aRect, aRectFnSet.GetLeft(pEnd2Pos->aPortion) );
-        else
-            aRectFnSet.SetLeft( aRect, aRectFnSet.GetRight(pEnd2Pos->aPortion) );
-        aRectFnSet.SetWidth( aRect, 1 );
-        aRectFnSet.SetHeight( aRect, aRectFnSet.GetHeight(pEnd2Pos->aLine) );
-        delete pEnd2Pos;
-    }
-
-    aTmpState.m_p2Lines = nullptr;
-    SwRect aTmp;
-    aPos = SwPosition( rNode, nChgStart );
-    rTextFrame.GetCharRect( aTmp, aPos, &aTmpState );
-
-    // i63141: GetCharRect(..) could cause a formatting,
-    // during the formatting SwTextFrames could be joined, deleted, created...
-    // => we have to reinit pStartFrame and pEndFrame after the formatting
     const SwTextFrame* pStartFrame = &rTextFrame;
     while( pStartFrame->HasFollow() &&
            iChgStart >= pStartFrame->GetFollow()->GetOfst())
         pStartFrame = pStartFrame->GetFollow();
-    pEndFrame = pStartFrame;
+    const SwTextFrame* pEndFrame = pStartFrame;
     while( pEndFrame->HasFollow() &&
            iChgEnd >= pEndFrame->GetFollow()->GetOfst())
         pEndFrame = pEndFrame->GetFollow();
 
-    // information about start of repaint area
-    Sw2LinesPos* pSt2Pos = aTmpState.m_p2Lines;
-    if ( pSt2Pos )
-    {
-        // we are inside a special portion, take right border
-        SwRectFnSet aRectFnSet(pStartFrame);
-        aRectFnSet.SetTop( aTmp, aRectFnSet.GetTop(pSt2Pos->aLine) );
-        if ( pStartFrame->IsRightToLeft() )
-            aRectFnSet.SetLeft( aTmp, aRectFnSet.GetRight(pSt2Pos->aPortion) );
-        else
-            aRectFnSet.SetLeft( aTmp, aRectFnSet.GetLeft(pSt2Pos->aPortion) );
-        aRectFnSet.SetWidth( aTmp, 1 );
-        aRectFnSet.SetHeight( aTmp, aRectFnSet.GetHeight(pSt2Pos->aLine) );
-        delete pSt2Pos;
-    }
-
     bool bSameFrame = true;
 
     if( rTextFrame.HasFollow() )
commit 6df3a7f377770eb644abc7d43e4c5011c3a4b100
Author:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
AuthorDate: Tue Jan 15 01:24:54 2019 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon May 13 19:51:04 2019 +0200

    Export PDF/A as 2b
    
    * replace export dialog option with 2b (from 1b)
    * keep A-1 support for UNO
    * add new SelectPdfVersion filter config param value of '2'
    
    Change-Id: Ia7eca732ef3d018dd5bb1bda79876400d6d03a02

diff --git a/filter/source/pdf/impdialog.cxx b/filter/source/pdf/impdialog.cxx
index fc75951aeb42..372505851e33 100644
--- a/filter/source/pdf/impdialog.cxx
+++ b/filter/source/pdf/impdialog.cxx
@@ -462,7 +462,7 @@ ImpPDFTabGeneralPage::ImpPDFTabGeneralPage(TabPageParent pParent, const SfxItemS
     , mxNfQuality(m_xBuilder->weld_metric_spin_button("quality", FUNIT_PERCENT))
     , mxCbReduceImageResolution(m_xBuilder->weld_check_button("reduceresolution"))
     , mxCoReduceImageResolution(m_xBuilder->weld_combo_box_text("resolution"))
-    , mxCbPDFA1b(m_xBuilder->weld_check_button("pdfa"))
+    , mxCbPDFA2b(m_xBuilder->weld_check_button("pdfa"))
     , mxCbTaggedPDF(m_xBuilder->weld_check_button("tagged"))
     , mxCbExportFormFields(m_xBuilder->weld_check_button("forms"))
     , mxFormsFrame(m_xBuilder->weld_widget("formsframe"))
@@ -530,16 +530,16 @@ void ImpPDFTabGeneralPage::SetFilterConfigItem(ImpPDFTabDialog* pParent)
     mxCbWatermark->connect_toggled( LINK( this, ImpPDFTabGeneralPage, ToggleWatermarkHdl ) );
     mxFtWatermark->set_sensitive(false );
     mxEdWatermark->set_sensitive( false );
-    mxCbPDFA1b->connect_toggled(LINK(this, ImpPDFTabGeneralPage, ToggleExportPDFAHdl));
+    mxCbPDFA2b->connect_toggled(LINK(this, ImpPDFTabGeneralPage, ToggleExportPDFAHdl));
     switch( pParent->mnPDFTypeSelection )
     {
     default:
-    case 0: mxCbPDFA1b->set_active( false ); // PDF 1.5
+        mxCbPDFA2b->set_active( false ); // PDF 1.5
         break;
-    case 1: mxCbPDFA1b->set_active(true); // PDF/A-1a
+    case 2: mxCbPDFA2b->set_active(true); // PDF/A-2a
         break;
     }
-    ToggleExportPDFAHdl( *mxCbPDFA1b );
+    ToggleExportPDFAHdl( *mxCbPDFA2b );
 
     mxCbExportFormFields->connect_toggled( LINK( this, ImpPDFTabGeneralPage, ToggleExportFormFieldsHdl ) );
 
@@ -547,7 +547,7 @@ void ImpPDFTabGeneralPage::SetFilterConfigItem(ImpPDFTabDialog* pParent)
     mbTaggedPDFUserSelection = pParent->mbUseTaggedPDF;
     mbExportFormFieldsUserSelection = pParent->mbExportFormFields;
 
-    if( !mxCbPDFA1b->get_active() )
+    if( !mxCbPDFA2b->get_active() )
     {
         // the value for PDF/A set by the ToggleExportPDFAHdl method called before
         mxCbTaggedPDF->set_active( mbTaggedPDFUserSelection  );
@@ -643,9 +643,9 @@ void ImpPDFTabGeneralPage::GetFilterConfigItem( ImpPDFTabDialog* pParent )
     }
 
     pParent->mnPDFTypeSelection = 0;
-    if( mxCbPDFA1b->get_active() )
+    if( mxCbPDFA2b->get_active() )
     {
-        pParent->mnPDFTypeSelection = 1;
+        pParent->mnPDFTypeSelection = 2;
         pParent->mbUseTaggedPDF =  mbTaggedPDFUserSelection;
         pParent->mbExportFormFields = mbExportFormFieldsUserSelection;
     }
@@ -759,11 +759,11 @@ IMPL_LINK_NOARG(ImpPDFTabGeneralPage, ToggleExportPDFAHdl, weld::ToggleButton&,
     ImpPDFTabSecurityPage* pSecPage = mpParent ? mpParent->getSecurityPage() : nullptr;
     if (pSecPage)
     {
-        pSecPage->ImplPDFASecurityControl(!mxCbPDFA1b->get_active());
+        pSecPage->ImplPDFASecurityControl(!mxCbPDFA2b->get_active());
     }
 
     // PDF/A-1 needs tagged PDF, so force disable the control, will be forced in pdfexport.
-    bool bPDFA1Sel = mxCbPDFA1b->get_active();
+    bool bPDFA1Sel = mxCbPDFA2b->get_active();
     mxFormsFrame->set_sensitive(bPDFA1Sel);
     if(bPDFA1Sel)
     {
@@ -784,14 +784,14 @@ IMPL_LINK_NOARG(ImpPDFTabGeneralPage, ToggleExportPDFAHdl, weld::ToggleButton&,
         mxCbExportFormFields->set_sensitive(true);
     }
 
-    // PDF/A-1 doesn't allow launch action, so enable/disable the selection on
+    // PDF/A-2 doesn't allow launch action, so enable/disable the selection on
     // Link page
     ImpPDFTabLinksPage* pLinksPage = mpParent ? mpParent->getLinksPage() : nullptr;
     if (pLinksPage)
-        pLinksPage->ImplPDFALinkControl(!mxCbPDFA1b->get_active());
+        pLinksPage->ImplPDFALinkControl(!mxCbPDFA2b->get_active());
 
     // if a password was set, inform the user that this will not be used in PDF/A case
-    if( mxCbPDFA1b->get_active() && pSecPage && pSecPage->hasPassword() )
+    if( mxCbPDFA2b->get_active() && pSecPage && pSecPage->hasPassword() )
     {
         std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xContainer.get(),
                                                   VclMessageType::Warning, VclButtonsType::Ok,
@@ -1347,11 +1347,11 @@ void ImpPDFTabLinksPage::SetFilterConfigItem( const  ImpPDFTabDialog* pParent )
 
     // now check the status of PDF/A selection
     // and set the link action accordingly
-    // PDF/A-1 doesn't allow launch action on links
+    // PDF/A-2 doesn't allow launch action on links
 
     ImpPDFTabGeneralPage* pGeneralPage = pParent->getGeneralPage();
     if (pGeneralPage)
-        ImplPDFALinkControl(!pGeneralPage->mxCbPDFA1b->get_active());
+        ImplPDFALinkControl(!pGeneralPage->mxCbPDFA2b->get_active());
 }
 
 
diff --git a/filter/source/pdf/impdialog.hxx b/filter/source/pdf/impdialog.hxx
index b2b0073a0775..6381c554bc47 100644
--- a/filter/source/pdf/impdialog.hxx
+++ b/filter/source/pdf/impdialog.hxx
@@ -190,7 +190,7 @@ class ImpPDFTabGeneralPage : public SfxTabPage
     std::unique_ptr<weld::MetricSpinButton> mxNfQuality;
     std::unique_ptr<weld::CheckButton> mxCbReduceImageResolution;
     std::unique_ptr<weld::ComboBoxText> mxCoReduceImageResolution;
-    std::unique_ptr<weld::CheckButton> mxCbPDFA1b;
+    std::unique_ptr<weld::CheckButton> mxCbPDFA2b;
     std::unique_ptr<weld::CheckButton> mxCbTaggedPDF;
     std::unique_ptr<weld::CheckButton> mxCbExportFormFields;
     std::unique_ptr<weld::Widget> mxFormsFrame;
@@ -235,7 +235,7 @@ public:
 
     void                        GetFilterConfigItem(ImpPDFTabDialog* paParent);
     void                        SetFilterConfigItem(ImpPDFTabDialog* paParent);
-    bool                        IsPdfaSelected() const { return mxCbPDFA1b->get_active(); }
+    bool                        IsPdfaSelected() const { return mxCbPDFA2b->get_active(); }
 };
 
 /// Class tab page viewer
diff --git a/filter/source/pdf/pdfexport.cxx b/filter/source/pdf/pdfexport.cxx
index c7e307f21453..387e2307ae9a 100644
--- a/filter/source/pdf/pdfexport.cxx
+++ b/filter/source/pdf/pdfexport.cxx
@@ -572,6 +572,13 @@ bool PDFExport::Export( const OUString& rFile, const Sequence< PropertyValue >&
                 mbEncrypt = false;              // no encryption
                 xEnc.clear();
                 break;
+            case 2:
+                aContext.Version    = vcl::PDFWriter::PDFVersion::PDF_A_2;
+                mbUseTaggedPDF = true;          // force the tagged PDF as well
+                mbRemoveTransparencies = false; // PDF/A-2 does allow transparencies
+                mbEncrypt = false;              // no encryption
+                xEnc.clear();
+                break;
             }
 
             // copy in context the values default in the constructor or set by the FilterData sequence of properties
diff --git a/filter/uiconfig/ui/pdfgeneralpage.ui b/filter/uiconfig/ui/pdfgeneralpage.ui
index 631b31cee483..f3d2d874bd02 100644
--- a/filter/uiconfig/ui/pdfgeneralpage.ui
+++ b/filter/uiconfig/ui/pdfgeneralpage.ui
@@ -463,11 +463,11 @@
                 </child>
                 <child>
                   <object class="GtkCheckButton" id="pdfa">
-                    <property name="label" translatable="yes" context="pdfgeneralpage|pdfa">Archive P_DF/A-1a (ISO 19005-1)</property>
+                    <property name="label" translatable="yes" context="pdfgeneralpage|pdfa">Archive P_DF/A-2b (ISO 19005-2)</property>
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
                     <property name="receives_default">False</property>
-                    <property name="tooltip_text" translatable="yes" context="pdfgeneralpage|pdfa|tooltip_text">Creates an ISO 19005-1 compliant PDF file, ideal for long-term document preservation</property>
+                    <property name="tooltip_text" translatable="yes" context="pdfgeneralpage|pdfa|tooltip_text">Creates an ISO 19005-2 compliant PDF file, ideal for long-term document preservation</property>
                     <property name="use_underline">True</property>
                     <property name="xalign">0</property>
                     <property name="draw_indicator">True</property>
diff --git a/include/vcl/pdfwriter.hxx b/include/vcl/pdfwriter.hxx
index 3c9afafc8180..231018c319a6 100644
--- a/include/vcl/pdfwriter.hxx
+++ b/include/vcl/pdfwriter.hxx
@@ -103,7 +103,7 @@ public:
     enum class Orientation { Portrait, Inherit };
 
     // in case the below enum is added PDF_1_6 PDF_1_7, please add them just after PDF_1_5
-    enum class PDFVersion { PDF_1_2, PDF_1_3, PDF_1_4, PDF_1_5, PDF_A_1 };//i59651, PDF/A-1b & -1a, only -1b implemented for now
+    enum class PDFVersion { PDF_1_2, PDF_1_3, PDF_1_4, PDF_1_5, PDF_A_1, PDF_A_2 };//i59651, PDF/A-1b & -1a, only -1b implemented for now
     // for the meaning of DestAreaType please look at PDF Reference Manual
     // version 1.4 section 8.2.1, page 475
     enum class DestAreaType { XYZ, FitRectangle };
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 181d2003f3e4..cd553e2fe7fe 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -1719,6 +1719,7 @@ void PDFWriterImpl::PDFPage::appendWaveLine( sal_Int32 nWidth, sal_Int32 nY, sal
         m_pEncryptionBuffer( nullptr ),
         m_nEncryptionBufferSize( 0 ),
         m_bIsPDF_A1( false ),
+        m_bIsPDF_A2( false ),
         m_rOuterFace( i_rOuterFace )
 {
 #ifdef DO_TEST_PDF
@@ -1820,6 +1821,9 @@ void PDFWriterImpl::PDFPage::appendWaveLine( sal_Int32 nWidth, sal_Int32 nY, sal
     m_bIsPDF_A1 = (m_aContext.Version == PDFWriter::PDFVersion::PDF_A_1);
     if( m_bIsPDF_A1 )
         m_aContext.Version = PDFWriter::PDFVersion::PDF_1_4; //meaning we need PDF 1.4, PDF/A flavour
+    m_bIsPDF_A2 = (m_aContext.Version == PDFWriter::PDFVersion::PDF_A_2);
+    if( m_bIsPDF_A2 )
+        m_aContext.Version = PDFWriter::PDFVersion::PDF_1_5; //we could even use 1.7 features
 }
 
 PDFWriterImpl::~PDFWriterImpl()
@@ -2628,11 +2632,15 @@ sal_Int32 PDFWriterImpl::emitStructure( PDFStructureElement& rEle )
             aLine.append( "/RoleMap<<" );
             for (auto const& role : m_aRoleMap)
             {
-                aLine.append( '/' );
-                aLine.append(role.first);
-                aLine.append( '/' );
-                aLine.append( role.second );
-                aLine.append( '\n' );
+                // hack!
+                if (role.first != role.second)
+                {
+                    aLine.append( '/' );
+                    aLine.append(role.first);
+                    aLine.append( '/' );
+                    aLine.append( role.second );
+                    aLine.append( '\n' );
+                }
             }
             aLine.append( ">>\n" );
         }
@@ -3799,7 +3807,7 @@ bool PDFWriterImpl::emitLinkAnnotations()
 // i59651: key /F set bits Print to 1 rest to 0. We don't set NoZoom NoRotate to 1, since it's a 'should'
 // see PDF 8.4.2 and ISO 19005-1:2005 6.5.3
         aLine.append( "<</Type/Annot" );
-        if( m_bIsPDF_A1 )
+        if( m_bIsPDF_A1 || m_bIsPDF_A2 )
             aLine.append( "/F 4" );
         aLine.append( "/Subtype/Link/Border[0 0 0]/Rect[" );
 
@@ -4021,7 +4029,7 @@ bool PDFWriterImpl::emitNoteAnnotations()
 // i59651: key /F set bits Print to 1 rest to 0. We don't set NoZoom NoRotate to 1, since it's a 'should'
 // see PDF 8.4.2 and ISO 19005-1:2005 6.5.3
         aLine.append( "<</Type/Annot" );
-        if( m_bIsPDF_A1 )
+        if( m_bIsPDF_A1 || m_bIsPDF_A2 )
             aLine.append( "/F 4" );
         aLine.append( "/Subtype/Text/Rect[" );
 
@@ -4820,8 +4828,11 @@ bool PDFWriterImpl::emitWidgetAnnotations()
                 }
                 else if( rWidget.m_aListEntries.empty() )
                 {
-                    // create a reset form action
-                    aLine.append( "/AA<</D<</Type/Action/S/ResetForm>>>>\n" );
+                    if( !m_bIsPDF_A2 )
+                    {
+                        // create a reset form action
+                        aLine.append( "/AA<</D<</Type/Action/S/ResetForm>>>>\n" );
+                    }
                 }
                 else if( rWidget.m_bSubmit )
                 {
@@ -5240,7 +5251,7 @@ bool PDFWriterImpl::emitCatalog()
         aLine.append( getResourceDictObj() );
         aLine.append( " 0 R" );
         // NeedAppearances must not be used if PDF is signed
-        if( m_bIsPDF_A1
+        if( m_bIsPDF_A1 || m_bIsPDF_A2
 #if HAVE_FEATURE_NSS
             || ( m_nSignatureObject != -1 )
 #endif
@@ -5560,7 +5571,7 @@ sal_Int32 PDFWriterImpl::emitNamedDestinations()
 // emits the output intent dictionary
 sal_Int32 PDFWriterImpl::emitOutputIntent()
 {
-    if( !m_bIsPDF_A1 )
+    if( !m_bIsPDF_A1 && !m_bIsPDF_A2 )
         return 0;
 
     //emit the sRGB standard profile, in ICC format, in a stream, per IEC61966-2.1
@@ -5667,7 +5678,7 @@ static void escapeStringXML( const OUString& rStr, OUString &rValue)
 // emits the document metadata
 sal_Int32 PDFWriterImpl::emitDocumentMetadata()
 {
-    if( !m_bIsPDF_A1 )
+    if( !m_bIsPDF_A1 && !m_bIsPDF_A2 )
         return 0;
 
     //get the object number for all the destinations
@@ -5688,8 +5699,14 @@ sal_Int32 PDFWriterImpl::emitDocumentMetadata()
         //PDF/A part ( ISO 19005-1:2005 - 6.7.11 )
         aMetadataStream.append( "  <rdf:Description rdf:about=\"\"\n" );
         aMetadataStream.append( "      xmlns:pdfaid=\"http://www.aiim.org/pdfa/ns/id/\">\n" );
-        aMetadataStream.append( "   <pdfaid:part>1</pdfaid:part>\n" );
-        aMetadataStream.append( "   <pdfaid:conformance>A</pdfaid:conformance>\n" );
+        if( m_bIsPDF_A2 )
+            aMetadataStream.append( "   <pdfaid:part>2</pdfaid:part>\n" );
+        else
+            aMetadataStream.append( "   <pdfaid:part>1</pdfaid:part>\n" );
+        if( m_bIsPDF_A2 )
+            aMetadataStream.append( "   <pdfaid:conformance>B</pdfaid:conformance>\n" );
+        else
+            aMetadataStream.append( "   <pdfaid:conformance>A</pdfaid:conformance>\n" );
         aMetadataStream.append( "  </rdf:Description>\n" );
         //... Dublin Core properties go here
         if( !m_aContext.DocumentInfo.Title.isEmpty() ||
diff --git a/vcl/source/gdi/pdfwriter_impl.hxx b/vcl/source/gdi/pdfwriter_impl.hxx
index 0aa63514b2c5..ca0dadcc4861 100644
--- a/vcl/source/gdi/pdfwriter_impl.hxx
+++ b/vcl/source/gdi/pdfwriter_impl.hxx
@@ -1005,6 +1005,8 @@ i12626
 
     /* true if PDF/A-1a or PDF/A-1b is output */
     bool            m_bIsPDF_A1;
+    /* true if PDF/A-2a is output */
+    bool            m_bIsPDF_A2;
     PDFWriter&      m_rOuterFace;
 
     /*
commit 2f581bd151513e97923c72a1f2e8cd197c0ae1a1
Author:     Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
AuthorDate: Wed Feb 13 08:59:01 2019 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon May 13 19:51:04 2019 +0200

    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.Mehrbrodt at 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 f0fcee564d848bf65bb5fa980d121b81455e2c44
Author:     Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
AuthorDate: Thu Feb 7 11:17:21 2019 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon May 13 19:51:03 2019 +0200

    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.Mehrbrodt at 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 b7cf955981e064a14fead1368843d02ae1c72f9f
Author:     Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
AuthorDate: Thu Jan 24 15:52:47 2019 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon May 13 19:51:03 2019 +0200

    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 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 934c23c0bafe6d828a6fa3a4f28e3eb9ea33f633
Author:     Noel Grandin <noel.grandin at collabora.co.uk>
AuthorDate: Tue Jun 5 14:16:23 2018 +0200
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon May 13 19:51:03 2019 +0200

    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());

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list