vcl: less text layout calls in ListBox

Number of GenericSalLayout::LayoutText() calls during Writer startup at
this call-site: 1068 -> 614.

Change-Id: I3bef56e550294a6b2c9fe73c0c6531249c9f1f30
Reviewed-on: https://gerrit.libreoffice.org/60164
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
diff --git a/vcl/inc/listbox.hxx b/vcl/inc/listbox.hxx
index 1130ad9..5e9b202 100644
--- a/vcl/inc/listbox.hxx
+++ b/vcl/inc/listbox.hxx
@@ -23,6 +23,7 @@
#include <vcl/button.hxx>
#include <vcl/floatwin.hxx>
#include <vcl/quickselectionengine.hxx>
#include <vcl/vcllayout.hxx>

#include <set>
#include <vector>
@@ -45,6 +46,7 @@ enum LB_EVENT_TYPE
struct ImplEntryType
{
    OUString    maStr;
    SalLayoutGlyphs maStrGlyphs;
    Image       maImage;
    void*       mpUserData;
    bool        mbIsSelected;
@@ -69,6 +71,9 @@ struct ImplEntryType
        mbIsSelected = false;
        mpUserData = nullptr;
    }

    /// Computes maStr's text layout (glyphs), cached in maStrGlyphs.
    SalLayoutGlyphs* GetTextGlyphs(OutputDevice* pOutputDevice);
};

class ImplEntryList
diff --git a/vcl/source/control/imp_listbox.cxx b/vcl/source/control/imp_listbox.cxx
index 0655b74..629d160 100644
--- a/vcl/source/control/imp_listbox.cxx
+++ b/vcl/source/control/imp_listbox.cxx
@@ -601,6 +601,27 @@ struct ImplEntryMetrics
    long    nImgHeight;
};

SalLayoutGlyphs* ImplEntryType::GetTextGlyphs(OutputDevice* pOutputDevice)
{
    if (!maStrGlyphs.empty())
        // Use pre-calculated result.
        return &maStrGlyphs;

    std::unique_ptr<SalLayout> pLayout = pOutputDevice->ImplLayout(
        maStr, 0, maStr.getLength(), Point(0, 0), 0, nullptr, SalLayoutFlags::GlyphItemsOnly);
    if (!pLayout)
        return nullptr;

    const SalLayoutGlyphs* pGlyphs = pLayout->GetGlyphs();
    if (!pGlyphs)
        return nullptr;

    // Remember the calculation result.
    maStrGlyphs = *pGlyphs;

    return &maStrGlyphs;
}

void ImplListBoxWindow::EnableQuickSelection( bool b )
{
    maQuickSelectionEngine.SetEnabled( b );
@@ -637,7 +658,9 @@ void ImplListBoxWindow::ImplUpdateEntryMetrics( ImplEntryType& rEntry )
        else
        {
            // normal single line case
            aMetrics.nTextWidth = static_cast<sal_uInt16>(GetTextWidth( rEntry.maStr ));
            const SalLayoutGlyphs* pGlyphs = rEntry.GetTextGlyphs(this);
            aMetrics.nTextWidth
                = static_cast<sal_uInt16>(GetTextWidth(rEntry.maStr, 0, -1, nullptr, pGlyphs));
            if( aMetrics.nTextWidth > mnMaxTxtWidth )
                mnMaxTxtWidth = aMetrics.nTextWidth;
            aMetrics.nEntryWidth = mnMaxTxtWidth;